summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/.gitattributes4
-rw-r--r--Source/CMakeInstallDestinations.cmake7
-rw-r--r--Source/CMakeInstallSignTool.cmake.in51
-rw-r--r--Source/CMakeLists.txt318
-rw-r--r--Source/CMakeVersion.cmake81
-rw-r--r--Source/CMakeVersion.rc.in28
-rw-r--r--Source/CMakeVersionCompute.cmake29
-rw-r--r--Source/CMakeVersionSource.cmake30
-rw-r--r--Source/CPack/IFW/cmCPackIFWCommon.cxx20
-rw-r--r--Source/CPack/IFW/cmCPackIFWGenerator.cxx296
-rw-r--r--Source/CPack/IFW/cmCPackIFWGenerator.h56
-rw-r--r--Source/CPack/IFW/cmCPackIFWInstaller.cxx84
-rw-r--r--Source/CPack/IFW/cmCPackIFWInstaller.h15
-rw-r--r--Source/CPack/IFW/cmCPackIFWPackage.cxx192
-rw-r--r--Source/CPack/IFW/cmCPackIFWPackage.h10
-rw-r--r--Source/CPack/IFW/cmCPackIFWRepository.cxx35
-rw-r--r--Source/CPack/IFW/cmCPackIFWRepository.h6
-rw-r--r--Source/CPack/OSXScriptLauncher.cxx22
-rw-r--r--Source/CPack/WiX/cmCMakeToWixPath.cxx39
-rw-r--r--Source/CPack/WiX/cmCMakeToWixPath.h12
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.cxx238
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.h34
-rw-r--r--Source/CPack/WiX/cmWIXAccessControlList.cxx19
-rw-r--r--Source/CPack/WiX/cmWIXAccessControlList.h3
-rw-r--r--Source/CPack/WiX/cmWIXDirectoriesSourceWriter.cxx10
-rw-r--r--Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h5
-rw-r--r--Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx12
-rw-r--r--Source/CPack/WiX/cmWIXFeaturesSourceWriter.h3
-rw-r--r--Source/CPack/WiX/cmWIXFilesSourceWriter.cxx9
-rw-r--r--Source/CPack/WiX/cmWIXFilesSourceWriter.h6
-rw-r--r--Source/CPack/WiX/cmWIXPatch.cxx28
-rw-r--r--Source/CPack/WiX/cmWIXPatch.h4
-rw-r--r--Source/CPack/WiX/cmWIXPatchParser.cxx12
-rw-r--r--Source/CPack/WiX/cmWIXPatchParser.h13
-rw-r--r--Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx2
-rw-r--r--Source/CPack/WiX/cmWIXRichTextFormatWriter.h5
-rw-r--r--Source/CPack/WiX/cmWIXShortcut.cxx16
-rw-r--r--Source/CPack/WiX/cmWIXShortcut.h10
-rw-r--r--Source/CPack/WiX/cmWIXSourceWriter.cxx15
-rw-r--r--Source/CPack/WiX/cmWIXSourceWriter.h6
-rw-r--r--Source/CPack/bills-comments.txt68
-rw-r--r--Source/CPack/cmCPack7zGenerator.cxx15
-rw-r--r--Source/CPack/cmCPack7zGenerator.h29
-rw-r--r--Source/CPack/cmCPackArchiveGenerator.cxx183
-rw-r--r--Source/CPack/cmCPackArchiveGenerator.h41
-rw-r--r--Source/CPack/cmCPackBundleGenerator.cxx56
-rw-r--r--Source/CPack/cmCPackBundleGenerator.h12
-rw-r--r--Source/CPack/cmCPackComponentGroup.cxx13
-rw-r--r--Source/CPack/cmCPackComponentGroup.h31
-rw-r--r--Source/CPack/cmCPackCygwinBinaryGenerator.cxx20
-rw-r--r--Source/CPack/cmCPackCygwinBinaryGenerator.h8
-rw-r--r--Source/CPack/cmCPackCygwinSourceGenerator.cxx63
-rw-r--r--Source/CPack/cmCPackCygwinSourceGenerator.h8
-rw-r--r--Source/CPack/cmCPackDebGenerator.cxx1254
-rw-r--r--Source/CPack/cmCPackDebGenerator.h20
-rw-r--r--Source/CPack/cmCPackDragNDropGenerator.cxx197
-rw-r--r--Source/CPack/cmCPackDragNDropGenerator.h23
-rw-r--r--Source/CPack/cmCPackExternalGenerator.cxx322
-rw-r--r--Source/CPack/cmCPackExternalGenerator.h90
-rw-r--r--Source/CPack/cmCPackFreeBSDGenerator.cxx337
-rw-r--r--Source/CPack/cmCPackFreeBSDGenerator.h37
-rw-r--r--Source/CPack/cmCPackGenerator.cxx1124
-rw-r--r--Source/CPack/cmCPackGenerator.h47
-rw-r--r--Source/CPack/cmCPackGeneratorFactory.cxx118
-rw-r--r--Source/CPack/cmCPackGeneratorFactory.h15
-rw-r--r--Source/CPack/cmCPackLog.cxx19
-rw-r--r--Source/CPack/cmCPackLog.h8
-rw-r--r--Source/CPack/cmCPackNSISGenerator.cxx446
-rw-r--r--Source/CPack/cmCPackNSISGenerator.h24
-rw-r--r--Source/CPack/cmCPackNuGetGenerator.cxx141
-rw-r--r--Source/CPack/cmCPackNuGetGenerator.h37
-rw-r--r--Source/CPack/cmCPackOSXX11Generator.cxx111
-rw-r--r--Source/CPack/cmCPackOSXX11Generator.h12
-rw-r--r--Source/CPack/cmCPackPKGGenerator.cxx154
-rw-r--r--Source/CPack/cmCPackPKGGenerator.h10
-rw-r--r--Source/CPack/cmCPackPackageMakerGenerator.cxx146
-rw-r--r--Source/CPack/cmCPackPackageMakerGenerator.h12
-rw-r--r--Source/CPack/cmCPackProductBuildGenerator.cxx63
-rw-r--r--Source/CPack/cmCPackProductBuildGenerator.h10
-rw-r--r--Source/CPack/cmCPackRPMGenerator.cxx76
-rw-r--r--Source/CPack/cmCPackRPMGenerator.h18
-rw-r--r--Source/CPack/cmCPackSTGZGenerator.cxx25
-rw-r--r--Source/CPack/cmCPackSTGZGenerator.h21
-rw-r--r--Source/CPack/cmCPackTGZGenerator.cxx15
-rw-r--r--Source/CPack/cmCPackTGZGenerator.h29
-rw-r--r--Source/CPack/cmCPackTXZGenerator.cxx15
-rw-r--r--Source/CPack/cmCPackTXZGenerator.h29
-rw-r--r--Source/CPack/cmCPackTarBZip2Generator.cxx15
-rw-r--r--Source/CPack/cmCPackTarBZip2Generator.h28
-rw-r--r--Source/CPack/cmCPackTarCompressGenerator.cxx15
-rw-r--r--Source/CPack/cmCPackTarCompressGenerator.h28
-rw-r--r--Source/CPack/cmCPackZIPGenerator.cxx15
-rw-r--r--Source/CPack/cmCPackZIPGenerator.h29
-rw-r--r--Source/CPack/cpack.cxx226
-rw-r--r--Source/CTest/cmCTestBZR.cxx92
-rw-r--r--Source/CTest/cmCTestBZR.h18
-rw-r--r--Source/CTest/cmCTestBatchTestHandler.cxx125
-rw-r--r--Source/CTest/cmCTestBatchTestHandler.h33
-rw-r--r--Source/CTest/cmCTestBinPacker.cxx203
-rw-r--r--Source/CTest/cmCTestBinPacker.h31
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.cxx199
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.h26
-rw-r--r--Source/CTest/cmCTestBuildCommand.cxx110
-rw-r--r--Source/CTest/cmCTestBuildCommand.h46
-rw-r--r--Source/CTest/cmCTestBuildHandler.cxx417
-rw-r--r--Source/CTest/cmCTestBuildHandler.h42
-rw-r--r--Source/CTest/cmCTestCVS.cxx64
-rw-r--r--Source/CTest/cmCTestCVS.h12
-rw-r--r--Source/CTest/cmCTestCommand.h4
-rw-r--r--Source/CTest/cmCTestConfigureCommand.cxx63
-rw-r--r--Source/CTest/cmCTestConfigureCommand.h31
-rw-r--r--Source/CTest/cmCTestConfigureHandler.cxx39
-rw-r--r--Source/CTest/cmCTestConfigureHandler.h8
-rw-r--r--Source/CTest/cmCTestCoverageCommand.cxx53
-rw-r--r--Source/CTest/cmCTestCoverageCommand.h40
-rw-r--r--Source/CTest/cmCTestCoverageHandler.cxx590
-rw-r--r--Source/CTest/cmCTestCoverageHandler.h29
-rw-r--r--Source/CTest/cmCTestCurl.cxx77
-rw-r--r--Source/CTest/cmCTestCurl.h7
-rw-r--r--Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx4
-rw-r--r--Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h20
-rw-r--r--Source/CTest/cmCTestGIT.cxx147
-rw-r--r--Source/CTest/cmCTestGIT.h18
-rw-r--r--Source/CTest/cmCTestGenericHandler.cxx29
-rw-r--r--Source/CTest/cmCTestGenericHandler.h7
-rw-r--r--Source/CTest/cmCTestGlobalVC.cxx34
-rw-r--r--Source/CTest/cmCTestGlobalVC.h12
-rw-r--r--Source/CTest/cmCTestHG.cxx96
-rw-r--r--Source/CTest/cmCTestHG.h18
-rw-r--r--Source/CTest/cmCTestHandlerCommand.cxx221
-rw-r--r--Source/CTest/cmCTestHandlerCommand.h56
-rw-r--r--Source/CTest/cmCTestLaunch.cxx214
-rw-r--r--Source/CTest/cmCTestLaunch.h18
-rw-r--r--Source/CTest/cmCTestMemCheckCommand.cxx26
-rw-r--r--Source/CTest/cmCTestMemCheckCommand.h29
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.cxx254
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.h29
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx1010
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.h61
-rw-r--r--Source/CTest/cmCTestP4.cxx105
-rw-r--r--Source/CTest/cmCTestP4.h18
-rw-r--r--Source/CTest/cmCTestReadCustomFilesCommand.cxx5
-rw-r--r--Source/CTest/cmCTestReadCustomFilesCommand.h19
-rw-r--r--Source/CTest/cmCTestResourceAllocator.cxx86
-rw-r--r--Source/CTest/cmCTestResourceAllocator.h39
-rw-r--r--Source/CTest/cmCTestResourceGroupsLexerHelper.cxx55
-rw-r--r--Source/CTest/cmCTestResourceGroupsLexerHelper.h44
-rw-r--r--Source/CTest/cmCTestResourceSpec.cxx198
-rw-r--r--Source/CTest/cmCTestResourceSpec.h55
-rw-r--r--Source/CTest/cmCTestRunScriptCommand.cxx9
-rw-r--r--Source/CTest/cmCTestRunScriptCommand.h19
-rw-r--r--Source/CTest/cmCTestRunTest.cxx789
-rw-r--r--Source/CTest/cmCTestRunTest.h91
-rw-r--r--Source/CTest/cmCTestSVN.cxx123
-rw-r--r--Source/CTest/cmCTestSVN.h28
-rw-r--r--Source/CTest/cmCTestScriptHandler.cxx425
-rw-r--r--Source/CTest/cmCTestScriptHandler.h36
-rw-r--r--Source/CTest/cmCTestSleepCommand.cxx4
-rw-r--r--Source/CTest/cmCTestSleepCommand.h19
-rw-r--r--Source/CTest/cmCTestStartCommand.cxx101
-rw-r--r--Source/CTest/cmCTestStartCommand.h19
-rw-r--r--Source/CTest/cmCTestSubmitCommand.cxx273
-rw-r--r--Source/CTest/cmCTestSubmitCommand.h75
-rw-r--r--Source/CTest/cmCTestSubmitHandler.cxx1177
-rw-r--r--Source/CTest/cmCTestSubmitHandler.h49
-rw-r--r--Source/CTest/cmCTestTestCommand.cxx147
-rw-r--r--Source/CTest/cmCTestTestCommand.h59
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx1325
-rw-r--r--Source/CTest/cmCTestTestHandler.h111
-rw-r--r--Source/CTest/cmCTestUpdateCommand.cxx22
-rw-r--r--Source/CTest/cmCTestUpdateCommand.h23
-rw-r--r--Source/CTest/cmCTestUpdateHandler.cxx108
-rw-r--r--Source/CTest/cmCTestUpdateHandler.h12
-rw-r--r--Source/CTest/cmCTestUploadCommand.cxx73
-rw-r--r--Source/CTest/cmCTestUploadCommand.h41
-rw-r--r--Source/CTest/cmCTestUploadHandler.cxx28
-rw-r--r--Source/CTest/cmCTestUploadHandler.h17
-rw-r--r--Source/CTest/cmCTestVC.cxx55
-rw-r--r--Source/CTest/cmCTestVC.h11
-rw-r--r--Source/CTest/cmParseBlanketJSCoverage.cxx26
-rw-r--r--Source/CTest/cmParseBlanketJSCoverage.h2
-rw-r--r--Source/CTest/cmParseCacheCoverage.cxx54
-rw-r--r--Source/CTest/cmParseCacheCoverage.h8
-rw-r--r--Source/CTest/cmParseCoberturaCoverage.cxx56
-rw-r--r--Source/CTest/cmParseDelphiCoverage.cxx27
-rw-r--r--Source/CTest/cmParseGTMCoverage.cxx58
-rw-r--r--Source/CTest/cmParseGTMCoverage.h8
-rw-r--r--Source/CTest/cmParseJacocoCoverage.cxx48
-rw-r--r--Source/CTest/cmParseMumpsCoverage.cxx41
-rw-r--r--Source/CTest/cmParsePHPCoverage.cxx23
-rw-r--r--Source/CTest/cmProcess.cxx743
-rw-r--r--Source/CTest/cmProcess.h106
-rw-r--r--Source/Checks/Curses.cmake41
-rw-r--r--Source/Checks/Curses/CMakeLists.txt25
-rw-r--r--Source/Checks/Curses/CheckCurses.c15
-rw-r--r--Source/Checks/cm_cxx14_check.cmake36
-rw-r--r--Source/Checks/cm_cxx14_check.cpp15
-rw-r--r--Source/Checks/cm_cxx14_cstdio.cmake33
-rw-r--r--Source/Checks/cm_cxx14_cstdio.cpp5
-rw-r--r--Source/Checks/cm_cxx17_check.cmake36
-rw-r--r--Source/Checks/cm_cxx17_check.cpp34
-rw-r--r--Source/Checks/cm_cxx_attribute_fallthrough.cxx11
-rw-r--r--Source/Checks/cm_cxx_auto_ptr.cxx18
-rw-r--r--Source/Checks/cm_cxx_eq_delete.cxx14
-rw-r--r--Source/Checks/cm_cxx_fallthrough.cxx11
-rw-r--r--Source/Checks/cm_cxx_features.cmake27
-rw-r--r--Source/Checks/cm_cxx_gnu_fallthrough.cxx11
-rw-r--r--Source/Checks/cm_cxx_nullptr.cxx14
-rw-r--r--Source/Checks/cm_cxx_override.cxx24
-rw-r--r--Source/Checks/cm_cxx_unordered_map.cxx7
-rw-r--r--Source/Checks/cm_cxx_unordered_set.cxx7
-rw-r--r--Source/CursesDialog/CMakeLists.txt44
-rw-r--r--Source/CursesDialog/ccmake.cxx76
-rw-r--r--Source/CursesDialog/cmCursesBoolWidget.cxx4
-rw-r--r--Source/CursesDialog/cmCursesBoolWidget.h9
-rw-r--r--Source/CursesDialog/cmCursesCacheEntryComposite.cxx96
-rw-r--r--Source/CursesDialog/cmCursesCacheEntryComposite.h26
-rw-r--r--Source/CursesDialog/cmCursesDummyWidget.h9
-rw-r--r--Source/CursesDialog/cmCursesFilePathWidget.h7
-rw-r--r--Source/CursesDialog/cmCursesForm.cxx4
-rw-r--r--Source/CursesDialog/cmCursesForm.h13
-rw-r--r--Source/CursesDialog/cmCursesLabelWidget.cxx4
-rw-r--r--Source/CursesDialog/cmCursesLabelWidget.h15
-rw-r--r--Source/CursesDialog/cmCursesLongMessageForm.cxx30
-rw-r--r--Source/CursesDialog/cmCursesLongMessageForm.h21
-rw-r--r--Source/CursesDialog/cmCursesMainForm.cxx384
-rw-r--r--Source/CursesDialog/cmCursesMainForm.h45
-rw-r--r--Source/CursesDialog/cmCursesOptionsWidget.cxx8
-rw-r--r--Source/CursesDialog/cmCursesOptionsWidget.h15
-rw-r--r--Source/CursesDialog/cmCursesPathWidget.cxx4
-rw-r--r--Source/CursesDialog/cmCursesPathWidget.h17
-rw-r--r--Source/CursesDialog/cmCursesStandardIncludes.h19
-rw-r--r--Source/CursesDialog/cmCursesStringWidget.cxx44
-rw-r--r--Source/CursesDialog/cmCursesStringWidget.h16
-rw-r--r--Source/CursesDialog/cmCursesWidget.cxx2
-rw-r--r--Source/CursesDialog/cmCursesWidget.h11
-rw-r--r--Source/CursesDialog/form/.gitattributes2
-rw-r--r--Source/CursesDialog/form/CMakeLists.txt17
-rw-r--r--Source/CursesDialog/form/frm_post.c2
-rw-r--r--Source/LexerParser/.gitattributes2
-rw-r--r--Source/LexerParser/cmCTestResourceGroupsLexer.cxx2224
-rw-r--r--Source/LexerParser/cmCTestResourceGroupsLexer.h692
-rw-r--r--Source/LexerParser/cmCTestResourceGroupsLexer.in.l102
-rw-r--r--Source/LexerParser/cmCommandArgumentLexer.cxx698
-rw-r--r--Source/LexerParser/cmCommandArgumentLexer.h441
-rw-r--r--Source/LexerParser/cmCommandArgumentLexer.in.l38
-rw-r--r--Source/LexerParser/cmCommandArgumentParser.cxx309
-rw-r--r--Source/LexerParser/cmCommandArgumentParser.y3
-rw-r--r--Source/LexerParser/cmCommandArgumentParserTokens.h8
-rw-r--r--Source/LexerParser/cmDependsJavaLexer.cxx773
-rw-r--r--Source/LexerParser/cmDependsJavaLexer.h441
-rw-r--r--Source/LexerParser/cmDependsJavaLexer.in.l19
-rw-r--r--Source/LexerParser/cmDependsJavaParser.cxx1637
-rw-r--r--Source/LexerParser/cmDependsJavaParser.y5
-rw-r--r--Source/LexerParser/cmDependsJavaParserTokens.h8
-rw-r--r--Source/LexerParser/cmExprLexer.cxx790
-rw-r--r--Source/LexerParser/cmExprLexer.h441
-rw-r--r--Source/LexerParser/cmExprLexer.in.l26
-rw-r--r--Source/LexerParser/cmExprParser.cxx382
-rw-r--r--Source/LexerParser/cmExprParser.y10
-rw-r--r--Source/LexerParser/cmExprParserTokens.h8
-rw-r--r--Source/LexerParser/cmFortranLexer.cxx973
-rw-r--r--Source/LexerParser/cmFortranLexer.h441
-rw-r--r--Source/LexerParser/cmFortranLexer.in.l19
-rw-r--r--Source/LexerParser/cmFortranParser.cxx325
-rw-r--r--Source/LexerParser/cmFortranParser.y7
-rw-r--r--Source/LexerParser/cmFortranParserTokens.h12
-rw-r--r--Source/LexerParser/cmListFileLexer.c887
-rw-r--r--Source/LexerParser/cmListFileLexer.in.l36
-rw-r--r--Source/Modules/CheckCXXLinkerFlag.cmake29
-rw-r--r--Source/Modules/FindLibUUID.cmake85
-rw-r--r--Source/Modules/FindLibUV.cmake2
-rw-r--r--Source/Modules/OverrideC.cmake3
-rw-r--r--Source/Modules/OverrideCXX.cmake3
-rw-r--r--Source/QtDialog/AddCacheEntry.cxx16
-rw-r--r--Source/QtDialog/AddCacheEntry.h5
-rw-r--r--Source/QtDialog/CMakeLists.txt28
-rw-r--r--Source/QtDialog/CMakeSetup.cxx140
-rw-r--r--Source/QtDialog/CMakeSetup.icnsbin138205 -> 195235 bytes
-rw-r--r--Source/QtDialog/CMakeSetup.icobin24542 -> 159613 bytes
-rw-r--r--Source/QtDialog/CMakeSetup128.pngbin13269 -> 7981 bytes
-rw-r--r--Source/QtDialog/CMakeSetup32.pngbin358 -> 1632 bytes
-rw-r--r--Source/QtDialog/CMakeSetup64.pngbin7213 -> 3566 bytes
-rw-r--r--Source/QtDialog/CMakeSetupDialog.cxx87
-rw-r--r--Source/QtDialog/CMakeSetupDialog.h19
-rw-r--r--Source/QtDialog/CMakeSetupDialog.ui3
-rw-r--r--Source/QtDialog/Compilers.h12
-rw-r--r--Source/QtDialog/Delete16.pngbin731 -> 538 bytes
-rw-r--r--Source/QtDialog/FirstConfigure.cxx111
-rw-r--r--Source/QtDialog/FirstConfigure.h17
-rw-r--r--Source/QtDialog/Plus16.pngbin358 -> 207 bytes
-rw-r--r--Source/QtDialog/QCMake.cxx157
-rw-r--r--Source/QtDialog/QCMake.h35
-rw-r--r--Source/QtDialog/QCMakeCacheView.cxx24
-rw-r--r--Source/QtDialog/QCMakeCacheView.h1
-rw-r--r--Source/QtDialog/QCMakeWidgets.cxx12
-rw-r--r--Source/QtDialog/QCMakeWidgets.h9
-rw-r--r--Source/QtDialog/RegexExplorer.cxx6
-rw-r--r--Source/QtDialog/RegexExplorer.h10
-rw-r--r--Source/QtDialog/WarningMessagesDialog.h6
-rw-r--r--Source/bindexplib.cxx269
-rw-r--r--Source/bindexplib.h10
-rw-r--r--Source/cmAddCompileDefinitionsCommand.cxx16
-rw-r--r--Source/cmAddCompileDefinitionsCommand.h16
-rw-r--r--Source/cmAddCompileOptionsCommand.cxx17
-rw-r--r--Source/cmAddCompileOptionsCommand.h21
-rw-r--r--Source/cmAddCustomCommandCommand.cxx330
-rw-r--r--Source/cmAddCustomCommandCommand.h30
-rw-r--r--Source/cmAddCustomTargetCommand.cxx132
-rw-r--r--Source/cmAddCustomTargetCommand.h28
-rw-r--r--Source/cmAddDefinitionsCommand.cxx19
-rw-r--r--Source/cmAddDefinitionsCommand.h27
-rw-r--r--Source/cmAddDependenciesCommand.cxx56
-rw-r--r--Source/cmAddDependenciesCommand.h26
-rw-r--r--Source/cmAddExecutableCommand.cxx136
-rw-r--r--Source/cmAddExecutableCommand.h27
-rw-r--r--Source/cmAddLibraryCommand.cxx245
-rw-r--r--Source/cmAddLibraryCommand.h27
-rw-r--r--Source/cmAddLinkOptionsCommand.cxx16
-rw-r--r--Source/cmAddLinkOptionsCommand.h16
-rw-r--r--Source/cmAddSubDirectoryCommand.cxx81
-rw-r--r--Source/cmAddSubDirectoryCommand.h28
-rw-r--r--Source/cmAddTestCommand.cxx72
-rw-r--r--Source/cmAddTestCommand.h29
-rw-r--r--Source/cmAffinity.cxx65
-rw-r--r--Source/cmAffinity.h12
-rw-r--r--Source/cmAlgorithms.h320
-rw-r--r--Source/cmArchiveWrite.cxx152
-rw-r--r--Source/cmArchiveWrite.h22
-rw-r--r--Source/cmArgumentParser.cxx97
-rw-r--r--Source/cmArgumentParser.h151
-rw-r--r--Source/cmAuxSourceDirectoryCommand.cxx43
-rw-r--r--Source/cmAuxSourceDirectoryCommand.h30
-rw-r--r--Source/cmBase32.cxx8
-rw-r--r--Source/cmBase32.h2
-rw-r--r--Source/cmBinUtilsLinker.cxx16
-rw-r--r--Source/cmBinUtilsLinker.h30
-rw-r--r--Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.cxx19
-rw-r--r--Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h30
-rw-r--r--Source/cmBinUtilsLinuxELFLinker.cxx179
-rw-r--r--Source/cmBinUtilsLinuxELFLinker.h44
-rw-r--r--Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx85
-rw-r--r--Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h26
-rw-r--r--Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.cxx19
-rw-r--r--Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h29
-rw-r--r--Source/cmBinUtilsMacOSMachOLinker.cxx231
-rw-r--r--Source/cmBinUtilsMacOSMachOLinker.h59
-rw-r--r--Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx100
-rw-r--r--Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h25
-rw-r--r--Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx68
-rw-r--r--Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h25
-rw-r--r--Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.cxx19
-rw-r--r--Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h28
-rw-r--r--Source/cmBinUtilsWindowsPELinker.cxx123
-rw-r--r--Source/cmBinUtilsWindowsPELinker.h33
-rw-r--r--Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx68
-rw-r--r--Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h25
-rw-r--r--Source/cmBreakCommand.cxx28
-rw-r--r--Source/cmBreakCommand.h23
-rw-r--r--Source/cmBuildCommand.cxx77
-rw-r--r--Source/cmBuildCommand.h39
-rw-r--r--Source/cmBuildNameCommand.cxx34
-rw-r--r--Source/cmBuildNameCommand.h13
-rw-r--r--Source/cmCLocaleEnvironmentScope.cxx9
-rw-r--r--Source/cmCLocaleEnvironmentScope.h10
-rw-r--r--Source/cmCMakeHostSystemInformationCommand.cxx151
-rw-r--r--Source/cmCMakeHostSystemInformationCommand.h40
-rw-r--r--Source/cmCMakeMinimumRequired.cxx115
-rw-r--r--Source/cmCMakeMinimumRequired.h27
-rw-r--r--Source/cmCMakePolicyCommand.cxx170
-rw-r--r--Source/cmCMakePolicyCommand.h28
-rw-r--r--Source/cmCPackPropertiesGenerator.cxx21
-rw-r--r--Source/cmCPackPropertiesGenerator.h14
-rw-r--r--Source/cmCPluginAPI.cxx193
-rw-r--r--Source/cmCPluginAPI.h19
-rw-r--r--Source/cmCTest.cxx2046
-rw-r--r--Source/cmCTest.h365
-rw-r--r--Source/cmCacheManager.cxx267
-rw-r--r--Source/cmCacheManager.h64
-rw-r--r--Source/cmCallVisualStudioMacro.cxx104
-rw-r--r--Source/cmCallVisualStudioMacro.h14
-rw-r--r--Source/cmCheckCustomOutputs.cxx36
-rw-r--r--Source/cmCheckCustomOutputs.h18
-rw-r--r--Source/cmCommand.cxx42
-rw-r--r--Source/cmCommand.h65
-rw-r--r--Source/cmCommandArgumentParserHelper.cxx107
-rw-r--r--Source/cmCommandArgumentParserHelper.h29
-rw-r--r--Source/cmCommandArgumentsHelper.cxx245
-rw-r--r--Source/cmCommandArgumentsHelper.h196
-rw-r--r--Source/cmCommands.cxx350
-rw-r--r--Source/cmCommonTargetGenerator.cxx83
-rw-r--r--Source/cmCommonTargetGenerator.h6
-rw-r--r--Source/cmComputeComponentGraph.cxx21
-rw-r--r--Source/cmComputeComponentGraph.h10
-rw-r--r--Source/cmComputeLinkDepends.cxx217
-rw-r--r--Source/cmComputeLinkDepends.h57
-rw-r--r--Source/cmComputeLinkInformation.cxx557
-rw-r--r--Source/cmComputeLinkInformation.h65
-rw-r--r--Source/cmComputeTargetDepends.cxx231
-rw-r--r--Source/cmComputeTargetDepends.h17
-rw-r--r--Source/cmConditionEvaluator.cxx117
-rw-r--r--Source/cmConditionEvaluator.h23
-rw-r--r--Source/cmConfigure.cmake.h.in44
-rw-r--r--Source/cmConfigureFileCommand.cxx94
-rw-r--r--Source/cmConfigureFileCommand.h31
-rw-r--r--Source/cmConnection.cxx164
-rw-r--r--Source/cmConnection.h137
-rw-r--r--Source/cmContinueCommand.cxx22
-rw-r--r--Source/cmContinueCommand.h23
-rw-r--r--Source/cmConvertMSBuildXMLToJSON.py21
-rw-r--r--Source/cmCoreTryCompile.cxx536
-rw-r--r--Source/cmCoreTryCompile.h4
-rw-r--r--Source/cmCreateTestSourceList.cxx54
-rw-r--r--Source/cmCreateTestSourceList.h26
-rw-r--r--Source/cmCryptoHash.cxx70
-rw-r--r--Source/cmCryptoHash.h20
-rw-r--r--Source/cmCurl.cxx71
-rw-r--r--Source/cmCurl.h9
-rw-r--r--Source/cmCustomCommand.cxx64
-rw-r--r--Source/cmCustomCommand.h52
-rw-r--r--Source/cmCustomCommandGenerator.cxx182
-rw-r--r--Source/cmCustomCommandGenerator.h23
-rw-r--r--Source/cmCustomCommandLines.cxx22
-rw-r--r--Source/cmCustomCommandLines.h19
-rw-r--r--Source/cmCustomCommandTypes.h39
-rw-r--r--Source/cmDefinePropertyCommand.cxx51
-rw-r--r--Source/cmDefinePropertyCommand.h23
-rw-r--r--Source/cmDefinitions.cxx96
-rw-r--r--Source/cmDefinitions.h63
-rw-r--r--Source/cmDepends.cxx252
-rw-r--r--Source/cmDepends.h51
-rw-r--r--Source/cmDependsC.cxx231
-rw-r--r--Source/cmDependsC.h40
-rw-r--r--Source/cmDependsFortran.cxx350
-rw-r--r--Source/cmDependsFortran.h36
-rw-r--r--Source/cmDependsJava.cxx12
-rw-r--r--Source/cmDependsJava.h22
-rw-r--r--Source/cmDependsJavaParserHelper.cxx90
-rw-r--r--Source/cmDependsJavaParserHelper.h4
-rw-r--r--Source/cmDisallowedCommand.cxx31
-rw-r--r--Source/cmDisallowedCommand.h51
-rw-r--r--Source/cmDocumentation.cxx204
-rw-r--r--Source/cmDocumentation.h25
-rw-r--r--Source/cmDocumentationEntry.h3
-rw-r--r--Source/cmDocumentationFormatter.cxx36
-rw-r--r--Source/cmDocumentationFormatter.h4
-rw-r--r--Source/cmDocumentationSection.cxx6
-rw-r--r--Source/cmDocumentationSection.h9
-rw-r--r--Source/cmDuration.cxx27
-rw-r--r--Source/cmDuration.h24
-rw-r--r--Source/cmDynamicLoader.cxx20
-rw-r--r--Source/cmDynamicLoader.h8
-rw-r--r--Source/cmELF.cxx209
-rw-r--r--Source/cmELF.h14
-rw-r--r--Source/cmEnableLanguageCommand.cxx24
-rw-r--r--Source/cmEnableLanguageCommand.h29
-rw-r--r--Source/cmEnableTestingCommand.cxx11
-rw-r--r--Source/cmEnableTestingCommand.h23
-rw-r--r--Source/cmExecProgramCommand.cxx106
-rw-r--r--Source/cmExecProgramCommand.h31
-rw-r--r--Source/cmExecuteProcessCommand.cxx416
-rw-r--r--Source/cmExecuteProcessCommand.h23
-rw-r--r--Source/cmExecutionStatus.h35
-rw-r--r--Source/cmExpandedCommandArgument.cxx16
-rw-r--r--Source/cmExpandedCommandArgument.h5
-rw-r--r--Source/cmExportBuildAndroidMKGenerator.cxx92
-rw-r--r--Source/cmExportBuildAndroidMKGenerator.h31
-rw-r--r--Source/cmExportBuildFileGenerator.cxx184
-rw-r--r--Source/cmExportBuildFileGenerator.h27
-rw-r--r--Source/cmExportCommand.cxx288
-rw-r--r--Source/cmExportCommand.h54
-rw-r--r--Source/cmExportFileGenerator.cxx391
-rw-r--r--Source/cmExportFileGenerator.h36
-rw-r--r--Source/cmExportInstallAndroidMKGenerator.cxx16
-rw-r--r--Source/cmExportInstallAndroidMKGenerator.h47
-rw-r--r--Source/cmExportInstallFileGenerator.cxx198
-rw-r--r--Source/cmExportInstallFileGenerator.h29
-rw-r--r--Source/cmExportLibraryDependenciesCommand.cxx121
-rw-r--r--Source/cmExportLibraryDependenciesCommand.h24
-rw-r--r--Source/cmExportSet.cxx30
-rw-r--r--Source/cmExportSet.h30
-rw-r--r--Source/cmExportSetMap.cxx29
-rw-r--r--Source/cmExportSetMap.h32
-rw-r--r--Source/cmExportTryCompileFileGenerator.cxx60
-rw-r--r--Source/cmExportTryCompileFileGenerator.h20
-rw-r--r--Source/cmExprParserHelper.cxx64
-rw-r--r--Source/cmExprParserHelper.h17
-rw-r--r--Source/cmExternalMakefileProjectGenerator.cxx23
-rw-r--r--Source/cmExternalMakefileProjectGenerator.h24
-rw-r--r--Source/cmExtraCodeBlocksGenerator.cxx328
-rw-r--r--Source/cmExtraCodeBlocksGenerator.h15
-rw-r--r--Source/cmExtraCodeLiteGenerator.cxx207
-rw-r--r--Source/cmExtraCodeLiteGenerator.h10
-rw-r--r--Source/cmExtraEclipseCDT4Generator.cxx417
-rw-r--r--Source/cmExtraEclipseCDT4Generator.h15
-rw-r--r--Source/cmExtraKateGenerator.cxx129
-rw-r--r--Source/cmExtraKateGenerator.h11
-rw-r--r--Source/cmExtraSublimeTextGenerator.cxx207
-rw-r--r--Source/cmExtraSublimeTextGenerator.h16
-rw-r--r--Source/cmFLTKWrapUICommand.cxx137
-rw-r--r--Source/cmFLTKWrapUICommand.h49
-rw-r--r--Source/cmFSPermissions.cxx34
-rw-r--r--Source/cmFSPermissions.h45
-rw-r--r--Source/cmFileAPI.cxx832
-rw-r--r--Source/cmFileAPI.h209
-rw-r--r--Source/cmFileAPICMakeFiles.cxx114
-rw-r--r--Source/cmFileAPICMakeFiles.h15
-rw-r--r--Source/cmFileAPICache.cxx106
-rw-r--r--Source/cmFileAPICache.h15
-rw-r--r--Source/cmFileAPICodemodel.cxx1424
-rw-r--r--Source/cmFileAPICodemodel.h15
-rw-r--r--Source/cmFileCommand.cxx3041
-rw-r--r--Source/cmFileCommand.h58
-rw-r--r--Source/cmFileCopier.cxx711
-rw-r--r--Source/cmFileCopier.h124
-rw-r--r--Source/cmFileInstaller.cxx351
-rw-r--r--Source/cmFileInstaller.h54
-rw-r--r--Source/cmFileLock.cxx9
-rw-r--r--Source/cmFileLock.h42
-rw-r--r--Source/cmFileLockPool.cxx38
-rw-r--r--Source/cmFileLockPool.h42
-rw-r--r--Source/cmFileLockResult.cxx35
-rw-r--r--Source/cmFileLockResult.h36
-rw-r--r--Source/cmFileLockUnix.cxx14
-rw-r--r--Source/cmFileLockWin32.cxx5
-rw-r--r--Source/cmFileMonitor.cxx55
-rw-r--r--Source/cmFileMonitor.h6
-rw-r--r--Source/cmFilePathChecksum.cxx59
-rw-r--r--Source/cmFilePathChecksum.h31
-rw-r--r--Source/cmFileTime.cxx50
-rw-r--r--Source/cmFileTime.h130
-rw-r--r--Source/cmFileTimeCache.cxx64
-rw-r--r--Source/cmFileTimeCache.h57
-rw-r--r--Source/cmFileTimeComparison.cxx227
-rw-r--r--Source/cmFileTimeComparison.h39
-rw-r--r--Source/cmFileTimes.cxx129
-rw-r--r--Source/cmFileTimes.h40
-rw-r--r--Source/cmFindBase.cxx69
-rw-r--r--Source/cmFindBase.h6
-rw-r--r--Source/cmFindCommon.cxx113
-rw-r--r--Source/cmFindCommon.h24
-rw-r--r--Source/cmFindFileCommand.cxx11
-rw-r--r--Source/cmFindFileCommand.h16
-rw-r--r--Source/cmFindLibraryCommand.cxx126
-rw-r--r--Source/cmFindLibraryCommand.h21
-rw-r--r--Source/cmFindPackageCommand.cxx834
-rw-r--r--Source/cmFindPackageCommand.h72
-rw-r--r--Source/cmFindPathCommand.cxx52
-rw-r--r--Source/cmFindPathCommand.h21
-rw-r--r--Source/cmFindProgramCommand.cxx92
-rw-r--r--Source/cmFindProgramCommand.h21
-rw-r--r--Source/cmForEachCommand.cxx208
-rw-r--r--Source/cmForEachCommand.h45
-rw-r--r--Source/cmFortranParser.h69
-rw-r--r--Source/cmFortranParserImpl.cxx134
-rw-r--r--Source/cmFunctionBlocker.cxx46
-rw-r--r--Source/cmFunctionBlocker.h33
-rw-r--r--Source/cmFunctionCommand.cxx180
-rw-r--r--Source/cmFunctionCommand.h38
-rw-r--r--Source/cmGeneratedFileStream.cxx72
-rw-r--r--Source/cmGeneratedFileStream.h46
-rw-r--r--Source/cmGeneratorExpression.cxx148
-rw-r--r--Source/cmGeneratorExpression.h115
-rw-r--r--Source/cmGeneratorExpressionContext.cxx14
-rw-r--r--Source/cmGeneratorExpressionContext.h12
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.cxx67
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.h33
-rw-r--r--Source/cmGeneratorExpressionEvaluationFile.cxx148
-rw-r--r--Source/cmGeneratorExpressionEvaluationFile.h26
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx81
-rw-r--r--Source/cmGeneratorExpressionEvaluator.h42
-rw-r--r--Source/cmGeneratorExpressionLexer.cxx28
-rw-r--r--Source/cmGeneratorExpressionLexer.h6
-rw-r--r--Source/cmGeneratorExpressionNode.cxx2146
-rw-r--r--Source/cmGeneratorExpressionNode.h10
-rw-r--r--Source/cmGeneratorExpressionParser.cxx49
-rw-r--r--Source/cmGeneratorExpressionParser.h3
-rw-r--r--Source/cmGeneratorTarget.cxx3574
-rw-r--r--Source/cmGeneratorTarget.h305
-rw-r--r--Source/cmGetCMakePropertyCommand.cxx23
-rw-r--r--Source/cmGetCMakePropertyCommand.h18
-rw-r--r--Source/cmGetDirectoryPropertyCommand.cxx64
-rw-r--r--Source/cmGetDirectoryPropertyCommand.h21
-rw-r--r--Source/cmGetFilenameComponentCommand.cxx63
-rw-r--r--Source/cmGetFilenameComponentCommand.h23
-rw-r--r--Source/cmGetPipes.cxx49
-rw-r--r--Source/cmGetPipes.h8
-rw-r--r--Source/cmGetPropertyCommand.cxx323
-rw-r--r--Source/cmGetPropertyCommand.h47
-rw-r--r--Source/cmGetSourceFilePropertyCommand.cxx25
-rw-r--r--Source/cmGetSourceFilePropertyCommand.h18
-rw-r--r--Source/cmGetTargetPropertyCommand.cxx36
-rw-r--r--Source/cmGetTargetPropertyCommand.h18
-rw-r--r--Source/cmGetTestPropertyCommand.cxx19
-rw-r--r--Source/cmGetTestPropertyCommand.h18
-rw-r--r--Source/cmGhsMultiGpj.cxx35
-rw-r--r--Source/cmGhsMultiGpj.h12
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx1088
-rw-r--r--Source/cmGhsMultiTargetGenerator.h126
-rw-r--r--Source/cmGlobVerificationManager.cxx179
-rw-r--r--Source/cmGlobVerificationManager.h85
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.cxx33
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.h28
-rw-r--r--Source/cmGlobalCommonGenerator.cxx66
-rw-r--r--Source/cmGlobalCommonGenerator.h28
-rw-r--r--Source/cmGlobalGenerator.cxx1737
-rw-r--r--Source/cmGlobalGenerator.h244
-rw-r--r--Source/cmGlobalGeneratorFactory.h40
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx954
-rw-r--r--Source/cmGlobalGhsMultiGenerator.h191
-rw-r--r--Source/cmGlobalJOMMakefileGenerator.cxx27
-rw-r--r--Source/cmGlobalJOMMakefileGenerator.h20
-rw-r--r--Source/cmGlobalKdevelopGenerator.cxx606
-rw-r--r--Source/cmGlobalKdevelopGenerator.h81
-rw-r--r--Source/cmGlobalMSYSMakefileGenerator.cxx22
-rw-r--r--Source/cmGlobalMSYSMakefileGenerator.h2
-rw-r--r--Source/cmGlobalMinGWMakefileGenerator.cxx10
-rw-r--r--Source/cmGlobalMinGWMakefileGenerator.h2
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.cxx38
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.h24
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx1640
-rw-r--r--Source/cmGlobalNinjaGenerator.h227
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx642
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h91
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx890
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h103
-rw-r--r--Source/cmGlobalVisualStudio11Generator.cxx101
-rw-r--r--Source/cmGlobalVisualStudio11Generator.h26
-rw-r--r--Source/cmGlobalVisualStudio12Generator.cxx80
-rw-r--r--Source/cmGlobalVisualStudio12Generator.h30
-rw-r--r--Source/cmGlobalVisualStudio14Generator.cxx155
-rw-r--r--Source/cmGlobalVisualStudio14Generator.h29
-rw-r--r--Source/cmGlobalVisualStudio15Generator.cxx206
-rw-r--r--Source/cmGlobalVisualStudio15Generator.h54
-rw-r--r--Source/cmGlobalVisualStudio71Generator.cxx58
-rw-r--r--Source/cmGlobalVisualStudio71Generator.h28
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx335
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h71
-rw-r--r--Source/cmGlobalVisualStudio8Generator.cxx334
-rw-r--r--Source/cmGlobalVisualStudio8Generator.h80
-rw-r--r--Source/cmGlobalVisualStudio9Generator.cxx55
-rw-r--r--Source/cmGlobalVisualStudio9Generator.h16
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx454
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h80
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.cxx522
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.h65
-rw-r--r--Source/cmGlobalWatcomWMakeGenerator.cxx32
-rw-r--r--Source/cmGlobalWatcomWMakeGenerator.h29
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx2122
-rw-r--r--Source/cmGlobalXCodeGenerator.h122
-rw-r--r--Source/cmGraphAdjacencyList.h10
-rw-r--r--Source/cmGraphVizWriter.cxx344
-rw-r--r--Source/cmGraphVizWriter.h22
-rw-r--r--Source/cmHexFileConverter.cxx33
-rw-r--r--Source/cmHexFileConverter.h9
-rw-r--r--Source/cmIDEFlagTable.h13
-rw-r--r--Source/cmIDEOptions.cxx105
-rw-r--r--Source/cmIDEOptions.h47
-rw-r--r--Source/cmIfCommand.cxx304
-rw-r--r--Source/cmIfCommand.h63
-rw-r--r--Source/cmIncludeCommand.cxx81
-rw-r--r--Source/cmIncludeCommand.h23
-rw-r--r--Source/cmIncludeDirectoryCommand.cxx72
-rw-r--r--Source/cmIncludeDirectoryCommand.h32
-rw-r--r--Source/cmIncludeExternalMSProjectCommand.cxx47
-rw-r--r--Source/cmIncludeExternalMSProjectCommand.h31
-rw-r--r--Source/cmIncludeGuardCommand.cxx108
-rw-r--r--Source/cmIncludeGuardCommand.h22
-rw-r--r--Source/cmIncludeRegularExpressionCommand.cxx18
-rw-r--r--Source/cmIncludeRegularExpressionCommand.h30
-rw-r--r--Source/cmInstallCommand.cxx1408
-rw-r--r--Source/cmInstallCommand.h41
-rw-r--r--Source/cmInstallCommandArguments.cxx134
-rw-r--r--Source/cmInstallCommandArguments.h39
-rw-r--r--Source/cmInstallDirectoryGenerator.cxx45
-rw-r--r--Source/cmInstallDirectoryGenerator.h16
-rw-r--r--Source/cmInstallExportAndroidMKGenerator.cxx140
-rw-r--r--Source/cmInstallExportAndroidMKGenerator.h37
-rw-r--r--Source/cmInstallExportGenerator.cxx74
-rw-r--r--Source/cmInstallExportGenerator.h21
-rw-r--r--Source/cmInstallFilesCommand.cxx104
-rw-r--r--Source/cmInstallFilesCommand.h46
-rw-r--r--Source/cmInstallFilesGenerator.cxx41
-rw-r--r--Source/cmInstallFilesGenerator.h16
-rw-r--r--Source/cmInstallGenerator.cxx39
-rw-r--r--Source/cmInstallGenerator.h29
-rw-r--r--Source/cmInstallProgramsCommand.cxx79
-rw-r--r--Source/cmInstallProgramsCommand.h45
-rw-r--r--Source/cmInstallScriptGenerator.cxx74
-rw-r--r--Source/cmInstallScriptGenerator.h22
-rw-r--r--Source/cmInstallSubdirectoryGenerator.cxx76
-rw-r--r--Source/cmInstallSubdirectoryGenerator.h41
-rw-r--r--Source/cmInstallTargetGenerator.cxx371
-rw-r--r--Source/cmInstallTargetGenerator.h37
-rw-r--r--Source/cmInstallTargetsCommand.cxx36
-rw-r--r--Source/cmInstallTargetsCommand.h28
-rw-r--r--Source/cmInstalledFile.cxx33
-rw-r--r--Source/cmInstalledFile.h21
-rw-r--r--Source/cmJsonObjectDictionary.h45
-rw-r--r--Source/cmJsonObjects.cxx692
-rw-r--r--Source/cmJsonObjects.h27
-rw-r--r--Source/cmLDConfigLDConfigTool.cxx71
-rw-r--r--Source/cmLDConfigLDConfigTool.h22
-rw-r--r--Source/cmLDConfigTool.cxx9
-rw-r--r--Source/cmLDConfigTool.h24
-rw-r--r--Source/cmLinkDirectoriesCommand.cxx54
-rw-r--r--Source/cmLinkDirectoriesCommand.h32
-rw-r--r--Source/cmLinkItem.cxx64
-rw-r--r--Source/cmLinkItem.h92
-rw-r--r--Source/cmLinkLibrariesCommand.cxx28
-rw-r--r--Source/cmLinkLibrariesCommand.h28
-rw-r--r--Source/cmLinkLineComputer.cxx151
-rw-r--r--Source/cmLinkLineComputer.h25
-rw-r--r--Source/cmLinkLineDeviceComputer.cxx220
-rw-r--r--Source/cmLinkLineDeviceComputer.h42
-rw-r--r--Source/cmLinkedTree.h21
-rw-r--r--Source/cmListCommand.cxx1348
-rw-r--r--Source/cmListCommand.h42
-rw-r--r--Source/cmListFileCache.cxx239
-rw-r--r--Source/cmListFileCache.h103
-rw-r--r--Source/cmListFileLexer.h16
-rw-r--r--Source/cmLoadCacheCommand.cxx78
-rw-r--r--Source/cmLoadCacheCommand.h34
-rw-r--r--Source/cmLoadCommandCommand.cxx262
-rw-r--r--Source/cmLoadCommandCommand.h13
-rw-r--r--Source/cmLocalCommonGenerator.cxx50
-rw-r--r--Source/cmLocalCommonGenerator.h16
-rw-r--r--Source/cmLocalGenerator.cxx2142
-rw-r--r--Source/cmLocalGenerator.h203
-rw-r--r--Source/cmLocalGhsMultiGenerator.cxx87
-rw-r--r--Source/cmLocalGhsMultiGenerator.h24
-rw-r--r--Source/cmLocalNinjaGenerator.cxx292
-rw-r--r--Source/cmLocalNinjaGenerator.h35
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx846
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.h114
-rw-r--r--Source/cmLocalVisualStudio10Generator.cxx70
-rw-r--r--Source/cmLocalVisualStudio10Generator.h23
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx870
-rw-r--r--Source/cmLocalVisualStudio7Generator.h37
-rw-r--r--Source/cmLocalVisualStudioGenerator.cxx50
-rw-r--r--Source/cmLocalVisualStudioGenerator.h14
-rw-r--r--Source/cmLocalXCodeGenerator.cxx35
-rw-r--r--Source/cmLocalXCodeGenerator.h18
-rw-r--r--Source/cmLocale.h12
-rw-r--r--Source/cmMSVC60LinkLineComputer.cxx2
-rw-r--r--Source/cmMSVC60LinkLineComputer.h11
-rw-r--r--Source/cmMachO.cxx43
-rw-r--r--Source/cmMachO.h8
-rw-r--r--Source/cmMacroCommand.cxx192
-rw-r--r--Source/cmMacroCommand.h38
-rw-r--r--Source/cmMakeDirectoryCommand.cxx15
-rw-r--r--Source/cmMakeDirectoryCommand.h23
-rw-r--r--Source/cmMakefile.cxx2656
-rw-r--r--Source/cmMakefile.h614
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx265
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.h6
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx420
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.h13
-rw-r--r--Source/cmMakefileTargetGenerator.cxx1019
-rw-r--r--Source/cmMakefileTargetGenerator.h42
-rw-r--r--Source/cmMakefileUtilityTargetGenerator.cxx23
-rw-r--r--Source/cmMakefileUtilityTargetGenerator.h6
-rw-r--r--Source/cmMarkAsAdvancedCommand.cxx15
-rw-r--r--Source/cmMarkAsAdvancedCommand.h23
-rw-r--r--Source/cmMathCommand.cxx99
-rw-r--r--Source/cmMathCommand.h24
-rw-r--r--Source/cmMessageCommand.cxx136
-rw-r--r--Source/cmMessageCommand.h23
-rw-r--r--Source/cmMessageType.h21
-rw-r--r--Source/cmMessenger.cxx117
-rw-r--r--Source/cmMessenger.h52
-rw-r--r--Source/cmNewLineStyle.cxx9
-rw-r--r--Source/cmNewLineStyle.h4
-rw-r--r--Source/cmNinjaLinkLineComputer.h10
-rw-r--r--Source/cmNinjaLinkLineDeviceComputer.cxx20
-rw-r--r--Source/cmNinjaLinkLineDeviceComputer.h34
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx840
-rw-r--r--Source/cmNinjaNormalTargetGenerator.h17
-rw-r--r--Source/cmNinjaTargetGenerator.cxx1142
-rw-r--r--Source/cmNinjaTargetGenerator.h47
-rw-r--r--Source/cmNinjaTypes.h47
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.cxx162
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.h6
-rw-r--r--Source/cmOSXBundleGenerator.cxx114
-rw-r--r--Source/cmOSXBundleGenerator.h5
-rw-r--r--Source/cmOptionCommand.cxx99
-rw-r--r--Source/cmOptionCommand.h24
-rw-r--r--Source/cmOrderDirectories.cxx125
-rw-r--r--Source/cmOrderDirectories.h11
-rw-r--r--Source/cmOutputConverter.cxx373
-rw-r--r--Source/cmOutputConverter.h52
-rw-r--r--Source/cmOutputRequiredFilesCommand.cxx220
-rw-r--r--Source/cmOutputRequiredFilesCommand.h23
-rw-r--r--Source/cmParseArgumentsCommand.cxx283
-rw-r--r--Source/cmParseArgumentsCommand.h24
-rw-r--r--Source/cmPathLabel.cxx10
-rw-r--r--Source/cmPathLabel.h2
-rw-r--r--Source/cmPipeConnection.cxx71
-rw-r--r--Source/cmPipeConnection.h29
-rw-r--r--Source/cmPolicies.cxx193
-rw-r--r--Source/cmPolicies.h122
-rw-r--r--Source/cmProcessOutput.cxx8
-rw-r--r--Source/cmProcessOutput.h10
-rw-r--r--Source/cmProcessTools.cxx27
-rw-r--r--Source/cmProcessTools.h26
-rw-r--r--Source/cmProjectCommand.cxx381
-rw-r--r--Source/cmProjectCommand.h29
-rw-r--r--Source/cmProperty.cxx28
-rw-r--r--Source/cmProperty.h18
-rw-r--r--Source/cmPropertyDefinition.h4
-rw-r--r--Source/cmPropertyDefinitionMap.cxx4
-rw-r--r--Source/cmPropertyDefinitionMap.h6
-rw-r--r--Source/cmPropertyMap.cxx79
-rw-r--r--Source/cmPropertyMap.h34
-rw-r--r--Source/cmQTWrapCPPCommand.cxx67
-rw-r--r--Source/cmQTWrapCPPCommand.h27
-rw-r--r--Source/cmQTWrapUICommand.cxx116
-rw-r--r--Source/cmQTWrapUICommand.h26
-rw-r--r--Source/cmQtAutoGen.cxx385
-rw-r--r--Source/cmQtAutoGen.h145
-rw-r--r--Source/cmQtAutoGenGlobalInitializer.cxx289
-rw-r--r--Source/cmQtAutoGenGlobalInitializer.h86
-rw-r--r--Source/cmQtAutoGenInitializer.cxx1735
-rw-r--r--Source/cmQtAutoGenInitializer.h248
-rw-r--r--Source/cmQtAutoGenerator.cxx492
-rw-r--r--Source/cmQtAutoGenerator.h181
-rw-r--r--Source/cmQtAutoGeneratorCommon.cxx216
-rw-r--r--Source/cmQtAutoGeneratorCommon.h39
-rw-r--r--Source/cmQtAutoGeneratorInitializer.cxx1131
-rw-r--r--Source/cmQtAutoGeneratorInitializer.h20
-rw-r--r--Source/cmQtAutoGenerators.cxx2066
-rw-r--r--Source/cmQtAutoGenerators.h222
-rw-r--r--Source/cmQtAutoMocUic.cxx2688
-rw-r--r--Source/cmQtAutoMocUic.h16
-rw-r--r--Source/cmQtAutoRcc.cxx503
-rw-r--r--Source/cmQtAutoRcc.h16
-rw-r--r--Source/cmRST.cxx140
-rw-r--r--Source/cmRST.h7
-rw-r--r--Source/cmRange.h239
-rw-r--r--Source/cmRemoveCommand.cxx30
-rw-r--r--Source/cmRemoveCommand.h23
-rw-r--r--Source/cmRemoveDefinitionsCommand.cxx19
-rw-r--r--Source/cmRemoveDefinitionsCommand.h28
-rw-r--r--Source/cmReturnCommand.cxx4
-rw-r--r--Source/cmReturnCommand.h27
-rw-r--r--Source/cmRulePlaceholderExpander.cxx53
-rw-r--r--Source/cmRulePlaceholderExpander.h13
-rw-r--r--Source/cmRuntimeDependencyArchive.cxx378
-rw-r--r--Source/cmRuntimeDependencyArchive.h70
-rw-r--r--Source/cmScriptGenerator.cxx54
-rw-r--r--Source/cmScriptGenerator.h22
-rw-r--r--Source/cmSearchPath.cxx82
-rw-r--r--Source/cmSearchPath.h10
-rw-r--r--Source/cmSeparateArgumentsCommand.cxx43
-rw-r--r--Source/cmSeparateArgumentsCommand.h23
-rw-r--r--Source/cmServer.cxx329
-rw-r--r--Source/cmServer.h144
-rw-r--r--Source/cmServerConnection.cxx418
-rw-r--r--Source/cmServerConnection.h106
-rw-r--r--Source/cmServerDictionary.h31
-rw-r--r--Source/cmServerProtocol.cxx697
-rw-r--r--Source/cmServerProtocol.h37
-rw-r--r--Source/cmSetCommand.cxx73
-rw-r--r--Source/cmSetCommand.h23
-rw-r--r--Source/cmSetDirectoryPropertiesCommand.cxx29
-rw-r--r--Source/cmSetDirectoryPropertiesCommand.h30
-rw-r--r--Source/cmSetPropertyCommand.cxx480
-rw-r--r--Source/cmSetPropertyCommand.h47
-rw-r--r--Source/cmSetSourceFilesPropertiesCommand.cxx55
-rw-r--r--Source/cmSetSourceFilesPropertiesCommand.h29
-rw-r--r--Source/cmSetTargetPropertiesCommand.cxx48
-rw-r--r--Source/cmSetTargetPropertiesCommand.h26
-rw-r--r--Source/cmSetTestsPropertiesCommand.cxx38
-rw-r--r--Source/cmSetTestsPropertiesCommand.h23
-rw-r--r--Source/cmSiteNameCommand.cxx35
-rw-r--r--Source/cmSiteNameCommand.h23
-rw-r--r--Source/cmSourceFile.cxx307
-rw-r--r--Source/cmSourceFile.h94
-rw-r--r--Source/cmSourceFileLocation.cxx91
-rw-r--r--Source/cmSourceFileLocation.h25
-rw-r--r--Source/cmSourceFileLocationKind.h15
-rw-r--r--Source/cmSourceGroup.cxx72
-rw-r--r--Source/cmSourceGroup.h23
-rw-r--r--Source/cmSourceGroupCommand.cxx346
-rw-r--r--Source/cmSourceGroupCommand.h33
-rw-r--r--Source/cmStandardLexer.h48
-rw-r--r--Source/cmState.cxx371
-rw-r--r--Source/cmState.h96
-rw-r--r--Source/cmStateDirectory.cxx250
-rw-r--r--Source/cmStateDirectory.h32
-rw-r--r--Source/cmStatePrivate.h13
-rw-r--r--Source/cmStateSnapshot.cxx110
-rw-r--r--Source/cmStateSnapshot.h12
-rw-r--r--Source/cmStateTypes.h2
-rw-r--r--Source/cmString.cxx152
-rw-r--r--Source/cmString.hxx817
-rw-r--r--Source/cmStringAlgorithms.cxx325
-rw-r--r--Source/cmStringAlgorithms.h294
-rw-r--r--Source/cmStringCommand.cxx662
-rw-r--r--Source/cmStringCommand.h70
-rw-r--r--Source/cmStringReplaceHelper.cxx121
-rw-r--r--Source/cmStringReplaceHelper.h68
-rw-r--r--Source/cmSubcommandTable.cxx31
-rw-r--r--Source/cmSubcommandTable.h37
-rw-r--r--Source/cmSubdirCommand.cxx41
-rw-r--r--Source/cmSubdirCommand.h28
-rw-r--r--Source/cmSubdirDependsCommand.cxx4
-rw-r--r--Source/cmSubdirDependsCommand.h13
-rw-r--r--Source/cmSystemTools.cxx1569
-rw-r--r--Source/cmSystemTools.h307
-rw-r--r--Source/cmTarget.cxx1629
-rw-r--r--Source/cmTarget.h289
-rw-r--r--Source/cmTargetCompileDefinitionsCommand.cxx87
-rw-r--r--Source/cmTargetCompileDefinitionsCommand.h35
-rw-r--r--Source/cmTargetCompileFeaturesCommand.cxx82
-rw-r--r--Source/cmTargetCompileFeaturesCommand.h24
-rw-r--r--Source/cmTargetCompileOptionsCommand.cxx77
-rw-r--r--Source/cmTargetCompileOptionsCommand.h32
-rw-r--r--Source/cmTargetDepend.h10
-rw-r--r--Source/cmTargetIncludeDirectoriesCommand.cxx99
-rw-r--r--Source/cmTargetIncludeDirectoriesCommand.h39
-rw-r--r--Source/cmTargetLinkDirectoriesCommand.cxx70
-rw-r--r--Source/cmTargetLinkDirectoriesCommand.h16
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx519
-rw-r--r--Source/cmTargetLinkLibrariesCommand.h50
-rw-r--r--Source/cmTargetLinkOptionsCommand.cxx50
-rw-r--r--Source/cmTargetLinkOptionsCommand.h16
-rw-r--r--Source/cmTargetPrecompileHeadersCommand.cxx87
-rw-r--r--Source/cmTargetPrecompileHeadersCommand.h16
-rw-r--r--Source/cmTargetPropCommandBase.cxx62
-rw-r--r--Source/cmTargetPropCommandBase.h24
-rw-r--r--Source/cmTargetPropertyComputer.cxx55
-rw-r--r--Source/cmTargetPropertyComputer.h16
-rw-r--r--Source/cmTargetSourcesCommand.cxx144
-rw-r--r--Source/cmTargetSourcesCommand.h33
-rw-r--r--Source/cmTest.cxx21
-rw-r--r--Source/cmTest.h15
-rw-r--r--Source/cmTestGenerator.cxx138
-rw-r--r--Source/cmTestGenerator.h35
-rw-r--r--Source/cmTimestamp.cxx40
-rw-r--r--Source/cmTimestamp.h10
-rw-r--r--Source/cmTryCompileCommand.cxx5
-rw-r--r--Source/cmTryCompileCommand.h15
-rw-r--r--Source/cmTryRunCommand.cxx145
-rw-r--r--Source/cmTryRunCommand.h15
-rw-r--r--Source/cmUVHandlePtr.cxx267
-rw-r--r--Source/cmUVHandlePtr.h271
-rw-r--r--Source/cmUVProcessChain.cxx396
-rw-r--r--Source/cmUVProcessChain.h100
-rw-r--r--Source/cmUVSignalHackRAII.h45
-rw-r--r--Source/cmUVStreambuf.h219
-rw-r--r--Source/cmUnexpectedCommand.cxx22
-rw-r--r--Source/cmUnexpectedCommand.h37
-rw-r--r--Source/cmUnsetCommand.cxx34
-rw-r--r--Source/cmUnsetCommand.h23
-rw-r--r--Source/cmUseMangledMesaCommand.cxx79
-rw-r--r--Source/cmUseMangledMesaCommand.h16
-rw-r--r--Source/cmUtilitySourceCommand.cxx80
-rw-r--r--Source/cmUtilitySourceCommand.h13
-rw-r--r--Source/cmUtils.hxx2
-rw-r--r--Source/cmUuid.cxx30
-rw-r--r--Source/cmUuid.h4
-rw-r--r--Source/cmVS10CLFlagTable.h204
-rw-r--r--Source/cmVS10CSharpFlagTable.h120
-rw-r--r--Source/cmVS10CudaFlagTable.h51
-rw-r--r--Source/cmVS10CudaHostFlagTable.h35
-rw-r--r--Source/cmVS10LibFlagTable.h76
-rw-r--r--Source/cmVS10LinkFlagTable.h244
-rw-r--r--Source/cmVS10MASMFlagTable.h76
-rw-r--r--Source/cmVS10NASMFlagTable.h50
-rw-r--r--Source/cmVS10RCFlagTable.h7
-rw-r--r--Source/cmVS11CLFlagTable.h219
-rw-r--r--Source/cmVS11CSharpFlagTable.h120
-rw-r--r--Source/cmVS11LibFlagTable.h76
-rw-r--r--Source/cmVS11LinkFlagTable.h269
-rw-r--r--Source/cmVS11MASMFlagTable.h76
-rw-r--r--Source/cmVS11RCFlagTable.h7
-rw-r--r--Source/cmVS12CLFlagTable.h221
-rw-r--r--Source/cmVS12CSharpFlagTable.h120
-rw-r--r--Source/cmVS12LibFlagTable.h76
-rw-r--r--Source/cmVS12LinkFlagTable.h269
-rw-r--r--Source/cmVS12MASMFlagTable.h76
-rw-r--r--Source/cmVS12RCFlagTable.h7
-rw-r--r--Source/cmVS140CLFlagTable.h239
-rw-r--r--Source/cmVS140CSharpFlagTable.h120
-rw-r--r--Source/cmVS140LinkFlagTable.h282
-rw-r--r--Source/cmVS141CLFlagTable.h250
-rw-r--r--Source/cmVS141CSharpFlagTable.h120
-rw-r--r--Source/cmVS141LinkFlagTable.h283
-rw-r--r--Source/cmVS14LibFlagTable.h76
-rw-r--r--Source/cmVS14MASMFlagTable.h76
-rw-r--r--Source/cmVS14RCFlagTable.h7
-rw-r--r--Source/cmVSSetupHelper.cxx171
-rw-r--r--Source/cmVSSetupHelper.h58
-rw-r--r--Source/cmVariableRequiresCommand.cxx35
-rw-r--r--Source/cmVariableRequiresCommand.h13
-rw-r--r--Source/cmVariableWatch.cxx51
-rw-r--r--Source/cmVariableWatch.h32
-rw-r--r--Source/cmVariableWatchCommand.cxx101
-rw-r--r--Source/cmVariableWatchCommand.h37
-rw-r--r--Source/cmVersionMacros.h2
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx4359
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h214
-rw-r--r--Source/cmVisualStudio10ToolsetOptions.cxx127
-rw-r--r--Source/cmVisualStudio10ToolsetOptions.h30
-rw-r--r--Source/cmVisualStudioGeneratorOptions.cxx328
-rw-r--r--Source/cmVisualStudioGeneratorOptions.h35
-rw-r--r--Source/cmVisualStudioSlnData.h6
-rw-r--r--Source/cmVisualStudioSlnParser.cxx39
-rw-r--r--Source/cmVisualStudioSlnParser.h7
-rw-r--r--Source/cmVisualStudioWCEPlatformParser.cxx8
-rw-r--r--Source/cmVisualStudioWCEPlatformParser.h5
-rw-r--r--Source/cmWhileCommand.cxx210
-rw-r--r--Source/cmWhileCommand.h53
-rw-r--r--Source/cmWorkerPool.cxx763
-rw-r--r--Source/cmWorkerPool.h225
-rw-r--r--Source/cmWorkingDirectory.cxx16
-rw-r--r--Source/cmWorkingDirectory.h20
-rw-r--r--Source/cmWriteFileCommand.cxx43
-rw-r--r--Source/cmWriteFileCommand.h23
-rw-r--r--Source/cmXCode21Object.cxx8
-rw-r--r--Source/cmXCode21Object.h2
-rw-r--r--Source/cmXCodeObject.cxx50
-rw-r--r--Source/cmXCodeObject.h28
-rw-r--r--Source/cmXCodeScheme.cxx278
-rw-r--r--Source/cmXCodeScheme.h40
-rw-r--r--Source/cmXMLParser.cxx28
-rw-r--r--Source/cmXMLParser.h2
-rw-r--r--Source/cmXMLSafe.cxx8
-rw-r--r--Source/cmXMLWriter.cxx34
-rw-r--r--Source/cmXMLWriter.h106
-rw-r--r--Source/cm_auto_ptr.hxx220
-rw-r--r--Source/cm_codecvt.cxx23
-rw-r--r--Source/cm_codecvt.hxx22
-rw-r--r--Source/cm_get_date.h2
-rw-r--r--Source/cm_static_string_view.hxx41
-rw-r--r--Source/cm_sys_stat.h4
-rw-r--r--Source/cm_unordered_map.hxx25
-rw-r--r--Source/cm_unordered_set.hxx25
-rw-r--r--Source/cm_utf8.c29
-rw-r--r--Source/cm_utf8.h4
-rw-r--r--Source/cmake.cxx1529
-rw-r--r--Source/cmake.h410
-rw-r--r--Source/cmakemain.cxx607
-rw-r--r--Source/cmakexbuild.cxx77
-rw-r--r--Source/cmcldeps.cxx12
-rw-r--r--Source/cmcmd.cxx1272
-rw-r--r--Source/cmcmd.h17
-rwxr-xr-xSource/cmparseMSBuildXML.py341
-rw-r--r--Source/ctest.cxx142
-rw-r--r--Source/kwsys/Base64.c2
-rw-r--r--Source/kwsys/Base64.h.in40
-rw-r--r--Source/kwsys/CMakeLists.txt380
-rw-r--r--Source/kwsys/CONTRIBUTING.rst2
-rw-r--r--Source/kwsys/CommandLineArguments.cxx65
-rw-r--r--Source/kwsys/CommandLineArguments.hxx.in3
-rw-r--r--Source/kwsys/Configure.h.in134
-rw-r--r--Source/kwsys/Configure.hxx.in52
-rw-r--r--Source/kwsys/ConsoleBuf.hxx.in34
-rw-r--r--Source/kwsys/Directory.cxx82
-rw-r--r--Source/kwsys/DynamicLoader.cxx185
-rw-r--r--Source/kwsys/DynamicLoader.hxx.in39
-rw-r--r--Source/kwsys/Encoding.h.in32
-rw-r--r--Source/kwsys/Encoding.hxx.in10
-rw-r--r--Source/kwsys/EncodingC.c4
-rw-r--r--Source/kwsys/EncodingCXX.cxx59
-rw-r--r--Source/kwsys/FStream.cxx2
-rw-r--r--Source/kwsys/FStream.hxx.in60
-rw-r--r--Source/kwsys/Glob.cxx33
-rw-r--r--Source/kwsys/Glob.hxx.in16
-rw-r--r--Source/kwsys/IOStream.cxx38
-rw-r--r--Source/kwsys/IOStream.hxx.in76
-rw-r--r--Source/kwsys/MD5.c20
-rw-r--r--Source/kwsys/MD5.h.in48
-rw-r--r--Source/kwsys/Process.h.in338
-rw-r--r--Source/kwsys/ProcessUNIX.c122
-rw-r--r--Source/kwsys/ProcessWin32.c109
-rw-r--r--Source/kwsys/RegularExpression.cxx358
-rw-r--r--Source/kwsys/RegularExpression.hxx.in269
-rw-r--r--Source/kwsys/SharedForward.h.in453
-rw-r--r--Source/kwsys/String.c42
-rw-r--r--Source/kwsys/String.h.in20
-rw-r--r--Source/kwsys/System.c2
-rw-r--r--Source/kwsys/System.h.in17
-rw-r--r--Source/kwsys/SystemInformation.cxx839
-rw-r--r--Source/kwsys/SystemInformation.hxx.in21
-rw-r--r--Source/kwsys/SystemTools.cxx1733
-rw-r--r--Source/kwsys/SystemTools.hxx.in144
-rw-r--r--Source/kwsys/Terminal.c80
-rw-r--r--Source/kwsys/Terminal.h.in158
-rw-r--r--Source/kwsys/hash_map.hxx.in18
-rw-r--r--Source/kwsys/hash_set.hxx.in18
-rw-r--r--Source/kwsys/hashtable.hxx.in114
-rw-r--r--Source/kwsys/kwsysPlatformTests.cmake5
-rw-r--r--Source/kwsys/kwsysPlatformTestsC.c65
-rw-r--r--Source/kwsys/kwsysPlatformTestsCXX.cxx142
-rw-r--r--Source/kwsys/kwsysPrivate.h16
-rw-r--r--Source/kwsys/testCommandLineArguments.cxx45
-rw-r--r--Source/kwsys/testCommandLineArguments1.cxx8
-rw-r--r--Source/kwsys/testConfigure.cxx30
-rw-r--r--Source/kwsys/testConsoleBuf.cxx133
-rw-r--r--Source/kwsys/testConsoleBufChild.cxx4
-rw-r--r--Source/kwsys/testDirectory.cxx110
-rw-r--r--Source/kwsys/testDynamicLoader.cxx32
-rw-r--r--Source/kwsys/testDynload.c4
-rw-r--r--Source/kwsys/testDynloadImpl.c10
-rw-r--r--Source/kwsys/testDynloadImpl.h15
-rw-r--r--Source/kwsys/testDynloadUse.c15
-rw-r--r--Source/kwsys/testEncode.c2
-rw-r--r--Source/kwsys/testEncoding.cxx15
-rw-r--r--Source/kwsys/testFStream.cxx6
-rw-r--r--Source/kwsys/testHashSTL.cxx9
-rw-r--r--Source/kwsys/testIOS.cxx139
-rw-r--r--Source/kwsys/testProcess.c65
-rw-r--r--Source/kwsys/testSharedForward.c.in10
-rw-r--r--Source/kwsys/testSystemInformation.cxx26
-rw-r--r--Source/kwsys/testSystemTools.cxx343
-rw-r--r--Source/kwsys/testTerminal.c2
1118 files changed, 93083 insertions, 65369 deletions
diff --git a/Source/.gitattributes b/Source/.gitattributes
index 0f829a368..d0aedc200 100644
--- a/Source/.gitattributes
+++ b/Source/.gitattributes
@@ -1,2 +1,4 @@
+CMakeVersion.cmake export-subst
+
# Do not format third-party sources.
-/kwsys/** -format.clang-format
+/kwsys/** -format.clang-format-6.0
diff --git a/Source/CMakeInstallDestinations.cmake b/Source/CMakeInstallDestinations.cmake
index 28f4e87ad..e82bec3cd 100644
--- a/Source/CMakeInstallDestinations.cmake
+++ b/Source/CMakeInstallDestinations.cmake
@@ -2,19 +2,22 @@
if(BEOS)
set(CMAKE_BIN_DIR_DEFAULT "bin") # HAIKU
set(CMAKE_DATA_DIR_DEFAULT "share/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}") # HAIKU
- set(CMAKE_MAN_DIR_DEFAULT "documentation/man") # HAIKU
set(CMAKE_DOC_DIR_DEFAULT "documentation/doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}") # HAIKU
+ set(CMAKE_INFO_DIR_DEFAULT "documentation/info") # HAIKU
+ set(CMAKE_MAN_DIR_DEFAULT "documentation/man") # HAIKU
set(CMAKE_XDGDATA_DIR_DEFAULT "share") # HAIKU
elseif(CYGWIN)
set(CMAKE_BIN_DIR_DEFAULT "bin") # CYGWIN
set(CMAKE_DATA_DIR_DEFAULT "share/cmake-${CMake_VERSION}") # CYGWIN
set(CMAKE_DOC_DIR_DEFAULT "share/doc/cmake-${CMake_VERSION}") # CYGWIN
+ set(CMAKE_INFO_DIR_DEFAULT "share/info") # CYGWIN
set(CMAKE_MAN_DIR_DEFAULT "share/man") # CYGWIN
set(CMAKE_XDGDATA_DIR_DEFAULT "share") # CYGWIN
else()
set(CMAKE_BIN_DIR_DEFAULT "bin") # OTHER
set(CMAKE_DATA_DIR_DEFAULT "share/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}") # OTHER
set(CMAKE_DOC_DIR_DEFAULT "doc/cmake-${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}") # OTHER
+ set(CMAKE_INFO_DIR_DEFAULT "info") # OTHER
set(CMAKE_MAN_DIR_DEFAULT "man") # OTHER
set(CMAKE_XDGDATA_DIR_DEFAULT "share") # OTHER
endif()
@@ -22,6 +25,7 @@ endif()
set(CMAKE_BIN_DIR_DESC "bin")
set(CMAKE_DATA_DIR_DESC "data")
set(CMAKE_DOC_DIR_DESC "docs")
+set(CMAKE_INFO_DIR_DESC "Info manual")
set(CMAKE_MAN_DIR_DESC "man pages")
set(CMAKE_XDGDATA_DIR_DESC "XDG specific files")
@@ -35,6 +39,7 @@ foreach(v
CMAKE_BIN_DIR
CMAKE_DATA_DIR
CMAKE_DOC_DIR
+ CMAKE_INFO_DIR
CMAKE_MAN_DIR
CMAKE_XDGDATA_DIR
)
diff --git a/Source/CMakeInstallSignTool.cmake.in b/Source/CMakeInstallSignTool.cmake.in
new file mode 100644
index 000000000..fca629c31
--- /dev/null
+++ b/Source/CMakeInstallSignTool.cmake.in
@@ -0,0 +1,51 @@
+# The signtool. Default to PATH.
+set(CMake_INSTALL_SIGNTOOL "@CMake_INSTALL_SIGNTOOL@")
+if(NOT CMake_INSTALL_SIGNTOOL)
+ set(CMake_INSTALL_SIGNTOOL signtool)
+endif()
+
+# Select a certificate by Subject Name. Default to automatic selection.
+set(CMake_INSTALL_SIGNTOOL_SUBJECT_NAME "@CMake_INSTALL_SIGNTOOL_SUBJECT_NAME@")
+if(CMake_INSTALL_SIGNTOOL_SUBJECT_NAME)
+ set(select_cert -n "${CMake_INSTALL_SIGNTOOL_SUBJECT_NAME}")
+else()
+ set(select_cert -a)
+endif()
+
+# Timestamp URL. Default to a common provider.
+set(CMake_INSTALL_SIGNTOOL_TIMESTAMP_URL "@CMake_INSTALL_SIGNTOOL_TIMESTAMP_URL@")
+if(NOT CMake_INSTALL_SIGNTOOL_TIMESTAMP_URL)
+ set(CMake_INSTALL_SIGNTOOL_TIMESTAMP_URL "http://timestamp.digicert.com")
+endif()
+
+# Glob files that need a signature.
+file(GLOB files "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/*.exe")
+
+# Sign all files at once.
+if(files)
+ # Run the signtool through 'cmd /c' to enable password prompt popup.
+ # Some providers have trouble when signtool is invoked with SW_HIDE.
+ set(cmd cmd /c "${CMake_INSTALL_SIGNTOOL}" sign -v ${select_cert})
+
+ # Sign with SHA-1 for Windows 7 and below.
+ execute_process(
+ COMMAND ${cmd} -t "${CMake_INSTALL_SIGNTOOL_TIMESTAMP_URL}" ${files}
+ RESULT_VARIABLE result
+ ERROR_VARIABLE stderr
+ )
+ if(NOT result EQUAL 0)
+ string(REPLACE "\n" "\n " stderr " ${stderr}")
+ message(WARNING "signtool failed:\n${stderr}")
+ endif()
+
+ # Sign with SHA-256 for Windows 8 and above.
+ execute_process(
+ COMMAND ${cmd} -tr "${CMake_INSTALL_SIGNTOOL_TIMESTAMP_URL}" -fd sha256 -td sha256 -as ${files}
+ RESULT_VARIABLE result
+ ERROR_VARIABLE stderr
+ )
+ if(NOT result EQUAL 0)
+ string(REPLACE "\n" "\n " stderr " ${stderr}")
+ message(WARNING "signtool failed:\n${stderr}")
+ endif()
+endif()
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 40403ca25..b1f7b29e5 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -31,6 +31,16 @@ else()
set(CMAKE_USE_ELF_PARSER)
endif()
+if(NOT CMake_DEFAULT_RECURSION_LIMIT)
+ if(DEFINED ENV{DASHBOARD_TEST_FROM_CTEST})
+ set(CMake_DEFAULT_RECURSION_LIMIT 100)
+ elseif(MINGW)
+ set(CMake_DEFAULT_RECURSION_LIMIT 400)
+ else()
+ set(CMake_DEFAULT_RECURSION_LIMIT 1000)
+ endif()
+endif()
+
if(APPLE)
set(CMAKE_USE_MACH_PARSER 1)
endif()
@@ -82,13 +92,9 @@ include_directories(
${CMAKE_ZLIB_INCLUDES}
${CMAKE_EXPAT_INCLUDES}
${CMAKE_TAR_INCLUDES}
- ${CMAKE_COMPRESS_INCLUDES}
${CMake_HAIKU_INCLUDE_DIRS}
)
-# let cmake know it is supposed to use it
-add_definitions(-DCMAKE_BUILD_WITH_CMAKE)
-
# Check if we can build the ELF parser.
if(CMAKE_USE_ELF_PARSER)
set(ELF_SRCS cmELF.h cmELF.cxx)
@@ -131,10 +137,39 @@ set(SRCS
LexerParser/cmListFileLexer.c
LexerParser/cmListFileLexer.in.l
+ cmAffinity.cxx
+ cmAffinity.h
+ cmAlgorithms.h
cmArchiveWrite.cxx
+ cmArgumentParser.cxx
+ cmArgumentParser.h
cmBase32.cxx
+ cmBinUtilsLinker.cxx
+ cmBinUtilsLinker.h
+ cmBinUtilsLinuxELFGetRuntimeDependenciesTool.cxx
+ cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h
+ cmBinUtilsLinuxELFLinker.cxx
+ cmBinUtilsLinuxELFLinker.h
+ cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx
+ cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h
+ cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.cxx
+ cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h
+ cmBinUtilsMacOSMachOLinker.cxx
+ cmBinUtilsMacOSMachOLinker.h
+ cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx
+ cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h
+ cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx
+ cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h
+ cmBinUtilsWindowsPEGetRuntimeDependenciesTool.cxx
+ cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h
+ cmBinUtilsWindowsPELinker.cxx
+ cmBinUtilsWindowsPELinker.h
+ cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx
+ cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h
cmCacheManager.cxx
cmCacheManager.h
+ cmCheckCustomOutputs.h
+ cmCheckCustomOutputs.cxx
cmCLocaleEnvironmentScope.h
cmCLocaleEnvironmentScope.cxx
cmCommandArgumentParserHelper.cxx
@@ -158,6 +193,9 @@ set(SRCS
cmCustomCommand.h
cmCustomCommandGenerator.cxx
cmCustomCommandGenerator.h
+ cmCustomCommandLines.cxx
+ cmCustomCommandLines.h
+ cmCustomCommandTypes.h
cmDefinitions.cxx
cmDefinitions.h
cmDepends.cxx
@@ -191,8 +229,6 @@ set(SRCS
cmExportTryCompileFileGenerator.cxx
cmExportSet.h
cmExportSet.cxx
- cmExportSetMap.h
- cmExportSetMap.cxx
cmExternalMakefileProjectGenerator.cxx
cmExternalMakefileProjectGenerator.h
cmExtraCodeBlocksGenerator.cxx
@@ -205,6 +241,18 @@ set(SRCS
cmExtraKateGenerator.h
cmExtraSublimeTextGenerator.cxx
cmExtraSublimeTextGenerator.h
+ cmFileAPI.cxx
+ cmFileAPI.h
+ cmFileAPICache.cxx
+ cmFileAPICache.h
+ cmFileAPICodemodel.cxx
+ cmFileAPICodemodel.h
+ cmFileAPICMakeFiles.cxx
+ cmFileAPICMakeFiles.h
+ cmFileCopier.cxx
+ cmFileCopier.h
+ cmFileInstaller.cxx
+ cmFileInstaller.h
cmFileLock.cxx
cmFileLock.h
cmFileLockPool.cxx
@@ -213,9 +261,15 @@ set(SRCS
cmFileLockResult.h
cmFilePathChecksum.cxx
cmFilePathChecksum.h
- cmFileTimeComparison.cxx
- cmFileTimeComparison.h
+ cmFileTime.cxx
+ cmFileTime.h
+ cmFileTimeCache.cxx
+ cmFileTimeCache.h
+ cmFileTimes.cxx
+ cmFileTimes.h
cmFortranParserImpl.cxx
+ cmFSPermissions.cxx
+ cmFSPermissions.h
cmGeneratedFileStream.cxx
cmGeneratorExpressionContext.cxx
cmGeneratorExpressionContext.h
@@ -235,6 +289,8 @@ set(SRCS
cmGeneratorExpression.h
cmGeneratorTarget.cxx
cmGeneratorTarget.h
+ cmGetPipes.cxx
+ cmGetPipes.h
cmGlobalCommonGenerator.cxx
cmGlobalCommonGenerator.h
cmGlobalGenerator.cxx
@@ -242,6 +298,8 @@ set(SRCS
cmGlobalGeneratorFactory.h
cmGlobalUnixMakefileGenerator3.cxx
cmGlobalUnixMakefileGenerator3.h
+ cmGlobVerificationManager.cxx
+ cmGlobVerificationManager.h
cmGraphAdjacencyList.h
cmGraphVizWriter.cxx
cmGraphVizWriter.h
@@ -254,11 +312,18 @@ set(SRCS
cmInstallFilesGenerator.cxx
cmInstallScriptGenerator.h
cmInstallScriptGenerator.cxx
+ cmInstallSubdirectoryGenerator.h
+ cmInstallSubdirectoryGenerator.cxx
cmInstallTargetGenerator.h
cmInstallTargetGenerator.cxx
cmInstallDirectoryGenerator.h
cmInstallDirectoryGenerator.cxx
+ cmLDConfigLDConfigTool.cxx
+ cmLDConfigLDConfigTool.h
+ cmLDConfigTool.cxx
+ cmLDConfigTool.h
cmLinkedTree.h
+ cmLinkItem.cxx
cmLinkItem.h
cmLinkLineComputer.cxx
cmLinkLineComputer.h
@@ -281,6 +346,7 @@ set(SRCS
cmMakefileExecutableTargetGenerator.cxx
cmMakefileLibraryTargetGenerator.cxx
cmMakefileUtilityTargetGenerator.cxx
+ cmMessageType.h
cmMessenger.cxx
cmMessenger.h
cmMSVC60LinkLineComputer.cxx
@@ -299,7 +365,6 @@ set(SRCS
cmProcessOutput.h
cmProcessTools.cxx
cmProcessTools.h
- cmProperty.cxx
cmProperty.h
cmPropertyDefinition.cxx
cmPropertyDefinition.h
@@ -307,20 +372,29 @@ set(SRCS
cmPropertyDefinitionMap.h
cmPropertyMap.cxx
cmPropertyMap.h
- cmQtAutoGeneratorCommon.cxx
- cmQtAutoGeneratorCommon.h
- cmQtAutoGeneratorInitializer.cxx
- cmQtAutoGeneratorInitializer.h
- cmQtAutoGenerators.cxx
- cmQtAutoGenerators.h
+ cmQtAutoGen.cxx
+ cmQtAutoGen.h
+ cmQtAutoGenerator.cxx
+ cmQtAutoGenerator.h
+ cmQtAutoGenGlobalInitializer.cxx
+ cmQtAutoGenGlobalInitializer.h
+ cmQtAutoGenInitializer.cxx
+ cmQtAutoGenInitializer.h
+ cmQtAutoMocUic.cxx
+ cmQtAutoMocUic.h
+ cmQtAutoRcc.cxx
+ cmQtAutoRcc.h
cmRST.cxx
cmRST.h
+ cmRuntimeDependencyArchive.cxx
+ cmRuntimeDependencyArchive.h
cmScriptGenerator.h
cmScriptGenerator.cxx
cmSourceFile.cxx
cmSourceFile.h
cmSourceFileLocation.cxx
cmSourceFileLocation.h
+ cmSourceFileLocationKind.h
cmSourceGroup.cxx
cmSourceGroup.h
cmState.cxx
@@ -330,6 +404,8 @@ set(SRCS
cmStateSnapshot.cxx
cmStateSnapshot.h
cmStateTypes.h
+ cmStringAlgorithms.cxx
+ cmStringAlgorithms.h
cmSystemTools.cxx
cmSystemTools.h
cmTarget.cxx
@@ -342,10 +418,18 @@ set(SRCS
cmTestGenerator.cxx
cmTestGenerator.h
cmUuid.cxx
+ cmUVHandlePtr.cxx
+ cmUVHandlePtr.h
+ cmUVProcessChain.cxx
+ cmUVProcessChain.h
+ cmUVStreambuf.h
+ cmUVSignalHackRAII.h
cmVariableWatch.cxx
cmVariableWatch.h
cmVersion.cxx
cmVersion.h
+ cmWorkerPool.cxx
+ cmWorkerPool.h
cmWorkingDirectory.cxx
cmWorkingDirectory.h
cmXMLParser.cxx
@@ -361,8 +445,12 @@ set(SRCS
cmCommand.h
cmCommands.cxx
cmCommands.h
+ cmAddCompileDefinitionsCommand.cxx
+ cmAddCompileDefinitionsCommand.h
cmAddCompileOptionsCommand.cxx
cmAddCompileOptionsCommand.h
+ cmAddLinkOptionsCommand.cxx
+ cmAddLinkOptionsCommand.h
cmAddCustomCommandCommand.cxx
cmAddCustomCommandCommand.h
cmAddCustomTargetCommand.cxx
@@ -393,8 +481,6 @@ set(SRCS
cmCMakeMinimumRequired.h
cmCMakePolicyCommand.cxx
cmCMakePolicyCommand.h
- cmCommandArgumentsHelper.cxx
- cmCommandArgumentsHelper.h
cmConditionEvaluator.cxx
cmConditionEvaluator.h
cmConfigureFileCommand.cxx
@@ -407,8 +493,6 @@ set(SRCS
cmCreateTestSourceList.h
cmDefinePropertyCommand.cxx
cmDefinePropertyCommand.h
- cmDisallowedCommand.cxx
- cmDisallowedCommand.h
cmEnableLanguageCommand.cxx
cmEnableLanguageCommand.h
cmEnableTestingCommand.cxx
@@ -443,6 +527,8 @@ set(SRCS
cmFindProgramCommand.h
cmForEachCommand.cxx
cmForEachCommand.h
+ cmFunctionBlocker.cxx
+ cmFunctionBlocker.h
cmFunctionCommand.cxx
cmFunctionCommand.h
cmGetCMakePropertyCommand.cxx
@@ -469,6 +555,8 @@ set(SRCS
cmIncludeDirectoryCommand.h
cmIncludeExternalMSProjectCommand.cxx
cmIncludeExternalMSProjectCommand.h
+ cmIncludeGuardCommand.cxx
+ cmIncludeGuardCommand.h
cmIncludeRegularExpressionCommand.cxx
cmIncludeRegularExpressionCommand.h
cmInstallCommand.cxx
@@ -541,8 +629,13 @@ set(SRCS
cmSiteNameCommand.h
cmSourceGroupCommand.cxx
cmSourceGroupCommand.h
+ cmString.cxx
+ cmString.hxx
+ cmStringReplaceHelper.cxx
cmStringCommand.cxx
cmStringCommand.h
+ cmSubcommandTable.cxx
+ cmSubcommandTable.h
cmSubdirCommand.cxx
cmSubdirCommand.h
cmSubdirDependsCommand.cxx
@@ -555,8 +648,14 @@ set(SRCS
cmTargetCompileOptionsCommand.h
cmTargetIncludeDirectoriesCommand.cxx
cmTargetIncludeDirectoriesCommand.h
+ cmTargetLinkOptionsCommand.cxx
+ cmTargetLinkOptionsCommand.h
+ cmTargetLinkDirectoriesCommand.cxx
+ cmTargetLinkDirectoriesCommand.h
cmTargetLinkLibrariesCommand.cxx
cmTargetLinkLibrariesCommand.h
+ cmTargetPrecompileHeadersCommand.cxx
+ cmTargetPrecompileHeadersCommand.h
cmTargetPropCommandBase.cxx
cmTargetPropCommandBase.h
cmTargetSourcesCommand.cxx
@@ -567,8 +666,6 @@ set(SRCS
cmTryCompileCommand.h
cmTryRunCommand.cxx
cmTryRunCommand.h
- cmUnexpectedCommand.cxx
- cmUnexpectedCommand.h
cmUnsetCommand.cxx
cmUnsetCommand.h
cmUseMangledMesaCommand.cxx
@@ -584,23 +681,21 @@ set(SRCS
cmWriteFileCommand.cxx
cmWriteFileCommand.h
- cm_auto_ptr.hxx
+ cm_static_string_view.hxx
cm_get_date.h
cm_get_date.c
cm_utf8.h
cm_utf8.c
cm_codecvt.hxx
cm_codecvt.cxx
+
+ 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}
@@ -655,10 +750,10 @@ if (WIN32)
cmGlobalVisualStudio12Generator.cxx
cmGlobalVisualStudio14Generator.h
cmGlobalVisualStudio14Generator.cxx
- cmGlobalVisualStudio15Generator.h
- cmGlobalVisualStudio15Generator.cxx
cmGlobalVisualStudioGenerator.cxx
cmGlobalVisualStudioGenerator.h
+ cmGlobalVisualStudioVersionedGenerator.h
+ cmGlobalVisualStudioVersionedGenerator.cxx
cmIDEFlagTable.h
cmIDEOptions.cxx
cmIDEOptions.h
@@ -672,14 +767,6 @@ if (WIN32)
cmVisualStudioSlnParser.cxx
cmVisualStudioWCEPlatformParser.h
cmVisualStudioWCEPlatformParser.cxx
- cmGlobalGhsMultiGenerator.cxx
- cmGlobalGhsMultiGenerator.h
- cmLocalGhsMultiGenerator.cxx
- cmLocalGhsMultiGenerator.h
- cmGhsMultiTargetGenerator.cxx
- cmGhsMultiTargetGenerator.h
- cmGhsMultiGpj.cxx
- cmGhsMultiGpj.h
cmVSSetupHelper.cxx
cmVSSetupHelper.h
)
@@ -699,6 +786,22 @@ if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux")
)
endif()
+# GHS support
+# Works only for windows and linux
+if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ set(SRCS ${SRCS}
+ cmGlobalGhsMultiGenerator.cxx
+ cmGlobalGhsMultiGenerator.h
+ cmLocalGhsMultiGenerator.cxx
+ cmLocalGhsMultiGenerator.h
+ cmGhsMultiTargetGenerator.cxx
+ cmGhsMultiTargetGenerator.h
+ cmGhsMultiGpj.cxx
+ cmGhsMultiGpj.h
+ )
+endif()
+
+
# Ninja support
set(SRCS ${SRCS}
cmGlobalNinjaGenerator.cxx
@@ -714,6 +817,8 @@ set(SRCS ${SRCS}
cmNinjaUtilityTargetGenerator.h
cmNinjaLinkLineComputer.cxx
cmNinjaLinkLineComputer.h
+ cmNinjaLinkLineDeviceComputer.cxx
+ cmNinjaLinkLineDeviceComputer.h
)
# Temporary variable for tools targets
@@ -741,20 +846,22 @@ foreach(check
else()
set(CMake_${check} 0)
endif()
- set_property(SOURCE cmFileTimeComparison.cxx APPEND PROPERTY
+ set_property(SOURCE cmFileTime.cxx APPEND PROPERTY
COMPILE_DEFINITIONS CMake_${check}=${CMake_${check}})
endforeach()
# create a library used by the command line and the GUI
add_library(CMakeLib ${SRCS})
target_link_libraries(CMakeLib cmsys
+ ${CMAKE_STD_LIBRARY}
${CMAKE_EXPAT_LIBRARIES} ${CMAKE_ZLIB_LIBRARIES}
- ${CMAKE_TAR_LIBRARIES} ${CMAKE_COMPRESS_LIBRARIES}
+ ${CMAKE_TAR_LIBRARIES}
${CMAKE_CURL_LIBRARIES}
${CMAKE_JSONCPP_LIBRARIES}
${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")
@@ -766,9 +873,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR MATCHES "sparc"
endif()
endif()
-# On Apple we need CoreFoundation
+# On Apple we need CoreFoundation and CoreServices
if(APPLE)
target_link_libraries(CMakeLib "-framework CoreFoundation")
+ target_link_libraries(CMakeLib "-framework CoreServices")
endif()
if(WIN32 AND NOT UNIX)
@@ -777,12 +885,13 @@ if(WIN32 AND NOT UNIX)
target_link_libraries(CMakeLib rpcrt4 crypt32)
endif()
+target_compile_definitions(CMakeLib PUBLIC ${CLANG_TIDY_DEFINITIONS})
+
#
# CTestLib
#
include_directories(
"${CMake_SOURCE_DIR}/Source/CTest"
- ${CMAKE_XMLRPC_INCLUDES}
${CMAKE_CURL_INCLUDES}
)
#
@@ -790,7 +899,7 @@ include_directories(
#
set(CTEST_SRCS cmCTest.cxx
CTest/cmProcess.cxx
- CTest/cmCTestBatchTestHandler.cxx
+ CTest/cmCTestBinPacker.cxx
CTest/cmCTestBuildAndTestHandler.cxx
CTest/cmCTestBuildCommand.cxx
CTest/cmCTestBuildHandler.cxx
@@ -810,11 +919,14 @@ set(CTEST_SRCS cmCTest.cxx
CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
CTest/cmCTestGenericHandler.cxx
CTest/cmCTestHandlerCommand.cxx
+ CTest/cmCTestResourceAllocator.cxx
+ CTest/cmCTestResourceSpec.cxx
CTest/cmCTestLaunch.cxx
CTest/cmCTestMemCheckCommand.cxx
CTest/cmCTestMemCheckHandler.cxx
CTest/cmCTestMultiProcessHandler.cxx
CTest/cmCTestReadCustomFilesCommand.cxx
+ CTest/cmCTestResourceGroupsLexerHelper.cxx
CTest/cmCTestRunScriptCommand.cxx
CTest/cmCTestRunTest.cxx
CTest/cmCTestScriptHandler.cxx
@@ -845,11 +957,15 @@ set(CTEST_SRCS cmCTest.cxx
CTest/cmCTestHG.h
CTest/cmCTestP4.cxx
CTest/cmCTestP4.h
+
+ LexerParser/cmCTestResourceGroupsLexer.cxx
+ LexerParser/cmCTestResourceGroupsLexer.h
+ LexerParser/cmCTestResourceGroupsLexer.in.l
)
# Build CTestLib
add_library(CTestLib ${CTEST_SRCS})
-target_link_libraries(CTestLib CMakeLib ${CMAKE_CURL_LIBRARIES} ${CMAKE_XMLRPC_LIBRARIES})
+target_link_libraries(CTestLib CMakeLib ${CMAKE_CURL_LIBRARIES})
#
# CPack
@@ -863,17 +979,14 @@ include_directories(
set(CPACK_SRCS
CPack/cmCPackArchiveGenerator.cxx
CPack/cmCPackComponentGroup.cxx
+ CPack/cmCPackDebGenerator.cxx
+ CPack/cmCPackExternalGenerator.cxx
CPack/cmCPackGeneratorFactory.cxx
CPack/cmCPackGenerator.cxx
CPack/cmCPackLog.cxx
CPack/cmCPackNSISGenerator.cxx
+ CPack/cmCPackNuGetGenerator.cxx
CPack/cmCPackSTGZGenerator.cxx
- CPack/cmCPackTGZGenerator.cxx
- CPack/cmCPackTXZGenerator.cxx
- CPack/cmCPackTarBZip2Generator.cxx
- CPack/cmCPackTarCompressGenerator.cxx
- CPack/cmCPackZIPGenerator.cxx
- CPack/cmCPack7zGenerator.cxx
)
# CPack IFW generator
set(CPACK_SRCS ${CPACK_SRCS}
@@ -896,15 +1009,48 @@ if(CYGWIN)
)
endif()
+option(CPACK_ENABLE_FREEBSD_PKG "Add FreeBSD pkg(8) generator to CPack." OFF)
+
if(UNIX)
set(CPACK_SRCS ${CPACK_SRCS}
- CPack/cmCPackDebGenerator.cxx
CPack/cmCPackRPMGenerator.cxx
)
+
+ # Optionally, try to use pkg(8)
+ if(CPACK_ENABLE_FREEBSD_PKG)
+ # On UNIX, you may find FreeBSD's pkg(8) and attendant
+ # library -- it can be used on FreeBSD, Dragonfly, NetBSD,
+ # 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")
+ if(FREEBSD_PKG_INCLUDE_DIRS)
+ find_library(FREEBSD_PKG_LIBRARIES
+ pkg
+ DOC "FreeBSD pkg(8) library")
+ if(FREEBSD_PKG_LIBRARIES)
+ set(CPACK_SRCS ${CPACK_SRCS}
+ CPack/cmCPackFreeBSDGenerator.cxx
+ )
+ endif()
+ endif()
+
+ if (NOT FREEBSD_PKG_INCLUDE_DIRS OR NOT FREEBSD_PKG_LIBRARIES)
+ message(FATAL_ERROR "CPack needs libpkg(3) to produce FreeBSD packages natively.")
+ endif()
+ else()
+ set(FREEBSD_PKG_INCLUDE_DIRS NOTFOUND)
+ set(FREEBSD_PKG_LIBRARIES NOTFOUND)
+ 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
@@ -925,7 +1071,7 @@ if(WIN32)
CPack/WiX/cmWIXShortcut.h
CPack/WiX/cmWIXSourceWriter.cxx
CPack/WiX/cmWIXSourceWriter.h
- )
+ )
endif()
if(APPLE)
@@ -958,11 +1104,18 @@ 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})
+ add_definitions(-DHAVE_FREEBSD_PKG)
+endif()
if(APPLE)
- add_executable(cmakexbuild cmakexbuild.cxx)
- list(APPEND _tools cmakexbuild)
- target_link_libraries(cmakexbuild CMakeLib)
add_executable(OSXScriptLauncher
CPack/OSXScriptLauncher.cxx)
target_link_libraries(OSXScriptLauncher cmsys)
@@ -974,18 +1127,19 @@ add_executable(cmake cmakemain.cxx cmcmd.cxx cmcmd.h ${MANIFEST_FILE})
list(APPEND _tools cmake)
target_link_libraries(cmake CMakeLib)
-if(CMake_ENABLE_SERVER_MODE)
- add_library(CMakeServerLib
- cmFileMonitor.cxx cmFileMonitor.h
- cmServer.cxx cmServer.h
- cmServerConnection.cxx cmServerConnection.h
- cmServerProtocol.cxx cmServerProtocol.h
- )
- target_link_libraries(CMakeServerLib CMakeLib)
- set_property(SOURCE cmcmd.cxx APPEND PROPERTY COMPILE_DEFINITIONS HAVE_SERVER_MODE=1)
-
- target_link_libraries(cmake CMakeServerLib)
-endif()
+add_library(CMakeServerLib
+ cmConnection.h cmConnection.cxx
+ cmFileMonitor.cxx cmFileMonitor.h
+ cmJsonObjectDictionary.h
+ cmJsonObjects.h
+ cmJsonObjects.cxx
+ cmPipeConnection.cxx cmPipeConnection.h
+ cmServer.cxx cmServer.h
+ cmServerConnection.cxx cmServerConnection.h
+ cmServerProtocol.cxx cmServerProtocol.h
+ )
+target_link_libraries(CMakeServerLib CMakeLib)
+target_link_libraries(cmake CMakeServerLib)
# Build CTest executable
add_executable(ctest ctest.cxx ${MANIFEST_FILE})
@@ -999,7 +1153,7 @@ target_link_libraries(cpack CPackLib)
# Curses GUI
if(BUILD_CursesDialog)
- include(${CMake_SOURCE_DIR}/Source/CursesDialog/CMakeLists.txt)
+ add_subdirectory(CursesDialog)
endif()
# Qt GUI
@@ -1011,6 +1165,34 @@ endif()
include (${CMake_BINARY_DIR}/Source/LocalUserOptions.cmake OPTIONAL)
include (${CMake_SOURCE_DIR}/Source/LocalUserOptions.cmake OPTIONAL)
+if(WIN32)
+ # 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_YEAR "${CMAKE_MATCH_1}")
+ set(CMake_RCVERSION_MONTH_DAY "${CMAKE_MATCH_2}")
+ string(REGEX REPLACE "^0+" "" CMake_RCVERSION_MONTH_DAY "${CMake_RCVERSION_MONTH_DAY}")
+ set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_RCVERSION_YEAR},${CMake_RCVERSION_MONTH_DAY})
+ unset(CMake_RCVERSION_MONTH_DAY)
+ unset(CMake_RCVERSION_YEAR)
+ else()
+ set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_VERSION_PATCH},0)
+ endif()
+ set(CMake_RCVERSION_STR ${CMake_VERSION})
+
+ # 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 ecf511607..23c0212f2 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,84 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
-set(CMake_VERSION_MINOR 9)
+set(CMake_VERSION_MINOR 16)
set(CMake_VERSION_PATCH 4)
#set(CMake_VERSION_RC 0)
+set(CMake_VERSION_IS_DIRTY 0)
+
+# Start with the full version number used in tags. It has no dev info.
+set(CMake_VERSION
+ "${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}")
+if(DEFINED CMake_VERSION_RC)
+ set(CMake_VERSION "${CMake_VERSION}-rc${CMake_VERSION_RC}")
+endif()
+
+# Releases define a small patch level.
+if("${CMake_VERSION_PATCH}" VERSION_LESS 20000000)
+ set(CMake_VERSION_IS_RELEASE 1)
+else()
+ set(CMake_VERSION_IS_RELEASE 0)
+endif()
+
+if(NOT CMake_VERSION_NO_GIT)
+ # If this source was exported by 'git archive', use its commit info.
+ set(git_info [==[$Format:%h %s$]==])
+
+ # Otherwise, try to identify the current development source version.
+ if(NOT git_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]?[0-9a-f]?)[0-9a-f]* "
+ AND EXISTS ${CMake_SOURCE_DIR}/.git)
+ find_package(Git QUIET)
+ if(GIT_FOUND)
+ macro(_git)
+ execute_process(
+ COMMAND ${GIT_EXECUTABLE} ${ARGN}
+ WORKING_DIRECTORY ${CMake_SOURCE_DIR}
+ RESULT_VARIABLE _git_res
+ OUTPUT_VARIABLE _git_out OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_VARIABLE _git_err ERROR_STRIP_TRAILING_WHITESPACE
+ )
+ endmacro()
+ endif()
+ if(COMMAND _git)
+ # Get the commit checked out in this work tree.
+ _git(log -n 1 HEAD "--pretty=format:%h %s" --)
+ set(git_info "${_git_out}")
+ endif()
+ endif()
+
+ # Extract commit information if available.
+ if(git_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]?[0-9a-f]?)[0-9a-f]* (.*)$")
+ # Have commit information.
+ set(git_hash "${CMAKE_MATCH_1}")
+ set(git_subject "${CMAKE_MATCH_2}")
+
+ # If this is not the exact commit of a release, add dev info.
+ if(NOT "${git_subject}" MATCHES "^[Cc][Mm]ake ${CMake_VERSION}$")
+ set(CMake_VERSION "${CMake_VERSION}-g${git_hash}")
+ endif()
+
+ # If this is a work tree, check whether it is dirty.
+ if(COMMAND _git)
+ _git(update-index -q --refresh)
+ _git(diff-index --name-only HEAD --)
+ if(_git_out)
+ set(CMake_VERSION_IS_DIRTY 1)
+ endif()
+ endif()
+ else()
+ # No commit information.
+ if(NOT CMake_VERSION_IS_RELEASE)
+ # Generic development version.
+ set(CMake_VERSION "${CMake_VERSION}-git")
+ endif()
+ endif()
+endif()
+
+# Extract the version suffix component.
+if(CMake_VERSION MATCHES "-(.*)$")
+ set(CMake_VERSION_SUFFIX "${CMAKE_MATCH_1}")
+else()
+ set(CMake_VERSION_SUFFIX "")
+endif()
+if(CMake_VERSION_IS_DIRTY)
+ set(CMake_VERSION ${CMake_VERSION}-dirty)
+endif()
diff --git a/Source/CMakeVersion.rc.in b/Source/CMakeVersion.rc.in
new file mode 100644
index 000000000..762d9bb62
--- /dev/null
+++ b/Source/CMakeVersion.rc.in
@@ -0,0 +1,28 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+1 VERSIONINFO
+FILEVERSION @CMake_RCVERSION@
+PRODUCTVERSION @CMake_RCVERSION@
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4"
+ BEGIN
+ VALUE "FileVersion", "@CMake_RCVERSION_STR@\0"
+ VALUE "ProductVersion", "@CMake_RCVERSION_STR@\0"
+ 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
deleted file mode 100644
index d9218d731..000000000
--- a/Source/CMakeVersionCompute.cmake
+++ /dev/null
@@ -1,29 +0,0 @@
-# Load version number components.
-include(${CMake_SOURCE_DIR}/Source/CMakeVersion.cmake)
-
-# Releases define a small patch level.
-if("${CMake_VERSION_PATCH}" VERSION_LESS 20000000)
- set(CMake_VERSION_IS_DIRTY 0)
- set(CMake_VERSION_IS_RELEASE 1)
- set(CMake_VERSION_SOURCE "")
-else()
- set(CMake_VERSION_IS_DIRTY 0) # may be set to 1 by CMakeVersionSource
- set(CMake_VERSION_IS_RELEASE 0)
- include(${CMake_SOURCE_DIR}/Source/CMakeVersionSource.cmake)
-endif()
-
-# Compute the full version string.
-set(CMake_VERSION ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH})
-if(CMake_VERSION_SOURCE)
- set(CMake_VERSION_SUFFIX "${CMake_VERSION_SOURCE}")
-elseif(CMake_VERSION_RC)
- set(CMake_VERSION_SUFFIX "rc${CMake_VERSION_RC}")
-else()
- set(CMake_VERSION_SUFFIX "")
-endif()
-if(CMake_VERSION_SUFFIX)
- set(CMake_VERSION ${CMake_VERSION}-${CMake_VERSION_SUFFIX})
-endif()
-if(CMake_VERSION_IS_DIRTY)
- set(CMake_VERSION ${CMake_VERSION}-dirty)
-endif()
diff --git a/Source/CMakeVersionSource.cmake b/Source/CMakeVersionSource.cmake
deleted file mode 100644
index 5ea1de3f4..000000000
--- a/Source/CMakeVersionSource.cmake
+++ /dev/null
@@ -1,30 +0,0 @@
-# Try to identify the current development source version.
-set(CMake_VERSION_SOURCE "")
-if(EXISTS ${CMake_SOURCE_DIR}/.git/HEAD)
- find_program(GIT_EXECUTABLE NAMES git git.cmd)
- mark_as_advanced(GIT_EXECUTABLE)
- if(GIT_EXECUTABLE)
- execute_process(
- COMMAND ${GIT_EXECUTABLE} rev-parse --verify -q --short=4 HEAD
- OUTPUT_VARIABLE head
- OUTPUT_STRIP_TRAILING_WHITESPACE
- WORKING_DIRECTORY ${CMake_SOURCE_DIR}
- )
- if(head)
- set(CMake_VERSION_SOURCE "g${head}")
- execute_process(
- COMMAND ${GIT_EXECUTABLE} update-index -q --refresh
- WORKING_DIRECTORY ${CMake_SOURCE_DIR}
- )
- execute_process(
- COMMAND ${GIT_EXECUTABLE} diff-index --name-only HEAD --
- OUTPUT_VARIABLE dirty
- OUTPUT_STRIP_TRAILING_WHITESPACE
- WORKING_DIRECTORY ${CMake_SOURCE_DIR}
- )
- if(dirty)
- set(CMake_VERSION_IS_DIRTY 1)
- endif()
- endif()
- endif()
-endif()
diff --git a/Source/CPack/IFW/cmCPackIFWCommon.cxx b/Source/CPack/IFW/cmCPackIFWCommon.cxx
index e8f05bd50..9fa74be76 100644
--- a/Source/CPack/IFW/cmCPackIFWCommon.cxx
+++ b/Source/CPack/IFW/cmCPackIFWCommon.cxx
@@ -2,27 +2,29 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackIFWCommon.h"
+#include <cstddef>
+#include <sstream>
+#include <utility>
+#include <vector>
+
#include "cmCPackGenerator.h"
#include "cmCPackIFWGenerator.h"
#include "cmCPackLog.h" // IWYU pragma: keep
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTimestamp.h"
#include "cmVersionConfig.h"
#include "cmXMLWriter.h"
-#include <sstream>
-#include <utility>
-#include <vector>
-
cmCPackIFWCommon::cmCPackIFWCommon()
- : Generator(CM_NULLPTR)
+ : Generator(nullptr)
{
}
const char* cmCPackIFWCommon::GetOption(const std::string& op) const
{
return this->Generator ? this->Generator->cmCPackGenerator::GetOption(op)
- : CM_NULLPTR;
+ : nullptr;
}
bool cmCPackIFWCommon::IsOn(const std::string& op) const
@@ -77,8 +79,7 @@ bool cmCPackIFWCommon::IsVersionEqual(const char* version)
void cmCPackIFWCommon::ExpandListArgument(
const std::string& arg, std::map<std::string, std::string>& argsOut)
{
- std::vector<std::string> args;
- cmSystemTools::ExpandListArgument(arg, args, false);
+ std::vector<std::string> args = cmExpandedList(arg, false);
if (args.empty()) {
return;
}
@@ -99,8 +100,7 @@ void cmCPackIFWCommon::ExpandListArgument(
void cmCPackIFWCommon::ExpandListArgument(
const std::string& arg, std::multimap<std::string, std::string>& argsOut)
{
- std::vector<std::string> args;
- cmSystemTools::ExpandListArgument(arg, args, false);
+ std::vector<std::string> args = cmExpandedList(arg, false);
if (args.empty()) {
return;
}
diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
index 226ea0a29..509ac6507 100644
--- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
@@ -2,6 +2,9 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackIFWGenerator.h"
+#include <sstream>
+#include <utility>
+
#include "cmCPackComponentGroup.h"
#include "cmCPackGenerator.h"
#include "cmCPackIFWCommon.h"
@@ -9,20 +12,17 @@
#include "cmCPackIFWPackage.h"
#include "cmCPackIFWRepository.h"
#include "cmCPackLog.h" // IWYU pragma: keep
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include <sstream>
-#include <utility>
-
cmCPackIFWGenerator::cmCPackIFWGenerator()
{
this->Generator = this;
}
-cmCPackIFWGenerator::~cmCPackIFWGenerator()
-{
-}
+cmCPackIFWGenerator::~cmCPackIFWGenerator() = default;
int cmCPackIFWGenerator::PackageFiles()
{
@@ -35,152 +35,202 @@ int cmCPackIFWGenerator::PackageFiles()
this->Installer.GeneratePackageFiles();
std::string ifwTLD = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- std::string ifwTmpFile = ifwTLD;
- ifwTmpFile += "/IFWOutput.log";
+ std::string ifwTmpFile = cmStrCat(ifwTLD, "/IFWOutput.log");
// Run repogen
if (!this->Installer.RemoteRepositories.empty()) {
- std::string ifwCmd = this->RepoGen;
+ std::vector<std::string> ifwCmd;
+ std::string ifwArg;
+
+ ifwCmd.emplace_back(this->RepoGen);
if (this->IsVersionLess("2.0.0")) {
- ifwCmd += " -c " + this->toplevel + "/config/config.xml";
+ ifwCmd.emplace_back("-c");
+ ifwCmd.emplace_back(this->toplevel + "/config/config.xml");
}
- ifwCmd += " -p " + this->toplevel + "/packages";
+ ifwCmd.emplace_back("-p");
+ ifwCmd.emplace_back(this->toplevel + "/packages");
if (!this->PkgsDirsVector.empty()) {
- for (std::vector<std::string>::iterator it =
- this->PkgsDirsVector.begin();
- it != this->PkgsDirsVector.end(); ++it) {
- ifwCmd += " -p " + *it;
+ for (std::string const& it : this->PkgsDirsVector) {
+ ifwCmd.emplace_back("-p");
+ ifwCmd.emplace_back(it);
+ }
+ }
+
+ if (!this->RepoDirsVector.empty()) {
+ if (!this->IsVersionLess("3.1")) {
+ for (std::string const& rd : this->RepoDirsVector) {
+ ifwCmd.emplace_back("--repository");
+ ifwCmd.emplace_back(rd);
+ }
+ } else {
+ cmCPackIFWLogger(WARNING,
+ "The \"CPACK_IFW_REPOSITORIES_DIRECTORIES\" "
+ << "variable is set, but content will be skipped, "
+ << "because this feature available only since "
+ << "QtIFW 3.1. Please update your QtIFW instance."
+ << std::endl);
}
}
if (!this->OnlineOnly && !this->DownloadedPackages.empty()) {
- ifwCmd += " -i ";
- std::set<cmCPackIFWPackage*>::iterator it =
- this->DownloadedPackages.begin();
- ifwCmd += (*it)->Name;
+ ifwCmd.emplace_back("-i");
+ auto it = this->DownloadedPackages.begin();
+ ifwArg = (*it)->Name;
++it;
while (it != this->DownloadedPackages.end()) {
- ifwCmd += "," + (*it)->Name;
+ ifwArg += "," + (*it)->Name;
++it;
}
+ ifwCmd.emplace_back(ifwArg);
}
- ifwCmd += " " + this->toplevel + "/repository";
- cmCPackIFWLogger(VERBOSE, "Execute: " << ifwCmd << std::endl);
+ ifwCmd.emplace_back(this->toplevel + "/repository");
+ cmCPackIFWLogger(VERBOSE,
+ "Execute: " << cmSystemTools::PrintSingleCommand(ifwCmd)
+ << std::endl);
std::string output;
int retVal = 1;
cmCPackIFWLogger(OUTPUT, "- Generate repository" << std::endl);
- bool res = cmSystemTools::RunSingleCommand(ifwCmd.c_str(), &output,
- &output, &retVal, CM_NULLPTR,
- this->GeneratorVerbose, 0);
+ bool res = cmSystemTools::RunSingleCommand(
+ ifwCmd, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+ cmDuration::zero());
if (!res || retVal) {
- cmGeneratedFileStream ofs(ifwTmpFile.c_str());
- ofs << "# Run command: " << ifwCmd << std::endl
+ cmGeneratedFileStream ofs(ifwTmpFile);
+ ofs << "# Run command: " << cmSystemTools::PrintSingleCommand(ifwCmd)
+ << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackIFWLogger(ERROR, "Problem running IFW command: "
- << ifwCmd << std::endl
- << "Please check " << ifwTmpFile << " for errors"
- << std::endl);
+ cmCPackIFWLogger(
+ ERROR,
+ "Problem running IFW command: "
+ << cmSystemTools::PrintSingleCommand(ifwCmd) << std::endl
+ << "Please check \"" << ifwTmpFile << "\" for errors" << std::endl);
return 0;
}
if (!this->Repository.RepositoryUpdate.empty() &&
!this->Repository.PatchUpdatesXml()) {
- cmCPackIFWLogger(WARNING, "Problem patch IFW \"Updates\" "
- << "file: "
- << this->toplevel + "/repository/Updates.xml"
- << std::endl);
+ cmCPackIFWLogger(WARNING,
+ "Problem patch IFW \"Updates\" "
+ << "file: \"" << this->toplevel
+ << "/repository/Updates.xml\"" << std::endl);
}
- cmCPackIFWLogger(OUTPUT, "- repository: " << this->toplevel
- << "/repository generated"
- << std::endl);
+ cmCPackIFWLogger(OUTPUT,
+ "- repository: \"" << this->toplevel
+ << "/repository\" generated"
+ << std::endl);
}
// Run binary creator
{
- std::string ifwCmd = this->BinCreator;
- ifwCmd += " -c " + this->toplevel + "/config/config.xml";
+ std::vector<std::string> ifwCmd;
+ std::string ifwArg;
+
+ ifwCmd.emplace_back(this->BinCreator);
+
+ ifwCmd.emplace_back("-c");
+ ifwCmd.emplace_back(this->toplevel + "/config/config.xml");
if (!this->Installer.Resources.empty()) {
- ifwCmd += " -r ";
- std::vector<std::string>::iterator it =
- this->Installer.Resources.begin();
+ ifwCmd.emplace_back("-r");
+ auto it = this->Installer.Resources.begin();
std::string path = this->toplevel + "/resources/";
- ifwCmd += path + *it;
+ ifwArg = path + *it;
++it;
while (it != this->Installer.Resources.end()) {
- ifwCmd += "," + path + *it;
+ ifwArg += "," + path + *it;
++it;
}
+ ifwCmd.emplace_back(ifwArg);
}
- ifwCmd += " -p " + this->toplevel + "/packages";
+ ifwCmd.emplace_back("-p");
+ ifwCmd.emplace_back(this->toplevel + "/packages");
if (!this->PkgsDirsVector.empty()) {
- for (std::vector<std::string>::iterator it =
- this->PkgsDirsVector.begin();
- it != this->PkgsDirsVector.end(); ++it) {
- ifwCmd += " -p " + *it;
+ for (std::string const& it : this->PkgsDirsVector) {
+ ifwCmd.emplace_back("-p");
+ ifwCmd.emplace_back(it);
+ }
+ }
+
+ if (!this->RepoDirsVector.empty()) {
+ if (!this->IsVersionLess("3.1")) {
+ for (std::string const& rd : this->RepoDirsVector) {
+ ifwCmd.emplace_back("--repository");
+ ifwCmd.emplace_back(rd);
+ }
+ } else {
+ cmCPackIFWLogger(WARNING,
+ "The \"CPACK_IFW_REPOSITORIES_DIRECTORIES\" "
+ << "variable is set, but content will be skipped, "
+ << "because this feature available only since "
+ << "QtIFW 3.1. Please update your QtIFW instance."
+ << std::endl);
}
}
if (this->OnlineOnly) {
- ifwCmd += " --online-only";
+ ifwCmd.emplace_back("--online-only");
} else if (!this->DownloadedPackages.empty() &&
!this->Installer.RemoteRepositories.empty()) {
- ifwCmd += " -e ";
- std::set<cmCPackIFWPackage*>::iterator it =
- this->DownloadedPackages.begin();
- ifwCmd += (*it)->Name;
+ ifwCmd.emplace_back("-e");
+ auto it = this->DownloadedPackages.begin();
+ ifwArg = (*it)->Name;
++it;
while (it != this->DownloadedPackages.end()) {
- ifwCmd += "," + (*it)->Name;
+ ifwArg += "," + (*it)->Name;
++it;
}
+ ifwCmd.emplace_back(ifwArg);
} else if (!this->DependentPackages.empty()) {
- ifwCmd += " -i ";
+ ifwCmd.emplace_back("-i");
+ ifwArg.clear();
// Binary
- std::set<cmCPackIFWPackage*>::iterator bit =
- this->BinaryPackages.begin();
+ auto bit = this->BinaryPackages.begin();
while (bit != this->BinaryPackages.end()) {
- ifwCmd += (*bit)->Name + ",";
+ ifwArg += (*bit)->Name + ",";
++bit;
}
// Depend
- DependenceMap::iterator it = this->DependentPackages.begin();
- ifwCmd += it->second.Name;
+ auto it = this->DependentPackages.begin();
+ ifwArg += it->second.Name;
++it;
while (it != this->DependentPackages.end()) {
- ifwCmd += "," + it->second.Name;
+ ifwArg += "," + it->second.Name;
++it;
}
+ ifwCmd.emplace_back(ifwArg);
}
// TODO: set correct name for multipackages
if (!this->packageFileNames.empty()) {
- ifwCmd += " " + this->packageFileNames[0];
+ ifwCmd.emplace_back(this->packageFileNames[0]);
} else {
- ifwCmd += " installer";
+ ifwCmd.emplace_back("installer" + this->OutputExtension);
}
- cmCPackIFWLogger(VERBOSE, "Execute: " << ifwCmd << std::endl);
+ cmCPackIFWLogger(VERBOSE,
+ "Execute: " << cmSystemTools::PrintSingleCommand(ifwCmd)
+ << std::endl);
std::string output;
int retVal = 1;
cmCPackIFWLogger(OUTPUT, "- Generate package" << std::endl);
- bool res = cmSystemTools::RunSingleCommand(ifwCmd.c_str(), &output,
- &output, &retVal, CM_NULLPTR,
- this->GeneratorVerbose, 0);
+ bool res = cmSystemTools::RunSingleCommand(
+ ifwCmd, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+ cmDuration::zero());
if (!res || retVal) {
- cmGeneratedFileStream ofs(ifwTmpFile.c_str());
- ofs << "# Run command: " << ifwCmd << std::endl
+ cmGeneratedFileStream ofs(ifwTmpFile);
+ ofs << "# Run command: " << cmSystemTools::PrintSingleCommand(ifwCmd)
+ << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackIFWLogger(ERROR, "Problem running IFW command: "
- << ifwCmd << std::endl
- << "Please check " << ifwTmpFile << " for errors"
- << std::endl);
+ cmCPackIFWLogger(
+ ERROR,
+ "Problem running IFW command: "
+ << cmSystemTools::PrintSingleCommand(ifwCmd) << std::endl
+ << "Please check \"" << ifwTmpFile << "\" for errors" << std::endl);
return 0;
}
}
@@ -205,7 +255,7 @@ const char* cmCPackIFWGenerator::GetPackagingInstallPrefix()
const char* cmCPackIFWGenerator::GetOutputExtension()
{
- return this->ExecutableSuffix.c_str();
+ return this->OutputExtension.c_str();
}
int cmCPackIFWGenerator::InitializeInternal()
@@ -224,15 +274,16 @@ int cmCPackIFWGenerator::InitializeInternal()
// Look 'binarycreator' executable (needs)
const char* BinCreatorStr = this->GetOption(BinCreatorOpt);
- if (!BinCreatorStr || cmSystemTools::IsNOTFOUND(BinCreatorStr)) {
- this->BinCreator = "";
+ if (!BinCreatorStr || cmIsNOTFOUND(BinCreatorStr)) {
+ this->BinCreator.clear();
} else {
this->BinCreator = BinCreatorStr;
}
if (this->BinCreator.empty()) {
- cmCPackIFWLogger(ERROR, "Cannot find QtIFW compiler \"binarycreator\": "
- "likely it is not installed, or not in your PATH"
+ cmCPackIFWLogger(ERROR,
+ "Cannot find QtIFW compiler \"binarycreator\": "
+ "likely it is not installed, or not in your PATH"
<< std::endl);
return 0;
}
@@ -240,8 +291,8 @@ int cmCPackIFWGenerator::InitializeInternal()
// Look 'repogen' executable (optional)
const char* RepoGenStr = this->GetOption(RepoGenOpt);
- if (!RepoGenStr || cmSystemTools::IsNOTFOUND(RepoGenStr)) {
- this->RepoGen = "";
+ if (!RepoGenStr || cmIsNOTFOUND(RepoGenStr)) {
+ this->RepoGen.clear();
} else {
this->RepoGen = RepoGenStr;
}
@@ -262,7 +313,14 @@ int cmCPackIFWGenerator::InitializeInternal()
// Additional packages dirs
this->PkgsDirsVector.clear();
if (const char* dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) {
- cmSystemTools::ExpandListArgument(dirs, this->PkgsDirsVector);
+ cmExpandList(dirs, this->PkgsDirsVector);
+ }
+
+ // Additional repositories dirs
+ this->RepoDirsVector.clear();
+ if (const char* dirs =
+ this->GetOption("CPACK_IFW_REPOSITORIES_DIRECTORIES")) {
+ cmExpandList(dirs, this->RepoDirsVector);
}
// Installer
@@ -279,19 +337,17 @@ int cmCPackIFWGenerator::InitializeInternal()
// Repositories
if (const char* RepoAllStr = this->GetOption("CPACK_IFW_REPOSITORIES_ALL")) {
- std::vector<std::string> RepoAllVector;
- cmSystemTools::ExpandListArgument(RepoAllStr, RepoAllVector);
- for (std::vector<std::string>::iterator rit = RepoAllVector.begin();
- rit != RepoAllVector.end(); ++rit) {
- this->GetRepository(*rit);
+ std::vector<std::string> RepoAllVector = cmExpandedList(RepoAllStr);
+ for (std::string const& r : RepoAllVector) {
+ this->GetRepository(r);
}
}
if (const char* ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) {
- this->OnlineOnly = cmSystemTools::IsOn(ifwDownloadAll);
+ this->OnlineOnly = cmIsOn(ifwDownloadAll);
} else if (const char* cpackDownloadAll =
this->GetOption("CPACK_DOWNLOAD_ALL")) {
- this->OnlineOnly = cmSystemTools::IsOn(cpackDownloadAll);
+ this->OnlineOnly = cmIsOn(cpackDownloadAll);
} else {
this->OnlineOnly = false;
}
@@ -305,16 +361,29 @@ int cmCPackIFWGenerator::InitializeInternal()
}
// Executable suffix
- if (const char* optExeSuffix = this->GetOption("CMAKE_EXECUTABLE_SUFFIX")) {
- this->ExecutableSuffix = optExeSuffix;
- if (this->ExecutableSuffix.empty()) {
- std::string sysName(this->GetOption("CMAKE_SYSTEM_NAME"));
- if (sysName == "Linux") {
- this->ExecutableSuffix = ".run";
- }
- }
+ std::string exeSuffix(this->GetOption("CMAKE_EXECUTABLE_SUFFIX"));
+ std::string sysName(this->GetOption("CMAKE_SYSTEM_NAME"));
+ if (sysName == "Linux") {
+ this->ExecutableSuffix = ".run";
+ } else if (sysName == "Windows") {
+ this->ExecutableSuffix = ".exe";
+ } else if (sysName == "Darwin") {
+ this->ExecutableSuffix = ".app";
} else {
- this->ExecutableSuffix = this->cmCPackGenerator::GetOutputExtension();
+ this->ExecutableSuffix = exeSuffix;
+ }
+
+ // Output extension
+ if (const char* optOutExt =
+ this->GetOption("CPACK_IFW_PACKAGE_FILE_EXTENSION")) {
+ this->OutputExtension = optOutExt;
+ } else if (sysName == "Darwin") {
+ this->OutputExtension = ".dmg";
+ } else {
+ this->OutputExtension = this->ExecutableSuffix;
+ }
+ if (this->OutputExtension.empty()) {
+ this->OutputExtension = this->cmCPackGenerator::GetOutputExtension();
}
return this->Superclass::InitializeInternal();
@@ -337,7 +406,7 @@ std::string cmCPackIFWGenerator::GetComponentInstallDirNameSuffix(
cmCPackComponent* cmCPackIFWGenerator::GetComponent(
const std::string& projectName, const std::string& componentName)
{
- ComponentsMap::iterator cit = this->Components.find(componentName);
+ auto cit = this->Components.find(componentName);
if (cit != this->Components.end()) {
return &(cit->second);
}
@@ -349,7 +418,7 @@ cmCPackComponent* cmCPackIFWGenerator::GetComponent(
}
std::string name = this->GetComponentPackageName(component);
- PackagesMap::iterator pit = this->Packages.find(name);
+ auto pit = this->Packages.find(name);
if (pit != this->Packages.end()) {
return component;
}
@@ -370,7 +439,8 @@ cmCPackComponent* cmCPackIFWGenerator::GetComponent(
}
} else {
this->Packages.erase(name);
- cmCPackIFWLogger(ERROR, "Cannot configure package \""
+ cmCPackIFWLogger(ERROR,
+ "Cannot configure package \""
<< name << "\" for component \"" << component->Name
<< "\"" << std::endl);
}
@@ -388,7 +458,7 @@ cmCPackComponentGroup* cmCPackIFWGenerator::GetComponentGroup(
}
std::string name = this->GetGroupPackageName(group);
- PackagesMap::iterator pit = this->Packages.find(name);
+ auto pit = this->Packages.find(name);
if (pit != this->Packages.end()) {
return group;
}
@@ -405,7 +475,8 @@ cmCPackComponentGroup* cmCPackIFWGenerator::GetComponentGroup(
this->BinaryPackages.insert(package);
} else {
this->Packages.erase(name);
- cmCPackIFWLogger(ERROR, "Cannot configure package \""
+ cmCPackIFWLogger(ERROR,
+ "Cannot configure package \""
<< name << "\" for component group \"" << group->Name
<< "\"" << std::endl);
}
@@ -518,23 +589,21 @@ std::string cmCPackIFWGenerator::GetComponentPackageName(
cmCPackIFWPackage* cmCPackIFWGenerator::GetGroupPackage(
cmCPackComponentGroup* group) const
{
- std::map<cmCPackComponentGroup*, cmCPackIFWPackage*>::const_iterator pit =
- this->GroupPackages.find(group);
- return pit != this->GroupPackages.end() ? pit->second : CM_NULLPTR;
+ auto pit = this->GroupPackages.find(group);
+ return pit != this->GroupPackages.end() ? pit->second : nullptr;
}
cmCPackIFWPackage* cmCPackIFWGenerator::GetComponentPackage(
cmCPackComponent* component) const
{
- std::map<cmCPackComponent*, cmCPackIFWPackage*>::const_iterator pit =
- this->ComponentPackages.find(component);
- return pit != this->ComponentPackages.end() ? pit->second : CM_NULLPTR;
+ auto pit = this->ComponentPackages.find(component);
+ return pit != this->ComponentPackages.end() ? pit->second : nullptr;
}
cmCPackIFWRepository* cmCPackIFWGenerator::GetRepository(
const std::string& repositoryName)
{
- RepositoriesMap::iterator rit = this->Repositories.find(repositoryName);
+ auto rit = this->Repositories.find(repositoryName);
if (rit != this->Repositories.end()) {
return &(rit->second);
}
@@ -550,8 +619,9 @@ cmCPackIFWRepository* cmCPackIFWGenerator::GetRepository(
}
} else {
this->Repositories.erase(repositoryName);
- repository = CM_NULLPTR;
- cmCPackIFWLogger(WARNING, "Invalid repository \""
+ repository = nullptr;
+ cmCPackIFWLogger(WARNING,
+ "Invalid repository \""
<< repositoryName << "\""
<< " configuration. Repository will be skipped."
<< std::endl);
diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.h b/Source/CPack/IFW/cmCPackIFWGenerator.h
index 8348ceeec..86a73c83f 100644
--- a/Source/CPack/IFW/cmCPackIFWGenerator.h
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.h
@@ -5,6 +5,11 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
#include "cmCPackComponentGroup.h"
#include "cmCPackGenerator.h"
#include "cmCPackIFWCommon.h"
@@ -12,27 +17,24 @@
#include "cmCPackIFWPackage.h"
#include "cmCPackIFWRepository.h"
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
/** \class cmCPackIFWGenerator
* \brief A generator for Qt Installer Framework tools
*
* http://qt-project.org/doc/qtinstallerframework/index.html
*/
-class cmCPackIFWGenerator : public cmCPackGenerator, public cmCPackIFWCommon
+class cmCPackIFWGenerator
+ : public cmCPackGenerator
+ , public cmCPackIFWCommon
{
public:
cmCPackTypeMacro(cmCPackIFWGenerator, cmCPackGenerator);
- typedef std::map<std::string, cmCPackIFWPackage> PackagesMap;
- typedef std::map<std::string, cmCPackIFWRepository> RepositoriesMap;
- typedef std::map<std::string, cmCPackComponent> ComponentsMap;
- typedef std::map<std::string, cmCPackComponentGroup> ComponentGoupsMap;
- typedef std::map<std::string, cmCPackIFWPackage::DependenceStruct>
- DependenceMap;
+ using PackagesMap = std::map<std::string, cmCPackIFWPackage>;
+ using RepositoriesMap = std::map<std::string, cmCPackIFWRepository>;
+ using ComponentsMap = std::map<std::string, cmCPackComponent>;
+ using ComponentGoupsMap = std::map<std::string, cmCPackComponentGroup>;
+ using DependenceMap =
+ std::map<std::string, cmCPackIFWPackage::DependenceStruct>;
using cmCPackIFWCommon::GetOption;
using cmCPackIFWCommon::IsOn;
@@ -47,7 +49,7 @@ public:
/**
* Destruct IFW generator
*/
- ~cmCPackIFWGenerator() CM_OVERRIDE;
+ ~cmCPackIFWGenerator() override;
protected:
// cmCPackGenerator reimplementation
@@ -56,18 +58,18 @@ protected:
* @brief Initialize generator
* @return 0 on failure
*/
- int InitializeInternal() CM_OVERRIDE;
- int PackageFiles() CM_OVERRIDE;
- const char* GetPackagingInstallPrefix() CM_OVERRIDE;
+ int InitializeInternal() override;
+ int PackageFiles() override;
+ const char* GetPackagingInstallPrefix() override;
/**
- * @brief Extension of binary installer
- * @return Executable suffix or value from default implementation
+ * @brief Target binary extension
+ * @return Executable suffix or disk image format
*/
- const char* GetOutputExtension() CM_OVERRIDE;
+ const char* GetOutputExtension() override;
std::string GetComponentInstallDirNameSuffix(
- const std::string& componentName) CM_OVERRIDE;
+ const std::string& componentName) override;
/**
* @brief Get Component
@@ -79,7 +81,7 @@ protected:
* @return Pointer to component
*/
cmCPackComponent* GetComponent(const std::string& projectName,
- const std::string& componentName) CM_OVERRIDE;
+ const std::string& componentName) override;
/**
* @brief Get group of component
@@ -91,12 +93,12 @@ protected:
* @return Pointer to component group
*/
cmCPackComponentGroup* GetComponentGroup(
- const std::string& projectName, const std::string& groupName) CM_OVERRIDE;
+ const std::string& projectName, const std::string& groupName) override;
- enum cmCPackGenerator::CPackSetDestdirSupport SupportsSetDestdir() const
- CM_OVERRIDE;
- bool SupportsAbsoluteDestination() const CM_OVERRIDE;
- bool SupportsComponentInstallation() const CM_OVERRIDE;
+ enum cmCPackGenerator::CPackSetDestdirSupport SupportsSetDestdir()
+ const override;
+ bool SupportsAbsoluteDestination() const override;
+ bool SupportsComponentInstallation() const override;
protected:
// Methods
@@ -143,10 +145,12 @@ private:
std::string BinCreator;
std::string FrameworkVersion;
std::string ExecutableSuffix;
+ std::string OutputExtension;
bool OnlineOnly;
bool ResolveDuplicateNames;
std::vector<std::string> PkgsDirsVector;
+ std::vector<std::string> RepoDirsVector;
};
#endif
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
index 288e924e5..4bad598e9 100644
--- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
@@ -2,29 +2,29 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackIFWInstaller.h"
+#include <cstddef>
+#include <sstream>
+#include <utility>
+
#include "cmCPackIFWCommon.h"
#include "cmCPackIFWGenerator.h"
#include "cmCPackIFWPackage.h"
#include "cmCPackIFWRepository.h"
#include "cmCPackLog.h" // IWYU pragma: keep
#include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
#include "cmXMLWriter.h"
-#include <sstream>
-#include <stddef.h>
-#include <utility>
-
-cmCPackIFWInstaller::cmCPackIFWInstaller()
-{
-}
+cmCPackIFWInstaller::cmCPackIFWInstaller() = default;
void cmCPackIFWInstaller::printSkippedOptionWarning(
const std::string& optionName, const std::string& optionValue)
{
cmCPackIFWLogger(
- WARNING, "Option "
+ WARNING,
+ "Option "
<< optionName << " is set to \"" << optionValue
<< "\" but will be skipped because the specified file does not exist."
<< std::endl);
@@ -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)) {
@@ -137,12 +146,22 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
if (this->WizardStyle != "Modern" && this->WizardStyle != "Aero" &&
this->WizardStyle != "Mac" && this->WizardStyle != "Classic") {
cmCPackIFWLogger(
- WARNING, "Option CPACK_IFW_PACKAGE_WIZARD_STYLE has unknown value \""
+ WARNING,
+ "Option CPACK_IFW_PACKAGE_WIZARD_STYLE has unknown value \""
<< option << "\". Expected values are: Modern, Aero, Mac, Classic."
<< std::endl);
}
}
+ // StyleSheet
+ if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_STYLE_SHEET")) {
+ if (cmSystemTools::FileExists(option)) {
+ this->StyleSheet = option;
+ } else {
+ this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_STYLE_SHEET", option);
+ }
+ }
+
// WizardDefaultWidth
if (const char* option =
this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH")) {
@@ -174,8 +193,8 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
this->TargetDir = optIFW_TARGET_DIRECTORY;
} else if (const char* optPACKAGE_INSTALL_DIRECTORY =
this->GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) {
- this->TargetDir = "@ApplicationsDir@/";
- this->TargetDir += optPACKAGE_INSTALL_DIRECTORY;
+ this->TargetDir =
+ cmStrCat("@ApplicationsDir@/", optPACKAGE_INSTALL_DIRECTORY);
} else {
this->TargetDir = "@RootDir@/usr/local";
}
@@ -226,8 +245,7 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
if (const char* optIFW_PACKAGE_RESOURCES =
this->GetOption("CPACK_IFW_PACKAGE_RESOURCES")) {
this->Resources.clear();
- cmSystemTools::ExpandListArgument(optIFW_PACKAGE_RESOURCES,
- this->Resources);
+ cmExpandList(optIFW_PACKAGE_RESOURCES, this->Resources);
}
}
@@ -262,7 +280,7 @@ public:
std::string path, basePath;
protected:
- void StartElement(const std::string& name, const char** /*atts*/) CM_OVERRIDE
+ void StartElement(const std::string& name, const char** /*atts*/) override
{
this->file = name == "file";
if (file) {
@@ -270,21 +288,20 @@ protected:
}
}
- void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
+ void CharacterDataHandler(const char* data, int length) override
{
if (this->file) {
std::string content(data, data + length);
- content = cmSystemTools::TrimWhitespace(content);
+ content = cmTrimWhitespace(content);
std::string source = this->basePath + "/" + content;
std::string destination = this->path + "/" + content;
- if (!cmSystemTools::CopyFileIfDifferent(source.data(),
- destination.data())) {
+ if (!cmSystemTools::CopyFileIfDifferent(source, destination)) {
this->hasErrors = true;
}
}
}
- void EndElement(const std::string& /*name*/) CM_OVERRIDE {}
+ void EndElement(const std::string& /*name*/) override {}
};
void cmCPackIFWInstaller::GenerateInstallerFile()
@@ -295,7 +312,7 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
}
// Output stream
- cmGeneratedFileStream fout((this->Directory + "/config/config.xml").data());
+ cmGeneratedFileStream fout(this->Directory + "/config/config.xml");
cmXMLWriter xout(fout);
xout.StartDocument();
@@ -373,6 +390,14 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
xout.Element("WizardStyle", this->WizardStyle);
}
+ // Stylesheet
+ if (!this->StyleSheet.empty()) {
+ std::string name = cmSystemTools::GetFilenameName(this->StyleSheet);
+ std::string path = this->Directory + "/config/" + name;
+ cmsys::SystemTools::CopyFileIfDifferent(this->StyleSheet, path);
+ xout.Element("StyleSheet", name);
+ }
+
// WizardDefaultWidth
if (!this->WizardDefaultWidth.empty()) {
xout.Element("WizardDefaultWidth", this->WizardDefaultWidth);
@@ -406,9 +431,8 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
// Remote repositories
if (!this->RemoteRepositories.empty()) {
xout.StartElement("RemoteRepositories");
- for (RepositoriesVector::iterator rit = this->RemoteRepositories.begin();
- rit != this->RemoteRepositories.end(); ++rit) {
- (*rit)->WriteRepositoryConfig(xout);
+ for (cmCPackIFWRepository* r : this->RemoteRepositories) {
+ r->WriteRepositoryConfig(xout);
}
xout.EndElement();
}
@@ -423,6 +447,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
@@ -455,9 +483,10 @@ 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 \""
+ cmCPackIFWLogger(WARNING,
+ "Can't copy resources from \""
<< this->Resources[i]
<< "\". Resource will be skipped." << std::endl);
}
@@ -492,9 +521,8 @@ void cmCPackIFWInstaller::GeneratePackageFiles()
}
// Generate packages meta information
- for (PackagesMap::iterator pit = this->Packages.begin();
- pit != this->Packages.end(); ++pit) {
- cmCPackIFWPackage* package = pit->second;
+ for (auto& p : this->Packages) {
+ cmCPackIFWPackage* package = p.second;
package->GeneratePackageFile();
}
}
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.h b/Source/CPack/IFW/cmCPackIFWInstaller.h
index b635f4222..8b3f96af8 100644
--- a/Source/CPack/IFW/cmCPackIFWInstaller.h
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.h
@@ -5,12 +5,12 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmCPackIFWCommon.h"
-
#include <map>
#include <string>
#include <vector>
+#include "cmCPackIFWCommon.h"
+
class cmCPackIFWPackage;
class cmCPackIFWRepository;
@@ -22,8 +22,8 @@ class cmCPackIFWInstaller : public cmCPackIFWCommon
public:
// Types
- typedef std::map<std::string, cmCPackIFWPackage*> PackagesMap;
- typedef std::vector<cmCPackIFWRepository*> RepositoriesVector;
+ using PackagesMap = std::map<std::string, cmCPackIFWPackage*>;
+ using RepositoriesVector = std::vector<cmCPackIFWRepository*>;
public:
// Constructor
@@ -72,6 +72,9 @@ public:
/// Wizard style name
std::string WizardStyle;
+ /// Filename for a style sheet
+ std::string StyleSheet;
+
/// Wizard width
std::string WizardDefaultWidth;
@@ -99,6 +102,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/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx
index c5311c31c..9a9cd5678 100644
--- a/Source/CPack/IFW/cmCPackIFWPackage.cxx
+++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx
@@ -2,21 +2,22 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackIFWPackage.h"
+#include <cstddef>
+#include <map>
+#include <sstream>
+#include <utility>
+
#include "cmCPackComponentGroup.h"
#include "cmCPackIFWCommon.h"
#include "cmCPackIFWGenerator.h"
#include "cmCPackIFWInstaller.h"
#include "cmCPackLog.h" // IWYU pragma: keep
#include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTimestamp.h"
#include "cmXMLWriter.h"
-#include <map>
-#include <sstream>
-#include <stddef.h>
-#include <utility>
-
//---------------------------------------------------------- CompareStruct ---
cmCPackIFWPackage::CompareStruct::CompareStruct()
: Type(cmCPackIFWPackage::CompareNone)
@@ -24,9 +25,7 @@ cmCPackIFWPackage::CompareStruct::CompareStruct()
}
//------------------------------------------------------- DependenceStruct ---
-cmCPackIFWPackage::DependenceStruct::DependenceStruct()
-{
-}
+cmCPackIFWPackage::DependenceStruct::DependenceStruct() = default;
cmCPackIFWPackage::DependenceStruct::DependenceStruct(
const std::string& dependence)
@@ -92,7 +91,7 @@ std::string cmCPackIFWPackage::DependenceStruct::NameWithCompare() const
//------------------------------------------------------ cmCPackIFWPackage ---
cmCPackIFWPackage::cmCPackIFWPackage()
- : Installer(CM_NULLPTR)
+ : Installer(nullptr)
{
}
@@ -111,25 +110,25 @@ void cmCPackIFWPackage::DefaultConfiguration()
{
this->DisplayName.clear();
this->Description.clear();
- this->Version = "";
- this->ReleaseDate = "";
- this->Script = "";
+ this->Version.clear();
+ this->ReleaseDate.clear();
+ this->Script.clear();
this->Licenses.clear();
this->UserInterfaces.clear();
this->Translations.clear();
- this->SortingPriority = "";
- this->UpdateText = "";
- this->Default = "";
- this->Essential = "";
- this->Virtual = "";
- this->ForcedInstallation = "";
- this->RequiresAdminRights = "";
+ this->SortingPriority.clear();
+ this->UpdateText.clear();
+ this->Default.clear();
+ this->Essential.clear();
+ this->Virtual.clear();
+ this->ForcedInstallation.clear();
+ this->RequiresAdminRights.clear();
}
-// Defaul configuration (all in one package)
+// Default configuration (all in one package)
int cmCPackIFWPackage::ConfigureFromOptions()
{
- // Restore defaul configuration
+ // Restore default configuration
this->DefaultConfiguration();
// Name
@@ -168,7 +167,7 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component)
return 0;
}
- // Restore defaul configuration
+ // Restore default configuration
this->DefaultConfiguration();
std::string prefix = "CPACK_IFW_COMPONENT_" +
@@ -198,22 +197,20 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component)
// User interfaces
if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) {
this->UserInterfaces.clear();
- cmSystemTools::ExpandListArgument(option, this->UserInterfaces);
+ cmExpandList(option, this->UserInterfaces);
}
// CMake dependencies
if (!component->Dependencies.empty()) {
- std::vector<cmCPackComponent*>::iterator dit;
- for (dit = component->Dependencies.begin();
- dit != component->Dependencies.end(); ++dit) {
- this->Dependencies.insert(this->Generator->ComponentPackages[*dit]);
+ for (cmCPackComponent* dep : component->Dependencies) {
+ this->Dependencies.insert(this->Generator->ComponentPackages[dep]);
}
}
// Licenses
if (const char* option = this->GetOption(prefix + "LICENSES")) {
this->Licenses.clear();
- cmSystemTools::ExpandListArgument(option, this->Licenses);
+ cmExpandList(option, this->Licenses);
if (this->Licenses.size() % 2 != 0) {
cmCPackIFWLogger(
WARNING,
@@ -228,7 +225,8 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component)
if (const char* option = this->GetOption(prefix + "PRIORITY")) {
this->SortingPriority = option;
cmCPackIFWLogger(
- WARNING, "The \"PRIORITY\" option is set "
+ WARNING,
+ "The \"PRIORITY\" option is set "
<< "for component \"" << component->Name << "\", but there option is "
<< "deprecated. Please use \"SORTING_PRIORITY\" option instead."
<< std::endl);
@@ -257,7 +255,7 @@ int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group)
return 0;
}
- // Restore defaul configuration
+ // Restore default configuration
this->DefaultConfiguration();
std::string prefix = "CPACK_IFW_COMPONENT_GROUP_" +
@@ -284,13 +282,13 @@ int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group)
// User interfaces
if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) {
this->UserInterfaces.clear();
- cmSystemTools::ExpandListArgument(option, this->UserInterfaces);
+ cmExpandList(option, this->UserInterfaces);
}
// Licenses
if (const char* option = this->GetOption(prefix + "LICENSES")) {
this->Licenses.clear();
- cmSystemTools::ExpandListArgument(option, this->Licenses);
+ cmExpandList(option, this->Licenses);
if (this->Licenses.size() % 2 != 0) {
cmCPackIFWLogger(
WARNING,
@@ -305,7 +303,8 @@ int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group)
if (const char* option = this->GetOption(prefix + "PRIORITY")) {
this->SortingPriority = option;
cmCPackIFWLogger(
- WARNING, "The \"PRIORITY\" option is set "
+ WARNING,
+ "The \"PRIORITY\" option is set "
<< "for component group \"" << group->Name
<< "\", but there option is "
<< "deprecated. Please use \"SORTING_PRIORITY\" option instead."
@@ -359,7 +358,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
if (this->IsSetToEmpty(option)) {
this->DisplayName.clear();
} else if (const char* value = this->GetOption(option)) {
- this->ExpandListArgument(value, this->DisplayName);
+ cmCPackIFWPackage::ExpandListArgument(value, this->DisplayName);
}
// Description
@@ -367,7 +366,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
if (this->IsSetToEmpty(option)) {
this->Description.clear();
} else if (const char* value = this->GetOption(option)) {
- this->ExpandListArgument(value, this->Description);
+ cmCPackIFWPackage::ExpandListArgument(value, this->Description);
}
// Release date
@@ -400,22 +399,21 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
this->Translations.clear();
} else if (const char* value = this->GetOption(option)) {
this->Translations.clear();
- cmSystemTools::ExpandListArgument(value, this->Translations);
+ cmExpandList(value, this->Translations);
}
// QtIFW dependencies
std::vector<std::string> deps;
option = prefix + "DEPENDS";
if (const char* value = this->GetOption(option)) {
- cmSystemTools::ExpandListArgument(value, deps);
+ cmExpandList(value, deps);
}
option = prefix + "DEPENDENCIES";
if (const char* value = this->GetOption(option)) {
- cmSystemTools::ExpandListArgument(value, deps);
+ cmExpandList(value, deps);
}
- for (std::vector<std::string>::iterator dit = deps.begin();
- dit != deps.end(); ++dit) {
- DependenceStruct dep(*dit);
+ for (std::string const& d : deps) {
+ DependenceStruct dep(d);
if (this->Generator->Packages.count(dep.Name)) {
cmCPackIFWPackage& depPkg = this->Generator->Packages[dep.Name];
dep.Name = depPkg.Name;
@@ -433,11 +431,9 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
if (this->IsSetToEmpty(option)) {
this->AlienAutoDependOn.clear();
} else if (const char* value = this->GetOption(option)) {
- std::vector<std::string> depsOn;
- cmSystemTools::ExpandListArgument(value, depsOn);
- for (std::vector<std::string>::iterator dit = depsOn.begin();
- dit != depsOn.end(); ++dit) {
- DependenceStruct dep(*dit);
+ std::vector<std::string> depsOn = cmExpandedList(value);
+ for (std::string const& d : depsOn) {
+ DependenceStruct dep(d);
if (this->Generator->Packages.count(dep.Name)) {
cmCPackIFWPackage& depPkg = this->Generator->Packages[dep.Name];
dep.Name = depPkg.Name;
@@ -486,6 +482,15 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
this->ForcedInstallation = "false";
}
+ // Replaces
+ option = prefix + "REPLACES";
+ if (this->IsSetToEmpty(option)) {
+ this->Replaces.clear();
+ } else if (const char* value = this->GetOption(option)) {
+ this->Replaces.clear();
+ cmExpandList(value, this->Replaces);
+ }
+
// Requires admin rights
option = prefix + "REQUIRES_ADMIN_RIGHTS";
if (this->IsSetToEmpty(option)) {
@@ -496,6 +501,16 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
this->RequiresAdminRights = "false";
}
+ // Checkable
+ option = prefix + "CHECKABLE";
+ if (this->IsSetToEmpty(option)) {
+ this->Checkable.clear();
+ } else if (this->IsOn(option)) {
+ this->Checkable = "true";
+ } else if (this->IsSetToOff(option)) {
+ this->Checkable = "false";
+ }
+
return 1;
}
@@ -511,7 +526,7 @@ void cmCPackIFWPackage::GeneratePackageFile()
}
// Output stream
- cmGeneratedFileStream fout((this->Directory + "/meta/package.xml").data());
+ cmGeneratedFileStream fout(this->Directory + "/meta/package.xml");
cmXMLWriter xout(fout);
xout.StartDocument();
@@ -521,26 +536,22 @@ void cmCPackIFWPackage::GeneratePackageFile()
xout.StartElement("Package");
// DisplayName (with translations)
- for (std::map<std::string, std::string>::iterator it =
- this->DisplayName.begin();
- it != this->DisplayName.end(); ++it) {
+ for (auto const& dn : this->DisplayName) {
xout.StartElement("DisplayName");
- if (!it->first.empty()) {
- xout.Attribute("xml:lang", it->first);
+ if (!dn.first.empty()) {
+ xout.Attribute("xml:lang", dn.first);
}
- xout.Content(it->second);
+ xout.Content(dn.second);
xout.EndElement();
}
// Description (with translations)
- for (std::map<std::string, std::string>::iterator it =
- this->Description.begin();
- it != this->Description.end(); ++it) {
+ for (auto const& d : this->Description) {
xout.StartElement("Description");
- if (!it->first.empty()) {
- xout.Attribute("xml:lang", it->first);
+ if (!d.first.empty()) {
+ xout.Attribute("xml:lang", d.first);
}
- xout.Content(it->second);
+ xout.Content(d.second);
xout.EndElement();
}
@@ -568,51 +579,48 @@ void cmCPackIFWPackage::GeneratePackageFile()
// User Interfaces (copy to meta dir)
std::vector<std::string> userInterfaces = UserInterfaces;
- for (size_t i = 0; i < userInterfaces.size(); i++) {
- std::string name = cmSystemTools::GetFilenameName(userInterfaces[i]);
+ for (std::string& userInterface : userInterfaces) {
+ std::string name = cmSystemTools::GetFilenameName(userInterface);
std::string path = this->Directory + "/meta/" + name;
- cmsys::SystemTools::CopyFileIfDifferent(userInterfaces[i], path);
- userInterfaces[i] = name;
+ cmsys::SystemTools::CopyFileIfDifferent(userInterface, path);
+ userInterface = name;
}
if (!userInterfaces.empty()) {
xout.StartElement("UserInterfaces");
- for (size_t i = 0; i < userInterfaces.size(); i++) {
- xout.Element("UserInterface", userInterfaces[i]);
+ for (std::string const& userInterface : userInterfaces) {
+ xout.Element("UserInterface", userInterface);
}
xout.EndElement();
}
// Translations (copy to meta dir)
std::vector<std::string> translations = Translations;
- for (size_t i = 0; i < translations.size(); i++) {
- std::string name = cmSystemTools::GetFilenameName(translations[i]);
+ for (std::string& translation : translations) {
+ std::string name = cmSystemTools::GetFilenameName(translation);
std::string path = this->Directory + "/meta/" + name;
- cmsys::SystemTools::CopyFileIfDifferent(translations[i], path);
- translations[i] = name;
+ cmsys::SystemTools::CopyFileIfDifferent(translation, path);
+ translation = name;
}
if (!translations.empty()) {
xout.StartElement("Translations");
- for (size_t i = 0; i < translations.size(); i++) {
- xout.Element("Translation", translations[i]);
+ for (std::string const& translation : translations) {
+ xout.Element("Translation", translation);
}
xout.EndElement();
}
// Dependencies
std::set<DependenceStruct> compDepSet;
- for (std::set<DependenceStruct*>::iterator ait =
- this->AlienDependencies.begin();
- ait != this->AlienDependencies.end(); ++ait) {
- compDepSet.insert(*(*ait));
+ for (DependenceStruct* ad : this->AlienDependencies) {
+ compDepSet.insert(*ad);
}
- for (std::set<cmCPackIFWPackage*>::iterator it = this->Dependencies.begin();
- it != this->Dependencies.end(); ++it) {
- compDepSet.insert(DependenceStruct((*it)->Name));
+ for (cmCPackIFWPackage* d : this->Dependencies) {
+ compDepSet.insert(DependenceStruct(d->Name));
}
// Write dependencies
if (!compDepSet.empty()) {
std::ostringstream dependencies;
- std::set<DependenceStruct>::iterator it = compDepSet.begin();
+ auto it = compDepSet.begin();
dependencies << it->NameWithCompare();
++it;
while (it != compDepSet.end()) {
@@ -624,15 +632,13 @@ void cmCPackIFWPackage::GeneratePackageFile()
// Automatic dependency on
std::set<DependenceStruct> compAutoDepSet;
- for (std::set<DependenceStruct*>::iterator ait =
- this->AlienAutoDependOn.begin();
- ait != this->AlienAutoDependOn.end(); ++ait) {
- compAutoDepSet.insert(*(*ait));
+ for (DependenceStruct* aad : this->AlienAutoDependOn) {
+ compAutoDepSet.insert(*aad);
}
// Write automatic dependency on
if (!compAutoDepSet.empty()) {
std::ostringstream dependencies;
- std::set<DependenceStruct>::iterator it = compAutoDepSet.begin();
+ auto it = compAutoDepSet.begin();
dependencies << it->NameWithCompare();
++it;
while (it != compAutoDepSet.end()) {
@@ -665,6 +671,19 @@ void cmCPackIFWPackage::GeneratePackageFile()
xout.Element("ForcedInstallation", this->ForcedInstallation);
}
+ // Replaces
+ if (!this->Replaces.empty()) {
+ std::ostringstream replaces;
+ auto it = this->Replaces.begin();
+ replaces << *it;
+ ++it;
+ while (it != this->Replaces.end()) {
+ replaces << "," << *it;
+ ++it;
+ }
+ xout.Element("Replaces", replaces.str());
+ }
+
if (!this->RequiresAdminRights.empty()) {
xout.Element("RequiresAdminRights", this->RequiresAdminRights);
}
@@ -685,6 +704,11 @@ void cmCPackIFWPackage::GeneratePackageFile()
xout.Element("SortingPriority", this->SortingPriority);
}
+ // Checkable
+ if (!this->Checkable.empty()) {
+ xout.Element("Checkable", this->Checkable);
+ }
+
xout.EndElement();
xout.EndDocument();
}
diff --git a/Source/CPack/IFW/cmCPackIFWPackage.h b/Source/CPack/IFW/cmCPackIFWPackage.h
index cec59b03c..6a4a170a5 100644
--- a/Source/CPack/IFW/cmCPackIFWPackage.h
+++ b/Source/CPack/IFW/cmCPackIFWPackage.h
@@ -5,13 +5,13 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmCPackIFWCommon.h"
-
#include <map>
#include <set>
#include <string>
#include <vector>
+#include "cmCPackIFWCommon.h"
+
class cmCPackComponent;
class cmCPackComponentGroup;
class cmCPackIFWInstaller;
@@ -114,9 +114,15 @@ public:
/// Determines that the package must always be installed
std::string ForcedInstallation;
+ /// List of components to replace
+ std::vector<std::string> Replaces;
+
/// Package needs to be installed with elevated permissions
std::string RequiresAdminRights;
+ /// Set to false if you want to hide the checkbox for an item
+ std::string Checkable;
+
public:
// Internal implementation
diff --git a/Source/CPack/IFW/cmCPackIFWRepository.cxx b/Source/CPack/IFW/cmCPackIFWRepository.cxx
index b115db057..a6965491e 100644
--- a/Source/CPack/IFW/cmCPackIFWRepository.cxx
+++ b/Source/CPack/IFW/cmCPackIFWRepository.cxx
@@ -2,14 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackIFWRepository.h"
+#include <cstddef>
+
#include "cmCPackIFWGenerator.h"
#include "cmGeneratedFileStream.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
#include "cmXMLWriter.h"
-#include <stddef.h>
-
cmCPackIFWRepository::cmCPackIFWRepository()
: Update(cmCPackIFWRepository::None)
{
@@ -62,49 +62,49 @@ bool cmCPackIFWRepository::ConfigureFromOptions()
if (const char* url = this->GetOption(prefix + "URL")) {
this->Url = url;
} else {
- this->Url = "";
+ this->Url.clear();
}
// Old url
if (const char* oldUrl = this->GetOption(prefix + "OLD_URL")) {
this->OldUrl = oldUrl;
} else {
- this->OldUrl = "";
+ this->OldUrl.clear();
}
// New url
if (const char* newUrl = this->GetOption(prefix + "NEW_URL")) {
this->NewUrl = newUrl;
} else {
- this->NewUrl = "";
+ this->NewUrl.clear();
}
// Enabled
if (this->IsOn(prefix + "DISABLED")) {
this->Enabled = "0";
} else {
- this->Enabled = "";
+ this->Enabled.clear();
}
// Username
if (const char* username = this->GetOption(prefix + "USERNAME")) {
this->Username = username;
} else {
- this->Username = "";
+ this->Username.clear();
}
// Password
if (const char* password = this->GetOption(prefix + "PASSWORD")) {
this->Password = password;
} else {
- this->Password = "";
+ this->Password.clear();
}
// DisplayName
if (const char* displayName = this->GetOption(prefix + "DISPLAY_NAME")) {
this->DisplayName = displayName;
} else {
- this->DisplayName = "";
+ this->DisplayName.clear();
}
return this->IsValid();
@@ -128,7 +128,7 @@ public:
bool patched;
protected:
- void StartElement(const std::string& name, const char** atts) CM_OVERRIDE
+ void StartElement(const std::string& name, const char** atts) override
{
this->xout.StartElement(name);
this->StartFragment(atts);
@@ -143,7 +143,7 @@ protected:
}
}
- void EndElement(const std::string& name) CM_OVERRIDE
+ void EndElement(const std::string& name) override
{
if (name == "Updates" && !this->patched) {
this->repository->WriteRepositoryUpdates(this->xout);
@@ -159,10 +159,10 @@ protected:
}
}
- void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
+ void CharacterDataHandler(const char* data, int length) override
{
std::string content(data, data + length);
- if (content == "" || content == " " || content == " " ||
+ if (content.empty() || content == " " || content == " " ||
content == "\n") {
return;
}
@@ -183,7 +183,7 @@ bool cmCPackIFWRepository::PatchUpdatesXml()
this->Directory + "/repository/UpdatesPatch.xml";
// Output stream
- cmGeneratedFileStream fout(updatesPatchXml.data());
+ cmGeneratedFileStream fout(updatesPatchXml);
cmXMLWriter xout(fout);
xout.StartDocument();
@@ -200,7 +200,7 @@ bool cmCPackIFWRepository::PatchUpdatesXml()
fout.Close();
- return cmSystemTools::RenameFile(updatesPatchXml.data(), updatesXml.data());
+ return cmSystemTools::RenameFile(updatesPatchXml, updatesXml);
}
void cmCPackIFWRepository::WriteRepositoryConfig(cmXMLWriter& xout)
@@ -279,9 +279,8 @@ void cmCPackIFWRepository::WriteRepositoryUpdates(cmXMLWriter& xout)
{
if (!this->RepositoryUpdate.empty()) {
xout.StartElement("RepositoryUpdate");
- for (RepositoriesVector::iterator rit = this->RepositoryUpdate.begin();
- rit != this->RepositoryUpdate.end(); ++rit) {
- (*rit)->WriteRepositoryUpdate(xout);
+ for (cmCPackIFWRepository* r : this->RepositoryUpdate) {
+ r->WriteRepositoryUpdate(xout);
}
xout.EndElement();
}
diff --git a/Source/CPack/IFW/cmCPackIFWRepository.h b/Source/CPack/IFW/cmCPackIFWRepository.h
index 227cfae7a..c29398124 100644
--- a/Source/CPack/IFW/cmCPackIFWRepository.h
+++ b/Source/CPack/IFW/cmCPackIFWRepository.h
@@ -5,11 +5,11 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmCPackIFWCommon.h"
-
#include <string>
#include <vector>
+#include "cmCPackIFWCommon.h"
+
class cmXMLWriter;
/** \class cmCPackIFWRepository
@@ -28,7 +28,7 @@ public:
Replace
};
- typedef std::vector<cmCPackIFWRepository*> RepositoriesVector;
+ using RepositoriesVector = std::vector<cmCPackIFWRepository*>;
public:
// Constructor
diff --git a/Source/CPack/OSXScriptLauncher.cxx b/Source/CPack/OSXScriptLauncher.cxx
index b48bf1214..21d27a02d 100644
--- a/Source/CPack/OSXScriptLauncher.cxx
+++ b/Source/CPack/OSXScriptLauncher.cxx
@@ -1,15 +1,16 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmsys/FStream.hxx"
-#include "cmsys/Process.h"
-#include "cmsys/SystemTools.hxx"
+#include <cstddef>
#include <iostream>
-#include <stddef.h>
#include <string>
#include <vector>
#include <CoreFoundation/CoreFoundation.h>
+#include "cmsys/FStream.hxx"
+#include "cmsys/Process.h"
+#include "cmsys/SystemTools.hxx"
+
// For the PATH_MAX constant
#include <sys/syslimits.h>
@@ -34,7 +35,7 @@ int main(int argc, char* argv[])
}
fileName = CFSTR("RuntimeScript");
if (!(scriptFileURL =
- CFBundleCopyResourceURL(appBundle, fileName, NULL, NULL))) {
+ CFBundleCopyResourceURL(appBundle, fileName, nullptr, nullptr))) {
DebugError("CFBundleCopyResourceURL failed");
return 1;
}
@@ -46,8 +47,7 @@ int main(int argc, char* argv[])
// get the file system path of the url as a cstring
// in an encoding suitable for posix apis
- if (CFURLGetFileSystemRepresentation(scriptFileURL, true, path, PATH_MAX) ==
- false) {
+ if (!CFURLGetFileSystemRepresentation(scriptFileURL, true, path, PATH_MAX)) {
DebugError("CFURLGetFileSystemRepresentation failed");
return 1;
}
@@ -71,10 +71,10 @@ int main(int argc, char* argv[])
for (cc = 1; cc < argc; ++cc) {
args.push_back(argv[cc]);
}
- args.push_back(0);
+ args.push_back(nullptr);
cmsysProcess* cp = cmsysProcess_New();
- cmsysProcess_SetCommand(cp, &*args.begin());
+ cmsysProcess_SetCommand(cp, args.data());
cmsysProcess_SetWorkingDirectory(cp, scriptDirectory.c_str());
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
cmsysProcess_SetTimeout(cp, 0);
@@ -83,7 +83,7 @@ int main(int argc, char* argv[])
std::vector<char> tempOutput;
char* data;
int length;
- while (cmsysProcess_WaitForData(cp, &data, &length, 0)) {
+ while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) {
// Translate NULL characters in the output into valid text.
for (int i = 0; i < length; ++i) {
if (data[i] == '\0') {
@@ -93,7 +93,7 @@ int main(int argc, char* argv[])
std::cout.write(data, length);
}
- cmsysProcess_WaitForExit(cp, 0);
+ cmsysProcess_WaitForExit(cp, nullptr);
bool result = true;
if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) {
diff --git a/Source/CPack/WiX/cmCMakeToWixPath.cxx b/Source/CPack/WiX/cmCMakeToWixPath.cxx
new file mode 100644
index 000000000..87385011a
--- /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 <string>
+#include <vector>
+
+#include "cmStringAlgorithms.h"
+
+#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 cmTrimWhitespace(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 274dfd0ce..e71a38fd2 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -2,27 +2,37 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackWIXGenerator.h"
+#include <algorithm>
+
+#include <cm/string_view>
+
+#include "cmsys/Directory.hxx"
+#include "cmsys/Encoding.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/SystemTools.hxx"
+
+#include "cmAlgorithms.h"
#include "cmCPackComponentGroup.h"
#include "cmCPackLog.h"
#include "cmCryptoHash.h"
#include "cmGeneratedFileStream.h"
#include "cmInstalledFile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmUuid.h"
-#include <algorithm>
-
#include "cmWIXDirectoriesSourceWriter.h"
#include "cmWIXFeaturesSourceWriter.h"
#include "cmWIXFilesSourceWriter.h"
#include "cmWIXRichTextFormatWriter.h"
#include "cmWIXSourceWriter.h"
-#include "cmsys/Directory.hxx"
-#include "cmsys/Encoding.hxx"
-#include "cmsys/FStream.hxx"
-#include "cmsys/SystemTools.hxx"
+#ifdef _WIN32
+# include <rpc.h> // for GUID generation (windows only)
+#else
+# include <uuid/uuid.h> // for GUID generation (libuuid)
+#endif
-#include <rpc.h> // for GUID generation
+#include "cmCMakeToWixPath.h"
cmCPackWIXGenerator::cmCPackWIXGenerator()
: Patch(0)
@@ -49,15 +59,14 @@ bool cmCPackWIXGenerator::RunWiXCommand(std::string const& command)
{
std::string logFileName = this->CPackTopLevel + "/wix.log";
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Running WiX command: " << command
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Running WiX command: " << command << std::endl);
std::string output;
int returnValue = 0;
- bool status = cmSystemTools::RunSingleCommand(command.c_str(), &output,
- &output, &returnValue, 0,
- cmSystemTools::OUTPUT_NONE);
+ bool status = cmSystemTools::RunSingleCommand(
+ command, &output, &output, &returnValue, 0, cmSystemTools::OUTPUT_NONE);
cmsys::ofstream logFile(logFileName.c_str(), std::ios::app);
logFile << command << std::endl;
@@ -65,8 +74,9 @@ bool cmCPackWIXGenerator::RunWiXCommand(std::string const& command)
logFile.close();
if (!status || returnValue) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running WiX candle. "
- "Please check '"
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running WiX candle. "
+ "Please check '"
<< logFileName << "' for errors." << std::endl);
return false;
@@ -89,9 +99,12 @@ bool cmCPackWIXGenerator::RunCandleCommand(std::string const& sourceFile,
command << " -arch " << GetArchitecture();
command << " -out " << QuotePath(objectFile);
- for (extension_set_t::const_iterator i = CandleExtensions.begin();
- i != CandleExtensions.end(); ++i) {
- command << " -ext " << QuotePath(*i);
+ for (std::string const& ext : CandleExtensions) {
+ command << " -ext " << QuotePath(ext);
+ }
+
+ if (sourceFile.rfind(this->CPackTopLevel, 0) != 0) {
+ command << " " << QuotePath("-I" + this->CPackTopLevel);
}
AddCustomFlags("CPACK_WIX_CANDLE_EXTRA_FLAGS", command);
@@ -111,11 +124,10 @@ 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 (extension_set_t::const_iterator i = this->LightExtensions.begin();
- i != this->LightExtensions.end(); ++i) {
- command << " -ext " << QuotePath(*i);
+ for (std::string const& ext : this->LightExtensions) {
+ command << " -ext " << QuotePath(ext);
}
const char* const cultures = GetOption("CPACK_WIX_CULTURES");
@@ -133,8 +145,8 @@ bool cmCPackWIXGenerator::RunLightCommand(std::string const& objectFiles)
int cmCPackWIXGenerator::PackageFiles()
{
if (!PackageFilesImpl() || cmSystemTools::GetErrorOccuredFlag()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Fatal WiX Generator Error"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Fatal WiX Generator Error" << std::endl);
return false;
}
@@ -143,9 +155,9 @@ int cmCPackWIXGenerator::PackageFiles()
bool cmCPackWIXGenerator::InitializeWiXConfiguration()
{
- if (!ReadListFile("CPackWIX.cmake")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while executing CPackWIX.cmake"
- << std::endl);
+ if (!ReadListFile("Internal/CPack/CPackWIX.cmake")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while executing CPackWIX.cmake" << std::endl);
return false;
}
@@ -162,12 +174,13 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration()
std::string guid = GenerateGUID();
SetOption("CPACK_WIX_UPGRADE_GUID", guid.c_str());
- cmCPackLogger(
- cmCPackLog::LOG_WARNING, "CPACK_WIX_UPGRADE_GUID implicitly set to "
- << guid << " . "
- "Please refer to the documentation on how and why "
- "you might want to set this explicitly."
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_WARNING,
+ "CPACK_WIX_UPGRADE_GUID implicitly set to "
+ << guid
+ << " . "
+ "Please refer to the documentation on how and why "
+ "you might want to set this explicitly."
+ << std::endl);
}
if (!RequireOption("CPACK_TOPLEVEL_DIRECTORY", this->CPackTopLevel)) {
@@ -216,11 +229,10 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration()
const char* patchFilePath = GetOption("CPACK_WIX_PATCH_FILE");
if (patchFilePath) {
- std::vector<std::string> patchFilePaths;
- cmSystemTools::ExpandListArgument(patchFilePath, patchFilePaths);
+ std::vector<std::string> patchFilePaths = cmExpandedList(patchFilePath);
- for (size_t i = 0; i < patchFilePaths.size(); ++i) {
- if (!this->Patch->LoadFragments(patchFilePaths[i])) {
+ for (std::string const& p : patchFilePaths) {
+ if (!this->Patch->LoadFragments(p)) {
return false;
}
}
@@ -228,7 +240,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration()
// if install folder is supposed to be set absolutely, the default
// component guid "*" cannot be used
- if (cmSystemTools::IsOn(GetOption("CPACK_WIX_SKIP_PROGRAM_FOLDER"))) {
+ if (cmIsOn(GetOption("CPACK_WIX_SKIP_PROGRAM_FOLDER"))) {
this->ComponentGuidType = cmWIXSourceWriter::CMAKE_GENERATED_GUID;
}
@@ -254,9 +266,7 @@ bool cmCPackWIXGenerator::PackageFilesImpl()
std::set<std::string> usedBaseNames;
std::ostringstream objectFiles;
- for (size_t i = 0; i < this->WixSources.size(); ++i) {
- std::string const& sourceFilename = this->WixSources[i];
-
+ for (std::string const& sourceFilename : this->WixSources) {
std::string baseName =
cmSystemTools::GetFilenameWithoutLastExtension(sourceFilename);
@@ -274,11 +284,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);
@@ -292,7 +303,7 @@ void cmCPackWIXGenerator::AppendUserSuppliedExtraSources()
if (!cpackWixExtraSources)
return;
- cmSystemTools::ExpandListArgument(cpackWixExtraSources, this->WixSources);
+ cmExpandList(cpackWixExtraSources, this->WixSources);
}
void cmCPackWIXGenerator::AppendUserSuppliedExtraObjects(std::ostream& stream)
@@ -301,13 +312,11 @@ void cmCPackWIXGenerator::AppendUserSuppliedExtraObjects(std::ostream& stream)
if (!cpackWixExtraObjects)
return;
- std::vector<std::string> expandedExtraObjects;
+ std::vector<std::string> expandedExtraObjects =
+ cmExpandedList(cpackWixExtraObjects);
- cmSystemTools::ExpandListArgument(cpackWixExtraObjects,
- expandedExtraObjects);
-
- for (size_t i = 0; i < expandedExtraObjects.size(); ++i) {
- stream << " " << QuotePath(expandedExtraObjects[i]);
+ for (std::string const& obj : expandedExtraObjects) {
+ stream << " " << QuotePath(obj);
}
}
@@ -324,10 +333,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");
@@ -345,9 +354,7 @@ void cmCPackWIXGenerator::CreateWiXPropertiesIncludeFile()
std::string prefix = "CPACK_WIX_PROPERTY_";
std::vector<std::string> options = GetOptions();
- for (size_t i = 0; i < options.size(); ++i) {
- std::string const& name = options[i];
-
+ for (std::string const& name : options) {
if (name.length() > prefix.length() &&
name.substr(0, prefix.length()) == prefix) {
std::string id = name.substr(prefix.length());
@@ -369,8 +376,9 @@ void cmCPackWIXGenerator::CreateWiXPropertiesIncludeFile()
includeFile.AddAttribute("Id", "FindInstallLocation");
includeFile.AddAttribute("Root", "HKLM");
includeFile.AddAttribute(
- "Key", "Software\\Microsoft\\Windows\\"
- "CurrentVersion\\Uninstall\\[WIX_UPGRADE_DETECTED]");
+ "Key",
+ "Software\\Microsoft\\Windows\\"
+ "CurrentVersion\\Uninstall\\[WIX_UPGRADE_DETECTED]");
includeFile.AddAttribute("Name", "InstallLocation");
includeFile.AddAttribute("Type", "raw");
includeFile.EndElement("RegistrySearch");
@@ -396,11 +404,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);
+ }
}
}
@@ -503,16 +516,12 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
globalShortcuts.AddShortcutTypes(emittedShortcutTypes);
} else {
- for (std::map<std::string, cmCPackComponent>::const_iterator i =
- this->Components.begin();
- i != this->Components.end(); ++i) {
- cmCPackComponent const& component = i->second;
+ for (auto const& i : this->Components) {
+ cmCPackComponent const& component = i.second;
- std::string componentPath = toplevel;
- componentPath += "/";
- componentPath += component.Name;
+ std::string componentPath = cmStrCat(toplevel, '/', component.Name);
- std::string componentFeatureId = "CM_C_" + component.Name;
+ std::string const componentFeatureId = "CM_C_" + component.Name;
cmWIXShortcuts featureShortcuts;
AddComponentsToFeature(componentPath, componentFeatureId,
@@ -529,9 +538,16 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
}
}
- bool emitUninstallShortcut =
- emittedShortcutTypes.find(cmWIXShortcuts::START_MENU) !=
- emittedShortcutTypes.end();
+ bool emitUninstallShortcut = true;
+ const char* cpackWixProgramMenuFolder =
+ GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER");
+ if (cpackWixProgramMenuFolder &&
+ cm::string_view(cpackWixProgramMenuFolder) == ".") {
+ emitUninstallShortcut = false;
+ } else if (emittedShortcutTypes.find(cmWIXShortcuts::START_MENU) ==
+ emittedShortcutTypes.end()) {
+ emitUninstallShortcut = false;
+ }
if (!CreateShortcuts(std::string(), "ProductFeature", globalShortcuts,
emitUninstallShortcut, fileDefinitions,
@@ -572,7 +588,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
std::string cmCPackWIXGenerator::GetRootFolderId() const
{
- if (cmSystemTools::IsOn(GetOption("CPACK_WIX_SKIP_PROGRAM_FOLDER"))) {
+ if (cmIsOn(GetOption("CPACK_WIX_SKIP_PROGRAM_FOLDER"))) {
return "";
}
@@ -608,9 +624,10 @@ bool cmCPackWIXGenerator::GenerateMainSourceFileFromTemplate()
std::string mainSourceFilePath = this->CPackTopLevel + "/main.wxs";
- if (!ConfigureFile(wixTemplate.c_str(), mainSourceFilePath.c_str())) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Failed creating '"
- << mainSourceFilePath << "'' from template." << std::endl);
+ if (!ConfigureFile(wixTemplate, mainSourceFilePath)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed creating '" << mainSourceFilePath
+ << "'' from template." << std::endl);
return false;
}
@@ -623,19 +640,15 @@ bool cmCPackWIXGenerator::GenerateMainSourceFileFromTemplate()
bool cmCPackWIXGenerator::CreateFeatureHierarchy(
cmWIXFeaturesSourceWriter& featureDefinitions)
{
- for (std::map<std::string, cmCPackComponentGroup>::const_iterator i =
- ComponentGroups.begin();
- i != ComponentGroups.end(); ++i) {
- cmCPackComponentGroup const& group = i->second;
+ for (auto const& i : ComponentGroups) {
+ cmCPackComponentGroup const& group = i.second;
if (group.ParentGroup == 0) {
featureDefinitions.EmitFeatureForComponentGroup(group, *this->Patch);
}
}
- for (std::map<std::string, cmCPackComponent>::const_iterator i =
- this->Components.begin();
- i != this->Components.end(); ++i) {
- cmCPackComponent const& component = i->second;
+ for (auto const& i : this->Components) {
+ cmCPackComponent const& component = i.second;
if (!component.Group) {
featureDefinitions.EmitFeatureForComponent(component, *this->Patch);
@@ -657,8 +670,7 @@ bool cmCPackWIXGenerator::AddComponentsToFeature(
std::vector<std::string> cpackPackageExecutablesList;
const char* cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES");
if (cpackPackageExecutables) {
- cmSystemTools::ExpandListArgument(cpackPackageExecutables,
- cpackPackageExecutablesList);
+ cmExpandList(cpackPackageExecutables, cpackPackageExecutablesList);
if (cpackPackageExecutablesList.size() % 2 != 0) {
cmCPackLogger(
cmCPackLog::LOG_ERROR,
@@ -673,8 +685,7 @@ bool cmCPackWIXGenerator::AddComponentsToFeature(
const char* cpackPackageDesktopLinks =
GetOption("CPACK_CREATE_DESKTOP_LINKS");
if (cpackPackageDesktopLinks) {
- cmSystemTools::ExpandListArgument(cpackPackageDesktopLinks,
- cpackPackageDesktopLinksList);
+ cmExpandList(cpackPackageDesktopLinks, cpackPackageDesktopLinksList);
}
AddDirectoryAndFileDefinitions(
@@ -730,9 +741,16 @@ bool cmCPackWIXGenerator::CreateShortcutsOfSpecificType(
{
std::string directoryId;
switch (type) {
- case cmWIXShortcuts::START_MENU:
- directoryId = "PROGRAM_MENU_FOLDER";
- break;
+ case cmWIXShortcuts::START_MENU: {
+ const char* cpackWixProgramMenuFolder =
+ GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER");
+ if (cpackWixProgramMenuFolder &&
+ cm::string_view(cpackWixProgramMenuFolder) == ".") {
+ directoryId = "ProgramMenuFolder";
+ } else {
+ directoryId = "PROGRAM_MENU_FOLDER";
+ }
+ } break;
case cmWIXShortcuts::DESKTOP:
directoryId = "DesktopFolder";
break;
@@ -786,8 +804,13 @@ bool cmCPackWIXGenerator::CreateShortcutsOfSpecificType(
fileDefinitions);
if (type == cmWIXShortcuts::START_MENU) {
- fileDefinitions.EmitRemoveFolder("CM_REMOVE_PROGRAM_MENU_FOLDER" +
- idSuffix);
+ const char* cpackWixProgramMenuFolder =
+ GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER");
+ if (cpackWixProgramMenuFolder &&
+ cm::string_view(cpackWixProgramMenuFolder) != ".") {
+ fileDefinitions.EmitRemoveFolder("CM_REMOVE_PROGRAM_MENU_FOLDER" +
+ idSuffix);
+ }
}
if (emitUninstallShortcut) {
@@ -937,9 +960,7 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitions(
shortcut.workingDirectoryId = directoryId;
shortcuts.insert(cmWIXShortcuts::START_MENU, id, shortcut);
- if (!desktopExecutables.empty() &&
- std::find(desktopExecutables.begin(), desktopExecutables.end(),
- executableName) != desktopExecutables.end()) {
+ if (cmContains(desktopExecutables, executableName)) {
shortcuts.insert(cmWIXShortcuts::DESKTOP, id, shortcut);
}
}
@@ -957,8 +978,8 @@ bool cmCPackWIXGenerator::RequireOption(std::string const& name,
return true;
} else {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Required variable "
- << name << " not set" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Required variable " << name << " not set" << std::endl);
return false;
}
@@ -978,6 +999,7 @@ std::string cmCPackWIXGenerator::GetArchitecture() const
std::string cmCPackWIXGenerator::GenerateGUID()
{
+#ifdef _WIN32
UUID guid;
UuidCreate(&guid);
@@ -987,6 +1009,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);
}
@@ -1074,8 +1104,7 @@ std::string cmCPackWIXGenerator::CreateHashedId(
cmCryptoHash sha1(cmCryptoHash::AlgoSHA1);
std::string const hash = sha1.HashString(path);
- std::string identifier;
- identifier += hash.substr(0, 7) + "_";
+ std::string identifier = cmStrCat(cm::string_view(hash).substr(0, 7), '_');
const size_t maxFileNameLength = 52;
if (normalizedFilename.length() > maxFileNameLength) {
@@ -1120,8 +1149,7 @@ void cmCPackWIXGenerator::CollectExtensions(std::string const& variableName,
if (!variableContent)
return;
- std::vector<std::string> list;
- cmSystemTools::ExpandListArgument(variableContent, list);
+ std::vector<std::string> list = cmExpandedList(variableContent);
extensions.insert(list.begin(), list.end());
}
@@ -1132,12 +1160,10 @@ void cmCPackWIXGenerator::AddCustomFlags(std::string const& variableName,
if (!variableContent)
return;
- std::vector<std::string> list;
- cmSystemTools::ExpandListArgument(variableContent, list);
+ std::vector<std::string> list = cmExpandedList(variableContent);
- for (std::vector<std::string>::const_iterator i = list.begin();
- i != list.end(); ++i) {
- stream << " " << QuotePath(*i);
+ for (std::string const& i : list) {
+ stream << " " << QuotePath(i);
}
}
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h
index b2633a7f9..d1933483f 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.h
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.h
@@ -3,14 +3,13 @@
#ifndef cmCPackWIXGenerator_h
#define cmCPackWIXGenerator_h
-#include "cmCPackGenerator.h"
+#include <map>
+#include <string>
+#include "cmCPackGenerator.h"
#include "cmWIXPatch.h"
#include "cmWIXShortcut.h"
-#include <map>
-#include <string>
-
class cmWIXSourceWriter;
class cmWIXDirectoriesSourceWriter;
class cmWIXFilesSourceWriter;
@@ -28,25 +27,31 @@ public:
~cmCPackWIXGenerator();
protected:
- virtual int InitializeInternal();
+ int InitializeInternal() override;
- virtual int PackageFiles();
+ int PackageFiles() override;
- virtual const char* GetOutputExtension() { return ".msi"; }
+ const char* GetOutputExtension() override { return ".msi"; }
- virtual enum CPackSetDestdirSupport SupportsSetDestdir() const
+ enum CPackSetDestdirSupport SupportsSetDestdir() const override
{
return SETDESTDIR_UNSUPPORTED;
}
- virtual bool SupportsAbsoluteDestination() const { return false; }
+ bool SupportsAbsoluteDestination() const override { return false; }
- virtual bool SupportsComponentInstallation() const { return true; }
+ bool SupportsComponentInstallation() const override { return true; }
private:
- typedef std::map<std::string, std::string> id_map_t;
- typedef std::map<std::string, size_t> ambiguity_map_t;
- typedef std::set<std::string> extension_set_t;
+ using id_map_t = std::map<std::string, std::string>;
+ using ambiguity_map_t = std::map<std::string, size_t>;
+ using extension_set_t = std::set<std::string>;
+
+ enum class DefinitionType
+ {
+ STRING,
+ PATH
+ };
bool InitializeWiXConfiguration();
@@ -58,7 +63,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/cmWIXAccessControlList.cxx b/Source/CPack/WiX/cmWIXAccessControlList.cxx
index 744a93298..3668b4613 100644
--- a/Source/CPack/WiX/cmWIXAccessControlList.cxx
+++ b/Source/CPack/WiX/cmWIXAccessControlList.cxx
@@ -3,7 +3,7 @@
#include "cmWIXAccessControlList.h"
#include "cmCPackGenerator.h"
-
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
cmWIXAccessControlList::cmWIXAccessControlList(
@@ -20,8 +20,8 @@ bool cmWIXAccessControlList::Apply()
std::vector<std::string> entries;
this->InstalledFile.GetPropertyAsList("CPACK_WIX_ACL", entries);
- for (size_t i = 0; i < entries.size(); ++i) {
- this->CreatePermissionElement(entries[i]);
+ for (std::string const& entry : entries) {
+ this->CreatePermissionElement(entry);
}
return true;
@@ -48,17 +48,15 @@ void cmWIXAccessControlList::CreatePermissionElement(std::string const& entry)
user = user_and_domain;
}
- std::vector<std::string> permissions =
- cmSystemTools::tokenize(permission_string, ",");
+ std::vector<std::string> permissions = cmTokenize(permission_string, ",");
this->SourceWriter.BeginElement("Permission");
this->SourceWriter.AddAttribute("User", user);
if (!domain.empty()) {
this->SourceWriter.AddAttribute("Domain", domain);
}
- for (size_t i = 0; i < permissions.size(); ++i) {
- this->EmitBooleanAttribute(entry,
- cmSystemTools::TrimWhitespace(permissions[i]));
+ for (std::string const& permission : permissions) {
+ this->EmitBooleanAttribute(entry, cmTrimWhitespace(permission));
}
this->SourceWriter.EndElement("Permission");
}
@@ -66,8 +64,9 @@ void cmWIXAccessControlList::CreatePermissionElement(std::string const& entry)
void cmWIXAccessControlList::ReportError(std::string const& entry,
std::string const& message)
{
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Failed processing ACL entry '"
- << entry << "': " << message << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed processing ACL entry '" << entry << "': " << message
+ << std::endl);
}
bool cmWIXAccessControlList::IsBooleanAttribute(std::string const& name)
diff --git a/Source/CPack/WiX/cmWIXAccessControlList.h b/Source/CPack/WiX/cmWIXAccessControlList.h
index 2a23f2f37..64f9a1382 100644
--- a/Source/CPack/WiX/cmWIXAccessControlList.h
+++ b/Source/CPack/WiX/cmWIXAccessControlList.h
@@ -3,10 +3,9 @@
#ifndef cmWIXAccessControlList_h
#define cmWIXAccessControlList_h
-#include "cmWIXSourceWriter.h"
-
#include "cmCPackLog.h"
#include "cmInstalledFile.h"
+#include "cmWIXSourceWriter.h"
class cmWIXAccessControlList
{
diff --git a/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.cxx b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.cxx
index 975dffb4f..0a83ca2c0 100644
--- a/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.cxx
+++ b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.cxx
@@ -14,10 +14,12 @@ void cmWIXDirectoriesSourceWriter::EmitStartMenuFolder(
BeginElement("Directory");
AddAttribute("Id", "ProgramMenuFolder");
- BeginElement("Directory");
- AddAttribute("Id", "PROGRAM_MENU_FOLDER");
- AddAttribute("Name", startMenuFolder);
- EndElement("Directory");
+ if (startMenuFolder != ".") {
+ BeginElement("Directory");
+ AddAttribute("Id", "PROGRAM_MENU_FOLDER");
+ AddAttribute("Name", startMenuFolder);
+ EndElement("Directory");
+ }
EndElement("Directory");
}
diff --git a/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h
index 8233331a3..a907d6d18 100644
--- a/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h
+++ b/Source/CPack/WiX/cmWIXDirectoriesSourceWriter.h
@@ -3,11 +3,10 @@
#ifndef cmWIXDirectoriesSourceWriter_h
#define cmWIXDirectoriesSourceWriter_h
-#include "cmWIXSourceWriter.h"
+#include <string>
#include "cmCPackGenerator.h"
-
-#include <string>
+#include "cmWIXSourceWriter.h"
/** \class cmWIXDirectoriesSourceWriter
* \brief Helper class to generate directories.wxs
diff --git a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx
index 0be43776e..a7a064881 100644
--- a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx
+++ b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.cxx
@@ -46,16 +46,12 @@ void cmWIXFeaturesSourceWriter::EmitFeatureForComponentGroup(
patch.ApplyFragment("CM_G_" + group.Name, *this);
- for (std::vector<cmCPackComponentGroup*>::const_iterator i =
- group.Subgroups.begin();
- i != group.Subgroups.end(); ++i) {
- EmitFeatureForComponentGroup(**i, patch);
+ for (cmCPackComponentGroup* subgroup : group.Subgroups) {
+ EmitFeatureForComponentGroup(*subgroup, patch);
}
- for (std::vector<cmCPackComponent*>::const_iterator i =
- group.Components.begin();
- i != group.Components.end(); ++i) {
- EmitFeatureForComponent(**i, patch);
+ for (cmCPackComponent* component : group.Components) {
+ EmitFeatureForComponent(*component, patch);
}
EndElement("Feature");
diff --git a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h
index e751ca719..e03e87bad 100644
--- a/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h
+++ b/Source/CPack/WiX/cmWIXFeaturesSourceWriter.h
@@ -3,11 +3,10 @@
#ifndef cmWIXFeaturesSourceWriter_h
#define cmWIXFeaturesSourceWriter_h
+#include "cmCPackGenerator.h"
#include "cmWIXPatch.h"
#include "cmWIXSourceWriter.h"
-#include "cmCPackGenerator.h"
-
/** \class cmWIXFeaturesSourceWriter
* \brief Helper class to generate features.wxs
*/
diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
index b4cd1a3d6..c0d879a0c 100644
--- a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
+++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
@@ -2,14 +2,13 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmWIXFilesSourceWriter.h"
-#include "cmWIXAccessControlList.h"
+#include "cm_sys_stat.h"
+#include "cmCMakeToWixPath.h"
#include "cmInstalledFile.h"
-
#include "cmSystemTools.h"
#include "cmUuid.h"
-
-#include "cm_sys_stat.h"
+#include "cmWIXAccessControlList.h"
cmWIXFilesSourceWriter::cmWIXFilesSourceWriter(cmCPackLog* logger,
std::string const& filename,
@@ -139,7 +138,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/cmWIXFilesSourceWriter.h b/Source/CPack/WiX/cmWIXFilesSourceWriter.h
index dc9c636d3..8cc98f52b 100644
--- a/Source/CPack/WiX/cmWIXFilesSourceWriter.h
+++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.h
@@ -3,12 +3,10 @@
#ifndef cmWIXFilesSourceWriter_h
#define cmWIXFilesSourceWriter_h
-#include "cmWIXSourceWriter.h"
-
+#include "cmCPackGenerator.h"
#include "cmWIXPatch.h"
#include "cmWIXShortcut.h"
-
-#include "cmCPackGenerator.h"
+#include "cmWIXSourceWriter.h"
/** \class cmWIXFilesSourceWriter
* \brief Helper class to generate files.wxs
diff --git a/Source/CPack/WiX/cmWIXPatch.cxx b/Source/CPack/WiX/cmWIXPatch.cxx
index 287a644bb..ca232f94b 100644
--- a/Source/CPack/WiX/cmWIXPatch.cxx
+++ b/Source/CPack/WiX/cmWIXPatch.cxx
@@ -13,8 +13,9 @@ bool cmWIXPatch::LoadFragments(std::string const& patchFilePath)
{
cmWIXPatchParser parser(Fragments, Logger);
if (!parser.ParseFile(patchFilePath.c_str())) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Failed parsing XML patch file: '"
- << patchFilePath << "'" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed parsing XML patch file: '" << patchFilePath << "'"
+ << std::endl);
return false;
}
@@ -29,10 +30,8 @@ void cmWIXPatch::ApplyFragment(std::string const& id,
return;
const cmWIXPatchElement& fragment = i->second;
- for (cmWIXPatchElement::attributes_t::const_iterator attr_i =
- fragment.attributes.begin();
- attr_i != fragment.attributes.end(); ++attr_i) {
- writer.AddAttribute(attr_i->first, attr_i->second);
+ for (auto const& attr : fragment.attributes) {
+ writer.AddAttribute(attr.first, attr.second);
}
this->ApplyElementChildren(fragment, writer);
@@ -42,11 +41,7 @@ void cmWIXPatch::ApplyFragment(std::string const& id,
void cmWIXPatch::ApplyElementChildren(const cmWIXPatchElement& element,
cmWIXSourceWriter& writer)
{
- for (cmWIXPatchElement::child_list_t::const_iterator j =
- element.children.begin();
- j != element.children.end(); ++j) {
- cmWIXPatchNode* node = *j;
-
+ for (cmWIXPatchNode* node : element.children) {
switch (node->type()) {
case cmWIXPatchNode::ELEMENT:
ApplyElement(dynamic_cast<const cmWIXPatchElement&>(*node), writer);
@@ -63,10 +58,8 @@ void cmWIXPatch::ApplyElement(const cmWIXPatchElement& element,
{
writer.BeginElement(element.name);
- for (cmWIXPatchElement::attributes_t::const_iterator i =
- element.attributes.begin();
- i != element.attributes.end(); ++i) {
- writer.AddAttribute(i->first, i->second);
+ for (auto const& attr : element.attributes) {
+ writer.AddAttribute(attr.first, attr.second);
}
this->ApplyElementChildren(element, writer);
@@ -77,14 +70,13 @@ void cmWIXPatch::ApplyElement(const cmWIXPatchElement& element,
bool cmWIXPatch::CheckForUnappliedFragments()
{
std::string fragmentList;
- for (cmWIXPatchParser::fragment_map_t::const_iterator i = Fragments.begin();
- i != Fragments.end(); ++i) {
+ for (auto const& fragment : Fragments) {
if (!fragmentList.empty()) {
fragmentList += ", ";
}
fragmentList += "'";
- fragmentList += i->first;
+ fragmentList += fragment.first;
fragmentList += "'";
}
diff --git a/Source/CPack/WiX/cmWIXPatch.h b/Source/CPack/WiX/cmWIXPatch.h
index a4c9e714d..31a60f4e8 100644
--- a/Source/CPack/WiX/cmWIXPatch.h
+++ b/Source/CPack/WiX/cmWIXPatch.h
@@ -3,11 +3,11 @@
#ifndef cmWIXPatch_h
#define cmWIXPatch_h
+#include <string>
+
#include "cmWIXPatchParser.h"
#include "cmWIXSourceWriter.h"
-#include <string>
-
/** \class cmWIXPatch
* \brief Class that maintains and applies patch fragments
*/
diff --git a/Source/CPack/WiX/cmWIXPatchParser.cxx b/Source/CPack/WiX/cmWIXPatchParser.cxx
index 0dcc74ae0..fd9103bc1 100644
--- a/Source/CPack/WiX/cmWIXPatchParser.cxx
+++ b/Source/CPack/WiX/cmWIXPatchParser.cxx
@@ -2,10 +2,10 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmWIXPatchParser.h"
-#include "cmCPackGenerator.h"
-
#include "cm_expat.h"
+#include "cmCPackGenerator.h"
+
cmWIXPatchNode::Type cmWIXPatchText::type()
{
return cmWIXPatchNode::TEXT;
@@ -22,8 +22,8 @@ cmWIXPatchNode::~cmWIXPatchNode()
cmWIXPatchElement::~cmWIXPatchElement()
{
- for (child_list_t::iterator i = children.begin(); i != children.end(); ++i) {
- delete *i;
+ for (cmWIXPatchNode* child : children) {
+ delete child;
}
}
@@ -72,7 +72,7 @@ void cmWIXPatchParser::StartElement(const std::string& name, const char** atts)
void cmWIXPatchParser::StartFragment(const char** attributes)
{
- cmWIXPatchElement* new_element = CM_NULLPTR;
+ cmWIXPatchElement* new_element = nullptr;
/* find the id of for fragment */
for (size_t i = 0; attributes[i]; i += 2) {
const std::string key = attributes[i];
@@ -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/WiX/cmWIXPatchParser.h b/Source/CPack/WiX/cmWIXPatchParser.h
index 52c7e3524..87dd89288 100644
--- a/Source/CPack/WiX/cmWIXPatchParser.h
+++ b/Source/CPack/WiX/cmWIXPatchParser.h
@@ -3,13 +3,12 @@
#ifndef cmCPackWIXPatchParser_h
#define cmCPackWIXPatchParser_h
-#include "cmCPackLog.h"
-
-#include "cmXMLParser.h"
-
#include <map>
#include <vector>
+#include "cmCPackLog.h"
+#include "cmXMLParser.h"
+
struct cmWIXPatchNode
{
enum Type
@@ -36,8 +35,8 @@ struct cmWIXPatchElement : cmWIXPatchNode
~cmWIXPatchElement();
- typedef std::vector<cmWIXPatchNode*> child_list_t;
- typedef std::map<std::string, std::string> attributes_t;
+ using child_list_t = std::vector<cmWIXPatchNode*>;
+ using attributes_t = std::map<std::string, std::string>;
std::string name;
child_list_t children;
@@ -50,7 +49,7 @@ struct cmWIXPatchElement : cmWIXPatchNode
class cmWIXPatchParser : public cmXMLParser
{
public:
- typedef std::map<std::string, cmWIXPatchElement> fragment_map_t;
+ using fragment_map_t = std::map<std::string, cmWIXPatchElement>;
cmWIXPatchParser(fragment_map_t& Fragments, cmCPackLog* logger);
diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx
index 2c99a2284..751f7dc3a 100644
--- a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx
+++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx
@@ -25,7 +25,7 @@ cmWIXRichTextFormatWriter::~cmWIXRichTextFormatWriter()
void cmWIXRichTextFormatWriter::AddText(std::string const& text)
{
- typedef unsigned char rtf_byte_t;
+ using rtf_byte_t = unsigned char;
for (size_t i = 0; i < text.size(); ++i) {
rtf_byte_t c = rtf_byte_t(text[i]);
diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h
index 30df87814..a879f3da9 100644
--- a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h
+++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h
@@ -3,11 +3,12 @@
#ifndef cmWIXRichTextFormatWriter_h
#define cmWIXRichTextFormatWriter_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmsys/FStream.hxx"
#include <string>
+#include "cmsys/FStream.hxx"
+
/** \class cmWIXRichtTextFormatWriter
* \brief Helper class to generate Rich Text Format (RTF) documents
* from plain text (e.g. for license and welcome text)
diff --git a/Source/CPack/WiX/cmWIXShortcut.cxx b/Source/CPack/WiX/cmWIXShortcut.cxx
index e5dea94c4..cd1988a1c 100644
--- a/Source/CPack/WiX/cmWIXShortcut.cxx
+++ b/Source/CPack/WiX/cmWIXShortcut.cxx
@@ -47,10 +47,9 @@ bool cmWIXShortcuts::EmitShortcuts(
return false;
}
- for (shortcut_id_map_t::const_iterator j = id_map.begin(); j != id_map.end();
- ++j) {
- std::string const& id = j->first;
- shortcut_list_t const& shortcutList = j->second;
+ for (auto const& j : id_map) {
+ std::string const& id = j.first;
+ shortcut_list_t const& shortcutList = j.second;
for (size_t shortcutListIndex = 0; shortcutListIndex < shortcutList.size();
++shortcutListIndex) {
@@ -68,9 +67,8 @@ bool cmWIXShortcuts::EmitShortcuts(
void cmWIXShortcuts::AddShortcutTypes(std::set<Type>& types)
{
- for (shortcut_type_map_t::const_iterator i = this->Shortcuts.begin();
- i != this->Shortcuts.end(); ++i) {
- types.insert(i->first);
+ for (auto const& shortcut : this->Shortcuts) {
+ types.insert(shortcut.first);
}
}
@@ -96,9 +94,9 @@ void cmWIXShortcuts::CreateFromProperty(std::string const& propertyName,
std::vector<std::string> list;
installedFile.GetPropertyAsList(propertyName, list);
- for (size_t i = 0; i < list.size(); ++i) {
+ for (std::string const& label : list) {
cmWIXShortcut shortcut;
- shortcut.label = list[i];
+ shortcut.label = label;
shortcut.workingDirectoryId = directoryId;
insert(type, id, shortcut);
}
diff --git a/Source/CPack/WiX/cmWIXShortcut.h b/Source/CPack/WiX/cmWIXShortcut.h
index 23ddc6a3f..c67baf369 100644
--- a/Source/CPack/WiX/cmWIXShortcut.h
+++ b/Source/CPack/WiX/cmWIXShortcut.h
@@ -3,13 +3,13 @@
#ifndef cmWIXShortcut_h
#define cmWIXShortcut_h
-#include "cmInstalledFile.h"
-
#include <map>
#include <set>
#include <string>
#include <vector>
+#include "cmInstalledFile.h"
+
class cmWIXFilesSourceWriter;
struct cmWIXShortcut
@@ -28,8 +28,8 @@ public:
STARTUP
};
- typedef std::vector<cmWIXShortcut> shortcut_list_t;
- typedef std::map<std::string, shortcut_list_t> shortcut_id_map_t;
+ using shortcut_list_t = std::vector<cmWIXShortcut>;
+ using shortcut_id_map_t = std::map<std::string, shortcut_list_t>;
void insert(Type type, std::string const& id, cmWIXShortcut const& shortcut);
@@ -46,7 +46,7 @@ public:
cmInstalledFile const& installedFile);
private:
- typedef std::map<Type, shortcut_id_map_t> shortcut_type_map_t;
+ using shortcut_type_map_t = std::map<Type, shortcut_id_map_t>;
void CreateFromProperty(std::string const& propertyName, Type type,
std::string const& id,
diff --git a/Source/CPack/WiX/cmWIXSourceWriter.cxx b/Source/CPack/WiX/cmWIXSourceWriter.cxx
index a86e28d1c..8e9bfdf3f 100644
--- a/Source/CPack/WiX/cmWIXSourceWriter.cxx
+++ b/Source/CPack/WiX/cmWIXSourceWriter.cxx
@@ -2,12 +2,11 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmWIXSourceWriter.h"
-#include "cmCPackGenerator.h"
+#include <windows.h>
+#include "cmCPackGenerator.h"
#include "cmUuid.h"
-#include <windows.h>
-
cmWIXSourceWriter::cmWIXSourceWriter(cmCPackLog* logger,
std::string const& filename,
GuidType componentGuidType,
@@ -32,7 +31,8 @@ cmWIXSourceWriter::cmWIXSourceWriter(cmCPackLog* logger,
cmWIXSourceWriter::~cmWIXSourceWriter()
{
if (Elements.size() > 1) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, Elements.size() - 1
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ Elements.size() - 1
<< " WiX elements were still open when closing '"
<< SourceFilename << "'" << std::endl);
return;
@@ -65,7 +65,8 @@ void cmWIXSourceWriter::EndElement(std::string const& name)
}
if (Elements.back() != name) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "WiX element <"
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "WiX element <"
<< Elements.back() << "> can not be closed by </" << name
<< "> in '" << SourceFilename << "'" << std::endl);
return;
@@ -158,9 +159,7 @@ std::string cmWIXSourceWriter::EscapeAttributeValue(std::string const& value)
std::string result;
result.reserve(value.size());
- char c = 0;
- for (size_t i = 0; i < value.size(); ++i) {
- c = value[i];
+ for (char c : value) {
switch (c) {
case '<':
result += "&lt;";
diff --git a/Source/CPack/WiX/cmWIXSourceWriter.h b/Source/CPack/WiX/cmWIXSourceWriter.h
index 4af1ed6ed..8cc2070a8 100644
--- a/Source/CPack/WiX/cmWIXSourceWriter.h
+++ b/Source/CPack/WiX/cmWIXSourceWriter.h
@@ -3,12 +3,12 @@
#ifndef cmWIXSourceWriter_h
#define cmWIXSourceWriter_h
-#include "cmCPackLog.h"
+#include <string>
+#include <vector>
#include "cmsys/FStream.hxx"
-#include <string>
-#include <vector>
+#include "cmCPackLog.h"
/** \class cmWIXSourceWriter
* \brief Helper class to generate XML WiX source files
diff --git a/Source/CPack/bills-comments.txt b/Source/CPack/bills-comments.txt
deleted file mode 100644
index c3b4ee8e7..000000000
--- a/Source/CPack/bills-comments.txt
+++ /dev/null
@@ -1,68 +0,0 @@
-cpack.cxx
-
-cmCPackGenerators -- creates cmCPackGenericGenerator's via NewGenerator
- - a cmCPackGenericGenerator factory
-
-
-cmCPackGenericGenerator::Initialize
- this->InitializeInternal
- CPACK_INCLUDE_TOPLEVEL_DIRECTORY = 0 turns off
-
-
-// binary package run
-cmCPackGenericGenerator::ProcessGenerator // DoPackage
- cmCPackGenericGenerator::PrepareNames -- sets a bunch of CPACK_vars
- cmCPackGenericGenerator::InstallProject
- run preinstall (make preinstall/fast)
- call ReadListFile(cmake_install.cmake)
- glob recurse in install directory to get list of files
- this->CompressFiles with the list of files
-
-
-// source package run
-cmCPackGenericGenerator::ProcessGenerator // DoPackage
- cmCPackGenericGenerator::PrepareNames -- sets a bunch of CPACK_vars
- cmCPackGenericGenerator::InstallProject -->
- if set CPACK_INSTALLED_DIRECTORIES
- glob the files in that directory
- copy those files to the tmp install directory _CPack something
- glob recurse in install directory to get list of files
- this->CompressFiles with the list of files
-
-
-cmCPackGenericGenerator::InstallProject is used for both source and binary
-packages. It is controled based on values set in CPACK_ variables.
-
-
-InstallProject
- 1. CPACK_INSTALL_COMMANDS - a list of commands used to install the package
-
- 2. CPACK_INSTALLED_DIRECTORIES - copy this directory to CPACK_TEMPORARY_DIRECTORY
-
- 3. CPACK_INSTALL_CMAKE_PROJECTS - a cmake install script
- - run make preinstall
- - run cmake_install.cmake
- - set CMAKE_INSTALL_PREFIX to the temp directory
- - CPACK_BUILD_CONFIG check this and set the BUILD_TYPE to it
- - ReadListFile on the install script cmake_install.cmake
- - run strip on the executables and libraries if CPACK_STRIP_FILES is TRUE
-
-Recommendations:
-
-rename cmCPackGenerators to cmCPackGeneratorFactory
-
-rename cmCPackGenericGenerator --> cmCPackGenerator
-
-rename cmCPackGenericGenerator::ProcessGenerator -> cmCPackGenerator::DoPackage
-
-
-break up cmCPackGenerator::InstallProject so it calls the following:
-
-// run user provided install commands
- cmCPackGenerator::RunInstallCommands();
-// copy entire directories that need no processing like source trees
- cmCPackGenerator::CopyPreInstalledDirectories();
-// run the cmake install scripts if provided
- cmCPackGenerator::RunCMakeInstallScripts()
-
--
diff --git a/Source/CPack/cmCPack7zGenerator.cxx b/Source/CPack/cmCPack7zGenerator.cxx
deleted file mode 100644
index f0c41a2a1..000000000
--- a/Source/CPack/cmCPack7zGenerator.cxx
+++ /dev/null
@@ -1,15 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmCPack7zGenerator.h"
-
-#include "cmArchiveWrite.h"
-#include "cmCPackArchiveGenerator.h"
-
-cmCPack7zGenerator::cmCPack7zGenerator()
- : cmCPackArchiveGenerator(cmArchiveWrite::CompressNone, "7zip")
-{
-}
-
-cmCPack7zGenerator::~cmCPack7zGenerator()
-{
-}
diff --git a/Source/CPack/cmCPack7zGenerator.h b/Source/CPack/cmCPack7zGenerator.h
deleted file mode 100644
index 42a47810c..000000000
--- a/Source/CPack/cmCPack7zGenerator.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmCPack7zGenerator_h
-#define cmCPack7zGenerator_h
-
-#include "cmConfigure.h"
-
-#include "cmCPackArchiveGenerator.h"
-#include "cmCPackGenerator.h"
-
-/** \class cmCPack7zGenerator
- * \brief A generator for 7z files
- */
-class cmCPack7zGenerator : public cmCPackArchiveGenerator
-{
-public:
- cmCPackTypeMacro(cmCPack7zGenerator, cmCPackArchiveGenerator);
-
- /**
- * Construct generator
- */
- cmCPack7zGenerator();
- ~cmCPack7zGenerator() CM_OVERRIDE;
-
-protected:
- const char* GetOutputExtension() CM_OVERRIDE { return ".7z"; }
-};
-
-#endif
diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx
index 575c94924..43f2946bd 100644
--- a/Source/CPack/cmCPackArchiveGenerator.cxx
+++ b/Source/CPack/cmCPackArchiveGenerator.cxx
@@ -2,29 +2,72 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackArchiveGenerator.h"
+#include <cstring>
+#include <map>
+#include <ostream>
+#include <utility>
+#include <vector>
+
#include "cmCPackComponentGroup.h"
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
#include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
-#include <map>
-#include <ostream>
-#include <utility>
-#include <vector>
+cmCPackGenerator* cmCPackArchiveGenerator::Create7ZGenerator()
+{
+ return new cmCPackArchiveGenerator(cmArchiveWrite::CompressNone, "7zip",
+ ".7z");
+}
+
+cmCPackGenerator* cmCPackArchiveGenerator::CreateTBZ2Generator()
+{
+ return new cmCPackArchiveGenerator(cmArchiveWrite::CompressBZip2, "paxr",
+ ".tar.bz2");
+}
+
+cmCPackGenerator* cmCPackArchiveGenerator::CreateTGZGenerator()
+{
+ return new cmCPackArchiveGenerator(cmArchiveWrite::CompressGZip, "paxr",
+ ".tar.gz");
+}
-cmCPackArchiveGenerator::cmCPackArchiveGenerator(cmArchiveWrite::Compress t,
- std::string const& format)
+cmCPackGenerator* cmCPackArchiveGenerator::CreateTXZGenerator()
{
- this->Compress = t;
- this->ArchiveFormat = format;
+ return new cmCPackArchiveGenerator(cmArchiveWrite::CompressXZ, "paxr",
+ ".tar.xz");
}
-cmCPackArchiveGenerator::~cmCPackArchiveGenerator()
+cmCPackGenerator* cmCPackArchiveGenerator::CreateTZGenerator()
{
+ return new cmCPackArchiveGenerator(cmArchiveWrite::CompressCompress, "paxr",
+ ".tar.Z");
}
+cmCPackGenerator* cmCPackArchiveGenerator::CreateTZSTGenerator()
+{
+ return new cmCPackArchiveGenerator(cmArchiveWrite::CompressZstd, "paxr",
+ ".tar.zst");
+}
+
+cmCPackGenerator* cmCPackArchiveGenerator::CreateZIPGenerator()
+{
+ return new cmCPackArchiveGenerator(cmArchiveWrite::CompressNone, "zip",
+ ".zip");
+}
+
+cmCPackArchiveGenerator::cmCPackArchiveGenerator(
+ cmArchiveWrite::Compress compress, std::string format, std::string extension)
+ : Compress(compress)
+ , ArchiveFormat(std::move(format))
+ , OutputExtension(std::move(extension))
+{
+}
+
+cmCPackArchiveGenerator::~cmCPackArchiveGenerator() = default;
+
std::string cmCPackArchiveGenerator::GetArchiveComponentFileName(
const std::string& component, bool isGroupName)
{
@@ -52,6 +95,7 @@ int cmCPackArchiveGenerator::InitializeInternal()
this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "1");
return this->Superclass::InitializeInternal();
}
+
int cmCPackArchiveGenerator::addOneComponentToArchive(
cmArchiveWrite& archive, cmCPackComponent* component)
{
@@ -62,10 +106,16 @@ int cmCPackArchiveGenerator::addOneComponentToArchive(
localToplevel += "/" + component->Name;
// Change to local toplevel
cmWorkingDirectory workdir(localToplevel);
+ if (workdir.Failed()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed to change working directory to "
+ << localToplevel << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ return 0;
+ }
std::string filePrefix;
if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
- filePrefix = this->GetOption("CPACK_PACKAGE_FILE_NAME");
- filePrefix += "/";
+ filePrefix = cmStrCat(this->GetOption("CPACK_PACKAGE_FILE_NAME"), '/');
}
const char* installPrefix =
this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
@@ -74,15 +124,14 @@ int cmCPackArchiveGenerator::addOneComponentToArchive(
filePrefix += installPrefix + 1;
filePrefix += "/";
}
- std::vector<std::string>::const_iterator fileIt;
- for (fileIt = component->Files.begin(); fileIt != component->Files.end();
- ++fileIt) {
- std::string rp = filePrefix + *fileIt;
+ for (std::string const& file : component->Files) {
+ std::string rp = filePrefix + file;
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Adding file: " << rp << std::endl);
- archive.Add(rp, 0, CM_NULLPTR, false);
+ archive.Add(rp, 0, nullptr, false);
if (!archive) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "ERROR while packaging files: "
- << archive.GetError() << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "ERROR while packaging files: " << archive.GetError()
+ << std::endl);
return 0;
}
}
@@ -96,20 +145,23 @@ int cmCPackArchiveGenerator::addOneComponentToArchive(
*/
#define DECLARE_AND_OPEN_ARCHIVE(filename, archive) \
cmGeneratedFileStream gf; \
- gf.Open((filename).c_str(), false, true); \
+ gf.Open((filename), false, true); \
if (!GenerateHeader(&gf)) { \
cmCPackLogger(cmCPackLog::LOG_ERROR, \
- "Problem to generate Header for archive < " \
+ "Problem to generate Header for archive <" \
<< (filename) << ">." << std::endl); \
return 0; \
} \
cmArchiveWrite archive(gf, this->Compress, this->ArchiveFormat); \
- if (!(archive)) { \
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem to create archive < " \
- << (filename) << ">. ERROR =" << (archive).GetError() \
- << std::endl); \
- return 0; \
- }
+ do { \
+ if (!(archive)) { \
+ cmCPackLogger(cmCPackLog::LOG_ERROR, \
+ "Problem to create archive <" \
+ << (filename) << ">, ERROR = " << (archive).GetError() \
+ << std::endl); \
+ return 0; \
+ } \
+ } while (false)
int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
{
@@ -117,79 +169,72 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
// The default behavior is to have one package by component group
// unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
if (!ignoreGroup) {
- std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
- for (compGIt = this->ComponentGroups.begin();
- compGIt != this->ComponentGroups.end(); ++compGIt) {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: "
- << compGIt->first << std::endl);
+ for (auto const& compG : this->ComponentGroups) {
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Packaging component group: " << compG.first << std::endl);
// Begin the archive for this group
std::string packageFileName = std::string(toplevel) + "/" +
- this->GetArchiveComponentFileName(compGIt->first, true);
+ this->GetArchiveComponentFileName(compG.first, true);
// open a block in order to automatically close archive
// at the end of the block
{
DECLARE_AND_OPEN_ARCHIVE(packageFileName, archive);
// now iterate over the component of this group
- std::vector<cmCPackComponent*>::iterator compIt;
- for (compIt = (compGIt->second).Components.begin();
- compIt != (compGIt->second).Components.end(); ++compIt) {
+ for (cmCPackComponent* comp : (compG.second).Components) {
// Add the files of this component to the archive
- addOneComponentToArchive(archive, *compIt);
+ addOneComponentToArchive(archive, comp);
}
}
// 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)
- std::map<std::string, cmCPackComponent>::iterator compIt;
- for (compIt = this->Components.begin(); compIt != this->Components.end();
- ++compIt) {
+ for (auto& comp : this->Components) {
// Does the component belong to a group?
- if (compIt->second.Group == CM_NULLPTR) {
+ if (comp.second.Group == nullptr) {
cmCPackLogger(
- cmCPackLog::LOG_VERBOSE, "Component <"
- << compIt->second.Name
+ cmCPackLog::LOG_VERBOSE,
+ "Component <"
+ << comp.second.Name
<< "> does not belong to any group, package it separately."
<< std::endl);
std::string localToplevel(
this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
std::string packageFileName = std::string(toplevel);
- localToplevel += "/" + compIt->first;
+ localToplevel += "/" + comp.first;
packageFileName +=
- "/" + this->GetArchiveComponentFileName(compIt->first, false);
+ "/" + this->GetArchiveComponentFileName(comp.first, false);
{
DECLARE_AND_OPEN_ARCHIVE(packageFileName, archive);
// Add the files of this component to the archive
- addOneComponentToArchive(archive, &(compIt->second));
+ addOneComponentToArchive(archive, &(comp.second));
}
// add the generated package to package file names list
- packageFileNames.push_back(packageFileName);
+ packageFileNames.push_back(std::move(packageFileName));
}
}
}
// CPACK_COMPONENTS_IGNORE_GROUPS is set
// We build 1 package per component
else {
- std::map<std::string, cmCPackComponent>::iterator compIt;
- for (compIt = this->Components.begin(); compIt != this->Components.end();
- ++compIt) {
+ for (auto& comp : this->Components) {
std::string localToplevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
std::string packageFileName = std::string(toplevel);
- localToplevel += "/" + compIt->first;
+ localToplevel += "/" + comp.first;
packageFileName +=
- "/" + this->GetArchiveComponentFileName(compIt->first, false);
+ "/" + this->GetArchiveComponentFileName(comp.first, false);
{
DECLARE_AND_OPEN_ARCHIVE(packageFileName, archive);
// Add the files of this component to the archive
- addOneComponentToArchive(archive, &(compIt->second));
+ 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;
@@ -199,7 +244,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")) {
@@ -217,11 +262,9 @@ int cmCPackArchiveGenerator::PackageComponentsAllInOne()
DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0], archive);
// The ALL COMPONENTS in ONE package case
- std::map<std::string, cmCPackComponent>::iterator compIt;
- for (compIt = this->Components.begin(); compIt != this->Components.end();
- ++compIt) {
+ for (auto& comp : this->Components) {
// Add the files of this component to the archive
- addOneComponentToArchive(archive, &(compIt->second));
+ addOneComponentToArchive(archive, &(comp.second));
}
// archive goes out of scope so it will finalized and closed.
@@ -249,17 +292,23 @@ int cmCPackArchiveGenerator::PackageFiles()
// CASE 3 : NON COMPONENT package.
DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0], archive);
- std::vector<std::string>::const_iterator fileIt;
cmWorkingDirectory workdir(toplevel);
- for (fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
+ if (workdir.Failed()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed to change working directory to "
+ << toplevel << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ return 0;
+ }
+ for (std::string const& file : files) {
// Get the relative path to the file
- std::string rp =
- cmSystemTools::RelativePath(toplevel.c_str(), fileIt->c_str());
- archive.Add(rp, 0, CM_NULLPTR, false);
+ std::string rp = cmSystemTools::RelativePath(toplevel, file);
+ archive.Add(rp, 0, nullptr, false);
if (!archive) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem while adding file< "
- << *fileIt << "> to archive <" << packageFileNames[0]
- << "> .ERROR =" << archive.GetError() << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem while adding file <"
+ << file << "> to archive <" << packageFileNames[0]
+ << ">, ERROR = " << archive.GetError() << std::endl);
return 0;
}
}
diff --git a/Source/CPack/cmCPackArchiveGenerator.h b/Source/CPack/cmCPackArchiveGenerator.h
index e7116c466..8d677208f 100644
--- a/Source/CPack/cmCPackArchiveGenerator.h
+++ b/Source/CPack/cmCPackArchiveGenerator.h
@@ -3,14 +3,14 @@
#ifndef cmCPackArchiveGenerator_h
#define cmCPackArchiveGenerator_h
-#include "cmConfigure.h"
-
-#include "cmArchiveWrite.h"
-#include "cmCPackGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
+#include "cmArchiveWrite.h"
+#include "cmCPackGenerator.h"
+
class cmCPackComponent;
/** \class cmCPackArchiveGenerator
@@ -22,17 +22,26 @@ class cmCPackComponent;
class cmCPackArchiveGenerator : public cmCPackGenerator
{
public:
- typedef cmCPackGenerator Superclass;
+ using Superclass = cmCPackGenerator;
+
+ static cmCPackGenerator* Create7ZGenerator();
+ static cmCPackGenerator* CreateTBZ2Generator();
+ static cmCPackGenerator* CreateTGZGenerator();
+ static cmCPackGenerator* CreateTXZGenerator();
+ static cmCPackGenerator* CreateTZGenerator();
+ static cmCPackGenerator* CreateTZSTGenerator();
+ static cmCPackGenerator* CreateZIPGenerator();
/**
* Construct generator
*/
- cmCPackArchiveGenerator(cmArchiveWrite::Compress, std::string const& format);
- ~cmCPackArchiveGenerator() CM_OVERRIDE;
+ cmCPackArchiveGenerator(cmArchiveWrite::Compress t, std::string format,
+ std::string extension);
+ ~cmCPackArchiveGenerator() override;
// Used to add a header to the archive
virtual int GenerateHeader(std::ostream* os);
// component support
- bool SupportsComponentInstallation() const CM_OVERRIDE;
+ bool SupportsComponentInstallation() const override;
private:
// get archive component filename
@@ -40,7 +49,7 @@ private:
bool isGroupName);
protected:
- int InitializeInternal() CM_OVERRIDE;
+ int InitializeInternal() override;
/**
* Add the files belonging to the specified component
* to the provided (already opened) archive.
@@ -56,7 +65,7 @@ protected:
* method will call either PackageComponents or
* PackageComponentsAllInOne.
*/
- int PackageFiles() CM_OVERRIDE;
+ int PackageFiles() override;
/**
* The method used to package files when component
* install is used. This will create one
@@ -68,9 +77,19 @@ protected:
* components will be put in a single installer.
*/
int PackageComponentsAllInOne();
- const char* GetOutputExtension() CM_OVERRIDE = 0;
+
+private:
+ const char* GetNameOfClass() override { return "cmCPackArchiveGenerator"; }
+
+ const char* GetOutputExtension() override
+ {
+ return this->OutputExtension.c_str();
+ }
+
+private:
cmArchiveWrite::Compress Compress;
std::string ArchiveFormat;
+ std::string OutputExtension;
};
#endif
diff --git a/Source/CPack/cmCPackBundleGenerator.cxx b/Source/CPack/cmCPackBundleGenerator.cxx
index d5389014a..4d5f43f9e 100644
--- a/Source/CPack/cmCPackBundleGenerator.cxx
+++ b/Source/CPack/cmCPackBundleGenerator.cxx
@@ -6,20 +6,17 @@
#include <vector>
#include "cmCPackLog.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-cmCPackBundleGenerator::cmCPackBundleGenerator()
-{
-}
+cmCPackBundleGenerator::cmCPackBundleGenerator() = default;
-cmCPackBundleGenerator::~cmCPackBundleGenerator()
-{
-}
+cmCPackBundleGenerator::~cmCPackBundleGenerator() = default;
int cmCPackBundleGenerator::InitializeInternal()
{
const char* name = this->GetOption("CPACK_BUNDLE_NAME");
- if (0 == name) {
+ if (nullptr == name) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_BUNDLE_NAME must be set to use the Bundle generator."
<< std::endl);
@@ -32,8 +29,8 @@ int cmCPackBundleGenerator::InitializeInternal()
"codesign", std::vector<std::string>(), false);
if (codesign_path.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot locate codesign command"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot locate codesign command" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_COMMAND_CODESIGN", codesign_path.c_str());
@@ -44,9 +41,8 @@ int cmCPackBundleGenerator::InitializeInternal()
const char* cmCPackBundleGenerator::GetPackagingInstallPrefix()
{
- this->InstallPrefix = "/";
- this->InstallPrefix += this->GetOption("CPACK_BUNDLE_NAME");
- this->InstallPrefix += ".app/Contents/Resources";
+ this->InstallPrefix = cmStrCat('/', this->GetOption("CPACK_BUNDLE_NAME"),
+ ".app/Contents/Resources");
return this->InstallPrefix.c_str();
}
@@ -59,8 +55,8 @@ int cmCPackBundleGenerator::ConstructBundle()
? this->GetOption("CPACK_BUNDLE_NAME")
: "";
if (cpack_bundle_name.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_NAME must be set."
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_BUNDLE_NAME must be set." << std::endl);
return 0;
}
@@ -69,8 +65,8 @@ int cmCPackBundleGenerator::ConstructBundle()
? this->GetOption("CPACK_BUNDLE_PLIST")
: "";
if (cpack_bundle_plist.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_PLIST must be set."
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_BUNDLE_PLIST must be set." << std::endl);
return 0;
}
@@ -79,8 +75,8 @@ int cmCPackBundleGenerator::ConstructBundle()
? this->GetOption("CPACK_BUNDLE_ICON")
: "";
if (cpack_bundle_icon.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_ICON must be set."
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_BUNDLE_ICON must be set." << std::endl);
return 0;
}
@@ -93,11 +89,10 @@ int cmCPackBundleGenerator::ConstructBundle()
// The staging directory contains everything that will end-up inside the
// final disk image ...
- std::ostringstream staging;
- staging << toplevel;
+ std::string const staging = toplevel;
std::ostringstream contents;
- contents << staging.str() << "/" << cpack_bundle_name << ".app/"
+ contents << staging << "/" << cpack_bundle_name << ".app/"
<< "Contents";
std::ostringstream application;
@@ -194,9 +189,8 @@ int cmCPackBundleGenerator::SignBundle(const std::string& src_dir)
if (!cpack_apple_cert_app.empty()) {
std::string output;
std::string bundle_path;
- bundle_path = src_dir + "/";
- bundle_path += this->GetOption("CPACK_BUNDLE_NAME");
- bundle_path += ".app";
+ bundle_path =
+ cmStrCat(src_dir, '/', this->GetOption("CPACK_BUNDLE_NAME"), ".app");
// A list of additional files to sign, ie. frameworks and plugins.
const std::string sign_parameter =
@@ -209,12 +203,10 @@ int cmCPackBundleGenerator::SignBundle(const std::string& src_dir)
? this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES")
: "";
- std::vector<std::string> relFiles;
- cmSystemTools::ExpandListArgument(sign_files, relFiles);
+ std::vector<std::string> relFiles = cmExpandedList(sign_files);
// sign the files supplied by the user, ie. frameworks.
- for (std::vector<std::string>::iterator it = relFiles.begin();
- it != relFiles.end(); ++it) {
+ for (auto const& file : relFiles) {
std::ostringstream temp_sign_file_cmd;
temp_sign_file_cmd << this->GetOption("CPACK_COMMAND_CODESIGN");
temp_sign_file_cmd << " " << sign_parameter << " -s \""
@@ -223,11 +215,11 @@ int cmCPackBundleGenerator::SignBundle(const std::string& src_dir)
temp_sign_file_cmd << this->GetOption("CPACK_APPLE_BUNDLE_ID");
temp_sign_file_cmd << " \"";
temp_sign_file_cmd << bundle_path;
- temp_sign_file_cmd << *it << "\"";
+ temp_sign_file_cmd << file << "\"";
if (!this->RunCommand(temp_sign_file_cmd, &output)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error signing file:" << bundle_path << *it << std::endl
+ "Error signing file:" << bundle_path << file << std::endl
<< output << std::endl);
return 0;
@@ -270,8 +262,8 @@ int cmCPackBundleGenerator::SignBundle(const std::string& src_dir)
return 0;
}
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Application has been codesigned"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Application has been codesigned" << std::endl);
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
(this->GetOption("CPACK_BUNDLE_APPLE_ENTITLEMENTS")
? "with entitlement sandboxing"
diff --git a/Source/CPack/cmCPackBundleGenerator.h b/Source/CPack/cmCPackBundleGenerator.h
index 861fe4b09..27bac3a5a 100644
--- a/Source/CPack/cmCPackBundleGenerator.h
+++ b/Source/CPack/cmCPackBundleGenerator.h
@@ -3,7 +3,7 @@
#ifndef cmCPackBundleGenerator_h
#define cmCPackBundleGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
@@ -21,15 +21,15 @@ public:
cmCPackTypeMacro(cmCPackBundleGenerator, cmCPackDragNDropGenerator);
cmCPackBundleGenerator();
- virtual ~cmCPackBundleGenerator();
+ ~cmCPackBundleGenerator() override;
protected:
- int InitializeInternal() CM_OVERRIDE;
- const char* GetPackagingInstallPrefix() CM_OVERRIDE;
+ int InitializeInternal() override;
+ const char* GetPackagingInstallPrefix() override;
int ConstructBundle();
int SignBundle(const std::string& src_dir);
- int PackageFiles() CM_OVERRIDE;
- bool SupportsComponentInstallation() const CM_OVERRIDE;
+ int PackageFiles() override;
+ bool SupportsComponentInstallation() const override;
std::string InstallPrefix;
};
diff --git a/Source/CPack/cmCPackComponentGroup.cxx b/Source/CPack/cmCPackComponentGroup.cxx
index e39398ad5..d40e5fcf8 100644
--- a/Source/CPack/cmCPackComponentGroup.cxx
+++ b/Source/CPack/cmCPackComponentGroup.cxx
@@ -2,10 +2,10 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackComponentGroup.h"
-#include "cmSystemTools.h"
-
#include <string>
-#include <vector>
+
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
unsigned long cmCPackComponent::GetInstalledSize(
const std::string& installDir) const
@@ -14,11 +14,8 @@ unsigned long cmCPackComponent::GetInstalledSize(
return this->TotalSize;
}
- std::vector<std::string>::const_iterator fileIt;
- for (fileIt = this->Files.begin(); fileIt != this->Files.end(); ++fileIt) {
- std::string path = installDir;
- path += '/';
- path += *fileIt;
+ for (std::string const& file : this->Files) {
+ std::string path = cmStrCat(installDir, '/', file);
this->TotalSize += cmSystemTools::FileLength(path);
}
diff --git a/Source/CPack/cmCPackComponentGroup.h b/Source/CPack/cmCPackComponentGroup.h
index 26d69ba68..bb980d77f 100644
--- a/Source/CPack/cmCPackComponentGroup.h
+++ b/Source/CPack/cmCPackComponentGroup.h
@@ -3,7 +3,7 @@
#ifndef cmCPackComponentGroup_h
#define cmCPackComponentGroup_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
@@ -36,7 +36,7 @@ class cmCPackComponent
{
public:
cmCPackComponent()
- : Group(CM_NULLPTR)
+ : Group(nullptr)
, IsRequired(true)
, IsHidden(false)
, IsDisabledByDefault(false)
@@ -114,7 +114,7 @@ class cmCPackComponentGroup
{
public:
cmCPackComponentGroup()
- : ParentGroup(CM_NULLPTR)
+ : ParentGroup(nullptr)
{
}
@@ -143,4 +143,29 @@ public:
std::vector<cmCPackComponentGroup*> Subgroups;
};
+/** \class cmCPackInstallCMakeProject
+ * \brief A single quadruplet from the CPACK_INSTALL_CMAKE_PROJECTS variable.
+ */
+class cmCPackInstallCMakeProject
+{
+public:
+ /// The directory of the CMake project.
+ std::string Directory;
+
+ /// The name of the CMake project.
+ std::string ProjectName;
+
+ /// The name of the component (or component set) to install.
+ std::string Component;
+
+ /// The subdirectory to install into.
+ std::string SubDirectory;
+
+ /// The list of installation types.
+ std::vector<cmCPackInstallationType*> InstallationTypes;
+
+ /// The list of components.
+ std::vector<cmCPackComponent*> Components;
+};
+
#endif
diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
index 2119f782b..b5abd5a6b 100644
--- a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
+++ b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
@@ -2,6 +2,8 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackCygwinBinaryGenerator.h"
+#include "cmsys/SystemTools.hxx"
+
#include "cmCPackLog.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
@@ -9,9 +11,8 @@
#include "cmSystemTools.h"
#include "cmake.h"
-#include "cmsys/SystemTools.hxx"
-
cmCPackCygwinBinaryGenerator::cmCPackCygwinBinaryGenerator()
+ : cmCPackArchiveGenerator(cmArchiveWrite::CompressBZip2, "paxr", ".tar.bz2")
{
}
@@ -28,13 +29,11 @@ int cmCPackCygwinBinaryGenerator::InitializeInternal()
int cmCPackCygwinBinaryGenerator::PackageFiles()
{
- std::string packageName = this->GetOption("CPACK_PACKAGE_NAME");
- packageName += "-";
- packageName += this->GetOption("CPACK_PACKAGE_VERSION");
+ std::string packageName =
+ cmStrCat(this->GetOption("CPACK_PACKAGE_NAME"), '-',
+ this->GetOption("CPACK_PACKAGE_VERSION"));
packageName = cmsys::SystemTools::LowerCase(packageName);
- std::string manifest = "/usr/share/doc/";
- manifest += packageName;
- manifest += "/MANIFEST";
+ std::string manifest = cmStrCat("/usr/share/doc/", packageName, "/MANIFEST");
std::string manifestFile = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
// Create a MANIFEST file that contains all of the files in
// the tar file
@@ -44,10 +43,9 @@ int cmCPackCygwinBinaryGenerator::PackageFiles()
// to create the file before the super class is called
{
cmGeneratedFileStream ofs(manifestFile.c_str());
- for (std::vector<std::string>::const_iterator i = files.begin();
- i != files.end(); ++i) {
+ for (std::string const& file : files) {
// remove the temp dir and replace with /usr
- ofs << (*i).substr(tempdir.size()) << "\n";
+ ofs << file.substr(tempdir.size()) << "\n";
}
ofs << manifest << "\n";
}
diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.h b/Source/CPack/cmCPackCygwinBinaryGenerator.h
index 58e80bda7..47bd41e13 100644
--- a/Source/CPack/cmCPackCygwinBinaryGenerator.h
+++ b/Source/CPack/cmCPackCygwinBinaryGenerator.h
@@ -3,21 +3,21 @@
#ifndef cmCPackCygwinBinaryGenerator_h
#define cmCPackCygwinBinaryGenerator_h
-#include "cmCPackTarBZip2Generator.h"
+#include "cmCPackArchiveGenerator.h"
/** \class cmCPackCygwinBinaryGenerator
* \brief A generator for TarBZip2 files
*/
-class cmCPackCygwinBinaryGenerator : public cmCPackTarBZip2Generator
+class cmCPackCygwinBinaryGenerator : public cmCPackArchiveGenerator
{
public:
- cmCPackTypeMacro(cmCPackCygwinBinaryGenerator, cmCPackTarBZip2Generator);
+ cmCPackTypeMacro(cmCPackCygwinBinaryGenerator, cmCPackArchiveGenerator);
/**
* Construct generator
*/
cmCPackCygwinBinaryGenerator();
- virtual ~cmCPackCygwinBinaryGenerator();
+ ~cmCPackCygwinBinaryGenerator() override;
protected:
virtual int InitializeInternal();
diff --git a/Source/CPack/cmCPackCygwinSourceGenerator.cxx b/Source/CPack/cmCPackCygwinSourceGenerator.cxx
index 2c289f668..64a88eba4 100644
--- a/Source/CPack/cmCPackCygwinSourceGenerator.cxx
+++ b/Source/CPack/cmCPackCygwinSourceGenerator.cxx
@@ -2,6 +2,8 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackCygwinSourceGenerator.h"
+#include "cmsys/SystemTools.hxx"
+
#include "cmCPackLog.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
@@ -9,17 +11,17 @@
#include "cmSystemTools.h"
#include "cmake.h"
-#include "cmsys/SystemTools.hxx"
-
// Includes needed for implementation of RenameFile. This is not in
// system tools because it is not implemented robustly enough to move
// files across directories.
#ifdef _WIN32
-#include "cm_sys_stat.h"
-#include <windows.h>
+# include <windows.h>
+
+# include "cm_sys_stat.h"
#endif
cmCPackCygwinSourceGenerator::cmCPackCygwinSourceGenerator()
+ : cmCPackArchiveGenerator(cmArchiveWrite::CompressBZip2, "paxr", ".tar.bz2")
{
}
@@ -37,15 +39,11 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
{
// Create a tar file of the sources
std::string packageDirFileName =
- this->GetOption("CPACK_TEMPORARY_DIRECTORY");
- packageDirFileName += ".tar.bz2";
+ cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), ".tar.bz2");
packageFileNames[0] = packageDirFileName;
std::string output;
- // skip one parent up to the cmCPackTarBZip2Generator
- // to create tar.bz2 file with the list of source
- // files
- this->Compress = cmArchiveWrite::CompressBZip2;
- if (!this->cmCPackTarBZip2Generator::PackageFiles()) {
+ // create tar.bz2 file with the list of source files
+ if (!this->cmCPackArchiveGenerator::PackageFiles()) {
return 0;
}
// Now create a tar file that contains the above .tar.bz2 file
@@ -73,7 +71,8 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
if (!cmSystemTools::CopyFileAlways(
this->GetOption("CPACK_CYGWIN_PATCH_FILE"),
this->GetOption("CPACK_TOPLEVEL_DIRECTORY"))) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "problem copying: ["
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "problem copying: ["
<< this->GetOption("CPACK_CYGWIN_PATCH_FILE") << "]\nto\n["
<< this->GetOption("CPACK_TOPLEVEL_DIRECTORY") << "]\n");
return 0;
@@ -87,35 +86,36 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
if (!cmSystemTools::CopyFileAlways(
this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT"),
this->GetOption("CPACK_TOPLEVEL_DIRECTORY"))) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "problem copying: "
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "problem copying: "
<< this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT") << "\nto\n"
<< this->GetOption("CPACK_TOPLEVEL_DIRECTORY") << "]\n");
return 0;
}
- std::string outerTarFile = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
- outerTarFile += "-";
+ std::string outerTarFile =
+ cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), '-');
const char* patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER");
if (!patch) {
- cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_CYGWIN_PATCH_NUMBER"
+ cmCPackLogger(cmCPackLog::LOG_WARNING,
+ "CPACK_CYGWIN_PATCH_NUMBER"
<< " not specified, defaulting to 1\n");
patch = "1";
}
outerTarFile += patch;
outerTarFile += "-src.tar.bz2";
std::string tmpDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- std::string buildScript = tmpDir;
- buildScript += "/";
- buildScript += cmSystemTools::GetFilenameName(
- this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT"));
- std::string patchFile = tmpDir;
- patchFile += "/";
- patchFile +=
- cmSystemTools::GetFilenameName(this->GetOption("CPACK_CYGWIN_PATCH_FILE"));
+ std::string buildScript =
+ cmStrCat(tmpDir, '/',
+ cmSystemTools::GetFilenameName(
+ this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT")));
+ std::string patchFile =
+ cmStrCat(tmpDir, '/',
+ cmSystemTools::GetFilenameName(
+ this->GetOption("CPACK_CYGWIN_PATCH_FILE")));
std::string file = cmSystemTools::GetFilenameName(compressOutFile);
- std::string sourceTar = cmSystemTools::GetFilenamePath(compressOutFile);
- sourceTar += "/";
- sourceTar += file;
+ std::string sourceTar =
+ cmStrCat(cmSystemTools::GetFilenamePath(compressOutFile), '/', file);
/* reset list of file to be packaged */
files.clear();
// a source release in cygwin should have the build script used
@@ -129,7 +129,7 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
packageFileNames[0] = outerTarFile;
/* update the toplevel dir */
toplevel = tmpDir;
- if (!this->cmCPackTarBZip2Generator::PackageFiles()) {
+ if (!this->cmCPackArchiveGenerator::PackageFiles()) {
return 0;
}
return 1;
@@ -137,8 +137,8 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
const char* cmCPackCygwinSourceGenerator::GetPackagingInstallPrefix()
{
- this->InstallPrefix = "/";
- this->InstallPrefix += this->GetOption("CPACK_PACKAGE_FILE_NAME");
+ this->InstallPrefix =
+ cmStrCat('/', this->GetOption("CPACK_PACKAGE_FILE_NAME"));
return this->InstallPrefix.c_str();
}
@@ -147,7 +147,8 @@ const char* cmCPackCygwinSourceGenerator::GetOutputExtension()
this->OutputExtension = "-";
const char* patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER");
if (!patch) {
- cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_CYGWIN_PATCH_NUMBER"
+ cmCPackLogger(cmCPackLog::LOG_WARNING,
+ "CPACK_CYGWIN_PATCH_NUMBER"
<< " not specified, defaulting to 1\n");
patch = "1";
}
diff --git a/Source/CPack/cmCPackCygwinSourceGenerator.h b/Source/CPack/cmCPackCygwinSourceGenerator.h
index 896de1d3e..98d8f0ab7 100644
--- a/Source/CPack/cmCPackCygwinSourceGenerator.h
+++ b/Source/CPack/cmCPackCygwinSourceGenerator.h
@@ -3,21 +3,21 @@
#ifndef cmCPackCygwinSourceGenerator_h
#define cmCPackCygwinSourceGenerator_h
-#include "cmCPackTarBZip2Generator.h"
+#include "cmCPackArchiveGenerator.h"
/** \class cmCPackCygwinSourceGenerator
* \brief A generator for cygwin source files
*/
-class cmCPackCygwinSourceGenerator : public cmCPackTarBZip2Generator
+class cmCPackCygwinSourceGenerator : public cmCPackArchiveGenerator
{
public:
- cmCPackTypeMacro(cmCPackCygwinSourceGenerator, cmCPackTarBZip2Generator);
+ cmCPackTypeMacro(cmCPackCygwinSourceGenerator, cmCPackArchiveGenerator);
/**
* Construct generator
*/
cmCPackCygwinSourceGenerator();
- virtual ~cmCPackCygwinSourceGenerator();
+ ~cmCPackCygwinSourceGenerator() override;
protected:
const char* GetPackagingInstallPrefix();
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index af54fce33..5b7d8fb68 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -2,44 +2,444 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackDebGenerator.h"
+#include <cstring>
+#include <map>
+#include <ostream>
+#include <set>
+#include <utility>
+
+#include "cmsys/Glob.hxx"
+
+#include "cm_sys_stat.h"
+
#include "cmArchiveWrite.h"
#include "cmCPackComponentGroup.h"
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
+#include "cmCryptoHash.h"
#include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cm_sys_stat.h"
-#include "cmsys/Glob.hxx"
-#include <limits.h>
-#include <map>
-#include <ostream>
-#include <set>
-#include <stdio.h>
-#include <string.h>
-#include <utility>
+namespace {
+
+class DebGenerator
+{
+public:
+ DebGenerator(cmCPackLog* logger, std::string outputName, std::string workDir,
+ std::string topLevelDir, std::string temporaryDir,
+ const char* debianCompressionType,
+ const char* debianArchiveType,
+ std::map<std::string, std::string> controlValues,
+ bool genShLibs, std::string shLibsFilename, bool genPostInst,
+ std::string postInst, bool genPostRm, std::string postRm,
+ const char* controlExtra, bool permissionStrctPolicy,
+ std::vector<std::string> packageFiles);
+
+ bool generate() const;
+
+private:
+ void generateDebianBinaryFile() const;
+ void generateControlFile() const;
+ bool generateDataTar() const;
+ std::string generateMD5File() const;
+ bool generateControlTar(std::string const& md5Filename) const;
+ bool generateDeb() const;
+
+ cmCPackLog* Logger;
+ const std::string OutputName;
+ const std::string WorkDir;
+ std::string CompressionSuffix;
+ const std::string TopLevelDir;
+ const std::string TemporaryDir;
+ const char* DebianArchiveType;
+ const std::map<std::string, std::string> ControlValues;
+ const bool GenShLibs;
+ const std::string ShLibsFilename;
+ const bool GenPostInst;
+ const std::string PostInst;
+ const bool GenPostRm;
+ const std::string PostRm;
+ const char* ControlExtra;
+ const bool PermissionStrictPolicy;
+ const std::vector<std::string> PackageFiles;
+ cmArchiveWrite::Compress TarCompressionType;
+};
+
+DebGenerator::DebGenerator(
+ cmCPackLog* logger, std::string outputName, std::string workDir,
+ std::string topLevelDir, std::string temporaryDir,
+ const char* debianCompressionType, const char* debianArchiveType,
+ std::map<std::string, std::string> controlValues, bool genShLibs,
+ std::string shLibsFilename, bool genPostInst, std::string postInst,
+ bool genPostRm, std::string postRm, const char* controlExtra,
+ bool permissionStrictPolicy, std::vector<std::string> packageFiles)
+ : Logger(logger)
+ , OutputName(std::move(outputName))
+ , WorkDir(std::move(workDir))
+ , TopLevelDir(std::move(topLevelDir))
+ , TemporaryDir(std::move(temporaryDir))
+ , DebianArchiveType(debianArchiveType ? debianArchiveType : "gnutar")
+ , ControlValues(std::move(controlValues))
+ , GenShLibs(genShLibs)
+ , ShLibsFilename(std::move(shLibsFilename))
+ , GenPostInst(genPostInst)
+ , PostInst(std::move(postInst))
+ , GenPostRm(genPostRm)
+ , PostRm(std::move(postRm))
+ , ControlExtra(controlExtra)
+ , PermissionStrictPolicy(permissionStrictPolicy)
+ , PackageFiles(std::move(packageFiles))
+{
+ if (!debianCompressionType) {
+ debianCompressionType = "gzip";
+ }
+
+ if (!strcmp(debianCompressionType, "lzma")) {
+ CompressionSuffix = ".lzma";
+ TarCompressionType = cmArchiveWrite::CompressLZMA;
+ } else if (!strcmp(debianCompressionType, "xz")) {
+ CompressionSuffix = ".xz";
+ TarCompressionType = cmArchiveWrite::CompressXZ;
+ } else if (!strcmp(debianCompressionType, "bzip2")) {
+ CompressionSuffix = ".bz2";
+ TarCompressionType = cmArchiveWrite::CompressBZip2;
+ } else if (!strcmp(debianCompressionType, "gzip")) {
+ CompressionSuffix = ".gz";
+ TarCompressionType = cmArchiveWrite::CompressGZip;
+ } else if (!strcmp(debianCompressionType, "none")) {
+ CompressionSuffix.clear();
+ TarCompressionType = cmArchiveWrite::CompressNone;
+ } else {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error unrecognized compression type: "
+ << debianCompressionType << std::endl);
+ }
+}
+
+bool DebGenerator::generate() const
+{
+ generateDebianBinaryFile();
+ generateControlFile();
+ if (!generateDataTar()) {
+ return false;
+ }
+ std::string md5Filename = generateMD5File();
+ if (!generateControlTar(md5Filename)) {
+ return false;
+ }
+ return generateDeb();
+}
+
+void DebGenerator::generateDebianBinaryFile() const
+{
+ // debian-binary file
+ const std::string dbfilename = WorkDir + "/debian-binary";
+ cmGeneratedFileStream out(dbfilename);
+ out << "2.0";
+ out << std::endl; // required for valid debian package
+}
+
+void DebGenerator::generateControlFile() const
+{
+ std::string ctlfilename = WorkDir + "/control";
+
+ cmGeneratedFileStream out(ctlfilename);
+ for (auto const& kv : ControlValues) {
+ out << kv.first << ": " << kv.second << "\n";
+ }
-// NOTE:
-// A debian package .deb is simply an 'ar' archive. The only subtle difference
-// is that debian uses the BSD ar style archive whereas most Linux distro have
-// a GNU ar.
-// See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=161593 for more info
-// Therefore we provide our own implementation of a BSD-ar:
-static int ar_append(const char* archive,
- const std::vector<std::string>& files);
+ unsigned long totalSize = 0;
+ {
+ std::string dirName = cmStrCat(TemporaryDir, '/');
+ for (std::string const& file : PackageFiles) {
+ totalSize += cmSystemTools::FileLength(file);
+ }
+ }
+ out << "Installed-Size: " << (totalSize + 1023) / 1024 << "\n";
+ out << std::endl;
+}
-cmCPackDebGenerator::cmCPackDebGenerator()
+bool DebGenerator::generateDataTar() const
{
+ std::string filename_data_tar = WorkDir + "/data.tar" + CompressionSuffix;
+ cmGeneratedFileStream fileStream_data_tar;
+ fileStream_data_tar.Open(filename_data_tar, false, true);
+ if (!fileStream_data_tar) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error opening the file \""
+ << filename_data_tar << "\" for writing" << std::endl);
+ return false;
+ }
+ cmArchiveWrite data_tar(fileStream_data_tar, TarCompressionType,
+ DebianArchiveType);
+
+ // uid/gid should be the one of the root user, and this root user has
+ // always uid/gid equal to 0.
+ data_tar.SetUIDAndGID(0u, 0u);
+ data_tar.SetUNAMEAndGNAME("root", "root");
+
+ // now add all directories which have to be compressed
+ // collect all top level install dirs for that
+ // e.g. /opt/bin/foo, /usr/bin/bar and /usr/bin/baz would
+ // give /usr and /opt
+ size_t topLevelLength = WorkDir.length();
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "WDIR: \"" << WorkDir << "\", length = " << topLevelLength
+ << std::endl);
+ std::set<std::string> orderedFiles;
+
+ // we have to reconstruct the parent folders as well
+
+ for (std::string currentPath : PackageFiles) {
+ while (currentPath != WorkDir) {
+ // the last one IS WorkDir, but we do not want this one:
+ // XXX/application/usr/bin/myprogram with GEN_WDIR=XXX/application
+ // should not add XXX/application
+ orderedFiles.insert(currentPath);
+ currentPath = cmSystemTools::CollapseFullPath("..", currentPath);
+ }
+ }
+
+ for (std::string const& file : orderedFiles) {
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "FILEIT: \"" << file << "\"" << std::endl);
+ std::string::size_type slashPos = file.find('/', topLevelLength + 1);
+ std::string relativeDir =
+ file.substr(topLevelLength, slashPos - topLevelLength);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "RELATIVEDIR: \"" << relativeDir << "\"" << std::endl);
+
+#ifdef WIN32
+ std::string mode_t_adt_filename = file + ":cmake_mode_t";
+ cmsys::ifstream permissionStream(mode_t_adt_filename.c_str());
+
+ mode_t permissions = 0;
+
+ if (permissionStream) {
+ permissionStream >> std::oct >> permissions;
+ }
+
+ if (permissions != 0) {
+ data_tar.SetPermissions(permissions);
+ } else if (cmSystemTools::FileIsDirectory(file)) {
+ data_tar.SetPermissions(0755);
+ } else {
+ data_tar.ClearPermissions();
+ }
+#endif
+
+ // do not recurse because the loop will do it
+ if (!data_tar.Add(file, topLevelLength, ".", false)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem adding file to tar:"
+ << std::endl
+ << "#top level directory: " << WorkDir << std::endl
+ << "#file: " << file << std::endl
+ << "#error:" << data_tar.GetError() << std::endl);
+ return false;
+ }
+ }
+ return true;
}
-cmCPackDebGenerator::~cmCPackDebGenerator()
+std::string DebGenerator::generateMD5File() const
{
+ std::string md5filename = WorkDir + "/md5sums";
+
+ cmGeneratedFileStream out(md5filename);
+
+ std::string topLevelWithTrailingSlash = cmStrCat(TemporaryDir, '/');
+ for (std::string const& file : PackageFiles) {
+ // hash only regular files
+ if (cmSystemTools::FileIsDirectory(file) ||
+ cmSystemTools::FileIsSymlink(file)) {
+ continue;
+ }
+
+ std::string output =
+ cmSystemTools::ComputeFileHash(file, cmCryptoHash::AlgoMD5);
+ if (output.empty()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem computing the md5 of " << file << std::endl);
+ }
+
+ output += " " + file + "\n";
+ // debian md5sums entries are like this:
+ // 014f3604694729f3bf19263bac599765 usr/bin/ccmake
+ // thus strip the full path (with the trailing slash)
+ cmSystemTools::ReplaceString(output, topLevelWithTrailingSlash.c_str(),
+ "");
+ out << output;
+ }
+ // each line contains a eol.
+ // Do not end the md5sum file with yet another (invalid)
+ return md5filename;
}
+bool DebGenerator::generateControlTar(std::string const& md5Filename) const
+{
+ std::string filename_control_tar = WorkDir + "/control.tar.gz";
+
+ cmGeneratedFileStream fileStream_control_tar;
+ fileStream_control_tar.Open(filename_control_tar, false, true);
+ if (!fileStream_control_tar) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error opening the file \""
+ << filename_control_tar << "\" for writing" << std::endl);
+ return false;
+ }
+ cmArchiveWrite control_tar(fileStream_control_tar,
+ cmArchiveWrite::CompressGZip, DebianArchiveType);
+
+ // sets permissions and uid/gid for the files
+ control_tar.SetUIDAndGID(0u, 0u);
+ control_tar.SetUNAMEAndGNAME("root", "root");
+
+ /* permissions are set according to
+ https://www.debian.org/doc/debian-policy/ch-files.html#s-permissions-owners
+ and
+ https://lintian.debian.org/tags/control-file-has-bad-permissions.html
+ */
+ const mode_t permission644 = 0644;
+ const mode_t permissionExecute = 0111;
+ const mode_t permission755 = permission644 | permissionExecute;
+
+ // for md5sum and control (that we have generated here), we use 644
+ // (RW-R--R--)
+ // so that deb lintian doesn't warn about it
+ control_tar.SetPermissions(permission644);
+
+ // adds control and md5sums
+ if (!control_tar.Add(md5Filename, WorkDir.length(), ".") ||
+ !control_tar.Add(WorkDir + "/control", WorkDir.length(), ".")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error adding file to tar:"
+ << std::endl
+ << "#top level directory: " << WorkDir << std::endl
+ << "#file: \"control\" or \"md5sums\"" << std::endl
+ << "#error:" << control_tar.GetError() << std::endl);
+ return false;
+ }
+
+ // adds generated shlibs file
+ if (GenShLibs) {
+ if (!control_tar.Add(ShLibsFilename, WorkDir.length(), ".")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error adding file to tar:"
+ << std::endl
+ << "#top level directory: " << WorkDir << std::endl
+ << "#file: \"shlibs\"" << std::endl
+ << "#error:" << control_tar.GetError() << std::endl);
+ return false;
+ }
+ }
+
+ // adds LDCONFIG related files
+ if (GenPostInst) {
+ control_tar.SetPermissions(permission755);
+ if (!control_tar.Add(PostInst, WorkDir.length(), ".")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error adding file to tar:"
+ << std::endl
+ << "#top level directory: " << WorkDir << std::endl
+ << "#file: \"postinst\"" << std::endl
+ << "#error:" << control_tar.GetError() << std::endl);
+ return false;
+ }
+ control_tar.SetPermissions(permission644);
+ }
+
+ if (GenPostRm) {
+ control_tar.SetPermissions(permission755);
+ if (!control_tar.Add(PostRm, WorkDir.length(), ".")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error adding file to tar:"
+ << std::endl
+ << "#top level directory: " << WorkDir << std::endl
+ << "#file: \"postinst\"" << std::endl
+ << "#error:" << control_tar.GetError() << std::endl);
+ return false;
+ }
+ control_tar.SetPermissions(permission644);
+ }
+
+ // for the other files, we use
+ // -either the original permission on the files
+ // -either a permission strictly defined by the Debian policies
+ if (ControlExtra) {
+ // permissions are now controlled by the original file permissions
+
+ static const char* strictFiles[] = { "config", "postinst", "postrm",
+ "preinst", "prerm" };
+ std::set<std::string> setStrictFiles(
+ strictFiles, strictFiles + sizeof(strictFiles) / sizeof(strictFiles[0]));
+
+ // default
+ control_tar.ClearPermissions();
+
+ std::vector<std::string> controlExtraList = cmExpandedList(ControlExtra);
+ for (std::string const& i : controlExtraList) {
+ std::string filenamename = cmsys::SystemTools::GetFilenameName(i);
+ std::string localcopy = WorkDir + "/" + filenamename;
+
+ if (PermissionStrictPolicy) {
+ control_tar.SetPermissions(
+ setStrictFiles.count(filenamename) ? permission755 : permission644);
+ }
+
+ // if we can copy the file, it means it does exist, let's add it:
+ if (cmsys::SystemTools::CopyFileIfDifferent(i, localcopy)) {
+ control_tar.Add(localcopy, WorkDir.length(), ".");
+ }
+ }
+ }
+
+ return true;
+}
+
+bool DebGenerator::generateDeb() const
+{
+ // ar -r your-package-name.deb debian-binary control.tar.* data.tar.*
+ // A debian package .deb is simply an 'ar' archive. The only subtle
+ // difference is that debian uses the BSD ar style archive whereas most
+ // Linux distro have a GNU ar.
+ // See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=161593 for more info
+ std::string const outputPath = TopLevelDir + "/" + OutputName;
+ std::string const tlDir = WorkDir + "/";
+ cmGeneratedFileStream debStream;
+ debStream.Open(outputPath, false, true);
+ cmArchiveWrite deb(debStream, cmArchiveWrite::CompressNone, "arbsd");
+
+ // uid/gid should be the one of the root user, and this root user has
+ // always uid/gid equal to 0.
+ deb.SetUIDAndGID(0u, 0u);
+ deb.SetUNAMEAndGNAME("root", "root");
+
+ if (!deb.Add(tlDir + "debian-binary", tlDir.length()) ||
+ !deb.Add(tlDir + "control.tar.gz", tlDir.length()) ||
+ !deb.Add(tlDir + "data.tar" + CompressionSuffix, tlDir.length())) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error creating debian package:"
+ << std::endl
+ << "#top level directory: " << TopLevelDir << std::endl
+ << "#file: " << OutputName << std::endl
+ << "#error:" << deb.GetError() << std::endl);
+ return false;
+ }
+ return true;
+}
+
+} // end anonymous namespace
+
+cmCPackDebGenerator::cmCPackDebGenerator() = default;
+
+cmCPackDebGenerator::~cmCPackDebGenerator() = default;
+
int cmCPackDebGenerator::InitializeInternal()
{
this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/usr");
- if (cmSystemTools::IsOff(this->GetOption("CPACK_SET_DESTDIR"))) {
+ if (cmIsOff(this->GetOption("CPACK_SET_DESTDIR"))) {
this->SetOption("CPACK_SET_DESTDIR", "I_ON");
}
return this->Superclass::InitializeInternal();
@@ -68,39 +468,65 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel,
// Tell CPackDeb.cmake the name of the component GROUP.
this->SetOption("CPACK_DEB_PACKAGE_COMPONENT", packageName.c_str());
// Tell CPackDeb.cmake the path where the component is.
- std::string component_path = "/";
- component_path += packageName;
+ std::string component_path = cmStrCat('/', packageName);
this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH",
component_path.c_str());
- if (!this->ReadListFile("CPackDeb.cmake")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackDeb.cmake"
- << std::endl);
+ if (!this->ReadListFile("Internal/CPack/CPackDeb.cmake")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while execution CPackDeb.cmake" << std::endl);
retval = 0;
return retval;
}
- cmsys::Glob gl;
- std::string findExpr(this->GetOption("GEN_WDIR"));
- findExpr += "/*";
- gl.RecurseOn();
- gl.SetRecurseListDirs(true);
- if (!gl.FindFiles(findExpr)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot find any files in the installed directory"
- << std::endl);
- return 0;
+ { // Isolate globbing of binaries vs. dbgsyms
+ cmsys::Glob gl;
+ std::string findExpr(this->GetOption("GEN_WDIR"));
+ findExpr += "/*";
+ gl.RecurseOn();
+ gl.SetRecurseListDirs(true);
+ if (!gl.FindFiles(findExpr)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find any files in the installed directory"
+ << std::endl);
+ return 0;
+ }
+ packageFiles = gl.GetFiles();
}
- packageFiles = gl.GetFiles();
int res = createDeb();
if (res != 1) {
retval = 0;
}
// add the generated package to package file names list
- packageFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- packageFileName += "/";
- packageFileName += this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME");
- packageFileNames.push_back(packageFileName);
+ packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
+ this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"));
+ packageFileNames.push_back(std::move(packageFileName));
+
+ if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE")) {
+ cmsys::Glob gl;
+ std::string findExpr(this->GetOption("GEN_DBGSYMDIR"));
+ findExpr += "/*";
+ gl.RecurseOn();
+ gl.SetRecurseListDirs(true);
+ if (!gl.FindFiles(findExpr)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find any files in the installed directory"
+ << std::endl);
+ return 0;
+ }
+ packageFiles = gl.GetFiles();
+
+ res = createDbgsymDDeb();
+ if (res != 1) {
+ retval = 0;
+ }
+ // add the generated package to package file names list
+ packageFileName =
+ cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
+ this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"));
+ packageFileNames.push_back(std::move(packageFileName));
+ }
+
return retval;
}
@@ -115,37 +541,32 @@ int cmCPackDebGenerator::PackageComponents(bool ignoreGroup)
// The default behavior is to have one package by component group
// unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
if (!ignoreGroup) {
- std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
- for (compGIt = this->ComponentGroups.begin();
- compGIt != this->ComponentGroups.end(); ++compGIt) {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: "
- << compGIt->first << std::endl);
+ for (auto const& compG : this->ComponentGroups) {
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Packaging component group: " << compG.first << std::endl);
// Begin the archive for this group
- retval &= PackageOnePack(initialTopLevel, compGIt->first);
+ retval &= PackageOnePack(initialTopLevel, compG.first);
}
// Handle Orphan components (components not belonging to any groups)
- std::map<std::string, cmCPackComponent>::iterator compIt;
- for (compIt = this->Components.begin(); compIt != this->Components.end();
- ++compIt) {
+ for (auto const& comp : this->Components) {
// Does the component belong to a group?
- if (compIt->second.Group == CM_NULLPTR) {
+ if (comp.second.Group == nullptr) {
cmCPackLogger(
- cmCPackLog::LOG_VERBOSE, "Component <"
- << compIt->second.Name
+ cmCPackLog::LOG_VERBOSE,
+ "Component <"
+ << comp.second.Name
<< "> does not belong to any group, package it separately."
<< std::endl);
// Begin the archive for this orphan component
- retval &= PackageOnePack(initialTopLevel, compIt->first);
+ retval &= PackageOnePack(initialTopLevel, comp.first);
}
}
}
// CPACK_COMPONENTS_IGNORE_GROUPS is set
// We build 1 package per component
else {
- std::map<std::string, cmCPackComponent>::iterator compIt;
- for (compIt = this->Components.begin(); compIt != this->Components.end();
- ++compIt) {
- retval &= PackageOnePack(initialTopLevel, compIt->first);
+ for (auto const& comp : this->Components) {
+ retval &= PackageOnePack(initialTopLevel, comp.first);
}
}
return retval;
@@ -190,14 +611,13 @@ int cmCPackDebGenerator::PackageComponentsAllInOne(
if (!compInstDirName.empty()) {
// Tell CPackDeb.cmake the path where the component is.
- std::string component_path = "/";
- component_path += compInstDirName;
+ std::string component_path = cmStrCat('/', compInstDirName);
this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH",
component_path.c_str());
}
- if (!this->ReadListFile("CPackDeb.cmake")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackDeb.cmake"
- << std::endl);
+ if (!this->ReadListFile("Internal/CPack/CPackDeb.cmake")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while execution CPackDeb.cmake" << std::endl);
retval = 0;
return retval;
}
@@ -220,10 +640,9 @@ int cmCPackDebGenerator::PackageComponentsAllInOne(
retval = 0;
}
// add the generated package to package file names list
- packageFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- packageFileName += "/";
- packageFileName += this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME");
- packageFileNames.push_back(packageFileName);
+ packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
+ this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"));
+ packageFileNames.push_back(std::move(packageFileName));
return retval;
}
@@ -250,114 +669,81 @@ int cmCPackDebGenerator::PackageFiles()
int cmCPackDebGenerator::createDeb()
{
- // debian-binary file
- const std::string strGenWDIR(this->GetOption("GEN_WDIR"));
- const std::string dbfilename = strGenWDIR + "/debian-binary";
- { // the scope is needed for cmGeneratedFileStream
- cmGeneratedFileStream out(dbfilename.c_str());
- out << "2.0";
- out << std::endl; // required for valid debian package
- }
-
- // control file
- std::string ctlfilename = strGenWDIR + "/control";
+ std::map<std::string, std::string> controlValues;
// debian policy enforce lower case for package name
- // mandatory entries:
- std::string debian_pkg_name = cmsys::SystemTools::LowerCase(
+ controlValues["Package"] = cmsys::SystemTools::LowerCase(
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME"));
- const char* debian_pkg_version =
+ controlValues["Version"] =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_VERSION");
- const char* debian_pkg_section =
+ controlValues["Section"] =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SECTION");
- const char* debian_pkg_priority =
+ controlValues["Priority"] =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PRIORITY");
- const char* debian_pkg_arch =
+ controlValues["Architecture"] =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE");
- const char* maintainer =
+ controlValues["Maintainer"] =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER");
- const char* desc = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DESCRIPTION");
+ controlValues["Description"] =
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DESCRIPTION");
- // optional entries
+ const char* debian_pkg_source =
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE");
+ if (debian_pkg_source && *debian_pkg_source) {
+ controlValues["Source"] = debian_pkg_source;
+ }
const char* debian_pkg_dep =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DEPENDS");
+ if (debian_pkg_dep && *debian_pkg_dep) {
+ controlValues["Depends"] = debian_pkg_dep;
+ }
const char* debian_pkg_rec =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_RECOMMENDS");
+ if (debian_pkg_rec && *debian_pkg_rec) {
+ controlValues["Recommends"] = debian_pkg_rec;
+ }
const char* debian_pkg_sug =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SUGGESTS");
+ if (debian_pkg_sug && *debian_pkg_sug) {
+ controlValues["Suggests"] = debian_pkg_sug;
+ }
const char* debian_pkg_url =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_HOMEPAGE");
+ if (debian_pkg_url && *debian_pkg_url) {
+ controlValues["Homepage"] = debian_pkg_url;
+ }
const char* debian_pkg_predep =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PREDEPENDS");
+ if (debian_pkg_predep && *debian_pkg_predep) {
+ controlValues["Pre-Depends"] = debian_pkg_predep;
+ }
const char* debian_pkg_enhances =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ENHANCES");
+ if (debian_pkg_enhances && *debian_pkg_enhances) {
+ controlValues["Enhances"] = debian_pkg_enhances;
+ }
const char* debian_pkg_breaks =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_BREAKS");
+ if (debian_pkg_breaks && *debian_pkg_breaks) {
+ controlValues["Breaks"] = debian_pkg_breaks;
+ }
const char* debian_pkg_conflicts =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONFLICTS");
+ if (debian_pkg_conflicts && *debian_pkg_conflicts) {
+ controlValues["Conflicts"] = debian_pkg_conflicts;
+ }
const char* debian_pkg_provides =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PROVIDES");
+ if (debian_pkg_provides && *debian_pkg_provides) {
+ controlValues["Provides"] = debian_pkg_provides;
+ }
const char* debian_pkg_replaces =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_REPLACES");
- const char* debian_pkg_source =
- this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE");
-
- { // the scope is needed for cmGeneratedFileStream
- cmGeneratedFileStream out(ctlfilename.c_str());
- out << "Package: " << debian_pkg_name << "\n";
- out << "Version: " << debian_pkg_version << "\n";
- out << "Section: " << debian_pkg_section << "\n";
- out << "Priority: " << debian_pkg_priority << "\n";
- out << "Architecture: " << debian_pkg_arch << "\n";
- if (debian_pkg_source && *debian_pkg_source) {
- out << "Source: " << debian_pkg_source << "\n";
- }
- if (debian_pkg_dep && *debian_pkg_dep) {
- out << "Depends: " << debian_pkg_dep << "\n";
- }
- if (debian_pkg_rec && *debian_pkg_rec) {
- out << "Recommends: " << debian_pkg_rec << "\n";
- }
- if (debian_pkg_sug && *debian_pkg_sug) {
- out << "Suggests: " << debian_pkg_sug << "\n";
- }
- if (debian_pkg_url && *debian_pkg_url) {
- out << "Homepage: " << debian_pkg_url << "\n";
- }
- if (debian_pkg_predep && *debian_pkg_predep) {
- out << "Pre-Depends: " << debian_pkg_predep << "\n";
- }
- if (debian_pkg_enhances && *debian_pkg_enhances) {
- out << "Enhances: " << debian_pkg_enhances << "\n";
- }
- if (debian_pkg_breaks && *debian_pkg_breaks) {
- out << "Breaks: " << debian_pkg_breaks << "\n";
- }
- if (debian_pkg_conflicts && *debian_pkg_conflicts) {
- out << "Conflicts: " << debian_pkg_conflicts << "\n";
- }
- if (debian_pkg_provides && *debian_pkg_provides) {
- out << "Provides: " << debian_pkg_provides << "\n";
- }
- if (debian_pkg_replaces && *debian_pkg_replaces) {
- out << "Replaces: " << debian_pkg_replaces << "\n";
- }
- unsigned long totalSize = 0;
- {
- std::string dirName = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
- dirName += '/';
- for (std::vector<std::string>::const_iterator fileIt =
- packageFiles.begin();
- fileIt != packageFiles.end(); ++fileIt) {
- totalSize += cmSystemTools::FileLength(*fileIt);
- }
- }
- out << "Installed-Size: " << (totalSize + 1023) / 1024 << "\n";
- out << "Maintainer: " << maintainer << "\n";
- out << "Description: " << desc << "\n";
- out << std::endl;
+ if (debian_pkg_replaces && *debian_pkg_replaces) {
+ controlValues["Replaces"] = debian_pkg_replaces;
}
+ const std::string strGenWDIR(this->GetOption("GEN_WDIR"));
const std::string shlibsfilename = strGenWDIR + "/shlibs";
const char* debian_pkg_shlibs =
@@ -365,7 +751,7 @@ int cmCPackDebGenerator::createDeb()
const bool gen_shibs = this->IsOn("CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS") &&
debian_pkg_shlibs && *debian_pkg_shlibs;
if (gen_shibs) {
- cmGeneratedFileStream out(shlibsfilename.c_str());
+ cmGeneratedFileStream out(shlibsfilename);
out << debian_pkg_shlibs;
out << std::endl;
}
@@ -373,7 +759,7 @@ int cmCPackDebGenerator::createDeb()
const std::string postinst = strGenWDIR + "/postinst";
const std::string postrm = strGenWDIR + "/postrm";
if (this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTINST")) {
- cmGeneratedFileStream out(postinst.c_str());
+ cmGeneratedFileStream out(postinst);
out << "#!/bin/sh\n\n"
"set -e\n\n"
"if [ \"$1\" = \"configure\" ]; then\n"
@@ -381,7 +767,7 @@ int cmCPackDebGenerator::createDeb()
"fi\n";
}
if (this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTRM")) {
- cmGeneratedFileStream out(postrm.c_str());
+ cmGeneratedFileStream out(postrm);
out << "#!/bin/sh\n\n"
"set -e\n\n"
"if [ \"$1\" = \"remove\" ]; then\n"
@@ -389,288 +775,74 @@ int cmCPackDebGenerator::createDeb()
"fi\n";
}
- cmArchiveWrite::Compress tar_compression_type = cmArchiveWrite::CompressGZip;
- const char* debian_compression_type =
- this->GetOption("GEN_CPACK_DEBIAN_COMPRESSION_TYPE");
- if (!debian_compression_type) {
- debian_compression_type = "gzip";
- }
-
- std::string compression_suffix;
- if (!strcmp(debian_compression_type, "lzma")) {
- compression_suffix = ".lzma";
- tar_compression_type = cmArchiveWrite::CompressLZMA;
- } else if (!strcmp(debian_compression_type, "xz")) {
- compression_suffix = ".xz";
- tar_compression_type = cmArchiveWrite::CompressXZ;
- } else if (!strcmp(debian_compression_type, "bzip2")) {
- compression_suffix = ".bz2";
- tar_compression_type = cmArchiveWrite::CompressBZip2;
- } else if (!strcmp(debian_compression_type, "gzip")) {
- compression_suffix = ".gz";
- tar_compression_type = cmArchiveWrite::CompressGZip;
- } else if (!strcmp(debian_compression_type, "none")) {
- compression_suffix = "";
- tar_compression_type = cmArchiveWrite::CompressNone;
- } else {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error unrecognized compression type: "
- << debian_compression_type << std::endl);
- }
+ DebGenerator gen(
+ Logger, this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"), strGenWDIR,
+ this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
+ this->GetOption("CPACK_TEMPORARY_DIRECTORY"),
+ this->GetOption("GEN_CPACK_DEBIAN_COMPRESSION_TYPE"),
+ this->GetOption("GEN_CPACK_DEBIAN_ARCHIVE_TYPE"), controlValues, gen_shibs,
+ shlibsfilename, this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTINST"), postinst,
+ this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTRM"), postrm,
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA"),
+ this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION"),
+ packageFiles);
- const char* debian_archive_type =
- this->GetOption("GEN_CPACK_DEBIAN_ARCHIVE_TYPE");
- if (!debian_archive_type) {
- debian_archive_type = "paxr";
+ if (!gen.generate()) {
+ return 0;
}
+ return 1;
+}
- std::string filename_data_tar =
- strGenWDIR + "/data.tar" + compression_suffix;
-
- // atomic file generation for data.tar
- {
- cmGeneratedFileStream fileStream_data_tar;
- fileStream_data_tar.Open(filename_data_tar.c_str(), false, true);
- if (!fileStream_data_tar) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error opening the file \""
- << filename_data_tar << "\" for writing" << std::endl);
- return 0;
- }
- cmArchiveWrite data_tar(fileStream_data_tar, tar_compression_type,
- debian_archive_type);
-
- // uid/gid should be the one of the root user, and this root user has
- // always uid/gid equal to 0.
- data_tar.SetUIDAndGID(0u, 0u);
- data_tar.SetUNAMEAndGNAME("root", "root");
-
- // now add all directories which have to be compressed
- // collect all top level install dirs for that
- // e.g. /opt/bin/foo, /usr/bin/bar and /usr/bin/baz would
- // give /usr and /opt
- size_t topLevelLength = strGenWDIR.length();
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "WDIR: \""
- << strGenWDIR << "\", length = " << topLevelLength
- << std::endl);
- std::set<std::string> orderedFiles;
-
- // we have to reconstruct the parent folders as well
-
- for (std::vector<std::string>::const_iterator fileIt =
- packageFiles.begin();
- fileIt != packageFiles.end(); ++fileIt) {
- std::string currentPath = *fileIt;
- while (currentPath != strGenWDIR) {
- // the last one IS strGenWDIR, but we do not want this one:
- // XXX/application/usr/bin/myprogram with GEN_WDIR=XXX/application
- // should not add XXX/application
- orderedFiles.insert(currentPath);
- currentPath = cmSystemTools::CollapseCombinedPath(currentPath, "..");
- }
- }
-
- for (std::set<std::string>::const_iterator fileIt = orderedFiles.begin();
- fileIt != orderedFiles.end(); ++fileIt) {
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "FILEIT: \"" << *fileIt << "\""
- << std::endl);
- std::string::size_type slashPos = fileIt->find('/', topLevelLength + 1);
- std::string relativeDir =
- fileIt->substr(topLevelLength, slashPos - topLevelLength);
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "RELATIVEDIR: \""
- << relativeDir << "\"" << std::endl);
-
- // do not recurse because the loop will do it
- if (!data_tar.Add(*fileIt, topLevelLength, ".", false)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem adding file to tar:"
- << std::endl
- << "#top level directory: " << strGenWDIR << std::endl
- << "#file: " << *fileIt << std::endl
- << "#error:" << data_tar.GetError() << std::endl);
- return 0;
- }
- }
- } // scope for file generation
-
- std::string md5filename = strGenWDIR + "/md5sums";
- {
- // the scope is needed for cmGeneratedFileStream
- cmGeneratedFileStream out(md5filename.c_str());
-
- std::string topLevelWithTrailingSlash =
- this->GetOption("CPACK_TEMPORARY_DIRECTORY");
- topLevelWithTrailingSlash += '/';
- for (std::vector<std::string>::const_iterator fileIt =
- packageFiles.begin();
- fileIt != packageFiles.end(); ++fileIt) {
- // hash only regular files
- if (cmSystemTools::FileIsDirectory(*fileIt) ||
- cmSystemTools::FileIsSymlink(*fileIt)) {
- continue;
- }
+int cmCPackDebGenerator::createDbgsymDDeb()
+{
+ // Packages containing debug symbols follow the same structure as .debs
+ // but have different metadata and content.
- char md5sum[33];
- if (!cmSystemTools::ComputeFileMD5(*fileIt, md5sum)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem computing the md5 of "
- << *fileIt << std::endl);
- }
+ std::map<std::string, std::string> controlValues;
+ // debian policy enforce lower case for package name
+ std::string packageNameLower = cmsys::SystemTools::LowerCase(
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME"));
+ const char* debian_pkg_version =
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_VERSION");
- md5sum[32] = 0;
+ controlValues["Package"] = packageNameLower + "-dbgsym";
+ controlValues["Package-Type"] = "ddeb";
+ controlValues["Version"] = debian_pkg_version;
+ controlValues["Auto-Built-Package"] = "debug-symbols";
+ controlValues["Depends"] = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME") +
+ std::string(" (= ") + debian_pkg_version + ")";
+ controlValues["Section"] = "debug";
+ controlValues["Priority"] = "optional";
+ controlValues["Architecture"] =
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE");
+ controlValues["Maintainer"] =
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER");
+ controlValues["Description"] =
+ std::string("debug symbols for ") + packageNameLower;
- std::string output(md5sum);
- output += " " + *fileIt + "\n";
- // debian md5sums entries are like this:
- // 014f3604694729f3bf19263bac599765 usr/bin/ccmake
- // thus strip the full path (with the trailing slash)
- cmSystemTools::ReplaceString(output, topLevelWithTrailingSlash.c_str(),
- "");
- out << output;
- }
- // each line contains a eol.
- // Do not end the md5sum file with yet another (invalid)
+ const char* debian_pkg_source =
+ this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE");
+ if (debian_pkg_source && *debian_pkg_source) {
+ controlValues["Source"] = debian_pkg_source;
+ }
+ const char* debian_build_ids = this->GetOption("GEN_BUILD_IDS");
+ if (debian_build_ids && *debian_build_ids) {
+ controlValues["Build-Ids"] = debian_build_ids;
}
- std::string filename_control_tar = strGenWDIR + "/control.tar.gz";
- // atomic file generation for control.tar
- {
- cmGeneratedFileStream fileStream_control_tar;
- fileStream_control_tar.Open(filename_control_tar.c_str(), false, true);
- if (!fileStream_control_tar) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error opening the file \""
- << filename_control_tar << "\" for writing"
- << std::endl);
- return 0;
- }
- cmArchiveWrite control_tar(fileStream_control_tar,
- cmArchiveWrite::CompressGZip,
- debian_archive_type);
-
- // sets permissions and uid/gid for the files
- control_tar.SetUIDAndGID(0u, 0u);
- control_tar.SetUNAMEAndGNAME("root", "root");
-
- /* permissions are set according to
- https://www.debian.org/doc/debian-policy/ch-files.html#s-permissions-owners
- and
- https://lintian.debian.org/tags/control-file-has-bad-permissions.html
- */
- const mode_t permission644 = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
- const mode_t permissionExecute = S_IXUSR | S_IXGRP | S_IXOTH;
- const mode_t permission755 = permission644 | permissionExecute;
-
- // for md5sum and control (that we have generated here), we use 644
- // (RW-R--R--)
- // so that deb lintian doesn't warn about it
- control_tar.SetPermissions(permission644);
-
- // adds control and md5sums
- if (!control_tar.Add(md5filename, strGenWDIR.length(), ".") ||
- !control_tar.Add(strGenWDIR + "/control", strGenWDIR.length(), ".")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error adding file to tar:"
- << std::endl
- << "#top level directory: " << strGenWDIR << std::endl
- << "#file: \"control\" or \"md5sums\"" << std::endl
- << "#error:" << control_tar.GetError() << std::endl);
- return 0;
- }
-
- // adds generated shlibs file
- if (gen_shibs) {
- if (!control_tar.Add(shlibsfilename, strGenWDIR.length(), ".")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error adding file to tar:"
- << std::endl
- << "#top level directory: " << strGenWDIR << std::endl
- << "#file: \"shlibs\"" << std::endl
- << "#error:" << control_tar.GetError() << std::endl);
- return 0;
- }
- }
+ DebGenerator gen(
+ Logger, this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"),
+ this->GetOption("GEN_DBGSYMDIR"),
- // adds LDCONFIG related files
- if (this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTINST")) {
- control_tar.SetPermissions(permission755);
- if (!control_tar.Add(postinst, strGenWDIR.length(), ".")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error adding file to tar:"
- << std::endl
- << "#top level directory: " << strGenWDIR << std::endl
- << "#file: \"postinst\"" << std::endl
- << "#error:" << control_tar.GetError() << std::endl);
- return 0;
- }
- control_tar.SetPermissions(permission644);
- }
+ this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
+ this->GetOption("CPACK_TEMPORARY_DIRECTORY"),
+ this->GetOption("GEN_CPACK_DEBIAN_COMPRESSION_TYPE"),
+ this->GetOption("GEN_CPACK_DEBIAN_ARCHIVE_TYPE"), controlValues, false, "",
+ false, "", false, "", nullptr,
+ this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION"),
+ packageFiles);
- if (this->IsOn("GEN_CPACK_DEBIAN_GENERATE_POSTRM")) {
- control_tar.SetPermissions(permission755);
- if (!control_tar.Add(postrm, strGenWDIR.length(), ".")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error adding file to tar:"
- << std::endl
- << "#top level directory: " << strGenWDIR << std::endl
- << "#file: \"postinst\"" << std::endl
- << "#error:" << control_tar.GetError() << std::endl);
- return 0;
- }
- control_tar.SetPermissions(permission644);
- }
-
- // for the other files, we use
- // -either the original permission on the files
- // -either a permission strictly defined by the Debian policies
- const char* controlExtra =
- this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA");
- if (controlExtra) {
- // permissions are now controlled by the original file permissions
-
- const bool permissionStrictPolicy =
- this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION");
-
- static const char* strictFiles[] = { "config", "postinst", "postrm",
- "preinst", "prerm" };
- std::set<std::string> setStrictFiles(
- strictFiles,
- strictFiles + sizeof(strictFiles) / sizeof(strictFiles[0]));
-
- // default
- control_tar.ClearPermissions();
-
- std::vector<std::string> controlExtraList;
- cmSystemTools::ExpandListArgument(controlExtra, controlExtraList);
- for (std::vector<std::string>::iterator i = controlExtraList.begin();
- i != controlExtraList.end(); ++i) {
- std::string filenamename = cmsys::SystemTools::GetFilenameName(*i);
- std::string localcopy = strGenWDIR + "/" + filenamename;
-
- if (permissionStrictPolicy) {
- control_tar.SetPermissions(setStrictFiles.count(filenamename)
- ? permission755
- : permission644);
- }
-
- // if we can copy the file, it means it does exist, let's add it:
- if (cmsys::SystemTools::CopyFileIfDifferent(*i, localcopy)) {
- control_tar.Add(localcopy, strGenWDIR.length(), ".");
- }
- }
- }
- }
-
- // ar -r your-package-name.deb debian-binary control.tar.* data.tar.*
- // since debian packages require BSD ar (most Linux distros and even
- // FreeBSD and NetBSD ship GNU ar) we use a copy of OpenBSD ar here.
- std::vector<std::string> arFiles;
- std::string topLevelString = strGenWDIR + "/";
- arFiles.push_back(topLevelString + "debian-binary");
- arFiles.push_back(topLevelString + "control.tar.gz");
- arFiles.push_back(topLevelString + "data.tar" + compression_suffix);
- std::string outputFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- outputFileName += "/";
- outputFileName += this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME");
- int res = ar_append(outputFileName.c_str(), arFiles);
- if (res != 0) {
- std::string tmpFile =
- this->GetOption("GEN_CPACK_TEMPORARY_PACKAGE_FILE_NAME");
- tmpFile += "/Deb.log";
- cmGeneratedFileStream ofs(tmpFile.c_str());
- ofs << "# Problem creating archive using: " << res << std::endl;
+ if (!gen.generate()) {
return 0;
}
return 1;
@@ -695,252 +867,8 @@ std::string cmCPackDebGenerator::GetComponentInstallDirNameSuffix(
// the current COMPONENT belongs to.
std::string groupVar =
"CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP";
- if (CM_NULLPTR != GetOption(groupVar)) {
+ if (nullptr != GetOption(groupVar)) {
return std::string(GetOption(groupVar));
}
return componentName;
}
-
-// The following code is taken from OpenBSD ar:
-// http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ar/
-// It has been slightly modified:
-// -return error codes instead exit() in functions
-// -use the stdio file I/O functions instead the file descriptor based ones
-// -merged into one cxx file
-// -no additional options supported
-// The coding style hasn't been modified.
-
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Hugh Smith at The University of Guelph.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#define ARMAG "!<arch>\n" /* ar "magic number" */
-#define SARMAG 8 /* strlen(ARMAG); */
-
-#define AR_EFMT1 "#1/" /* extended format #1 */
-#define ARFMAG "`\n"
-
-/* Header format strings. */
-#define HDR1 "%s%-13d%-12ld%-6u%-6u%-8o%-10lld%2s"
-#define HDR2 "%-16.16s%-12ld%-6u%-6u%-8o%-10lld%2s"
-
-struct ar_hdr
-{
- char ar_name[16]; /* name */
- char ar_date[12]; /* modification time */
- char ar_uid[6]; /* user id */
- char ar_gid[6]; /* group id */
- char ar_mode[8]; /* octal file permissions */
- char ar_size[10]; /* size in bytes */
- char ar_fmag[2]; /* consistency check */
-};
-
-/* Set up file copy. */
-#define SETCF(from, fromname, to, toname, pad) \
- { \
- cf.rFile = from; \
- cf.rname = fromname; \
- cf.wFile = to; \
- cf.wname = toname; \
- cf.flags = pad; \
- }
-
-/* File copy structure. */
-typedef struct
-{
- FILE* rFile; /* read file descriptor */
- const char* rname; /* read name */
- FILE* wFile; /* write file descriptor */
- const char* wname; /* write name */
-#define NOPAD 0x00 /* don't pad */
-#define WPAD 0x02 /* pad on writes */
- unsigned int flags; /* pad flags */
-} CF;
-
-/* misc.c */
-
-static const char* ar_rname(const char* path)
-{
- const char* ind = strrchr(path, '/');
- return (ind) ? ind + 1 : path;
-}
-
-/* archive.c */
-
-typedef struct ar_hdr HDR;
-static char ar_hb[sizeof(HDR) + 1]; /* real header */
-
-static size_t ar_already_written;
-
-/* copy_ar --
- * Copy size bytes from one file to another - taking care to handle the
- * extra byte (for odd size files) when reading archives and writing an
- * extra byte if necessary when adding files to archive. The length of
- * the object is the long name plus the object itself; the variable
- * already_written gets set if a long name was written.
- *
- * The padding is really unnecessary, and is almost certainly a remnant
- * of early archive formats where the header included binary data which
- * a PDP-11 required to start on an even byte boundary. (Or, perhaps,
- * because 16-bit word addressed copies were faster?) Anyhow, it should
- * have been ripped out long ago.
- */
-static int copy_ar(CF* cfp, off_t size)
-{
- static char pad = '\n';
- off_t sz = size;
- size_t nr, nw;
- char buf[8 * 1024];
-
- if (sz == 0) {
- return 0;
- }
-
- FILE* from = cfp->rFile;
- FILE* to = cfp->wFile;
- while (sz &&
- (nr = fread(buf, 1, sz < static_cast<off_t>(sizeof(buf))
- ? static_cast<size_t>(sz)
- : sizeof(buf),
- from)) > 0) {
- sz -= nr;
- for (size_t off = 0; off < nr; nr -= off, off += nw) {
- if ((nw = fwrite(buf + off, 1, nr, to)) < nr) {
- return -1;
- }
- }
- }
- if (sz) {
- return -2;
- }
-
- if (cfp->flags & WPAD && (size + ar_already_written) & 1 &&
- fwrite(&pad, 1, 1, to) != 1) {
- return -4;
- }
-
- return 0;
-}
-
-/* put_arobj -- Write an archive member to a file. */
-static int put_arobj(CF* cfp, struct stat* sb)
-{
- int result = 0;
- struct ar_hdr* hdr;
-
- /* If passed an sb structure, reading a file from disk. Get stat(2)
- * information, build a name and construct a header. (Files are named
- * by their last component in the archive.) */
- const char* name = ar_rname(cfp->rname);
- (void)stat(cfp->rname, sb);
-
- /* If not truncating names and the name is too long or contains
- * a space, use extended format 1. */
- size_t lname = strlen(name);
- uid_t uid = sb->st_uid;
- gid_t gid = sb->st_gid;
- if (uid > USHRT_MAX) {
- uid = USHRT_MAX;
- }
- if (gid > USHRT_MAX) {
- gid = USHRT_MAX;
- }
- if (lname > sizeof(hdr->ar_name) || strchr(name, ' ')) {
- (void)sprintf(ar_hb, HDR1, AR_EFMT1, (int)lname, (long int)sb->st_mtime,
- (unsigned)uid, (unsigned)gid, (unsigned)sb->st_mode,
- (long long)sb->st_size + lname, ARFMAG);
- } else {
- lname = 0;
- (void)sprintf(ar_hb, HDR2, name, (long int)sb->st_mtime, (unsigned)uid,
- (unsigned)gid, (unsigned)sb->st_mode, (long long)sb->st_size,
- ARFMAG);
- }
- off_t size = sb->st_size;
-
- if (fwrite(ar_hb, 1, sizeof(HDR), cfp->wFile) != sizeof(HDR)) {
- return -1;
- }
-
- if (lname) {
- if (fwrite(name, 1, lname, cfp->wFile) != lname) {
- return -2;
- }
- ar_already_written = lname;
- }
- result = copy_ar(cfp, size);
- ar_already_written = 0;
- return result;
-}
-
-/* append.c */
-
-/* append --
- * Append files to the archive - modifies original archive or creates
- * a new archive if named archive does not exist.
- */
-static int ar_append(const char* archive,
- const std::vector<std::string>& files)
-{
- int eval = 0;
- FILE* aFile = cmSystemTools::Fopen(archive, "wb+");
- if (aFile != CM_NULLPTR) {
- fwrite(ARMAG, SARMAG, 1, aFile);
- if (fseek(aFile, 0, SEEK_END) != -1) {
- CF cf;
- struct stat sb;
- /* Read from disk, write to an archive; pad on write. */
- SETCF(CM_NULLPTR, CM_NULLPTR, aFile, archive, WPAD);
- for (std::vector<std::string>::const_iterator fileIt = files.begin();
- fileIt != files.end(); ++fileIt) {
- const char* filename = fileIt->c_str();
- FILE* file = cmSystemTools::Fopen(filename, "rb");
- if (file == CM_NULLPTR) {
- eval = -1;
- continue;
- }
- cf.rFile = file;
- cf.rname = filename;
- int result = put_arobj(&cf, &sb);
- (void)fclose(file);
- if (result != 0) {
- eval = -2;
- break;
- }
- }
- } else {
- eval = -3;
- }
- fclose(aFile);
- } else {
- eval = -4;
- }
- return eval;
-}
diff --git a/Source/CPack/cmCPackDebGenerator.h b/Source/CPack/cmCPackDebGenerator.h
index e7cde1145..ce77e0804 100644
--- a/Source/CPack/cmCPackDebGenerator.h
+++ b/Source/CPack/cmCPackDebGenerator.h
@@ -3,13 +3,13 @@
#ifndef cmCPackDebGenerator_h
#define cmCPackDebGenerator_h
-#include "cmConfigure.h"
-
-#include "cmCPackGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
+#include "cmCPackGenerator.h"
+
/** \class cmCPackDebGenerator
* \brief A generator for Debian packages
*
@@ -23,7 +23,7 @@ public:
* Construct generator
*/
cmCPackDebGenerator();
- ~cmCPackDebGenerator() CM_OVERRIDE;
+ ~cmCPackDebGenerator() override;
static bool CanGenerate()
{
@@ -40,7 +40,7 @@ public:
}
protected:
- int InitializeInternal() CM_OVERRIDE;
+ int InitializeInternal() override;
/**
* This method factors out the work done in component packaging case.
*/
@@ -57,14 +57,16 @@ protected:
* components will be put in a single installer.
*/
int PackageComponentsAllInOne(const std::string& compInstDirName);
- int PackageFiles() CM_OVERRIDE;
- const char* GetOutputExtension() CM_OVERRIDE { return ".deb"; }
- bool SupportsComponentInstallation() const CM_OVERRIDE;
+ int PackageFiles() override;
+ const char* GetOutputExtension() override { return ".deb"; }
+ bool SupportsComponentInstallation() const override;
std::string GetComponentInstallDirNameSuffix(
- const std::string& componentName) CM_OVERRIDE;
+ const std::string& componentName) override;
private:
int createDeb();
+ int createDbgsymDDeb();
+
std::vector<std::string> packageFiles;
};
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index d26d5bc1a..ea7100708 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -2,25 +2,28 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackDragNDropGenerator.h"
-#include "cmCPackGenerator.h"
-#include "cmCPackLog.h"
-#include "cmGeneratedFileStream.h"
-#include "cmSystemTools.h"
-
-#include "cmsys/FStream.hxx"
-#include "cmsys/RegularExpression.hxx"
#include <algorithm>
+#include <cstdlib>
#include <iomanip>
#include <map>
-#include <stdlib.h>
#include <CoreFoundation/CoreFoundation.h>
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmCPackGenerator.h"
+#include "cmCPackLog.h"
+#include "cmDuration.h"
+#include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
#ifdef HAVE_CoreServices
// For the old LocaleStringToLangAndRegionCodes() function, to convert
// to the old Script Manager RegionCode values needed for the 'LPic' data
// structure used for generating multi-lingual SLAs.
-#include <CoreServices/CoreServices.h>
+# include <CoreServices/CoreServices.h>
#endif
static const char* SLAHeader =
@@ -61,23 +64,21 @@ cmCPackDragNDropGenerator::cmCPackDragNDropGenerator()
this->componentPackageMethod = ONE_PACKAGE;
}
-cmCPackDragNDropGenerator::~cmCPackDragNDropGenerator()
-{
-}
+cmCPackDragNDropGenerator::~cmCPackDragNDropGenerator() = default;
int cmCPackDragNDropGenerator::InitializeInternal()
{
// Starting with Xcode 4.3, look in "/Applications/Xcode.app" first:
//
std::vector<std::string> paths;
- paths.push_back("/Applications/Xcode.app/Contents/Developer/Tools");
- paths.push_back("/Developer/Tools");
+ paths.emplace_back("/Applications/Xcode.app/Contents/Developer/Tools");
+ paths.emplace_back("/Developer/Tools");
const std::string hdiutil_path =
cmSystemTools::FindProgram("hdiutil", std::vector<std::string>(), false);
if (hdiutil_path.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot locate hdiutil command"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot locate hdiutil command" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_COMMAND_HDIUTIL", hdiutil_path.c_str());
@@ -85,16 +86,16 @@ int cmCPackDragNDropGenerator::InitializeInternal()
const std::string setfile_path =
cmSystemTools::FindProgram("SetFile", paths, false);
if (setfile_path.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot locate SetFile command"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot locate SetFile command" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_COMMAND_SETFILE", setfile_path.c_str());
const std::string rez_path = cmSystemTools::FindProgram("Rez", paths, false);
if (rez_path.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot locate Rez command"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot locate Rez command" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_COMMAND_REZ", rez_path.c_str());
@@ -123,30 +124,31 @@ int cmCPackDragNDropGenerator::InitializeInternal()
return 0;
}
if (!cmSystemTools::FileExists(slaDirectory, false)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_DMG_SLA_DIR does not exist"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_DMG_SLA_DIR does not exist" << std::endl);
return 0;
}
- std::vector<std::string> languages;
- cmSystemTools::ExpandListArgument(
- this->GetOption("CPACK_DMG_SLA_LANGUAGES"), languages);
+ std::vector<std::string> languages =
+ cmExpandedList(this->GetOption("CPACK_DMG_SLA_LANGUAGES"));
if (languages.empty()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_DMG_SLA_LANGUAGES set but empty" << std::endl);
return 0;
}
- for (size_t i = 0; i < languages.size(); ++i) {
- std::string license = slaDirectory + "/" + languages[i] + ".license.txt";
+ for (auto const& language : languages) {
+ std::string license = slaDirectory + "/" + language + ".license.txt";
if (!singleLicense && !cmSystemTools::FileExists(license)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Missing license file "
- << languages[i] << ".license.txt" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Missing license file " << language << ".license.txt"
+ << std::endl);
return 0;
}
- std::string menu = slaDirectory + "/" + languages[i] + ".menu.txt";
+ std::string menu = slaDirectory + "/" + language + ".menu.txt";
if (!cmSystemTools::FileExists(menu)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Missing menu file "
- << languages[i] << ".menu.txt" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Missing menu file " << language << ".menu.txt"
+ << std::endl);
return 0;
}
}
@@ -185,19 +187,17 @@ int cmCPackDragNDropGenerator::PackageFiles()
// loop to create dmg files
packageFileNames.clear();
- for (size_t i = 0; i < package_files.size(); i++) {
+ for (auto const& package_file : package_files) {
std::string full_package_name = std::string(toplevel) + std::string("/");
- if (package_files[i] == "ALL_IN_ONE") {
+ if (package_file == "ALL_IN_ONE") {
full_package_name += this->GetOption("CPACK_PACKAGE_FILE_NAME");
} else {
- full_package_name += package_files[i];
+ full_package_name += package_file;
}
full_package_name += std::string(GetOutputExtension());
packageFileNames.push_back(full_package_name);
- std::string src_dir = toplevel;
- src_dir += "/";
- src_dir += package_files[i];
+ std::string src_dir = cmStrCat(toplevel, '/', package_file);
if (0 == this->CreateDMG(src_dir, full_package_name)) {
return 0;
@@ -209,10 +209,10 @@ int cmCPackDragNDropGenerator::PackageFiles()
bool cmCPackDragNDropGenerator::CopyFile(std::ostringstream& source,
std::ostringstream& target)
{
- if (!cmSystemTools::CopyFileIfDifferent(source.str().c_str(),
- target.str().c_str())) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error copying "
- << source.str() << " to " << target.str() << std::endl);
+ if (!cmSystemTools::CopyFileIfDifferent(source.str(), target.str())) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error copying " << source.str() << " to " << target.str()
+ << std::endl);
return false;
}
@@ -226,14 +226,14 @@ bool cmCPackDragNDropGenerator::CreateEmptyFile(std::ostringstream& target,
cmsys::ofstream fout(target.str().c_str(), std::ios::out | std::ios::binary);
if (!fout) {
return false;
- } else {
- // Seek to desired size - 1 byte
- fout.seekp(size - 1, std::ios::beg);
- char byte = 0;
- // Write one byte to ensure file grows
- fout.write(&byte, 1);
}
+ // Seek to desired size - 1 byte
+ fout.seekp(size - 1, std::ios::beg);
+ char byte = 0;
+ // Write one byte to ensure file grows
+ fout.write(&byte, 1);
+
return true;
}
@@ -242,13 +242,13 @@ bool cmCPackDragNDropGenerator::RunCommand(std::ostringstream& command,
{
int exit_code = 1;
- bool result =
- cmSystemTools::RunSingleCommand(command.str().c_str(), output, output,
- &exit_code, 0, this->GeneratorVerbose, 0);
+ bool result = cmSystemTools::RunSingleCommand(
+ command.str(), output, output, &exit_code, nullptr, this->GeneratorVerbose,
+ cmDuration::zero());
if (!result || exit_code) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error executing: " << command.str()
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error executing: " << command.str() << std::endl);
return false;
}
@@ -399,8 +399,8 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
std::ostringstream dummy_padding;
dummy_padding << staging.str() << "/.dummy-padding-file";
if (!this->CreateEmptyFile(dummy_padding, 1048576)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error creating dummy padding file."
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error creating dummy padding file." << std::endl);
return 0;
}
@@ -408,21 +408,25 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
}
// Create a temporary read-write disk image ...
- std::string temp_image = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- temp_image += "/temp.dmg";
+ std::string temp_image =
+ cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/temp.dmg");
+ std::string create_error;
std::ostringstream temp_image_command;
temp_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
temp_image_command << " create";
temp_image_command << " -ov";
temp_image_command << " -srcfolder \"" << staging.str() << "\"";
temp_image_command << " -volname \"" << cpack_dmg_volume_name << "\"";
+ temp_image_command << " -fs HFS+";
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;
}
@@ -448,28 +452,32 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
cmsys::RegularExpression mountpoint_regex(".*(/Volumes/[^\n]+)\n.*");
mountpoint_regex.find(attach_output.c_str());
std::string const temp_mount = mountpoint_regex.match(1);
+ std::string const temp_mount_name =
+ temp_mount.substr(sizeof("/Volumes/") - 1);
// Remove dummy padding file so we have enough space on RW image ...
std::ostringstream dummy_padding;
dummy_padding << temp_mount << "/.dummy-padding-file";
if (!cmSystemTools::RemoveFile(dummy_padding.str())) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error removing dummy padding file."
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error removing dummy padding file." << std::endl);
had_error = true;
}
// 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;
}
@@ -481,7 +489,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
std::ostringstream setup_script_command;
setup_script_command << "osascript"
<< " \"" << cpack_dmg_ds_store_setup_script << "\""
- << " \"" << cpack_dmg_volume_name << "\"";
+ << " \"" << temp_mount_name << "\"";
std::string error;
if (!this->RunCommand(setup_script_command, &error)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
@@ -513,15 +521,15 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
if (!cpack_license_file.empty() || !slaDirectory.empty()) {
// Use old hardcoded style if sla_dir is not set
bool oldStyle = slaDirectory.empty();
- std::string sla_r = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- sla_r += "/sla.r";
+ std::string sla_r =
+ cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/sla.r");
std::vector<std::string> languages;
if (!oldStyle) {
- cmSystemTools::ExpandListArgument(cpack_dmg_languages, languages);
+ cmExpandList(cpack_dmg_languages, languages);
}
- cmGeneratedFileStream ofs(sla_r.c_str());
+ cmGeneratedFileStream ofs(sla_r);
ofs << "#include <CoreServices/CoreServices.r>\n\n";
if (oldStyle) {
ofs << SLAHeader;
@@ -551,16 +559,18 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
header_data.push_back(languages.size());
for (size_t i = 0; i < languages.size(); ++i) {
CFStringRef language_cfstring = CFStringCreateWithCString(
- NULL, languages[i].c_str(), kCFStringEncodingUTF8);
+ nullptr, languages[i].c_str(), kCFStringEncodingUTF8);
CFStringRef iso_language =
CFLocaleCreateCanonicalLanguageIdentifierFromString(
- NULL, language_cfstring);
+ nullptr, language_cfstring);
if (!iso_language) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, languages[i]
- << " is not a recognized language" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ languages[i] << " is not a recognized language"
+ << std::endl);
}
- char* iso_language_cstr = (char*)malloc(65);
- CFStringGetCString(iso_language, iso_language_cstr, 64,
+ char iso_language_cstr[65];
+ CFStringGetCString(iso_language, iso_language_cstr,
+ sizeof(iso_language_cstr) - 1,
kCFStringEncodingMacRoman);
LangCode lang = 0;
RegionCode region = 0;
@@ -573,11 +583,9 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
cmCPackLogger(cmCPackLog::LOG_ERROR,
"No language/region code available for "
<< iso_language_cstr << std::endl);
- free(iso_language_cstr);
return 0;
}
#ifdef HAVE_CoreServices
- free(iso_language_cstr);
header_data.push_back(region);
header_data.push_back(i);
header_data.push_back(0);
@@ -630,17 +638,18 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
ofs.Close();
if (have_write_license_error) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error writing license file to SLA."
- << std::endl
- << error << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error writing license file to SLA." << std::endl
+ << error
+ << std::endl);
return 0;
}
if (temp_image_format != "UDZO") {
temp_image_format = "UDZO";
// convert to UDZO to enable unflatten/flatten
- std::string temp_udzo = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- temp_udzo += "/temp-udzo.dmg";
+ std::string temp_udzo = cmStrCat(
+ this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/temp-udzo.dmg");
std::ostringstream udco_image_command;
udco_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
@@ -684,9 +693,9 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
embed_sla_command << "\"" << temp_image << "\"";
if (!this->RunCommand(embed_sla_command, &error)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error adding SLA." << std::endl
- << error
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error adding SLA." << std::endl
+ << error << std::endl);
return 0;
}
@@ -715,9 +724,13 @@ 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)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error compressing disk image."
- << std::endl);
+ std::string convert_error;
+
+ if (!this->RunCommand(final_image_command, &convert_error)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error compressing disk image." << std::endl
+ << convert_error
+ << std::endl);
return 0;
}
@@ -767,7 +780,8 @@ std::string cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix(
bool cmCPackDragNDropGenerator::WriteLicense(
cmGeneratedFileStream& outputStream, int licenseNumber,
- std::string licenseLanguage, std::string licenseFile, std::string* error)
+ std::string licenseLanguage, const std::string& licenseFile,
+ std::string* error)
{
if (!licenseFile.empty() && !singleLicense) {
licenseNumber = 5002;
@@ -793,8 +807,8 @@ bool cmCPackDragNDropGenerator::WriteLicense(
if (!this->BreakLongLine(line, lines, error)) {
return false;
}
- for (size_t i = 0; i < lines.size(); ++i) {
- outputStream << " \"" << lines[i] << "\"\n";
+ for (auto const& l : lines) {
+ outputStream << " \"" << l << "\"\n";
}
}
outputStream << " \"\\n\"\n";
@@ -863,10 +877,11 @@ bool cmCPackDragNDropGenerator::BreakLongLine(const std::string& line,
size_t line_length = max_line_length;
if (i + line_length > line.size()) {
line_length = line.size() - i;
- } else
+ } else {
while (line_length > 0 && line[i + line_length - 1] != ' ') {
line_length = line_length - 1;
}
+ }
if (line_length == 0) {
*error = "Please make sure there are no words "
diff --git a/Source/CPack/cmCPackDragNDropGenerator.h b/Source/CPack/cmCPackDragNDropGenerator.h
index ae2cc173f..f8c86c06d 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.h
+++ b/Source/CPack/cmCPackDragNDropGenerator.h
@@ -3,13 +3,14 @@
#ifndef cmCPackDragNDropGenerator_h
#define cmCPackDragNDropGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <sstream>
-#include <stddef.h>
#include <string>
#include <vector>
+#include <stddef.h>
+
#include "cmCPackGenerator.h"
class cmGeneratedFileStream;
@@ -23,32 +24,30 @@ public:
cmCPackTypeMacro(cmCPackDragNDropGenerator, cmCPackGenerator);
cmCPackDragNDropGenerator();
- virtual ~cmCPackDragNDropGenerator();
+ ~cmCPackDragNDropGenerator() override;
protected:
- int InitializeInternal() CM_OVERRIDE;
- const char* GetOutputExtension() CM_OVERRIDE;
- int PackageFiles() CM_OVERRIDE;
- bool SupportsComponentInstallation() const CM_OVERRIDE;
+ int InitializeInternal() override;
+ const char* GetOutputExtension() override;
+ int PackageFiles() override;
+ bool SupportsComponentInstallation() const override;
bool CopyFile(std::ostringstream& source, std::ostringstream& target);
bool CreateEmptyFile(std::ostringstream& target, size_t size);
bool RunCommand(std::ostringstream& command, std::string* output = 0);
std::string GetComponentInstallDirNameSuffix(
- const std::string& componentName) CM_OVERRIDE;
+ const std::string& componentName) override;
int CreateDMG(const std::string& src_dir, const std::string& output_file);
- std::string InstallPrefix;
-
private:
std::string slaDirectory;
bool singleLicense;
bool WriteLicense(cmGeneratedFileStream& outputStream, int licenseNumber,
- std::string licenseLanguage, std::string licenseFile,
- std::string* error);
+ std::string licenseLanguage,
+ const std::string& licenseFile, std::string* error);
bool BreakLongLine(const std::string& line, std::vector<std::string>& lines,
std::string* error);
void EscapeQuotesAndBackslashes(std::string& line);
diff --git a/Source/CPack/cmCPackExternalGenerator.cxx b/Source/CPack/cmCPackExternalGenerator.cxx
new file mode 100644
index 000000000..142eb6fbf
--- /dev/null
+++ b/Source/CPack/cmCPackExternalGenerator.cxx
@@ -0,0 +1,322 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackExternalGenerator.h"
+
+#include <map>
+#include <utility>
+#include <vector>
+
+#include <cm/memory>
+
+#include "cmsys/FStream.hxx"
+
+#include "cm_jsoncpp_value.h"
+#include "cm_jsoncpp_writer.h"
+
+#include "cmCPackComponentGroup.h"
+#include "cmCPackLog.h"
+#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+int cmCPackExternalGenerator::InitializeInternal()
+{
+ this->SetOption("CPACK_EXTERNAL_KNOWN_VERSIONS", "1.0");
+
+ if (!this->ReadListFile("Internal/CPack/CPackExternal.cmake")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while executing CPackExternal.cmake" << std::endl);
+ return 0;
+ }
+
+ std::string major = this->GetOption("CPACK_EXTERNAL_SELECTED_MAJOR");
+ if (major == "1") {
+ this->Generator = cm::make_unique<cmCPackExternalVersion1Generator>(this);
+ }
+
+ return this->Superclass::InitializeInternal();
+}
+
+int cmCPackExternalGenerator::PackageFiles()
+{
+ Json::StreamWriterBuilder builder;
+ builder["indentation"] = " ";
+
+ std::string filename = "package.json";
+ if (!this->packageFileNames.empty()) {
+ filename = this->packageFileNames[0];
+ }
+
+ cmsys::ofstream fout(filename.c_str());
+ std::unique_ptr<Json::StreamWriter> jout(builder.newStreamWriter());
+
+ Json::Value root(Json::objectValue);
+
+ if (!this->Generator->WriteToJSON(root)) {
+ return 0;
+ }
+
+ if (jout->write(root, &fout)) {
+ return 0;
+ }
+
+ const char* packageScript = this->GetOption("CPACK_EXTERNAL_PACKAGE_SCRIPT");
+ if (packageScript && *packageScript) {
+ if (!cmSystemTools::FileIsFullPath(packageScript)) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
+ "CPACK_EXTERNAL_PACKAGE_SCRIPT does not contain a full file path"
+ << std::endl);
+ return 0;
+ }
+
+ bool res = this->MakefileMap->ReadListFile(packageScript);
+
+ if (cmSystemTools::GetErrorOccuredFlag() || !res) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+bool cmCPackExternalGenerator::SupportsComponentInstallation() const
+{
+ return true;
+}
+
+int cmCPackExternalGenerator::InstallProjectViaInstallCommands(
+ bool setDestDir, const std::string& tempInstallDirectory)
+{
+ if (this->StagingEnabled()) {
+ return cmCPackGenerator::InstallProjectViaInstallCommands(
+ setDestDir, tempInstallDirectory);
+ }
+
+ return 1;
+}
+
+int cmCPackExternalGenerator::InstallProjectViaInstallScript(
+ bool setDestDir, const std::string& tempInstallDirectory)
+{
+ if (this->StagingEnabled()) {
+ return cmCPackGenerator::InstallProjectViaInstallScript(
+ setDestDir, tempInstallDirectory);
+ }
+
+ return 1;
+}
+
+int cmCPackExternalGenerator::InstallProjectViaInstalledDirectories(
+ bool setDestDir, const std::string& tempInstallDirectory,
+ const mode_t* default_dir_mode)
+{
+ if (this->StagingEnabled()) {
+ return cmCPackGenerator::InstallProjectViaInstalledDirectories(
+ setDestDir, tempInstallDirectory, default_dir_mode);
+ }
+
+ return 1;
+}
+
+int cmCPackExternalGenerator::RunPreinstallTarget(
+ const std::string& installProjectName, const std::string& installDirectory,
+ cmGlobalGenerator* globalGenerator, const std::string& buildConfig)
+{
+ if (this->StagingEnabled()) {
+ return cmCPackGenerator::RunPreinstallTarget(
+ installProjectName, installDirectory, globalGenerator, buildConfig);
+ }
+
+ return 1;
+}
+
+int cmCPackExternalGenerator::InstallCMakeProject(
+ bool setDestDir, const std::string& installDirectory,
+ const std::string& baseTempInstallDirectory, const mode_t* default_dir_mode,
+ const std::string& component, bool componentInstall,
+ const std::string& installSubDirectory, const std::string& buildConfig,
+ std::string& absoluteDestFiles)
+{
+ if (this->StagingEnabled()) {
+ return cmCPackGenerator::InstallCMakeProject(
+ setDestDir, installDirectory, baseTempInstallDirectory, default_dir_mode,
+ component, componentInstall, installSubDirectory, buildConfig,
+ absoluteDestFiles);
+ }
+
+ return 1;
+}
+
+bool cmCPackExternalGenerator::StagingEnabled() const
+{
+ return !cmIsOff(this->GetOption("CPACK_EXTERNAL_ENABLE_STAGING"));
+}
+
+cmCPackExternalGenerator::cmCPackExternalVersionGenerator::
+ cmCPackExternalVersionGenerator(cmCPackExternalGenerator* parent)
+ : Parent(parent)
+{
+}
+
+int cmCPackExternalGenerator::cmCPackExternalVersionGenerator::WriteVersion(
+ Json::Value& root)
+{
+ root["formatVersionMajor"] = this->GetVersionMajor();
+ root["formatVersionMinor"] = this->GetVersionMinor();
+
+ return 1;
+}
+
+int cmCPackExternalGenerator::cmCPackExternalVersionGenerator::WriteToJSON(
+ Json::Value& root)
+{
+ if (!this->WriteVersion(root)) {
+ return 0;
+ }
+
+ const char* packageName = this->Parent->GetOption("CPACK_PACKAGE_NAME");
+ if (packageName) {
+ root["packageName"] = packageName;
+ }
+
+ const char* packageVersion =
+ this->Parent->GetOption("CPACK_PACKAGE_VERSION");
+ if (packageVersion) {
+ root["packageVersion"] = packageVersion;
+ }
+
+ const char* packageDescriptionFile =
+ this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE");
+ if (packageDescriptionFile) {
+ root["packageDescriptionFile"] = packageDescriptionFile;
+ }
+
+ const char* packageDescriptionSummary =
+ this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY");
+ if (packageDescriptionSummary) {
+ root["packageDescriptionSummary"] = packageDescriptionSummary;
+ }
+
+ const char* buildConfigCstr = this->Parent->GetOption("CPACK_BUILD_CONFIG");
+ if (buildConfigCstr) {
+ root["buildConfig"] = buildConfigCstr;
+ }
+
+ const char* defaultDirectoryPermissions =
+ this->Parent->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
+ if (defaultDirectoryPermissions && *defaultDirectoryPermissions) {
+ root["defaultDirectoryPermissions"] = defaultDirectoryPermissions;
+ }
+ if (cmIsInternallyOn(this->Parent->GetOption("CPACK_SET_DESTDIR"))) {
+ root["setDestdir"] = true;
+ root["packagingInstallPrefix"] =
+ this->Parent->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
+ } else {
+ root["setDestdir"] = false;
+ }
+
+ root["stripFiles"] = !cmIsOff(this->Parent->GetOption("CPACK_STRIP_FILES"));
+ root["warnOnAbsoluteInstallDestination"] =
+ this->Parent->IsOn("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION");
+ root["errorOnAbsoluteInstallDestination"] =
+ this->Parent->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION");
+
+ Json::Value& projects = root["projects"] = Json::Value(Json::arrayValue);
+ for (auto& project : this->Parent->CMakeProjects) {
+ Json::Value jsonProject(Json::objectValue);
+
+ jsonProject["projectName"] = project.ProjectName;
+ jsonProject["component"] = project.Component;
+ jsonProject["directory"] = project.Directory;
+ jsonProject["subDirectory"] = project.SubDirectory;
+
+ Json::Value& installationTypes = jsonProject["installationTypes"] =
+ Json::Value(Json::arrayValue);
+ for (auto& installationType : project.InstallationTypes) {
+ installationTypes.append(installationType->Name);
+ }
+
+ Json::Value& components = jsonProject["components"] =
+ Json::Value(Json::arrayValue);
+ for (auto& component : project.Components) {
+ components.append(component->Name);
+ }
+
+ projects.append(jsonProject);
+ }
+
+ Json::Value& installationTypes = root["installationTypes"] =
+ Json::Value(Json::objectValue);
+ for (auto& installationType : this->Parent->InstallationTypes) {
+ Json::Value& jsonInstallationType =
+ installationTypes[installationType.first] =
+ Json::Value(Json::objectValue);
+
+ jsonInstallationType["name"] = installationType.second.Name;
+ jsonInstallationType["displayName"] = installationType.second.DisplayName;
+ jsonInstallationType["index"] = installationType.second.Index;
+ }
+
+ Json::Value& components = root["components"] =
+ Json::Value(Json::objectValue);
+ for (auto& component : this->Parent->Components) {
+ Json::Value& jsonComponent = components[component.first] =
+ Json::Value(Json::objectValue);
+
+ jsonComponent["name"] = component.second.Name;
+ jsonComponent["displayName"] = component.second.DisplayName;
+ if (component.second.Group) {
+ jsonComponent["group"] = component.second.Group->Name;
+ }
+ jsonComponent["isRequired"] = component.second.IsRequired;
+ jsonComponent["isHidden"] = component.second.IsHidden;
+ jsonComponent["isDisabledByDefault"] =
+ component.second.IsDisabledByDefault;
+ jsonComponent["isDownloaded"] = component.second.IsDownloaded;
+ jsonComponent["description"] = component.second.Description;
+ jsonComponent["archiveFile"] = component.second.ArchiveFile;
+
+ Json::Value& cmpInstallationTypes = jsonComponent["installationTypes"] =
+ Json::Value(Json::arrayValue);
+ for (auto& installationType : component.second.InstallationTypes) {
+ cmpInstallationTypes.append(installationType->Name);
+ }
+
+ Json::Value& dependencies = jsonComponent["dependencies"] =
+ Json::Value(Json::arrayValue);
+ for (auto& dep : component.second.Dependencies) {
+ dependencies.append(dep->Name);
+ }
+ }
+
+ Json::Value& groups = root["componentGroups"] =
+ Json::Value(Json::objectValue);
+ for (auto& group : this->Parent->ComponentGroups) {
+ Json::Value& jsonGroup = groups[group.first] =
+ Json::Value(Json::objectValue);
+
+ jsonGroup["name"] = group.second.Name;
+ jsonGroup["displayName"] = group.second.DisplayName;
+ jsonGroup["description"] = group.second.Description;
+ jsonGroup["isBold"] = group.second.IsBold;
+ jsonGroup["isExpandedByDefault"] = group.second.IsExpandedByDefault;
+ if (group.second.ParentGroup) {
+ jsonGroup["parentGroup"] = group.second.ParentGroup->Name;
+ }
+
+ Json::Value& subgroups = jsonGroup["subgroups"] =
+ Json::Value(Json::arrayValue);
+ for (auto& subgroup : group.second.Subgroups) {
+ subgroups.append(subgroup->Name);
+ }
+
+ Json::Value& groupComponents = jsonGroup["components"] =
+ Json::Value(Json::arrayValue);
+ for (auto& component : group.second.Components) {
+ groupComponents.append(component->Name);
+ }
+ }
+
+ return 1;
+}
diff --git a/Source/CPack/cmCPackExternalGenerator.h b/Source/CPack/cmCPackExternalGenerator.h
new file mode 100644
index 000000000..80011fddd
--- /dev/null
+++ b/Source/CPack/cmCPackExternalGenerator.h
@@ -0,0 +1,90 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCPackExternalGenerator_h
+#define cmCPackExternalGenerator_h
+
+#include <memory>
+#include <string>
+
+#include "cm_sys_stat.h"
+
+#include "cmCPackGenerator.h"
+
+class cmGlobalGenerator;
+namespace Json {
+class Value;
+}
+
+/** \class cmCPackExternalGenerator
+ * \brief A generator for CPack External packaging tools
+ */
+class cmCPackExternalGenerator : public cmCPackGenerator
+{
+public:
+ cmCPackTypeMacro(cmCPackExternalGenerator, cmCPackGenerator);
+
+ const char* GetOutputExtension() override { return ".json"; }
+
+protected:
+ int InitializeInternal() override;
+
+ int PackageFiles() override;
+
+ bool SupportsComponentInstallation() const override;
+
+ int InstallProjectViaInstallCommands(
+ bool setDestDir, const std::string& tempInstallDirectory) override;
+ int InstallProjectViaInstallScript(
+ bool setDestDir, const std::string& tempInstallDirectory) override;
+ int InstallProjectViaInstalledDirectories(
+ bool setDestDir, const std::string& tempInstallDirectory,
+ const mode_t* default_dir_mode) override;
+
+ int RunPreinstallTarget(const std::string& installProjectName,
+ const std::string& installDirectory,
+ cmGlobalGenerator* globalGenerator,
+ const std::string& buildConfig) override;
+ int InstallCMakeProject(bool setDestDir, const std::string& installDirectory,
+ const std::string& baseTempInstallDirectory,
+ const mode_t* default_dir_mode,
+ const std::string& component, bool componentInstall,
+ const std::string& installSubDirectory,
+ const std::string& buildConfig,
+ std::string& absoluteDestFiles) override;
+
+private:
+ bool StagingEnabled() const;
+
+ class cmCPackExternalVersionGenerator
+ {
+ public:
+ cmCPackExternalVersionGenerator(cmCPackExternalGenerator* parent);
+
+ virtual ~cmCPackExternalVersionGenerator() = default;
+
+ virtual int WriteToJSON(Json::Value& root);
+
+ protected:
+ virtual int GetVersionMajor() = 0;
+ virtual int GetVersionMinor() = 0;
+
+ int WriteVersion(Json::Value& root);
+
+ cmCPackExternalGenerator* Parent;
+ };
+
+ class cmCPackExternalVersion1Generator
+ : public cmCPackExternalVersionGenerator
+ {
+ public:
+ using cmCPackExternalVersionGenerator::cmCPackExternalVersionGenerator;
+
+ protected:
+ int GetVersionMajor() override { return 1; }
+ int GetVersionMinor() override { return 0; }
+ };
+
+ std::unique_ptr<cmCPackExternalVersionGenerator> Generator;
+};
+
+#endif
diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx
new file mode 100644
index 000000000..e3cc352fb
--- /dev/null
+++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx
@@ -0,0 +1,337 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackFreeBSDGenerator.h"
+
+#include "cmArchiveWrite.h"
+#include "cmCPackArchiveGenerator.h"
+#include "cmCPackLog.h"
+#include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+// Needed for ::open() and ::stat()
+#include <algorithm>
+#include <ostream>
+#include <utility>
+#include <vector>
+
+#include <fcntl.h>
+#include <pkg.h>
+
+#include <sys/stat.h>
+
+cmCPackFreeBSDGenerator::cmCPackFreeBSDGenerator()
+ : cmCPackArchiveGenerator(cmArchiveWrite::CompressXZ, "paxr", ".txz")
+{
+}
+
+int cmCPackFreeBSDGenerator::InitializeInternal()
+{
+ this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/usr/local");
+ this->SetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "0");
+ return this->Superclass::InitializeInternal();
+}
+
+cmCPackFreeBSDGenerator::~cmCPackFreeBSDGenerator() = default;
+
+// This is a wrapper, for use only in stream-based output,
+// that will output a string in UCL escaped fashion (in particular,
+// quotes and backslashes are escaped). The list of characters
+// to escape is taken from https://github.com/vstakhov/libucl
+// (which is the reference implementation pkg(8) refers to).
+class EscapeQuotes
+{
+public:
+ const std::string& value;
+
+ EscapeQuotes(const std::string& s)
+ : value(s)
+ {
+ }
+};
+
+// Output a string as "string" with escaping applied.
+cmGeneratedFileStream& operator<<(cmGeneratedFileStream& s,
+ const EscapeQuotes& v)
+{
+ s << '"';
+ for (char c : v.value) {
+ switch (c) {
+ case '\n':
+ s << "\\n";
+ break;
+ case '\r':
+ s << "\\r";
+ break;
+ case '\b':
+ s << "\\b";
+ break;
+ case '\t':
+ s << "\\t";
+ break;
+ case '\f':
+ s << "\\f";
+ break;
+ case '\\':
+ s << "\\\\";
+ break;
+ case '"':
+ s << "\\\"";
+ break;
+ default:
+ s << c;
+ break;
+ }
+ }
+ s << '"';
+ return s;
+}
+
+// The following classes are all helpers for writing out the UCL
+// manifest file (it also looks like JSON). ManifestKey just has
+// a (string-valued) key; subclasses add a specific kind of
+// value-type to the key, and implement write_value() to output
+// the corresponding UCL.
+class ManifestKey
+{
+public:
+ std::string key;
+
+ ManifestKey(std::string k)
+ : key(std::move(k))
+ {
+ }
+
+ virtual ~ManifestKey() = default;
+
+ // Output the value associated with this key to the stream @p s.
+ // Format is to be decided by subclasses.
+ virtual void write_value(cmGeneratedFileStream& s) const = 0;
+};
+
+// Basic string-value (e.g. "name": "cmake")
+class ManifestKeyValue : public ManifestKey
+{
+public:
+ std::string value;
+
+ ManifestKeyValue(const std::string& k, std::string v)
+ : ManifestKey(k)
+ , value(std::move(v))
+ {
+ }
+
+ void write_value(cmGeneratedFileStream& s) const override
+ {
+ s << EscapeQuotes(value);
+ }
+};
+
+// List-of-strings values (e.g. "licenses": ["GPLv2", "LGPLv2"])
+class ManifestKeyListValue : public ManifestKey
+{
+public:
+ using VList = std::vector<std::string>;
+ VList value;
+
+ ManifestKeyListValue(const std::string& k)
+ : ManifestKey(k)
+ {
+ }
+
+ ManifestKeyListValue& operator<<(const std::string& v)
+ {
+ value.push_back(v);
+ return *this;
+ }
+
+ ManifestKeyListValue& operator<<(const std::vector<std::string>& v)
+ {
+ for (std::string const& e : v) {
+ (*this) << e;
+ }
+ return *this;
+ }
+
+ void write_value(cmGeneratedFileStream& s) const override
+ {
+ bool with_comma = false;
+
+ s << '[';
+ for (std::string const& elem : value) {
+ s << (with_comma ? ',' : ' ');
+ s << EscapeQuotes(elem);
+ with_comma = true;
+ }
+ s << " ]";
+ }
+};
+
+// Deps: actually a dictionary, but we'll treat it as a
+// list so we only name the deps, and produce dictionary-
+// like output via write_value()
+class ManifestKeyDepsValue : public ManifestKeyListValue
+{
+public:
+ ManifestKeyDepsValue(const std::string& k)
+ : ManifestKeyListValue(k)
+ {
+ }
+
+ void write_value(cmGeneratedFileStream& s) const override
+ {
+ s << "{\n";
+ for (std::string const& elem : value) {
+ s << " \"" << elem << R"(": {"origin": ")" << elem << "\"},\n";
+ }
+ s << '}';
+ }
+};
+
+// Write one of the key-value classes (above) to the stream @p s
+cmGeneratedFileStream& operator<<(cmGeneratedFileStream& s,
+ const ManifestKey& v)
+{
+ s << '"' << v.key << "\": ";
+ v.write_value(s);
+ s << ",\n";
+ return s;
+}
+
+// Look up variable; if no value is set, returns an empty string;
+// basically a wrapper that handles the NULL-ptr return from GetOption().
+std::string cmCPackFreeBSDGenerator::var_lookup(const char* var_name)
+{
+ const char* pv = this->GetOption(var_name);
+ if (!pv) {
+ return std::string();
+ }
+ return pv;
+}
+
+// Produce UCL in the given @p manifest file for the common
+// manifest fields (common to the compact and regular formats),
+// by reading the CPACK_FREEBSD_* variables.
+void cmCPackFreeBSDGenerator::write_manifest_fields(
+ cmGeneratedFileStream& manifest)
+{
+ manifest << ManifestKeyValue("name",
+ var_lookup("CPACK_FREEBSD_PACKAGE_NAME"));
+ manifest << ManifestKeyValue("origin",
+ var_lookup("CPACK_FREEBSD_PACKAGE_ORIGIN"));
+ manifest << ManifestKeyValue("version",
+ var_lookup("CPACK_FREEBSD_PACKAGE_VERSION"));
+ manifest << ManifestKeyValue("maintainer",
+ var_lookup("CPACK_FREEBSD_PACKAGE_MAINTAINER"));
+ manifest << ManifestKeyValue("comment",
+ var_lookup("CPACK_FREEBSD_PACKAGE_COMMENT"));
+ manifest << ManifestKeyValue(
+ "desc", var_lookup("CPACK_FREEBSD_PACKAGE_DESCRIPTION"));
+ manifest << ManifestKeyValue("www", var_lookup("CPACK_FREEBSD_PACKAGE_WWW"));
+ std::vector<std::string> licenses =
+ cmExpandedList(var_lookup("CPACK_FREEBSD_PACKAGE_LICENSE"));
+ std::string licenselogic("single");
+ if (licenses.empty()) {
+ cmSystemTools::SetFatalErrorOccured();
+ } else if (licenses.size() > 1) {
+ licenselogic = var_lookup("CPACK_FREEBSD_PACKAGE_LICENSE_LOGIC");
+ }
+ manifest << ManifestKeyValue("licenselogic", licenselogic);
+ manifest << (ManifestKeyListValue("licenses") << licenses);
+ std::vector<std::string> categories =
+ cmExpandedList(var_lookup("CPACK_FREEBSD_PACKAGE_CATEGORIES"));
+ manifest << (ManifestKeyListValue("categories") << categories);
+ manifest << ManifestKeyValue("prefix", var_lookup("CMAKE_INSTALL_PREFIX"));
+ std::vector<std::string> deps =
+ cmExpandedList(var_lookup("CPACK_FREEBSD_PACKAGE_DEPS"));
+ if (!deps.empty()) {
+ manifest << (ManifestKeyDepsValue("deps") << deps);
+ }
+}
+
+// Package only actual files; others are ignored (in particular,
+// intermediate subdirectories are ignored).
+static bool ignore_file(const std::string& filename)
+{
+ struct stat statbuf;
+ return stat(filename.c_str(), &statbuf) < 0 ||
+ (statbuf.st_mode & S_IFMT) != S_IFREG;
+}
+
+// Write the given list of @p files to the manifest stream @p s,
+// as the UCL field "files" (which is dictionary-valued, to
+// associate filenames with hashes). All the files are transformed
+// to paths relative to @p toplevel, with a leading / (since the paths
+// in FreeBSD package files are supposed to be absolute).
+void write_manifest_files(cmGeneratedFileStream& s,
+ const std::string& toplevel,
+ const std::vector<std::string>& files)
+{
+ s << "\"files\": {\n";
+ for (std::string const& file : files) {
+ s << " \"/" << cmSystemTools::RelativePath(toplevel, file) << "\": \""
+ << "<sha256>"
+ << "\",\n";
+ }
+ s << " },\n";
+}
+
+int cmCPackFreeBSDGenerator::PackageFiles()
+{
+ if (!this->ReadListFile("Internal/CPack/CPackFreeBSD.cmake")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while execution CPackFreeBSD.cmake" << std::endl);
+ return 0;
+ }
+
+ std::vector<std::string>::const_iterator fileIt;
+ std::string dir = cmSystemTools::GetCurrentWorkingDirectory();
+ cmSystemTools::ChangeDirectory(toplevel);
+
+ files.erase(std::remove_if(files.begin(), files.end(), ignore_file),
+ files.end());
+
+ std::string manifestname = toplevel + "/+MANIFEST";
+ {
+ cmGeneratedFileStream manifest(manifestname);
+ manifest << "{\n";
+ write_manifest_fields(manifest);
+ write_manifest_files(manifest, toplevel, files);
+ manifest << "}\n";
+ }
+
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: " << toplevel << std::endl);
+
+ if (WantsComponentInstallation()) {
+ // CASE 1 : COMPONENT ALL-IN-ONE package
+ // If ALL COMPONENTS in ONE package has been requested
+ // then the package file is unique and should be open here.
+ if (componentPackageMethod == ONE_PACKAGE) {
+ return PackageComponentsAllInOne();
+ }
+ // CASE 2 : COMPONENT CLASSICAL package(s) (i.e. not all-in-one)
+ // There will be 1 package for each component group
+ // however one may require to ignore component group and
+ // in this case you'll get 1 package for each component.
+ return PackageComponents(componentPackageMethod ==
+ ONE_PACKAGE_PER_COMPONENT);
+ }
+
+ std::string output_dir = cmSystemTools::CollapseFullPath("../", toplevel);
+ pkg_create_from_manifest(output_dir.c_str(), ::TXZ, toplevel.c_str(),
+ manifestname.c_str(), nullptr);
+
+ std::string broken_suffix =
+ cmStrCat('-', var_lookup("CPACK_TOPLEVEL_TAG"), ".txz");
+ for (std::string& name : packageFileNames) {
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "Packagefile " << name << std::endl);
+ if (cmHasSuffix(name, broken_suffix)) {
+ name.replace(name.size() - broken_suffix.size(), std::string::npos,
+ ".txz");
+ break;
+ }
+ }
+
+ cmSystemTools::ChangeDirectory(dir);
+ return 1;
+}
diff --git a/Source/CPack/cmCPackFreeBSDGenerator.h b/Source/CPack/cmCPackFreeBSDGenerator.h
new file mode 100644
index 000000000..a18b72f62
--- /dev/null
+++ b/Source/CPack/cmCPackFreeBSDGenerator.h
@@ -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. */
+#ifndef cmCPackFreeBSDGenerator_h
+#define cmCPackFreeBSDGenerator_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+
+#include "cmCPackArchiveGenerator.h"
+#include "cmCPackGenerator.h"
+
+class cmGeneratedFileStream;
+
+/** \class cmCPackFreeBSDGenerator
+ * \brief A generator for FreeBSD package files (TXZ with a manifest)
+ *
+ */
+class cmCPackFreeBSDGenerator : public cmCPackArchiveGenerator
+{
+public:
+ cmCPackTypeMacro(cmCPackFreeBSDGenerator, cmCPackArchiveGenerator);
+ /**
+ * Construct generator
+ */
+ cmCPackFreeBSDGenerator();
+ ~cmCPackFreeBSDGenerator() override;
+
+ int InitializeInternal() override;
+ int PackageFiles() override;
+
+protected:
+ std::string var_lookup(const char* var_name);
+ void write_manifest_fields(cmGeneratedFileStream&);
+};
+
+#endif
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index d8e2753cf..6698f3c11 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -2,49 +2,53 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackGenerator.h"
+#include <algorithm>
+#include <cstring>
+#include <memory>
+#include <utility>
+
#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"
-#include <algorithm>
-#include <utility>
#include "cmCPackComponentGroup.h"
#include "cmCPackLog.h"
#include "cmCryptoHash.h"
+#include "cmDuration.h"
+#include "cmFSPermissions.h"
+#include "cmFileTimes.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmState.h"
#include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmVersion.h"
#include "cmWorkingDirectory.h"
#include "cmXMLSafe.h"
-#include "cm_auto_ptr.hxx"
#include "cmake.h"
#if defined(__HAIKU__)
-#include <FindDirectory.h>
-#include <StorageDefs.h>
+# include <FindDirectory.h>
+# include <StorageDefs.h>
#endif
cmCPackGenerator::cmCPackGenerator()
{
this->GeneratorVerbose = cmSystemTools::OUTPUT_NONE;
- this->MakefileMap = CM_NULLPTR;
- this->Logger = CM_NULLPTR;
+ this->MakefileMap = nullptr;
+ this->Logger = nullptr;
this->componentPackageMethod = ONE_PACKAGE_PER_GROUP;
}
cmCPackGenerator::~cmCPackGenerator()
{
- this->MakefileMap = CM_NULLPTR;
+ this->MakefileMap = nullptr;
}
-void cmCPackGeneratorProgress(const char* msg, float prog, void* ptr)
-{
- cmCPackGenerator* self = static_cast<cmCPackGenerator*>(ptr);
- self->DisplayVerboseOutput(msg, prog);
-}
-
-void cmCPackGenerator::DisplayVerboseOutput(const char* msg, float progress)
+void cmCPackGenerator::DisplayVerboseOutput(const std::string& msg,
+ float progress)
{
(void)progress;
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "" << msg << std::endl);
@@ -57,9 +61,10 @@ int cmCPackGenerator::PrepareNames()
// checks CPACK_SET_DESTDIR support
if (IsOn("CPACK_SET_DESTDIR")) {
if (SETDESTDIR_UNSUPPORTED == SupportsSetDestdir()) {
- cmCPackLogger(
- cmCPackLog::LOG_ERROR, "CPACK_SET_DESTDIR is set to ON but the '"
- << Name << "' generator does NOT support it." << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_SET_DESTDIR is set to ON but the '"
+ << Name << "' generator does NOT support it."
+ << std::endl);
return 0;
}
if (SETDESTDIR_SHOULD_NOT_BE_USED == SupportsSetDestdir()) {
@@ -70,8 +75,8 @@ int cmCPackGenerator::PrepareNames()
}
}
- std::string tempDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY");
- tempDirectory += "/_CPack_Packages/";
+ std::string tempDirectory =
+ cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/_CPack_Packages/");
const char* toplevelTag = this->GetOption("CPACK_TOPLEVEL_TAG");
if (toplevelTag) {
tempDirectory += toplevelTag;
@@ -88,8 +93,8 @@ int cmCPackGenerator::PrepareNames()
std::string outName = pfname;
tempDirectory += "/" + outName;
if (!this->GetOutputExtension()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "No output extension specified"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "No output extension specified" << std::endl);
return 0;
}
outName += this->GetOutputExtension();
@@ -120,9 +125,9 @@ int cmCPackGenerator::PrepareNames()
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"Look for: CPACK_PACKAGE_DESCRIPTION_FILE" << std::endl);
const char* descFileName = this->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE");
- if (descFileName) {
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Look for: " << descFileName
- << std::endl);
+ if (descFileName && !this->GetOption("CPACK_PACKAGE_DESCRIPTION")) {
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Look for: " << descFileName << std::endl);
if (!cmSystemTools::FileExists(descFileName)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Cannot find description file name: ["
@@ -144,7 +149,12 @@ int cmCPackGenerator::PrepareNames()
while (ifs && cmSystemTools::GetLineFromStream(ifs, line)) {
ostr << cmXMLSafe(line) << std::endl;
}
- this->SetOptionIfNotSet("CPACK_PACKAGE_DESCRIPTION", ostr.str().c_str());
+ this->SetOption("CPACK_PACKAGE_DESCRIPTION", ostr.str().c_str());
+ const char* defFileName =
+ this->GetOption("CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE");
+ if (defFileName && !strcmp(defFileName, descFileName)) {
+ this->SetOption("CPACK_USED_DEFAULT_PACKAGE_DESCRIPTION_FILE", "ON");
+ }
}
if (!this->GetOption("CPACK_PACKAGE_DESCRIPTION")) {
cmCPackLogger(
@@ -156,9 +166,10 @@ int cmCPackGenerator::PrepareNames()
}
const char* algoSignature = this->GetOption("CPACK_PACKAGE_CHECKSUM");
if (algoSignature) {
- if (cmCryptoHash::New(algoSignature).get() == CM_NULLPTR) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot recognize algorithm: "
- << algoSignature << std::endl);
+ if (!cmCryptoHash::New(algoSignature)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot recognize algorithm: " << algoSignature
+ << std::endl);
return 0;
}
}
@@ -176,15 +187,15 @@ int cmCPackGenerator::InstallProject()
std::string bareTempInstallDirectory =
this->GetOption("CPACK_TEMPORARY_INSTALL_DIRECTORY");
std::string tempInstallDirectoryStr = bareTempInstallDirectory;
- bool setDestDir = cmSystemTools::IsOn(this->GetOption("CPACK_SET_DESTDIR")) |
- cmSystemTools::IsInternallyOn(this->GetOption("CPACK_SET_DESTDIR"));
+ bool setDestDir = cmIsOn(this->GetOption("CPACK_SET_DESTDIR")) |
+ cmIsInternallyOn(this->GetOption("CPACK_SET_DESTDIR"));
if (!setDestDir) {
tempInstallDirectoryStr += this->GetPackagingInstallPrefix();
}
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)")
@@ -193,14 +204,37 @@ int cmCPackGenerator::InstallProject()
}
if (setDestDir) {
- std::string destDir = "DESTDIR=";
- destDir += tempInstallDirectory;
+ std::string destDir = cmStrCat("DESTDIR=", tempInstallDirectory);
cmSystemTools::PutEnv(destDir);
} else {
// Make sure there is no destdir
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 =
+ cmExpandedList(default_dir_install_permissions);
+ 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,
@@ -208,7 +242,7 @@ int cmCPackGenerator::InstallProject()
return 0;
}
- // If the CPackConfig file sets CPACK_INSTALL_SCRIPT then run them
+ // If the CPackConfig file sets CPACK_INSTALL_SCRIPT(S) then run them
// as listed
if (!this->InstallProjectViaInstallScript(setDestDir,
tempInstallDirectory)) {
@@ -218,15 +252,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;
}
@@ -243,31 +277,30 @@ int cmCPackGenerator::InstallProjectViaInstallCommands(
(void)setDestDir;
const char* installCommands = this->GetOption("CPACK_INSTALL_COMMANDS");
if (installCommands && *installCommands) {
- std::string tempInstallDirectoryEnv = "CMAKE_INSTALL_PREFIX=";
- tempInstallDirectoryEnv += tempInstallDirectory;
+ std::string tempInstallDirectoryEnv =
+ cmStrCat("CMAKE_INSTALL_PREFIX=", tempInstallDirectory);
cmSystemTools::PutEnv(tempInstallDirectoryEnv);
- std::vector<std::string> installCommandsVector;
- cmSystemTools::ExpandListArgument(installCommands, installCommandsVector);
- std::vector<std::string>::iterator it;
- for (it = installCommandsVector.begin(); it != installCommandsVector.end();
- ++it) {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << *it << std::endl);
+ std::vector<std::string> installCommandsVector =
+ cmExpandedList(installCommands);
+ for (std::string const& ic : installCommandsVector) {
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ic << std::endl);
std::string output;
int retVal = 1;
- bool resB =
- cmSystemTools::RunSingleCommand(it->c_str(), &output, &output, &retVal,
- CM_NULLPTR, this->GeneratorVerbose, 0);
+ bool resB = cmSystemTools::RunSingleCommand(
+ ic, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+ cmDuration::zero());
if (!resB || retVal) {
- std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- tmpFile += "/InstallOutput.log";
- cmGeneratedFileStream ofs(tmpFile.c_str());
- ofs << "# Run command: " << *it << std::endl
+ std::string tmpFile = cmStrCat(
+ this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/InstallOutput.log");
+ cmGeneratedFileStream ofs(tmpFile);
+ ofs << "# Run command: " << ic << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackLogger(
- cmCPackLog::LOG_ERROR, "Problem running install command: "
- << *it << std::endl
- << "Please check " << tmpFile << " for errors" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running install command: "
+ << ic << std::endl
+ << "Please check " << tmpFile << " for errors"
+ << std::endl);
return 0;
}
}
@@ -276,30 +309,27 @@ 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;
std::vector<cmsys::RegularExpression> ignoreFilesRegex;
const char* cpackIgnoreFiles = this->GetOption("CPACK_IGNORE_FILES");
if (cpackIgnoreFiles) {
- std::vector<std::string> ignoreFilesRegexString;
- cmSystemTools::ExpandListArgument(cpackIgnoreFiles,
- ignoreFilesRegexString);
- std::vector<std::string>::iterator it;
- for (it = ignoreFilesRegexString.begin();
- it != ignoreFilesRegexString.end(); ++it) {
+ std::vector<std::string> ignoreFilesRegexString =
+ cmExpandedList(cpackIgnoreFiles);
+ for (std::string const& ifr : ignoreFilesRegexString) {
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
- "Create ignore files regex for: " << *it << std::endl);
- ignoreFilesRegex.push_back(it->c_str());
+ "Create ignore files regex for: " << ifr << std::endl);
+ ignoreFilesRegex.emplace_back(ifr);
}
}
const char* installDirectories =
this->GetOption("CPACK_INSTALLED_DIRECTORIES");
if (installDirectories && *installDirectories) {
- std::vector<std::string> installDirectoriesVector;
- cmSystemTools::ExpandListArgument(installDirectories,
- installDirectoriesVector);
+ std::vector<std::string> installDirectoriesVector =
+ cmExpandedList(installDirectories);
if (installDirectoriesVector.size() % 2 != 0) {
cmCPackLogger(
cmCPackLog::LOG_ERROR,
@@ -313,14 +343,13 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
const std::string& tempDir = tempInstallDirectory;
for (it = installDirectoriesVector.begin();
it != installDirectoriesVector.end(); ++it) {
- std::vector<std::pair<std::string, std::string> > symlinkedFiles;
+ std::vector<std::pair<std::string, std::string>> symlinkedFiles;
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl);
cmsys::Glob gl;
std::string top = *it;
it++;
std::string subdir = *it;
- std::string findExpr = top;
- findExpr += "/*";
+ std::string findExpr = cmStrCat(top, "/*");
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"- Install directory: " << top << std::endl);
gl.RecurseOn();
@@ -332,17 +361,14 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
return 0;
}
files = gl.GetFiles();
- std::vector<std::string>::iterator gfit;
- std::vector<cmsys::RegularExpression>::iterator regIt;
- for (gfit = files.begin(); gfit != files.end(); ++gfit) {
+ for (std::string const& gf : files) {
bool skip = false;
- std::string inFile = *gfit;
- if (cmSystemTools::FileIsDirectory(*gfit)) {
+ std::string inFile = gf;
+ if (cmSystemTools::FileIsDirectory(gf)) {
inFile += '/';
}
- for (regIt = ignoreFilesRegex.begin(); regIt != ignoreFilesRegex.end();
- ++regIt) {
- if (regIt->find(inFile.c_str())) {
+ for (cmsys::RegularExpression& reg : ignoreFilesRegex) {
+ if (reg.find(inFile)) {
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Ignore file: " << inFile << std::endl);
skip = true;
@@ -351,64 +377,71 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
if (skip) {
continue;
}
- std::string filePath = tempDir;
- filePath += "/" + subdir + "/" +
- cmSystemTools::RelativePath(top.c_str(), gfit->c_str());
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Copy file: "
- << inFile << " -> " << filePath << std::endl);
+ std::string filePath = cmStrCat(tempDir, '/', 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(),
- filePath.c_str()) &&
- cmSystemTools::CopyFileTime(inFile.c_str(),
- filePath.c_str()))) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying file: "
- << inFile << " -> " << filePath << std::endl);
+ else if (!(cmSystemTools::CopyFileIfDifferent(inFile, filePath) &&
+ cmFileTimes::Copy(inFile, filePath))) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem copying file: " << inFile << " -> "
+ << filePath << std::endl);
return 0;
}
}
/* rebuild symlinks in the installed tree */
if (!symlinkedFiles.empty()) {
- std::vector<std::pair<std::string, std::string> >::iterator
- symlinkedIt;
std::string curDir = cmSystemTools::GetCurrentWorkingDirectory();
- std::string goToDir = tempDir;
- goToDir += "/" + subdir;
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Change dir to: " << goToDir
- << std::endl);
+ std::string goToDir = cmStrCat(tempDir, '/', subdir);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Change dir to: " << goToDir << std::endl);
cmWorkingDirectory workdir(goToDir);
- for (symlinkedIt = symlinkedFiles.begin();
- symlinkedIt != symlinkedFiles.end(); ++symlinkedIt) {
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Will create a symlink: "
- << symlinkedIt->second << "--> "
- << symlinkedIt->first << std::endl);
+ if (workdir.Failed()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed to change working directory to "
+ << goToDir << " : "
+ << std::strerror(workdir.GetLastResult())
+ << std::endl);
+ return 0;
+ }
+ for (auto const& symlinked : symlinkedFiles) {
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Will create a symlink: " << symlinked.second << "--> "
+ << symlinked.first
+ << std::endl);
// make sure directory exists for symlink
std::string destDir =
- cmSystemTools::GetFilenamePath(symlinkedIt->second);
- if (!destDir.empty() && !cmSystemTools::MakeDirectory(destDir)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot create dir: "
+ cmSystemTools::GetFilenamePath(symlinked.second);
+ if (!destDir.empty() &&
+ !cmSystemTools::MakeDirectory(destDir, default_dir_mode)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot create dir: "
<< destDir << "\nTrying to create symlink: "
- << symlinkedIt->second << "--> "
- << symlinkedIt->first << std::endl);
+ << symlinked.second << "--> " << symlinked.first
+ << std::endl);
}
- if (!cmSystemTools::CreateSymlink(symlinkedIt->first,
- symlinkedIt->second)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot create symlink: "
- << symlinkedIt->second << "--> "
- << symlinkedIt->first << std::endl);
+ if (!cmSystemTools::CreateSymlink(symlinked.first,
+ symlinked.second)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot create symlink: "
+ << symlinked.second << "--> " << symlinked.first
+ << std::endl);
return 0;
}
}
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Going back to: " << curDir
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Going back to: " << curDir << std::endl);
}
}
}
@@ -418,16 +451,24 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
int cmCPackGenerator::InstallProjectViaInstallScript(
bool setDestDir, const std::string& tempInstallDirectory)
{
- const char* cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPT");
+ const char* cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPTS");
+ {
+ const char* const cmakeScript = this->GetOption("CPACK_INSTALL_SCRIPT");
+ if (cmakeScript && cmakeScripts) {
+ cmCPackLogger(
+ cmCPackLog::LOG_WARNING,
+ "Both CPACK_INSTALL_SCRIPTS and CPACK_INSTALL_SCRIPT are set, "
+ "the latter will be ignored."
+ << std::endl);
+ } else if (cmakeScript && !cmakeScripts) {
+ cmakeScripts = cmakeScript;
+ }
+ }
if (cmakeScripts && *cmakeScripts) {
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Install scripts: " << cmakeScripts
- << std::endl);
- std::vector<std::string> cmakeScriptsVector;
- cmSystemTools::ExpandListArgument(cmakeScripts, cmakeScriptsVector);
- std::vector<std::string>::iterator it;
- for (it = cmakeScriptsVector.begin(); it != cmakeScriptsVector.end();
- ++it) {
- std::string installScript = *it;
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Install scripts: " << cmakeScripts << std::endl);
+ std::vector<std::string> cmakeScriptsVector = cmExpandedList(cmakeScripts);
+ for (std::string const& installScript : cmakeScriptsVector) {
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"- Install script: " << installScript << std::endl);
@@ -465,7 +506,7 @@ int cmCPackGenerator::InstallProjectViaInstallScript(
tempInstallDirectory.c_str());
this->SetOptionIfNotSet("CMAKE_CURRENT_SOURCE_DIR",
tempInstallDirectory.c_str());
- int res = this->MakefileMap->ReadListFile(installScript.c_str());
+ bool res = this->MakefileMap->ReadListFile(installScript);
if (cmSystemTools::GetErrorOccuredFlag() || !res) {
return 0;
}
@@ -475,7 +516,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");
@@ -489,8 +531,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
<< std::endl);
return 0;
}
- std::vector<std::string> cmakeProjectsVector;
- cmSystemTools::ExpandListArgument(cmakeProjects, cmakeProjectsVector);
+ std::vector<std::string> cmakeProjectsVector =
+ cmExpandedList(cmakeProjects);
std::vector<std::string>::iterator it;
for (it = cmakeProjectsVector.begin(); it != cmakeProjectsVector.end();
++it) {
@@ -510,10 +552,13 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
++it;
std::string installProjectName = *it;
++it;
- std::string installComponent = *it;
+ cmCPackInstallCMakeProject project;
+
+ project.Directory = installDirectory;
+ project.ProjectName = installProjectName;
+ project.Component = *it;
++it;
- std::string installSubDirectory = *it;
- std::string installFile = installDirectory + "/cmake_install.cmake";
+ project.SubDirectory = *it;
std::vector<std::string> componentsVector;
@@ -524,45 +569,61 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
* - the user did not request Monolithic install
* (this works at CPack time too)
*/
- if (this->SupportsComponentInstallation() &
+ if (this->SupportsComponentInstallation() &&
!(this->IsOn("CPACK_MONOLITHIC_INSTALL"))) {
// Determine the installation types for this project (if provided).
std::string installTypesVar = "CPACK_" +
- cmSystemTools::UpperCase(installComponent) + "_INSTALL_TYPES";
+ cmSystemTools::UpperCase(project.Component) + "_INSTALL_TYPES";
const char* installTypes = this->GetOption(installTypesVar);
if (installTypes && *installTypes) {
- std::vector<std::string> installTypesVector;
- cmSystemTools::ExpandListArgument(installTypes, installTypesVector);
- std::vector<std::string>::iterator installTypeIt;
- for (installTypeIt = installTypesVector.begin();
- installTypeIt != installTypesVector.end(); ++installTypeIt) {
- this->GetInstallationType(installProjectName, *installTypeIt);
+ std::vector<std::string> installTypesVector =
+ cmExpandedList(installTypes);
+ for (std::string const& installType : installTypesVector) {
+ project.InstallationTypes.push_back(
+ this->GetInstallationType(project.ProjectName, installType));
}
}
// Determine the set of components that will be used in this project
std::string componentsVar =
- "CPACK_COMPONENTS_" + cmSystemTools::UpperCase(installComponent);
+ "CPACK_COMPONENTS_" + cmSystemTools::UpperCase(project.Component);
const char* components = this->GetOption(componentsVar);
if (components && *components) {
- cmSystemTools::ExpandListArgument(components, componentsVector);
- std::vector<std::string>::iterator compIt;
- for (compIt = componentsVector.begin();
- compIt != componentsVector.end(); ++compIt) {
- GetComponent(installProjectName, *compIt);
+ cmExpandList(components, componentsVector);
+ for (std::string const& comp : componentsVector) {
+ project.Components.push_back(
+ this->GetComponent(project.ProjectName, comp));
}
componentInstall = true;
}
}
if (componentsVector.empty()) {
- componentsVector.push_back(installComponent);
+ componentsVector.push_back(project.Component);
}
- const char* buildConfigCstr = this->GetOption("CPACK_BUILD_CONFIG");
- std::string buildConfig = buildConfigCstr ? buildConfigCstr : "";
- cmGlobalGenerator* globalGenerator =
+ std::vector<std::string> buildConfigs;
+
+ // Try get configuration names given via `-C` CLI option
+ {
+ const char* const buildConfigCstr =
+ this->GetOption("CPACK_BUILD_CONFIG");
+ auto buildConfig = buildConfigCstr ? buildConfigCstr : std::string{};
+ cmExpandList(buildConfig, buildConfigs);
+ }
+
+ // Remove duplicates
+ std::sort(buildConfigs.begin(), buildConfigs.end());
+ buildConfigs.erase(std::unique(buildConfigs.begin(), buildConfigs.end()),
+ buildConfigs.end());
+
+ // Ensure we have at least one configuration.
+ if (buildConfigs.empty()) {
+ buildConfigs.emplace_back();
+ }
+
+ std::unique_ptr<cmGlobalGenerator> globalGenerator(
this->MakefileMap->GetCMakeInstance()->CreateGlobalGenerator(
- cmakeGenerator);
+ cmakeGenerator));
if (!globalGenerator) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Specified package generator not found. "
@@ -575,289 +636,317 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
// on windows.
cmSystemTools::SetForceUnixPaths(globalGenerator->GetForceUnixPaths());
- // Does this generator require pre-install?
- if (const char* preinstall =
- globalGenerator->GetPreinstallTargetName()) {
- std::string buildCommand = globalGenerator->GenerateCMakeBuildCommand(
- preinstall, buildConfig, "", false);
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "- Install command: " << buildCommand << std::endl);
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Run preinstall target for: "
- << installProjectName << std::endl);
- std::string output;
- int retVal = 1;
- bool resB = cmSystemTools::RunSingleCommand(
- buildCommand.c_str(), &output, &output, &retVal,
- installDirectory.c_str(), this->GeneratorVerbose, 0);
- if (!resB || retVal) {
- std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- tmpFile += "/PreinstallOutput.log";
- cmGeneratedFileStream ofs(tmpFile.c_str());
- ofs << "# Run command: " << buildCommand << std::endl
- << "# Directory: " << installDirectory << std::endl
- << "# Output:" << std::endl
- << output << std::endl;
- cmCPackLogger(
- cmCPackLog::LOG_ERROR, "Problem running install command: "
- << buildCommand << std::endl
- << "Please check " << tmpFile << " for errors" << std::endl);
+ // Run the installation for the selected build configurations
+ for (auto const& buildConfig : buildConfigs) {
+ if (!this->RunPreinstallTarget(project.ProjectName, project.Directory,
+ globalGenerator.get(), buildConfig)) {
return 0;
}
- }
- delete globalGenerator;
-
- cmCPackLogger(cmCPackLog::LOG_OUTPUT,
- "- Install project: " << installProjectName << std::endl);
-
- // Run the installation for each component
- std::vector<std::string>::iterator componentIt;
- for (componentIt = componentsVector.begin();
- componentIt != componentsVector.end(); ++componentIt) {
- std::string tempInstallDirectory = baseTempInstallDirectory;
- installComponent = *componentIt;
- if (componentInstall) {
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Install component: "
- << installComponent << std::endl);
- }
- cmake cm(cmake::RoleScript);
- cm.SetHomeDirectory("");
- cm.SetHomeOutputDirectory("");
- cm.GetCurrentSnapshot().SetDefaultDefinitions();
- cm.AddCMakePaths();
- cm.SetProgressCallback(cmCPackGeneratorProgress, this);
- cmGlobalGenerator gg(&cm);
- CM_AUTO_PTR<cmMakefile> mf(
- new cmMakefile(&gg, cm.GetCurrentSnapshot()));
- if (!installSubDirectory.empty() && installSubDirectory != "/" &&
- installSubDirectory != ".") {
- tempInstallDirectory += installSubDirectory;
- }
- if (componentInstall) {
- tempInstallDirectory += "/";
- // Some CPack generators would rather chose
- // the local installation directory suffix.
- // Some (e.g. RPM) use
- // one install directory for each component **GROUP**
- // instead of the default
- // one install directory for each component.
- tempInstallDirectory +=
- GetComponentInstallDirNameSuffix(installComponent);
- if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
- tempInstallDirectory += "/";
- tempInstallDirectory += this->GetOption("CPACK_PACKAGE_FILE_NAME");
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Install project: " << project.ProjectName << " ["
+ << buildConfig << ']'
+ << std::endl);
+ // Run the installation for each component
+ for (std::string const& component : componentsVector) {
+ if (!this->InstallCMakeProject(
+ setDestDir, project.Directory, baseTempInstallDirectory,
+ default_dir_mode, component, componentInstall,
+ project.SubDirectory, buildConfig, absoluteDestFiles)) {
+ return 0;
}
}
+ }
- if (!setDestDir) {
- tempInstallDirectory += this->GetPackagingInstallPrefix();
- }
+ this->CMakeProjects.emplace_back(std::move(project));
+ }
+ }
+ this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES",
+ absoluteDestFiles.c_str());
+ return 1;
+}
- if (setDestDir) {
- // For DESTDIR based packaging, use the *project*
- // CMAKE_INSTALL_PREFIX underneath the tempInstallDirectory. The
- // value of the project's CMAKE_INSTALL_PREFIX is sent in here as
- // the value of the CPACK_INSTALL_PREFIX variable.
- //
- // If DESTDIR has been 'internally set ON' this means that
- // the underlying CPack specific generator did ask for that
- // In this case we may override CPACK_INSTALL_PREFIX with
- // CPACK_PACKAGING_INSTALL_PREFIX
- // I know this is tricky and awkward but it's the price for
- // CPACK_SET_DESTDIR backward compatibility.
- if (cmSystemTools::IsInternallyOn(
- this->GetOption("CPACK_SET_DESTDIR"))) {
- this->SetOption("CPACK_INSTALL_PREFIX",
- this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"));
- }
- std::string dir;
- if (this->GetOption("CPACK_INSTALL_PREFIX")) {
- dir += this->GetOption("CPACK_INSTALL_PREFIX");
- }
- mf->AddDefinition("CMAKE_INSTALL_PREFIX", dir.c_str());
+int cmCPackGenerator::RunPreinstallTarget(
+ const std::string& installProjectName, const std::string& installDirectory,
+ cmGlobalGenerator* globalGenerator, const std::string& buildConfig)
+{
+ // Does this generator require pre-install?
+ if (const char* preinstall = globalGenerator->GetPreinstallTargetName()) {
+ std::string buildCommand = globalGenerator->GenerateCMakeBuildCommand(
+ preinstall, buildConfig, "", false);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Install command: " << buildCommand << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Run preinstall target for: " << installProjectName
+ << std::endl);
+ std::string output;
+ int retVal = 1;
+ bool resB = cmSystemTools::RunSingleCommand(
+ buildCommand, &output, &output, &retVal, installDirectory.c_str(),
+ this->GeneratorVerbose, cmDuration::zero());
+ if (!resB || retVal) {
+ std::string tmpFile = cmStrCat(
+ this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/PreinstallOutput.log");
+ cmGeneratedFileStream ofs(tmpFile);
+ ofs << "# Run command: " << buildCommand << std::endl
+ << "# Directory: " << installDirectory << std::endl
+ << "# Output:" << std::endl
+ << output << std::endl;
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running install command: "
+ << buildCommand << std::endl
+ << "Please check " << tmpFile << " for errors"
+ << std::endl);
+ return 0;
+ }
+ }
- cmCPackLogger(
- cmCPackLog::LOG_DEBUG,
- "- Using DESTDIR + CPACK_INSTALL_PREFIX... (mf->AddDefinition)"
- << std::endl);
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "- Setting CMAKE_INSTALL_PREFIX to '" << dir << "'"
- << std::endl);
-
- // Make sure that DESTDIR + CPACK_INSTALL_PREFIX directory
- // exists:
- //
- if (cmSystemTools::StringStartsWith(dir.c_str(), "/")) {
- dir = tempInstallDirectory + dir;
- } else {
- dir = tempInstallDirectory + "/" + dir;
- }
- /*
- * We must re-set DESTDIR for each component
- * We must not add the CPACK_INSTALL_PREFIX part because
- * it will be added using the override of CMAKE_INSTALL_PREFIX
- * The main reason for this awkward trick is that
- * are using DESTDIR for 2 different reasons:
- * - Because it was asked by the CPack Generator or the user
- * using CPACK_SET_DESTDIR
- * - Because it was already used for component install
- * in order to put things in subdirs...
- */
- cmSystemTools::PutEnv(std::string("DESTDIR=") +
- tempInstallDirectory);
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "- Creating directory: '"
- << dir << "'" << std::endl);
-
- if (!cmsys::SystemTools::MakeDirectory(dir.c_str())) {
- cmCPackLogger(
- cmCPackLog::LOG_ERROR,
- "Problem creating temporary directory: " << dir << std::endl);
- return 0;
- }
- } else {
- mf->AddDefinition("CMAKE_INSTALL_PREFIX",
- tempInstallDirectory.c_str());
+ return 1;
+}
- if (!cmsys::SystemTools::MakeDirectory(
- tempInstallDirectory.c_str())) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem creating temporary directory: "
- << tempInstallDirectory << std::endl);
- return 0;
- }
+int cmCPackGenerator::InstallCMakeProject(
+ bool setDestDir, const std::string& installDirectory,
+ const std::string& baseTempInstallDirectory, const mode_t* default_dir_mode,
+ const std::string& component, bool componentInstall,
+ const std::string& installSubDirectory, const std::string& buildConfig,
+ std::string& absoluteDestFiles)
+{
+ std::string tempInstallDirectory = baseTempInstallDirectory;
+ std::string installFile = installDirectory + "/cmake_install.cmake";
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "- Using non-DESTDIR install... (mf->AddDefinition)"
- << std::endl);
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "- Setting CMAKE_INSTALL_PREFIX to '"
- << tempInstallDirectory << "'" << std::endl);
- }
+ if (componentInstall) {
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Install component: " << component << std::endl);
+ }
- if (!buildConfig.empty()) {
- mf->AddDefinition("BUILD_TYPE", buildConfig.c_str());
- }
- std::string installComponentLowerCase =
- cmSystemTools::LowerCase(installComponent);
- if (installComponentLowerCase != "all") {
- mf->AddDefinition("CMAKE_INSTALL_COMPONENT",
- installComponent.c_str());
- }
+ cmake cm(cmake::RoleScript, cmState::CPack);
+ cm.SetHomeDirectory("");
+ cm.SetHomeOutputDirectory("");
+ cm.GetCurrentSnapshot().SetDefaultDefinitions();
+ cm.AddCMakePaths();
+ cm.SetProgressCallback([this](const std::string& msg, float prog) {
+ this->DisplayVerboseOutput(msg, prog);
+ });
+ cm.SetTrace(this->Trace);
+ cm.SetTraceExpand(this->TraceExpand);
+ cmGlobalGenerator gg(&cm);
+ cmMakefile mf(&gg, cm.GetCurrentSnapshot());
+ if (!installSubDirectory.empty() && installSubDirectory != "/" &&
+ installSubDirectory != ".") {
+ tempInstallDirectory += installSubDirectory;
+ }
+ if (componentInstall) {
+ tempInstallDirectory += "/";
+ // Some CPack generators would rather chose
+ // the local installation directory suffix.
+ // Some (e.g. RPM) use
+ // one install directory for each component **GROUP**
+ // instead of the default
+ // one install directory for each component.
+ tempInstallDirectory += GetComponentInstallDirNameSuffix(component);
+ if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
+ tempInstallDirectory += "/";
+ tempInstallDirectory += this->GetOption("CPACK_PACKAGE_FILE_NAME");
+ }
+ }
- // strip on TRUE, ON, 1, one or several file names, but not on
- // FALSE, OFF, 0 and an empty string
- if (!cmSystemTools::IsOff(this->GetOption("CPACK_STRIP_FILES"))) {
- mf->AddDefinition("CMAKE_INSTALL_DO_STRIP", "1");
- }
- // Remember the list of files before installation
- // of the current component (if we are in component install)
- const char* InstallPrefix = tempInstallDirectory.c_str();
- std::vector<std::string> filesBefore;
- std::string findExpr(InstallPrefix);
- if (componentInstall) {
- cmsys::Glob glB;
- findExpr += "/*";
- glB.RecurseOn();
- glB.SetRecurseListDirs(true);
- glB.FindFiles(findExpr);
- filesBefore = glB.GetFiles();
- std::sort(filesBefore.begin(), filesBefore.end());
- }
+ 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 CPack was asked to warn on ABSOLUTE INSTALL DESTINATION
- // then forward request to cmake_install.cmake script
- if (this->IsOn("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION")) {
- mf->AddDefinition("CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION", "1");
- }
- // If current CPack generator does support
- // ABSOLUTE INSTALL DESTINATION or CPack has been asked for
- // then ask cmake_install.cmake script to error out
- // as soon as it occurs (before installing file)
- if (!SupportsAbsoluteDestination() ||
- this->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION")) {
- mf->AddDefinition("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION",
- "1");
- }
- // do installation
- int res = mf->ReadListFile(installFile.c_str());
- // forward definition of CMAKE_ABSOLUTE_DESTINATION_FILES
- // to CPack (may be used by generators like CPack RPM or DEB)
- // in order to transparently handle ABSOLUTE PATH
- if (mf->GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) {
- mf->AddDefinition(
- "CPACK_ABSOLUTE_DESTINATION_FILES",
- mf->GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES"));
- }
+ if (!setDestDir) {
+ tempInstallDirectory += this->GetPackagingInstallPrefix();
+ }
- // Now rebuild the list of files after installation
- // of the current component (if we are in component install)
- if (componentInstall) {
- cmsys::Glob glA;
- glA.RecurseOn();
- glA.SetRecurseListDirs(true);
- glA.SetRecurseThroughSymlinks(false);
- glA.FindFiles(findExpr);
- std::vector<std::string> filesAfter = glA.GetFiles();
- std::sort(filesAfter.begin(), filesAfter.end());
- std::vector<std::string>::iterator diff;
- std::vector<std::string> result(filesAfter.size());
- diff = std::set_difference(filesAfter.begin(), filesAfter.end(),
- filesBefore.begin(), filesBefore.end(),
- result.begin());
-
- std::vector<std::string>::iterator fit;
- 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 =
- localFileName.substr(localFileName.find_first_not_of('/'));
- Components[installComponent].Files.push_back(localFileName);
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Adding file <"
- << localFileName << "> to component <"
- << installComponent << ">" << std::endl);
- }
- }
+ if (setDestDir) {
+ // For DESTDIR based packaging, use the *project*
+ // CMAKE_INSTALL_PREFIX underneath the tempInstallDirectory. The
+ // value of the project's CMAKE_INSTALL_PREFIX is sent in here as
+ // the value of the CPACK_INSTALL_PREFIX variable.
+ //
+ // If DESTDIR has been 'internally set ON' this means that
+ // the underlying CPack specific generator did ask for that
+ // In this case we may override CPACK_INSTALL_PREFIX with
+ // CPACK_PACKAGING_INSTALL_PREFIX
+ // I know this is tricky and awkward but it's the price for
+ // CPACK_SET_DESTDIR backward compatibility.
+ if (cmIsInternallyOn(this->GetOption("CPACK_SET_DESTDIR"))) {
+ this->SetOption("CPACK_INSTALL_PREFIX",
+ this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"));
+ }
+ std::string dir;
+ if (this->GetOption("CPACK_INSTALL_PREFIX")) {
+ dir += this->GetOption("CPACK_INSTALL_PREFIX");
+ }
+ mf.AddDefinition("CMAKE_INSTALL_PREFIX", dir);
- if (CM_NULLPTR !=
- mf->GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")) {
- if (!absoluteDestFiles.empty()) {
- absoluteDestFiles += ";";
- }
- absoluteDestFiles +=
- mf->GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES");
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "Got some ABSOLUTE DESTINATION FILES: "
- << absoluteDestFiles << std::endl);
- // define component specific var
- if (componentInstall) {
- std::string absoluteDestFileComponent =
- std::string("CPACK_ABSOLUTE_DESTINATION_FILES") + "_" +
- GetComponentInstallDirNameSuffix(installComponent);
- if (CM_NULLPTR != this->GetOption(absoluteDestFileComponent)) {
- std::string absoluteDestFilesListComponent =
- this->GetOption(absoluteDestFileComponent);
- absoluteDestFilesListComponent += ";";
- absoluteDestFilesListComponent +=
- mf->GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES");
- this->SetOption(absoluteDestFileComponent,
- absoluteDestFilesListComponent.c_str());
- } else {
- this->SetOption(
- absoluteDestFileComponent,
- mf->GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"));
- }
- }
- }
- if (cmSystemTools::GetErrorOccuredFlag() || !res) {
- return 0;
- }
+ cmCPackLogger(
+ cmCPackLog::LOG_DEBUG,
+ "- Using DESTDIR + CPACK_INSTALL_PREFIX... (mf.AddDefinition)"
+ << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Setting CMAKE_INSTALL_PREFIX to '" << dir << "'"
+ << std::endl);
+
+ // Make sure that DESTDIR + CPACK_INSTALL_PREFIX directory
+ // exists:
+ //
+ if (cmHasLiteralPrefix(dir, "/")) {
+ dir = tempInstallDirectory + dir;
+ } else {
+ dir = tempInstallDirectory + "/" + dir;
+ }
+ /*
+ * We must re-set DESTDIR for each component
+ * We must not add the CPACK_INSTALL_PREFIX part because
+ * it will be added using the override of CMAKE_INSTALL_PREFIX
+ * The main reason for this awkward trick is that
+ * are using DESTDIR for 2 different reasons:
+ * - Because it was asked by the CPack Generator or the user
+ * using CPACK_SET_DESTDIR
+ * - Because it was already used for component install
+ * in order to put things in subdirs...
+ */
+ cmSystemTools::PutEnv(std::string("DESTDIR=") + tempInstallDirectory);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Creating directory: '" << dir << "'" << std::endl);
+
+ if (!cmsys::SystemTools::MakeDirectory(dir, default_dir_mode)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem creating temporary directory: " << dir
+ << std::endl);
+ return 0;
+ }
+ } else {
+ mf.AddDefinition("CMAKE_INSTALL_PREFIX", tempInstallDirectory);
+
+ if (!cmsys::SystemTools::MakeDirectory(tempInstallDirectory,
+ default_dir_mode)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem creating temporary directory: "
+ << tempInstallDirectory << std::endl);
+ return 0;
+ }
+
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Using non-DESTDIR install... (mf.AddDefinition)"
+ << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "- Setting CMAKE_INSTALL_PREFIX to '" << tempInstallDirectory
+ << "'" << std::endl);
+ }
+
+ if (!buildConfig.empty()) {
+ mf.AddDefinition("BUILD_TYPE", buildConfig);
+ }
+ std::string installComponentLowerCase = cmSystemTools::LowerCase(component);
+ if (installComponentLowerCase != "all") {
+ mf.AddDefinition("CMAKE_INSTALL_COMPONENT", component);
+ }
+
+ // strip on TRUE, ON, 1, one or several file names, but not on
+ // FALSE, OFF, 0 and an empty string
+ if (!cmIsOff(this->GetOption("CPACK_STRIP_FILES"))) {
+ mf.AddDefinition("CMAKE_INSTALL_DO_STRIP", "1");
+ }
+ // Remember the list of files before installation
+ // of the current component (if we are in component install)
+ std::string const& InstallPrefix = tempInstallDirectory;
+ std::vector<std::string> filesBefore;
+ std::string findExpr = tempInstallDirectory;
+ if (componentInstall) {
+ cmsys::Glob glB;
+ findExpr += "/*";
+ glB.RecurseOn();
+ glB.SetRecurseListDirs(true);
+ glB.FindFiles(findExpr);
+ filesBefore = glB.GetFiles();
+ std::sort(filesBefore.begin(), filesBefore.end());
+ }
+
+ // If CPack was asked to warn on ABSOLUTE INSTALL DESTINATION
+ // then forward request to cmake_install.cmake script
+ if (this->IsOn("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION")) {
+ mf.AddDefinition("CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION", "1");
+ }
+ // If current CPack generator does support
+ // ABSOLUTE INSTALL DESTINATION or CPack has been asked for
+ // then ask cmake_install.cmake script to error out
+ // as soon as it occurs (before installing file)
+ if (!SupportsAbsoluteDestination() ||
+ this->IsOn("CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION")) {
+ mf.AddDefinition("CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION", "1");
+ }
+ // do installation
+ bool res = mf.ReadListFile(installFile);
+ // forward definition of CMAKE_ABSOLUTE_DESTINATION_FILES
+ // to CPack (may be used by generators like CPack RPM or DEB)
+ // in order to transparently handle ABSOLUTE PATH
+ if (const char* def = mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) {
+ mf.AddDefinition("CPACK_ABSOLUTE_DESTINATION_FILES", def);
+ }
+
+ // Now rebuild the list of files after installation
+ // of the current component (if we are in component install)
+ if (componentInstall) {
+ cmsys::Glob glA;
+ glA.RecurseOn();
+ glA.SetRecurseListDirs(true);
+ glA.SetRecurseThroughSymlinks(false);
+ glA.FindFiles(findExpr);
+ std::vector<std::string> filesAfter = glA.GetFiles();
+ std::sort(filesAfter.begin(), filesAfter.end());
+ std::vector<std::string>::iterator diff;
+ std::vector<std::string> result(filesAfter.size());
+ diff = std::set_difference(filesAfter.begin(), filesAfter.end(),
+ filesBefore.begin(), filesBefore.end(),
+ result.begin());
+
+ std::vector<std::string>::iterator fit;
+ std::string localFileName;
+ // Populate the File field of each component
+ for (fit = result.begin(); fit != diff; ++fit) {
+ localFileName = cmSystemTools::RelativePath(InstallPrefix, *fit);
+ localFileName =
+ localFileName.substr(localFileName.find_first_not_of('/'));
+ Components[component].Files.push_back(localFileName);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Adding file <" << localFileName << "> to component <"
+ << component << ">" << std::endl);
+ }
+ }
+
+ if (nullptr != mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")) {
+ if (!absoluteDestFiles.empty()) {
+ absoluteDestFiles += ";";
+ }
+ absoluteDestFiles += mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES");
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Got some ABSOLUTE DESTINATION FILES: " << absoluteDestFiles
+ << std::endl);
+ // define component specific var
+ if (componentInstall) {
+ std::string absoluteDestFileComponent =
+ std::string("CPACK_ABSOLUTE_DESTINATION_FILES") + "_" +
+ GetComponentInstallDirNameSuffix(component);
+ if (nullptr != this->GetOption(absoluteDestFileComponent)) {
+ std::string absoluteDestFilesListComponent =
+ cmStrCat(this->GetOption(absoluteDestFileComponent), ';',
+ mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"));
+ this->SetOption(absoluteDestFileComponent,
+ absoluteDestFilesListComponent.c_str());
+ } else {
+ this->SetOption(absoluteDestFileComponent,
+ mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"));
}
}
}
- this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES",
- absoluteDestFiles.c_str());
+ if (cmSystemTools::GetErrorOccuredFlag() || !res) {
+ return 0;
+ }
return 1;
}
@@ -865,7 +954,7 @@ bool cmCPackGenerator::ReadListFile(const char* moduleName)
{
bool retval;
std::string fullPath = this->MakefileMap->GetModulesFile(moduleName);
- retval = this->MakefileMap->ReadListFile(fullPath.c_str());
+ retval = this->MakefileMap->ReadListFile(fullPath);
// include FATAL_ERROR and ERROR in the return status
retval = retval && (!cmSystemTools::GetErrorOccuredFlag());
return retval;
@@ -887,16 +976,16 @@ void cmCPackGenerator::SetOption(const std::string& op, const char* value)
this->MakefileMap->RemoveDefinition(op);
return;
}
- cmCPackLogger(cmCPackLog::LOG_DEBUG, this->GetNameOfClass()
- << "::SetOption(" << op << ", " << value << ")"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ this->GetNameOfClass() << "::SetOption(" << op << ", " << value
+ << ")" << std::endl);
this->MakefileMap->AddDefinition(op, value);
}
int cmCPackGenerator::DoPackage()
{
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Create package using " << this->Name
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "Create package using " << this->Name << std::endl);
// Prepare CPack internal name and check
// values for many CPACK_xxx vars
@@ -909,13 +998,13 @@ int cmCPackGenerator::DoPackage()
return 0;
}
- if (cmSystemTools::IsOn(
- this->GetOption("CPACK_REMOVE_TOPLEVEL_DIRECTORY"))) {
+ if (cmIsOn(this->GetOption("CPACK_REMOVE_TOPLEVEL_DIRECTORY"))) {
const char* toplevelDirectory =
this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
if (cmSystemTools::FileExists(toplevelDirectory)) {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Remove toplevel directory: "
- << toplevelDirectory << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Remove toplevel directory: " << toplevelDirectory
+ << std::endl);
if (!cmSystemTools::RepeatedRemoveDirectory(toplevelDirectory)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem removing toplevel directory: "
@@ -924,8 +1013,8 @@ int cmCPackGenerator::DoPackage()
}
}
}
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "About to install project "
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "About to install project " << std::endl);
if (!this->InstallProject()) {
return 0;
@@ -938,8 +1027,7 @@ int cmCPackGenerator::DoPackage()
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl);
cmsys::Glob gl;
- std::string findExpr = tempDirectory;
- findExpr += "/*";
+ std::string findExpr = cmStrCat(tempDirectory, "/*");
gl.RecurseOn();
gl.SetRecurseListDirs(true);
gl.SetRecurseThroughSymlinks(false);
@@ -950,16 +1038,16 @@ int cmCPackGenerator::DoPackage()
}
cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Create package" << std::endl);
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Package files to: "
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Package files to: "
<< (tempPackageFileName ? tempPackageFileName : "(NULL)")
<< std::endl);
if (cmSystemTools::FileExists(tempPackageFileName)) {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Remove old package file"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Remove old package file" << std::endl);
cmSystemTools::RemoveFile(tempPackageFileName);
}
- if (cmSystemTools::IsOn(
- this->GetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY"))) {
+ if (cmIsOn(this->GetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY"))) {
tempDirectory = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
}
@@ -972,17 +1060,25 @@ int cmCPackGenerator::DoPackage()
* may update this during PackageFiles.
* (either putting several names or updating the provided one)
*/
- packageFileNames.push_back(tempPackageFileName ? tempPackageFileName : "");
+ packageFileNames.emplace_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(),
+ std::string());
+
+ if (!this->PackageFiles() || cmSystemTools::GetErrorOccuredFlag()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem compressing the directory" << std::endl);
+ return 0;
+ }
}
/* Prepare checksum algorithm*/
const char* algo = this->GetOption("CPACK_PACKAGE_CHECKSUM");
- CM_AUTO_PTR<cmCryptoHash> crypto = cmCryptoHash::New(algo ? algo : "");
+ std::unique_ptr<cmCryptoHash> crypto = cmCryptoHash::New(algo ? algo : "");
/*
* Copy the generated packages to final destination
@@ -990,46 +1086,49 @@ int cmCPackGenerator::DoPackage()
* - the initially provided name may have changed
* (because the specific generator did 'normalize' it)
*/
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Copying final package(s) ["
- << packageFileNames.size() << "]:" << std::endl);
- std::vector<std::string>::iterator it;
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Copying final package(s) [" << packageFileNames.size()
+ << "]:" << std::endl);
/* now copy package one by one */
- for (it = packageFileNames.begin(); it != packageFileNames.end(); ++it) {
+ for (std::string const& pkgFileName : packageFileNames) {
std::string tmpPF(this->GetOption("CPACK_OUTPUT_FILE_PREFIX"));
- std::string filename(cmSystemTools::GetFilenameName(*it));
- tempPackageFileName = it->c_str();
+ std::string filename(cmSystemTools::GetFilenameName(pkgFileName));
+ tempPackageFileName = pkgFileName.c_str();
tmpPF += "/" + filename;
const char* packageFileName = tmpPF.c_str();
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Copy final package(s): "
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Copy final package(s): "
<< (tempPackageFileName ? tempPackageFileName : "(NULL)")
<< " to " << (packageFileName ? packageFileName : "(NULL)")
<< std::endl);
- if (!cmSystemTools::CopyFileIfDifferent(tempPackageFileName,
- packageFileName)) {
+ if (!cmSystemTools::CopyFileIfDifferent(pkgFileName, tmpPF)) {
cmCPackLogger(
- cmCPackLog::LOG_ERROR, "Problem copying the package: "
+ cmCPackLog::LOG_ERROR,
+ "Problem copying the package: "
<< (tempPackageFileName ? tempPackageFileName : "(NULL)") << " to "
<< (packageFileName ? packageFileName : "(NULL)") << std::endl);
return 0;
}
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- package: "
- << packageFileName << " generated." << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- package: " << packageFileName << " generated."
+ << std::endl);
/* Generate checksum file */
- if (crypto.get() != CM_NULLPTR) {
+ if (crypto) {
std::string hashFile(this->GetOption("CPACK_OUTPUT_FILE_PREFIX"));
- hashFile +=
- "/" + filename.substr(0, filename.rfind(this->GetOutputExtension()));
+ hashFile += "/" + filename;
hashFile += "." + cmSystemTools::LowerCase(algo);
cmsys::ofstream outF(hashFile.c_str());
if (!outF) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot create checksum file: "
- << hashFile << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot create checksum file: " << hashFile
+ << std::endl);
return 0;
}
outF << crypto->HashFile(packageFileName) << " " << filename << "\n";
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- checksum file: "
- << hashFile << " generated." << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- checksum file: " << hashFile << " generated."
+ << std::endl);
}
}
@@ -1072,14 +1171,14 @@ bool cmCPackGenerator::IsSet(const std::string& name) const
bool cmCPackGenerator::IsOn(const std::string& name) const
{
- return cmSystemTools::IsOn(GetOption(name));
+ return cmIsOn(GetOption(name));
}
bool cmCPackGenerator::IsSetToOff(const std::string& op) const
{
const char* ret = this->MakefileMap->GetDefinition(op);
if (ret && *ret) {
- return cmSystemTools::IsOff(ret);
+ return cmIsOff(ret);
}
return false;
}
@@ -1124,8 +1223,7 @@ const char* cmCPackGenerator::GetInstallPath()
if (cmsys::SystemTools::GetEnv("ProgramFiles", prgfiles)) {
this->InstallPath = prgfiles;
} else if (cmsys::SystemTools::GetEnv("SystemDrive", sysDrive)) {
- this->InstallPath = sysDrive;
- this->InstallPath += "/Program Files";
+ this->InstallPath = cmStrCat(sysDrive, "/Program Files");
} else {
this->InstallPath = "c:/Program Files";
}
@@ -1149,7 +1247,8 @@ const char* cmCPackGenerator::GetInstallPath()
const char* cmCPackGenerator::GetPackagingInstallPrefix()
{
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "GetPackagingInstallPrefix: '"
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "GetPackagingInstallPrefix: '"
<< this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX") << "'"
<< std::endl);
@@ -1158,11 +1257,22 @@ const char* cmCPackGenerator::GetPackagingInstallPrefix()
std::string cmCPackGenerator::FindTemplate(const char* name)
{
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Look for template: "
- << (name ? name : "(NULL)") << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Look for template: " << (name ? name : "(NULL)")
+ << std::endl);
+ // Search CMAKE_MODULE_PATH for a custom template.
std::string ffile = this->MakefileMap->GetModulesFile(name);
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Found template: " << ffile
- << std::endl);
+ if (ffile.empty()) {
+ // Fall back to our internal builtin default.
+ ffile = cmStrCat(cmSystemTools::GetCMakeRoot(), "/Modules/Internal/CPack/",
+ name);
+ cmSystemTools::ConvertToUnixSlashes(ffile);
+ if (!cmSystemTools::FileExists(ffile)) {
+ ffile.clear();
+ }
+ }
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Found template: " << ffile << std::endl);
return ffile;
}
@@ -1173,7 +1283,8 @@ bool cmCPackGenerator::ConfigureString(const std::string& inString,
return true;
}
-bool cmCPackGenerator::ConfigureFile(const char* inName, const char* outName,
+bool cmCPackGenerator::ConfigureFile(const std::string& inName,
+ const std::string& outName,
bool copyOnly /* = false */)
{
return this->MakefileMap->ConfigureFile(inName, outName, copyOnly, true,
@@ -1182,9 +1293,8 @@ bool cmCPackGenerator::ConfigureFile(const char* inName, const char* outName,
int cmCPackGenerator::CleanTemporaryDirectory()
{
- std::string tempInstallDirectoryWithPostfix =
+ std::string tempInstallDirectory =
this->GetOption("CPACK_TEMPORARY_INSTALL_DIRECTORY");
- const char* tempInstallDirectory = tempInstallDirectoryWithPostfix.c_str();
if (cmsys::SystemTools::FileExists(tempInstallDirectory)) {
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"- Clean temporary : " << tempInstallDirectory << std::endl);
@@ -1225,15 +1335,15 @@ int cmCPackGenerator::PrepareGroupingKind()
std::string groupingType;
// Second way to specify grouping
- if (CM_NULLPTR != this->GetOption("CPACK_COMPONENTS_GROUPING")) {
+ if (nullptr != this->GetOption("CPACK_COMPONENTS_GROUPING")) {
groupingType = this->GetOption("CPACK_COMPONENTS_GROUPING");
}
if (!groupingType.empty()) {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "["
- << this->Name << "]"
- << " requested component grouping = " << groupingType
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "[" << this->Name << "]"
+ << " requested component grouping = " << groupingType
+ << std::endl);
if (groupingType == "ALL_COMPONENTS_IN_ONE") {
method = ONE_PACKAGE;
} else if (groupingType == "IGNORE") {
@@ -1242,11 +1352,11 @@ int cmCPackGenerator::PrepareGroupingKind()
method = ONE_PACKAGE_PER_GROUP;
} else {
cmCPackLogger(
- cmCPackLog::LOG_WARNING, "["
- << this->Name << "]"
- << " requested component grouping type <" << groupingType
- << "> UNKNOWN not in (ALL_COMPONENTS_IN_ONE,IGNORE,ONE_PER_GROUP)"
- << std::endl);
+ cmCPackLog::LOG_WARNING,
+ "[" << this->Name << "]"
+ << " requested component grouping type <" << groupingType
+ << "> UNKNOWN not in (ALL_COMPONENTS_IN_ONE,IGNORE,ONE_PER_GROUP)"
+ << std::endl);
}
}
@@ -1260,11 +1370,11 @@ int cmCPackGenerator::PrepareGroupingKind()
method = ONE_PACKAGE_PER_COMPONENT;
}
cmCPackLogger(
- cmCPackLog::LOG_WARNING, "["
- << this->Name << "]"
- << " One package per component group requested, "
- << "but NO component groups exist: Ignoring component group."
- << std::endl);
+ cmCPackLog::LOG_WARNING,
+ "[" << this->Name << "]"
+ << " One package per component group requested, "
+ << "but NO component groups exist: Ignoring component group."
+ << std::endl);
}
// if user specified packaging method, override the default packaging method
@@ -1275,10 +1385,10 @@ int cmCPackGenerator::PrepareGroupingKind()
const char* method_names[] = { "ALL_COMPONENTS_IN_ONE", "IGNORE_GROUPS",
"ONE_PER_GROUP" };
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "["
- << this->Name << "]"
- << " requested component grouping = "
- << method_names[componentPackageMethod] << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "[" << this->Name << "]"
+ << " requested component grouping = "
+ << method_names[componentPackageMethod] << std::endl);
return 1;
}
@@ -1341,7 +1451,8 @@ bool cmCPackGenerator::SupportsComponentInstallation() const
bool cmCPackGenerator::WantsComponentInstallation() const
{
- return (!IsOn("CPACK_MONOLITHIC_INSTALL") && SupportsComponentInstallation()
+ return (!IsOn("CPACK_MONOLITHIC_INSTALL") &&
+ SupportsComponentInstallation()
// check that we have at least one group or component
&& (!this->ComponentGroups.empty() || !this->Components.empty()));
}
@@ -1390,7 +1501,7 @@ cmCPackComponent* cmCPackGenerator::GetComponent(
component->IsRequired = this->IsOn(macroPrefix + "_REQUIRED");
component->IsDisabledByDefault = this->IsOn(macroPrefix + "_DISABLED");
component->IsDownloaded = this->IsOn(macroPrefix + "_DOWNLOADED") ||
- cmSystemTools::IsOn(this->GetOption("CPACK_DOWNLOAD_ALL"));
+ cmIsOn(this->GetOption("CPACK_DOWNLOAD_ALL"));
const char* archiveFile = this->GetOption(macroPrefix + "_ARCHIVE_FILE");
if (archiveFile && *archiveFile) {
@@ -1407,7 +1518,7 @@ cmCPackComponent* cmCPackGenerator::GetComponent(
component->Group = GetComponentGroup(projectName, groupName);
component->Group->Components.push_back(component);
} else {
- component->Group = CM_NULLPTR;
+ component->Group = nullptr;
}
const char* description = this->GetOption(macroPrefix + "_DESCRIPTION");
@@ -1418,25 +1529,20 @@ cmCPackComponent* cmCPackGenerator::GetComponent(
// Determine the installation types.
const char* installTypes = this->GetOption(macroPrefix + "_INSTALL_TYPES");
if (installTypes && *installTypes) {
- std::vector<std::string> installTypesVector;
- cmSystemTools::ExpandListArgument(installTypes, installTypesVector);
- std::vector<std::string>::iterator installTypesIt;
- for (installTypesIt = installTypesVector.begin();
- installTypesIt != installTypesVector.end(); ++installTypesIt) {
+ std::vector<std::string> installTypesVector =
+ cmExpandedList(installTypes);
+ for (std::string const& installType : installTypesVector) {
component->InstallationTypes.push_back(
- this->GetInstallationType(projectName, *installTypesIt));
+ this->GetInstallationType(projectName, installType));
}
}
// Determine the component dependencies.
const char* depends = this->GetOption(macroPrefix + "_DEPENDS");
if (depends && *depends) {
- std::vector<std::string> dependsVector;
- cmSystemTools::ExpandListArgument(depends, dependsVector);
- std::vector<std::string>::iterator dependIt;
- for (dependIt = dependsVector.begin(); dependIt != dependsVector.end();
- ++dependIt) {
- cmCPackComponent* child = GetComponent(projectName, *dependIt);
+ std::vector<std::string> dependsVector = cmExpandedList(depends);
+ for (std::string const& depend : dependsVector) {
+ cmCPackComponent* child = GetComponent(projectName, depend);
component->Dependencies.push_back(child);
child->ReverseDependencies.push_back(component);
}
@@ -1475,7 +1581,7 @@ cmCPackComponentGroup* cmCPackGenerator::GetComponentGroup(
group->ParentGroup = GetComponentGroup(projectName, parentGroupName);
group->ParentGroup->Subgroups.push_back(group);
} else {
- group->ParentGroup = CM_NULLPTR;
+ group->ParentGroup = nullptr;
}
}
return group;
diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h
index 45777fa05..33026c1d9 100644
--- a/Source/CPack/cmCPackGenerator.h
+++ b/Source/CPack/cmCPackGenerator.h
@@ -3,17 +3,20 @@
#ifndef cmCPackGenerator_h
#define cmCPackGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
#include <sstream>
#include <string>
#include <vector>
+#include "cm_sys_stat.h"
+
#include "cmCPackComponentGroup.h"
#include "cmSystemTools.h"
class cmCPackLog;
+class cmGlobalGenerator;
class cmInstalledFile;
class cmMakefile;
@@ -35,6 +38,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
@@ -84,7 +97,7 @@ public:
void SetLogger(cmCPackLog* log) { this->Logger = log; }
//! Display verbose information via logger
- void DisplayVerboseOutput(const char* msg, float progress);
+ void DisplayVerboseOutput(const std::string& msg, float progress);
bool ReadListFile(const char* moduleName);
@@ -105,7 +118,7 @@ protected:
cmInstalledFile const* GetInstalledFile(std::string const& name) const;
virtual const char* GetOutputExtension() { return ".cpack"; }
- virtual const char* GetOutputPostfix() { return CM_NULLPTR; }
+ virtual const char* GetOutputPostfix() { return nullptr; }
/**
* Prepare requested grouping kind from CPACK_xxx vars
@@ -157,7 +170,8 @@ protected:
virtual const char* GetPackagingInstallPrefix();
virtual std::string FindTemplate(const char* name);
- virtual bool ConfigureFile(const char* inName, const char* outName,
+ virtual bool ConfigureFile(const std::string& inName,
+ const std::string& outName,
bool copyOnly = false);
virtual bool ConfigureString(const std::string& input, std::string& output);
virtual int InitializeInternal();
@@ -168,9 +182,22 @@ 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);
+
+ virtual int RunPreinstallTarget(const std::string& installProjectName,
+ const std::string& installDirectory,
+ cmGlobalGenerator* globalGenerator,
+ const std::string& buildConfig);
+ virtual int InstallCMakeProject(
+ bool setDestDir, const std::string& installDirectory,
+ const std::string& baseTempInstallDirectory,
+ const mode_t* default_dir_mode, const std::string& component,
+ bool componentInstall, const std::string& installSubDirectory,
+ const std::string& buildConfig, std::string& absoluteDestFiles);
/**
* The various level of support of
@@ -258,6 +285,7 @@ protected:
*/
std::vector<std::string> files;
+ std::vector<cmCPackInstallCMakeProject> CMakeProjects;
std::map<std::string, cmCPackInstallationType> InstallationTypes;
/**
* The set of components.
@@ -292,14 +320,15 @@ protected:
ComponentPackageMethod componentPackageMethod;
cmCPackLog* Logger;
+ bool Trace;
+ bool TraceExpand;
-private:
cmMakefile* MakefileMap;
};
#define cmCPackTypeMacro(klass, superclass) \
- typedef superclass Superclass; \
- const char* GetNameOfClass() CM_OVERRIDE { return #klass; } \
+ using Superclass = superclass; \
+ const char* GetNameOfClass() override { return #klass; } \
static cmCPackGenerator* CreateGenerator() { return new klass; } \
class cmCPackTypeMacro_UseTrailingSemicolon
diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx
index 31f48c7e3..79e344be7 100644
--- a/Source/CPack/cmCPackGeneratorFactory.cxx
+++ b/Source/CPack/cmCPackGeneratorFactory.cxx
@@ -2,55 +2,61 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackGeneratorFactory.h"
-#include "cmConfigure.h"
#include <ostream>
#include <utility>
#include "IFW/cmCPackIFWGenerator.h"
-#include "cmAlgorithms.h"
-#include "cmCPack7zGenerator.h"
+#ifdef HAVE_FREEBSD_PKG
+# include "cmCPackFreeBSDGenerator.h"
+#endif
+#include "cmCPackArchiveGenerator.h"
+#include "cmCPackDebGenerator.h"
+#include "cmCPackExternalGenerator.h"
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
#include "cmCPackNSISGenerator.h"
+#include "cmCPackNuGetGenerator.h"
#include "cmCPackSTGZGenerator.h"
-#include "cmCPackTGZGenerator.h"
-#include "cmCPackTXZGenerator.h"
-#include "cmCPackTarBZip2Generator.h"
-#include "cmCPackTarCompressGenerator.h"
-#include "cmCPackZIPGenerator.h"
#ifdef __APPLE__
-#include "cmCPackBundleGenerator.h"
-#include "cmCPackDragNDropGenerator.h"
-#include "cmCPackOSXX11Generator.h"
-#include "cmCPackPackageMakerGenerator.h"
-#include "cmCPackProductBuildGenerator.h"
+# include "cmCPackBundleGenerator.h"
+# include "cmCPackDragNDropGenerator.h"
+# include "cmCPackOSXX11Generator.h"
+# include "cmCPackPackageMakerGenerator.h"
+# include "cmCPackProductBuildGenerator.h"
#endif
#ifdef __CYGWIN__
-#include "cmCPackCygwinBinaryGenerator.h"
-#include "cmCPackCygwinSourceGenerator.h"
+# include "cmCPackCygwinBinaryGenerator.h"
+# include "cmCPackCygwinSourceGenerator.h"
#endif
#if !defined(_WIN32) && !defined(__QNXNTO__) && !defined(__BEOS__) && \
!defined(__HAIKU__)
-#include "cmCPackDebGenerator.h"
-#include "cmCPackRPMGenerator.h"
+# include "cmCPackRPMGenerator.h"
#endif
-#ifdef _WIN32
-#include "WiX/cmCPackWIXGenerator.h"
+#if defined(_WIN32) || (defined(__CYGWIN__) && defined(HAVE_LIBUUID))
+# include "WiX/cmCPackWIXGenerator.h"
#endif
cmCPackGeneratorFactory::cmCPackGeneratorFactory()
{
- if (cmCPackTGZGenerator::CanGenerate()) {
+ if (cmCPackArchiveGenerator::CanGenerate()) {
+ this->RegisterGenerator("7Z", "7-Zip file format",
+ cmCPackArchiveGenerator::Create7ZGenerator);
+ this->RegisterGenerator("TBZ2", "Tar BZip2 compression",
+ cmCPackArchiveGenerator::CreateTBZ2Generator);
this->RegisterGenerator("TGZ", "Tar GZip compression",
- cmCPackTGZGenerator::CreateGenerator);
- }
- if (cmCPackTXZGenerator::CanGenerate()) {
+ cmCPackArchiveGenerator::CreateTGZGenerator);
this->RegisterGenerator("TXZ", "Tar XZ compression",
- cmCPackTXZGenerator::CreateGenerator);
+ cmCPackArchiveGenerator::CreateTXZGenerator);
+ this->RegisterGenerator("TZ", "Tar Compress compression",
+ cmCPackArchiveGenerator::CreateTZGenerator);
+ this->RegisterGenerator("TZST", "Tar Zstandard compression",
+ cmCPackArchiveGenerator::CreateTZSTGenerator);
+ this->RegisterGenerator("ZIP", "ZIP file format",
+ cmCPackArchiveGenerator::CreateZIPGenerator);
}
if (cmCPackSTGZGenerator::CanGenerate()) {
this->RegisterGenerator("STGZ", "Self extracting Tar GZip compression",
@@ -76,28 +82,23 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory()
cmCPackCygwinSourceGenerator::CreateGenerator);
}
#endif
-
- if (cmCPackZIPGenerator::CanGenerate()) {
- this->RegisterGenerator("ZIP", "ZIP file format",
- cmCPackZIPGenerator::CreateGenerator);
- }
- if (cmCPack7zGenerator::CanGenerate()) {
- 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);
}
#endif
- if (cmCPackTarBZip2Generator::CanGenerate()) {
- this->RegisterGenerator("TBZ2", "Tar BZip2 compression",
- cmCPackTarBZip2Generator::CreateGenerator);
+ if (cmCPackDebGenerator::CanGenerate()) {
+ this->RegisterGenerator("DEB", "Debian packages",
+ cmCPackDebGenerator::CreateGenerator);
}
- if (cmCPackTarCompressGenerator::CanGenerate()) {
- this->RegisterGenerator("TZ", "Tar Compress compression",
- cmCPackTarCompressGenerator::CreateGenerator);
+ if (cmCPackNuGetGenerator::CanGenerate()) {
+ this->RegisterGenerator("NuGet", "NuGet packages",
+ cmCPackNuGetGenerator::CreateGenerator);
+ }
+ if (cmCPackExternalGenerator::CanGenerate()) {
+ this->RegisterGenerator("External", "CPack External packages",
+ cmCPackExternalGenerator::CreateGenerator);
}
#ifdef __APPLE__
if (cmCPackDragNDropGenerator::CanGenerate()) {
@@ -123,45 +124,34 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory()
#endif
#if !defined(_WIN32) && !defined(__QNXNTO__) && !defined(__BEOS__) && \
!defined(__HAIKU__)
- if (cmCPackDebGenerator::CanGenerate()) {
- this->RegisterGenerator("DEB", "Debian packages",
- cmCPackDebGenerator::CreateGenerator);
- }
if (cmCPackRPMGenerator::CanGenerate()) {
this->RegisterGenerator("RPM", "RPM packages",
cmCPackRPMGenerator::CreateGenerator);
}
#endif
+#ifdef HAVE_FREEBSD_PKG
+ if (cmCPackFreeBSDGenerator::CanGenerate()) {
+ this->RegisterGenerator("FREEBSD", "FreeBSD pkg(8) packages",
+ cmCPackFreeBSDGenerator::CreateGenerator);
+ }
+#endif
}
-cmCPackGeneratorFactory::~cmCPackGeneratorFactory()
-{
- cmDeleteAll(this->Generators);
-}
-
-cmCPackGenerator* cmCPackGeneratorFactory::NewGenerator(
+std::unique_ptr<cmCPackGenerator> cmCPackGeneratorFactory::NewGenerator(
const std::string& name)
{
- cmCPackGenerator* gen = this->NewGeneratorInternal(name);
+ auto it = this->GeneratorCreators.find(name);
+ if (it == this->GeneratorCreators.end()) {
+ return nullptr;
+ }
+ std::unique_ptr<cmCPackGenerator> gen(it->second());
if (!gen) {
- return CM_NULLPTR;
+ return nullptr;
}
- this->Generators.push_back(gen);
gen->SetLogger(this->Logger);
return gen;
}
-cmCPackGenerator* cmCPackGeneratorFactory::NewGeneratorInternal(
- const std::string& name)
-{
- cmCPackGeneratorFactory::t_GeneratorCreatorsMap::iterator it =
- this->GeneratorCreators.find(name);
- if (it == this->GeneratorCreators.end()) {
- return CM_NULLPTR;
- }
- return (it->second)();
-}
-
void cmCPackGeneratorFactory::RegisterGenerator(
const std::string& name, const char* generatorDescription,
CreateGeneratorCall* createGenerator)
diff --git a/Source/CPack/cmCPackGeneratorFactory.h b/Source/CPack/cmCPackGeneratorFactory.h
index 7f633e473..62b748423 100644
--- a/Source/CPack/cmCPackGeneratorFactory.h
+++ b/Source/CPack/cmCPackGeneratorFactory.h
@@ -6,8 +6,8 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
+#include <memory>
#include <string>
-#include <vector>
class cmCPackGenerator;
class cmCPackLog;
@@ -20,13 +20,11 @@ class cmCPackGeneratorFactory
{
public:
cmCPackGeneratorFactory();
- ~cmCPackGeneratorFactory();
//! Get the generator
- cmCPackGenerator* NewGenerator(const std::string& name);
- void DeleteGenerator(cmCPackGenerator* gen);
+ std::unique_ptr<cmCPackGenerator> NewGenerator(const std::string& name);
- typedef cmCPackGenerator* CreateGeneratorCall();
+ using CreateGeneratorCall = cmCPackGenerator*();
void RegisterGenerator(const std::string& name,
const char* generatorDescription,
@@ -34,17 +32,14 @@ public:
void SetLogger(cmCPackLog* logger) { this->Logger = logger; }
- typedef std::map<std::string, std::string> DescriptionsMap;
+ using DescriptionsMap = std::map<std::string, std::string>;
const DescriptionsMap& GetGeneratorsList() const
{
return this->GeneratorDescriptions;
}
private:
- cmCPackGenerator* NewGeneratorInternal(const std::string& name);
- std::vector<cmCPackGenerator*> Generators;
-
- typedef std::map<std::string, CreateGeneratorCall*> t_GeneratorCreatorsMap;
+ using t_GeneratorCreatorsMap = std::map<std::string, CreateGeneratorCall*>;
t_GeneratorCreatorsMap GeneratorCreators;
DescriptionsMap GeneratorDescriptions;
cmCPackLog* Logger;
diff --git a/Source/CPack/cmCPackLog.cxx b/Source/CPack/cmCPackLog.cxx
index 5c7123959..ca675fdc8 100644
--- a/Source/CPack/cmCPackLog.cxx
+++ b/Source/CPack/cmCPackLog.cxx
@@ -2,7 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackLog.h"
-#include "cmConfigure.h"
#include <iostream>
#include "cmGeneratedFileStream.h"
@@ -19,13 +18,13 @@ cmCPackLog::cmCPackLog()
this->DefaultOutput = &std::cout;
this->DefaultError = &std::cerr;
- this->LogOutput = CM_NULLPTR;
+ this->LogOutput = nullptr;
this->LogOutputCleanup = false;
}
cmCPackLog::~cmCPackLog()
{
- this->SetLogOutputStream(CM_NULLPTR);
+ this->SetLogOutputStream(nullptr);
}
void cmCPackLog::SetLogOutputStream(std::ostream* os)
@@ -39,13 +38,13 @@ void cmCPackLog::SetLogOutputStream(std::ostream* os)
bool cmCPackLog::SetLogOutputFile(const char* fname)
{
- cmGeneratedFileStream* cg = CM_NULLPTR;
+ cmGeneratedFileStream* cg = nullptr;
if (fname) {
cg = new cmGeneratedFileStream(fname);
}
if (cg && !*cg) {
delete cg;
- cg = CM_NULLPTR;
+ cg = nullptr;
}
this->SetLogOutputStream(cg);
if (!cg) {
@@ -84,7 +83,7 @@ void cmCPackLog::Log(int tag, const char* file, int line, const char* msg,
if (!tagString.empty()) {
tagString += ",";
}
- tagString = "VERBOSE";
+ tagString += "VERBOSE";
}
}
if (tag & LOG_WARNING) {
@@ -94,7 +93,7 @@ void cmCPackLog::Log(int tag, const char* file, int line, const char* msg,
if (!tagString.empty()) {
tagString += ",";
}
- tagString = "WARNING";
+ tagString += "WARNING";
}
}
if (tag & LOG_ERROR) {
@@ -104,7 +103,7 @@ void cmCPackLog::Log(int tag, const char* file, int line, const char* msg,
if (!tagString.empty()) {
tagString += ",";
}
- tagString = "ERROR";
+ tagString += "ERROR";
}
}
if (tag & LOG_DEBUG && this->Debug) {
@@ -114,7 +113,7 @@ void cmCPackLog::Log(int tag, const char* file, int line, const char* msg,
if (!tagString.empty()) {
tagString += ",";
}
- tagString = "DEBUG";
+ tagString += "DEBUG";
}
useFileAndLine = true;
}
@@ -125,7 +124,7 @@ void cmCPackLog::Log(int tag, const char* file, int line, const char* msg,
if (!tagString.empty()) {
tagString += ",";
}
- tagString = "VERBOSE";
+ tagString += "VERBOSE";
}
}
if (this->Quiet) {
diff --git a/Source/CPack/cmCPackLog.h b/Source/CPack/cmCPackLog.h
index 10deda450..1cb16433c 100644
--- a/Source/CPack/cmCPackLog.h
+++ b/Source/CPack/cmCPackLog.h
@@ -6,9 +6,10 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <ostream>
-#include <string.h>
#include <string>
+#include <string.h>
+
#define cmCPack_Log(ctSelf, logType, msg) \
do { \
std::ostringstream cmCPackLog_msg; \
@@ -26,6 +27,9 @@ public:
cmCPackLog();
~cmCPackLog();
+ cmCPackLog(const cmCPackLog&) = delete;
+ cmCPackLog& operator=(const cmCPackLog&) = delete;
+
enum __log_tags
{
NOTAG = 0,
@@ -84,7 +88,7 @@ public:
bool SetLogOutputFile(const char* fname);
//! Set the various prefixes for the logging. SetPrefix sets the generic
- // prefix that overwrittes missing ones.
+ // prefix that overwrites missing ones.
void SetPrefix(std::string const& pfx) { this->Prefix = pfx; }
void SetOutputPrefix(std::string const& pfx) { this->OutputPrefix = pfx; }
void SetVerbosePrefix(std::string const& pfx) { this->VerbosePrefix = pfx; }
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index 9697a3832..9bf72dfb8 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -2,26 +2,30 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackNSISGenerator.h"
+#include <algorithm>
+#include <cstdlib>
+#include <cstring>
+#include <map>
+#include <sstream>
+#include <utility>
+
+#include "cmsys/Directory.hxx"
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmAlgorithms.h"
#include "cmCPackComponentGroup.h"
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmsys/Directory.hxx"
-#include "cmsys/RegularExpression.hxx"
-#include <algorithm>
-#include <map>
-#include <sstream>
-#include <stdlib.h>
-#include <string.h>
-#include <utility>
-
/* NSIS uses different command line syntax on Windows and others */
#ifdef _WIN32
-#define NSIS_OPT "/"
+# define NSIS_OPT "/"
#else
-#define NSIS_OPT "-"
+# define NSIS_OPT "-"
#endif
cmCPackNSISGenerator::cmCPackNSISGenerator(bool nsis64)
@@ -29,9 +33,7 @@ cmCPackNSISGenerator::cmCPackNSISGenerator(bool nsis64)
Nsis64 = nsis64;
}
-cmCPackNSISGenerator::~cmCPackNSISGenerator()
-{
-}
+cmCPackNSISGenerator::~cmCPackNSISGenerator() = default;
int cmCPackNSISGenerator::PackageFiles()
{
@@ -54,16 +56,13 @@ int cmCPackNSISGenerator::PackageFiles()
}
std::string nsisFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- std::string tmpFile = nsisFileName;
- tmpFile += "/NSISOutput.log";
+ std::string tmpFile = cmStrCat(nsisFileName, "/NSISOutput.log");
std::string nsisInstallOptions = nsisFileName + "/NSIS.InstallOptions.ini";
nsisFileName += "/project.nsi";
std::ostringstream str;
- std::vector<std::string>::const_iterator it;
- for (it = files.begin(); it != files.end(); ++it) {
+ for (std::string const& file : files) {
std::string outputDir = "$INSTDIR";
- std::string fileN =
- cmSystemTools::RelativePath(toplevel.c_str(), it->c_str());
+ std::string fileN = cmSystemTools::RelativePath(toplevel, file);
if (!this->Components.empty()) {
const std::string::size_type pos = fileN.find('/');
@@ -82,17 +81,15 @@ int cmCPackNSISGenerator::PackageFiles()
str << " Delete \"" << outputDir << "\\" << fileN << "\"" << std::endl;
}
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Uninstall Files: " << str.str()
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Uninstall Files: " << str.str() << std::endl);
this->SetOptionIfNotSet("CPACK_NSIS_DELETE_FILES", str.str().c_str());
std::vector<std::string> dirs;
this->GetListOfSubdirectories(toplevel.c_str(), dirs);
- std::vector<std::string>::const_iterator sit;
std::ostringstream dstr;
- for (sit = dirs.begin(); sit != dirs.end(); ++sit) {
+ for (std::string const& dir : dirs) {
std::string componentName;
- std::string fileN =
- cmSystemTools::RelativePath(toplevel.c_str(), sit->c_str());
+ std::string fileN = cmSystemTools::RelativePath(toplevel, dir);
if (fileN.empty()) {
continue;
}
@@ -117,15 +114,16 @@ 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()
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Uninstall Dirs: " << dstr.str() << std::endl);
this->SetOptionIfNotSet("CPACK_NSIS_DELETE_DIRECTORIES", dstr.str().c_str());
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
- << nsisInFileName << " to " << nsisFileName << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Configure file: " << nsisInFileName << " to " << nsisFileName
+ << std::endl);
if (this->IsSet("CPACK_NSIS_MUI_ICON") ||
this->IsSet("CPACK_NSIS_MUI_UNIICON")) {
std::string installerIconCode;
@@ -143,39 +141,34 @@ int cmCPackNSISGenerator::PackageFiles()
installerIconCode.c_str());
}
if (this->IsSet("CPACK_PACKAGE_ICON")) {
- std::string installerIconCode = "!define MUI_HEADERIMAGE_BITMAP \"";
- installerIconCode += this->GetOption("CPACK_PACKAGE_ICON");
- installerIconCode += "\"\n";
+ std::string installerIconCode =
+ cmStrCat("!define MUI_HEADERIMAGE_BITMAP \"",
+ this->GetOption("CPACK_PACKAGE_ICON"), "\"\n");
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_ICON_CODE",
installerIconCode.c_str());
}
if (this->IsSet("CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP")) {
- std::string installerBitmapCode =
- "!define MUI_WELCOMEFINISHPAGE_BITMAP \"";
- installerBitmapCode +=
- this->GetOption("CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP");
- installerBitmapCode += "\"\n";
+ std::string installerBitmapCode = cmStrCat(
+ "!define MUI_WELCOMEFINISHPAGE_BITMAP \"",
+ this->GetOption("CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP"), "\"\n");
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_WELCOMEFINISH_CODE",
installerBitmapCode.c_str());
}
if (this->IsSet("CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP")) {
- std::string installerBitmapCode =
- "!define MUI_UNWELCOMEFINISHPAGE_BITMAP \"";
- installerBitmapCode +=
- this->GetOption("CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP");
- installerBitmapCode += "\"\n";
+ std::string installerBitmapCode = cmStrCat(
+ "!define MUI_UNWELCOMEFINISHPAGE_BITMAP \"",
+ this->GetOption("CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP"), "\"\n");
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_UNWELCOMEFINISH_CODE",
installerBitmapCode.c_str());
}
if (this->IsSet("CPACK_NSIS_MUI_FINISHPAGE_RUN")) {
- std::string installerRunCode = "!define MUI_FINISHPAGE_RUN \"$INSTDIR\\";
- installerRunCode += this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY");
- installerRunCode += "\\";
- installerRunCode += this->GetOption("CPACK_NSIS_MUI_FINISHPAGE_RUN");
- installerRunCode += "\"\n";
+ std::string installerRunCode =
+ cmStrCat("!define MUI_FINISHPAGE_RUN \"$INSTDIR\\",
+ this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY"), '\\',
+ this->GetOption("CPACK_NSIS_MUI_FINISHPAGE_RUN"), "\"\n");
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_FINISHPAGE_RUN_CODE",
installerRunCode.c_str());
}
@@ -186,7 +179,7 @@ int cmCPackNSISGenerator::PackageFiles()
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC", "");
this->SetOptionIfNotSet("CPACK_NSIS_PAGE_COMPONENTS", "");
this->SetOptionIfNotSet("CPACK_NSIS_FULL_INSTALL",
- "File /r \"${INST_DIR}\\*.*\"");
+ R"(File /r "${INST_DIR}\*.*")");
this->SetOptionIfNotSet("CPACK_NSIS_COMPONENT_SECTIONS", "");
this->SetOptionIfNotSet("CPACK_NSIS_COMPONENT_SECTION_LIST", "");
this->SetOptionIfNotSet("CPACK_NSIS_SECTION_SELECTED_VARS", "");
@@ -205,65 +198,59 @@ int cmCPackNSISGenerator::PackageFiles()
// in a vector based on the indices, and print them in that order.
std::vector<cmCPackInstallationType*> installTypes(
this->InstallationTypes.size());
- std::map<std::string, cmCPackInstallationType>::iterator installTypeIt;
- for (installTypeIt = this->InstallationTypes.begin();
- installTypeIt != this->InstallationTypes.end(); ++installTypeIt) {
- installTypes[installTypeIt->second.Index - 1] = &installTypeIt->second;
- }
- std::vector<cmCPackInstallationType*>::iterator installTypeIt2;
- for (installTypeIt2 = installTypes.begin();
- installTypeIt2 != installTypes.end(); ++installTypeIt2) {
+ for (auto& installType : this->InstallationTypes) {
+ installTypes[installType.second.Index - 1] = &installType.second;
+ }
+ for (cmCPackInstallationType* installType : installTypes) {
installTypesCode += "InstType \"";
- installTypesCode += (*installTypeIt2)->DisplayName;
+ installTypesCode += installType->DisplayName;
installTypesCode += "\"\n";
}
// Create installation groups first
- std::map<std::string, cmCPackComponentGroup>::iterator groupIt;
- for (groupIt = this->ComponentGroups.begin();
- groupIt != this->ComponentGroups.end(); ++groupIt) {
- if (groupIt->second.ParentGroup == CM_NULLPTR) {
+ for (auto& group : this->ComponentGroups) {
+ if (group.second.ParentGroup == nullptr) {
componentCode +=
- this->CreateComponentGroupDescription(&groupIt->second, macrosOut);
+ this->CreateComponentGroupDescription(&group.second, macrosOut);
}
// Add the group description, if any.
- if (!groupIt->second.Description.empty()) {
+ if (!group.second.Description.empty()) {
groupDescriptions += " !insertmacro MUI_DESCRIPTION_TEXT ${" +
- groupIt->first + "} \"" +
- this->TranslateNewlines(groupIt->second.Description) + "\"\n";
+ group.first + "} \"" +
+ cmCPackNSISGenerator::TranslateNewlines(group.second.Description) +
+ "\"\n";
}
}
// Create the remaining components, which aren't associated with groups.
- std::map<std::string, cmCPackComponent>::iterator compIt;
- for (compIt = this->Components.begin(); compIt != this->Components.end();
- ++compIt) {
- if (compIt->second.Files.empty()) {
+ for (auto& comp : this->Components) {
+ if (comp.second.Files.empty()) {
// NSIS cannot cope with components that have no files.
continue;
}
anyDownloadedComponents =
- anyDownloadedComponents || compIt->second.IsDownloaded;
+ anyDownloadedComponents || comp.second.IsDownloaded;
- if (!compIt->second.Group) {
+ if (!comp.second.Group) {
componentCode +=
- this->CreateComponentDescription(&compIt->second, macrosOut);
+ this->CreateComponentDescription(&comp.second, macrosOut);
}
// Add this component to the various section lists.
- sectionList += " !insertmacro \"${MacroName}\" \"";
- sectionList += compIt->first;
+ sectionList += R"( !insertmacro "${MacroName}" ")";
+ sectionList += comp.first;
sectionList += "\"\n";
- selectedVarsList += "Var " + compIt->first + "_selected\n";
- selectedVarsList += "Var " + compIt->first + "_was_installed\n";
+ selectedVarsList += "Var " + comp.first + "_selected\n";
+ selectedVarsList += "Var " + comp.first + "_was_installed\n";
// Add the component description, if any.
- if (!compIt->second.Description.empty()) {
+ if (!comp.second.Description.empty()) {
componentDescriptions += " !insertmacro MUI_DESCRIPTION_TEXT ${" +
- compIt->first + "} \"" +
- this->TranslateNewlines(compIt->second.Description) + "\"\n";
+ comp.first + "} \"" +
+ cmCPackNSISGenerator::TranslateNewlines(comp.second.Description) +
+ "\"\n";
}
}
@@ -283,7 +270,7 @@ int cmCPackNSISGenerator::PackageFiles()
if (anyDownloadedComponents) {
defines += "!define CPACK_USES_DOWNLOAD\n";
- if (cmSystemTools::IsOn(this->GetOption("CPACK_ADD_REMOVE"))) {
+ if (cmIsOn(this->GetOption("CPACK_ADD_REMOVE"))) {
defines += "!define CPACK_NSIS_ADD_REMOVE\n";
}
}
@@ -302,27 +289,27 @@ int cmCPackNSISGenerator::PackageFiles()
this->SetOption("CPACK_NSIS_DEFINES", defines.c_str());
}
- this->ConfigureFile(nsisInInstallOptions.c_str(),
- nsisInstallOptions.c_str());
- this->ConfigureFile(nsisInFileName.c_str(), nsisFileName.c_str());
- std::string nsisCmd = "\"";
- nsisCmd += this->GetOption("CPACK_INSTALLER_PROGRAM");
- nsisCmd += "\" \"" + nsisFileName + "\"";
+ this->ConfigureFile(nsisInInstallOptions, nsisInstallOptions);
+ this->ConfigureFile(nsisInFileName, nsisFileName);
+ std::string nsisCmd =
+ cmStrCat('"', this->GetOption("CPACK_INSTALLER_PROGRAM"), "\" \"",
+ nsisFileName, '"');
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << nsisCmd << std::endl);
std::string output;
int retVal = 1;
- bool res =
- cmSystemTools::RunSingleCommand(nsisCmd.c_str(), &output, &output, &retVal,
- CM_NULLPTR, this->GeneratorVerbose, 0);
+ bool res = cmSystemTools::RunSingleCommand(
+ nsisCmd, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+ cmDuration::zero());
if (!res || retVal) {
- cmGeneratedFileStream ofs(tmpFile.c_str());
+ cmGeneratedFileStream ofs(tmpFile);
ofs << "# Run command: " << nsisCmd << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running NSIS command: "
- << nsisCmd << std::endl
- << "Please check " << tmpFile << " for errors"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running NSIS command: " << nsisCmd << std::endl
+ << "Please check "
+ << tmpFile << " for errors"
+ << std::endl);
return 0;
}
return 1;
@@ -330,38 +317,40 @@ int cmCPackNSISGenerator::PackageFiles()
int cmCPackNSISGenerator::InitializeInternal()
{
- if (cmSystemTools::IsOn(
- this->GetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY"))) {
+ if (cmIsOn(this->GetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY"))) {
cmCPackLogger(
cmCPackLog::LOG_WARNING,
"NSIS Generator cannot work with CPACK_INCLUDE_TOPLEVEL_DIRECTORY set. "
"This option will be reset to 0 (for this generator only)."
<< std::endl);
- this->SetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", CM_NULLPTR);
+ this->SetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", nullptr);
}
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "cmCPackNSISGenerator::Initialize()"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "cmCPackNSISGenerator::Initialize()" << std::endl);
std::vector<std::string> path;
std::string nsisPath;
bool gotRegValue = false;
#ifdef _WIN32
if (Nsis64) {
- if (!gotRegValue && cmsys::SystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS\\Unicode",
- nsisPath, cmsys::SystemTools::KeyWOW64_64)) {
+ if (!gotRegValue &&
+ cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS\\Unicode", nsisPath,
+ cmsys::SystemTools::KeyWOW64_64)) {
gotRegValue = true;
}
- if (!gotRegValue && cmsys::SystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath,
- cmsys::SystemTools::KeyWOW64_64)) {
+ if (!gotRegValue &&
+ cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath,
+ cmsys::SystemTools::KeyWOW64_64)) {
gotRegValue = true;
}
}
- if (!gotRegValue && cmsys::SystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS\\Unicode",
- nsisPath, cmsys::SystemTools::KeyWOW64_32)) {
+ if (!gotRegValue &&
+ cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS\\Unicode", nsisPath,
+ cmsys::SystemTools::KeyWOW64_32)) {
gotRegValue = true;
}
if (!gotRegValue &&
@@ -369,13 +358,15 @@ int cmCPackNSISGenerator::InitializeInternal()
"HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS\\Unicode", nsisPath)) {
gotRegValue = true;
}
- if (!gotRegValue && cmsys::SystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath,
- cmsys::SystemTools::KeyWOW64_32)) {
+ if (!gotRegValue &&
+ cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath,
+ cmsys::SystemTools::KeyWOW64_32)) {
gotRegValue = true;
}
- if (!gotRegValue && cmsys::SystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath)) {
+ if (!gotRegValue &&
+ cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath)) {
gotRegValue = true;
}
@@ -406,35 +397,35 @@ int cmCPackNSISGenerator::InitializeInternal()
}
std::string nsisCmd = "\"" + nsisPath + "\" " NSIS_OPT "VERSION";
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Test NSIS version: " << nsisCmd
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Test NSIS version: " << nsisCmd << std::endl);
std::string output;
int retVal = 1;
- bool resS =
- cmSystemTools::RunSingleCommand(nsisCmd.c_str(), &output, &output, &retVal,
- CM_NULLPTR, this->GeneratorVerbose, 0);
+ bool resS = cmSystemTools::RunSingleCommand(
+ nsisCmd, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+ cmDuration::zero());
cmsys::RegularExpression versionRex("v([0-9]+.[0-9]+)");
cmsys::RegularExpression versionRexCVS("v(.*)\\.cvs");
if (!resS || retVal ||
(!versionRex.find(output) && !versionRexCVS.find(output))) {
const char* topDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- std::string tmpFile = topDir ? topDir : ".";
- tmpFile += "/NSISOutput.log";
- cmGeneratedFileStream ofs(tmpFile.c_str());
+ std::string tmpFile = cmStrCat(topDir ? topDir : ".", "/NSISOutput.log");
+ cmGeneratedFileStream ofs(tmpFile);
ofs << "# Run command: " << nsisCmd << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackLogger(
- cmCPackLog::LOG_ERROR, "Problem checking NSIS version with command: "
- << nsisCmd << std::endl
- << "Please check " << tmpFile << " for errors" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem checking NSIS version with command: "
+ << nsisCmd << std::endl
+ << "Please check " << tmpFile << " for errors"
+ << std::endl);
return 0;
}
if (versionRex.find(output)) {
double nsisVersion = atof(versionRex.match(1).c_str());
double minNSISVersion = 2.09;
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "NSIS Version: " << nsisVersion
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "NSIS Version: " << nsisVersion << std::endl);
if (nsisVersion < minNSISVersion) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPack requires NSIS Version 2.09 or greater. "
@@ -445,8 +436,8 @@ int cmCPackNSISGenerator::InitializeInternal()
}
if (versionRexCVS.find(output)) {
// No version check for NSIS cvs build
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "NSIS Version: CVS "
- << versionRexCVS.match(1) << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "NSIS Version: CVS " << versionRexCVS.match(1) << std::endl);
}
this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", nsisPath.c_str());
this->SetOptionIfNotSet("CPACK_NSIS_EXECUTABLES_DIRECTORY", "bin");
@@ -458,19 +449,18 @@ int cmCPackNSISGenerator::InitializeInternal()
this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY");
std::vector<std::string> cpackPackageDesktopLinksVector;
if (cpackPackageDeskTopLinks) {
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "CPACK_CREATE_DESKTOP_LINKS: "
- << cpackPackageDeskTopLinks << std::endl);
-
- cmSystemTools::ExpandListArgument(cpackPackageDeskTopLinks,
- cpackPackageDesktopLinksVector);
- for (std::vector<std::string>::iterator i =
- cpackPackageDesktopLinksVector.begin();
- i != cpackPackageDesktopLinksVector.end(); ++i) {
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "CPACK_CREATE_DESKTOP_LINKS: " << cpackPackageDeskTopLinks
+ << std::endl);
+
+ cmExpandList(cpackPackageDeskTopLinks, cpackPackageDesktopLinksVector);
+ for (std::string const& cpdl : cpackPackageDesktopLinksVector) {
cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "CPACK_CREATE_DESKTOP_LINKS: " << *i << std::endl);
+ "CPACK_CREATE_DESKTOP_LINKS: " << cpdl << std::endl);
}
} else {
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "CPACK_CREATE_DESKTOP_LINKS: "
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "CPACK_CREATE_DESKTOP_LINKS: "
<< "not set" << std::endl);
}
@@ -478,11 +468,11 @@ int cmCPackNSISGenerator::InitializeInternal()
std::ostringstream deleteStr;
if (cpackPackageExecutables) {
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "The cpackPackageExecutables: "
- << cpackPackageExecutables << "." << std::endl);
- std::vector<std::string> cpackPackageExecutablesVector;
- cmSystemTools::ExpandListArgument(cpackPackageExecutables,
- cpackPackageExecutablesVector);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "The cpackPackageExecutables: " << cpackPackageExecutables
+ << "." << std::endl);
+ std::vector<std::string> cpackPackageExecutablesVector =
+ cmExpandedList(cpackPackageExecutables);
if (cpackPackageExecutablesVector.size() % 2 != 0) {
cmCPackLogger(
cmCPackLog::LOG_ERROR,
@@ -497,20 +487,17 @@ int cmCPackNSISGenerator::InitializeInternal()
std::string execName = *it;
++it;
std::string linkName = *it;
- str << " CreateShortCut \"$SMPROGRAMS\\$STARTMENU_FOLDER\\" << linkName
- << ".lnk\" \"$INSTDIR\\" << cpackNsisExecutablesDirectory << "\\"
+ str << R"( CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\)" << linkName
+ << R"(.lnk" "$INSTDIR\)" << cpackNsisExecutablesDirectory << "\\"
<< execName << ".exe\"" << std::endl;
- deleteStr << " Delete \"$SMPROGRAMS\\$MUI_TEMP\\" << linkName
+ deleteStr << R"( Delete "$SMPROGRAMS\$MUI_TEMP\)" << linkName
<< ".lnk\"" << std::endl;
// see if CPACK_CREATE_DESKTOP_LINK_ExeName is on
// if so add a desktop link
- if (!cpackPackageDesktopLinksVector.empty() &&
- std::find(cpackPackageDesktopLinksVector.begin(),
- cpackPackageDesktopLinksVector.end(),
- execName) != cpackPackageDesktopLinksVector.end()) {
+ if (cmContains(cpackPackageDesktopLinksVector, execName)) {
str << " StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2\n";
str << " CreateShortCut \"$DESKTOP\\" << linkName
- << ".lnk\" \"$INSTDIR\\" << cpackNsisExecutablesDirectory << "\\"
+ << R"(.lnk" "$INSTDIR\)" << cpackNsisExecutablesDirectory << "\\"
<< execName << ".exe\"" << std::endl;
deleteStr << " StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2\n";
deleteStr << " Delete \"$DESKTOP\\" << linkName << ".lnk\""
@@ -537,8 +524,8 @@ void cmCPackNSISGenerator::CreateMenuLinks(std::ostream& str,
}
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"The cpackMenuLinks: " << cpackMenuLinks << "." << std::endl);
- std::vector<std::string> cpackMenuLinksVector;
- cmSystemTools::ExpandListArgument(cpackMenuLinks, cpackMenuLinksVector);
+ std::vector<std::string> cpackMenuLinksVector =
+ cmExpandedList(cpackMenuLinks);
if (cpackMenuLinksVector.size() % 2 != 0) {
cmCPackLogger(
cmCPackLog::LOG_ERROR,
@@ -566,25 +553,24 @@ void cmCPackNSISGenerator::CreateMenuLinks(std::ostream& str,
++it;
std::string linkName = *it;
if (!url) {
- str << " CreateShortCut \"$SMPROGRAMS\\$STARTMENU_FOLDER\\" << linkName
- << ".lnk\" \"$INSTDIR\\" << sourceName << "\"" << std::endl;
- deleteStr << " Delete \"$SMPROGRAMS\\$MUI_TEMP\\" << linkName
+ str << R"( CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\)" << linkName
+ << R"(.lnk" "$INSTDIR\)" << sourceName << "\"" << std::endl;
+ deleteStr << R"( Delete "$SMPROGRAMS\$MUI_TEMP\)" << linkName
<< ".lnk\"" << std::endl;
} else {
- str << " WriteINIStr \"$SMPROGRAMS\\$STARTMENU_FOLDER\\" << linkName
- << ".url\" \"InternetShortcut\" \"URL\" \"" << sourceName << "\""
+ str << R"( WriteINIStr "$SMPROGRAMS\$STARTMENU_FOLDER\)" << linkName
+ << R"(.url" "InternetShortcut" "URL" ")" << sourceName << "\""
<< std::endl;
- deleteStr << " Delete \"$SMPROGRAMS\\$MUI_TEMP\\" << linkName
+ deleteStr << R"( Delete "$SMPROGRAMS\$MUI_TEMP\)" << linkName
<< ".url\"" << std::endl;
}
// see if CPACK_CREATE_DESKTOP_LINK_ExeName is on
// if so add a desktop link
- std::string desktop = "CPACK_CREATE_DESKTOP_LINK_";
- desktop += linkName;
+ std::string desktop = cmStrCat("CPACK_CREATE_DESKTOP_LINK_", linkName);
if (this->IsSet(desktop)) {
str << " StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2\n";
str << " CreateShortCut \"$DESKTOP\\" << linkName
- << ".lnk\" \"$INSTDIR\\" << sourceName << "\"" << std::endl;
+ << R"(.lnk" "$INSTDIR\)" << sourceName << "\"" << std::endl;
deleteStr << " StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2\n";
deleteStr << " Delete \"$DESKTOP\\" << linkName << ".lnk\""
<< std::endl;
@@ -610,7 +596,7 @@ bool cmCPackNSISGenerator::GetListOfSubdirectories(
}
}
}
- dirs.push_back(topdir);
+ dirs.emplace_back(topdir);
return true;
}
@@ -647,11 +633,9 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
componentCode += " SectionIn RO\n";
} else if (!component->InstallationTypes.empty()) {
std::ostringstream out;
- std::vector<cmCPackInstallationType*>::iterator installTypeIter;
- for (installTypeIter = component->InstallationTypes.begin();
- installTypeIter != component->InstallationTypes.end();
- ++installTypeIter) {
- out << " " << (*installTypeIter)->Index;
+ for (cmCPackInstallationType const* installType :
+ component->InstallationTypes) {
+ out << " " << installType->Index;
}
componentCode += " SectionIn" + out.str() + "\n";
}
@@ -664,8 +648,8 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
if (component->IsDownloaded) {
if (component->ArchiveFile.empty()) {
// Compute the name of the archive.
- std::string packagesDir = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
- packagesDir += ".dummy";
+ std::string packagesDir =
+ cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), ".dummy");
std::ostringstream out;
out << cmSystemTools::GetFilenameWithoutLastExtension(packagesDir) << "-"
<< component->Name << ".zip";
@@ -679,11 +663,11 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
if (userUploadDirectory && *userUploadDirectory) {
uploadDirectory = userUploadDirectory;
} else {
- uploadDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY");
- uploadDirectory += "/CPackUploads";
+ uploadDirectory =
+ cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/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);
@@ -696,53 +680,49 @@ 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);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Unable to remove archive file " << archiveFile
+ << std::endl);
return "";
}
}
// Find a ZIP program
if (!this->IsSet("ZIP_EXECUTABLE")) {
- this->ReadListFile("CPackZIP.cmake");
+ this->ReadListFile("Internal/CPack/CPackZIP.cmake");
if (!this->IsSet("ZIP_EXECUTABLE")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Unable to find ZIP program"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Unable to find ZIP program" << std::endl);
return "";
}
}
// The directory where this component's files reside
- std::string dirName = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
- dirName += '/';
- dirName += component->Name;
- dirName += '/';
+ std::string dirName = cmStrCat(
+ this->GetOption("CPACK_TEMPORARY_DIRECTORY"), '/', component->Name, '/');
// Build the list of files to go into this archive, and determine the
// size of the installed component.
- std::string zipListFileName = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
- zipListFileName += "/winZip.filelist";
- bool needQuotesInFile =
- cmSystemTools::IsOn(this->GetOption("CPACK_ZIP_NEED_QUOTES"));
+ std::string zipListFileName = cmStrCat(
+ this->GetOption("CPACK_TEMPORARY_DIRECTORY"), "/winZip.filelist");
+ bool needQuotesInFile = cmIsOn(this->GetOption("CPACK_ZIP_NEED_QUOTES"));
unsigned long totalSize = 0;
{ // the scope is needed for cmGeneratedFileStream
- cmGeneratedFileStream out(zipListFileName.c_str());
- std::vector<std::string>::iterator fileIt;
- for (fileIt = component->Files.begin(); fileIt != component->Files.end();
- ++fileIt) {
+ cmGeneratedFileStream out(zipListFileName);
+ for (std::string const& file : component->Files) {
if (needQuotesInFile) {
out << "\"";
}
- out << *fileIt;
+ out << file;
if (needQuotesInFile) {
out << "\"";
}
out << std::endl;
- totalSize += cmSystemTools::FileLength(dirName + *fileIt);
+ totalSize += cmSystemTools::FileLength(dirName + file);
}
}
@@ -753,20 +733,21 @@ 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, &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";
- cmGeneratedFileStream ofs(tmpFile.c_str());
+ std::string tmpFile = cmStrCat(
+ this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/CompressZip.log");
+ cmGeneratedFileStream ofs(tmpFile);
ofs << "# Run command: " << cmd << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running zip command: "
- << cmd << std::endl
- << "Please check " << tmpFile << " for errors"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running zip command: " << cmd << std::endl
+ << "Please check "
+ << tmpFile << " for errors"
+ << std::endl);
return "";
}
@@ -798,17 +779,14 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
macrosOut << "!macro Remove_${" << component->Name << "}\n";
macrosOut << " IntCmp $" << component->Name << "_was_installed 0 noremove_"
<< component->Name << "\n";
- std::vector<std::string>::iterator pathIt;
std::string path;
- for (pathIt = component->Files.begin(); pathIt != component->Files.end();
- ++pathIt) {
- path = *pathIt;
+ for (std::string const& pathIt : component->Files) {
+ path = pathIt;
std::replace(path.begin(), path.end(), '/', '\\');
macrosOut << " Delete \"" << componentOutputDir << "\\" << path << "\"\n";
}
- for (pathIt = component->Directories.begin();
- pathIt != component->Directories.end(); ++pathIt) {
- path = *pathIt;
+ for (std::string const& pathIt : component->Directories) {
+ path = pathIt;
std::replace(path.begin(), path.end(), '/', '\\');
macrosOut << " RMDir \"" << componentOutputDir << "\\" << path << "\"\n";
}
@@ -841,17 +819,14 @@ std::string cmCPackNSISGenerator::CreateSelectionDependenciesDescription(
visited.insert(component);
std::ostringstream out;
- std::vector<cmCPackComponent*>::iterator dependIt;
- for (dependIt = component->Dependencies.begin();
- dependIt != component->Dependencies.end(); ++dependIt) {
+ for (cmCPackComponent* depend : component->Dependencies) {
// Write NSIS code to select this dependency
- out << " SectionGetFlags ${" << (*dependIt)->Name << "} $0\n";
+ out << " SectionGetFlags ${" << depend->Name << "} $0\n";
out << " IntOp $0 $0 | ${SF_SELECTED}\n";
- out << " SectionSetFlags ${" << (*dependIt)->Name << "} $0\n";
- out << " IntOp $" << (*dependIt)->Name
- << "_selected 0 + ${SF_SELECTED}\n";
+ out << " SectionSetFlags ${" << depend->Name << "} $0\n";
+ out << " IntOp $" << depend->Name << "_selected 0 + ${SF_SELECTED}\n";
// Recurse
- out << CreateSelectionDependenciesDescription(*dependIt, visited).c_str();
+ out << CreateSelectionDependenciesDescription(depend, visited).c_str();
}
return out.str();
@@ -867,19 +842,16 @@ std::string cmCPackNSISGenerator::CreateDeselectionDependenciesDescription(
visited.insert(component);
std::ostringstream out;
- std::vector<cmCPackComponent*>::iterator dependIt;
- for (dependIt = component->ReverseDependencies.begin();
- dependIt != component->ReverseDependencies.end(); ++dependIt) {
+ for (cmCPackComponent* depend : component->ReverseDependencies) {
// Write NSIS code to deselect this dependency
- out << " SectionGetFlags ${" << (*dependIt)->Name << "} $0\n";
+ out << " SectionGetFlags ${" << depend->Name << "} $0\n";
out << " IntOp $1 ${SF_SELECTED} ~\n";
out << " IntOp $0 $0 & $1\n";
- out << " SectionSetFlags ${" << (*dependIt)->Name << "} $0\n";
- out << " IntOp $" << (*dependIt)->Name << "_selected 0 + 0\n";
+ out << " SectionSetFlags ${" << depend->Name << "} $0\n";
+ out << " IntOp $" << depend->Name << "_selected 0 + 0\n";
// Recurse
- out
- << CreateDeselectionDependenciesDescription(*dependIt, visited).c_str();
+ out << CreateDeselectionDependenciesDescription(depend, visited).c_str();
}
return out.str();
@@ -903,20 +875,16 @@ std::string cmCPackNSISGenerator::CreateComponentGroupDescription(
code += "\"" + group->DisplayName + "\" " + group->Name + "\n";
}
- std::vector<cmCPackComponentGroup*>::iterator groupIt;
- for (groupIt = group->Subgroups.begin(); groupIt != group->Subgroups.end();
- ++groupIt) {
- code += this->CreateComponentGroupDescription(*groupIt, macrosOut);
+ for (cmCPackComponentGroup* g : group->Subgroups) {
+ code += this->CreateComponentGroupDescription(g, macrosOut);
}
- std::vector<cmCPackComponent*>::iterator comp;
- for (comp = group->Components.begin(); comp != group->Components.end();
- ++comp) {
- if ((*comp)->Files.empty()) {
+ for (cmCPackComponent* comp : group->Components) {
+ if (comp->Files.empty()) {
continue;
}
- code += this->CreateComponentDescription(*comp, macrosOut);
+ code += this->CreateComponentDescription(comp, macrosOut);
}
code += "SectionGroupEnd\n";
return code;
diff --git a/Source/CPack/cmCPackNSISGenerator.h b/Source/CPack/cmCPackNSISGenerator.h
index 77be3256d..0af37af50 100644
--- a/Source/CPack/cmCPackNSISGenerator.h
+++ b/Source/CPack/cmCPackNSISGenerator.h
@@ -3,15 +3,15 @@
#ifndef cmCPackNSISGenerator_h
#define cmCPackNSISGenerator_h
-#include "cmConfigure.h"
-
-#include "cmCPackGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <set>
#include <string>
#include <vector>
+#include "cmCPackGenerator.h"
+
class cmCPackComponent;
class cmCPackComponentGroup;
@@ -34,22 +34,22 @@ public:
* Construct generator
*/
cmCPackNSISGenerator(bool nsis64 = false);
- ~cmCPackNSISGenerator() CM_OVERRIDE;
+ ~cmCPackNSISGenerator() override;
protected:
- int InitializeInternal() CM_OVERRIDE;
+ int InitializeInternal() override;
void CreateMenuLinks(std::ostream& str, std::ostream& deleteStr);
- int PackageFiles() CM_OVERRIDE;
- const char* GetOutputExtension() CM_OVERRIDE { return ".exe"; }
- const char* GetOutputPostfix() CM_OVERRIDE { return "win32"; }
+ int PackageFiles() override;
+ const char* GetOutputExtension() override { return ".exe"; }
+ const char* GetOutputPostfix() override { return "win32"; }
bool GetListOfSubdirectories(const char* dir,
std::vector<std::string>& dirs);
- enum cmCPackGenerator::CPackSetDestdirSupport SupportsSetDestdir() const
- CM_OVERRIDE;
- bool SupportsAbsoluteDestination() const CM_OVERRIDE;
- bool SupportsComponentInstallation() const CM_OVERRIDE;
+ enum cmCPackGenerator::CPackSetDestdirSupport SupportsSetDestdir()
+ const override;
+ bool SupportsAbsoluteDestination() const override;
+ bool SupportsComponentInstallation() const override;
/// Produce a string that contains the NSIS code to describe a
/// particular component. Any added macros will be emitted via
diff --git a/Source/CPack/cmCPackNuGetGenerator.cxx b/Source/CPack/cmCPackNuGetGenerator.cxx
new file mode 100644
index 000000000..60faecd0b
--- /dev/null
+++ b/Source/CPack/cmCPackNuGetGenerator.cxx
@@ -0,0 +1,141 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackNuGetGenerator.h"
+
+#include <algorithm>
+#include <iterator>
+#include <map>
+#include <ostream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cmCPackComponentGroup.h"
+#include "cmCPackLog.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+bool cmCPackNuGetGenerator::SupportsComponentInstallation() const
+{
+ return IsOn("CPACK_NUGET_COMPONENT_INSTALL");
+}
+
+int cmCPackNuGetGenerator::PackageFiles()
+{
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: " << toplevel << std::endl);
+
+ /* Reset package file name list it will be populated after the
+ * `CPackNuGet.cmake` run */
+ packageFileNames.clear();
+
+ /* Are we in the component packaging case */
+ if (WantsComponentInstallation()) {
+ if (componentPackageMethod == ONE_PACKAGE) {
+ // CASE 1 : COMPONENT ALL-IN-ONE package
+ // Meaning that all per-component pre-installed files
+ // goes into the single package.
+ this->SetOption("CPACK_NUGET_ALL_IN_ONE", "TRUE");
+ SetupGroupComponentVariables(true);
+ } else {
+ // CASE 2 : COMPONENT CLASSICAL package(s) (i.e. not all-in-one)
+ // There will be 1 package for each component group
+ // however one may require to ignore component group and
+ // in this case you'll get 1 package for each component.
+ SetupGroupComponentVariables(componentPackageMethod ==
+ ONE_PACKAGE_PER_COMPONENT);
+ }
+ } else {
+ // CASE 3 : NON COMPONENT package.
+ this->SetOption("CPACK_NUGET_ORDINAL_MONOLITIC", "TRUE");
+ }
+
+ auto retval = this->ReadListFile("Internal/CPack/CPackNuGet.cmake");
+ if (retval) {
+ AddGeneratedPackageNames();
+ } else {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while execution CPackNuGet.cmake" << std::endl);
+ }
+
+ return retval;
+}
+
+void cmCPackNuGetGenerator::SetupGroupComponentVariables(bool ignoreGroup)
+{
+ // The default behavior is to have one package by component group
+ // unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
+ if (!ignoreGroup) {
+ std::vector<std::string> groups;
+ for (auto const& compG : this->ComponentGroups) {
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Packaging component group: " << compG.first << std::endl);
+ groups.push_back(compG.first);
+ auto compGUp =
+ cmSystemTools::UpperCase(cmSystemTools::MakeCidentifier(compG.first));
+
+ // Collect components for this group
+ std::vector<std::string> components;
+ std::transform(begin(compG.second.Components),
+ end(compG.second.Components),
+ std::back_inserter(components),
+ [](cmCPackComponent const* comp) { return comp->Name; });
+ this->SetOption("CPACK_NUGET_" + compGUp + "_GROUP_COMPONENTS",
+ cmJoin(components, ";").c_str());
+ }
+ if (!groups.empty()) {
+ this->SetOption("CPACK_NUGET_GROUPS", cmJoin(groups, ";").c_str());
+ }
+
+ // Handle Orphan components (components not belonging to any groups)
+ std::vector<std::string> components;
+ for (auto const& comp : this->Components) {
+ // Does the component belong to a group?
+ if (comp.second.Group == nullptr) {
+ cmCPackLogger(
+ cmCPackLog::LOG_VERBOSE,
+ "Component <"
+ << comp.second.Name
+ << "> does not belong to any group, package it separately."
+ << std::endl);
+ components.push_back(comp.first);
+ }
+ }
+ if (!components.empty()) {
+ this->SetOption("CPACK_NUGET_COMPONENTS",
+ cmJoin(components, ";").c_str());
+ }
+
+ } else {
+ std::vector<std::string> components;
+ components.reserve(this->Components.size());
+ std::transform(begin(this->Components), end(this->Components),
+ std::back_inserter(components),
+ [](std::pair<std::string, cmCPackComponent> const& comp) {
+ return comp.first;
+ });
+ this->SetOption("CPACK_NUGET_COMPONENTS", cmJoin(components, ";").c_str());
+ }
+}
+
+void cmCPackNuGetGenerator::AddGeneratedPackageNames()
+{
+ const char* const files_list = this->GetOption("GEN_CPACK_OUTPUT_FILES");
+ if (!files_list) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
+ "Error while execution CPackNuGet.cmake: No NuGet package has generated"
+ << std::endl);
+ return;
+ }
+ // add the generated packages to package file names list
+ std::string fileNames{ files_list };
+ const char sep = ';';
+ std::string::size_type pos1 = 0;
+ std::string::size_type pos2 = fileNames.find(sep, pos1 + 1);
+ while (pos2 != std::string::npos) {
+ packageFileNames.push_back(fileNames.substr(pos1, pos2 - pos1));
+ pos1 = pos2 + 1;
+ pos2 = fileNames.find(sep, pos1 + 1);
+ }
+ packageFileNames.push_back(fileNames.substr(pos1, pos2 - pos1));
+}
diff --git a/Source/CPack/cmCPackNuGetGenerator.h b/Source/CPack/cmCPackNuGetGenerator.h
new file mode 100644
index 000000000..a59db2d04
--- /dev/null
+++ b/Source/CPack/cmCPackNuGetGenerator.h
@@ -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. */
+#ifndef cmCPackNuGetGenerator_h
+#define cmCPackNuGetGenerator_h
+
+#include "cmCPackGenerator.h"
+
+/** \class cmCPackNuGetGenerator
+ * \brief A generator for RPM packages
+ */
+class cmCPackNuGetGenerator : public cmCPackGenerator
+{
+public:
+ cmCPackTypeMacro(cmCPackNuGetGenerator, cmCPackGenerator);
+
+ // NOTE In fact, it is possible to have NuGet not only for Windows...
+ // https://docs.microsoft.com/en-us/nuget/install-nuget-client-tools
+ static bool CanGenerate() { return true; }
+
+protected:
+ bool SupportsComponentInstallation() const override;
+ int PackageFiles() override;
+
+ const char* GetOutputExtension() override { return ".nupkg"; }
+ bool SupportsAbsoluteDestination() const override { return false; }
+ /**
+ * The method used to prepare variables when component
+ * install is used.
+ */
+ void SetupGroupComponentVariables(bool ignoreGroup);
+ /**
+ * Populate \c packageFileNames vector of built packages.
+ */
+ void AddGeneratedPackageNames();
+};
+
+#endif
diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx
index 8ea88a87a..951c65f4d 100644
--- a/Source/CPack/cmCPackOSXX11Generator.cxx
+++ b/Source/CPack/cmCPackOSXX11Generator.cxx
@@ -4,19 +4,18 @@
#include <sstream>
+#include "cm_sys_stat.h"
+
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cm_sys_stat.h"
-cmCPackOSXX11Generator::cmCPackOSXX11Generator()
-{
-}
+cmCPackOSXX11Generator::cmCPackOSXX11Generator() = default;
-cmCPackOSXX11Generator::~cmCPackOSXX11Generator()
-{
-}
+cmCPackOSXX11Generator::~cmCPackOSXX11Generator() = default;
int cmCPackOSXX11Generator::PackageFiles()
{
@@ -26,13 +25,13 @@ int cmCPackOSXX11Generator::PackageFiles()
const char* cpackPackageExecutables =
this->GetOption("CPACK_PACKAGE_EXECUTABLES");
if (cpackPackageExecutables) {
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "The cpackPackageExecutables: "
- << cpackPackageExecutables << "." << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "The cpackPackageExecutables: " << cpackPackageExecutables
+ << "." << std::endl);
std::ostringstream str;
std::ostringstream deleteStr;
- std::vector<std::string> cpackPackageExecutablesVector;
- cmSystemTools::ExpandListArgument(cpackPackageExecutables,
- cpackPackageExecutablesVector);
+ std::vector<std::string> cpackPackageExecutablesVector =
+ cmExpandedList(cpackPackageExecutables);
if (cpackPackageExecutablesVector.size() % 2 != 0) {
cmCPackLogger(
cmCPackLog::LOG_ERROR,
@@ -57,16 +56,14 @@ int cmCPackOSXX11Generator::PackageFiles()
diskImageDirectory + "/.background";
// App bundle directories
- std::string packageDirFileName = toplevel;
- packageDirFileName += "/";
- packageDirFileName += this->GetOption("CPACK_PACKAGE_FILE_NAME");
- packageDirFileName += ".app";
+ std::string packageDirFileName = cmStrCat(
+ toplevel, '/', this->GetOption("CPACK_PACKAGE_FILE_NAME"), ".app");
std::string contentsDirectory = packageDirFileName + "/Contents";
std::string resourcesDirectory = contentsDirectory + "/Resources";
std::string appDirectory = contentsDirectory + "/MacOS";
std::string scriptDirectory = resourcesDirectory + "/Scripts";
- std::string resourceFileName = this->GetOption("CPACK_PACKAGE_FILE_NAME");
- resourceFileName += ".rsrc";
+ std::string resourceFileName =
+ cmStrCat(this->GetOption("CPACK_PACKAGE_FILE_NAME"), ".rsrc");
const char* dir = resourcesDirectory.c_str();
const char* appdir = appDirectory.c_str();
@@ -77,14 +74,15 @@ int cmCPackOSXX11Generator::PackageFiles()
if (iconFile) {
std::string iconFileName = cmsys::SystemTools::GetFilenameName(iconFile);
if (!cmSystemTools::FileExists(iconFile)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find icon file: "
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find icon file: "
<< iconFile
<< ". Please check CPACK_PACKAGE_ICON setting."
<< std::endl);
return 0;
}
std::string destFileName = resourcesDirectory + "/" + iconFileName;
- this->ConfigureFile(iconFile, destFileName.c_str(), true);
+ this->ConfigureFile(iconFile, destFileName, true);
this->SetOptionIfNotSet("CPACK_APPLE_GUI_ICON", iconFileName.c_str());
}
@@ -108,19 +106,16 @@ int cmCPackOSXX11Generator::PackageFiles()
!this->CopyResourcePlistFile("OSXScriptLauncher", appdir,
this->GetOption("CPACK_PACKAGE_FILE_NAME"),
true)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem copying the resource files" << std::endl);
return 0;
}
// Two of the files need to have execute permission, so ensure they do:
- std::string runTimeScript = dir;
- runTimeScript += "/";
- runTimeScript += "RuntimeScript";
+ std::string runTimeScript = cmStrCat(dir, "/RuntimeScript");
- std::string appScriptName = appdir;
- appScriptName += "/";
- appScriptName += this->GetOption("CPACK_PACKAGE_FILE_NAME");
+ std::string appScriptName =
+ cmStrCat(appdir, '/', this->GetOption("CPACK_PACKAGE_FILE_NAME"));
mode_t mode;
if (cmsys::SystemTools::GetPermissions(runTimeScript.c_str(), mode)) {
@@ -140,23 +135,24 @@ int cmCPackOSXX11Generator::PackageFiles()
}
std::string output;
- std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- tmpFile += "/hdiutilOutput.log";
+ std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
+ "/hdiutilOutput.log");
std::ostringstream dmgCmd;
dmgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM_DISK_IMAGE")
- << "\" create -ov -format UDZO -srcfolder \"" << diskImageDirectory
- << "\" \"" << packageFileNames[0] << "\"";
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Compress disk image using command: "
- << dmgCmd.str() << std::endl);
+ << "\" create -ov -fs HFS+ -format UDZO -srcfolder \""
+ << diskImageDirectory << "\" \"" << packageFileNames[0] << "\"";
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Compress disk image using command: " << dmgCmd.str()
+ << std::endl);
// since we get random dashboard failures with this one
// try running it more than once
int retVal = 1;
int numTries = 10;
bool res = false;
while (numTries > 0) {
- res =
- cmSystemTools::RunSingleCommand(dmgCmd.str().c_str(), &output, &output,
- &retVal, 0, this->GeneratorVerbose, 0);
+ res = cmSystemTools::RunSingleCommand(
+ dmgCmd.str(), &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+ cmDuration::zero());
if (res && !retVal) {
numTries = -1;
break;
@@ -165,11 +161,12 @@ int cmCPackOSXX11Generator::PackageFiles()
numTries--;
}
if (!res || retVal) {
- cmGeneratedFileStream ofs(tmpFile.c_str());
+ cmGeneratedFileStream ofs(tmpFile);
ofs << "# Run command: " << dmgCmd.str() << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running hdiutil command: "
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running hdiutil command: "
<< dmgCmd.str() << std::endl
<< "Please check " << tmpFile << " for errors"
<< std::endl);
@@ -181,13 +178,13 @@ int cmCPackOSXX11Generator::PackageFiles()
int cmCPackOSXX11Generator::InitializeInternal()
{
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "cmCPackOSXX11Generator::Initialize()"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "cmCPackOSXX11Generator::Initialize()" << std::endl);
std::vector<std::string> path;
std::string pkgPath = cmSystemTools::FindProgram("hdiutil", path, false);
if (pkgPath.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find hdiutil compiler"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find hdiutil compiler" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE",
@@ -227,15 +224,14 @@ bool cmCPackOSXX11Generator::CopyCreateResourceFile(const std::string& name)
return false;
}
- std::string destFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- destFileName += "/Resources/";
- destFileName += name + ext;
+ std::string destFileName = cmStrCat(
+this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/Resources/", name, ext );
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
<< (inFileName ? inFileName : "(NULL)")
<< " to " << destFileName << std::endl);
- this->ConfigureFile(inFileName, destFileName.c_str());
+ this->ConfigureFile(inFileName, destFileName);
return true;
}
*/
@@ -244,9 +240,7 @@ bool cmCPackOSXX11Generator::CopyResourcePlistFile(
const std::string& name, const std::string& dir,
const char* outputFileName /* = 0 */, bool copyOnly /* = false */)
{
- std::string inFName = "CPack.";
- inFName += name;
- inFName += ".in";
+ std::string inFName = cmStrCat("CPack.", name, ".in");
std::string inFileName = this->FindTemplate(inFName.c_str());
if (inFileName.empty()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
@@ -258,20 +252,19 @@ bool cmCPackOSXX11Generator::CopyResourcePlistFile(
outputFileName = name.c_str();
}
- std::string destFileName = dir;
- destFileName += "/";
- destFileName += outputFileName;
+ std::string destFileName = cmStrCat(dir, '/', outputFileName);
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
- << inFileName << " to " << destFileName << std::endl);
- this->ConfigureFile(inFileName.c_str(), destFileName.c_str(), copyOnly);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Configure file: " << inFileName << " to " << destFileName
+ << std::endl);
+ this->ConfigureFile(inFileName, destFileName, copyOnly);
return true;
}
const char* cmCPackOSXX11Generator::GetPackagingInstallPrefix()
{
- this->InstallPrefix = "/";
- this->InstallPrefix += this->GetOption("CPACK_PACKAGE_FILE_NAME");
- this->InstallPrefix += ".app/Contents/Resources";
+ this->InstallPrefix =
+ cmStrCat('/', this->GetOption("CPACK_PACKAGE_FILE_NAME"),
+ ".app/Contents/Resources");
return this->InstallPrefix.c_str();
}
diff --git a/Source/CPack/cmCPackOSXX11Generator.h b/Source/CPack/cmCPackOSXX11Generator.h
index 0eebc6dd1..a6461c854 100644
--- a/Source/CPack/cmCPackOSXX11Generator.h
+++ b/Source/CPack/cmCPackOSXX11Generator.h
@@ -3,7 +3,7 @@
#ifndef cmCPackOSXX11Generator_h
#define cmCPackOSXX11Generator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
@@ -23,13 +23,13 @@ public:
* Construct generator
*/
cmCPackOSXX11Generator();
- virtual ~cmCPackOSXX11Generator();
+ ~cmCPackOSXX11Generator() override;
protected:
- virtual int InitializeInternal() CM_OVERRIDE;
- int PackageFiles() CM_OVERRIDE;
- const char* GetPackagingInstallPrefix() CM_OVERRIDE;
- const char* GetOutputExtension() CM_OVERRIDE { return ".dmg"; }
+ virtual int InitializeInternal() override;
+ int PackageFiles() override;
+ const char* GetPackagingInstallPrefix() override;
+ const char* GetOutputExtension() override { return ".dmg"; }
// bool CopyCreateResourceFile(const std::string& name,
// const std::string& dir);
diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx
index 70ae267fb..dae5ec9d4 100644
--- a/Source/CPack/cmCPackPKGGenerator.cxx
+++ b/Source/CPack/cmCPackPKGGenerator.cxx
@@ -7,6 +7,7 @@
#include "cmCPackComponentGroup.h"
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLWriter.h"
@@ -15,9 +16,7 @@ cmCPackPKGGenerator::cmCPackPKGGenerator()
this->componentPackageMethod = ONE_PACKAGE;
}
-cmCPackPKGGenerator::~cmCPackPKGGenerator()
-{
-}
+cmCPackPKGGenerator::~cmCPackPKGGenerator() = default;
bool cmCPackPKGGenerator::SupportsComponentInstallation() const
{
@@ -26,8 +25,8 @@ bool cmCPackPKGGenerator::SupportsComponentInstallation() const
int cmCPackPKGGenerator::InitializeInternal()
{
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "cmCPackPKGGenerator::Initialize()"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "cmCPackPKGGenerator::Initialize()" << std::endl);
return this->Superclass::InitializeInternal();
}
@@ -36,15 +35,15 @@ std::string cmCPackPKGGenerator::GetPackageName(
const cmCPackComponent& component)
{
if (component.ArchiveFile.empty()) {
- std::string packagesDir = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
- packagesDir += ".dummy";
+ std::string packagesDir =
+ cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), ".dummy");
std::ostringstream out;
out << cmSystemTools::GetFilenameWithoutLastExtension(packagesDir) << "-"
<< component.Name << ".pkg";
return out.str();
- } else {
- return component.ArchiveFile + ".pkg";
}
+
+ return component.ArchiveFile + ".pkg";
}
void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile)
@@ -52,13 +51,14 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile)
std::string distributionTemplate =
this->FindTemplate("CPack.distribution.dist.in");
if (distributionTemplate.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find input file: "
- << distributionTemplate << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find input file: " << distributionTemplate
+ << std::endl);
return;
}
- std::string distributionFile = metapackageFile;
- distributionFile += "/Contents/distribution.dist";
+ std::string distributionFile =
+ cmStrCat(metapackageFile, "/Contents/distribution.dist");
// Create the choice outline, which provides a tree-based view of
// the components in their groups.
@@ -67,21 +67,17 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile)
xout.StartElement("choices-outline");
// Emit the outline for the groups
- std::map<std::string, cmCPackComponentGroup>::iterator groupIt;
- for (groupIt = this->ComponentGroups.begin();
- groupIt != this->ComponentGroups.end(); ++groupIt) {
- if (groupIt->second.ParentGroup == 0) {
- CreateChoiceOutline(groupIt->second, xout);
+ for (auto const& group : this->ComponentGroups) {
+ if (group.second.ParentGroup == nullptr) {
+ CreateChoiceOutline(group.second, xout);
}
}
// Emit the outline for the non-grouped components
- std::map<std::string, cmCPackComponent>::iterator compIt;
- for (compIt = this->Components.begin(); compIt != this->Components.end();
- ++compIt) {
- if (!compIt->second.Group) {
+ for (auto const& comp : this->Components) {
+ if (!comp.second.Group) {
xout.StartElement("line");
- xout.Attribute("choice", compIt->first + "Choice");
+ xout.Attribute("choice", comp.first + "Choice");
xout.Content(""); // Avoid self-closing tag.
xout.EndElement();
}
@@ -95,13 +91,11 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile)
xout.EndElement(); // choices-outline>
// Create the actual choices
- for (groupIt = this->ComponentGroups.begin();
- groupIt != this->ComponentGroups.end(); ++groupIt) {
- CreateChoice(groupIt->second, xout);
+ for (auto const& group : this->ComponentGroups) {
+ CreateChoice(group.second, xout);
}
- for (compIt = this->Components.begin(); compIt != this->Components.end();
- ++compIt) {
- CreateChoice(compIt->second, xout);
+ for (auto const& comp : this->Components) {
+ CreateChoice(comp.second, xout);
}
if (!this->PostFlightComponent.Name.empty()) {
@@ -112,7 +106,7 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile)
// Create the distribution.dist file in the metapackage to turn it
// into a distribution package.
- this->ConfigureFile(distributionTemplate.c_str(), distributionFile.c_str());
+ this->ConfigureFile(distributionTemplate, distributionFile);
}
void cmCPackPKGGenerator::CreateChoiceOutline(
@@ -120,17 +114,13 @@ void cmCPackPKGGenerator::CreateChoiceOutline(
{
xout.StartElement("line");
xout.Attribute("choice", group.Name + "Choice");
- std::vector<cmCPackComponentGroup*>::const_iterator groupIt;
- for (groupIt = group.Subgroups.begin(); groupIt != group.Subgroups.end();
- ++groupIt) {
- CreateChoiceOutline(**groupIt, xout);
+ for (cmCPackComponentGroup* subgroup : group.Subgroups) {
+ CreateChoiceOutline(*subgroup, xout);
}
- std::vector<cmCPackComponent*>::const_iterator compIt;
- for (compIt = group.Components.begin(); compIt != group.Components.end();
- ++compIt) {
+ for (cmCPackComponent* comp : group.Components) {
xout.StartElement("line");
- xout.Attribute("choice", (*compIt)->Name + "Choice");
+ xout.Attribute("choice", comp->Name + "Choice");
xout.Content(""); // Avoid self-closing tag.
xout.EndElement();
}
@@ -155,12 +145,9 @@ void cmCPackPKGGenerator::CreateChoice(const cmCPackComponentGroup& group,
void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component,
cmXMLWriter& xout)
{
- std::string packageId = "com.";
- packageId += this->GetOption("CPACK_PACKAGE_VENDOR");
- packageId += '.';
- packageId += this->GetOption("CPACK_PACKAGE_NAME");
- packageId += '.';
- packageId += component.Name;
+ std::string packageId =
+ cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"), '.',
+ this->GetOption("CPACK_PACKAGE_NAME"), '.', component.Name);
xout.StartElement("choice");
xout.Attribute("id", component.Name + "Choice");
@@ -189,7 +176,7 @@ void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component,
// This way, selecting C will automatically select everything it depends
// on (B and A), while selecting something that depends on C--either D
// or E--will automatically cause C to get selected.
- std::ostringstream selected("my.choice.selected");
+ std::ostringstream selected("my.choice.selected", std::ios_base::ate);
std::set<const cmCPackComponent*> visited;
AddDependencyAttributes(component, visited, selected);
visited.clear();
@@ -203,14 +190,13 @@ void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component,
// Create a description of the package associated with this
// component.
- std::string relativePackageLocation = "Contents/Packages/";
- relativePackageLocation += this->GetPackageName(component);
+ std::string relativePackageLocation =
+ cmStrCat("Contents/Packages/", this->GetPackageName(component));
// Determine the installed size of the package.
- std::string dirName = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
- dirName += '/';
- dirName += component.Name;
- dirName += this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
+ std::string dirName =
+ cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), '/', component.Name,
+ this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"));
unsigned long installedSize = component.GetInstalledSizeInKbytes(dirName);
xout.StartElement("pkg-ref");
@@ -224,7 +210,8 @@ void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component,
xout.Content(this->GetPackageName(component));
} else {
xout.Content("file:./");
- xout.Content(relativePackageLocation);
+ xout.Content(cmSystemTools::EncodeURL(relativePackageLocation,
+ /*escapeSlashes=*/false));
}
xout.EndElement(); // pkg-ref
}
@@ -238,11 +225,9 @@ void cmCPackPKGGenerator::AddDependencyAttributes(
}
visited.insert(&component);
- std::vector<cmCPackComponent*>::const_iterator dependIt;
- for (dependIt = component.Dependencies.begin();
- dependIt != component.Dependencies.end(); ++dependIt) {
- out << " && choices['" << (*dependIt)->Name << "Choice'].selected";
- AddDependencyAttributes(**dependIt, visited, out);
+ for (cmCPackComponent* depend : component.Dependencies) {
+ out << " && choices['" << depend->Name << "Choice'].selected";
+ AddDependencyAttributes(*depend, visited, out);
}
}
@@ -255,11 +240,9 @@ void cmCPackPKGGenerator::AddReverseDependencyAttributes(
}
visited.insert(&component);
- std::vector<cmCPackComponent*>::const_iterator dependIt;
- for (dependIt = component.ReverseDependencies.begin();
- dependIt != component.ReverseDependencies.end(); ++dependIt) {
- out << " || choices['" << (*dependIt)->Name << "Choice'].selected";
- AddReverseDependencyAttributes(**dependIt, visited, out);
+ for (cmCPackComponent* depend : component.ReverseDependencies) {
+ out << " || choices['" << depend->Name << "Choice'].selected";
+ AddReverseDependencyAttributes(*depend, visited, out);
}
}
@@ -270,32 +253,33 @@ bool cmCPackPKGGenerator::CopyCreateResourceFile(const std::string& name,
std::string cpackVar = "CPACK_RESOURCE_FILE_" + uname;
const char* inFileName = this->GetOption(cpackVar);
if (!inFileName) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "CPack option: "
- << cpackVar.c_str()
- << " not specified. It should point to "
- << (!name.empty() ? name : "<empty>") << ".rtf, " << name
- << ".html, or " << name << ".txt file" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPack option: " << cpackVar.c_str()
+ << " not specified. It should point to "
+ << (!name.empty() ? name : "<empty>")
+ << ".rtf, " << name << ".html, or " << name
+ << ".txt file" << std::endl);
return false;
}
if (!cmSystemTools::FileExists(inFileName)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find "
- << (!name.empty() ? name : "<empty>")
- << " resource file: " << inFileName << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find " << (!name.empty() ? name : "<empty>")
+ << " resource file: " << inFileName
+ << std::endl);
return false;
}
std::string ext = cmSystemTools::GetFilenameLastExtension(inFileName);
if (ext != ".rtfd" && ext != ".rtf" && ext != ".html" && ext != ".txt") {
cmCPackLogger(
- cmCPackLog::LOG_ERROR, "Bad file extension specified: "
+ cmCPackLog::LOG_ERROR,
+ "Bad file extension specified: "
<< ext
<< ". Currently only .rtfd, .rtf, .html, and .txt files allowed."
<< std::endl);
return false;
}
- std::string destFileName = dirName;
- destFileName += '/';
- destFileName += name + ext;
+ std::string destFileName = cmStrCat(dirName, '/', name, ext);
// Set this so that distribution.dist gets the right name (without
// the path).
@@ -305,7 +289,7 @@ bool cmCPackPKGGenerator::CopyCreateResourceFile(const std::string& name,
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Configure file: " << (inFileName ? inFileName : "(NULL)")
<< " to " << destFileName << std::endl);
- this->ConfigureFile(inFileName, destFileName.c_str());
+ this->ConfigureFile(inFileName, destFileName);
return true;
}
@@ -316,9 +300,7 @@ bool cmCPackPKGGenerator::CopyResourcePlistFile(const std::string& name,
outName = name.c_str();
}
- std::string inFName = "CPack.";
- inFName += name;
- inFName += ".in";
+ std::string inFName = cmStrCat("CPack.", name, ".in");
std::string inFileName = this->FindTemplate(inFName.c_str());
if (inFileName.empty()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
@@ -326,13 +308,13 @@ bool cmCPackPKGGenerator::CopyResourcePlistFile(const std::string& name,
return false;
}
- std::string destFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- destFileName += "/";
- destFileName += outName;
+ std::string destFileName =
+ cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', outName);
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
- << inFileName << " to " << destFileName << std::endl);
- this->ConfigureFile(inFileName.c_str(), destFileName.c_str());
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Configure file: " << inFileName << " to " << destFileName
+ << std::endl);
+ this->ConfigureFile(inFileName, destFileName);
return true;
}
@@ -340,9 +322,7 @@ int cmCPackPKGGenerator::CopyInstallScript(const std::string& resdir,
const std::string& script,
const std::string& name)
{
- std::string dst = resdir;
- dst += "/";
- dst += name;
+ std::string dst = cmStrCat(resdir, '/', name);
cmSystemTools::CopyFileAlways(script, dst);
cmSystemTools::SetPermissions(dst.c_str(), 0777);
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
diff --git a/Source/CPack/cmCPackPKGGenerator.h b/Source/CPack/cmCPackPKGGenerator.h
index f873c5936..69286ffde 100644
--- a/Source/CPack/cmCPackPKGGenerator.h
+++ b/Source/CPack/cmCPackPKGGenerator.h
@@ -3,7 +3,7 @@
#ifndef cmCPackPKGGenerator_h
#define cmCPackPKGGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <set>
#include <sstream>
@@ -27,13 +27,13 @@ public:
* Construct generator
*/
cmCPackPKGGenerator();
- virtual ~cmCPackPKGGenerator();
+ ~cmCPackPKGGenerator() override;
- bool SupportsComponentInstallation() const CM_OVERRIDE;
+ bool SupportsComponentInstallation() const override;
protected:
- int InitializeInternal() CM_OVERRIDE;
- const char* GetOutputPostfix() CM_OVERRIDE { return "darwin"; }
+ int InitializeInternal() override;
+ const char* GetOutputPostfix() override { return "darwin"; }
// Copies or creates the resource file with the given name to the
// package or package staging directory dirName. The variable
diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx
index 8db7cfb3d..c5ba726d5 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.cxx
+++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx
@@ -2,18 +2,21 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackPackageMakerGenerator.h"
-#include "cmsys/FStream.hxx"
-#include "cmsys/RegularExpression.hxx"
-#include <assert.h>
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
#include <map>
#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
#include <string>
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+
#include "cmCPackComponentGroup.h"
#include "cmCPackLog.h"
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLWriter.h"
@@ -29,9 +32,7 @@ cmCPackPackageMakerGenerator::cmCPackPackageMakerGenerator()
this->PackageCompatibilityVersion = getVersion(10, 4);
}
-cmCPackPackageMakerGenerator::~cmCPackPackageMakerGenerator()
-{
-}
+cmCPackPackageMakerGenerator::~cmCPackPackageMakerGenerator() = default;
bool cmCPackPackageMakerGenerator::SupportsComponentInstallation() const
{
@@ -48,8 +49,8 @@ int cmCPackPackageMakerGenerator::PackageFiles()
this->GetOption("CPACK_TEMPORARY_DIRECTORY");
if (this->Components.empty()) {
packageDirFileName += ".pkg";
- resDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- resDir += "/Resources";
+ resDir =
+ cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/Resources");
} else {
packageDirFileName += ".mpkg";
if (!cmsys::SystemTools::MakeDirectory(packageDirFileName.c_str())) {
@@ -59,8 +60,7 @@ int cmCPackPackageMakerGenerator::PackageFiles()
return 0;
}
- resDir = packageDirFileName;
- resDir += "/Contents";
+ resDir = cmStrCat(packageDirFileName, "/Contents");
if (!cmsys::SystemTools::MakeDirectory(resDir.c_str())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"unable to create package subdirectory " << resDir
@@ -156,8 +156,8 @@ int cmCPackPackageMakerGenerator::PackageFiles()
if (!this->Components.empty()) {
// Create the directory where component packages will be built.
- std::string basePackageDir = packageDirFileName;
- basePackageDir += "/Contents/Packages";
+ std::string basePackageDir =
+ cmStrCat(packageDirFileName, "/Contents/Packages");
if (!cmsys::SystemTools::MakeDirectory(basePackageDir.c_str())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem creating component packages directory: "
@@ -173,8 +173,8 @@ int cmCPackPackageMakerGenerator::PackageFiles()
if (userUploadDirectory && *userUploadDirectory) {
uploadDirectory = userUploadDirectory;
} else {
- uploadDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY");
- uploadDirectory += "/CPackUploads";
+ uploadDirectory =
+ cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/CPackUploads");
}
// Create packages for each component
@@ -233,9 +233,7 @@ int cmCPackPackageMakerGenerator::PackageFiles()
packageFile += '/';
packageFile += GetPackageName(compIt->second);
- std::string packageDir = toplevel;
- packageDir += '/';
- packageDir += compIt->first;
+ std::string packageDir = cmStrCat(toplevel, '/', compIt->first);
if (!this->GenerateComponentPackage(
packageFile.c_str(), packageDir.c_str(), compIt->second)) {
return 0;
@@ -250,8 +248,8 @@ int cmCPackPackageMakerGenerator::PackageFiles()
!this->CopyCreateResourceFile("Welcome", resDir) ||
!this->CopyResourcePlistFile("Info.plist") ||
!this->CopyResourcePlistFile("Description.plist")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem copying the resource files" << std::endl);
return 0;
}
@@ -275,28 +273,29 @@ int cmCPackPackageMakerGenerator::PackageFiles()
if (this->PackageMakerVersion > 2.0) {
pkgCmd << " -v";
}
- if (!RunPackageMaker(pkgCmd.str().c_str(), packageDirFileName.c_str()))
+ if (!RunPackageMaker(pkgCmd.str().c_str(), packageDirFileName.c_str())) {
return 0;
+ }
} else {
// We have built the package in place. Generate the
// distribution.dist file to describe it for the installer.
WriteDistributionFile(packageDirFileName.c_str());
}
- std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- tmpFile += "/hdiutilOutput.log";
+ std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
+ "/hdiutilOutput.log");
std::ostringstream dmgCmd;
dmgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM_DISK_IMAGE")
- << "\" create -ov -format UDZO -srcfolder \"" << packageDirFileName
- << "\" \"" << packageFileNames[0] << "\"";
+ << "\" create -ov -fs HFS+ -format UDZO -srcfolder \""
+ << packageDirFileName << "\" \"" << packageFileNames[0] << "\"";
std::string output;
int retVal = 1;
int numTries = 10;
bool res = false;
while (numTries > 0) {
- res =
- cmSystemTools::RunSingleCommand(dmgCmd.str().c_str(), &output, &output,
- &retVal, 0, this->GeneratorVerbose, 0);
+ res = cmSystemTools::RunSingleCommand(
+ dmgCmd.str(), &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+ cmDuration::zero());
if (res && !retVal) {
numTries = -1;
break;
@@ -305,11 +304,12 @@ int cmCPackPackageMakerGenerator::PackageFiles()
numTries--;
}
if (!res || retVal) {
- cmGeneratedFileStream ofs(tmpFile.c_str());
+ cmGeneratedFileStream ofs(tmpFile);
ofs << "# Run command: " << dmgCmd.str() << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running hdiutil command: "
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running hdiutil command: "
<< dmgCmd.str() << std::endl
<< "Please check " << tmpFile << " for errors"
<< std::endl);
@@ -337,16 +337,16 @@ int cmCPackPackageMakerGenerator::InitializeInternal()
// If found, save result in the CPACK_INSTALLER_PROGRAM variable.
std::vector<std::string> paths;
- paths.push_back("/Applications/Xcode.app/Contents/Applications"
- "/PackageMaker.app/Contents/MacOS");
- paths.push_back("/Applications/Utilities"
- "/PackageMaker.app/Contents/MacOS");
- paths.push_back("/Applications"
- "/PackageMaker.app/Contents/MacOS");
- paths.push_back("/Developer/Applications/Utilities"
- "/PackageMaker.app/Contents/MacOS");
- paths.push_back("/Developer/Applications"
- "/PackageMaker.app/Contents/MacOS");
+ paths.emplace_back("/Applications/Xcode.app/Contents/Applications"
+ "/PackageMaker.app/Contents/MacOS");
+ paths.emplace_back("/Applications/Utilities"
+ "/PackageMaker.app/Contents/MacOS");
+ paths.emplace_back("/Applications"
+ "/PackageMaker.app/Contents/MacOS");
+ paths.emplace_back("/Developer/Applications/Utilities"
+ "/PackageMaker.app/Contents/MacOS");
+ paths.emplace_back("/Developer/Applications"
+ "/PackageMaker.app/Contents/MacOS");
std::string pkgPath;
const char* inst_program = this->GetOption("CPACK_INSTALLER_PROGRAM");
@@ -355,8 +355,8 @@ int cmCPackPackageMakerGenerator::InitializeInternal()
} else {
pkgPath = cmSystemTools::FindProgram("PackageMaker", paths, false);
if (pkgPath.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find PackageMaker compiler"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find PackageMaker compiler" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", pkgPath.c_str());
@@ -413,12 +413,13 @@ int cmCPackPackageMakerGenerator::InitializeInternal()
}
this->PackageMakerVersion = atof(rexVersion.match(1).c_str());
if (this->PackageMakerVersion < 1.0) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Require PackageMaker 1.0 or higher"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Require PackageMaker 1.0 or higher" << std::endl);
return 0;
}
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "PackageMaker version is: "
- << this->PackageMakerVersion << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "PackageMaker version is: " << this->PackageMakerVersion
+ << std::endl);
// Determine the package compatibility version. If it wasn't
// specified by the user, we define it based on which features the
@@ -446,8 +447,8 @@ int cmCPackPackageMakerGenerator::InitializeInternal()
std::vector<std::string> no_paths;
pkgPath = cmSystemTools::FindProgram("hdiutil", no_paths, false);
if (pkgPath.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find hdiutil compiler"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find hdiutil compiler" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE",
@@ -459,25 +460,27 @@ int cmCPackPackageMakerGenerator::InitializeInternal()
bool cmCPackPackageMakerGenerator::RunPackageMaker(const char* command,
const char* packageFile)
{
- std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- tmpFile += "/PackageMakerOutput.log";
+ std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
+ "/PackageMakerOutput.log");
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << command << std::endl);
std::string output;
int retVal = 1;
bool res = cmSystemTools::RunSingleCommand(
- command, &output, &output, &retVal, 0, this->GeneratorVerbose, 0);
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Done running package maker"
- << std::endl);
+ command, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+ cmDuration::zero());
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Done running package maker" << std::endl);
if (!res || retVal) {
- cmGeneratedFileStream ofs(tmpFile.c_str());
+ cmGeneratedFileStream ofs(tmpFile);
ofs << "# Run command: " << command << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
- cmCPackLogger(
- cmCPackLog::LOG_ERROR, "Problem running PackageMaker command: "
- << command << std::endl
- << "Please check " << tmpFile << " for errors" << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running PackageMaker command: "
+ << command << std::endl
+ << "Please check " << tmpFile << " for errors"
+ << std::endl);
return false;
}
// sometimes the command finishes but the directory is not yet
@@ -502,8 +505,9 @@ bool cmCPackPackageMakerGenerator::GenerateComponentPackage(
const char* packageFile, const char* packageDir,
const cmCPackComponent& component)
{
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Building component package: "
- << packageFile << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Building component package: " << packageFile
+ << std::endl);
// The command that will be used to run PackageMaker
std::ostringstream pkgCmd;
@@ -512,8 +516,9 @@ bool cmCPackPackageMakerGenerator::GenerateComponentPackage(
this->PackageMakerVersion < 3.0) {
// Create Description.plist and Info.plist files for normal Mac OS
// X packages, which work on Mac OS X 10.3 and newer.
- std::string descriptionFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- descriptionFile += '/' + component.Name + "-Description.plist";
+ std::string descriptionFile =
+ cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
+ component.Name, "-Description.plist");
cmsys::ofstream out(descriptionFile.c_str());
cmXMLWriter xout(out);
xout.StartDocument();
@@ -534,12 +539,10 @@ bool cmCPackPackageMakerGenerator::GenerateComponentPackage(
out.close();
// Create the Info.plist file for this component
- std::string moduleVersionSuffix = ".";
- moduleVersionSuffix += component.Name;
+ std::string moduleVersionSuffix = cmStrCat('.', component.Name);
this->SetOption("CPACK_MODULE_VERSION_SUFFIX",
moduleVersionSuffix.c_str());
- std::string infoFileName = component.Name;
- infoFileName += "-Info.plist";
+ std::string infoFileName = cmStrCat(component.Name, "-Info.plist");
if (!this->CopyResourcePlistFile("Info.plist", infoFileName.c_str())) {
return false;
}
@@ -556,12 +559,9 @@ bool cmCPackPackageMakerGenerator::GenerateComponentPackage(
// like normal packages, and can be downloaded by the installer
// on-the-fly in Mac OS X 10.5 or newer. Thus, we need to create
// flat packages when the packages will be downloaded on the fly.
- std::string pkgId = "com.";
- pkgId += this->GetOption("CPACK_PACKAGE_VENDOR");
- pkgId += '.';
- pkgId += this->GetOption("CPACK_PACKAGE_NAME");
- pkgId += '.';
- pkgId += component.Name;
+ std::string pkgId =
+ cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"), '.',
+ this->GetOption("CPACK_PACKAGE_NAME"), '.', component.Name);
pkgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM")
<< "\" --root \"" << packageDir << "\""
diff --git a/Source/CPack/cmCPackPackageMakerGenerator.h b/Source/CPack/cmCPackPackageMakerGenerator.h
index 62745152b..0575587d5 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.h
+++ b/Source/CPack/cmCPackPackageMakerGenerator.h
@@ -3,7 +3,7 @@
#ifndef cmCPackPackageMakerGenerator_h
#define cmCPackPackageMakerGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include "cmCPackGenerator.h"
#include "cmCPackPKGGenerator.h"
@@ -25,13 +25,13 @@ public:
* Construct generator
*/
cmCPackPackageMakerGenerator();
- virtual ~cmCPackPackageMakerGenerator();
- bool SupportsComponentInstallation() const CM_OVERRIDE;
+ ~cmCPackPackageMakerGenerator() override;
+ bool SupportsComponentInstallation() const override;
protected:
- int InitializeInternal() CM_OVERRIDE;
- int PackageFiles() CM_OVERRIDE;
- const char* GetOutputExtension() CM_OVERRIDE { return ".dmg"; }
+ int InitializeInternal() override;
+ int PackageFiles() override;
+ const char* GetOutputExtension() override { return ".dmg"; }
// Run PackageMaker with the given command line, which will (if
// successful) produce the given package file. Returns true if
diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx
index 1389eaa5a..dae268c5c 100644
--- a/Source/CPack/cmCPackProductBuildGenerator.cxx
+++ b/Source/CPack/cmCPackProductBuildGenerator.cxx
@@ -2,13 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackProductBuildGenerator.h"
+#include <cstddef>
#include <map>
#include <sstream>
-#include <stddef.h>
#include "cmCPackComponentGroup.h"
#include "cmCPackLog.h"
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
cmCPackProductBuildGenerator::cmCPackProductBuildGenerator()
@@ -16,9 +18,7 @@ cmCPackProductBuildGenerator::cmCPackProductBuildGenerator()
this->componentPackageMethod = ONE_PACKAGE;
}
-cmCPackProductBuildGenerator::~cmCPackProductBuildGenerator()
-{
-}
+cmCPackProductBuildGenerator::~cmCPackProductBuildGenerator() = default;
int cmCPackProductBuildGenerator::PackageFiles()
{
@@ -29,8 +29,8 @@ int cmCPackProductBuildGenerator::PackageFiles()
this->GetOption("CPACK_TEMPORARY_DIRECTORY");
// Create the directory where component packages will be built.
- std::string basePackageDir = packageDirFileName;
- basePackageDir += "/Contents/Packages";
+ std::string basePackageDir =
+ cmStrCat(packageDirFileName, "/Contents/Packages");
if (!cmsys::SystemTools::MakeDirectory(basePackageDir.c_str())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem creating component packages directory: "
@@ -42,9 +42,7 @@ int cmCPackProductBuildGenerator::PackageFiles()
std::map<std::string, cmCPackComponent>::iterator compIt;
for (compIt = this->Components.begin(); compIt != this->Components.end();
++compIt) {
- std::string packageDir = toplevel;
- packageDir += '/';
- packageDir += compIt->first;
+ std::string packageDir = cmStrCat(toplevel, '/', compIt->first);
if (!this->GenerateComponentPackage(basePackageDir,
GetPackageName(compIt->second),
packageDir, &compIt->second)) {
@@ -54,7 +52,7 @@ int cmCPackProductBuildGenerator::PackageFiles()
} else {
if (!this->GenerateComponentPackage(basePackageDir,
this->GetOption("CPACK_PACKAGE_NAME"),
- toplevel, NULL)) {
+ toplevel, nullptr)) {
return 0;
}
}
@@ -66,8 +64,8 @@ int cmCPackProductBuildGenerator::PackageFiles()
this->GetOption("CPACK_PRODUCTBUILD_RESOURCES_DIR");
if (!cmSystemTools::CopyADirectory(userResDir, resDir)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem copying the resource files" << std::endl);
return 0;
}
}
@@ -120,16 +118,16 @@ int cmCPackProductBuildGenerator::InitializeInternal()
std::string program =
cmSystemTools::FindProgram("pkgbuild", no_paths, false);
if (program.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find pkgbuild executable"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find pkgbuild executable" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_COMMAND_PKGBUILD", program.c_str());
program = cmSystemTools::FindProgram("productbuild", no_paths, false);
if (program.empty()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find productbuild executable"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find productbuild executable" << std::endl);
return 0;
}
this->SetOptionIfNotSet("CPACK_COMMAND_PRODUCTBUILD", program.c_str());
@@ -139,18 +137,18 @@ int cmCPackProductBuildGenerator::InitializeInternal()
bool cmCPackProductBuildGenerator::RunProductBuild(const std::string& command)
{
- std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- tmpFile += "/ProductBuildOutput.log";
+ std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
+ "/ProductBuildOutput.log");
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << command << std::endl);
- std::string output, error_output;
+ std::string output;
int retVal = 1;
- bool res =
- cmSystemTools::RunSingleCommand(command.c_str(), &output, &error_output,
- &retVal, 0, this->GeneratorVerbose, 0);
+ bool res = cmSystemTools::RunSingleCommand(
+ command, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+ cmDuration::zero());
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Done running command" << std::endl);
if (!res || retVal) {
- cmGeneratedFileStream ofs(tmpFile.c_str());
+ cmGeneratedFileStream ofs(tmpFile);
ofs << "# Run command: " << command << std::endl
<< "# Output:" << std::endl
<< output << std::endl;
@@ -167,14 +165,13 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage(
const std::string& packageFileDir, const std::string& packageFileName,
const std::string& packageDir, const cmCPackComponent* component)
{
- std::string packageFile = packageFileDir;
- packageFile += '/';
- packageFile += packageFileName;
+ std::string packageFile = cmStrCat(packageFileDir, '/', packageFileName);
- cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Building component package: "
- << packageFile << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Building component package: " << packageFile
+ << std::endl);
- const char* comp_name = component ? component->Name.c_str() : NULL;
+ const char* comp_name = component ? component->Name.c_str() : nullptr;
const char* preflight = this->GetComponentScript("PREFLIGHT", comp_name);
const char* postflight = this->GetComponentScript("POSTFLIGHT", comp_name);
@@ -190,7 +187,7 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage(
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem creating installer directory: " << scriptDir
<< std::endl);
- return 0;
+ return false;
}
// if preflight, postflight, or postupgrade are set
@@ -206,10 +203,8 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage(
// The command that will be used to run ProductBuild
std::ostringstream pkgCmd;
- std::string pkgId = "com.";
- pkgId += this->GetOption("CPACK_PACKAGE_VENDOR");
- pkgId += '.';
- pkgId += this->GetOption("CPACK_PACKAGE_NAME");
+ std::string pkgId = cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"),
+ '.', this->GetOption("CPACK_PACKAGE_NAME"));
if (component) {
pkgId += '.';
pkgId += component->Name;
diff --git a/Source/CPack/cmCPackProductBuildGenerator.h b/Source/CPack/cmCPackProductBuildGenerator.h
index 12093a0e8..015fe4ace 100644
--- a/Source/CPack/cmCPackProductBuildGenerator.h
+++ b/Source/CPack/cmCPackProductBuildGenerator.h
@@ -3,7 +3,7 @@
#ifndef cmCPackProductBuildGenerator_h
#define cmCPackProductBuildGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
@@ -25,12 +25,12 @@ public:
* Construct generator
*/
cmCPackProductBuildGenerator();
- virtual ~cmCPackProductBuildGenerator();
+ ~cmCPackProductBuildGenerator() override;
protected:
- int InitializeInternal() CM_OVERRIDE;
- int PackageFiles() CM_OVERRIDE;
- const char* GetOutputExtension() CM_OVERRIDE { return ".pkg"; }
+ int InitializeInternal() override;
+ int PackageFiles() override;
+ const char* GetOutputExtension() override { return ".pkg"; }
// Run ProductBuild with the given command line, which will (if
// successful) produce the given package file. Returns true if
diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx
index 8ec03c236..0c1cecf39 100644
--- a/Source/CPack/cmCPackRPMGenerator.cxx
+++ b/Source/CPack/cmCPackRPMGenerator.cxx
@@ -3,7 +3,7 @@
#include "cmCPackRPMGenerator.h"
#include <algorithm>
-#include <ctype.h>
+#include <cctype>
#include <map>
#include <ostream>
#include <utility>
@@ -12,20 +12,17 @@
#include "cmCPackComponentGroup.h"
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-cmCPackRPMGenerator::cmCPackRPMGenerator()
-{
-}
+cmCPackRPMGenerator::cmCPackRPMGenerator() = default;
-cmCPackRPMGenerator::~cmCPackRPMGenerator()
-{
-}
+cmCPackRPMGenerator::~cmCPackRPMGenerator() = default;
int cmCPackRPMGenerator::InitializeInternal()
{
this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/usr");
- if (cmSystemTools::IsOff(this->GetOption("CPACK_SET_DESTDIR"))) {
+ if (cmIsOff(this->GetOption("CPACK_SET_DESTDIR"))) {
this->SetOption("CPACK_SET_DESTDIR", "I_ON");
}
/* Replace space in CPACK_PACKAGE_NAME in order to avoid
@@ -85,13 +82,12 @@ int cmCPackRPMGenerator::PackageOnePack(std::string const& initialToplevel,
// Tell CPackRPM.cmake the name of the component NAME.
this->SetOption("CPACK_RPM_PACKAGE_COMPONENT", packageName.c_str());
// Tell CPackRPM.cmake the path where the component is.
- std::string component_path = "/";
- component_path += packageName;
+ std::string component_path = cmStrCat('/', packageName);
this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH",
component_path.c_str());
- if (!this->ReadListFile("CPackRPM.cmake")) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackRPM.cmake"
- << std::endl);
+ if (!this->ReadListFile("Internal/CPack/CPackRPM.cmake")) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while execution CPackRPM.cmake" << std::endl);
retval = 0;
}
@@ -148,7 +144,7 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
for (compIt = this->Components.begin();
compIt != this->Components.end(); ++compIt) {
// Does the component belong to a group?
- if (compIt->second.Group == CM_NULLPTR) {
+ if (compIt->second.Group == nullptr) {
std::string component(compIt->first);
std::transform(component.begin(), component.end(),
component.begin(), ::toupper);
@@ -165,7 +161,8 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
}
if (shouldSet) {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Setting "
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Setting "
<< "CPACK_RPM_DEBUGINFO_PACKAGE because "
<< "CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE is set but "
<< " none of the "
@@ -187,8 +184,7 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
// The default behavior is to have one package by component group
// unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
if (!ignoreGroup) {
- std::map<std::string, cmCPackComponentGroup>::iterator mainCompGIt =
- this->ComponentGroups.end();
+ auto mainCompGIt = this->ComponentGroups.end();
std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
for (compGIt = this->ComponentGroups.begin();
@@ -203,18 +199,18 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
continue;
}
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: "
- << compGIt->first << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Packaging component group: " << compGIt->first
+ << std::endl);
retval &= PackageOnePack(initialTopLevel, compGIt->first);
}
// Handle Orphan components (components not belonging to any groups)
- std::map<std::string, cmCPackComponent>::iterator mainCompIt =
- this->Components.end();
+ auto mainCompIt = this->Components.end();
std::map<std::string, cmCPackComponent>::iterator compIt;
for (compIt = this->Components.begin(); compIt != this->Components.end();
++compIt) {
// Does the component belong to a group?
- if (compIt->second.Group == CM_NULLPTR) {
+ if (compIt->second.Group == nullptr) {
std::string component(compIt->first);
std::transform(component.begin(), component.end(), component.begin(),
::toupper);
@@ -226,7 +222,8 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
}
cmCPackLogger(
- cmCPackLog::LOG_VERBOSE, "Component <"
+ cmCPackLog::LOG_VERBOSE,
+ "Component <"
<< compIt->second.Name
<< "> does not belong to any group, package it separately."
<< std::endl);
@@ -242,7 +239,8 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
} else if (mainCompIt != this->Components.end()) {
retval &= PackageOnePack(initialTopLevel, mainCompIt->first);
} else {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_RPM_MAIN_COMPONENT set"
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_RPM_MAIN_COMPONENT set"
<< " to non existing component.\n");
retval = 0;
}
@@ -251,8 +249,7 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
// CPACK_COMPONENTS_IGNORE_GROUPS is set
// We build 1 package per component
else {
- std::map<std::string, cmCPackComponent>::iterator mainCompIt =
- this->Components.end();
+ auto mainCompIt = this->Components.end();
std::map<std::string, cmCPackComponent>::iterator compIt;
for (compIt = this->Components.begin(); compIt != this->Components.end();
@@ -276,7 +273,8 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
if (mainCompIt != this->Components.end()) {
retval &= PackageOnePack(initialTopLevel, mainCompIt->first);
} else {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_RPM_MAIN_COMPONENT set"
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_RPM_MAIN_COMPONENT set"
<< " to non existing component.\n");
retval = 0;
}
@@ -290,8 +288,9 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
std::map<std::string, cmCPackComponentGroup>::iterator compGIt;
for (compGIt = this->ComponentGroups.begin();
compGIt != this->ComponentGroups.end(); ++compGIt) {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: "
- << compGIt->first << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Packaging component group: " << compGIt->first
+ << std::endl);
retval &= PackageOnePack(initialTopLevel, compGIt->first);
}
// Handle Orphan components (components not belonging to any groups)
@@ -299,9 +298,10 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
for (compIt = this->Components.begin(); compIt != this->Components.end();
++compIt) {
// Does the component belong to a group?
- if (compIt->second.Group == CM_NULLPTR) {
+ if (compIt->second.Group == nullptr) {
cmCPackLogger(
- cmCPackLog::LOG_VERBOSE, "Component <"
+ cmCPackLog::LOG_VERBOSE,
+ "Component <"
<< compIt->second.Name
<< "> does not belong to any group, package it separately."
<< std::endl);
@@ -320,7 +320,8 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
}
} else {
cmCPackLogger(
- cmCPackLog::LOG_ERROR, "CPACK_RPM_MAIN_COMPONENT not set but"
+ cmCPackLog::LOG_ERROR,
+ "CPACK_RPM_MAIN_COMPONENT not set but"
<< " it is mandatory with CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE"
<< " being set.\n");
retval = 0;
@@ -371,17 +372,16 @@ int cmCPackRPMGenerator::PackageComponentsAllInOne(
if (!compInstDirName.empty()) {
// Tell CPackRPM.cmake the path where the component is.
- std::string component_path = "/";
- component_path += compInstDirName;
+ std::string component_path = cmStrCat('/', compInstDirName);
this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH",
component_path.c_str());
}
- if (this->ReadListFile("CPackRPM.cmake")) {
+ if (this->ReadListFile("Internal/CPack/CPackRPM.cmake")) {
AddGeneratedPackageNames();
} else {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Error while execution CPackRPM.cmake"
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while execution CPackRPM.cmake" << std::endl);
retval = 0;
}
@@ -430,7 +430,7 @@ std::string cmCPackRPMGenerator::GetComponentInstallDirNameSuffix(
// the current COMPONENT belongs to.
std::string groupVar =
"CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP";
- if (CM_NULLPTR != GetOption(groupVar)) {
+ if (nullptr != GetOption(groupVar)) {
return std::string(GetOption(groupVar));
}
return componentName;
diff --git a/Source/CPack/cmCPackRPMGenerator.h b/Source/CPack/cmCPackRPMGenerator.h
index 52cfc13ed..075ce8458 100644
--- a/Source/CPack/cmCPackRPMGenerator.h
+++ b/Source/CPack/cmCPackRPMGenerator.h
@@ -3,12 +3,12 @@
#ifndef cmCPackRPMGenerator_h
#define cmCPackRPMGenerator_h
-#include "cmConfigure.h"
-
-#include "cmCPackGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
+#include "cmCPackGenerator.h"
+
/** \class cmCPackRPMGenerator
* \brief A generator for RPM packages
* The idea of the CPack RPM generator is to use
@@ -26,7 +26,7 @@ public:
* Construct generator
*/
cmCPackRPMGenerator();
- ~cmCPackRPMGenerator() CM_OVERRIDE;
+ ~cmCPackRPMGenerator() override;
static bool CanGenerate()
{
@@ -43,8 +43,8 @@ public:
}
protected:
- int InitializeInternal() CM_OVERRIDE;
- int PackageFiles() CM_OVERRIDE;
+ int InitializeInternal() override;
+ int PackageFiles() override;
/**
* This method factors out the work done in component packaging case.
*/
@@ -61,10 +61,10 @@ protected:
* components will be put in a single installer.
*/
int PackageComponentsAllInOne(const std::string& compInstDirName);
- const char* GetOutputExtension() CM_OVERRIDE { return ".rpm"; }
- bool SupportsComponentInstallation() const CM_OVERRIDE;
+ const char* GetOutputExtension() override { return ".rpm"; }
+ bool SupportsComponentInstallation() const override;
std::string GetComponentInstallDirNameSuffix(
- const std::string& componentName) CM_OVERRIDE;
+ const std::string& componentName) override;
void AddGeneratedPackageNames();
};
diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx
index c54161426..a4a5e6fcd 100644
--- a/Source/CPack/cmCPackSTGZGenerator.cxx
+++ b/Source/CPack/cmCPackSTGZGenerator.cxx
@@ -2,24 +2,26 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackSTGZGenerator.h"
-#include "cmsys/FStream.hxx"
+#include <cstdio>
#include <sstream>
-#include <stdio.h>
#include <string>
#include <vector>
+#include "cmsys/FStream.hxx"
+
+#include "cm_sys_stat.h"
+
+#include "cmArchiveWrite.h"
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
#include "cmSystemTools.h"
-#include "cm_sys_stat.h"
cmCPackSTGZGenerator::cmCPackSTGZGenerator()
+ : cmCPackArchiveGenerator(cmArchiveWrite::CompressGZip, "paxr", ".sh")
{
}
-cmCPackSTGZGenerator::~cmCPackSTGZGenerator()
-{
-}
+cmCPackSTGZGenerator::~cmCPackSTGZGenerator() = default;
int cmCPackSTGZGenerator::InitializeInternal()
{
@@ -48,9 +50,8 @@ int cmCPackSTGZGenerator::PackageFiles()
* have generated several packages (component packaging)
* so we must iterate over generated packages.
*/
- for (std::vector<std::string>::iterator it = packageFileNames.begin();
- it != packageFileNames.end(); ++it) {
- retval &= cmSystemTools::SetPermissions((*it).c_str(),
+ for (std::string const& pfn : packageFileNames) {
+ retval &= cmSystemTools::SetPermissions(pfn.c_str(),
#if defined(_MSC_VER) || defined(__MINGW32__)
S_IREAD | S_IWRITE | S_IEXEC
#else
@@ -58,7 +59,7 @@ int cmCPackSTGZGenerator::PackageFiles()
S_IRGRP | S_IWGRP | S_IXGRP |
S_IROTH | S_IWOTH | S_IXOTH
#endif
- );
+ );
}
return retval;
}
@@ -102,8 +103,8 @@ int cmCPackSTGZGenerator::GenerateHeader(std::ostream* os)
++ptr;
}
counter++;
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "Number of lines: " << counter
- << std::endl);
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Number of lines: " << counter << std::endl);
char buffer[1024];
sprintf(buffer, "%d", counter);
cmSystemTools::ReplaceString(res, headerLengthTag, buffer);
diff --git a/Source/CPack/cmCPackSTGZGenerator.h b/Source/CPack/cmCPackSTGZGenerator.h
index 8304e8076..79d7035e1 100644
--- a/Source/CPack/cmCPackSTGZGenerator.h
+++ b/Source/CPack/cmCPackSTGZGenerator.h
@@ -3,33 +3,32 @@
#ifndef cmCPackSTGZGenerator_h
#define cmCPackSTGZGenerator_h
-#include "cmConfigure.h"
-
-#include "cmCPackGenerator.h"
-#include "cmCPackTGZGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
+#include "cmCPackArchiveGenerator.h"
+#include "cmCPackGenerator.h"
+
/** \class cmCPackSTGZGenerator
* \brief A generator for Self extractable TGZ files
*
*/
-class cmCPackSTGZGenerator : public cmCPackTGZGenerator
+class cmCPackSTGZGenerator : public cmCPackArchiveGenerator
{
public:
- cmCPackTypeMacro(cmCPackSTGZGenerator, cmCPackTGZGenerator);
+ cmCPackTypeMacro(cmCPackSTGZGenerator, cmCPackArchiveGenerator);
/**
* Construct generator
*/
cmCPackSTGZGenerator();
- ~cmCPackSTGZGenerator() CM_OVERRIDE;
+ ~cmCPackSTGZGenerator() override;
protected:
- int PackageFiles() CM_OVERRIDE;
- int InitializeInternal() CM_OVERRIDE;
- int GenerateHeader(std::ostream* os) CM_OVERRIDE;
- const char* GetOutputExtension() CM_OVERRIDE { return ".sh"; }
+ int PackageFiles() override;
+ int InitializeInternal() override;
+ int GenerateHeader(std::ostream* os) override;
};
#endif
diff --git a/Source/CPack/cmCPackTGZGenerator.cxx b/Source/CPack/cmCPackTGZGenerator.cxx
deleted file mode 100644
index eaf8186fe..000000000
--- a/Source/CPack/cmCPackTGZGenerator.cxx
+++ /dev/null
@@ -1,15 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmCPackTGZGenerator.h"
-
-#include "cmArchiveWrite.h"
-#include "cmCPackArchiveGenerator.h"
-
-cmCPackTGZGenerator::cmCPackTGZGenerator()
- : cmCPackArchiveGenerator(cmArchiveWrite::CompressGZip, "paxr")
-{
-}
-
-cmCPackTGZGenerator::~cmCPackTGZGenerator()
-{
-}
diff --git a/Source/CPack/cmCPackTGZGenerator.h b/Source/CPack/cmCPackTGZGenerator.h
deleted file mode 100644
index 9426b3a01..000000000
--- a/Source/CPack/cmCPackTGZGenerator.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmCPackTGZGenerator_h
-#define cmCPackTGZGenerator_h
-
-#include "cmConfigure.h"
-
-#include "cmCPackArchiveGenerator.h"
-#include "cmCPackGenerator.h"
-
-/** \class cmCPackTGZGenerator
- * \brief A generator for TGZ files
- *
- */
-class cmCPackTGZGenerator : public cmCPackArchiveGenerator
-{
-public:
- cmCPackTypeMacro(cmCPackTGZGenerator, cmCPackArchiveGenerator);
- /**
- * Construct generator
- */
- cmCPackTGZGenerator();
- ~cmCPackTGZGenerator() CM_OVERRIDE;
-
-protected:
- const char* GetOutputExtension() CM_OVERRIDE { return ".tar.gz"; }
-};
-
-#endif
diff --git a/Source/CPack/cmCPackTXZGenerator.cxx b/Source/CPack/cmCPackTXZGenerator.cxx
deleted file mode 100644
index e55e903e9..000000000
--- a/Source/CPack/cmCPackTXZGenerator.cxx
+++ /dev/null
@@ -1,15 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmCPackTXZGenerator.h"
-
-#include "cmArchiveWrite.h"
-#include "cmCPackArchiveGenerator.h"
-
-cmCPackTXZGenerator::cmCPackTXZGenerator()
- : cmCPackArchiveGenerator(cmArchiveWrite::CompressXZ, "paxr")
-{
-}
-
-cmCPackTXZGenerator::~cmCPackTXZGenerator()
-{
-}
diff --git a/Source/CPack/cmCPackTXZGenerator.h b/Source/CPack/cmCPackTXZGenerator.h
deleted file mode 100644
index 3b96e2d78..000000000
--- a/Source/CPack/cmCPackTXZGenerator.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmCPackTXZGenerator_h
-#define cmCPackTXZGenerator_h
-
-#include "cmConfigure.h"
-
-#include "cmCPackArchiveGenerator.h"
-#include "cmCPackGenerator.h"
-
-/** \class cmCPackTXZGenerator
- * \brief A generator for TXZ files
- *
- */
-class cmCPackTXZGenerator : public cmCPackArchiveGenerator
-{
-public:
- cmCPackTypeMacro(cmCPackTXZGenerator, cmCPackArchiveGenerator);
- /**
- * Construct generator
- */
- cmCPackTXZGenerator();
- ~cmCPackTXZGenerator() CM_OVERRIDE;
-
-protected:
- const char* GetOutputExtension() CM_OVERRIDE { return ".tar.xz"; }
-};
-
-#endif
diff --git a/Source/CPack/cmCPackTarBZip2Generator.cxx b/Source/CPack/cmCPackTarBZip2Generator.cxx
deleted file mode 100644
index c7a3dd429..000000000
--- a/Source/CPack/cmCPackTarBZip2Generator.cxx
+++ /dev/null
@@ -1,15 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmCPackTarBZip2Generator.h"
-
-#include "cmArchiveWrite.h"
-#include "cmCPackArchiveGenerator.h"
-
-cmCPackTarBZip2Generator::cmCPackTarBZip2Generator()
- : cmCPackArchiveGenerator(cmArchiveWrite::CompressBZip2, "paxr")
-{
-}
-
-cmCPackTarBZip2Generator::~cmCPackTarBZip2Generator()
-{
-}
diff --git a/Source/CPack/cmCPackTarBZip2Generator.h b/Source/CPack/cmCPackTarBZip2Generator.h
deleted file mode 100644
index 9b4b8f4ff..000000000
--- a/Source/CPack/cmCPackTarBZip2Generator.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmCPackTarBZip2Generator_h
-#define cmCPackTarBZip2Generator_h
-
-#include "cmConfigure.h"
-
-#include "cmCPackArchiveGenerator.h"
-#include "cmCPackGenerator.h"
-
-/** \class cmCPackTarBZip2Generator
- * \brief A generator for TarBZip2 files
- */
-class cmCPackTarBZip2Generator : public cmCPackArchiveGenerator
-{
-public:
- cmCPackTypeMacro(cmCPackTarBZip2Generator, cmCPackArchiveGenerator);
- /**
- * Construct generator
- */
- cmCPackTarBZip2Generator();
- ~cmCPackTarBZip2Generator() CM_OVERRIDE;
-
-protected:
- const char* GetOutputExtension() CM_OVERRIDE { return ".tar.bz2"; }
-};
-
-#endif
diff --git a/Source/CPack/cmCPackTarCompressGenerator.cxx b/Source/CPack/cmCPackTarCompressGenerator.cxx
deleted file mode 100644
index 0a7cd978c..000000000
--- a/Source/CPack/cmCPackTarCompressGenerator.cxx
+++ /dev/null
@@ -1,15 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmCPackTarCompressGenerator.h"
-
-#include "cmArchiveWrite.h"
-#include "cmCPackArchiveGenerator.h"
-
-cmCPackTarCompressGenerator::cmCPackTarCompressGenerator()
- : cmCPackArchiveGenerator(cmArchiveWrite::CompressCompress, "paxr")
-{
-}
-
-cmCPackTarCompressGenerator::~cmCPackTarCompressGenerator()
-{
-}
diff --git a/Source/CPack/cmCPackTarCompressGenerator.h b/Source/CPack/cmCPackTarCompressGenerator.h
deleted file mode 100644
index 381d6eb2f..000000000
--- a/Source/CPack/cmCPackTarCompressGenerator.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmCPackTarCompressGenerator_h
-#define cmCPackTarCompressGenerator_h
-
-#include "cmConfigure.h"
-
-#include "cmCPackArchiveGenerator.h"
-#include "cmCPackGenerator.h"
-
-/** \class cmCPackTarCompressGenerator
- * \brief A generator for TarCompress files
- */
-class cmCPackTarCompressGenerator : public cmCPackArchiveGenerator
-{
-public:
- cmCPackTypeMacro(cmCPackTarCompressGenerator, cmCPackArchiveGenerator);
- /**
- * Construct generator
- */
- cmCPackTarCompressGenerator();
- ~cmCPackTarCompressGenerator() CM_OVERRIDE;
-
-protected:
- const char* GetOutputExtension() CM_OVERRIDE { return ".tar.Z"; }
-};
-
-#endif
diff --git a/Source/CPack/cmCPackZIPGenerator.cxx b/Source/CPack/cmCPackZIPGenerator.cxx
deleted file mode 100644
index 6b77c363d..000000000
--- a/Source/CPack/cmCPackZIPGenerator.cxx
+++ /dev/null
@@ -1,15 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmCPackZIPGenerator.h"
-
-#include "cmArchiveWrite.h"
-#include "cmCPackArchiveGenerator.h"
-
-cmCPackZIPGenerator::cmCPackZIPGenerator()
- : cmCPackArchiveGenerator(cmArchiveWrite::CompressNone, "zip")
-{
-}
-
-cmCPackZIPGenerator::~cmCPackZIPGenerator()
-{
-}
diff --git a/Source/CPack/cmCPackZIPGenerator.h b/Source/CPack/cmCPackZIPGenerator.h
deleted file mode 100644
index 00c872029..000000000
--- a/Source/CPack/cmCPackZIPGenerator.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmCPackZIPGenerator_h
-#define cmCPackZIPGenerator_h
-
-#include "cmConfigure.h"
-
-#include "cmCPackArchiveGenerator.h"
-#include "cmCPackGenerator.h"
-
-/** \class cmCPackZIPGenerator
- * \brief A generator for ZIP files
- */
-class cmCPackZIPGenerator : public cmCPackArchiveGenerator
-{
-public:
- cmCPackTypeMacro(cmCPackZIPGenerator, cmCPackArchiveGenerator);
-
- /**
- * Construct generator
- */
- cmCPackZIPGenerator();
- ~cmCPackZIPGenerator() CM_OVERRIDE;
-
-protected:
- const char* GetOutputExtension() CM_OVERRIDE { return ".zip"; }
-};
-
-#endif
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index a44bc3d68..58956522f 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -1,55 +1,63 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmConfigure.h"
#include "cmsys/CommandLineArguments.hxx"
#include "cmsys/Encoding.hxx"
-#include <iostream>
-#include <map>
-#include <sstream>
-#include <stddef.h>
-#include <string>
-#include <utility>
-#include <vector>
-
-#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmsys/ConsoleBuf.hxx"
-#endif
#include "cmCPackGenerator.h"
#include "cmCPackGeneratorFactory.h"
#include "cmCPackLog.h"
#include "cmDocumentation.h"
#include "cmDocumentationEntry.h"
+#include "cmDocumentationFormatter.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmState.h"
#include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cm_auto_ptr.hxx"
#include "cmake.h"
-static const char* cmDocumentationName[][2] = {
- { CM_NULLPTR, " cpack - Packaging driver provided by CMake." },
- { CM_NULLPTR, CM_NULLPTR }
+#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
+# include "cmsys/ConsoleBuf.hxx"
+#endif
+
+#include <cstddef>
+#include <iostream>
+#include <map>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace {
+const char* cmDocumentationName[][2] = {
+ { nullptr, " cpack - Packaging driver provided by CMake." },
+ { nullptr, nullptr }
};
-static const char* cmDocumentationUsage[][2] = {
- { CM_NULLPTR, " cpack -G <generator> [options]" },
- { CM_NULLPTR, CM_NULLPTR }
+const char* cmDocumentationUsage[][2] = {
+ // clang-format off
+ { nullptr, " cpack [options]" },
+ { nullptr, nullptr }
+ // clang-format on
};
-static const char* cmDocumentationOptions[][2] = {
- { "-G <generator>", "Use the specified generator to generate package." },
+const char* cmDocumentationOptions[][2] = {
+ { "-G <generators>", "Override/define CPACK_GENERATOR" },
{ "-C <Configuration>", "Specify the project configuration" },
{ "-D <var>=<value>", "Set a CPack variable." },
- { "--config <config file>", "Specify the config file." },
- { "--verbose,-V", "enable verbose output" },
- { "--debug", "enable debug output (for CPack developers)" },
- { "-P <package name>", "override/define CPACK_PACKAGE_NAME" },
- { "-R <package version>", "override/define CPACK_PACKAGE_VERSION" },
- { "-B <package directory>", "override/define CPACK_PACKAGE_DIRECTORY" },
- { "--vendor <vendor name>", "override/define CPACK_PACKAGE_VENDOR" },
- { CM_NULLPTR, CM_NULLPTR }
+ { "--config <configFile>", "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 <packageName>", "Override/define CPACK_PACKAGE_NAME" },
+ { "-R <packageVersion>", "Override/define CPACK_PACKAGE_VERSION" },
+ { "-B <packageDirectory>", "Override/define CPACK_PACKAGE_DIRECTORY" },
+ { "--vendor <vendorName>", "Override/define CPACK_PACKAGE_VENDOR" },
+ { nullptr, nullptr }
};
int cpackUnknownArgument(const char* /*unused*/, void* /*unused*/)
@@ -59,7 +67,7 @@ int cpackUnknownArgument(const char* /*unused*/, void* /*unused*/)
struct cpackDefinitions
{
- typedef std::map<std::string, std::string> MapType;
+ using MapType = std::map<std::string, std::string>;
MapType Map;
cmCPackLog* Log;
};
@@ -77,17 +85,25 @@ int cpackDefinitionArgument(const char* argument, const char* cValue,
return 0;
}
std::string key = value.substr(0, pos);
- value = value.c_str() + pos + 1;
+ value = value.substr(pos + 1);
def->Map[key] = value;
- cmCPack_Log(def->Log, cmCPackLog::LOG_DEBUG, "Set CPack variable: "
- << key << " to \"" << value << "\"" << std::endl);
+ cmCPack_Log(def->Log, cmCPackLog::LOG_DEBUG,
+ "Set CPack variable: " << key << " to \"" << value << "\""
+ << std::endl);
return 1;
}
+void cpackProgressCallback(const std::string& message, float /*unused*/)
+{
+ std::cout << "-- " << message << std::endl;
+}
+} // namespace
+
// this is CPack.
int main(int argc, char const* const* argv)
{
-#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
+ cmSystemTools::EnsureStdPipes();
+#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
// Replace streambuf so we can output Unicode to console
cmsys::ConsoleBuf::Manager consoleOut(std::cout);
consoleOut.SetUTF8Pipes();
@@ -99,6 +115,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;
@@ -107,8 +125,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."
@@ -120,6 +136,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;
@@ -136,11 +154,11 @@ int main(int argc, char const* const* argv)
cpackDefinitions definitions;
definitions.Log = &log;
- cpackConfigFile = "";
+ cpackConfigFile.clear();
cmsys::CommandLineArguments arg;
arg.Initialize(argc, argv);
- typedef cmsys::CommandLineArguments argT;
+ using argT = cmsys::CommandLineArguments;
// Help arguments
arg.AddArgument("--help", argT::NO_ARGUMENT, &help, "CPack help");
arg.AddArgument("--help-full", argT::SPACE_ARGUMENT, &helpFull,
@@ -155,6 +173,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");
@@ -188,27 +210,34 @@ int main(int argc, char const* const* argv)
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
"Read CPack config file: " << cpackConfigFile << std::endl);
- cmake cminst(cmake::RoleScript);
+ cmake cminst(cmake::RoleScript, cmState::CPack);
cminst.SetHomeDirectory("");
cminst.SetHomeOutputDirectory("");
+ cminst.SetProgressCallback(cpackProgressCallback);
cminst.GetCurrentSnapshot().SetDefaultDefinitions();
cmGlobalGenerator cmgg(&cminst);
- CM_AUTO_PTR<cmMakefile> globalMF(
- new cmMakefile(&cmgg, cminst.GetCurrentSnapshot()));
+ cmMakefile globalMF(&cmgg, cminst.GetCurrentSnapshot());
#if defined(__CYGWIN__)
- globalMF->AddDefinition("CMAKE_LEGACY_CYGWIN_WIN32", "0");
+ 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();
- cpackConfigFile += "/CPackConfig.cmake";
+ cpackConfigFile = cmStrCat(cmSystemTools::GetCurrentWorkingDirectory(),
+ "/CPackConfig.cmake");
cpackConfigFileSpecified = false;
}
cmCPackGeneratorFactory generators;
generators.SetLogger(&log);
- cmCPackGenerator* cpackGenerator = CM_NULLPTR;
cmDocumentation doc;
doc.addCPackStandardDocSections();
@@ -226,16 +255,16 @@ int main(int argc, char const* const* argv)
// find out which system cpack is running on, so it can setup the search
// paths, so FIND_XXX() commands can be used in scripts
std::string systemFile =
- globalMF->GetModulesFile("CMakeDetermineSystem.cmake");
- if (!globalMF->ReadListFile(systemFile.c_str())) {
+ globalMF.GetModulesFile("CMakeDetermineSystem.cmake");
+ if (!globalMF.ReadListFile(systemFile)) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Error reading CMakeDetermineSystem.cmake" << std::endl);
return 1;
}
systemFile =
- globalMF->GetModulesFile("CMakeSystemSpecificInformation.cmake");
- if (!globalMF->ReadListFile(systemFile.c_str())) {
+ globalMF.GetModulesFile("CMakeSystemSpecificInformation.cmake");
+ if (!globalMF.ReadListFile(systemFile)) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Error reading CMakeSystemSpecificInformation.cmake"
<< std::endl);
@@ -243,15 +272,15 @@ int main(int argc, char const* const* argv)
}
if (!cpackBuildConfig.empty()) {
- globalMF->AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig.c_str());
+ globalMF.AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig);
}
- 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
<< std::endl);
- if (!globalMF->ReadListFile(cpackConfigFile.c_str())) {
+ if (!globalMF.ReadListFile(cpackConfigFile)) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Problem reading CPack config file: \""
<< cpackConfigFile << "\"" << std::endl);
@@ -265,58 +294,49 @@ int main(int argc, char const* const* argv)
}
if (!generator.empty()) {
- globalMF->AddDefinition("CPACK_GENERATOR", generator.c_str());
+ globalMF.AddDefinition("CPACK_GENERATOR", generator);
}
if (!cpackProjectName.empty()) {
- globalMF->AddDefinition("CPACK_PACKAGE_NAME", cpackProjectName.c_str());
+ globalMF.AddDefinition("CPACK_PACKAGE_NAME", cpackProjectName);
}
if (!cpackProjectVersion.empty()) {
- globalMF->AddDefinition("CPACK_PACKAGE_VERSION",
- cpackProjectVersion.c_str());
+ globalMF.AddDefinition("CPACK_PACKAGE_VERSION", cpackProjectVersion);
}
if (!cpackProjectVendor.empty()) {
- globalMF->AddDefinition("CPACK_PACKAGE_VENDOR",
- cpackProjectVendor.c_str());
+ globalMF.AddDefinition("CPACK_PACKAGE_VENDOR", cpackProjectVendor);
}
// if this is not empty it has been set on the command line
// go for it. Command line override values set in config file.
if (!cpackProjectDirectory.empty()) {
- globalMF->AddDefinition("CPACK_PACKAGE_DIRECTORY",
- cpackProjectDirectory.c_str());
+ globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", cpackProjectDirectory);
}
// The value has not been set on the command line
else {
// get a default value (current working directory)
cpackProjectDirectory = cmsys::SystemTools::GetCurrentWorkingDirectory();
// use default value iff no value has been provided by the config file
- if (!globalMF->IsSet("CPACK_PACKAGE_DIRECTORY")) {
- globalMF->AddDefinition("CPACK_PACKAGE_DIRECTORY",
- cpackProjectDirectory.c_str());
+ if (!globalMF.IsSet("CPACK_PACKAGE_DIRECTORY")) {
+ globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY",
+ cpackProjectDirectory);
}
}
- cpackDefinitions::MapType::iterator cdit;
- for (cdit = definitions.Map.begin(); cdit != definitions.Map.end();
- ++cdit) {
- globalMF->AddDefinition(cdit->first, cdit->second.c_str());
+ for (auto const& cd : definitions.Map) {
+ globalMF.AddDefinition(cd.first, cd.second);
}
- const char* cpackModulesPath =
- globalMF->GetDefinition("CPACK_MODULE_PATH");
+ const char* cpackModulesPath = globalMF.GetDefinition("CPACK_MODULE_PATH");
if (cpackModulesPath) {
- globalMF->AddDefinition("CMAKE_MODULE_PATH", cpackModulesPath);
+ globalMF.AddDefinition("CMAKE_MODULE_PATH", cpackModulesPath);
}
- const char* genList = globalMF->GetDefinition("CPACK_GENERATOR");
+ const char* genList = globalMF.GetDefinition("CPACK_GENERATOR");
if (!genList) {
- cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "CPack generator not specified"
- << std::endl);
+ cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
+ "CPack generator not specified" << std::endl);
} else {
- std::vector<std::string> generatorsVector;
- cmSystemTools::ExpandListArgument(genList, generatorsVector);
- std::vector<std::string>::iterator it;
- for (it = generatorsVector.begin(); it != generatorsVector.end(); ++it) {
- const char* gen = it->c_str();
- cmMakefile::ScopePushPop raii(globalMF.get());
- cmMakefile* mf = globalMF.get();
+ std::vector<std::string> generatorsVector = cmExpandedList(genList);
+ for (std::string const& gen : generatorsVector) {
+ cmMakefile::ScopePushPop raii(&globalMF);
+ cmMakefile* mf = &globalMF;
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
"Specified generator: " << gen << std::endl);
if (parsed && !mf->GetDefinition("CPACK_PACKAGE_NAME")) {
@@ -340,13 +360,31 @@ int main(int argc, char const* const* argv)
parsed = 0;
}
if (parsed) {
- cpackGenerator = generators.NewGenerator(gen);
- if (!cpackGenerator) {
+ std::unique_ptr<cmCPackGenerator> cpackGenerator =
+ generators.NewGenerator(gen);
+ if (cpackGenerator) {
+ cpackGenerator->SetTrace(trace);
+ cpackGenerator->SetTraceExpand(traceExpand);
+ } else {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "Cannot initialize CPack generator: " << gen
- << std::endl);
+ "Could not create CPack generator: " << gen
+ << std::endl);
+ // Print out all the valid generators
+ cmDocumentation generatorDocs;
+ std::vector<cmDocumentationEntry> v;
+ for (auto const& g : generators.GetGeneratorsList()) {
+ cmDocumentationEntry e;
+ e.Name = g.first;
+ e.Brief = g.second;
+ v.push_back(std::move(e));
+ }
+ generatorDocs.SetSection("Generators", v);
+ std::cerr << "\n";
+ generatorDocs.PrintDocumentation(cmDocumentation::ListGenerators,
+ std::cerr);
parsed = 0;
}
+
if (parsed && !cpackGenerator->Initialize(gen, mf)) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Cannot initialize the generator " << gen
@@ -355,21 +393,23 @@ int main(int argc, char const* const* argv)
}
if (!mf->GetDefinition("CPACK_INSTALL_COMMANDS") &&
+ !mf->GetDefinition("CPACK_INSTALL_SCRIPT") &&
!mf->GetDefinition("CPACK_INSTALLED_DIRECTORIES") &&
!mf->GetDefinition("CPACK_INSTALL_CMAKE_PROJECTS")) {
cmCPack_Log(
&log, cmCPackLog::LOG_ERROR,
"Please specify build tree of the project that uses CMake "
"using CPACK_INSTALL_CMAKE_PROJECTS, specify "
- "CPACK_INSTALL_COMMANDS, or specify "
+ "CPACK_INSTALL_COMMANDS, CPACK_INSTALL_SCRIPT, or "
"CPACK_INSTALLED_DIRECTORIES."
<< std::endl);
parsed = 0;
}
if (parsed) {
const char* projName = mf->GetDefinition("CPACK_PACKAGE_NAME");
- cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Use generator: "
- << cpackGenerator->GetNameOfClass() << std::endl);
+ cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
+ "Use generator: " << cpackGenerator->GetNameOfClass()
+ << std::endl);
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
"For project: " << projName << std::endl);
@@ -385,7 +425,7 @@ int main(int argc, char const* const* argv)
std::ostringstream ostr;
ostr << projVersionMajor << "." << projVersionMinor << "."
<< projVersionPatch;
- mf->AddDefinition("CPACK_PACKAGE_VERSION", ostr.str().c_str());
+ mf->AddDefinition("CPACK_PACKAGE_VERSION", ostr.str());
}
int res = cpackGenerator->DoPackage();
@@ -414,13 +454,11 @@ int main(int argc, char const* const* argv)
doc.PrependSection("Options", cmDocumentationOptions);
std::vector<cmDocumentationEntry> v;
- cmCPackGeneratorFactory::DescriptionsMap::const_iterator generatorIt;
- for (generatorIt = generators.GetGeneratorsList().begin();
- generatorIt != generators.GetGeneratorsList().end(); ++generatorIt) {
+ for (auto const& g : generators.GetGeneratorsList()) {
cmDocumentationEntry e;
- e.Name = generatorIt->first;
- e.Brief = generatorIt->second;
- v.push_back(e);
+ e.Name = g.first;
+ e.Brief = g.second;
+ v.push_back(std::move(e));
}
doc.SetSection("Generators", v);
diff --git a/Source/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx
index 94f39c265..8640c46f8 100644
--- a/Source/CTest/cmCTestBZR.cxx
+++ b/Source/CTest/cmCTestBZR.cxx
@@ -2,20 +2,23 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestBZR.h"
+#include <cstdlib>
+#include <list>
+#include <map>
+#include <ostream>
+#include <vector>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cm_expat.h"
+
+#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestVC.h"
#include "cmProcessTools.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
-#include "cm_expat.h"
-#include "cmsys/RegularExpression.hxx"
-#include <list>
-#include <map>
-#include <ostream>
-#include <stdlib.h>
-#include <vector>
-
extern "C" int cmBZRXMLParserUnknownEncodingHandler(void* /*unused*/,
const XML_Char* name,
XML_Encoding* info)
@@ -77,9 +80,7 @@ cmCTestBZR::cmCTestBZR(cmCTest* ct, std::ostream& log)
cmSystemTools::PutEnv("BZR_PROGRESS_BAR=none");
}
-cmCTestBZR::~cmCTestBZR()
-{
-}
+cmCTestBZR::~cmCTestBZR() = default;
class cmCTestBZR::InfoParser : public cmCTestVC::LineParser
{
@@ -98,7 +99,7 @@ private:
bool CheckOutFound;
cmsys::RegularExpression RegexCheckOut;
cmsys::RegularExpression RegexParent;
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (this->RegexCheckOut.find(this->Line)) {
this->BZR->URL = this->RegexCheckOut.match(1);
@@ -123,7 +124,7 @@ public:
private:
std::string& Rev;
cmsys::RegularExpression RegexRevno;
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (this->RegexRevno.find(this->Line)) {
this->Rev = this->RegexRevno.match(1);
@@ -136,13 +137,13 @@ std::string cmCTestBZR::LoadInfo()
{
// Run "bzr info" to get the repository info from the work tree.
const char* bzr = this->CommandLineTool.c_str();
- const char* bzr_info[] = { bzr, "info", CM_NULLPTR };
+ const char* bzr_info[] = { bzr, "info", nullptr };
InfoParser iout(this, "info-out> ");
OutputLogger ierr(this->Log, "info-err> ");
this->RunChild(bzr_info, &iout, &ierr);
// Run "bzr revno" to get the repository revision number from the work tree.
- const char* bzr_revno[] = { bzr, "revno", CM_NULLPTR };
+ const char* bzr_revno[] = { bzr, "revno", nullptr };
std::string rev;
RevnoParser rout(this, "revno-out> ", rev);
OutputLogger rerr(this->Log, "revno-err> ");
@@ -155,8 +156,9 @@ bool cmCTestBZR::NoteOldRevision()
{
this->OldRevision = this->LoadInfo();
this->Log << "Revision before update: " << this->OldRevision << "\n";
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: "
- << this->OldRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Old revision of repository is: " << this->OldRevision
+ << "\n");
this->PriorRev.Rev = this->OldRevision;
return true;
}
@@ -165,14 +167,16 @@ bool cmCTestBZR::NoteNewRevision()
{
this->NewRevision = this->LoadInfo();
this->Log << "Revision after update: " << this->NewRevision << "\n";
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: "
- << this->NewRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " New revision of repository is: " << this->NewRevision
+ << "\n");
this->Log << "URL = " << this->URL << "\n";
return true;
}
-class cmCTestBZR::LogParser : public cmCTestVC::OutputLogger,
- private cmXMLParser
+class cmCTestBZR::LogParser
+ : public cmCTestVC::OutputLogger
+ , private cmXMLParser
{
public:
LogParser(cmCTestBZR* bzr, const char* prefix)
@@ -182,15 +186,15 @@ public:
{
this->InitializeParser();
}
- ~LogParser() CM_OVERRIDE { this->CleanupParser(); }
+ ~LogParser() override { this->CleanupParser(); }
- int InitializeParser() CM_OVERRIDE
+ int InitializeParser() override
{
int res = cmXMLParser::InitializeParser();
if (res) {
XML_SetUnknownEncodingHandler(static_cast<XML_Parser>(this->Parser),
cmBZRXMLParserUnknownEncodingHandler,
- CM_NULLPTR);
+ nullptr);
}
return res;
}
@@ -198,8 +202,8 @@ public:
private:
cmCTestBZR* BZR;
- typedef cmCTestBZR::Revision Revision;
- typedef cmCTestBZR::Change Change;
+ using Revision = cmCTestBZR::Revision;
+ using Change = cmCTestBZR::Change;
Revision Rev;
std::vector<Change> Changes;
Change CurChange;
@@ -207,14 +211,14 @@ private:
cmsys::RegularExpression EmailRegex;
- bool ProcessChunk(const char* data, int length) CM_OVERRIDE
+ bool ProcessChunk(const char* data, int length) override
{
this->OutputLogger::ProcessChunk(data, length);
this->ParseChunk(data, length);
return true;
}
- void StartElement(const std::string& name, const char** /*atts*/) CM_OVERRIDE
+ void StartElement(const std::string& name, const char** /*atts*/) override
{
this->CData.clear();
if (name == "log") {
@@ -239,12 +243,12 @@ private:
}
}
- void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
+ void CharacterDataHandler(const char* data, int length) override
{
- this->CData.insert(this->CData.end(), data, data + length);
+ cmAppend(this->CData, data, data + length);
}
- void EndElement(const std::string& name) CM_OVERRIDE
+ void EndElement(const std::string& name) override
{
if (name == "log") {
this->BZR->DoRevision(this->Rev, this->Changes);
@@ -274,7 +278,7 @@ private:
this->CData.clear();
}
- void ReportError(int /*line*/, int /*column*/, const char* msg) CM_OVERRIDE
+ void ReportError(int /*line*/, int /*column*/, const char* msg) override
{
this->BZR->Log << "Error parsing bzr log xml: " << msg << "\n";
}
@@ -294,7 +298,7 @@ private:
cmCTestBZR* BZR;
cmsys::RegularExpression RegexUpdate;
- bool ProcessChunk(const char* first, int length) CM_OVERRIDE
+ bool ProcessChunk(const char* first, int length) override
{
bool last_is_new_line = (*first == '\r' || *first == '\n');
@@ -309,11 +313,11 @@ private:
// Hand this line to the subclass implementation.
if (!this->ProcessLine()) {
- this->Line = "";
+ this->Line.clear();
return false;
}
- this->Line = "";
+ this->Line.clear();
last_is_new_line = true;
}
} else {
@@ -325,7 +329,7 @@ private:
return true;
}
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (this->RegexUpdate.find(this->Line)) {
this->DoPath(this->RegexUpdate.match(1)[0],
@@ -364,7 +368,7 @@ bool cmCTestBZR::UpdateImpl()
if (opts.empty()) {
opts = this->CTest->GetCTestConfiguration("BZRUpdateOptions");
}
- std::vector<std::string> args = cmSystemTools::ParseArguments(opts.c_str());
+ std::vector<std::string> args = cmSystemTools::ParseArguments(opts);
// TODO: if(this->CTest->GetTestModel() == cmCTest::NIGHTLY)
@@ -373,14 +377,13 @@ bool cmCTestBZR::UpdateImpl()
bzr_update.push_back(this->CommandLineTool.c_str());
bzr_update.push_back("pull");
- for (std::vector<std::string>::const_iterator ai = args.begin();
- ai != args.end(); ++ai) {
- bzr_update.push_back(ai->c_str());
+ for (std::string const& arg : args) {
+ bzr_update.push_back(arg.c_str());
}
bzr_update.push_back(this->URL.c_str());
- bzr_update.push_back(CM_NULLPTR);
+ bzr_update.push_back(nullptr);
// For some reason bzr uses stderr to display the update status.
OutputLogger out(this->Log, "pull-out> ");
@@ -408,8 +411,7 @@ bool cmCTestBZR::LoadRevisions()
// Run "bzr log" to get all global revisions of interest.
const char* bzr = this->CommandLineTool.c_str();
const char* bzr_log[] = {
- bzr, "log", "-v", "-r", revs.c_str(), "--xml", this->URL.c_str(),
- CM_NULLPTR
+ bzr, "log", "-v", "-r", revs.c_str(), "--xml", this->URL.c_str(), nullptr
};
{
LogParser out(this, "log-out> ");
@@ -433,7 +435,7 @@ public:
private:
cmCTestBZR* BZR;
cmsys::RegularExpression RegexStatus;
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (this->RegexStatus.find(this->Line)) {
this->DoPath(this->RegexStatus.match(1)[0],
@@ -467,7 +469,7 @@ bool cmCTestBZR::LoadModifications()
{
// Run "bzr status" which reports local modifications.
const char* bzr = this->CommandLineTool.c_str();
- const char* bzr_status[] = { bzr, "status", "-SV", CM_NULLPTR };
+ const char* bzr_status[] = { bzr, "status", "-SV", nullptr };
StatusParser out(this, "status-out> ");
OutputLogger err(this->Log, "status-err> ");
this->RunChild(bzr_status, &out, &err);
diff --git a/Source/CTest/cmCTestBZR.h b/Source/CTest/cmCTestBZR.h
index 2e8e88f95..d7c632128 100644
--- a/Source/CTest/cmCTestBZR.h
+++ b/Source/CTest/cmCTestBZR.h
@@ -3,13 +3,13 @@
#ifndef cmCTestBZR_h
#define cmCTestBZR_h
-#include "cmConfigure.h"
-
-#include "cmCTestGlobalVC.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
+#include "cmCTestGlobalVC.h"
+
class cmCTest;
/** \class cmCTestBZR
@@ -22,20 +22,20 @@ public:
/** Construct with a CTest instance and update log stream. */
cmCTestBZR(cmCTest* ctest, std::ostream& log);
- ~cmCTestBZR() CM_OVERRIDE;
+ ~cmCTestBZR() override;
private:
// Implement cmCTestVC internal API.
- bool NoteOldRevision() CM_OVERRIDE;
- bool NoteNewRevision() CM_OVERRIDE;
- bool UpdateImpl() CM_OVERRIDE;
+ bool NoteOldRevision() override;
+ bool NoteNewRevision() override;
+ bool UpdateImpl() override;
// URL of repository directory checked out in the working tree.
std::string URL;
std::string LoadInfo();
- bool LoadModifications() CM_OVERRIDE;
- bool LoadRevisions() CM_OVERRIDE;
+ bool LoadModifications() override;
+ bool LoadRevisions() override;
// Parsing helper classes.
class InfoParser;
diff --git a/Source/CTest/cmCTestBatchTestHandler.cxx b/Source/CTest/cmCTestBatchTestHandler.cxx
deleted file mode 100644
index beee53a13..000000000
--- a/Source/CTest/cmCTestBatchTestHandler.cxx
+++ /dev/null
@@ -1,125 +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 (TestMap::iterator i = this->Tests.begin(); i != this->Tests.end();
- ++i) {
- this->WriteSrunArgs(i->first, fout);
- this->WriteTestCommand(i->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::vector<std::string>::iterator arg = processArgs.begin();
- arg != processArgs.end(); ++arg) {
- 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 4a5dac1d6..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"
-
-#include "cmCTestMultiProcessHandler.h"
-#include "cmsys/FStream.hxx"
-#include <string>
-
-/** \class cmCTestBatchTestHandler
- * \brief run parallel ctest
- *
- * cmCTestBatchTestHandler
- */
-class cmCTestBatchTestHandler : public cmCTestMultiProcessHandler
-{
-public:
- ~cmCTestBatchTestHandler() CM_OVERRIDE;
- void RunTests() CM_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/cmCTestBinPacker.cxx b/Source/CTest/cmCTestBinPacker.cxx
new file mode 100644
index 000000000..e21b14dd7
--- /dev/null
+++ b/Source/CTest/cmCTestBinPacker.cxx
@@ -0,0 +1,203 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCTestBinPacker.h"
+
+#include <algorithm>
+#include <utility>
+
+bool cmCTestBinPackerAllocation::operator==(
+ const cmCTestBinPackerAllocation& other) const
+{
+ return this->ProcessIndex == other.ProcessIndex &&
+ this->SlotsNeeded == other.SlotsNeeded && this->Id == other.Id;
+}
+
+bool cmCTestBinPackerAllocation::operator!=(
+ const cmCTestBinPackerAllocation& other) const
+{
+ return !(*this == other);
+}
+
+namespace {
+
+/*
+ * The following algorithm is used to do two things:
+ *
+ * 1) Determine if a test's resource requirements can fit within the resources
+ * present on the system, and
+ * 2) Do the actual allocation
+ *
+ * This algorithm performs a recursive search, looking for a bin pack that will
+ * fit the specified requirements. It has a template to specify different
+ * optimization strategies. If it ever runs out of room, it backtracks as far
+ * down the stack as it needs to and tries a different combination until no
+ * more combinations can be tried.
+ */
+template <typename AllocationStrategy>
+static bool AllocateCTestResources(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ const std::vector<std::string>& resourcesSorted, std::size_t currentIndex,
+ std::vector<cmCTestBinPackerAllocation*>& allocations)
+{
+ // Iterate through all large enough resources until we find a solution
+ std::size_t resourceIndex = 0;
+ while (resourceIndex < resourcesSorted.size()) {
+ auto const& resource = resources.at(resourcesSorted[resourceIndex]);
+ if (resource.Free() >=
+ static_cast<unsigned int>(allocations[currentIndex]->SlotsNeeded)) {
+ // Preemptively allocate the resource
+ allocations[currentIndex]->Id = resourcesSorted[resourceIndex];
+ if (currentIndex + 1 >= allocations.size()) {
+ // We have a solution
+ return true;
+ }
+
+ // Move the resource up the list until it is sorted again
+ auto resources2 = resources;
+ auto resourcesSorted2 = resourcesSorted;
+ resources2[resourcesSorted2[resourceIndex]].Locked +=
+ allocations[currentIndex]->SlotsNeeded;
+ AllocationStrategy::IncrementalSort(resources2, resourcesSorted2,
+ resourceIndex);
+
+ // Recurse one level deeper
+ if (AllocateCTestResources<AllocationStrategy>(
+ resources2, resourcesSorted2, currentIndex + 1, allocations)) {
+ return true;
+ }
+ }
+
+ // No solution found here, deallocate the resource and try the next one
+ allocations[currentIndex]->Id.clear();
+ auto freeSlots = resources.at(resourcesSorted.at(resourceIndex)).Free();
+ do {
+ ++resourceIndex;
+ } while (resourceIndex < resourcesSorted.size() &&
+ resources.at(resourcesSorted.at(resourceIndex)).Free() ==
+ freeSlots);
+ }
+
+ // No solution was found
+ return false;
+}
+
+template <typename AllocationStrategy>
+static bool AllocateCTestResources(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<cmCTestBinPackerAllocation>& allocations)
+{
+ // Sort the resource requirements in descending order by slots needed
+ std::vector<cmCTestBinPackerAllocation*> allocationsPtr;
+ allocationsPtr.reserve(allocations.size());
+ for (auto& allocation : allocations) {
+ allocationsPtr.push_back(&allocation);
+ }
+ std::stable_sort(
+ allocationsPtr.rbegin(), allocationsPtr.rend(),
+ [](cmCTestBinPackerAllocation* a1, cmCTestBinPackerAllocation* a2) {
+ return a1->SlotsNeeded < a2->SlotsNeeded;
+ });
+
+ // Sort the resources according to sort strategy
+ std::vector<std::string> resourcesSorted;
+ resourcesSorted.reserve(resources.size());
+ for (auto const& res : resources) {
+ resourcesSorted.push_back(res.first);
+ }
+ AllocationStrategy::InitialSort(resources, resourcesSorted);
+
+ // Do the actual allocation
+ return AllocateCTestResources<AllocationStrategy>(
+ resources, resourcesSorted, std::size_t(0), allocationsPtr);
+}
+
+class RoundRobinAllocationStrategy
+{
+public:
+ static void InitialSort(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<std::string>& resourcesSorted);
+
+ static void IncrementalSort(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<std::string>& resourcesSorted, std::size_t lastAllocatedIndex);
+};
+
+void RoundRobinAllocationStrategy::InitialSort(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<std::string>& resourcesSorted)
+{
+ std::stable_sort(
+ resourcesSorted.rbegin(), resourcesSorted.rend(),
+ [&resources](const std::string& id1, const std::string& id2) {
+ return resources.at(id1).Free() < resources.at(id2).Free();
+ });
+}
+
+void RoundRobinAllocationStrategy::IncrementalSort(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<std::string>& resourcesSorted, std::size_t lastAllocatedIndex)
+{
+ auto tmp = resourcesSorted[lastAllocatedIndex];
+ std::size_t i = lastAllocatedIndex;
+ while (i < resourcesSorted.size() - 1 &&
+ resources.at(resourcesSorted[i + 1]).Free() >
+ resources.at(tmp).Free()) {
+ resourcesSorted[i] = resourcesSorted[i + 1];
+ ++i;
+ }
+ resourcesSorted[i] = tmp;
+}
+
+class BlockAllocationStrategy
+{
+public:
+ static void InitialSort(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<std::string>& resourcesSorted);
+
+ static void IncrementalSort(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<std::string>& resourcesSorted, std::size_t lastAllocatedIndex);
+};
+
+void BlockAllocationStrategy::InitialSort(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<std::string>& resourcesSorted)
+{
+ std::stable_sort(
+ resourcesSorted.rbegin(), resourcesSorted.rend(),
+ [&resources](const std::string& id1, const std::string& id2) {
+ return resources.at(id1).Free() < resources.at(id2).Free();
+ });
+}
+
+void BlockAllocationStrategy::IncrementalSort(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>&,
+ std::vector<std::string>& resourcesSorted, std::size_t lastAllocatedIndex)
+{
+ auto tmp = resourcesSorted[lastAllocatedIndex];
+ std::size_t i = lastAllocatedIndex;
+ while (i > 0) {
+ resourcesSorted[i] = resourcesSorted[i - 1];
+ --i;
+ }
+ resourcesSorted[i] = tmp;
+}
+}
+
+bool cmAllocateCTestResourcesRoundRobin(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<cmCTestBinPackerAllocation>& allocations)
+{
+ return AllocateCTestResources<RoundRobinAllocationStrategy>(resources,
+ allocations);
+}
+
+bool cmAllocateCTestResourcesBlock(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<cmCTestBinPackerAllocation>& allocations)
+{
+ return AllocateCTestResources<BlockAllocationStrategy>(resources,
+ allocations);
+}
diff --git a/Source/CTest/cmCTestBinPacker.h b/Source/CTest/cmCTestBinPacker.h
new file mode 100644
index 000000000..ff02b8565
--- /dev/null
+++ b/Source/CTest/cmCTestBinPacker.h
@@ -0,0 +1,31 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCTestBinPacker_h
+#define cmCTestBinPacker_h
+
+#include <cstddef>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "cmCTestResourceAllocator.h"
+
+struct cmCTestBinPackerAllocation
+{
+ std::size_t ProcessIndex;
+ int SlotsNeeded;
+ std::string Id;
+
+ bool operator==(const cmCTestBinPackerAllocation& other) const;
+ bool operator!=(const cmCTestBinPackerAllocation& other) const;
+};
+
+bool cmAllocateCTestResourcesRoundRobin(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<cmCTestBinPackerAllocation>& allocations);
+
+bool cmAllocateCTestResourcesBlock(
+ const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
+ std::vector<cmCTestBinPackerAllocation>& allocations);
+
+#endif
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index cc290715c..2ad661cf0 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -2,22 +2,29 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestBuildAndTestHandler.h"
+#include <chrono>
+#include <cstdlib>
+#include <cstring>
+#include <ratio>
+
+#include "cmsys/Process.h"
+
#include "cmCTest.h"
#include "cmCTestTestHandler.h"
#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
#include "cmake.h"
-#include "cmsys/Process.h"
-#include <stdlib.h>
-
cmCTestBuildAndTestHandler::cmCTestBuildAndTestHandler()
{
this->BuildTwoConfig = false;
this->BuildNoClean = false;
this->BuildNoCMake = false;
- this->Timeout = 0;
+ this->Timeout = cmDuration::zero();
}
void cmCTestBuildAndTestHandler::Initialize()
@@ -32,7 +39,7 @@ const char* cmCTestBuildAndTestHandler::GetOutput()
}
int cmCTestBuildAndTestHandler::ProcessHandler()
{
- this->Output = "";
+ this->Output.clear();
std::string output;
cmSystemTools::ResetErrorOccuredFlag();
int retv = this->RunCMakeAndTest(&this->Output);
@@ -45,27 +52,20 @@ int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring,
std::string& cmakeOutString,
cmake* cm)
{
- unsigned int k;
std::vector<std::string> args;
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 = CM_NULLPTR;
+ const char* config = nullptr;
if (!this->CTest->GetConfigType().empty()) {
config = this->CTest->GetConfigType().c_str();
}
@@ -76,12 +76,16 @@ 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));
+ }
+ if (!this->BuildMakeProgram.empty() &&
+ (this->BuildGenerator.find("Make") != std::string::npos ||
+ this->BuildGenerator.find("Ninja") != std::string::npos)) {
+ args.push_back("-DCMAKE_MAKE_PROGRAM:FILEPATH=" + this->BuildMakeProgram);
}
- for (k = 0; k < this->BuildOptions.size(); ++k) {
- args.push_back(this->BuildOptions[k]);
+ for (std::string const& opt : this->BuildOptions) {
+ args.push_back(opt);
}
if (cm->Run(args) != 0) {
out << "Error: cmake execution failed\n";
@@ -112,27 +116,6 @@ int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring,
return 0;
}
-void CMakeMessageCallback(const char* m, const char* /*unused*/,
- bool& /*unused*/, void* s)
-{
- std::string* out = (std::string*)s;
- *out += m;
- *out += "\n";
-}
-
-void CMakeProgressCallback(const char* msg, float /*unused*/, void* s)
-{
- std::string* out = (std::string*)s;
- *out += msg;
- *out += "\n";
-}
-
-void CMakeOutputCallback(const char* m, size_t len, void* s)
-{
- std::string* out = (std::string*)s;
- out->append(m, len);
-}
-
class cmCTestBuildAndTestCaptureRAII
{
cmake& CM;
@@ -141,18 +124,35 @@ public:
cmCTestBuildAndTestCaptureRAII(cmake& cm, std::string& s)
: CM(cm)
{
- cmSystemTools::SetMessageCallback(CMakeMessageCallback, &s);
- cmSystemTools::SetStdoutCallback(CMakeOutputCallback, &s);
- cmSystemTools::SetStderrCallback(CMakeOutputCallback, &s);
- this->CM.SetProgressCallback(CMakeProgressCallback, &s);
+ cmSystemTools::SetMessageCallback(
+ [&s](const std::string& msg, const char* /*unused*/) {
+ s += msg;
+ s += "\n";
+ });
+
+ cmSystemTools::SetStdoutCallback([&s](std::string const& m) { s += m; });
+ cmSystemTools::SetStderrCallback([&s](std::string const& m) { s += m; });
+
+ this->CM.SetProgressCallback([&s](const std::string& msg, float prog) {
+ if (prog < 0) {
+ s += msg;
+ s += "\n";
+ }
+ });
}
+
~cmCTestBuildAndTestCaptureRAII()
{
- this->CM.SetProgressCallback(CM_NULLPTR, CM_NULLPTR);
- cmSystemTools::SetStderrCallback(CM_NULLPTR, CM_NULLPTR);
- cmSystemTools::SetStdoutCallback(CM_NULLPTR, CM_NULLPTR);
- cmSystemTools::SetMessageCallback(CM_NULLPTR, CM_NULLPTR);
+ this->CM.SetProgressCallback(nullptr);
+ cmSystemTools::SetStderrCallback(nullptr);
+ cmSystemTools::SetStdoutCallback(nullptr);
+ cmSystemTools::SetMessageCallback(nullptr);
}
+
+ cmCTestBuildAndTestCaptureRAII(const cmCTestBuildAndTestCaptureRAII&) =
+ delete;
+ cmCTestBuildAndTestCaptureRAII& operator=(
+ const cmCTestBuildAndTestCaptureRAII&) = delete;
};
int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
@@ -167,7 +167,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
return 1;
}
- cmake cm(cmake::RoleProject);
+ cmake cm(cmake::RoleProject, cmState::Project);
cm.SetHomeDirectory("");
cm.SetHomeOutputDirectory("");
std::string cmakeOutString;
@@ -193,21 +193,36 @@ 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);
+ if (workdir.Failed()) {
+ auto msg = "Failed to change working directory to " + this->BinaryDir +
+ " : " + std::strerror(workdir.GetLastResult()) + "\n";
+ if (outstring) {
+ *outstring = msg;
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, msg);
+ }
+ return 1;
+ }
if (this->BuildNoCMake) {
// Make the generator available for the Build call below.
- cm.SetGlobalGenerator(cm.CreateGlobalGenerator(this->BuildGenerator));
- cm.SetGeneratorPlatform(this->BuildGeneratorPlatform);
- cm.SetGeneratorToolset(this->BuildGeneratorToolset);
+ cmGlobalGenerator* gen = cm.CreateGlobalGenerator(this->BuildGenerator);
+ cm.SetGlobalGenerator(gen);
+ if (!this->BuildGeneratorPlatform.empty()) {
+ cmMakefile mf(gen, cm.GetCurrentSnapshot());
+ if (!gen->SetGeneratorPlatform(this->BuildGeneratorPlatform, &mf)) {
+ return 1;
+ }
+ }
// Load the cache to make CMAKE_MAKE_PROGRAM available.
cm.LoadCache(this->BinaryDir);
@@ -219,16 +234,15 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
}
// do the build
- std::vector<std::string>::iterator tarIt;
if (this->BuildTargets.empty()) {
- this->BuildTargets.push_back("");
- }
- for (tarIt = this->BuildTargets.begin(); tarIt != this->BuildTargets.end();
- ++tarIt) {
- double remainingTime = 0;
- if (this->Timeout > 0) {
- remainingTime = this->Timeout - cmSystemTools::GetTime() + clock_start;
- if (remainingTime <= 0) {
+ this->BuildTargets.emplace_back();
+ }
+ for (std::string const& tar : this->BuildTargets) {
+ 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. ";
}
@@ -236,7 +250,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
}
}
std::string output;
- const char* config = CM_NULLPTR;
+ const char* config = nullptr;
if (!this->CTest->GetConfigType().empty()) {
config = this->CTest->GetConfigType().c_str();
}
@@ -249,9 +263,9 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
config = "Debug";
}
int retVal = cm.GetGlobalGenerator()->Build(
- this->SourceDir, this->BinaryDir, this->BuildProject, *tarIt, output,
- this->BuildMakeProgram, config, !this->BuildNoClean, false, false,
- remainingTime);
+ cmake::NO_BUILD_PARALLEL_LEVEL, this->SourceDir, this->BinaryDir,
+ this->BuildProject, { tar }, output, this->BuildMakeProgram, config,
+ !this->BuildNoClean, false, false, remainingTime);
out << output;
// if the build failed then return
if (retVal) {
@@ -277,9 +291,8 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
std::vector<std::string> extraPaths;
// if this->ExecutableDirectory is set try that as well
if (!this->ExecutableDirectory.empty()) {
- std::string tempPath = this->ExecutableDirectory;
- tempPath += "/";
- tempPath += this->TestCommand;
+ std::string tempPath =
+ cmStrCat(this->ExecutableDirectory, '/', this->TestCommand);
extraPaths.push_back(tempPath);
}
std::vector<std::string> failed;
@@ -287,13 +300,13 @@ 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";
out << fullPath << "\n";
- for (unsigned int i = 0; i < failed.size(); ++i) {
- out << failed[i] << "\n";
+ for (std::string const& fail : failed) {
+ out << fail << "\n";
}
if (outstring) {
*outstring = out.str();
@@ -305,28 +318,38 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
std::vector<const char*> testCommand;
testCommand.push_back(fullPath.c_str());
- for (size_t k = 0; k < this->TestCommandArgs.size(); ++k) {
- testCommand.push_back(this->TestCommandArgs[k].c_str());
+ for (std::string const& testCommandArg : this->TestCommandArgs) {
+ testCommand.push_back(testCommandArg.c_str());
}
- testCommand.push_back(CM_NULLPTR);
+ testCommand.push_back(nullptr);
std::string outs;
int retval = 0;
// run the test from the this->BuildRunDir if set
if (!this->BuildRunDir.empty()) {
out << "Run test in directory: " << this->BuildRunDir << "\n";
- cmSystemTools::ChangeDirectory(this->BuildRunDir);
+ if (!workdir.SetDirectory(this->BuildRunDir)) {
+ out << "Failed to change working directory : "
+ << std::strerror(workdir.GetLastResult()) << "\n";
+ if (outstring) {
+ *outstring = out.str();
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, out.str());
+ }
+ return 1;
+ }
}
out << "Running test command: \"" << fullPath << "\"";
- for (size_t k = 0; k < this->TestCommandArgs.size(); ++k) {
- out << " \"" << this->TestCommandArgs[k] << "\"";
+ for (std::string const& testCommandArg : this->TestCommandArgs) {
+ out << " \"" << testCommandArg << "\"";
}
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. ";
}
@@ -334,8 +357,8 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
}
}
- int runTestRes = this->CTest->RunTest(testCommand, &outs, &retval,
- CM_NULLPTR, remainingTime, CM_NULLPTR);
+ int runTestRes = this->CTest->RunTest(testCommand, &outs, &retval, nullptr,
+ remainingTime, nullptr);
if (runTestRes != cmsysProcess_State_Exited || retval != 0) {
out << "Test command failed: " << testCommand[0] << "\n";
@@ -364,7 +387,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 {
@@ -394,7 +417,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 2e85e9fed..0c8a04079 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.h
+++ b/Source/CTest/cmCTestBuildAndTestHandler.h
@@ -3,15 +3,17 @@
#ifndef cmCTestBuildAndTestHandler_h
#define cmCTestBuildAndTestHandler_h
-#include "cmConfigure.h"
-
-#include "cmCTestGenericHandler.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <sstream>
-#include <stddef.h>
#include <string>
#include <vector>
+#include <stddef.h>
+
+#include "cmCTestGenericHandler.h"
+#include "cmDuration.h"
+
class cmake;
/** \class cmCTestBuildAndTestHandler
@@ -21,17 +23,17 @@ class cmake;
class cmCTestBuildAndTestHandler : public cmCTestGenericHandler
{
public:
- typedef cmCTestGenericHandler Superclass;
+ using Superclass = cmCTestGenericHandler;
/*
* The main entry point for this class
*/
- int ProcessHandler() CM_OVERRIDE;
+ int ProcessHandler() override;
//! Set all the build and test arguments
- int ProcessCommandLineArguments(const std::string& currentArg, size_t& idx,
- const std::vector<std::string>& allArgs)
- CM_OVERRIDE;
+ int ProcessCommandLineArguments(
+ const std::string& currentArg, size_t& idx,
+ const std::vector<std::string>& allArgs) override;
/*
* Get the output variable
@@ -40,10 +42,10 @@ public:
cmCTestBuildAndTestHandler();
- void Initialize() CM_OVERRIDE;
+ void Initialize() override;
protected:
- ///! Run CMake and build a test and then run it as a single test.
+ //! Run CMake and build a test and then run it as a single test.
int RunCMakeAndTest(std::string* output);
int RunCMake(std::string* outstring, std::ostringstream& out,
std::string& cmakeOutString, cmake* cm);
@@ -67,7 +69,7 @@ protected:
std::vector<std::string> TestCommandArgs;
std::vector<std::string> BuildTargets;
bool BuildNoCMake;
- double Timeout;
+ cmDuration Timeout;
};
#endif
diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx
index 4c8276007..18df2141e 100644
--- a/Source/CTest/cmCTestBuildCommand.cxx
+++ b/Source/CTest/cmCTestBuildCommand.cxx
@@ -2,48 +2,47 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestBuildCommand.h"
+#include <cstring>
+#include <sstream>
+
+#include "cm_static_string_view.hxx"
+
#include "cmCTest.h"
#include "cmCTestBuildHandler.h"
-#include "cmCTestGenericHandler.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
-#include <sstream>
-#include <string.h>
-
class cmExecutionStatus;
-cmCTestBuildCommand::cmCTestBuildCommand()
+void cmCTestBuildCommand::BindArguments()
{
- this->GlobalGenerator = CM_NULLPTR;
- this->Arguments[ctb_NUMBER_ERRORS] = "NUMBER_ERRORS";
- this->Arguments[ctb_NUMBER_WARNINGS] = "NUMBER_WARNINGS";
- this->Arguments[ctb_TARGET] = "TARGET";
- this->Arguments[ctb_CONFIGURATION] = "CONFIGURATION";
- this->Arguments[ctb_FLAGS] = "FLAGS";
- this->Arguments[ctb_PROJECT_NAME] = "PROJECT_NAME";
- this->Arguments[ctb_LAST] = CM_NULLPTR;
- this->Last = ctb_LAST;
+ this->cmCTestHandlerCommand::BindArguments();
+ this->Bind("NUMBER_ERRORS"_s, this->NumberErrors);
+ this->Bind("NUMBER_WARNINGS"_s, this->NumberWarnings);
+ this->Bind("TARGET"_s, this->Target);
+ this->Bind("CONFIGURATION"_s, this->Configuration);
+ this->Bind("FLAGS"_s, this->Flags);
+ this->Bind("PROJECT_NAME"_s, this->ProjectName);
}
cmCTestBuildCommand::~cmCTestBuildCommand()
{
if (this->GlobalGenerator) {
delete this->GlobalGenerator;
- this->GlobalGenerator = CM_NULLPTR;
+ this->GlobalGenerator = nullptr;
}
}
cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
{
- cmCTestGenericHandler* handler = this->CTest->GetInitializedHandler("build");
- if (!handler) {
- this->SetError("internal CTest error. Cannot instantiate build handler");
- return CM_NULLPTR;
- }
- this->Handler = (cmCTestBuildHandler*)handler;
+ cmCTestBuildHandler* handler = this->CTest->GetBuildHandler();
+ handler->Initialize();
+
+ this->Handler = handler;
const char* ctestBuildCommand =
this->Makefile->GetDefinition("CTEST_BUILD_COMMAND");
@@ -53,10 +52,6 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
} else {
const char* cmakeGeneratorName =
this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR");
- const char* cmakeProjectName =
- (this->Values[ctb_PROJECT_NAME] && *this->Values[ctb_PROJECT_NAME])
- ? this->Values[ctb_PROJECT_NAME]
- : this->Makefile->GetDefinition("CTEST_PROJECT_NAME");
// Build configuration is determined by: CONFIGURATION argument,
// or CTEST_BUILD_CONFIGURATION script variable, or
@@ -65,31 +60,27 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
//
const char* ctestBuildConfiguration =
this->Makefile->GetDefinition("CTEST_BUILD_CONFIGURATION");
- const char* cmakeBuildConfiguration =
- (this->Values[ctb_CONFIGURATION] && *this->Values[ctb_CONFIGURATION])
- ? this->Values[ctb_CONFIGURATION]
+ const char* cmakeBuildConfiguration = !this->Configuration.empty()
+ ? this->Configuration.c_str()
: ((ctestBuildConfiguration && *ctestBuildConfiguration)
? ctestBuildConfiguration
: this->CTest->GetConfigType().c_str());
- const char* cmakeBuildAdditionalFlags =
- (this->Values[ctb_FLAGS] && *this->Values[ctb_FLAGS])
- ? this->Values[ctb_FLAGS]
+ const char* cmakeBuildAdditionalFlags = !this->Flags.empty()
+ ? this->Flags.c_str()
: this->Makefile->GetDefinition("CTEST_BUILD_FLAGS");
- const char* cmakeBuildTarget =
- (this->Values[ctb_TARGET] && *this->Values[ctb_TARGET])
- ? this->Values[ctb_TARGET]
+ const char* cmakeBuildTarget = !this->Target.empty()
+ ? this->Target.c_str()
: this->Makefile->GetDefinition("CTEST_BUILD_TARGET");
- if (cmakeGeneratorName && *cmakeGeneratorName && cmakeProjectName &&
- *cmakeProjectName) {
+ if (cmakeGeneratorName && *cmakeGeneratorName) {
if (!cmakeBuildConfiguration) {
cmakeBuildConfiguration = "Release";
}
if (this->GlobalGenerator) {
if (this->GlobalGenerator->GetName() != cmakeGeneratorName) {
delete this->GlobalGenerator;
- this->GlobalGenerator = CM_NULLPTR;
+ this->GlobalGenerator = nullptr;
}
}
if (!this->GlobalGenerator) {
@@ -97,16 +88,15 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
this->Makefile->GetCMakeInstance()->CreateGlobalGenerator(
cmakeGeneratorName);
if (!this->GlobalGenerator) {
- std::string e = "could not create generator named \"";
- e += cmakeGeneratorName;
- e += "\"";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e);
+ std::string e = cmStrCat("could not create generator named \"",
+ cmakeGeneratorName, '"');
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e);
cmSystemTools::SetFatalErrorOccured();
- return CM_NULLPTR;
+ return nullptr;
}
}
if (strlen(cmakeBuildConfiguration) == 0) {
- const char* config = CM_NULLPTR;
+ const char* config = nullptr;
#ifdef CMAKE_INTDIR
config = CMAKE_INTDIR;
#endif
@@ -132,18 +122,11 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
/* clang-format off */
ostr << "has no project to build. If this is a "
"\"built with CMake\" project, verify that CTEST_CMAKE_GENERATOR "
- "and CTEST_PROJECT_NAME are set."
- "\n"
- "CTEST_PROJECT_NAME is usually set in CTestConfig.cmake. Verify "
- "that CTestConfig.cmake exists, or CTEST_PROJECT_NAME "
- "is set in the script, or PROJECT_NAME is passed as an argument "
- "to ctest_build."
- "\n"
- "Alternatively, set CTEST_BUILD_COMMAND to build the project "
+ "is set. Otherwise, set CTEST_BUILD_COMMAND to build the project "
"with a custom command line.";
/* clang-format on */
this->SetError(ostr.str());
- return CM_NULLPTR;
+ return nullptr;
}
}
@@ -153,6 +136,12 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
this->Quiet);
}
+ if (const char* labelsForSubprojects =
+ this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) {
+ this->CTest->SetCTestConfiguration("LabelsForSubprojects",
+ labelsForSubprojects, this->Quiet);
+ }
+
handler->SetQuiet(this->Quiet);
return handler;
}
@@ -161,18 +150,13 @@ bool cmCTestBuildCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
bool ret = cmCTestHandlerCommand::InitialPass(args, status);
- if (this->Values[ctb_NUMBER_ERRORS] && *this->Values[ctb_NUMBER_ERRORS]) {
- std::ostringstream str;
- str << this->Handler->GetTotalErrors();
- this->Makefile->AddDefinition(this->Values[ctb_NUMBER_ERRORS],
- str.str().c_str());
+ if (!this->NumberErrors.empty()) {
+ this->Makefile->AddDefinition(
+ this->NumberErrors, std::to_string(this->Handler->GetTotalErrors()));
}
- if (this->Values[ctb_NUMBER_WARNINGS] &&
- *this->Values[ctb_NUMBER_WARNINGS]) {
- std::ostringstream str;
- str << this->Handler->GetTotalWarnings();
- this->Makefile->AddDefinition(this->Values[ctb_NUMBER_WARNINGS],
- str.str().c_str());
+ if (!this->NumberWarnings.empty()) {
+ this->Makefile->AddDefinition(
+ this->NumberWarnings, std::to_string(this->Handler->GetTotalWarnings()));
}
return ret;
}
diff --git a/Source/CTest/cmCTestBuildCommand.h b/Source/CTest/cmCTestBuildCommand.h
index 9cf6a9652..da00a43c6 100644
--- a/Source/CTest/cmCTestBuildCommand.h
+++ b/Source/CTest/cmCTestBuildCommand.h
@@ -3,16 +3,19 @@
#ifndef cmCTestBuildCommand_h
#define cmCTestBuildCommand_h
-#include "cmConfigure.h"
-
-#include "cmCTestHandlerCommand.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
+#include <utility>
#include <vector>
+#include <cm/memory>
+
+#include "cmCTestHandlerCommand.h"
+#include "cmCommand.h"
+
class cmCTestBuildHandler;
class cmCTestGenericHandler;
-class cmCommand;
class cmExecutionStatus;
class cmGlobalGenerator;
@@ -24,45 +27,40 @@ class cmGlobalGenerator;
class cmCTestBuildCommand : public cmCTestHandlerCommand
{
public:
- cmCTestBuildCommand();
- ~cmCTestBuildCommand() CM_OVERRIDE;
+ ~cmCTestBuildCommand() override;
/**
* This is a virtual constructor for the command.
*/
- cmCommand* Clone() CM_OVERRIDE
+ std::unique_ptr<cmCommand> Clone() override
{
- cmCTestBuildCommand* ni = new cmCTestBuildCommand;
+ auto ni = cm::make_unique<cmCTestBuildCommand>();
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
- return ni;
+ return std::unique_ptr<cmCommand>(std::move(ni));
}
/**
* The name of the command as specified in CMakeList.txt.
*/
- std::string GetName() const CM_OVERRIDE { return "ctest_build"; }
+ std::string GetName() const override { return "ctest_build"; }
bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
+ cmExecutionStatus& status) override;
- cmGlobalGenerator* GlobalGenerator;
+ cmGlobalGenerator* GlobalGenerator = nullptr;
protected:
cmCTestBuildHandler* Handler;
- enum
- {
- ctb_BUILD = ct_LAST,
- ctb_NUMBER_ERRORS,
- ctb_NUMBER_WARNINGS,
- ctb_TARGET,
- ctb_CONFIGURATION,
- ctb_FLAGS,
- ctb_PROJECT_NAME,
- ctb_LAST
- };
+ void BindArguments() override;
+ cmCTestGenericHandler* InitializeHandler() override;
- cmCTestGenericHandler* InitializeHandler() CM_OVERRIDE;
+ std::string NumberErrors;
+ std::string NumberWarnings;
+ std::string Target;
+ std::string Configuration;
+ std::string Flags;
+ std::string ProjectName;
};
#endif
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index 18ef05c67..9cb5449d9 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -2,22 +2,27 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestBuildHandler.h"
+#include <cstdlib>
+#include <cstring>
+#include <set>
+#include <utility>
+
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/Process.h"
+
#include "cmAlgorithms.h"
#include "cmCTest.h"
-#include "cmFileTimeComparison.h"
+#include "cmDuration.h"
+#include "cmFileTimeCache.h"
#include "cmGeneratedFileStream.h"
#include "cmMakefile.h"
#include "cmProcessOutput.h"
+#include "cmStringAlgorithms.h"
+#include "cmStringReplaceHelper.h"
#include "cmSystemTools.h"
#include "cmXMLWriter.h"
-#include "cmsys/Directory.hxx"
-#include "cmsys/FStream.hxx"
-#include "cmsys/Process.h"
-#include <set>
-#include <stdlib.h>
-#include <string.h>
-
static const char* cmCTestErrorMatches[] = {
"^[Bb]us [Ee]rror",
"^[Ss]egmentation [Vv]iolation",
@@ -30,13 +35,13 @@ static const char* cmCTestErrorMatches[] = {
"^Error: ",
"^Error ",
"[0-9] ERROR: ",
- "^\"[^\"]+\", line [0-9]+: [^Ww]",
+ R"(^"[^"]+", line [0-9]+: [^Ww])",
"^cc[^C]*CC: ERROR File = ([^,]+), Line = ([0-9]+)",
"^ld([^:])*:([ \\t])*ERROR([^:])*:",
- "^ild:([ \\t])*\\(undefined symbol\\)",
+ R"(^ild:([ \t])*\(undefined symbol\))",
"([^ :]+) : (error|fatal error|catastrophic error)",
"([^:]+): (Error:|error|undefined reference|multiply defined)",
- "([^:]+)\\(([^\\)]+)\\) ?: (error|fatal error|catastrophic error)",
+ R"(([^:]+)\(([^\)]+)\) ?: (error|fatal error|catastrophic error))",
"^fatal error C[0-9]+:",
": syntax error ",
"^collect2: ld returned 1 exit status",
@@ -48,14 +53,14 @@ static const char* cmCTestErrorMatches[] = {
"^CMake Error.*:",
":[ \\t]cannot find",
":[ \\t]can't find",
- ": \\*\\*\\* No rule to make target [`'].*\\'. Stop",
- ": \\*\\*\\* No targets specified and no makefile found",
+ R"(: \*\*\* No rule to make target [`'].*\'. Stop)",
+ R"(: \*\*\* No targets specified and no makefile found)",
": Invalid loader fixup for symbol",
": Invalid fixups exist",
": Can't find library for",
": internal link edit command failed",
": Unrecognized option [`'].*\\'",
- "\", line [0-9]+\\.[0-9]+: [0-9]+-[0-9]+ \\([^WI]\\)",
+ R"(", line [0-9]+\.[0-9]+: [0-9]+-[0-9]+ \([^WI]\))",
"ld: 0706-006 Cannot find or open library file: -l ",
"ild: \\(argument error\\) can't find library argument ::",
"^could not be found and will not be loaded.",
@@ -64,23 +69,24 @@ static const char* cmCTestErrorMatches[] = {
"ld: 0711-993 Error occurred while writing to the output file:",
"ld: fatal: ",
"final link failed:",
- "make: \\*\\*\\*.*Error",
- "make\\[.*\\]: \\*\\*\\*.*Error",
- "\\*\\*\\* Error code",
+ R"(make: \*\*\*.*Error)",
+ R"(make\[.*\]: \*\*\*.*Error)",
+ R"(\*\*\* Error code)",
"nternal error:",
- "Makefile:[0-9]+: \\*\\*\\* .* Stop\\.",
+ R"(Makefile:[0-9]+: \*\*\* .* Stop\.)",
": No such file or directory",
": Invalid argument",
"^The project cannot be built\\.",
"^\\[ERROR\\]",
"^Command .* failed with exit code",
- CM_NULLPTR
+ nullptr
};
static const char* cmCTestErrorExceptions[] = {
"instantiated from ",
"candidates are:",
": warning",
+ ": WARNING",
": \\(Warning\\)",
": note",
"Note:",
@@ -89,7 +95,7 @@ static const char* cmCTestErrorExceptions[] = {
":[ \\t]+Where:",
"([^ :]+):([0-9]+): Warning",
"------ Build started: .* ------",
- CM_NULLPTR
+ nullptr
};
static const char* cmCTestWarningMatches[] = {
@@ -98,29 +104,29 @@ static const char* cmCTestWarningMatches[] = {
"^cc[^C]*CC: WARNING File = ([^,]+), Line = ([0-9]+)",
"^ld([^:])*:([ \\t])*WARNING([^:])*:",
"([^:]+): warning ([0-9]+):",
- "^\"[^\"]+\", line [0-9]+: [Ww](arning|arnung)",
+ R"(^"[^"]+", line [0-9]+: [Ww](arning|arnung))",
"([^:]+): warning[ \\t]*[0-9]+[ \\t]*:",
"^(Warning|Warnung) ([0-9]+):",
"^(Warning|Warnung)[ :]",
"WARNING: ",
"([^ :]+) : warning",
"([^:]+): warning",
- "\", line [0-9]+\\.[0-9]+: [0-9]+-[0-9]+ \\([WI]\\)",
+ R"(", line [0-9]+\.[0-9]+: [0-9]+-[0-9]+ \([WI]\))",
"^cxx: Warning:",
".*file: .* has no symbols",
"([^ :]+):([0-9]+): (Warning|Warnung)",
"\\([0-9]*\\): remark #[0-9]*",
- "\".*\", line [0-9]+: remark\\([0-9]*\\):",
+ R"(".*", line [0-9]+: remark\([0-9]*\):)",
"cc-[0-9]* CC: REMARK File = .*, Line = [0-9]*",
"^CMake Warning.*:",
"^\\[WARNING\\]",
- CM_NULLPTR
+ nullptr
};
static const char* cmCTestWarningExceptions[] = {
- "/usr/.*/X11/Xlib\\.h:[0-9]+: war.*: ANSI C\\+\\+ forbids declaration",
- "/usr/.*/X11/Xutil\\.h:[0-9]+: war.*: ANSI C\\+\\+ forbids declaration",
- "/usr/.*/X11/XResource\\.h:[0-9]+: war.*: ANSI C\\+\\+ forbids declaration",
+ R"(/usr/.*/X11/Xlib\.h:[0-9]+: war.*: ANSI C\+\+ forbids declaration)",
+ R"(/usr/.*/X11/Xutil\.h:[0-9]+: war.*: ANSI C\+\+ forbids declaration)",
+ R"(/usr/.*/X11/XResource\.h:[0-9]+: war.*: ANSI C\+\+ forbids declaration)",
"WARNING 84 :",
"WARNING 47 :",
"makefile:",
@@ -134,7 +140,7 @@ static const char* cmCTestWarningExceptions[] = {
"ld32: WARNING 85: definition of dataKey in",
"cc: warning 422: Unknown option \"\\+b",
"_with_warning_C",
- CM_NULLPTR
+ nullptr
};
struct cmCTestBuildCompileErrorWarningRex
@@ -147,12 +153,12 @@ struct cmCTestBuildCompileErrorWarningRex
static cmCTestBuildCompileErrorWarningRex cmCTestWarningErrorFileLine[] = {
{ "^Warning W[0-9]+ ([a-zA-Z.\\:/0-9_+ ~-]+) ([0-9]+):", 1, 2 },
{ "^([a-zA-Z./0-9_+ ~-]+):([0-9]+):", 1, 2 },
- { "^([a-zA-Z.\\:/0-9_+ ~-]+)\\(([0-9]+)\\)", 1, 2 },
- { "^[0-9]+>([a-zA-Z.\\:/0-9_+ ~-]+)\\(([0-9]+)\\)", 1, 2 },
+ { R"(^([a-zA-Z.\:/0-9_+ ~-]+)\(([0-9]+)\))", 1, 2 },
+ { R"(^[0-9]+>([a-zA-Z.\:/0-9_+ ~-]+)\(([0-9]+)\))", 1, 2 },
{ "^([a-zA-Z./0-9_+ ~-]+)\\(([0-9]+)\\)", 1, 2 },
{ "\"([a-zA-Z./0-9_+ ~-]+)\", line ([0-9]+)", 1, 2 },
{ "File = ([a-zA-Z./0-9_+ ~-]+), Line = ([0-9]+)", 1, 2 },
- { CM_NULLPTR, 0, 0 }
+ { nullptr, 0, 0 }
};
cmCTestBuildHandler::cmCTestBuildHandler()
@@ -171,8 +177,8 @@ cmCTestBuildHandler::cmCTestBuildHandler()
void cmCTestBuildHandler::Initialize()
{
this->Superclass::Initialize();
- this->StartBuild = "";
- this->EndBuild = "";
+ this->StartBuild.clear();
+ this->EndBuild.clear();
this->CustomErrorMatches.clear();
this->CustomErrorExceptions.clear();
this->CustomWarningMatches.clear();
@@ -190,8 +196,8 @@ void cmCTestBuildHandler::Initialize()
this->BuildOutputLogSize = 0;
this->CurrentProcessingLine.clear();
- this->SimplifySourceDir = "";
- this->SimplifyBuildDir = "";
+ this->SimplifySourceDir.clear();
+ this->SimplifyBuildDir.clear();
this->OutputLineCounter = 0;
this->ErrorsAndWarnings.clear();
this->LastErrorOrWarning = this->ErrorsAndWarnings.end();
@@ -243,13 +249,11 @@ void cmCTestBuildHandler::PopulateCustomVectors(cmMakefile* mf)
// Record the user-specified custom warning rules.
if (const char* customWarningMatchers =
mf->GetDefinition("CTEST_CUSTOM_WARNING_MATCH")) {
- cmSystemTools::ExpandListArgument(customWarningMatchers,
- this->ReallyCustomWarningMatches);
+ cmExpandList(customWarningMatchers, this->ReallyCustomWarningMatches);
}
if (const char* customWarningExceptions =
mf->GetDefinition("CTEST_CUSTOM_WARNING_EXCEPTION")) {
- cmSystemTools::ExpandListArgument(customWarningExceptions,
- this->ReallyCustomWarningExceptions);
+ cmExpandList(customWarningExceptions, this->ReallyCustomWarningExceptions);
}
}
@@ -260,11 +264,11 @@ std::string cmCTestBuildHandler::GetMakeCommand()
"MakeCommand:" << makeCommand << "\n", this->Quiet);
std::string configType = this->CTest->GetConfigType();
- if (configType == "") {
+ if (configType.empty()) {
configType =
this->CTest->GetCTestConfiguration("DefaultCTestConfigurationType");
}
- if (configType == "") {
+ if (configType.empty()) {
configType = "Release";
}
@@ -282,7 +286,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,10 +298,11 @@ 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: "
+ this->CTest, ERROR_MESSAGE,
+ "Problem Compiling regular expression: "
<< cmCTestWarningErrorFileLine[entry].RegularExpressionString
<< std::endl);
}
@@ -323,46 +328,48 @@ int cmCTestBuildHandler::ProcessHandler()
std::string const& useLaunchers =
this->CTest->GetCTestConfiguration("UseLaunchers");
- this->UseCTestLaunch = cmSystemTools::IsOn(useLaunchers.c_str());
+ this->UseCTestLaunch = cmIsOn(useLaunchers);
// 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);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot create build log file" << std::endl);
}
// Create lists of regular expression strings for errors, error exceptions,
// warnings and warning exceptions.
std::vector<std::string>::size_type cc;
for (cc = 0; cmCTestErrorMatches[cc]; cc++) {
- this->CustomErrorMatches.push_back(cmCTestErrorMatches[cc]);
+ this->CustomErrorMatches.emplace_back(cmCTestErrorMatches[cc]);
}
for (cc = 0; cmCTestErrorExceptions[cc]; cc++) {
- this->CustomErrorExceptions.push_back(cmCTestErrorExceptions[cc]);
+ this->CustomErrorExceptions.emplace_back(cmCTestErrorExceptions[cc]);
}
for (cc = 0; cmCTestWarningMatches[cc]; cc++) {
- this->CustomWarningMatches.push_back(cmCTestWarningMatches[cc]);
+ this->CustomWarningMatches.emplace_back(cmCTestWarningMatches[cc]);
}
for (cc = 0; cmCTestWarningExceptions[cc]; cc++) {
- this->CustomWarningExceptions.push_back(cmCTestWarningExceptions[cc]);
+ this->CustomWarningExceptions.emplace_back(cmCTestWarningExceptions[cc]);
}
// Pre-compile regular expressions objects for all regular expressions
- std::vector<std::string>::iterator it;
#define cmCTestBuildHandlerPopulateRegexVector(strings, regexes) \
- regexes.clear(); \
- cmCTestOptionalLog(this->CTest, DEBUG, \
- this << "Add " #regexes << std::endl, this->Quiet); \
- for (it = (strings).begin(); it != (strings).end(); ++it) { \
+ do { \
+ regexes.clear(); \
cmCTestOptionalLog(this->CTest, DEBUG, \
- "Add " #strings ": " << *it << std::endl, \
- this->Quiet); \
- (regexes).push_back(it->c_str()); \
- }
+ this << "Add " #regexes << std::endl, this->Quiet); \
+ for (std::string const& s : (strings)) { \
+ cmCTestOptionalLog(this->CTest, DEBUG, \
+ "Add " #strings ": " << s << std::endl, \
+ this->Quiet); \
+ (regexes).emplace_back(s); \
+ } \
+ } while (false)
+
cmCTestBuildHandlerPopulateRegexVector(this->CustomErrorMatches,
this->ErrorMatchRegex);
cmCTestBuildHandlerPopulateRegexVector(this->CustomErrorExceptions,
@@ -373,16 +380,13 @@ int cmCTestBuildHandler::ProcessHandler()
this->WarningExceptionRegex);
// Determine source and binary tree substitutions to simplify the output.
- this->SimplifySourceDir = "";
- this->SimplifyBuildDir = "";
+ this->SimplifySourceDir.clear();
+ this->SimplifyBuildDir.clear();
if (this->CTest->GetCTestConfiguration("SourceDirectory").size() > 20) {
std::string srcdir =
this->CTest->GetCTestConfiguration("SourceDirectory") + "/";
- std::string srcdirrep;
for (cc = srcdir.size() - 2; cc > 0; cc--) {
if (srcdir[cc] == '/') {
- srcdirrep = srcdir.c_str() + cc;
- srcdirrep = "/..." + srcdirrep;
srcdir = srcdir.substr(0, cc + 1);
break;
}
@@ -392,11 +396,8 @@ int cmCTestBuildHandler::ProcessHandler()
if (this->CTest->GetCTestConfiguration("BuildDirectory").size() > 20) {
std::string bindir =
this->CTest->GetCTestConfiguration("BuildDirectory") + "/";
- std::string bindirrep;
for (cc = bindir.size() - 2; cc > 0; cc--) {
if (bindir[cc] == '/') {
- bindirrep = bindir.c_str() + cc;
- bindirrep = "/..." + bindirrep;
bindir = bindir.substr(0, cc + 1);
break;
}
@@ -408,12 +409,15 @@ int cmCTestBuildHandler::ProcessHandler()
// Remember start build time
this->StartBuild = this->CTest->CurrentTime();
- this->StartBuildTime = cmSystemTools::GetTime();
+ this->StartBuildTime = std::chrono::system_clock::now();
+
+ cmStringReplaceHelper colorRemover("\x1b\\[[0-9;]*m", "", nullptr);
+ this->ColorRemover = &colorRemover;
int retVal = 0;
int res = cmsysProcess_State_Exited;
if (!this->CTest->GetShowOnly()) {
- res = this->RunMakeCommand(makeCommand.c_str(), &retVal,
- buildDirectory.c_str(), 0, ofs);
+ res = this->RunMakeCommand(makeCommand, &retVal, buildDirectory.c_str(), 0,
+ ofs);
} else {
cmCTestOptionalLog(this->CTest, DEBUG,
"Build with command: " << makeCommand << std::endl,
@@ -422,31 +426,29 @@ 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.
- t_ErrorsAndWarningsVector::iterator evit;
if (!this->SimplifySourceDir.empty()) {
- for (evit = this->ErrorsAndWarnings.begin();
- evit != this->ErrorsAndWarnings.end(); ++evit) {
- cmSystemTools::ReplaceString(evit->Text, this->SimplifySourceDir.c_str(),
+ for (cmCTestBuildErrorWarning& evit : this->ErrorsAndWarnings) {
+ cmSystemTools::ReplaceString(evit.Text, this->SimplifySourceDir.c_str(),
"/.../");
- cmSystemTools::ReplaceString(evit->PreContext,
+ cmSystemTools::ReplaceString(evit.PreContext,
this->SimplifySourceDir.c_str(), "/.../");
- cmSystemTools::ReplaceString(evit->PostContext,
+ cmSystemTools::ReplaceString(evit.PostContext,
this->SimplifySourceDir.c_str(), "/.../");
}
}
if (!this->SimplifyBuildDir.empty()) {
- for (evit = this->ErrorsAndWarnings.begin();
- evit != this->ErrorsAndWarnings.end(); ++evit) {
- cmSystemTools::ReplaceString(evit->Text, this->SimplifyBuildDir.c_str(),
+ for (cmCTestBuildErrorWarning& evit : this->ErrorsAndWarnings) {
+ cmSystemTools::ReplaceString(evit.Text, this->SimplifyBuildDir.c_str(),
"/.../");
- cmSystemTools::ReplaceString(evit->PreContext,
+ cmSystemTools::ReplaceString(evit.PreContext,
this->SimplifyBuildDir.c_str(), "/.../");
- cmSystemTools::ReplaceString(evit->PostContext,
+ cmSystemTools::ReplaceString(evit.PostContext,
this->SimplifyBuildDir.c_str(), "/.../");
}
}
@@ -454,8 +456,8 @@ int cmCTestBuildHandler::ProcessHandler()
// Generate XML output
cmGeneratedFileStream xofs;
if (!this->StartResultingXML(cmCTest::PartBuild, "Build", xofs)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create build XML file"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot create build XML file" << std::endl);
return -1;
}
cmXMLWriter xml(xofs);
@@ -468,19 +470,20 @@ int cmCTestBuildHandler::ProcessHandler()
this->GenerateXMLFooter(xml, elapsed_build_time);
if (res != cmsysProcess_State_Exited || retVal || this->TotalErrors > 0) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Error(s) when building project"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error(s) when building project" << std::endl);
}
// Display message about number of errors and warnings
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " "
- << this->TotalErrors
- << (this->TotalErrors >= this->MaxErrors ? " or more" : "")
- << " Compiler errors" << std::endl);
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " "
- << this->TotalWarnings
- << (this->TotalWarnings >= this->MaxWarnings ? " or more" : "")
- << " Compiler warnings" << std::endl);
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " " << this->TotalErrors
+ << (this->TotalErrors >= this->MaxErrors ? " or more" : "")
+ << " Compiler errors" << std::endl);
+ cmCTestLog(
+ this->CTest, HANDLER_OUTPUT,
+ " " << this->TotalWarnings
+ << (this->TotalWarnings >= this->MaxWarnings ? " or more" : "")
+ << " Compiler warnings" << std::endl);
return retVal;
}
@@ -488,38 +491,34 @@ int cmCTestBuildHandler::ProcessHandler()
void cmCTestBuildHandler::GenerateXMLHeader(cmXMLWriter& xml)
{
this->CTest->StartXML(xml, this->AppendXML);
+ 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());
}
class cmCTestBuildHandler::FragmentCompare
{
public:
- FragmentCompare(cmFileTimeComparison* ftc)
+ FragmentCompare(cmFileTimeCache* ftc)
: FTC(ftc)
{
}
- FragmentCompare()
- : FTC(CM_NULLPTR)
- {
- }
+ FragmentCompare() = default;
bool operator()(std::string const& l, std::string const& r) const
{
// Order files by modification time. Use lexicographic order
// among files with the same time.
int result;
- if (this->FTC->FileTimeCompare(l.c_str(), r.c_str(), &result) &&
- result != 0) {
+ if (this->FTC->Compare(l, r, &result) && result != 0) {
return result < 0;
}
return l < r;
}
private:
- cmFileTimeComparison* FTC;
+ cmFileTimeCache* FTC = nullptr;
};
void cmCTestBuildHandler::GenerateXMLLaunched(cmXMLWriter& xml)
@@ -529,9 +528,9 @@ void cmCTestBuildHandler::GenerateXMLLaunched(cmXMLWriter& xml)
}
// Sort XML fragments in chronological order.
- cmFileTimeComparison ftc;
+ cmFileTimeCache ftc;
FragmentCompare fragmentCompare(&ftc);
- typedef std::set<std::string, FragmentCompare> Fragments;
+ using Fragments = std::set<std::string, FragmentCompare>;
Fragments fragments(fragmentCompare);
// only report the first 50 warnings and first 50 errors
@@ -555,9 +554,8 @@ void cmCTestBuildHandler::GenerateXMLLaunched(cmXMLWriter& xml)
}
// Copy the fragments into the final XML file.
- for (Fragments::const_iterator fi = fragments.begin(); fi != fragments.end();
- ++fi) {
- xml.FragmentFile(fi->c_str());
+ for (std::string const& f : fragments) {
+ xml.FragmentFile(f.c_str());
}
}
@@ -572,8 +570,7 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(cmXMLWriter& xml)
std::string srcdir = this->CTest->GetCTestConfiguration("SourceDirectory");
// make sure the source dir is in the correct case on windows
// via a call to collapse full path.
- srcdir = cmSystemTools::CollapseFullPath(srcdir);
- srcdir += "/";
+ srcdir = cmStrCat(cmSystemTools::CollapseFullPath(srcdir), '/');
for (it = ew.begin();
it != ew.end() && (numErrorsAllowed || numWarningsAllowed); it++) {
cmCTestBuildErrorWarning* cm = &(*it);
@@ -587,12 +584,11 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(cmXMLWriter& xml)
xml.StartElement(cm->Error ? "Error" : "Warning");
xml.Element("BuildLogLine", cm->LogLine);
xml.Element("Text", cm->Text);
- std::vector<cmCTestCompileErrorWarningRex>::iterator rit;
- for (rit = this->ErrorWarningFileLineRegex.begin();
- rit != this->ErrorWarningFileLineRegex.end(); ++rit) {
- cmsys::RegularExpression* re = &rit->RegularExpression;
- if (re->find(cm->Text.c_str())) {
- cm->SourceFile = re->match(rit->FileIndex);
+ for (cmCTestCompileErrorWarningRex& rit :
+ this->ErrorWarningFileLineRegex) {
+ cmsys::RegularExpression* re = &rit.RegularExpression;
+ if (re->find(cm->Text)) {
+ cm->SourceFile = re->match(rit.FileIndex);
// At this point we need to make this->SourceFile relative to
// the source root of the project, so cvs links will work
cmSystemTools::ConvertToUnixSlashes(cm->SourceFile);
@@ -608,7 +604,7 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(cmXMLWriter& xml)
cm->SourceFile = cmSystemTools::CollapseFullPath(cm->SourceFile);
cmSystemTools::ReplaceString(cm->SourceFile, srcdir.c_str(), "");
}
- cm->LineNumber = atoi(re->match(rit->LineIndex).c_str());
+ cm->LineNumber = atoi(re->match(rit.LineIndex).c_str());
break;
}
}
@@ -640,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");
@@ -648,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);
}
@@ -679,6 +677,8 @@ class cmCTestBuildHandler::LaunchHelper
public:
LaunchHelper(cmCTestBuildHandler* handler);
~LaunchHelper();
+ LaunchHelper(const LaunchHelper&) = delete;
+ LaunchHelper& operator=(const LaunchHelper&) = delete;
private:
cmCTestBuildHandler* Handler;
@@ -701,20 +701,17 @@ cmCTestBuildHandler::LaunchHelper::LaunchHelper(cmCTestBuildHandler* handler)
} else {
// Compute a directory in which to store launcher fragments.
std::string& launchDir = this->Handler->CTestLaunchDir;
- launchDir = this->CTest->GetBinaryDir();
- launchDir += "/Testing/";
- launchDir += tag;
- launchDir += "/Build";
+ launchDir =
+ cmStrCat(this->CTest->GetBinaryDir(), "/Testing/", tag, "/Build");
// Clean out any existing launcher fragments.
cmSystemTools::RemoveADirectory(launchDir);
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;
+ std::string launchEnv = cmStrCat("CTEST_LAUNCH_LOGS=", launchDir);
cmSystemTools::PutEnv(launchEnv);
}
}
@@ -740,9 +737,9 @@ void cmCTestBuildHandler::LaunchHelper::WriteLauncherConfig()
this->Handler->ReallyCustomWarningExceptions);
// Give some testing configuration information to the launcher.
- std::string fname = this->Handler->CTestLaunchDir;
- fname += "/CTestLaunchConfig.cmake";
- cmGeneratedFileStream fout(fname.c_str());
+ std::string fname =
+ cmStrCat(this->Handler->CTestLaunchDir, "/CTestLaunchConfig.cmake");
+ cmGeneratedFileStream fout(fname);
std::string srcdir = this->CTest->GetCTestConfiguration("SourceDirectory");
fout << "set(CTEST_SOURCE_DIRECTORY \"" << srcdir << "\")\n";
}
@@ -753,20 +750,18 @@ void cmCTestBuildHandler::LaunchHelper::WriteScrapeMatchers(
if (matchers.empty()) {
return;
}
- std::string fname = this->Handler->CTestLaunchDir;
- fname += "/Custom";
- fname += purpose;
- fname += ".txt";
- cmGeneratedFileStream fout(fname.c_str());
- for (std::vector<std::string>::const_iterator mi = matchers.begin();
- mi != matchers.end(); ++mi) {
- fout << *mi << "\n";
+ std::string fname =
+ cmStrCat(this->Handler->CTestLaunchDir, "/Custom", purpose, ".txt");
+ cmGeneratedFileStream fout(fname);
+ for (std::string const& m : matchers) {
+ fout << m << "\n";
}
}
-int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal,
- const char* dir, int timeout,
- std::ostream& ofs, Encoding encoding)
+int cmCTestBuildHandler::RunMakeCommand(const std::string& command,
+ int* retVal, const char* dir,
+ int timeout, std::ostream& ofs,
+ Encoding encoding)
{
// First generate the command and arguments
std::vector<std::string> args = cmSystemTools::ParseArguments(command);
@@ -776,18 +771,20 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal,
}
std::vector<const char*> argv;
- for (std::vector<std::string>::const_iterator a = args.begin();
- a != args.end(); ++a) {
- argv.push_back(a->c_str());
+ argv.reserve(args.size() + 1);
+ for (std::string const& arg : args) {
+ argv.push_back(arg.c_str());
}
- argv.push_back(CM_NULLPTR);
+ argv.push_back(nullptr);
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run command:",
- this->Quiet);
- std::vector<const char*>::iterator ait;
- for (ait = argv.begin(); ait != argv.end() && *ait; ++ait) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Run command:", this->Quiet);
+ for (char const* arg : argv) {
+ if (!arg) {
+ break;
+ }
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " \"" << *ait << "\"", this->Quiet);
+ " \"" << arg << "\"", this->Quiet);
}
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl,
this->Quiet);
@@ -798,7 +795,7 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal,
// Now create process object
cmsysProcess* cp = cmsysProcess_New();
- cmsysProcess_SetCommand(cp, &*argv.begin());
+ cmsysProcess_SetCommand(cp, argv.data());
cmsysProcess_SetWorkingDirectory(cp, dir);
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
cmsysProcess_SetTimeout(cp, timeout);
@@ -813,7 +810,8 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal,
cmProcessOutput processOutput(encoding);
std::string strdata;
cmCTestOptionalLog(
- this->CTest, HANDLER_PROGRESS_OUTPUT, " Each symbol represents "
+ this->CTest, HANDLER_PROGRESS_OUTPUT,
+ " Each symbol represents "
<< tick_len << " bytes of output." << std::endl
<< (this->UseCTestLaunch
? ""
@@ -834,7 +832,7 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal,
// For every chunk of data
int res;
- while ((res = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR))) {
+ while ((res = cmsysProcess_WaitForData(cp, &data, &length, nullptr))) {
// Replace '\0' with '\n', since '\0' does not really make sense. This is
// for Visual Studio output
for (int cc = 0; cc < length; ++cc) {
@@ -865,17 +863,18 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal,
&this->BuildProcessingQueue);
}
- this->ProcessBuffer(CM_NULLPTR, 0, tick, tick_len, ofs,
+ this->ProcessBuffer(nullptr, 0, tick, tick_len, ofs,
&this->BuildProcessingQueue);
- this->ProcessBuffer(CM_NULLPTR, 0, tick, tick_len, ofs,
+ this->ProcessBuffer(nullptr, 0, tick, tick_len, ofs,
&this->BuildProcessingErrorQueue);
- cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT, " Size of output: "
+ cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT,
+ " Size of output: "
<< ((this->BuildOutputLogSize + 512) / 1024) << "K"
<< std::endl,
this->Quiet);
// Properly handle output of the build command
- cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+ cmsysProcess_WaitForExit(cp, nullptr);
int result = cmsysProcess_GetState(cp);
if (result == cmsysProcess_State_Exited) {
@@ -891,13 +890,12 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal,
// dashboard.
cmCTestBuildErrorWarning errorwarning;
errorwarning.LogLine = 1;
- errorwarning.Text =
- "*** WARNING non-zero return value in ctest from: ";
- errorwarning.Text += argv[0];
- errorwarning.PreContext = "";
- errorwarning.PostContext = "";
+ errorwarning.Text = cmStrCat(
+ "*** WARNING non-zero return value in ctest from: ", argv[0]);
+ errorwarning.PreContext.clear();
+ errorwarning.PostContext.clear();
errorwarning.Error = false;
- this->ErrorsAndWarnings.push_back(errorwarning);
+ this->ErrorsAndWarnings.push_back(std::move(errorwarning));
this->TotalWarnings++;
}
}
@@ -915,15 +913,16 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal,
// If there was an error running command, report that on the dashboard.
cmCTestBuildErrorWarning errorwarning;
errorwarning.LogLine = 1;
- errorwarning.Text = "*** ERROR executing: ";
- errorwarning.Text += cmsysProcess_GetErrorString(cp);
- errorwarning.PreContext = "";
- errorwarning.PostContext = "";
+ errorwarning.Text =
+ cmStrCat("*** ERROR executing: ", cmsysProcess_GetErrorString(cp));
+ 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);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "There was an error: " << cmsysProcess_GetErrorString(cp)
+ << std::endl);
}
cmsysProcess_Delete(cp);
@@ -970,10 +969,9 @@ void cmCTestBuildHandler::ProcessBuffer(const char* data, size_t length,
if (it != queue->end()) {
// Create a contiguous array for the line
this->CurrentProcessingLine.clear();
- this->CurrentProcessingLine.insert(this->CurrentProcessingLine.end(),
- queue->begin(), it);
+ cmAppend(this->CurrentProcessingLine, queue->begin(), it);
this->CurrentProcessingLine.push_back(0);
- const char* line = &*this->CurrentProcessingLine.begin();
+ const char* line = this->CurrentProcessingLine.data();
// Process the line
int lineType = this->ProcessSingleLine(line);
@@ -1002,19 +1000,17 @@ void cmCTestBuildHandler::ProcessBuffer(const char* data, size_t length,
// This is an error or warning, so generate report
errorwarning.LogLine = static_cast<int>(this->OutputLineCounter + 1);
errorwarning.Text = line;
- errorwarning.PreContext = "";
- errorwarning.PostContext = "";
+ errorwarning.PreContext.clear();
+ errorwarning.PostContext.clear();
// Copy pre-context to report
- std::deque<std::string>::iterator pcit;
- for (pcit = this->PreContext.begin(); pcit != this->PreContext.end();
- ++pcit) {
- errorwarning.PreContext += *pcit + "\n";
+ for (std::string const& pc : this->PreContext) {
+ errorwarning.PreContext += pc + "\n";
}
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 {
@@ -1030,7 +1026,7 @@ void cmCTestBuildHandler::ProcessBuffer(const char* data, size_t length,
}
} else {
// Otherwise store pre-context for the next error
- this->PreContext.push_back(line);
+ this->PreContext.emplace_back(line);
if (this->PreContext.size() > this->MaxPreContext) {
this->PreContext.erase(this->PreContext.begin(),
this->PreContext.end() -
@@ -1052,7 +1048,8 @@ void cmCTestBuildHandler::ProcessBuffer(const char* data, size_t length,
this->LastTickChar, this->Quiet);
tickDisplayed = true;
if (tick % tick_line_len == 0 && tick > 0) {
- cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT, " Size: "
+ cmCTestOptionalLog(this->CTest, HANDLER_PROGRESS_OUTPUT,
+ " Size: "
<< ((this->BuildOutputLogSize + 512) / 1024) << "K"
<< std::endl
<< " ",
@@ -1078,10 +1075,13 @@ int cmCTestBuildHandler::ProcessSingleLine(const char* data)
return b_REGULAR_LINE;
}
- cmCTestOptionalLog(this->CTest, DEBUG, "Line: [" << data << "]" << std::endl,
- this->Quiet);
+ // Ignore ANSI color codes when checking for errors and warnings.
+ std::string input(data);
+ std::string line;
+ this->ColorRemover->Replace(input, line);
- std::vector<cmsys::RegularExpression>::iterator it;
+ cmCTestOptionalLog(this->CTest, DEBUG, "Line: [" << line << "]" << std::endl,
+ this->Quiet);
int warningLine = 0;
int errorLine = 0;
@@ -1091,12 +1091,11 @@ int cmCTestBuildHandler::ProcessSingleLine(const char* data)
if (!this->ErrorQuotaReached) {
// Errors
int wrxCnt = 0;
- for (it = this->ErrorMatchRegex.begin(); it != this->ErrorMatchRegex.end();
- ++it) {
- if (it->find(data)) {
+ for (cmsys::RegularExpression& rx : this->ErrorMatchRegex) {
+ if (rx.find(line.c_str())) {
errorLine = 1;
cmCTestOptionalLog(this->CTest, DEBUG,
- " Error Line: " << data << " (matches: "
+ " Error Line: " << line << " (matches: "
<< this->CustomErrorMatches[wrxCnt]
<< ")" << std::endl,
this->Quiet);
@@ -1106,12 +1105,12 @@ int cmCTestBuildHandler::ProcessSingleLine(const char* data)
}
// Error exceptions
wrxCnt = 0;
- for (it = this->ErrorExceptionRegex.begin();
- it != this->ErrorExceptionRegex.end(); ++it) {
- if (it->find(data)) {
+ for (cmsys::RegularExpression& rx : this->ErrorExceptionRegex) {
+ if (rx.find(line.c_str())) {
errorLine = 0;
- cmCTestOptionalLog(this->CTest, DEBUG, " Not an error Line: "
- << data << " (matches: "
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ " Not an error Line: "
+ << line << " (matches: "
<< this->CustomErrorExceptions[wrxCnt] << ")"
<< std::endl,
this->Quiet);
@@ -1123,12 +1122,12 @@ int cmCTestBuildHandler::ProcessSingleLine(const char* data)
if (!this->WarningQuotaReached) {
// Warnings
int wrxCnt = 0;
- for (it = this->WarningMatchRegex.begin();
- it != this->WarningMatchRegex.end(); ++it) {
- if (it->find(data)) {
+ for (cmsys::RegularExpression& rx : this->WarningMatchRegex) {
+ if (rx.find(line.c_str())) {
warningLine = 1;
- cmCTestOptionalLog(this->CTest, DEBUG, " Warning Line: "
- << data << " (matches: "
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ " Warning Line: "
+ << line << " (matches: "
<< this->CustomWarningMatches[wrxCnt] << ")"
<< std::endl,
this->Quiet);
@@ -1139,12 +1138,12 @@ int cmCTestBuildHandler::ProcessSingleLine(const char* data)
wrxCnt = 0;
// Warning exceptions
- for (it = this->WarningExceptionRegex.begin();
- it != this->WarningExceptionRegex.end(); ++it) {
- if (it->find(data)) {
+ for (cmsys::RegularExpression& rx : this->WarningExceptionRegex) {
+ if (rx.find(line.c_str())) {
warningLine = 0;
- cmCTestOptionalLog(this->CTest, DEBUG, " Not a warning Line: "
- << data << " (matches: "
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ " Not a warning Line: "
+ << line << " (matches: "
<< this->CustomWarningExceptions[wrxCnt] << ")"
<< std::endl,
this->Quiet);
diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h
index ef3cddf1b..a5193f6e5 100644
--- a/Source/CTest/cmCTestBuildHandler.h
+++ b/Source/CTest/cmCTestBuildHandler.h
@@ -3,19 +3,24 @@
#ifndef cmCTestBuildHandler_h
#define cmCTestBuildHandler_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmCTestGenericHandler.h"
-
-#include "cmProcessOutput.h"
-#include "cmsys/RegularExpression.hxx"
+#include <chrono>
#include <deque>
#include <iosfwd>
-#include <stddef.h>
#include <string>
#include <vector>
+#include <stddef.h>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmCTestGenericHandler.h"
+#include "cmDuration.h"
+#include "cmProcessOutput.h"
+
class cmMakefile;
+class cmStringReplaceHelper;
class cmXMLWriter;
/** \class cmCTestBuildHandler
@@ -25,22 +30,22 @@ class cmXMLWriter;
class cmCTestBuildHandler : public cmCTestGenericHandler
{
public:
- typedef cmCTestGenericHandler Superclass;
- typedef cmProcessOutput::Encoding Encoding;
+ using Superclass = cmCTestGenericHandler;
+ using Encoding = cmProcessOutput::Encoding;
/*
* The main entry point for this class
*/
- int ProcessHandler() CM_OVERRIDE;
+ int ProcessHandler() override;
cmCTestBuildHandler();
- void PopulateCustomVectors(cmMakefile* mf) CM_OVERRIDE;
+ void PopulateCustomVectors(cmMakefile* mf) override;
/**
* Initialize handler
*/
- void Initialize() CM_OVERRIDE;
+ void Initialize() override;
int GetTotalErrors() { return this->TotalErrors; }
int GetTotalWarnings() { return this->TotalWarnings; }
@@ -50,7 +55,7 @@ private:
//! Run command specialized for make and configure. Returns process status
// and retVal is return value or exception.
- int RunMakeCommand(const char* command, int* retVal, const char* dir,
+ int RunMakeCommand(const std::string& command, int* retVal, const char* dir,
int timeout, std::ostream& ofs,
Encoding encoding = cmProcessOutput::Auto);
@@ -86,14 +91,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;
@@ -108,7 +113,7 @@ private:
std::vector<cmsys::RegularExpression> WarningMatchRegex;
std::vector<cmsys::RegularExpression> WarningExceptionRegex;
- typedef std::deque<char> t_BuildProcessingQueueType;
+ using t_BuildProcessingQueueType = std::deque<char>;
void ProcessBuffer(const char* data, size_t length, size_t& tick,
size_t tick_len, std::ostream& ofs,
@@ -123,7 +128,7 @@ private:
std::string SimplifySourceDir;
std::string SimplifyBuildDir;
size_t OutputLineCounter;
- typedef std::vector<cmCTestBuildErrorWarning> t_ErrorsAndWarningsVector;
+ using t_ErrorsAndWarningsVector = std::vector<cmCTestBuildErrorWarning>;
t_ErrorsAndWarningsVector ErrorsAndWarnings;
t_ErrorsAndWarningsVector::iterator LastErrorOrWarning;
size_t PostContextCount;
@@ -141,6 +146,9 @@ private:
int MaxErrors;
int MaxWarnings;
+ // Used to remove ANSI color codes before checking for errors and warnings.
+ cmStringReplaceHelper* ColorRemover;
+
bool UseCTestLaunch;
std::string CTestLaunchDir;
class LaunchHelper;
diff --git a/Source/CTest/cmCTestCVS.cxx b/Source/CTest/cmCTestCVS.cxx
index fad360ba4..45ec39066 100644
--- a/Source/CTest/cmCTestCVS.cxx
+++ b/Source/CTest/cmCTestCVS.cxx
@@ -2,23 +2,25 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestCVS.h"
+#include <utility>
+
+#include <cm/string_view>
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+
#include "cmCTest.h"
#include "cmProcessTools.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLWriter.h"
-#include "cmsys/FStream.hxx"
-#include "cmsys/RegularExpression.hxx"
-#include <utility>
-
cmCTestCVS::cmCTestCVS(cmCTest* ct, std::ostream& log)
: cmCTestVC(ct, log)
{
}
-cmCTestCVS::~cmCTestCVS()
-{
-}
+cmCTestCVS::~cmCTestCVS() = default;
class cmCTestCVS::UpdateParser : public cmCTestVC::LineParser
{
@@ -46,7 +48,7 @@ private:
cmsys::RegularExpression RegexFileRemoved1;
cmsys::RegularExpression RegexFileRemoved2;
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (this->RegexFileUpdated.find(this->Line)) {
this->DoFile(PathUpdated, this->RegexFileUpdated.match(2));
@@ -80,7 +82,7 @@ bool cmCTestCVS::UpdateImpl()
opts = "-dP";
}
}
- std::vector<std::string> args = cmSystemTools::ParseArguments(opts.c_str());
+ std::vector<std::string> args = cmSystemTools::ParseArguments(opts);
// Specify the start time for nightly testing.
if (this->CTest->GetTestModel() == cmCTest::NIGHTLY) {
@@ -92,11 +94,10 @@ bool cmCTestCVS::UpdateImpl()
cvs_update.push_back(this->CommandLineTool.c_str());
cvs_update.push_back("-z3");
cvs_update.push_back("update");
- for (std::vector<std::string>::const_iterator ai = args.begin();
- ai != args.end(); ++ai) {
- cvs_update.push_back(ai->c_str());
+ for (std::string const& arg : args) {
+ cvs_update.push_back(arg.c_str());
}
- cvs_update.push_back(CM_NULLPTR);
+ cvs_update.push_back(nullptr);
UpdateParser out(this, "up-out> ");
UpdateParser err(this, "up-err> ");
@@ -106,14 +107,14 @@ bool cmCTestCVS::UpdateImpl()
class cmCTestCVS::LogParser : public cmCTestVC::LineParser
{
public:
- typedef cmCTestCVS::Revision Revision;
+ using Revision = cmCTestCVS::Revision;
LogParser(cmCTestCVS* cvs, const char* prefix, std::vector<Revision>& revs)
: CVS(cvs)
, Revisions(revs)
, Section(SectionHeader)
{
- this->SetLog(&cvs->Log, prefix),
- this->RegexRevision.compile("^revision +([^ ]*) *$");
+ this->SetLog(&cvs->Log, prefix);
+ this->RegexRevision.compile("^revision +([^ ]*) *$");
this->RegexBranches.compile("^branches: .*$");
this->RegexPerson.compile("^date: +([^;]+); +author: +([^;]+);");
}
@@ -133,10 +134,11 @@ private:
SectionType Section;
Revision Rev;
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
- if (this->Line == ("======================================="
- "======================================")) {
+ if (this->Line ==
+ ("======================================="
+ "======================================")) {
// This line ends the revision list.
if (this->Section == SectionRevisions) {
this->FinishRevision();
@@ -206,8 +208,7 @@ std::string cmCTestCVS::ComputeBranchFlag(std::string const& dir)
if (tagStream && cmSystemTools::GetLineFromStream(tagStream, tagLine) &&
tagLine.size() > 1 && tagLine[0] == 'T') {
// Use the branch specified in the tag file.
- std::string flag = "-r";
- flag += tagLine.substr(1);
+ std::string flag = cmStrCat("-r", cm::string_view(tagLine).substr(1));
return flag;
}
// Use the default branch.
@@ -221,8 +222,9 @@ void cmCTestCVS::LoadRevisions(std::string const& file, const char* branchFlag,
// Run "cvs log" to get revisions of this file on this branch.
const char* cvs = this->CommandLineTool.c_str();
- const char* cvs_log[] = { cvs, "log", "-N",
- branchFlag, file.c_str(), CM_NULLPTR };
+ const char* cvs_log[] = {
+ cvs, "log", "-N", branchFlag, file.c_str(), nullptr
+ };
LogParser out(this, "log-out> ", revisions);
OutputLogger err(this->Log, "log-err> ");
@@ -241,12 +243,12 @@ void cmCTestCVS::WriteXMLDirectory(cmXMLWriter& xml, std::string const& path,
// Load revisions and write an entry for each file in this directory.
std::vector<Revision> revisions;
- for (Directory::const_iterator fi = dir.begin(); fi != dir.end(); ++fi) {
- std::string full = path + slash + fi->first;
+ for (auto const& fi : dir) {
+ std::string full = path + slash + fi.first;
// Load two real or unknown revisions.
revisions.clear();
- if (fi->second != PathUpdated) {
+ if (fi.second != PathUpdated) {
// For local modifications the current rev is unknown and the
// prior rev is the latest from cvs.
revisions.push_back(this->Unknown);
@@ -255,8 +257,8 @@ void cmCTestCVS::WriteXMLDirectory(cmXMLWriter& xml, std::string const& path,
revisions.resize(2, this->Unknown);
// Write the entry for this file with these revisions.
- File f(fi->second, &revisions[0], &revisions[1]);
- this->WriteXMLEntry(xml, path, fi->first, full, f);
+ File f(fi.second, &revisions[0], &revisions[1]);
+ this->WriteXMLEntry(xml, path, fi.first, full, f);
}
xml.EndElement(); // Directory
}
@@ -268,10 +270,8 @@ bool cmCTestCVS::WriteXMLUpdates(cmXMLWriter& xml)
" "
<< std::flush);
- for (std::map<std::string, Directory>::const_iterator di =
- this->Dirs.begin();
- di != this->Dirs.end(); ++di) {
- this->WriteXMLDirectory(xml, di->first, di->second);
+ for (auto const& d : this->Dirs) {
+ this->WriteXMLDirectory(xml, d.first, d.second);
}
cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl);
diff --git a/Source/CTest/cmCTestCVS.h b/Source/CTest/cmCTestCVS.h
index 1208cfad6..7d33d8f2d 100644
--- a/Source/CTest/cmCTestCVS.h
+++ b/Source/CTest/cmCTestCVS.h
@@ -3,15 +3,15 @@
#ifndef cmCTestCVS_h
#define cmCTestCVS_h
-#include "cmConfigure.h"
-
-#include "cmCTestVC.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <map>
#include <string>
#include <vector>
+#include "cmCTestVC.h"
+
class cmCTest;
class cmXMLWriter;
@@ -25,12 +25,12 @@ public:
/** Construct with a CTest instance and update log stream. */
cmCTestCVS(cmCTest* ctest, std::ostream& log);
- ~cmCTestCVS() CM_OVERRIDE;
+ ~cmCTestCVS() override;
private:
// Implement cmCTestVC internal API.
- bool UpdateImpl() CM_OVERRIDE;
- bool WriteXMLUpdates(cmXMLWriter& xml) CM_OVERRIDE;
+ bool UpdateImpl() override;
+ bool WriteXMLUpdates(cmXMLWriter& xml) override;
// Update status for files in each directory.
class Directory : public std::map<std::string, PathStatus>
diff --git a/Source/CTest/cmCTestCommand.h b/Source/CTest/cmCTestCommand.h
index 6fc237aac..8efb4194c 100644
--- a/Source/CTest/cmCTestCommand.h
+++ b/Source/CTest/cmCTestCommand.h
@@ -20,8 +20,8 @@ class cmCTestCommand : public cmCommand
public:
cmCTestCommand()
{
- this->CTest = CM_NULLPTR;
- this->CTestScriptHandler = CM_NULLPTR;
+ this->CTest = nullptr;
+ this->CTestScriptHandler = nullptr;
}
cmCTest* CTest;
diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx
index 73e893df3..f2f42b4f2 100644
--- a/Source/CTest/cmCTestConfigureCommand.cxx
+++ b/Source/CTest/cmCTestConfigureCommand.cxx
@@ -2,30 +2,32 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestConfigureCommand.h"
+#include <cstring>
+#include <sstream>
+#include <vector>
+
+#include "cm_static_string_view.hxx"
+
#include "cmCTest.h"
-#include "cmCTestGenericHandler.h"
+#include "cmCTestConfigureHandler.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
-#include <sstream>
-#include <string.h>
-#include <vector>
-
-cmCTestConfigureCommand::cmCTestConfigureCommand()
+void cmCTestConfigureCommand::BindArguments()
{
- this->Arguments[ctc_OPTIONS] = "OPTIONS";
- this->Arguments[ctc_LAST] = CM_NULLPTR;
- this->Last = ctc_LAST;
+ this->cmCTestHandlerCommand::BindArguments();
+ this->Bind("OPTIONS"_s, this->Options);
}
cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
{
std::vector<std::string> options;
- if (this->Values[ctc_OPTIONS]) {
- cmSystemTools::ExpandListArgument(this->Values[ctc_OPTIONS], options);
+ if (!this->Options.empty()) {
+ cmExpandList(this->Options, options);
}
if (this->CTest->GetCTestConfiguration("BuildDirectory").empty()) {
@@ -33,7 +35,7 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
"Build directory not specified. Either use BUILD "
"argument to CTEST_CONFIGURE command or set CTEST_BINARY_DIRECTORY "
"variable");
- return CM_NULLPTR;
+ return nullptr;
}
const char* ctestConfigureCommand =
@@ -53,15 +55,15 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
"Source directory not specified. Either use SOURCE "
"argument to CTEST_CONFIGURE command or set CTEST_SOURCE_DIRECTORY "
"variable");
- return CM_NULLPTR;
+ return nullptr;
}
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());
- return CM_NULLPTR;
+ return nullptr;
}
bool multiConfig = false;
@@ -75,22 +77,16 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
delete gg;
}
- std::string cmakeConfigureCommand = "\"";
- cmakeConfigureCommand += cmSystemTools::GetCMakeCommand();
- cmakeConfigureCommand += "\"";
-
- std::vector<std::string>::const_iterator it;
- std::string option;
- for (it = options.begin(); it != options.end(); ++it) {
- option = *it;
+ std::string cmakeConfigureCommand =
+ cmStrCat('"', cmSystemTools::GetCMakeCommand(), '"');
+ for (std::string const& option : options) {
cmakeConfigureCommand += " \"";
cmakeConfigureCommand += option;
cmakeConfigureCommand += "\"";
- if ((CM_NULLPTR != strstr(option.c_str(), "CMAKE_BUILD_TYPE=")) ||
- (CM_NULLPTR !=
- strstr(option.c_str(), "CMAKE_BUILD_TYPE:STRING="))) {
+ if ((nullptr != strstr(option.c_str(), "CMAKE_BUILD_TYPE=")) ||
+ (nullptr != strstr(option.c_str(), "CMAKE_BUILD_TYPE:STRING="))) {
cmakeBuildTypeInOptions = true;
}
}
@@ -137,17 +133,18 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
"Configure command is not specified. If this is a "
"\"built with CMake\" project, set CTEST_CMAKE_GENERATOR. If not, "
"set CTEST_CONFIGURE_COMMAND.");
- return CM_NULLPTR;
+ return nullptr;
}
}
- cmCTestGenericHandler* handler =
- this->CTest->GetInitializedHandler("configure");
- if (!handler) {
- this->SetError(
- "internal CTest error. Cannot instantiate configure handler");
- return CM_NULLPTR;
+ if (const char* labelsForSubprojects =
+ this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) {
+ this->CTest->SetCTestConfiguration("LabelsForSubprojects",
+ labelsForSubprojects, this->Quiet);
}
+
+ cmCTestConfigureHandler* handler = this->CTest->GetConfigureHandler();
+ handler->Initialize();
handler->SetQuiet(this->Quiet);
return handler;
}
diff --git a/Source/CTest/cmCTestConfigureCommand.h b/Source/CTest/cmCTestConfigureCommand.h
index 917f5ab8b..3f5944af6 100644
--- a/Source/CTest/cmCTestConfigureCommand.h
+++ b/Source/CTest/cmCTestConfigureCommand.h
@@ -3,14 +3,17 @@
#ifndef cmCTestConfigureCommand_h
#define cmCTestConfigureCommand_h
-#include "cmConfigure.h"
-
-#include "cmCTestHandlerCommand.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
+#include <utility>
+
+#include <cm/memory>
+
+#include "cmCTestHandlerCommand.h"
+#include "cmCommand.h"
class cmCTestGenericHandler;
-class cmCommand;
/** \class cmCTestConfigure
* \brief Run a ctest script
@@ -20,33 +23,27 @@ class cmCommand;
class cmCTestConfigureCommand : public cmCTestHandlerCommand
{
public:
- cmCTestConfigureCommand();
-
/**
* This is a virtual constructor for the command.
*/
- cmCommand* Clone() CM_OVERRIDE
+ std::unique_ptr<cmCommand> Clone() override
{
- cmCTestConfigureCommand* ni = new cmCTestConfigureCommand;
+ auto ni = cm::make_unique<cmCTestConfigureCommand>();
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
- return ni;
+ return std::unique_ptr<cmCommand>(std::move(ni));
}
/**
* The name of the command as specified in CMakeList.txt.
*/
- std::string GetName() const CM_OVERRIDE { return "ctest_configure"; }
+ std::string GetName() const override { return "ctest_configure"; }
protected:
- cmCTestGenericHandler* InitializeHandler() CM_OVERRIDE;
+ void BindArguments() override;
+ cmCTestGenericHandler* InitializeHandler() override;
- enum
- {
- ctc_FIRST = ct_LAST,
- ctc_OPTIONS,
- ctc_LAST
- };
+ std::string Options;
};
#endif
diff --git a/Source/CTest/cmCTestConfigureHandler.cxx b/Source/CTest/cmCTestConfigureHandler.cxx
index 5d87f3fb4..914930e00 100644
--- a/Source/CTest/cmCTestConfigureHandler.cxx
+++ b/Source/CTest/cmCTestConfigureHandler.cxx
@@ -2,17 +2,16 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestConfigureHandler.h"
+#include <chrono>
+#include <ostream>
+#include <string>
+
#include "cmCTest.h"
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
-#include "cmSystemTools.h"
#include "cmXMLWriter.h"
-#include <ostream>
-#include <string>
-
-cmCTestConfigureHandler::cmCTestConfigureHandler()
-{
-}
+cmCTestConfigureHandler::cmCTestConfigureHandler() = default;
void cmCTestConfigureHandler::Initialize()
{
@@ -43,28 +42,28 @@ 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;
if (!this->CTest->GetShowOnly()) {
cmGeneratedFileStream os;
if (!this->StartResultingXML(cmCTest::PartConfigure, "Configure", os)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open configure file"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot open configure file" << std::endl);
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);
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Configure with command: " << cCommand << std::endl,
this->Quiet);
- res = this->CTest->RunMakeCommand(cCommand.c_str(), output, &retVal,
- buildDirectory.c_str(), 0, ofs);
+ res = this->CTest->RunMakeCommand(cCommand, output, &retVal,
+ buildDirectory.c_str(),
+ cmDuration::zero(), ofs);
if (ofs) {
ofs.close();
@@ -73,6 +72,7 @@ int cmCTestConfigureHandler::ProcessHandler()
if (os) {
cmXMLWriter xml(os);
this->CTest->StartXML(xml, this->AppendXML);
+ this->CTest->GenerateSubprojectsOutput(xml);
xml.StartElement("Configure");
xml.Element("StartDateTime", start_time);
xml.Element("StartConfigureTime", start_time_time);
@@ -81,12 +81,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/cmCTestConfigureHandler.h b/Source/CTest/cmCTestConfigureHandler.h
index 2b452829c..01fe8011e 100644
--- a/Source/CTest/cmCTestConfigureHandler.h
+++ b/Source/CTest/cmCTestConfigureHandler.h
@@ -3,7 +3,7 @@
#ifndef cmCTestConfigureHandler_h
#define cmCTestConfigureHandler_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include "cmCTestGenericHandler.h"
@@ -14,16 +14,16 @@
class cmCTestConfigureHandler : public cmCTestGenericHandler
{
public:
- typedef cmCTestGenericHandler Superclass;
+ using Superclass = cmCTestGenericHandler;
/*
* The main entry point for this class
*/
- int ProcessHandler() CM_OVERRIDE;
+ int ProcessHandler() override;
cmCTestConfigureHandler();
- void Initialize() CM_OVERRIDE;
+ void Initialize() override;
};
#endif
diff --git a/Source/CTest/cmCTestCoverageCommand.cxx b/Source/CTest/cmCTestCoverageCommand.cxx
index 535da586d..d6e6be395 100644
--- a/Source/CTest/cmCTestCoverageCommand.cxx
+++ b/Source/CTest/cmCTestCoverageCommand.cxx
@@ -2,14 +2,27 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestCoverageCommand.h"
+#include <set>
+
+#include "cm_static_string_view.hxx"
+
+#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestCoverageHandler.h"
class cmCTestGenericHandler;
-cmCTestCoverageCommand::cmCTestCoverageCommand()
+void cmCTestCoverageCommand::BindArguments()
+{
+ this->cmCTestHandlerCommand::BindArguments();
+ this->Bind("LABELS"_s, this->Labels);
+}
+
+void cmCTestCoverageCommand::CheckArguments(
+ std::vector<std::string> const& keywords)
{
- this->LabelsMentioned = false;
+ this->LabelsMentioned =
+ !this->Labels.empty() || cmContains(keywords, "LABELS");
}
cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
@@ -19,43 +32,15 @@ cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
this->CTest->SetCTestConfigurationFromCMakeVariable(
this->Makefile, "CoverageExtraFlags", "CTEST_COVERAGE_EXTRA_FLAGS",
this->Quiet);
- cmCTestCoverageHandler* handler = static_cast<cmCTestCoverageHandler*>(
- this->CTest->GetInitializedHandler("coverage"));
- if (!handler) {
- this->SetError("internal CTest error. Cannot instantiate test handler");
- return CM_NULLPTR;
- }
+ cmCTestCoverageHandler* handler = this->CTest->GetCoverageHandler();
+ handler->Initialize();
// If a LABELS option was given, select only files with the labels.
if (this->LabelsMentioned) {
- handler->SetLabelFilter(this->Labels);
+ handler->SetLabelFilter(
+ std::set<std::string>(this->Labels.begin(), this->Labels.end()));
}
handler->SetQuiet(this->Quiet);
return handler;
}
-
-bool cmCTestCoverageCommand::CheckArgumentKeyword(std::string const& arg)
-{
- // Look for arguments specific to this command.
- if (arg == "LABELS") {
- this->ArgumentDoing = ArgumentDoingLabels;
- this->LabelsMentioned = true;
- return true;
- }
-
- // Look for other arguments.
- return this->Superclass::CheckArgumentKeyword(arg);
-}
-
-bool cmCTestCoverageCommand::CheckArgumentValue(std::string const& arg)
-{
- // Handle states specific to this command.
- if (this->ArgumentDoing == ArgumentDoingLabels) {
- this->Labels.insert(arg);
- return true;
- }
-
- // Look for other arguments.
- return this->Superclass::CheckArgumentValue(arg);
-}
diff --git a/Source/CTest/cmCTestCoverageCommand.h b/Source/CTest/cmCTestCoverageCommand.h
index 78c4f61f6..76aaf46f8 100644
--- a/Source/CTest/cmCTestCoverageCommand.h
+++ b/Source/CTest/cmCTestCoverageCommand.h
@@ -3,15 +3,18 @@
#ifndef cmCTestCoverageCommand_h
#define cmCTestCoverageCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmCTestHandlerCommand.h"
-
-#include <set>
#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm/memory>
+
+#include "cmCTestHandlerCommand.h"
+#include "cmCommand.h"
class cmCTestGenericHandler;
-class cmCommand;
/** \class cmCTestCoverage
* \brief Run a ctest script
@@ -21,40 +24,29 @@ class cmCommand;
class cmCTestCoverageCommand : public cmCTestHandlerCommand
{
public:
- cmCTestCoverageCommand();
-
/**
* This is a virtual constructor for the command.
*/
- cmCommand* Clone() CM_OVERRIDE
+ std::unique_ptr<cmCommand> Clone() override
{
- cmCTestCoverageCommand* ni = new cmCTestCoverageCommand;
+ auto ni = cm::make_unique<cmCTestCoverageCommand>();
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
- return ni;
+ return std::unique_ptr<cmCommand>(std::move(ni));
}
/**
* The name of the command as specified in CMakeList.txt.
*/
- std::string GetName() const CM_OVERRIDE { return "ctest_coverage"; }
-
- typedef cmCTestHandlerCommand Superclass;
+ std::string GetName() const override { return "ctest_coverage"; }
protected:
- cmCTestGenericHandler* InitializeHandler() CM_OVERRIDE;
-
- bool CheckArgumentKeyword(std::string const& arg) CM_OVERRIDE;
- bool CheckArgumentValue(std::string const& arg) CM_OVERRIDE;
-
- enum
- {
- ArgumentDoingLabels = Superclass::ArgumentDoingLast1,
- ArgumentDoingLast2
- };
+ void BindArguments() override;
+ void CheckArguments(std::vector<std::string> const& keywords) override;
+ cmCTestGenericHandler* InitializeHandler() override;
bool LabelsMentioned;
- std::set<std::string> Labels;
+ std::vector<std::string> Labels;
};
#endif
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 28fae1c7e..4cd783fd6 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -2,7 +2,24 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestCoverageHandler.h"
+#include <algorithm>
+#include <chrono>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iomanip>
+#include <iterator>
+#include <sstream>
+#include <utility>
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/Process.h"
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmAlgorithms.h"
#include "cmCTest.h"
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
#include "cmParseBlanketJSCoverage.h"
#include "cmParseCacheCoverage.h"
@@ -11,22 +28,10 @@
#include "cmParseGTMCoverage.h"
#include "cmParseJacocoCoverage.h"
#include "cmParsePHPCoverage.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
#include "cmXMLWriter.h"
-#include "cmake.h"
-
-#include "cmsys/FStream.hxx"
-#include "cmsys/Glob.hxx"
-#include "cmsys/Process.h"
-#include "cmsys/RegularExpression.hxx"
-#include <algorithm>
-#include <iomanip>
-#include <iterator>
-#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
-#include <utility>
class cmMakefile;
@@ -39,7 +44,7 @@ public:
{
this->Process = cmsysProcess_New();
this->PipeState = -1;
- this->TimeOut = -1;
+ this->TimeOut = cmDuration(-1);
}
~cmCTestRunProcess()
{
@@ -50,38 +55,37 @@ public:
}
cmsysProcess_Delete(this->Process);
}
+ cmCTestRunProcess(const cmCTestRunProcess&) = delete;
+ cmCTestRunProcess& operator=(const cmCTestRunProcess&) = delete;
void SetCommand(const char* command)
{
this->CommandLineStrings.clear();
- this->CommandLineStrings.push_back(command);
- ;
+ this->CommandLineStrings.emplace_back(command);
}
void AddArgument(const char* arg)
{
if (arg) {
- this->CommandLineStrings.push_back(arg);
+ this->CommandLineStrings.emplace_back(arg);
}
}
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;
- for (std::vector<std::string>::iterator i =
- this->CommandLineStrings.begin();
- i != this->CommandLineStrings.end(); ++i) {
- args.push_back(i->c_str());
+ for (std::string const& cl : this->CommandLineStrings) {
+ args.push_back(cl.c_str());
}
- args.push_back(CM_NULLPTR); // null terminate
- cmsysProcess_SetCommand(this->Process, &*args.begin());
+ args.push_back(nullptr); // null terminate
+ cmsysProcess_SetCommand(this->Process, args.data());
if (!this->WorkingDirectory.empty()) {
cmsysProcess_SetWorkingDirectory(this->Process,
this->WorkingDirectory.c_str());
}
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);
@@ -97,7 +101,7 @@ public:
{
cmsysProcess_SetPipeFile(this->Process, cmsysProcess_Pipe_STDERR, fname);
}
- int WaitForExit(double* timeout = CM_NULLPTR)
+ int WaitForExit(double* timeout = nullptr)
{
this->PipeState = cmsysProcess_WaitForExit(this->Process, timeout);
return this->PipeState;
@@ -109,12 +113,10 @@ private:
cmsysProcess* Process;
std::vector<std::string> CommandLineStrings;
std::string WorkingDirectory;
- double TimeOut;
+ cmDuration TimeOut;
};
-cmCTestCoverageHandler::cmCTestCoverageHandler()
-{
-}
+cmCTestCoverageHandler::cmCTestCoverageHandler() = default;
void cmCTestCoverageHandler::Initialize()
{
@@ -129,17 +131,15 @@ void cmCTestCoverageHandler::Initialize()
void cmCTestCoverageHandler::CleanCoverageLogFiles(std::ostream& log)
{
- std::string logGlob = this->CTest->GetCTestConfiguration("BuildDirectory");
- logGlob += "/Testing/";
- logGlob += this->CTest->GetCurrentTag();
- logGlob += "/CoverageLog*";
+ std::string logGlob =
+ cmStrCat(this->CTest->GetCTestConfiguration("BuildDirectory"), "/Testing/",
+ this->CTest->GetCurrentTag(), "/CoverageLog*");
cmsys::Glob gl;
gl.FindFiles(logGlob);
std::vector<std::string> const& files = gl.GetFiles();
- for (std::vector<std::string>::const_iterator fi = files.begin();
- fi != files.end(); ++fi) {
- log << "Removing old coverage log: " << *fi << "\n";
- cmSystemTools::RemoveFile(*fi);
+ for (std::string const& f : files) {
+ log << "Removing old coverage log: " << f << "\n";
+ cmSystemTools::RemoveFile(f);
}
}
@@ -176,34 +176,31 @@ 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);
}
-bool cmCTestCoverageHandler::ShouldIDoCoverage(const char* file,
- const char* srcDir,
- const char* binDir)
+bool cmCTestCoverageHandler::ShouldIDoCoverage(std::string const& file,
+ std::string const& srcDir,
+ std::string const& binDir)
{
if (this->IsFilteredOut(file)) {
return false;
}
- std::vector<cmsys::RegularExpression>::iterator sit;
- for (sit = this->CustomCoverageExcludeRegex.begin();
- sit != this->CustomCoverageExcludeRegex.end(); ++sit) {
- if (sit->find(file)) {
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " File "
- << file << " is excluded in CTestCustom.ctest"
- << std::endl;
- , this->Quiet);
+ for (cmsys::RegularExpression& rx : this->CustomCoverageExcludeRegex) {
+ if (rx.find(file)) {
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_VERBOSE_OUTPUT,
+ " File " << file << " is excluded in CTestCustom.ctest" << std::endl;
+ , this->Quiet);
return false;
}
}
@@ -230,7 +227,7 @@ bool cmCTestCoverageHandler::ShouldIDoCoverage(const char* file,
checkDir = fBinDir;
}
std::string ndc = cmSystemTools::FileExistsInParentDirectories(
- ".NoDartCoverage", fFile.c_str(), checkDir.c_str());
+ ".NoDartCoverage", fFile, checkDir);
if (!ndc.empty()) {
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Found: " << ndc << " so skip coverage of " << file
@@ -244,7 +241,7 @@ bool cmCTestCoverageHandler::ShouldIDoCoverage(const char* 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;
}
@@ -261,8 +258,8 @@ bool cmCTestCoverageHandler::ShouldIDoCoverage(const char* file,
return true;
}
- ndc = cmSystemTools::FileExistsInParentDirectories(
- ".NoDartCoverage", fFile.c_str(), checkDir.c_str());
+ ndc = cmSystemTools::FileExistsInParentDirectories(".NoDartCoverage", fFile,
+ checkDir);
if (!ndc.empty()) {
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Found: " << ndc << " so skip coverage of: " << file
@@ -281,13 +278,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");
@@ -295,13 +291,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);
@@ -319,11 +316,8 @@ int cmCTestCoverageHandler::ProcessHandler()
// setup the regex exclude stuff
this->CustomCoverageExcludeRegex.clear();
- std::vector<std::string>::iterator rexIt;
- for (rexIt = this->CustomCoverageExclude.begin();
- rexIt != this->CustomCoverageExclude.end(); ++rexIt) {
- this->CustomCoverageExcludeRegex.push_back(
- cmsys::RegularExpression(rexIt->c_str()));
+ for (std::string const& rex : this->CustomCoverageExclude) {
+ this->CustomCoverageExcludeRegex.emplace_back(rex);
}
if (this->HandleBullseyeCoverage(&cont)) {
@@ -396,8 +390,8 @@ int cmCTestCoverageHandler::ProcessHandler()
if (!this->StartResultingXML(cmCTest::PartCoverage, "Coverage",
covSumFile)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open coverage summary file."
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot open coverage summary file." << std::endl);
return -1;
}
covSumFile.setf(std::ios::fixed, std::ios::floatfield);
@@ -414,7 +408,6 @@ int cmCTestCoverageHandler::ProcessHandler()
return -1;
}
this->StartCoverageLogXML(covLogXML);
- cmCTestCoverageHandlerContainer::TotalCoverageMap::iterator fileIterator;
int cnt = 0;
long total_tested = 0;
long total_untested = 0;
@@ -430,22 +423,22 @@ int cmCTestCoverageHandler::ProcessHandler()
std::vector<std::string> errorsWhileAccumulating;
file_count = 0;
- for (fileIterator = cont.TotalCoverage.begin();
- fileIterator != cont.TotalCoverage.end(); ++fileIterator) {
+ for (auto const& file : cont.TotalCoverage) {
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "." << std::flush,
this->Quiet);
file_count++;
if (file_count % 50 == 0) {
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " processed: "
- << file_count << " out of "
- << cont.TotalCoverage.size() << std::endl,
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " processed: " << file_count << " out of "
+ << cont.TotalCoverage.size()
+ << std::endl,
this->Quiet);
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " ", this->Quiet);
}
- const std::string fullFileName = fileIterator->first;
- bool shouldIDoCoverage = this->ShouldIDoCoverage(
- fullFileName.c_str(), sourceDir.c_str(), binaryDir.c_str());
+ const std::string fullFileName = file.first;
+ bool shouldIDoCoverage =
+ this->ShouldIDoCoverage(fullFileName, sourceDir, binaryDir);
if (!shouldIDoCoverage) {
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
".NoDartCoverage found, so skip coverage check for: "
@@ -458,7 +451,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;
@@ -478,7 +471,7 @@ int cmCTestCoverageHandler::ProcessHandler()
std::string shortFileName =
this->CTest->GetShortPathToFile(fullFileName.c_str());
const cmCTestCoverageHandlerContainer::SingleFileCoverageVector& fcov =
- fileIterator->second;
+ file.second;
covLogXML.StartElement("File");
covLogXML.Attribute("Name", fileName);
covLogXML.Attribute("FullPath", shortFileName);
@@ -531,8 +524,9 @@ int cmCTestCoverageHandler::ProcessHandler()
float cper = 0;
float cmet = 0;
if (tested + untested > 0) {
- cper = (100 * SAFEDIV(static_cast<float>(tested),
- static_cast<float>(tested + untested)));
+ cper = (100 *
+ SAFEDIV(static_cast<float>(tested),
+ static_cast<float>(tested + untested)));
cmet = (SAFEDIV(static_cast<float>(tested + 10),
static_cast<float>(tested + untested + 10)));
}
@@ -554,14 +548,13 @@ int cmCTestCoverageHandler::ProcessHandler()
}
// Handle all the files in the extra coverage globs that have no cov data
- for (std::set<std::string>::iterator i = uncovered.begin();
- i != uncovered.end(); ++i) {
- std::string fileName = cmSystemTools::GetFilenameName(*i);
- std::string fullPath = cont.SourceDir + "/" + *i;
+ for (std::string const& u : uncovered) {
+ std::string fileName = cmSystemTools::GetFilenameName(u);
+ std::string fullPath = cont.SourceDir + "/" + u;
covLogXML.StartElement("File");
covLogXML.Attribute("Name", fileName);
- covLogXML.Attribute("FullPath", *i);
+ covLogXML.Attribute("FullPath", u);
covLogXML.StartElement("Report");
cmsys::ifstream ifs(fullPath.c_str());
@@ -577,7 +570,7 @@ int cmCTestCoverageHandler::ProcessHandler()
int untested = 0;
std::string line;
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Actually performing coverage for: " << *i << std::endl,
+ "Actually performing coverage for: " << u << std::endl,
this->Quiet);
while (cmSystemTools::GetLineFromStream(ifs, line)) {
covLogXML.StartElement("Line");
@@ -593,13 +586,13 @@ int cmCTestCoverageHandler::ProcessHandler()
total_untested += untested;
covSumXML.StartElement("File");
covSumXML.Attribute("Name", fileName);
- covSumXML.Attribute("FullPath", *i);
+ covSumXML.Attribute("FullPath", u);
covSumXML.Attribute("Covered", "true");
covSumXML.Element("LOCTested", 0);
covSumXML.Element("LOCUnTested", untested);
covSumXML.Element("PercentCoverage", 0);
covSumXML.Element("CoverageMetric", 0);
- this->WriteXMLLabels(covSumXML, *i);
+ this->WriteXMLLabels(covSumXML, u);
covSumXML.EndElement(); // File
}
@@ -610,10 +603,8 @@ int cmCTestCoverageHandler::ProcessHandler()
cmCTestLog(this->CTest, ERROR_MESSAGE, std::endl);
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Error(s) while accumulating results:" << std::endl);
- std::vector<std::string>::iterator erIt;
- for (erIt = errorsWhileAccumulating.begin();
- erIt != errorsWhileAccumulating.end(); ++erIt) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, " " << *erIt << std::endl);
+ for (std::string const& er : errorsWhileAccumulating) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, " " << er << std::endl);
}
}
@@ -631,23 +622,22 @@ 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);
- cmCTestLog(this->CTest, HANDLER_OUTPUT, ""
- << std::endl
- << "\tCovered LOC: " << total_tested << std::endl
- << "\tNot covered LOC: " << total_untested << std::endl
- << "\tTotal LOC: " << total_lines << std::endl
- << "\tPercentage Coverage: "
- << std::setiosflags(std::ios::fixed) << std::setprecision(2)
- << (percent_coverage) << "%" << std::endl);
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ "" << std::endl
+ << "\tCovered LOC: " << total_tested << std::endl
+ << "\tNot covered LOC: " << total_untested << std::endl
+ << "\tTotal LOC: " << total_lines << std::endl
+ << "\tPercentage Coverage: "
+ << std::setiosflags(std::ios::fixed) << std::setprecision(2)
+ << (percent_coverage) << "%" << std::endl);
ofs << "\tCovered LOC: " << total_tested << std::endl
<< "\tNot covered LOC: " << total_untested << std::endl
@@ -670,17 +660,14 @@ void cmCTestCoverageHandler::PopulateCustomVectors(cmMakefile* mf)
this->CustomCoverageExclude);
this->CTest->PopulateCustomVector(mf, "CTEST_EXTRA_COVERAGE_GLOB",
this->ExtraCoverageGlobs);
- std::vector<std::string>::iterator it;
- for (it = this->CustomCoverageExclude.begin();
- it != this->CustomCoverageExclude.end(); ++it) {
+ for (std::string const& cce : this->CustomCoverageExclude) {
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " Add coverage exclude: " << *it << std::endl,
+ " Add coverage exclude: " << cce << std::endl,
this->Quiet);
}
- for (it = this->ExtraCoverageGlobs.begin();
- it != this->ExtraCoverageGlobs.end(); ++it) {
+ for (std::string const& ecg : this->ExtraCoverageGlobs) {
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " Add coverage glob: " << *it << std::endl,
+ " Add coverage glob: " << ecg << std::endl,
this->Quiet);
}
}
@@ -691,9 +678,9 @@ void cmCTestCoverageHandler::PopulateCustomVectors(cmMakefile* mf)
// Compare file names: fnc(fn1) == fnc(fn2) // fnc == file name compare
//
#ifdef _WIN32
-#define fnc(s) cmSystemTools::LowerCase(s)
+# define fnc(s) cmSystemTools::LowerCase(s)
#else
-#define fnc(s) s
+# define fnc(s) s
#endif
bool IsFileInDir(const std::string& infile, const std::string& indir)
@@ -733,7 +720,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
@@ -756,7 +743,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);
@@ -769,7 +756,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);
@@ -803,6 +790,9 @@ struct cmCTestCoverageHandlerLocale
cmSystemTools::UnsetEnv("LC_ALL");
}
}
+ cmCTestCoverageHandlerLocale(const cmCTestCoverageHandlerLocale&) = delete;
+ cmCTestCoverageHandlerLocale& operator=(
+ const cmCTestCoverageHandlerLocale&) = delete;
std::string lc_all;
};
@@ -825,15 +815,11 @@ int cmCTestCoverageHandler::HandleJacocoCoverage(
// ...and in the binary directory.
cmsys::Glob g2;
- std::vector<std::string> binFiles;
g2.SetRecurse(true);
std::string binaryDir = this->CTest->GetCTestConfiguration("BuildDirectory");
std::string binCoverageFile = binaryDir + "/*jacoco.xml";
g2.FindFiles(binCoverageFile);
- binFiles = g2.GetFiles();
- if (!binFiles.empty()) {
- files.insert(files.end(), binFiles.begin(), binFiles.end());
- }
+ cmAppend(files, g2.GetFiles());
if (!files.empty()) {
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
@@ -877,6 +863,24 @@ int cmCTestCoverageHandler::HandleDelphiCoverage(
return static_cast<int>(cont->TotalCoverage.size());
}
+static std::string joinCommandLine(const std::vector<std::string>& args)
+{
+ std::string ret;
+
+ for (std::string const& s : args) {
+ if (s.find(' ') == std::string::npos) {
+ ret += s + ' ';
+ } else {
+ ret += "\"" + s + "\" ";
+ }
+ }
+
+ // drop trailing whitespace
+ ret.erase(ret.size() - 1);
+
+ return ret;
+}
+
int cmCTestCoverageHandler::HandleBlanketJSCoverage(
cmCTestCoverageHandlerContainer* cont)
{
@@ -895,12 +899,12 @@ int cmCTestCoverageHandler::HandleBlanketJSCoverage(
// Blanket.js output. Check for the "node-jscoverage"
// string on the second line
std::string line;
- for (unsigned int fileEntry = 0; fileEntry < files.size(); fileEntry++) {
- cmsys::ifstream in(files[fileEntry].c_str());
+ for (std::string const& fileEntry : files) {
+ cmsys::ifstream in(fileEntry.c_str());
cmSystemTools::GetLineFromStream(in, line);
cmSystemTools::GetLineFromStream(in, line);
if (line.find("node-jscoverage") != std::string::npos) {
- blanketFiles.push_back(files[fileEntry]);
+ blanketFiles.push_back(fileEntry);
}
}
// Take all files with the node-jscoverage string and parse those
@@ -924,7 +928,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
std::string gcovCommand =
this->CTest->GetCTestConfiguration("CoverageCommand");
if (gcovCommand.empty()) {
- cmCTestLog(this->CTest, WARNING, "Could not find gcov." << std::endl);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Could not find gcov." << std::endl, this->Quiet);
return 0;
}
std::string gcovExtraFlags =
@@ -961,7 +966,6 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
std::vector<std::string> files;
this->FindGCovFiles(files);
- std::vector<std::string>::iterator it;
if (files.empty()) {
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
@@ -973,7 +977,12 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
std::string testingDir = this->CTest->GetBinaryDir() + "/Testing";
std::string tempDir = testingDir + "/CoverageInfo";
- cmSystemTools::MakeDirectory(tempDir.c_str());
+ if (!cmSystemTools::MakeDirectory(tempDir)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unable to make directory: " << tempDir << std::endl);
+ cont->Error++;
+ return 0;
+ }
cmWorkingDirectory workdir(tempDir);
int gcovStyle = 0;
@@ -992,19 +1001,26 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
cmCTestCoverageHandlerLocale locale_C;
static_cast<void>(locale_C);
+ std::vector<std::string> basecovargs =
+ cmSystemTools::ParseArguments(gcovExtraFlags);
+ basecovargs.insert(basecovargs.begin(), gcovCommand);
+ basecovargs.emplace_back("-o");
+
// files is a list of *.da and *.gcda files with coverage data in them.
// These are binary files that you give as input to gcov so that it will
// give us text output we can analyze to summarize coverage.
//
- for (it = files.begin(); it != files.end(); ++it) {
+ for (std::string const& f : files) {
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "." << std::flush,
this->Quiet);
// Call gcov to get coverage data for this *.gcda file:
//
- std::string fileDir = cmSystemTools::GetFilenamePath(*it);
- std::string command = "\"" + gcovCommand + "\" " + gcovExtraFlags + " " +
- "-o \"" + fileDir + "\" " + "\"" + *it + "\"";
+ std::string fileDir = cmSystemTools::GetFilenamePath(f);
+ std::vector<std::string> covargs = basecovargs;
+ covargs.push_back(fileDir);
+ covargs.push_back(f);
+ const std::string command = joinCommandLine(covargs);
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
command << std::endl, this->Quiet);
@@ -1014,23 +1030,24 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
int retVal = 0;
*cont->OFS << "* Run coverage for: " << fileDir << std::endl;
*cont->OFS << " Command: " << command << std::endl;
- int res =
- this->CTest->RunCommand(command.c_str(), &output, &errors, &retVal,
- tempDir.c_str(), 0 /*this->TimeOut*/);
+ int res = this->CTest->RunCommand(covargs, &output, &errors, &retVal,
+ tempDir.c_str(),
+ cmDuration::zero() /*this->TimeOut*/);
*cont->OFS << " Output: " << output << std::endl;
*cont->OFS << " Errors: " << errors << std::endl;
if (!res) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Problem running coverage on file: " << *it << std::endl);
+ "Problem running coverage on file: " << f << std::endl);
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Command produced error: " << errors << std::endl);
cont->Error++;
continue;
}
if (retVal != 0) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Coverage command returned: "
- << retVal << " while processing: " << *it << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Coverage command returned: "
+ << retVal << " while processing: " << f << std::endl);
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Command produced error: " << cont->Error << std::endl);
}
@@ -1044,86 +1061,84 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
this->Quiet);
std::vector<std::string> lines;
- std::vector<std::string>::iterator line;
+ cmsys::SystemTools::Split(output, lines);
- cmSystemTools::Split(output.c_str(), lines);
-
- for (line = lines.begin(); line != lines.end(); ++line) {
+ for (std::string const& line : lines) {
std::string sourceFile;
std::string gcovFile;
cmCTestOptionalLog(this->CTest, DEBUG,
- "Line: [" << *line << "]" << std::endl, this->Quiet);
+ "Line: [" << line << "]" << std::endl, this->Quiet);
- if (line->empty()) {
+ if (line.empty()) {
// Ignore empty line; probably style 2
- } else if (st1re1.find(line->c_str())) {
+ } else if (st1re1.find(line)) {
if (gcovStyle == 0) {
gcovStyle = 1;
}
if (gcovStyle != 1) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e1"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output style e1" << std::endl);
cont->Error++;
break;
}
- actualSourceFile = "";
+ actualSourceFile.clear();
sourceFile = st1re1.match(2);
- } else if (st1re2.find(line->c_str())) {
+ } else if (st1re2.find(line)) {
if (gcovStyle == 0) {
gcovStyle = 1;
}
if (gcovStyle != 1) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e2"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output style e2" << std::endl);
cont->Error++;
break;
}
gcovFile = st1re2.match(1);
- } else if (st2re1.find(line->c_str())) {
+ } else if (st2re1.find(line)) {
if (gcovStyle == 0) {
gcovStyle = 2;
}
if (gcovStyle != 2) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e3"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output style e3" << std::endl);
cont->Error++;
break;
}
- actualSourceFile = "";
+ actualSourceFile.clear();
sourceFile = st2re1.match(1);
- } else if (st2re2.find(line->c_str())) {
+ } else if (st2re2.find(line)) {
if (gcovStyle == 0) {
gcovStyle = 2;
}
if (gcovStyle != 2) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e4"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output style e4" << std::endl);
cont->Error++;
break;
}
- } else if (st2re3.find(line->c_str())) {
+ } else if (st2re3.find(line)) {
if (gcovStyle == 0) {
gcovStyle = 2;
}
if (gcovStyle != 2) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e5"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output style e5" << std::endl);
cont->Error++;
break;
}
gcovFile = st2re3.match(2);
- } else if (st2re4.find(line->c_str())) {
+ } else if (st2re4.find(line)) {
if (gcovStyle == 0) {
gcovStyle = 2;
}
if (gcovStyle != 2) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e6"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output style e6" << std::endl);
cont->Error++;
break;
}
@@ -1132,42 +1147,45 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
"Warning: " << st2re4.match(1)
<< " had unexpected EOF" << std::endl,
this->Quiet);
- } else if (st2re5.find(line->c_str())) {
+ } else if (st2re5.find(line)) {
if (gcovStyle == 0) {
gcovStyle = 2;
}
if (gcovStyle != 2) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e7"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output style e7" << std::endl);
cont->Error++;
break;
}
- cmCTestOptionalLog(this->CTest, WARNING, "Warning: Cannot open file: "
- << st2re5.match(1) << std::endl,
+ cmCTestOptionalLog(this->CTest, WARNING,
+ "Warning: Cannot open file: " << st2re5.match(1)
+ << std::endl,
this->Quiet);
- } else if (st2re6.find(line->c_str())) {
+ } else if (st2re6.find(line)) {
if (gcovStyle == 0) {
gcovStyle = 2;
}
if (gcovStyle != 2) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output style e8"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output style e8" << std::endl);
cont->Error++;
break;
}
- cmCTestOptionalLog(this->CTest, WARNING, "Warning: File: "
- << st2re6.match(1) << " is newer than "
- << st2re6.match(2) << std::endl,
+ cmCTestOptionalLog(this->CTest, WARNING,
+ "Warning: File: " << st2re6.match(1)
+ << " is newer than "
+ << st2re6.match(2) << std::endl,
this->Quiet);
} else {
// gcov 4.7 can have output lines saying "No executable lines" and
// "Removing 'filename.gcov'"... Don't log those as "errors."
- if (*line != "No executable lines" &&
- !cmSystemTools::StringStartsWith(line->c_str(), "Removing ")) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output line: ["
- << *line << "]" << std::endl);
+ if (line != "No executable lines" &&
+ !cmHasLiteralPrefix(line, "Removing ")) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output line: [" << line << "]"
+ << std::endl);
cont->Error++;
// abort();
}
@@ -1235,11 +1253,11 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
}
}
- actualSourceFile = "";
+ actualSourceFile.clear();
}
if (!sourceFile.empty() && actualSourceFile.empty()) {
- gcovFile = "";
+ gcovFile.clear();
// Is it in the source dir or the binary dir?
//
@@ -1332,7 +1350,6 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
"Error while finding LCov files.\n");
return 0;
}
- std::vector<std::string>::iterator it;
if (files.empty()) {
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
@@ -1357,14 +1374,26 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
cmCTestCoverageHandlerLocale locale_C;
static_cast<void>(locale_C);
+ std::vector<std::string> covargs =
+ cmSystemTools::ParseArguments(lcovExtraFlags);
+ covargs.insert(covargs.begin(), lcovCommand);
+ const std::string command = joinCommandLine(covargs);
+
// In intel compiler we have to call codecov only once in each executable
// directory. It collects all *.dyn files to generate .dpi file.
- for (it = files.begin(); it != files.end(); ++it) {
+ for (std::string const& f : files) {
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "." << std::flush,
this->Quiet);
- std::string fileDir = cmSystemTools::GetFilenamePath(*it);
+ std::string fileDir = cmSystemTools::GetFilenamePath(f);
cmWorkingDirectory workdir(fileDir);
- std::string command = "\"" + lcovCommand + "\" " + lcovExtraFlags + " ";
+ if (workdir.Failed()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unable to change working directory to "
+ << fileDir << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ cont->Error++;
+ continue;
+ }
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Current coverage dir: " << fileDir << std::endl,
@@ -1377,23 +1406,24 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
int retVal = 0;
*cont->OFS << "* Run coverage for: " << fileDir << std::endl;
*cont->OFS << " Command: " << command << std::endl;
- int res =
- this->CTest->RunCommand(command.c_str(), &output, &errors, &retVal,
- fileDir.c_str(), 0 /*this->TimeOut*/);
+ int res = this->CTest->RunCommand(covargs, &output, &errors, &retVal,
+ fileDir.c_str(),
+ cmDuration::zero() /*this->TimeOut*/);
*cont->OFS << " Output: " << output << std::endl;
*cont->OFS << " Errors: " << errors << std::endl;
if (!res) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Problem running coverage on file: " << *it << std::endl);
+ "Problem running coverage on file: " << f << std::endl);
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Command produced error: " << errors << std::endl);
cont->Error++;
continue;
}
if (retVal != 0) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Coverage command returned: "
- << retVal << " while processing: " << *it << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Coverage command returned: "
+ << retVal << " while processing: " << f << std::endl);
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Command produced error: " << cont->Error << std::endl);
}
@@ -1407,15 +1437,13 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
this->Quiet);
std::vector<std::string> lines;
- std::vector<std::string>::iterator line;
-
- cmSystemTools::Split(output.c_str(), lines);
+ cmsys::SystemTools::Split(output, lines);
- for (line = lines.begin(); line != lines.end(); ++line) {
+ for (std::string const& line : lines) {
std::string sourceFile;
std::string lcovFile;
- if (line->empty()) {
+ if (line.empty()) {
// Ignore empty line
}
// Look for LCOV files in binary directory
@@ -1428,19 +1456,16 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
std::vector<std::string> lcovFiles;
dir = this->CTest->GetBinaryDir();
std::string daGlob;
- daGlob = dir;
- daGlob += "/*.LCOV";
+ daGlob = cmStrCat(dir, "/*.LCOV");
cmCTestOptionalLog(
this->CTest, HANDLER_VERBOSE_OUTPUT,
" looking for LCOV files in: " << daGlob << std::endl, this->Quiet);
gl.FindFiles(daGlob);
// Keep a list of all LCOV files
- lcovFiles.insert(lcovFiles.end(), gl.GetFiles().begin(),
- gl.GetFiles().end());
+ cmAppend(lcovFiles, gl.GetFiles());
- for (std::vector<std::string>::iterator a = lcovFiles.begin();
- a != lcovFiles.end(); ++a) {
- lcovFile = *a;
+ for (std::string const& file : lcovFiles) {
+ lcovFile = file;
cmsys::ifstream srcead(lcovFile.c_str());
if (!srcead) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
@@ -1462,10 +1487,9 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
sourceFile = srcname;
actualSourceFile = srcname;
- for (std::vector<std::string>::iterator t = lcovFiles.begin();
- t != lcovFiles.end(); ++t) {
+ for (std::string const& t : lcovFiles) {
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Found LCOV File: " << *t << std::endl,
+ "Found LCOV File: " << t << std::endl,
this->Quiet);
}
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
@@ -1537,7 +1561,7 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
}
}
- actualSourceFile = "";
+ actualSourceFile.clear();
}
}
}
@@ -1562,10 +1586,9 @@ void cmCTestCoverageHandler::FindGCovFiles(std::vector<std::string>& files)
gl.RecurseOn();
gl.RecurseThroughSymlinksOff();
- for (LabelMapType::const_iterator lmi = this->TargetDirs.begin();
- lmi != this->TargetDirs.end(); ++lmi) {
+ for (auto const& lm : this->TargetDirs) {
// Skip targets containing no interesting labels.
- if (!this->IntersectsFilter(lmi->second)) {
+ if (!this->IntersectsFilter(lm.second)) {
continue;
}
@@ -1573,15 +1596,13 @@ void cmCTestCoverageHandler::FindGCovFiles(std::vector<std::string>& files)
// support directory.
cmCTestOptionalLog(
this->CTest, HANDLER_VERBOSE_OUTPUT,
- " globbing for coverage in: " << lmi->first << std::endl, this->Quiet);
- std::string daGlob = lmi->first;
- daGlob += "/*.da";
+ " globbing for coverage in: " << lm.first << std::endl, this->Quiet);
+ std::string daGlob = cmStrCat(lm.first, "/*.da");
gl.FindFiles(daGlob);
- files.insert(files.end(), gl.GetFiles().begin(), gl.GetFiles().end());
- daGlob = lmi->first;
- daGlob += "/*.gcda";
+ cmAppend(files, gl.GetFiles());
+ daGlob = cmStrCat(lm.first, "/*.gcda");
gl.FindFiles(daGlob);
- files.insert(files.end(), gl.GetFiles().begin(), gl.GetFiles().end());
+ cmAppend(files, gl.GetFiles());
}
}
@@ -1593,6 +1614,12 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files)
gl.RecurseThroughSymlinksOff();
std::string buildDir = this->CTest->GetCTestConfiguration("BuildDirectory");
cmWorkingDirectory workdir(buildDir);
+ if (workdir.Failed()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unable to change working directory to " << buildDir
+ << std::endl);
+ return false;
+ }
// Run profmerge to merge all *.dyn files into dpi files
if (!cmSystemTools::RunSingleCommand("profmerge")) {
@@ -1602,8 +1629,7 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files)
// DPI file should appear in build directory
std::string daGlob;
- daGlob = buildDir;
- daGlob += "/*.dpi";
+ daGlob = cmStrCat(buildDir, "/*.dpi");
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
" looking for dpi files in: " << daGlob << std::endl,
this->Quiet);
@@ -1612,7 +1638,7 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files)
"Error while finding files matching " << daGlob << std::endl);
return false;
}
- files.insert(files.end(), gl.GetFiles().begin(), gl.GetFiles().end());
+ cmAppend(files, gl.GetFiles());
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Now searching in: " << daGlob << std::endl, this->Quiet);
return true;
@@ -1639,16 +1665,15 @@ int cmCTestCoverageHandler::HandleTracePyCoverage(
std::string testingDir = this->CTest->GetBinaryDir() + "/Testing";
std::string tempDir = testingDir + "/CoverageInfo";
- cmSystemTools::MakeDirectory(tempDir.c_str());
+ cmSystemTools::MakeDirectory(tempDir);
- std::vector<std::string>::iterator fileIt;
int file_count = 0;
- for (fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
- std::string fileName = this->FindFile(cont, *fileIt);
+ for (std::string const& file : files) {
+ std::string fileName = this->FindFile(cont, file);
if (fileName.empty()) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Cannot find source Python file corresponding to: "
- << *fileIt << std::endl);
+ << file << std::endl);
continue;
}
@@ -1660,11 +1685,11 @@ int cmCTestCoverageHandler::HandleTracePyCoverage(
cmCTestCoverageHandlerContainer::SingleFileCoverageVector* vec =
&cont->TotalCoverage[actualSourceFile];
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " in file: " << *fileIt << std::endl, this->Quiet);
- cmsys::ifstream ifile(fileIt->c_str());
+ " in file: " << file << std::endl, this->Quiet);
+ cmsys::ifstream ifile(file.c_str());
if (!ifile) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot open file: " << *fileIt << std::endl);
+ "Cannot open file: " << file << std::endl);
} else {
long cnt = -1;
std::string nl;
@@ -1736,11 +1761,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 "";
@@ -1761,7 +1786,7 @@ const char* bullseyeHelp[] = {
" condition evaluated true or false, respectively.",
" * A k indicates a constant decision or condition.",
" * The slash / means this probe is excluded from summary results. ",
- CM_NULLPTR
+ nullptr
};
}
@@ -1789,8 +1814,9 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch(
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"run covbr: " << std::endl, this->Quiet);
- if (!this->RunBullseyeCommand(cont, "covbr", CM_NULLPTR, outputFile)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "error running covbr for."
+ if (!this->RunBullseyeCommand(cont, "covbr", nullptr, outputFile)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "error running covbr for."
<< "\n");
return -1;
}
@@ -1805,9 +1831,8 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch(
return 0;
}
std::map<std::string, std::string> fileMap;
- std::vector<std::string>::iterator fp = filesFullPath.begin();
- for (std::vector<std::string>::iterator f = files.begin(); f != files.end();
- ++f, ++fp) {
+ auto fp = filesFullPath.begin();
+ for (auto f = files.begin(); f != files.end(); ++f, ++fp) {
fileMap[*f] = *fp;
}
@@ -1845,7 +1870,7 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch(
this->StartCoverageLogXML(covLogXML);
count++; // move on one
}
- std::map<std::string, std::string>::iterator i = fileMap.find(file);
+ auto i = fileMap.find(file);
// if the file should be covered write out the header for that file
if (i != fileMap.end()) {
// we have a new file so count it in the output
@@ -1862,7 +1887,7 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch(
covLogXML.StartElement("Report");
// write the bullseye header
line = 0;
- for (int k = 0; bullseyeHelp[k] != CM_NULLPTR; ++k) {
+ for (int k = 0; bullseyeHelp[k] != nullptr; ++k) {
covLogXML.StartElement("Line");
covLogXML.Attribute("Number", line);
covLogXML.Attribute("Count", -1);
@@ -1916,10 +1941,9 @@ int cmCTestCoverageHandler::RunBullseyeCommand(
cmCTestRunProcess runCoverageSrc;
runCoverageSrc.SetCommand(program.c_str());
runCoverageSrc.AddArgument(arg);
- std::string stdoutFile = cont->BinaryDir + "/Testing/Temporary/";
- stdoutFile += this->GetCTestInstance()->GetCurrentTag();
- stdoutFile += "-";
- stdoutFile += cmd;
+ std::string stdoutFile =
+ cmStrCat(cont->BinaryDir, "/Testing/Temporary/",
+ this->GetCTestInstance()->GetCurrentTag(), '-', cmd);
std::string stderrFile = stdoutFile;
stdoutFile += ".stdout";
stderrFile += ".stderr";
@@ -1954,17 +1978,16 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary(
cmXMLWriter xml(covSumFile);
if (!this->StartResultingXML(cmCTest::PartCoverage, "Coverage",
covSumFile)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open coverage summary file."
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot open coverage summary file." << std::endl);
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:
@@ -2007,15 +2030,13 @@ 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 += "/";
- file += sourceFile;
+ file = cmStrCat(cont->BinaryDir, '/', sourceFile);
}
file = cmSystemTools::CollapseFullPath(file);
- bool shouldIDoCoverage = this->ShouldIDoCoverage(
- file.c_str(), cont->SourceDir.c_str(), cont->BinaryDir.c_str());
+ bool shouldIDoCoverage =
+ this->ShouldIDoCoverage(file, cont->SourceDir, cont->BinaryDir);
if (!shouldIDoCoverage) {
cmCTestOptionalLog(
this->CTest, HANDLER_VERBOSE_OUTPUT,
@@ -2085,11 +2106,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);
@@ -2172,7 +2193,8 @@ bool cmCTestCoverageHandler::ParseBullsEyeCovsrcLine(
}
// should be at the end now
if (pos != std::string::npos) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Error parsing input : "
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error parsing input : "
<< inputLine << " last pos not npos = " << pos << "\n");
}
return true;
@@ -2180,7 +2202,7 @@ bool cmCTestCoverageHandler::ParseBullsEyeCovsrcLine(
int cmCTestCoverageHandler::GetLabelId(std::string const& label)
{
- LabelIdMapType::iterator i = this->LabelIdMap.find(label);
+ auto i = this->LabelIdMap.find(label);
if (i == this->LabelIdMap.end()) {
int n = int(this->Labels.size());
this->Labels.push_back(label);
@@ -2192,9 +2214,8 @@ int cmCTestCoverageHandler::GetLabelId(std::string const& label)
void cmCTestCoverageHandler::LoadLabels()
{
- std::string fileList = this->CTest->GetBinaryDir();
- fileList += cmake::GetCMakeFilesDirectory();
- fileList += "/TargetDirectories.txt";
+ std::string fileList =
+ cmStrCat(this->CTest->GetBinaryDir(), "/CMakeFiles/TargetDirectories.txt");
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
" target directory list [" << fileList << "]\n",
this->Quiet);
@@ -2208,8 +2229,7 @@ void cmCTestCoverageHandler::LoadLabels()
void cmCTestCoverageHandler::LoadLabels(const char* dir)
{
LabelSet& dirLabels = this->TargetDirs[dir];
- std::string fname = dir;
- fname += "/Labels.txt";
+ std::string fname = cmStrCat(dir, "/Labels.txt");
cmsys::ifstream fin(fname.c_str());
if (!fin) {
return;
@@ -2253,12 +2273,11 @@ void cmCTestCoverageHandler::LoadLabels(const char* dir)
void cmCTestCoverageHandler::WriteXMLLabels(cmXMLWriter& xml,
std::string const& source)
{
- LabelMapType::const_iterator li = this->SourceLabels.find(source);
+ auto li = this->SourceLabels.find(source);
if (li != this->SourceLabels.end() && !li->second.empty()) {
xml.StartElement("Labels");
- for (LabelSet::const_iterator lsi = li->second.begin();
- lsi != li->second.end(); ++lsi) {
- xml.Element("Label", this->Labels[*lsi]);
+ for (auto const& ls : li->second) {
+ xml.Element("Label", this->Labels[ls]);
}
xml.EndElement(); // Labels
}
@@ -2268,9 +2287,8 @@ void cmCTestCoverageHandler::SetLabelFilter(
std::set<std::string> const& labels)
{
this->LabelFilter.clear();
- for (std::set<std::string>::const_iterator li = labels.begin();
- li != labels.end(); ++li) {
- this->LabelFilter.insert(this->GetLabelId(*li));
+ for (std::string const& l : labels) {
+ this->LabelFilter.insert(this->GetLabelId(l));
}
}
@@ -2298,7 +2316,7 @@ bool cmCTestCoverageHandler::IsFilteredOut(std::string const& source)
// The source is filtered out if it does not have any labels in
// common with the filter set.
std::string shortSrc = this->CTest->GetShortPathToFile(source.c_str());
- LabelMapType::const_iterator li = this->SourceLabels.find(shortSrc);
+ auto li = this->SourceLabels.find(shortSrc);
if (li != this->SourceLabels.end()) {
return !this->IntersectsFilter(li->second);
}
@@ -2310,29 +2328,23 @@ std::set<std::string> cmCTestCoverageHandler::FindUncoveredFiles(
{
std::set<std::string> extraMatches;
- for (std::vector<std::string>::iterator i = this->ExtraCoverageGlobs.begin();
- i != this->ExtraCoverageGlobs.end(); ++i) {
+ for (std::string const& ecg : this->ExtraCoverageGlobs) {
cmsys::Glob gl;
gl.RecurseOn();
gl.RecurseThroughSymlinksOff();
- std::string glob = cont->SourceDir + "/" + *i;
+ std::string glob = cont->SourceDir + "/" + ecg;
gl.FindFiles(glob);
std::vector<std::string> files = gl.GetFiles();
- for (std::vector<std::string>::iterator f = files.begin();
- f != files.end(); ++f) {
- if (this->ShouldIDoCoverage(f->c_str(), cont->SourceDir.c_str(),
- cont->BinaryDir.c_str())) {
- extraMatches.insert(this->CTest->GetShortPathToFile(f->c_str()));
+ for (std::string const& f : files) {
+ if (this->ShouldIDoCoverage(f, cont->SourceDir, cont->BinaryDir)) {
+ extraMatches.insert(this->CTest->GetShortPathToFile(f.c_str()));
}
}
}
if (!extraMatches.empty()) {
- for (cmCTestCoverageHandlerContainer::TotalCoverageMap::iterator i =
- cont->TotalCoverage.begin();
- i != cont->TotalCoverage.end(); ++i) {
- std::string shortPath =
- this->CTest->GetShortPathToFile(i->first.c_str());
+ for (auto const& i : cont->TotalCoverage) {
+ std::string shortPath = this->CTest->GetShortPathToFile(i.first.c_str());
extraMatches.erase(shortPath);
}
}
diff --git a/Source/CTest/cmCTestCoverageHandler.h b/Source/CTest/cmCTestCoverageHandler.h
index 933f60660..991b89d7b 100644
--- a/Source/CTest/cmCTestCoverageHandler.h
+++ b/Source/CTest/cmCTestCoverageHandler.h
@@ -3,17 +3,18 @@
#ifndef cmCTestCoverageHandler_h
#define cmCTestCoverageHandler_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmCTestGenericHandler.h"
-
-#include "cmsys/RegularExpression.hxx"
#include <iosfwd>
#include <map>
#include <set>
#include <string>
#include <vector>
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmCTestGenericHandler.h"
+
class cmGeneratedFileStream;
class cmMakefile;
class cmXMLWriter;
@@ -24,8 +25,8 @@ public:
int Error;
std::string SourceDir;
std::string BinaryDir;
- typedef std::vector<int> SingleFileCoverageVector;
- typedef std::map<std::string, SingleFileCoverageVector> TotalCoverageMap;
+ using SingleFileCoverageVector = std::vector<int>;
+ using TotalCoverageMap = std::map<std::string, SingleFileCoverageVector>;
TotalCoverageMap TotalCoverage;
std::ostream* OFS;
bool Quiet;
@@ -37,28 +38,28 @@ public:
class cmCTestCoverageHandler : public cmCTestGenericHandler
{
public:
- typedef cmCTestGenericHandler Superclass;
+ using Superclass = cmCTestGenericHandler;
/*
* The main entry point for this class
*/
- int ProcessHandler() CM_OVERRIDE;
+ int ProcessHandler() override;
cmCTestCoverageHandler();
- void Initialize() CM_OVERRIDE;
+ void Initialize() override;
/**
* This method is called when reading CTest custom file
*/
- void PopulateCustomVectors(cmMakefile* mf) CM_OVERRIDE;
+ void PopulateCustomVectors(cmMakefile* mf) override;
/** Report coverage only for sources with these labels. */
void SetLabelFilter(std::set<std::string> const& labels);
private:
- bool ShouldIDoCoverage(const char* file, const char* srcDir,
- const char* binDir);
+ bool ShouldIDoCoverage(std::string const& file, std::string const& srcDir,
+ std::string const& binDir);
void CleanCoverageLogFiles(std::ostream& log);
bool StartCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount);
void EndCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount);
@@ -128,12 +129,12 @@ private:
class LabelSet : public std::set<int>
{
};
- typedef std::map<std::string, LabelSet> LabelMapType;
+ using LabelMapType = std::map<std::string, LabelSet>;
LabelMapType SourceLabels;
LabelMapType TargetDirs;
// Map from label name to label id.
- typedef std::map<std::string, int> LabelIdMapType;
+ using LabelIdMapType = std::map<std::string, int>;
LabelIdMapType LabelIdMap;
std::vector<std::string> Labels;
int GetLabelId(std::string const& label);
diff --git a/Source/CTest/cmCTestCurl.cxx b/Source/CTest/cmCTestCurl.cxx
index b80ea5ade..ccac832f0 100644
--- a/Source/CTest/cmCTestCurl.cxx
+++ b/Source/CTest/cmCTestCurl.cxx
@@ -2,13 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestCurl.h"
+#include <cstdio>
+#include <ostream>
+
+#include "cmAlgorithms.h"
#include "cmCTest.h"
+#include "cmCurl.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmConfigure.h"
-#include <ostream>
-#include <stdio.h>
-
cmCTestCurl::cmCTestCurl(cmCTest* ctest)
{
this->CTest = ctest;
@@ -42,32 +44,27 @@ namespace {
size_t curlWriteMemoryCallback(void* ptr, size_t size, size_t nmemb,
void* data)
{
- int realsize = (int)(size * nmemb);
-
- std::vector<char>* vec = static_cast<std::vector<char>*>(data);
+ int realsize = static_cast<int>(size * nmemb);
const char* chPtr = static_cast<char*>(ptr);
- vec->insert(vec->end(), chPtr, chPtr + realsize);
+ cmAppend(*static_cast<std::vector<char>*>(data), chPtr, chPtr + realsize);
return realsize;
}
size_t curlDebugCallback(CURL* /*unused*/, curl_infotype /*unused*/,
char* chPtr, size_t size, void* data)
{
- std::vector<char>* vec = static_cast<std::vector<char>*>(data);
- vec->insert(vec->end(), chPtr, chPtr + size);
-
+ cmAppend(*static_cast<std::vector<char>*>(data), chPtr, chPtr + size);
return size;
}
}
void cmCTestCurl::SetCurlOptions(std::vector<std::string> const& args)
{
- for (std::vector<std::string>::const_iterator i = args.begin();
- i != args.end(); ++i) {
- if (*i == "CURLOPT_SSL_VERIFYPEER_OFF") {
+ for (std::string const& arg : args) {
+ if (arg == "CURLOPT_SSL_VERIFYPEER_OFF") {
this->VerifyPeerOff = true;
}
- if (*i == "CURLOPT_SSL_VERIFYHOST_OFF") {
+ if (arg == "CURLOPT_SSL_VERIFYHOST_OFF") {
this->VerifyHostOff = true;
}
}
@@ -78,6 +75,7 @@ bool cmCTestCurl::InitCurl()
if (!this->Curl) {
return false;
}
+ cmCurlSetCAInfo(this->Curl);
if (this->VerifyPeerOff) {
curl_easy_setopt(this->Curl, CURLOPT_SSL_VERIFYPEER, 0);
}
@@ -111,7 +109,7 @@ bool cmCTestCurl::UploadFile(std::string const& local_file,
std::string const& url, std::string const& fields,
std::string& response)
{
- response = "";
+ response.clear();
if (!this->InitCurl()) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Initialization of curl failed");
return false;
@@ -130,9 +128,7 @@ bool cmCTestCurl::UploadFile(std::string const& local_file,
return false;
}
// set the url
- std::string upload_url = url;
- upload_url += "?";
- upload_url += fields;
+ std::string upload_url = cmStrCat(url, '?', fields);
::curl_easy_setopt(this->Curl, CURLOPT_URL, upload_url.c_str());
// now specify which file to upload
::curl_easy_setopt(this->Curl, CURLOPT_INFILE, ftpfile);
@@ -145,20 +141,19 @@ bool cmCTestCurl::UploadFile(std::string const& local_file,
::curl_easy_setopt(this->Curl, CURLOPT_DEBUGFUNCTION, curlDebugCallback);
// Set Content-Type to satisfy fussy modsecurity rules.
struct curl_slist* headers =
- ::curl_slist_append(CM_NULLPTR, "Content-Type: text/xml");
+ ::curl_slist_append(nullptr, "Content-Type: text/xml");
// Add any additional headers that the user specified.
- for (std::vector<std::string>::const_iterator h = this->HttpHeaders.begin();
- h != this->HttpHeaders.end(); ++h) {
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Add HTTP Header: \"" << *h << "\"" << std::endl,
+ for (std::string const& h : this->HttpHeaders) {
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ " Add HTTP Header: \"" << h << "\"" << std::endl,
this->Quiet);
- headers = ::curl_slist_append(headers, h->c_str());
+ headers = ::curl_slist_append(headers, h.c_str());
}
::curl_easy_setopt(this->Curl, CURLOPT_HTTPHEADER, headers);
std::vector<char> responseData;
std::vector<char> debugData;
- ::curl_easy_setopt(this->Curl, CURLOPT_FILE, (void*)&responseData);
- ::curl_easy_setopt(this->Curl, CURLOPT_DEBUGDATA, (void*)&debugData);
+ ::curl_easy_setopt(this->Curl, CURLOPT_FILE, &responseData);
+ ::curl_easy_setopt(this->Curl, CURLOPT_DEBUGDATA, &debugData);
::curl_easy_setopt(this->Curl, CURLOPT_FAILONERROR, 1);
// Now run off and do what you've been told!
::curl_easy_perform(this->Curl);
@@ -178,7 +173,8 @@ bool cmCTestCurl::UploadFile(std::string const& local_file,
"Curl debug: [" << curlDebug << "]\n", this->Quiet);
}
if (response.empty()) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "No response from server.\n"
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "No response from server.\n"
<< curlDebug);
return false;
}
@@ -188,8 +184,9 @@ bool cmCTestCurl::UploadFile(std::string const& local_file,
bool cmCTestCurl::HttpRequest(std::string const& url,
std::string const& fields, std::string& response)
{
- response = "";
- cmCTestOptionalLog(this->CTest, DEBUG, "HttpRequest\n"
+ response.clear();
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "HttpRequest\n"
<< "url: " << url << "\n"
<< "fields " << fields << "\n",
this->Quiet);
@@ -207,20 +204,18 @@ bool cmCTestCurl::HttpRequest(std::string const& url,
::curl_easy_setopt(this->Curl, CURLOPT_DEBUGFUNCTION, curlDebugCallback);
std::vector<char> responseData;
std::vector<char> debugData;
- ::curl_easy_setopt(this->Curl, CURLOPT_FILE, (void*)&responseData);
- ::curl_easy_setopt(this->Curl, CURLOPT_DEBUGDATA, (void*)&debugData);
+ ::curl_easy_setopt(this->Curl, CURLOPT_FILE, &responseData);
+ ::curl_easy_setopt(this->Curl, CURLOPT_DEBUGDATA, &debugData);
::curl_easy_setopt(this->Curl, CURLOPT_FAILONERROR, 1);
// Add headers if any were specified.
- struct curl_slist* headers = CM_NULLPTR;
+ struct curl_slist* headers = nullptr;
if (!this->HttpHeaders.empty()) {
- for (std::vector<std::string>::const_iterator h =
- this->HttpHeaders.begin();
- h != this->HttpHeaders.end(); ++h) {
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Add HTTP Header: \"" << *h << "\"" << std::endl,
+ for (std::string const& h : this->HttpHeaders) {
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ " Add HTTP Header: \"" << h << "\"" << std::endl,
this->Quiet);
- headers = ::curl_slist_append(headers, h->c_str());
+ headers = ::curl_slist_append(headers, h.c_str());
}
}
@@ -245,10 +240,10 @@ bool cmCTestCurl::HttpRequest(std::string const& url,
void cmCTestCurl::SetProxyType()
{
- this->HTTPProxy = "";
+ this->HTTPProxy.clear();
// this is the default
this->HTTPProxyType = CURLPROXY_HTTP;
- this->HTTPProxyAuth = "";
+ this->HTTPProxyAuth.clear();
if (cmSystemTools::GetEnv("HTTP_PROXY", this->HTTPProxy)) {
std::string port;
if (cmSystemTools::GetEnv("HTTP_PROXY_PORT", port)) {
diff --git a/Source/CTest/cmCTestCurl.h b/Source/CTest/cmCTestCurl.h
index 427a39232..9c5ba667e 100644
--- a/Source/CTest/cmCTestCurl.h
+++ b/Source/CTest/cmCTestCurl.h
@@ -5,10 +5,11 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cm_curl.h"
#include <string>
#include <vector>
+#include "cm_curl.h"
+
class cmCTest;
class cmCTestCurl
@@ -16,7 +17,9 @@ class cmCTestCurl
public:
cmCTestCurl(cmCTest*);
~cmCTestCurl();
- bool UploadFile(std::string const& url, std::string const& file,
+ cmCTestCurl(const cmCTestCurl&) = delete;
+ cmCTestCurl& operator=(const cmCTestCurl&) = delete;
+ bool UploadFile(std::string const& local_file, std::string const& url,
std::string const& fields, std::string& response);
bool HttpRequest(std::string const& url, std::string const& fields,
std::string& response);
diff --git a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
index f4531a1ee..051c117ca 100644
--- a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
+++ b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
@@ -2,10 +2,10 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestEmptyBinaryDirectoryCommand.h"
-#include "cmCTestScriptHandler.h"
-
#include <sstream>
+#include "cmCTestScriptHandler.h"
+
class cmExecutionStatus;
bool cmCTestEmptyBinaryDirectoryCommand::InitialPass(
diff --git a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h
index 503ed234d..ac96a4e30 100644
--- a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h
+++ b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h
@@ -3,14 +3,17 @@
#ifndef cmCTestEmptyBinaryDirectoryCommand_h
#define cmCTestEmptyBinaryDirectoryCommand_h
-#include "cmConfigure.h"
-
-#include "cmCTestCommand.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
+#include <utility>
#include <vector>
-class cmCommand;
+#include <cm/memory>
+
+#include "cmCTestCommand.h"
+#include "cmCommand.h"
+
class cmExecutionStatus;
/** \class cmCTestEmptyBinaryDirectory
@@ -27,13 +30,12 @@ public:
/**
* This is a virtual constructor for the command.
*/
- cmCommand* Clone() CM_OVERRIDE
+ std::unique_ptr<cmCommand> Clone() override
{
- cmCTestEmptyBinaryDirectoryCommand* ni =
- new cmCTestEmptyBinaryDirectoryCommand;
+ auto ni = cm::make_unique<cmCTestEmptyBinaryDirectoryCommand>();
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
- return ni;
+ return std::unique_ptr<cmCommand>(std::move(ni));
}
/**
@@ -41,7 +43,7 @@ public:
* the CMakeLists.txt file.
*/
bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
+ cmExecutionStatus& status) override;
};
#endif
diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx
index 230aedf3b..3f3c1074f 100644
--- a/Source/CTest/cmCTestGIT.cxx
+++ b/Source/CTest/cmCTestGIT.cxx
@@ -2,19 +2,20 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestGIT.h"
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include <ctime>
+#include <vector>
+
#include "cmsys/FStream.hxx"
#include "cmsys/Process.h"
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <vector>
-#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestVC.h"
#include "cmProcessOutput.h"
#include "cmProcessTools.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
static unsigned int cmCTestGITVersion(unsigned int epic, unsigned int major,
@@ -31,9 +32,7 @@ cmCTestGIT::cmCTestGIT(cmCTest* ct, std::ostream& log)
this->CurrentGitVersion = 0;
}
-cmCTestGIT::~cmCTestGIT()
-{
-}
+cmCTestGIT::~cmCTestGIT() = default;
class cmCTestGIT::OneLineParser : public cmCTestVC::LineParser
{
@@ -46,7 +45,7 @@ public:
private:
std::string& Line1;
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
// Only the first line is of interest.
this->Line1 = this->Line;
@@ -58,8 +57,8 @@ std::string cmCTestGIT::GetWorkingRevision()
{
// Run plumbing "git rev-list" to get work tree revision.
const char* git = this->CommandLineTool.c_str();
- const char* git_rev_list[] = { git, "rev-list", "-n", "1",
- "HEAD", "--", CM_NULLPTR };
+ const char* git_rev_list[] = { git, "rev-list", "-n", "1",
+ "HEAD", "--", nullptr };
std::string rev;
OneLineParser out(this, "rl-out> ", rev);
OutputLogger err(this->Log, "rl-err> ");
@@ -70,8 +69,9 @@ std::string cmCTestGIT::GetWorkingRevision()
bool cmCTestGIT::NoteOldRevision()
{
this->OldRevision = this->GetWorkingRevision();
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: "
- << this->OldRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Old revision of repository is: " << this->OldRevision
+ << "\n");
this->PriorRev.Rev = this->OldRevision;
return true;
}
@@ -79,8 +79,9 @@ bool cmCTestGIT::NoteOldRevision()
bool cmCTestGIT::NoteNewRevision()
{
this->NewRevision = this->GetWorkingRevision();
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: "
- << this->NewRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " New revision of repository is: " << this->NewRevision
+ << "\n");
return true;
}
@@ -90,11 +91,11 @@ std::string cmCTestGIT::FindGitDir()
// Run "git rev-parse --git-dir" to locate the real .git directory.
const char* git = this->CommandLineTool.c_str();
- char const* git_rev_parse[] = { git, "rev-parse", "--git-dir", CM_NULLPTR };
+ char const* git_rev_parse[] = { git, "rev-parse", "--git-dir", nullptr };
std::string git_dir_line;
OneLineParser rev_parse_out(this, "rev-parse-out> ", git_dir_line);
OutputLogger rev_parse_err(this->Log, "rev-parse-err> ");
- if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err, CM_NULLPTR,
+ if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err, nullptr,
cmProcessOutput::UTF8)) {
git_dir = git_dir_line;
}
@@ -111,14 +112,14 @@ std::string cmCTestGIT::FindGitDir()
else if (git_dir[0] == '/') {
// Cygwin Git reports a full path that Cygwin understands, but we
// 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())) {
+ std::string cygpath_exe =
+ cmStrCat(cmSystemTools::GetFilenamePath(git), "/cygpath.exe");
+ 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);
OutputLogger cygpath_err(this->Log, "cygpath-err> ");
- if (this->RunChild(cygpath, &cygpath_out, &cygpath_err, CM_NULLPTR,
+ if (this->RunChild(cygpath, &cygpath_out, &cygpath_err, nullptr,
cmProcessOutput::UTF8)) {
git_dir = git_dir_line;
}
@@ -134,12 +135,11 @@ std::string cmCTestGIT::FindTopDir()
// Run "git rev-parse --show-cdup" to locate the top of the tree.
const char* git = this->CommandLineTool.c_str();
- char const* git_rev_parse[] = { git, "rev-parse", "--show-cdup",
- CM_NULLPTR };
+ char const* git_rev_parse[] = { git, "rev-parse", "--show-cdup", nullptr };
std::string cdup;
OneLineParser rev_parse_out(this, "rev-parse-out> ", cdup);
OutputLogger rev_parse_err(this->Log, "rev-parse-err> ");
- if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err, CM_NULLPTR,
+ if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err, nullptr,
cmProcessOutput::UTF8) &&
!cdup.empty()) {
top_dir += "/";
@@ -163,14 +163,13 @@ bool cmCTestGIT::UpdateByFetchAndReset()
if (opts.empty()) {
opts = this->CTest->GetCTestConfiguration("GITUpdateOptions");
}
- std::vector<std::string> args = cmSystemTools::ParseArguments(opts.c_str());
- for (std::vector<std::string>::const_iterator ai = args.begin();
- ai != args.end(); ++ai) {
- git_fetch.push_back(ai->c_str());
+ std::vector<std::string> args = cmSystemTools::ParseArguments(opts);
+ for (std::string const& arg : args) {
+ git_fetch.push_back(arg.c_str());
}
// Sentinel argument.
- git_fetch.push_back(CM_NULLPTR);
+ git_fetch.push_back(nullptr);
// Fetch upstream refs.
OutputLogger fetch_out(this->Log, "fetch-out> ");
@@ -205,8 +204,7 @@ bool cmCTestGIT::UpdateByFetchAndReset()
}
// Reset the local branch to point at that tracked from upstream.
- char const* git_reset[] = { git, "reset", "--hard", sha1.c_str(),
- CM_NULLPTR };
+ char const* git_reset[] = { git, "reset", "--hard", sha1.c_str(), nullptr };
OutputLogger reset_out(this->Log, "reset-out> ");
OutputLogger reset_err(this->Log, "reset-err> ");
return this->RunChild(&git_reset[0], &reset_out, &reset_err);
@@ -214,14 +212,13 @@ bool cmCTestGIT::UpdateByFetchAndReset()
bool cmCTestGIT::UpdateByCustom(std::string const& custom)
{
- std::vector<std::string> git_custom_command;
- cmSystemTools::ExpandListArgument(custom, git_custom_command, true);
+ std::vector<std::string> git_custom_command = cmExpandedList(custom, true);
std::vector<char const*> git_custom;
- for (std::vector<std::string>::const_iterator i = git_custom_command.begin();
- i != git_custom_command.end(); ++i) {
- git_custom.push_back(i->c_str());
+ git_custom.reserve(git_custom_command.size() + 1);
+ for (std::string const& i : git_custom_command) {
+ git_custom.push_back(i.c_str());
}
- git_custom.push_back(CM_NULLPTR);
+ git_custom.push_back(nullptr);
OutputLogger custom_out(this->Log, "custom-out> ");
OutputLogger custom_err(this->Log, "custom-err> ");
@@ -250,18 +247,18 @@ bool cmCTestGIT::UpdateImpl()
// Git < 1.6.5 did not support submodule --recursive
if (this->GetGitVersion() < cmCTestGITVersion(1, 6, 5, 0)) {
- recursive = CM_NULLPTR;
+ 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";
}
}
// Git < 1.8.1 did not support sync --recursive
if (this->GetGitVersion() < cmCTestGITVersion(1, 8, 1, 0)) {
- sync_recursive = CM_NULLPTR;
+ 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";
}
}
@@ -273,9 +270,8 @@ bool cmCTestGIT::UpdateImpl()
std::string init_submodules =
this->CTest->GetCTestConfiguration("GITInitSubmodules");
- if (cmSystemTools::IsOn(init_submodules.c_str())) {
- char const* git_submodule_init[] = { git, "submodule", "init",
- CM_NULLPTR };
+ if (cmIsOn(init_submodules)) {
+ char const* git_submodule_init[] = { git, "submodule", "init", nullptr };
ret = this->RunChild(git_submodule_init, &submodule_out, &submodule_err,
top_dir.c_str());
@@ -285,7 +281,7 @@ bool cmCTestGIT::UpdateImpl()
}
char const* git_submodule_sync[] = { git, "submodule", "sync",
- sync_recursive, CM_NULLPTR };
+ sync_recursive, nullptr };
ret = this->RunChild(git_submodule_sync, &submodule_out, &submodule_err,
top_dir.c_str());
@@ -294,7 +290,7 @@ bool cmCTestGIT::UpdateImpl()
}
char const* git_submodule[] = { git, "submodule", "update", recursive,
- CM_NULLPTR };
+ nullptr };
return this->RunChild(git_submodule, &submodule_out, &submodule_err,
top_dir.c_str());
}
@@ -303,7 +299,7 @@ unsigned int cmCTestGIT::GetGitVersion()
{
if (!this->CurrentGitVersion) {
const char* git = this->CommandLineTool.c_str();
- char const* git_version[] = { git, "--version", CM_NULLPTR };
+ char const* git_version[] = { git, "--version", nullptr };
std::string version;
OneLineParser version_out(this, "version-out> ", version);
OutputLogger version_err(this->Log, "version-err> ");
@@ -338,7 +334,7 @@ public:
this->SetLog(&git->Log, prefix);
}
- typedef cmCTestGIT::Change Change;
+ using Change = cmCTestGIT::Change;
std::vector<Change> Changes;
protected:
@@ -359,7 +355,7 @@ protected:
this->Changes.clear();
}
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (this->Line[0] == ':') {
this->DiffField = DiffFieldChange;
@@ -461,7 +457,7 @@ public:
}
private:
- typedef cmCTestGIT::Revision Revision;
+ using Revision = cmCTestGIT::Revision;
enum SectionType
{
SectionHeader,
@@ -477,15 +473,8 @@ private:
{
std::string Name;
std::string EMail;
- unsigned long Time;
- long TimeZone;
- Person()
- : Name()
- , EMail()
- , Time(0)
- , TimeZone(0)
- {
- }
+ unsigned long Time = 0;
+ long TimeZone = 0;
};
void ParsePerson(const char* str, Person& person)
@@ -513,11 +502,11 @@ private:
const char* email_last = *c ? c++ : c;
person.EMail.assign(email_first, email_last - email_first);
- person.Time = strtoul(c, (char**)&c, 10);
- person.TimeZone = strtol(c, (char**)&c, 10);
+ person.Time = strtoul(c, const_cast<char**>(&c), 10);
+ person.TimeZone = strtol(c, const_cast<char**>(&c), 10);
}
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (this->Line.empty()) {
if (this->Section == SectionBody && this->LineEnd == '\0') {
@@ -557,15 +546,15 @@ private:
void DoHeaderLine()
{
// Look for header fields that we need.
- if (cmHasLiteralPrefix(this->Line.c_str(), "commit ")) {
- this->Rev.Rev = this->Line.c_str() + 7;
- } else if (cmHasLiteralPrefix(this->Line.c_str(), "author ")) {
+ if (cmHasLiteralPrefix(this->Line, "commit ")) {
+ this->Rev.Rev = this->Line.substr(7);
+ } 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;
@@ -615,13 +604,13 @@ bool cmCTestGIT::LoadRevisions()
std::string range = this->OldRevision + ".." + this->NewRevision;
const char* git = this->CommandLineTool.c_str();
const char* git_rev_list[] = { git, "rev-list", "--reverse",
- range.c_str(), "--", CM_NULLPTR };
+ range.c_str(), "--", nullptr };
const char* git_diff_tree[] = {
git, "diff-tree", "--stdin", "--always", "-z",
- "-r", "--pretty=raw", "--encoding=utf-8", CM_NULLPTR
+ "-r", "--pretty=raw", "--encoding=utf-8", nullptr
};
- this->Log << this->ComputeCommandLine(git_rev_list) << " | "
- << this->ComputeCommandLine(git_diff_tree) << "\n";
+ this->Log << cmCTestGIT::ComputeCommandLine(git_rev_list) << " | "
+ << cmCTestGIT::ComputeCommandLine(git_diff_tree) << "\n";
cmsysProcess* cp = cmsysProcess_New();
cmsysProcess_AddCommand(cp, git_rev_list);
@@ -630,7 +619,7 @@ bool cmCTestGIT::LoadRevisions()
CommitParser out(this, "dt-out> ");
OutputLogger err(this->Log, "dt-err> ");
- this->RunProcess(cp, &out, &err, cmProcessOutput::UTF8);
+ cmCTestGIT::RunProcess(cp, &out, &err, cmProcessOutput::UTF8);
// Send one extra zero-byte to terminate the last record.
out.Process("", 1);
@@ -645,23 +634,21 @@ bool cmCTestGIT::LoadModifications()
// Use 'git update-index' to refresh the index w.r.t. the work tree.
const char* git_update_index[] = { git, "update-index", "--refresh",
- CM_NULLPTR };
+ nullptr };
OutputLogger ui_out(this->Log, "ui-out> ");
OutputLogger ui_err(this->Log, "ui-err> ");
- this->RunChild(git_update_index, &ui_out, &ui_err, CM_NULLPTR,
+ this->RunChild(git_update_index, &ui_out, &ui_err, nullptr,
cmProcessOutput::UTF8);
// Use 'git diff-index' to get modified files.
const char* git_diff_index[] = { git, "diff-index", "-z",
- "HEAD", "--", CM_NULLPTR };
+ "HEAD", "--", nullptr };
DiffParser out(this, "di-out> ");
OutputLogger err(this->Log, "di-err> ");
- this->RunChild(git_diff_index, &out, &err, CM_NULLPTR,
- cmProcessOutput::UTF8);
+ this->RunChild(git_diff_index, &out, &err, nullptr, cmProcessOutput::UTF8);
- for (std::vector<Change>::const_iterator ci = out.Changes.begin();
- ci != out.Changes.end(); ++ci) {
- this->DoModification(PathModified, ci->Path);
+ for (Change const& c : out.Changes) {
+ this->DoModification(PathModified, c.Path);
}
return true;
}
diff --git a/Source/CTest/cmCTestGIT.h b/Source/CTest/cmCTestGIT.h
index 4bf8294e6..3103d8492 100644
--- a/Source/CTest/cmCTestGIT.h
+++ b/Source/CTest/cmCTestGIT.h
@@ -3,13 +3,13 @@
#ifndef cmCTestGIT_h
#define cmCTestGIT_h
-#include "cmConfigure.h"
-
-#include "cmCTestGlobalVC.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
+#include "cmCTestGlobalVC.h"
+
class cmCTest;
/** \class cmCTestGIT
@@ -22,15 +22,15 @@ public:
/** Construct with a CTest instance and update log stream. */
cmCTestGIT(cmCTest* ctest, std::ostream& log);
- ~cmCTestGIT() CM_OVERRIDE;
+ ~cmCTestGIT() override;
private:
unsigned int CurrentGitVersion;
unsigned int GetGitVersion();
std::string GetWorkingRevision();
- bool NoteOldRevision() CM_OVERRIDE;
- bool NoteNewRevision() CM_OVERRIDE;
- bool UpdateImpl() CM_OVERRIDE;
+ bool NoteOldRevision() override;
+ bool NoteNewRevision() override;
+ bool UpdateImpl() override;
std::string FindGitDir();
std::string FindTopDir();
@@ -39,8 +39,8 @@ private:
bool UpdateByCustom(std::string const& custom);
bool UpdateInternal();
- bool LoadRevisions() CM_OVERRIDE;
- bool LoadModifications() CM_OVERRIDE;
+ bool LoadRevisions() override;
+ bool LoadModifications() override;
// "public" needed by older Sun compilers
public:
diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx
index 19034c01b..cc0b4ed0c 100644
--- a/Source/CTest/cmCTestGenericHandler.cxx
+++ b/Source/CTest/cmCTestGenericHandler.cxx
@@ -2,7 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestGenericHandler.h"
-#include "cmConfigure.h"
#include <sstream>
#include <utility>
@@ -12,22 +11,19 @@
cmCTestGenericHandler::cmCTestGenericHandler()
{
this->HandlerVerbose = cmSystemTools::OUTPUT_NONE;
- this->CTest = CM_NULLPTR;
+ this->CTest = nullptr;
this->SubmitIndex = 0;
this->AppendXML = false;
this->Quiet = false;
this->TestLoad = 0;
}
-cmCTestGenericHandler::~cmCTestGenericHandler()
-{
-}
+cmCTestGenericHandler::~cmCTestGenericHandler() = default;
void cmCTestGenericHandler::SetOption(const std::string& op, const char* value)
{
if (!value) {
- cmCTestGenericHandler::t_StringToString::iterator remit =
- this->Options.find(op);
+ auto remit = this->Options.find(op);
if (remit != this->Options.end()) {
this->Options.erase(remit);
}
@@ -42,8 +38,7 @@ void cmCTestGenericHandler::SetPersistentOption(const std::string& op,
{
this->SetOption(op, value);
if (!value) {
- cmCTestGenericHandler::t_StringToString::iterator remit =
- this->PersistentOptions.find(op);
+ auto remit = this->PersistentOptions.find(op);
if (remit != this->PersistentOptions.end()) {
this->PersistentOptions.erase(remit);
}
@@ -58,19 +53,16 @@ void cmCTestGenericHandler::Initialize()
this->AppendXML = false;
this->TestLoad = 0;
this->Options.clear();
- t_StringToString::iterator it;
- for (it = this->PersistentOptions.begin();
- it != this->PersistentOptions.end(); ++it) {
- this->Options[it->first] = it->second;
+ for (auto const& po : this->PersistentOptions) {
+ this->Options[po.first] = po.second;
}
}
const char* cmCTestGenericHandler::GetOption(const std::string& op)
{
- cmCTestGenericHandler::t_StringToString::iterator remit =
- this->Options.find(op);
+ auto remit = this->Options.find(op);
if (remit == this->Options.end()) {
- return CM_NULLPTR;
+ return nullptr;
}
return remit->second.c_str();
}
@@ -103,8 +95,9 @@ bool cmCTestGenericHandler::StartResultingXML(cmCTest::Part part,
}
if (!this->CTest->OpenOutputFile(this->CTest->GetCurrentTag(), ostr.str(),
xofs, true)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create resulting XML file: "
- << ostr.str() << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot create resulting XML file: " << ostr.str()
+ << std::endl);
return false;
}
this->CTest->AddSubmitFile(part, ostr.str().c_str());
diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h
index e881252c9..94e541865 100644
--- a/Source/CTest/cmCTestGenericHandler.h
+++ b/Source/CTest/cmCTestGenericHandler.h
@@ -6,10 +6,11 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
-#include <stddef.h>
#include <string>
#include <vector>
+#include <stddef.h>
+
#include "cmCTest.h"
#include "cmSystemTools.h"
@@ -25,7 +26,7 @@ class cmCTestGenericHandler
{
public:
/**
- * If verbose then more informaiton is printed out
+ * If verbose then more information is printed out
*/
void SetVerbose(bool val)
{
@@ -71,7 +72,7 @@ public:
cmCTestGenericHandler();
virtual ~cmCTestGenericHandler();
- typedef std::map<std::string, std::string> t_StringToString;
+ using t_StringToString = std::map<std::string, std::string>;
void SetPersistentOption(const std::string& op, const char* value);
void SetOption(const std::string& op, const char* value);
diff --git a/Source/CTest/cmCTestGlobalVC.cxx b/Source/CTest/cmCTestGlobalVC.cxx
index 25294b5ae..5f05efb33 100644
--- a/Source/CTest/cmCTestGlobalVC.cxx
+++ b/Source/CTest/cmCTestGlobalVC.cxx
@@ -2,22 +2,20 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestGlobalVC.h"
+#include <ostream>
+#include <utility>
+
#include "cmCTest.h"
#include "cmSystemTools.h"
#include "cmXMLWriter.h"
-#include <ostream>
-#include <utility>
-
cmCTestGlobalVC::cmCTestGlobalVC(cmCTest* ct, std::ostream& log)
: cmCTestVC(ct, log)
{
this->PriorRev = this->Unknown;
}
-cmCTestGlobalVC::~cmCTestGlobalVC()
-{
-}
+cmCTestGlobalVC::~cmCTestGlobalVC() = default;
const char* cmCTestGlobalVC::LocalPath(std::string const& path)
{
@@ -48,15 +46,14 @@ void cmCTestGlobalVC::DoRevision(Revision const& revision,
/* clang-format on */
// Update information about revisions of the changed files.
- for (std::vector<Change>::const_iterator ci = changes.begin();
- ci != changes.end(); ++ci) {
- if (const char* local = this->LocalPath(ci->Path)) {
+ for (Change const& c : changes) {
+ if (const char* local = this->LocalPath(c.Path)) {
std::string dir = cmSystemTools::GetFilenamePath(local);
std::string name = cmSystemTools::GetFilenameName(local);
File& file = this->Dirs[dir][name];
file.PriorRev = file.Rev ? file.Rev : &this->PriorRev;
file.Rev = &rev;
- this->Log << " " << ci->Action << " " << local << " "
+ this->Log << " " << c.Action << " " << local << " "
<< "\n";
}
}
@@ -83,9 +80,9 @@ void cmCTestGlobalVC::WriteXMLDirectory(cmXMLWriter& xml,
const char* slash = path.empty() ? "" : "/";
xml.StartElement("Directory");
xml.Element("Name", path);
- for (Directory::const_iterator fi = dir.begin(); fi != dir.end(); ++fi) {
- std::string full = path + slash + fi->first;
- this->WriteXMLEntry(xml, path, fi->first, full, fi->second);
+ for (auto const& f : dir) {
+ std::string const full = path + slash + f.first;
+ this->WriteXMLEntry(xml, path, f.first, full, f.second);
}
xml.EndElement(); // Directory
}
@@ -114,11 +111,14 @@ bool cmCTestGlobalVC::WriteXMLUpdates(cmXMLWriter& xml)
this->WriteXMLGlobal(xml);
- for (std::map<std::string, Directory>::const_iterator di =
- this->Dirs.begin();
- di != this->Dirs.end(); ++di) {
- this->WriteXMLDirectory(xml, di->first, di->second);
+ for (auto const& d : this->Dirs) {
+ this->WriteXMLDirectory(xml, d.first, d.second);
}
return result;
}
+
+void cmCTestGlobalVC::SetNewRevision(std::string const& revision)
+{
+ this->NewRevision = revision;
+}
diff --git a/Source/CTest/cmCTestGlobalVC.h b/Source/CTest/cmCTestGlobalVC.h
index a5273d3dd..ff86591ea 100644
--- a/Source/CTest/cmCTestGlobalVC.h
+++ b/Source/CTest/cmCTestGlobalVC.h
@@ -3,9 +3,7 @@
#ifndef cmCTestGlobalVC_h
#define cmCTestGlobalVC_h
-#include "cmConfigure.h"
-
-#include "cmCTestVC.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <list>
@@ -13,6 +11,8 @@
#include <string>
#include <vector>
+#include "cmCTestVC.h"
+
class cmCTest;
class cmXMLWriter;
@@ -26,11 +26,13 @@ public:
/** Construct with a CTest instance and update log stream. */
cmCTestGlobalVC(cmCTest* ctest, std::ostream& log);
- ~cmCTestGlobalVC() CM_OVERRIDE;
+ ~cmCTestGlobalVC() override;
protected:
// Implement cmCTestVC internal API.
- bool WriteXMLUpdates(cmXMLWriter& xml) CM_OVERRIDE;
+ bool WriteXMLUpdates(cmXMLWriter& xml) override;
+
+ void SetNewRevision(std::string const& revision) override;
/** Represent a vcs-reported action for one path in a revision. */
struct Change
diff --git a/Source/CTest/cmCTestHG.cxx b/Source/CTest/cmCTestHG.cxx
index 49f9a6500..3265498c0 100644
--- a/Source/CTest/cmCTestHG.cxx
+++ b/Source/CTest/cmCTestHG.cxx
@@ -2,25 +2,25 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestHG.h"
+#include <ostream>
+#include <vector>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestVC.h"
#include "cmProcessTools.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
-#include "cmsys/RegularExpression.hxx"
-#include <ostream>
-#include <vector>
-
cmCTestHG::cmCTestHG(cmCTest* ct, std::ostream& log)
: cmCTestGlobalVC(ct, log)
{
this->PriorRev = this->Unknown;
}
-cmCTestHG::~cmCTestHG()
-{
-}
+cmCTestHG::~cmCTestHG() = default;
class cmCTestHG::IdentifyParser : public cmCTestVC::LineParser
{
@@ -36,7 +36,7 @@ private:
std::string& Rev;
cmsys::RegularExpression RegexIdentify;
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (this->RegexIdentify.find(this->Line)) {
this->Rev = this->RegexIdentify.match(1);
@@ -60,7 +60,7 @@ private:
cmCTestHG* HG;
cmsys::RegularExpression RegexStatus;
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (this->RegexStatus.find(this->Line)) {
this->DoPath(this->RegexStatus.match(1)[0], this->RegexStatus.match(2));
@@ -96,7 +96,7 @@ std::string cmCTestHG::GetWorkingRevision()
{
// Run plumbing "hg identify" to get work tree revision.
const char* hg = this->CommandLineTool.c_str();
- const char* hg_identify[] = { hg, "identify", "-i", CM_NULLPTR };
+ const char* hg_identify[] = { hg, "identify", "-i", nullptr };
std::string rev;
IdentifyParser out(this, "rev-out> ", rev);
OutputLogger err(this->Log, "rev-err> ");
@@ -107,8 +107,9 @@ std::string cmCTestHG::GetWorkingRevision()
bool cmCTestHG::NoteOldRevision()
{
this->OldRevision = this->GetWorkingRevision();
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: "
- << this->OldRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Old revision of repository is: " << this->OldRevision
+ << "\n");
this->PriorRev.Rev = this->OldRevision;
return true;
}
@@ -116,8 +117,9 @@ bool cmCTestHG::NoteOldRevision()
bool cmCTestHG::NoteNewRevision()
{
this->NewRevision = this->GetWorkingRevision();
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: "
- << this->NewRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " New revision of repository is: " << this->NewRevision
+ << "\n");
return true;
}
@@ -126,7 +128,7 @@ bool cmCTestHG::UpdateImpl()
// Use "hg pull" followed by "hg update" to update the working tree.
{
const char* hg = this->CommandLineTool.c_str();
- const char* hg_pull[] = { hg, "pull", "-v", CM_NULLPTR };
+ const char* hg_pull[] = { hg, "pull", "-v", nullptr };
OutputLogger out(this->Log, "pull-out> ");
OutputLogger err(this->Log, "pull-err> ");
this->RunChild(&hg_pull[0], &out, &err);
@@ -144,22 +146,22 @@ bool cmCTestHG::UpdateImpl()
if (opts.empty()) {
opts = this->CTest->GetCTestConfiguration("HGUpdateOptions");
}
- std::vector<std::string> args = cmSystemTools::ParseArguments(opts.c_str());
- for (std::vector<std::string>::const_iterator ai = args.begin();
- ai != args.end(); ++ai) {
- hg_update.push_back(ai->c_str());
+ std::vector<std::string> args = cmSystemTools::ParseArguments(opts);
+ for (std::string const& arg : args) {
+ hg_update.push_back(arg.c_str());
}
// Sentinel argument.
- hg_update.push_back(CM_NULLPTR);
+ hg_update.push_back(nullptr);
OutputLogger out(this->Log, "update-out> ");
OutputLogger err(this->Log, "update-err> ");
return this->RunUpdateCommand(&hg_update[0], &out, &err);
}
-class cmCTestHG::LogParser : public cmCTestVC::OutputLogger,
- private cmXMLParser
+class cmCTestHG::LogParser
+ : public cmCTestVC::OutputLogger
+ , private cmXMLParser
{
public:
LogParser(cmCTestHG* hg, const char* prefix)
@@ -168,42 +170,44 @@ public:
{
this->InitializeParser();
}
- ~LogParser() CM_OVERRIDE { this->CleanupParser(); }
+ ~LogParser() override { this->CleanupParser(); }
+
private:
cmCTestHG* HG;
- typedef cmCTestHG::Revision Revision;
- typedef cmCTestHG::Change Change;
+ using Revision = cmCTestHG::Revision;
+ using Change = cmCTestHG::Change;
Revision Rev;
std::vector<Change> Changes;
Change CurChange;
std::vector<char> CData;
- bool ProcessChunk(const char* data, int length) CM_OVERRIDE
+ bool ProcessChunk(const char* data, int length) override
{
this->OutputLogger::ProcessChunk(data, length);
this->ParseChunk(data, length);
return true;
}
- void StartElement(const std::string& name, const char** atts) CM_OVERRIDE
+ void StartElement(const std::string& name, const char** atts) override
{
this->CData.clear();
if (name == "logentry") {
this->Rev = Revision();
- if (const char* rev = this->FindAttribute(atts, "revision")) {
+ if (const char* rev =
+ cmCTestHG::LogParser::FindAttribute(atts, "revision")) {
this->Rev.Rev = rev;
}
this->Changes.clear();
}
}
- void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
+ void CharacterDataHandler(const char* data, int length) override
{
- this->CData.insert(this->CData.end(), data, data + length);
+ cmAppend(this->CData, data, data + length);
}
- void EndElement(const std::string& name) CM_OVERRIDE
+ void EndElement(const std::string& name) override
{
if (name == "logentry") {
this->HG->DoRevision(this->Rev, this->Changes);
@@ -217,25 +221,25 @@ private:
this->Rev.Log.assign(&this->CData[0], this->CData.size());
} else if (!this->CData.empty() && name == "files") {
std::vector<std::string> paths = this->SplitCData();
- for (unsigned int i = 0; i < paths.size(); ++i) {
+ for (std::string const& path : paths) {
// Updated by default, will be modified using file_adds and
// file_dels.
this->CurChange = Change('U');
- this->CurChange.Path = paths[i];
+ this->CurChange.Path = path;
this->Changes.push_back(this->CurChange);
}
} else if (!this->CData.empty() && name == "file_adds") {
std::string added_paths(this->CData.begin(), this->CData.end());
- for (unsigned int i = 0; i < this->Changes.size(); ++i) {
- if (added_paths.find(this->Changes[i].Path) != std::string::npos) {
- this->Changes[i].Action = 'A';
+ for (Change& change : this->Changes) {
+ if (added_paths.find(change.Path) != std::string::npos) {
+ change.Action = 'A';
}
}
} else if (!this->CData.empty() && name == "file_dels") {
std::string added_paths(this->CData.begin(), this->CData.end());
- for (unsigned int i = 0; i < this->Changes.size(); ++i) {
- if (added_paths.find(this->Changes[i].Path) != std::string::npos) {
- this->Changes[i].Action = 'D';
+ for (Change& change : this->Changes) {
+ if (added_paths.find(change.Path) != std::string::npos) {
+ change.Action = 'D';
}
}
}
@@ -246,19 +250,19 @@ private:
{
std::vector<std::string> output;
std::string currPath;
- for (unsigned int i = 0; i < this->CData.size(); ++i) {
- if (this->CData[i] != ' ') {
- currPath += this->CData[i];
+ for (char i : this->CData) {
+ if (i != ' ') {
+ currPath += i;
} else {
output.push_back(currPath);
- currPath = "";
+ currPath.clear();
}
}
output.push_back(currPath);
return output;
}
- void ReportError(int /*line*/, int /*column*/, const char* msg) CM_OVERRIDE
+ void ReportError(int /*line*/, int /*column*/, const char* msg) override
{
this->HG->Log << "Error parsing hg log xml: " << msg << "\n";
}
@@ -286,7 +290,7 @@ bool cmCTestHG::LoadRevisions()
"</logentry>\n";
const char* hg_log[] = {
hg, "log", "--removed", "-r", range.c_str(),
- "--template", hgXMLTemplate, CM_NULLPTR
+ "--template", hgXMLTemplate, nullptr
};
LogParser out(this, "log-out> ");
@@ -302,7 +306,7 @@ bool cmCTestHG::LoadModifications()
{
// Use 'hg status' to get modified files.
const char* hg = this->CommandLineTool.c_str();
- const char* hg_status[] = { hg, "status", CM_NULLPTR };
+ const char* hg_status[] = { hg, "status", nullptr };
StatusParser out(this, "status-out> ");
OutputLogger err(this->Log, "status-err> ");
this->RunChild(hg_status, &out, &err);
diff --git a/Source/CTest/cmCTestHG.h b/Source/CTest/cmCTestHG.h
index ec9eaffe8..2900139b4 100644
--- a/Source/CTest/cmCTestHG.h
+++ b/Source/CTest/cmCTestHG.h
@@ -3,13 +3,13 @@
#ifndef cmCTestHG_h
#define cmCTestHG_h
-#include "cmConfigure.h"
-
-#include "cmCTestGlobalVC.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
+#include "cmCTestGlobalVC.h"
+
class cmCTest;
/** \class cmCTestHG
@@ -22,16 +22,16 @@ public:
/** Construct with a CTest instance and update log stream. */
cmCTestHG(cmCTest* ctest, std::ostream& log);
- ~cmCTestHG() CM_OVERRIDE;
+ ~cmCTestHG() override;
private:
std::string GetWorkingRevision();
- bool NoteOldRevision() CM_OVERRIDE;
- bool NoteNewRevision() CM_OVERRIDE;
- bool UpdateImpl() CM_OVERRIDE;
+ bool NoteOldRevision() override;
+ bool NoteNewRevision() override;
+ bool UpdateImpl() override;
- bool LoadRevisions() CM_OVERRIDE;
- bool LoadModifications() CM_OVERRIDE;
+ bool LoadRevisions() override;
+ bool LoadModifications() override;
// Parsing helper classes.
class IdentifyParser;
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx
index c99e450d0..b1034c9ff 100644
--- a/Source/CTest/cmCTestHandlerCommand.cxx
+++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -2,35 +2,21 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestHandlerCommand.h"
+#include <algorithm>
+#include <cstdlib>
+#include <cstring>
+#include <sstream>
+
+#include "cm_static_string_view.hxx"
+
#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
-#include "cmake.h"
-
-#include <sstream>
-#include <stdlib.h>
-
-class cmExecutionStatus;
-
-cmCTestHandlerCommand::cmCTestHandlerCommand()
-{
- const size_t INIT_SIZE = 100;
- size_t cc;
- this->Arguments.reserve(INIT_SIZE);
- for (cc = 0; cc < INIT_SIZE; ++cc) {
- this->Arguments.push_back(CM_NULLPTR);
- }
- this->Arguments[ct_RETURN_VALUE] = "RETURN_VALUE";
- this->Arguments[ct_CAPTURE_CMAKE_ERROR] = "CAPTURE_CMAKE_ERROR";
- this->Arguments[ct_SOURCE] = "SOURCE";
- this->Arguments[ct_BUILD] = "BUILD";
- this->Arguments[ct_SUBMIT_INDEX] = "SUBMIT_INDEX";
- this->Last = ct_LAST;
- this->AppendXML = false;
- this->Quiet = false;
-}
namespace {
// class to save and restore the error state for ctest_* commands
@@ -75,6 +61,8 @@ public:
}
}
}
+ SaveRestoreErrorState(const SaveRestoreErrorState&) = delete;
+ SaveRestoreErrorState& operator=(const SaveRestoreErrorState&) = delete;
private:
bool InitialErrorState;
@@ -83,48 +71,46 @@ private:
}
bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& /*unused*/)
+ cmExecutionStatus& status)
{
// save error state and restore it if needed
SaveRestoreErrorState errorState;
// Allocate space for argument values.
- this->Values.clear();
- this->Values.resize(this->Last, CM_NULLPTR);
+ this->BindArguments();
// Process input arguments.
- this->ArgumentDoing = ArgumentDoingNone;
- // look at all arguments and do not short circuit on the first
- // bad one so that CAPTURE_CMAKE_ERROR can override setting the
- // global error state
- bool foundBadArgument = false;
- for (unsigned int i = 0; i < args.size(); ++i) {
- // Check this argument.
- if (!this->CheckArgumentKeyword(args[i]) &&
- !this->CheckArgumentValue(args[i])) {
- std::ostringstream e;
- e << "called with unknown argument \"" << args[i] << "\".";
- this->SetError(e.str());
- foundBadArgument = true;
- }
- // note bad argument
- if (this->ArgumentDoing == ArgumentDoingError) {
- foundBadArgument = true;
- }
+ std::vector<std::string> unparsedArguments;
+ std::vector<std::string> keywordsMissingValue;
+ std::vector<std::string> parsedKeywords;
+ this->Parse(args, &unparsedArguments, &keywordsMissingValue,
+ &parsedKeywords);
+ this->CheckArguments(keywordsMissingValue);
+
+ std::sort(parsedKeywords.begin(), parsedKeywords.end());
+ auto it = std::adjacent_find(parsedKeywords.begin(), parsedKeywords.end());
+ if (it != parsedKeywords.end()) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Called with more than one value for ", *it));
+ }
+
+ bool const foundBadArgument = !unparsedArguments.empty();
+ if (foundBadArgument) {
+ this->SetError(cmStrCat("called with unknown argument \"",
+ unparsedArguments.front(), "\"."));
}
- bool capureCMakeError = (this->Values[ct_CAPTURE_CMAKE_ERROR] &&
- *this->Values[ct_CAPTURE_CMAKE_ERROR]);
+ bool const captureCMakeError = !this->CaptureCMakeError.empty();
// now that arguments are parsed check to see if there is a
// CAPTURE_CMAKE_ERROR specified let the errorState object know.
- if (capureCMakeError) {
+ if (captureCMakeError) {
errorState.CaptureCMakeError();
}
// if we found a bad argument then exit before running command
if (foundBadArgument) {
// store the cmake error
- if (capureCMakeError) {
- this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
- "-1");
- std::string const err = this->GetName() + " " + this->GetError();
+ if (captureCMakeError) {
+ this->Makefile->AddDefinition(this->CaptureCMakeError, "-1");
+ std::string const err = this->GetName() + " " + status.GetError();
if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) {
cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n");
}
@@ -145,29 +131,27 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
this->CTest->SetConfigType(ctestConfigType);
}
- if (this->Values[ct_BUILD]) {
+ if (!this->Build.empty()) {
this->CTest->SetCTestConfiguration(
- "BuildDirectory",
- cmSystemTools::CollapseFullPath(this->Values[ct_BUILD]).c_str(),
+ "BuildDirectory", cmSystemTools::CollapseFullPath(this->Build).c_str(),
this->Quiet);
} else {
- const char* bdir =
+ std::string const& bdir =
this->Makefile->GetSafeDefinition("CTEST_BINARY_DIRECTORY");
- if (bdir) {
+ if (!bdir.empty()) {
this->CTest->SetCTestConfiguration(
"BuildDirectory", cmSystemTools::CollapseFullPath(bdir).c_str(),
this->Quiet);
} else {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "CTEST_BINARY_DIRECTORY not set"
- << std::endl;);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "CTEST_BINARY_DIRECTORY not set" << std::endl;);
}
}
- if (this->Values[ct_SOURCE]) {
- cmCTestLog(this->CTest, DEBUG, "Set source directory to: "
- << this->Values[ct_SOURCE] << std::endl);
+ if (!this->Source.empty()) {
+ cmCTestLog(this->CTest, DEBUG,
+ "Set source directory to: " << this->Source << std::endl);
this->CTest->SetCTestConfiguration(
- "SourceDirectory",
- cmSystemTools::CollapseFullPath(this->Values[ct_SOURCE]).c_str(),
+ "SourceDirectory", cmSystemTools::CollapseFullPath(this->Source).c_str(),
this->Quiet);
} else {
this->CTest->SetCTestConfiguration(
@@ -186,13 +170,13 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl;);
cmCTestGenericHandler* handler = this->InitializeHandler();
if (!handler) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot instantiate test handler "
- << this->GetName() << std::endl);
- if (capureCMakeError) {
- this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
- "-1");
- const char* err = this->GetError();
- if (err && !cmSystemTools::FindLastString(err, "unknown error.")) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot instantiate test handler " << this->GetName()
+ << std::endl);
+ if (captureCMakeError) {
+ this->Makefile->AddDefinition(this->CaptureCMakeError, "-1");
+ std::string const& err = status.GetError();
+ if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) {
cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n");
}
return true;
@@ -200,48 +184,47 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
return false;
}
- handler->SetAppendXML(this->AppendXML);
+ handler->SetAppendXML(this->Append);
handler->PopulateCustomVectors(this->Makefile);
- if (this->Values[ct_SUBMIT_INDEX]) {
- if (!this->CTest->GetDropSiteCDash() &&
- this->CTest->GetDartVersion() <= 1) {
- cmCTestLog(
- this->CTest, ERROR_MESSAGE,
- "Dart before version 2.0 does not support collecting submissions."
- << std::endl
- << "Please upgrade the server to Dart 2 or higher, or do not use "
- "SUBMIT_INDEX."
- << std::endl);
- } else {
- handler->SetSubmitIndex(atoi(this->Values[ct_SUBMIT_INDEX]));
- }
+ if (!this->SubmitIndex.empty()) {
+ handler->SetSubmitIndex(atoi(this->SubmitIndex.c_str()));
}
cmWorkingDirectory workdir(
this->CTest->GetCTestConfiguration("BuildDirectory"));
+ if (workdir.Failed()) {
+ this->SetError("failed to change directory to " +
+ this->CTest->GetCTestConfiguration("BuildDirectory") +
+ " : " + std::strerror(workdir.GetLastResult()));
+ if (captureCMakeError) {
+ this->Makefile->AddDefinition(this->CaptureCMakeError, "-1");
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ this->GetName() << " " << status.GetError() << "\n");
+ // return success because failure is recorded in CAPTURE_CMAKE_ERROR
+ return true;
+ }
+ return false;
+ }
+
int res = handler->ProcessHandler();
- if (this->Values[ct_RETURN_VALUE] && *this->Values[ct_RETURN_VALUE]) {
- std::ostringstream str;
- str << res;
- this->Makefile->AddDefinition(this->Values[ct_RETURN_VALUE],
- str.str().c_str());
+ if (!this->ReturnValue.empty()) {
+ this->Makefile->AddDefinition(this->ReturnValue, std::to_string(res));
}
this->ProcessAdditionalValues(handler);
// log the error message if there was an error
- if (capureCMakeError) {
+ if (captureCMakeError) {
const char* returnString = "0";
if (cmSystemTools::GetErrorOccuredFlag()) {
returnString = "-1";
- const char* err = this->GetError();
+ std::string const& err = status.GetError();
// print out the error if it is not "unknown error" which means
// there was no message
- if (err && !cmSystemTools::FindLastString(err, "unknown error.")) {
+ if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) {
cmCTestLog(this->CTest, ERROR_MESSAGE, err);
}
}
// store the captured cmake error state 0 or -1
- this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
- returnString);
+ this->Makefile->AddDefinition(this->CaptureCMakeError, returnString);
}
return true;
}
@@ -250,47 +233,17 @@ void cmCTestHandlerCommand::ProcessAdditionalValues(cmCTestGenericHandler*)
{
}
-bool cmCTestHandlerCommand::CheckArgumentKeyword(std::string const& arg)
+void cmCTestHandlerCommand::BindArguments()
{
- // Look for non-value arguments common to all commands.
- if (arg == "APPEND") {
- this->ArgumentDoing = ArgumentDoingNone;
- this->AppendXML = true;
- return true;
- }
- if (arg == "QUIET") {
- this->ArgumentDoing = ArgumentDoingNone;
- this->Quiet = true;
- return true;
- }
-
- // Check for a keyword in our argument/value table.
- for (unsigned int k = 0; k < this->Arguments.size(); ++k) {
- if (this->Arguments[k] && arg == this->Arguments[k]) {
- this->ArgumentDoing = ArgumentDoingKeyword;
- this->ArgumentIndex = k;
- return true;
- }
- }
- return false;
+ this->Bind("APPEND"_s, this->Append);
+ this->Bind("QUIET"_s, this->Quiet);
+ this->Bind("RETURN_VALUE"_s, this->ReturnValue);
+ this->Bind("CAPTURE_CMAKE_ERROR"_s, this->CaptureCMakeError);
+ this->Bind("SOURCE"_s, this->Source);
+ this->Bind("BUILD"_s, this->Build);
+ this->Bind("SUBMIT_INDEX"_s, this->SubmitIndex);
}
-bool cmCTestHandlerCommand::CheckArgumentValue(std::string const& arg)
+void cmCTestHandlerCommand::CheckArguments(std::vector<std::string> const&)
{
- if (this->ArgumentDoing == ArgumentDoingKeyword) {
- this->ArgumentDoing = ArgumentDoingNone;
- unsigned int k = this->ArgumentIndex;
- if (this->Values[k]) {
- std::ostringstream e;
- e << "Called with more than one value for " << this->Arguments[k];
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
- this->ArgumentDoing = ArgumentDoingError;
- return true;
- }
- this->Values[k] = arg.c_str();
- cmCTestLog(this->CTest, DEBUG, "Set " << this->Arguments[k] << " to "
- << arg << "\n");
- return true;
- }
- return false;
}
diff --git a/Source/CTest/cmCTestHandlerCommand.h b/Source/CTest/cmCTestHandlerCommand.h
index 0ea061225..a20d607e2 100644
--- a/Source/CTest/cmCTestHandlerCommand.h
+++ b/Source/CTest/cmCTestHandlerCommand.h
@@ -3,14 +3,14 @@
#ifndef cmCTestHandlerCommand_h
#define cmCTestHandlerCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmCTestCommand.h"
-
-#include <stddef.h>
#include <string>
#include <vector>
+#include "cmArgumentParser.h"
+#include "cmCTestCommand.h"
+
class cmCTestGenericHandler;
class cmExecutionStatus;
@@ -19,11 +19,11 @@ class cmExecutionStatus;
*
* cmCTestHandlerCommand defineds the command to test the project.
*/
-class cmCTestHandlerCommand : public cmCTestCommand
+class cmCTestHandlerCommand
+ : public cmCTestCommand
+ , public cmArgumentParser<void>
{
public:
- cmCTestHandlerCommand();
-
/**
* The name of the command as specified in CMakeList.txt.
*/
@@ -34,18 +34,7 @@ public:
* the CMakeLists.txt file.
*/
bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
- enum
- {
- ct_NONE,
- ct_RETURN_VALUE,
- ct_CAPTURE_CMAKE_ERROR,
- ct_BUILD,
- ct_SOURCE,
- ct_SUBMIT_INDEX,
- ct_LAST
- };
+ cmExecutionStatus& status) override;
protected:
virtual cmCTestGenericHandler* InitializeHandler() = 0;
@@ -53,25 +42,16 @@ protected:
virtual void ProcessAdditionalValues(cmCTestGenericHandler* handler);
// Command argument handling.
- virtual bool CheckArgumentKeyword(std::string const& arg);
- virtual bool CheckArgumentValue(std::string const& arg);
- enum
- {
- ArgumentDoingNone,
- ArgumentDoingError,
- ArgumentDoingKeyword,
- ArgumentDoingLast1
- };
- int ArgumentDoing;
- unsigned int ArgumentIndex;
-
- bool AppendXML;
- bool Quiet;
-
- std::string ReturnVariable;
- std::vector<const char*> Arguments;
- std::vector<const char*> Values;
- size_t Last;
+ virtual void BindArguments();
+ virtual void CheckArguments(std::vector<std::string> const& keywords);
+
+ bool Append = false;
+ bool Quiet = false;
+ std::string CaptureCMakeError;
+ std::string ReturnValue;
+ std::string Build;
+ std::string Source;
+ std::string SubmitIndex;
};
#define CTEST_COMMAND_APPEND_OPTION_DOCS \
diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx
index 5b213518a..647f5fff9 100644
--- a/Source/CTest/cmCTestLaunch.cxx
+++ b/Source/CTest/cmCTestLaunch.cxx
@@ -2,36 +2,36 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestLaunch.h"
-#include "cmConfigure.h"
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
#include "cmsys/FStream.hxx"
#include "cmsys/Process.h"
#include "cmsys/RegularExpression.hxx"
-#include <iostream>
-#include <stdlib.h>
-#include <string.h>
#include "cmCryptoHash.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmProcessOutput.h"
+#include "cmState.h"
#include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLWriter.h"
-#include "cm_auto_ptr.hxx"
#include "cmake.h"
#ifdef _WIN32
-#include <fcntl.h> // for _O_BINARY
-#include <io.h> // for _setmode
-#include <stdio.h> // for std{out,err} and fileno
+# include <fcntl.h> // for _O_BINARY
+# include <io.h> // for _setmode
+# include <stdio.h> // for std{out,err} and fileno
#endif
cmCTestLaunch::cmCTestLaunch(int argc, const char* const* argv)
{
this->Passthru = true;
- this->Process = CM_NULLPTR;
+ this->Process = nullptr;
this->ExitCode = 1;
this->CWD = cmSystemTools::GetCurrentWorkingDirectory();
@@ -129,7 +129,7 @@ bool cmCTestLaunch::ParseArguments(int argc, const char* const* argv)
return true;
}
this->RealArgC = 0;
- this->RealArgV = CM_NULLPTR;
+ this->RealArgV = nullptr;
std::cerr << "No launch/command separator ('--') found!\n";
return false;
}
@@ -147,7 +147,7 @@ void cmCTestLaunch::HandleRealArg(const char* arg)
return;
}
#endif
- this->RealArgs.push_back(arg);
+ this->RealArgs.emplace_back(arg);
}
void cmCTestLaunch::ComputeFileNames()
@@ -171,21 +171,14 @@ void cmCTestLaunch::ComputeFileNames()
cmCryptoHash md5(cmCryptoHash::AlgoMD5);
md5.Initialize();
md5.Append(this->CWD);
- for (std::vector<std::string>::const_iterator ai = this->RealArgs.begin();
- ai != this->RealArgs.end(); ++ai) {
- md5.Append(*ai);
+ for (std::string const& realArg : this->RealArgs) {
+ md5.Append(realArg);
}
this->LogHash = md5.FinalizeHex();
// We store stdout and stderr in temporary log files.
- this->LogOut = this->LogDir;
- this->LogOut += "launch-";
- this->LogOut += this->LogHash;
- this->LogOut += "-out.txt";
- this->LogErr = this->LogDir;
- this->LogErr += "launch-";
- this->LogErr += this->LogHash;
- this->LogErr += "-err.txt";
+ this->LogOut = cmStrCat(this->LogDir, "launch-", this->LogHash, "-out.txt");
+ this->LogErr = cmStrCat(this->LogDir, "launch-", this->LogHash, "-err.txt");
}
void cmCTestLaunch::RunChild()
@@ -224,11 +217,11 @@ void cmCTestLaunch::RunChild()
// Record child stdout and stderr if necessary.
if (!this->Passthru) {
- char* data = CM_NULLPTR;
+ char* data = nullptr;
int length = 0;
cmProcessOutput processOutput;
std::string strdata;
- while (int p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) {
+ while (int p = cmsysProcess_WaitForData(cp, &data, &length, nullptr)) {
if (p == cmsysProcess_Pipe_STDOUT) {
processOutput.DecodeText(data, length, strdata, 1);
fout.write(strdata.c_str(), strdata.size());
@@ -254,7 +247,7 @@ void cmCTestLaunch::RunChild()
}
// Wait for the real command to finish.
- cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+ cmsysProcess_WaitForExit(cp, nullptr);
this->ExitCode = cmsysProcess_GetExitValue(cp);
}
@@ -284,11 +277,8 @@ void cmCTestLaunch::LoadLabels()
}
// Labels are listed in per-target files.
- std::string fname = this->OptionBuildDir;
- fname += cmake::GetCMakeFilesDirectory();
- fname += "/";
- fname += this->OptionTargetName;
- fname += ".dir/Labels.txt";
+ std::string fname = cmStrCat(this->OptionBuildDir, "/CMakeFiles/",
+ this->OptionTargetName, ".dir/Labels.txt");
// We are interested in per-target labels for this source file.
std::string source = this->OptionSource;
@@ -310,7 +300,7 @@ void cmCTestLaunch::LoadLabels()
if (line[0] == ' ') {
// Label lines appear indented by one space.
if (inTarget || inSource) {
- this->Labels.insert(line.c_str() + 1);
+ this->Labels.insert(line.substr(1));
}
} else if (!this->OptionSource.empty() && !inSource) {
// Non-indented lines specify a source file name. The first one
@@ -342,36 +332,34 @@ bool cmCTestLaunch::IsError() const
void cmCTestLaunch::WriteXML()
{
// Name the xml file.
- std::string logXML = this->LogDir;
- logXML += this->IsError() ? "error-" : "warning-";
- logXML += this->LogHash;
- logXML += ".xml";
+ std::string logXML =
+ cmStrCat(this->LogDir, this->IsError() ? "error-" : "warning-",
+ this->LogHash, ".xml");
// Use cmGeneratedFileStream to atomically create the report file.
- cmGeneratedFileStream fxml(logXML.c_str());
+ cmGeneratedFileStream fxml(logXML);
cmXMLWriter xml(fxml, 2);
- xml.StartElement("Failure");
- xml.Attribute("type", this->IsError() ? "Error" : "Warning");
- this->WriteXMLAction(xml);
- this->WriteXMLCommand(xml);
- this->WriteXMLResult(xml);
- this->WriteXMLLabels(xml);
- xml.EndElement(); // Failure
+ cmXMLElement e2(xml, "Failure");
+ e2.Attribute("type", this->IsError() ? "Error" : "Warning");
+ this->WriteXMLAction(e2);
+ this->WriteXMLCommand(e2);
+ this->WriteXMLResult(e2);
+ this->WriteXMLLabels(e2);
}
-void cmCTestLaunch::WriteXMLAction(cmXMLWriter& xml)
+void cmCTestLaunch::WriteXMLAction(cmXMLElement& e2)
{
- xml.Comment("Meta-information about the build action");
- xml.StartElement("Action");
+ e2.Comment("Meta-information about the build action");
+ cmXMLElement e3(e2, "Action");
// TargetName
if (!this->OptionTargetName.empty()) {
- xml.Element("TargetName", this->OptionTargetName);
+ e3.Element("TargetName", this->OptionTargetName);
}
// Language
if (!this->OptionLanguage.empty()) {
- xml.Element("Language", this->OptionLanguage);
+ e3.Element("Language", this->OptionLanguage);
}
// SourceFile
@@ -380,23 +368,22 @@ 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);
+ e3.Element("SourceFile", source);
}
// OutputFile
if (!this->OptionOutput.empty()) {
- xml.Element("OutputFile", this->OptionOutput);
+ e3.Element("OutputFile", this->OptionOutput);
}
// OutputType
- const char* outputType = CM_NULLPTR;
+ const char* outputType = nullptr;
if (!this->OptionTargetType.empty()) {
if (this->OptionTargetType == "EXECUTABLE") {
outputType = "executable";
@@ -411,106 +398,99 @@ void cmCTestLaunch::WriteXMLAction(cmXMLWriter& xml)
outputType = "object file";
}
if (outputType) {
- xml.Element("OutputType", outputType);
+ e3.Element("OutputType", outputType);
}
-
- xml.EndElement(); // Action
}
-void cmCTestLaunch::WriteXMLCommand(cmXMLWriter& xml)
+void cmCTestLaunch::WriteXMLCommand(cmXMLElement& e2)
{
- xml.Comment("Details of command");
- xml.StartElement("Command");
+ e2.Comment("Details of command");
+ cmXMLElement e3(e2, "Command");
if (!this->CWD.empty()) {
- xml.Element("WorkingDirectory", this->CWD);
+ e3.Element("WorkingDirectory", this->CWD);
}
- for (std::vector<std::string>::const_iterator ai = this->RealArgs.begin();
- ai != this->RealArgs.end(); ++ai) {
- xml.Element("Argument", *ai);
+ for (std::string const& realArg : this->RealArgs) {
+ e3.Element("Argument", realArg);
}
- xml.EndElement(); // Command
}
-void cmCTestLaunch::WriteXMLResult(cmXMLWriter& xml)
+void cmCTestLaunch::WriteXMLResult(cmXMLElement& e2)
{
- xml.Comment("Result of command");
- xml.StartElement("Result");
+ e2.Comment("Result of command");
+ cmXMLElement e3(e2, "Result");
// StdOut
- xml.StartElement("StdOut");
- this->DumpFileToXML(xml, this->LogOut);
- xml.EndElement(); // StdOut
+ this->DumpFileToXML(e3, "StdOut", this->LogOut);
// StdErr
- xml.StartElement("StdErr");
- this->DumpFileToXML(xml, this->LogErr);
- xml.EndElement(); // StdErr
+ this->DumpFileToXML(e3, "StdErr", this->LogErr);
// ExitCondition
- xml.StartElement("ExitCondition");
+ cmXMLElement e4(e3, "ExitCondition");
cmsysProcess* cp = this->Process;
switch (cmsysProcess_GetState(cp)) {
case cmsysProcess_State_Starting:
- xml.Content("No process has been executed");
+ e4.Content("No process has been executed");
break;
case cmsysProcess_State_Executing:
- xml.Content("The process is still executing");
+ e4.Content("The process is still executing");
break;
case cmsysProcess_State_Disowned:
- xml.Content("Disowned");
+ e4.Content("Disowned");
break;
case cmsysProcess_State_Killed:
- xml.Content("Killed by parent");
+ e4.Content("Killed by parent");
break;
case cmsysProcess_State_Expired:
- xml.Content("Killed when timeout expired");
+ e4.Content("Killed when timeout expired");
break;
case cmsysProcess_State_Exited:
- xml.Content(this->ExitCode);
+ e4.Content(this->ExitCode);
break;
case cmsysProcess_State_Exception:
- xml.Content("Terminated abnormally: ");
- xml.Content(cmsysProcess_GetExceptionString(cp));
+ e4.Content("Terminated abnormally: ");
+ e4.Content(cmsysProcess_GetExceptionString(cp));
break;
case cmsysProcess_State_Error:
- xml.Content("Error administrating child process: ");
- xml.Content(cmsysProcess_GetErrorString(cp));
+ e4.Content("Error administrating child process: ");
+ e4.Content(cmsysProcess_GetErrorString(cp));
break;
- };
- xml.EndElement(); // ExitCondition
-
- xml.EndElement(); // Result
+ }
}
-void cmCTestLaunch::WriteXMLLabels(cmXMLWriter& xml)
+void cmCTestLaunch::WriteXMLLabels(cmXMLElement& e2)
{
this->LoadLabels();
if (!this->Labels.empty()) {
- xml.Comment("Interested parties");
- xml.StartElement("Labels");
- for (std::set<std::string>::const_iterator li = this->Labels.begin();
- li != this->Labels.end(); ++li) {
- xml.Element("Label", *li);
+ e2.Comment("Interested parties");
+ cmXMLElement e3(e2, "Labels");
+ for (std::string const& label : this->Labels) {
+ e3.Element("Label", label);
}
- xml.EndElement(); // Labels
}
}
-void cmCTestLaunch::DumpFileToXML(cmXMLWriter& xml, std::string const& fname)
+void cmCTestLaunch::DumpFileToXML(cmXMLElement& e3, const char* tag,
+ std::string const& fname)
{
cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
std::string line;
const char* sep = "";
+ cmXMLElement e4(e3, tag);
while (cmSystemTools::GetLineFromStream(fin, line)) {
if (MatchesFilterPrefix(line)) {
continue;
}
-
- xml.Content(sep);
- xml.Content(line);
+ if (this->Match(line, this->RegexWarningSuppress)) {
+ line = cmStrCat("[CTest: warning suppressed] ", line);
+ } else if (this->Match(line, this->RegexWarning)) {
+ line = cmStrCat("[CTest: warning matched] ", line);
+ }
+ e4.Content(sep);
+ e4.Content(line);
sep = "\n";
}
}
@@ -545,9 +525,9 @@ void cmCTestLaunch::LoadScrapeRules()
// Common compiler warning formats. These are much simpler than the
// full log-scraping expressions because we do not need to extract
// file and line information.
- this->RegexWarning.push_back("(^|[ :])[Ww][Aa][Rr][Nn][Ii][Nn][Gg]");
- this->RegexWarning.push_back("(^|[ :])[Rr][Ee][Mm][Aa][Rr][Kk]");
- this->RegexWarning.push_back("(^|[ :])[Nn][Oo][Tt][Ee]");
+ this->RegexWarning.emplace_back("(^|[ :])[Ww][Aa][Rr][Nn][Ii][Nn][Gg]");
+ this->RegexWarning.emplace_back("(^|[ :])[Rr][Ee][Mm][Aa][Rr][Kk]");
+ this->RegexWarning.emplace_back("(^|[ :])[Nn][Oo][Tt][Ee]");
// Load custom match rules given to us by CTest.
this->LoadScrapeRules("Warning", this->RegexWarning);
@@ -557,15 +537,12 @@ void cmCTestLaunch::LoadScrapeRules()
void cmCTestLaunch::LoadScrapeRules(
const char* purpose, std::vector<cmsys::RegularExpression>& regexps)
{
- std::string fname = this->LogDir;
- fname += "Custom";
- fname += purpose;
- fname += ".txt";
+ std::string fname = cmStrCat(this->LogDir, "Custom", purpose, ".txt");
cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
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);
}
}
@@ -595,9 +572,8 @@ bool cmCTestLaunch::ScrapeLog(std::string const& fname)
bool cmCTestLaunch::Match(std::string const& line,
std::vector<cmsys::RegularExpression>& regexps)
{
- for (std::vector<cmsys::RegularExpression>::iterator ri = regexps.begin();
- ri != regexps.end(); ++ri) {
- if (ri->find(line.c_str())) {
+ for (cmsys::RegularExpression& r : regexps) {
+ if (r.find(line)) {
return true;
}
}
@@ -607,7 +583,7 @@ bool cmCTestLaunch::Match(std::string const& line,
bool cmCTestLaunch::MatchesFilterPrefix(std::string const& line) const
{
return !this->OptionFilterPrefix.empty() &&
- cmSystemTools::StringStartsWith(line, this->OptionFilterPrefix.c_str());
+ cmHasPrefix(line, this->OptionFilterPrefix);
}
int cmCTestLaunch::Main(int argc, const char* const argv[])
@@ -623,17 +599,15 @@ int cmCTestLaunch::Main(int argc, const char* const argv[])
void cmCTestLaunch::LoadConfig()
{
- cmake cm(cmake::RoleScript);
+ cmake cm(cmake::RoleScript, cmState::CTest);
cm.SetHomeDirectory("");
cm.SetHomeOutputDirectory("");
cm.GetCurrentSnapshot().SetDefaultDefinitions();
cmGlobalGenerator gg(&cm);
- CM_AUTO_PTR<cmMakefile> mf(new cmMakefile(&gg, cm.GetCurrentSnapshot()));
- std::string fname = this->LogDir;
- fname += "CTestLaunchConfig.cmake";
- if (cmSystemTools::FileExists(fname.c_str()) &&
- mf->ReadListFile(fname.c_str())) {
- this->SourceDir = mf->GetSafeDefinition("CTEST_SOURCE_DIRECTORY");
+ cmMakefile mf(&gg, cm.GetCurrentSnapshot());
+ std::string fname = cmStrCat(this->LogDir, "CTestLaunchConfig.cmake");
+ if (cmSystemTools::FileExists(fname) && mf.ReadListFile(fname)) {
+ this->SourceDir = mf.GetSafeDefinition("CTEST_SOURCE_DIRECTORY");
cmSystemTools::ConvertToUnixSlashes(this->SourceDir);
}
}
diff --git a/Source/CTest/cmCTestLaunch.h b/Source/CTest/cmCTestLaunch.h
index 29986ff60..79a7712aa 100644
--- a/Source/CTest/cmCTestLaunch.h
+++ b/Source/CTest/cmCTestLaunch.h
@@ -5,12 +5,13 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmsys/RegularExpression.hxx"
#include <set>
#include <string>
#include <vector>
-class cmXMLWriter;
+#include "cmsys/RegularExpression.hxx"
+
+class cmXMLElement;
/** \class cmCTestLaunch
* \brief Launcher for make rules to report results for ctest
@@ -28,6 +29,9 @@ private:
cmCTestLaunch(int argc, const char* const* argv);
~cmCTestLaunch();
+ cmCTestLaunch(const cmCTestLaunch&) = delete;
+ cmCTestLaunch& operator=(const cmCTestLaunch&) = delete;
+
// Run the real command.
int Run();
void RunChild();
@@ -89,11 +93,11 @@ private:
// Methods to generate the xml fragment.
void WriteXML();
- void WriteXMLAction(cmXMLWriter& xml);
- void WriteXMLCommand(cmXMLWriter& xml);
- void WriteXMLResult(cmXMLWriter& xml);
- void WriteXMLLabels(cmXMLWriter& xml);
- void DumpFileToXML(cmXMLWriter& xml, std::string const& fname);
+ void WriteXMLAction(cmXMLElement&);
+ void WriteXMLCommand(cmXMLElement&);
+ void WriteXMLResult(cmXMLElement&);
+ void WriteXMLLabels(cmXMLElement&);
+ void DumpFileToXML(cmXMLElement&, const char* tag, std::string const& fname);
// Configuration
void LoadConfig();
diff --git a/Source/CTest/cmCTestMemCheckCommand.cxx b/Source/CTest/cmCTestMemCheckCommand.cxx
index b9cae3bfe..39dec6d87 100644
--- a/Source/CTest/cmCTestMemCheckCommand.cxx
+++ b/Source/CTest/cmCTestMemCheckCommand.cxx
@@ -2,26 +2,22 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestMemCheckCommand.h"
-#include <sstream>
-#include <string>
-#include <vector>
+#include "cm_static_string_view.hxx"
#include "cmCTest.h"
-#include "cmCTestGenericHandler.h"
#include "cmCTestMemCheckHandler.h"
#include "cmMakefile.h"
-cmCTestMemCheckCommand::cmCTestMemCheckCommand()
+void cmCTestMemCheckCommand::BindArguments()
{
- this->Arguments[ctm_DEFECT_COUNT] = "DEFECT_COUNT";
- this->Arguments[ctm_LAST] = CM_NULLPTR;
- this->Last = ctm_LAST;
+ this->cmCTestTestCommand::BindArguments();
+ this->Bind("DEFECT_COUNT"_s, this->DefectCount);
}
cmCTestGenericHandler* cmCTestMemCheckCommand::InitializeActualHandler()
{
- cmCTestGenericHandler* handler =
- this->CTest->GetInitializedHandler("memcheck");
+ cmCTestMemCheckHandler* handler = this->CTest->GetMemCheckHandler();
+ handler->Initialize();
this->CTest->SetCTestConfigurationFromCMakeVariable(
this->Makefile, "MemoryCheckType", "CTEST_MEMORYCHECK_TYPE", this->Quiet);
@@ -45,10 +41,10 @@ cmCTestGenericHandler* cmCTestMemCheckCommand::InitializeActualHandler()
void cmCTestMemCheckCommand::ProcessAdditionalValues(
cmCTestGenericHandler* handler)
{
- if (this->Values[ctm_DEFECT_COUNT] && *this->Values[ctm_DEFECT_COUNT]) {
- std::ostringstream str;
- str << static_cast<cmCTestMemCheckHandler*>(handler)->GetDefectCount();
- this->Makefile->AddDefinition(this->Values[ctm_DEFECT_COUNT],
- str.str().c_str());
+ if (!this->DefectCount.empty()) {
+ this->Makefile->AddDefinition(
+ this->DefectCount,
+ std::to_string(
+ static_cast<cmCTestMemCheckHandler*>(handler)->GetDefectCount()));
}
}
diff --git a/Source/CTest/cmCTestMemCheckCommand.h b/Source/CTest/cmCTestMemCheckCommand.h
index fa595594a..8f4ffb89a 100644
--- a/Source/CTest/cmCTestMemCheckCommand.h
+++ b/Source/CTest/cmCTestMemCheckCommand.h
@@ -3,12 +3,17 @@
#ifndef cmCTestMemCheckCommand_h
#define cmCTestMemCheckCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <utility>
+
+#include <cm/memory>
#include "cmCTestTestCommand.h"
+#include "cmCommand.h"
class cmCTestGenericHandler;
-class cmCommand;
/** \class cmCTestMemCheck
* \brief Run a ctest script
@@ -18,29 +23,25 @@ class cmCommand;
class cmCTestMemCheckCommand : public cmCTestTestCommand
{
public:
- cmCTestMemCheckCommand();
-
/**
* This is a virtual constructor for the command.
*/
- cmCommand* Clone() CM_OVERRIDE
+ std::unique_ptr<cmCommand> Clone() override
{
- cmCTestMemCheckCommand* ni = new cmCTestMemCheckCommand;
+ auto ni = cm::make_unique<cmCTestMemCheckCommand>();
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
- return ni;
+ return std::unique_ptr<cmCommand>(std::move(ni));
}
protected:
- cmCTestGenericHandler* InitializeActualHandler() CM_OVERRIDE;
+ void BindArguments() override;
- void ProcessAdditionalValues(cmCTestGenericHandler* handler) CM_OVERRIDE;
+ cmCTestGenericHandler* InitializeActualHandler() override;
- enum
- {
- ctm_DEFECT_COUNT = ctt_LAST,
- ctm_LAST
- };
+ void ProcessAdditionalValues(cmCTestGenericHandler* handler) override;
+
+ std::string DefectCount;
};
#endif
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index c35f0bc70..a5ec1ae81 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -2,17 +2,21 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestMemCheckHandler.h"
-#include "cmCTest.h"
-#include "cmSystemTools.h"
-#include "cmXMLParser.h"
-#include "cmXMLWriter.h"
+#include <chrono>
+#include <cstring>
+#include <iostream>
+#include <sstream>
+#include <utility>
#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"
-#include <iostream>
-#include <sstream>
-#include <string.h>
+
+#include "cmCTest.h"
+#include "cmDuration.h"
+#include "cmSystemTools.h"
+#include "cmXMLParser.h"
+#include "cmXMLWriter.h"
struct CatToErrorType
{
@@ -28,14 +32,15 @@ static CatToErrorType cmCTestMemCheckBoundsChecker[] = {
{ "Allocation Conflict", cmCTestMemCheckHandler::FMM },
{ "Bad Pointer Use", cmCTestMemCheckHandler::FMW },
{ "Dangling Pointer", cmCTestMemCheckHandler::FMR },
- { CM_NULLPTR, 0 }
+ { nullptr, 0 }
};
static void xmlReportError(int line, const char* msg, void* data)
{
- cmCTest* ctest = (cmCTest*)data;
- cmCTestLog(ctest, ERROR_MESSAGE, "Error parsing XML in stream at line "
- << line << ": " << msg << std::endl);
+ cmCTest* ctest = static_cast<cmCTest*>(data);
+ cmCTestLog(ctest, ERROR_MESSAGE,
+ "Error parsing XML in stream at line " << line << ": " << msg
+ << std::endl);
}
// parse the xml file containing the results of last BoundsChecker run
@@ -45,9 +50,9 @@ public:
cmBoundsCheckerParser(cmCTest* c)
{
this->CTest = c;
- this->SetErrorCallback(xmlReportError, (void*)c);
+ this->SetErrorCallback(xmlReportError, c);
}
- void StartElement(const std::string& name, const char** atts) CM_OVERRIDE
+ void StartElement(const std::string& name, const char** atts) override
{
if (name == "MemoryLeak" || name == "ResourceLeak") {
this->Errors.push_back(cmCTestMemCheckHandler::MLK);
@@ -58,23 +63,23 @@ public:
std::ostringstream ostr;
ostr << name << ":\n";
int i = 0;
- for (; atts[i] != CM_NULLPTR; i += 2) {
+ for (; atts[i] != nullptr; i += 2) {
ostr << " " << atts[i] << " - " << atts[i + 1] << "\n";
}
ostr << "\n";
this->Log += ostr.str();
}
- void EndElement(const std::string& /*name*/) CM_OVERRIDE {}
+ void EndElement(const std::string& /*name*/) override {}
const char* GetAttribute(const char* name, const char** atts)
{
int i = 0;
- for (; atts[i] != CM_NULLPTR; ++i) {
+ for (; atts[i] != nullptr; ++i) {
if (strcmp(name, atts[i]) == 0) {
return atts[i + 1];
}
}
- return CM_NULLPTR;
+ return nullptr;
}
void ParseError(const char** atts)
{
@@ -122,11 +127,11 @@ void cmCTestMemCheckHandler::Initialize()
this->LogWithPID = false;
this->CustomMaximumPassedTestOutputSize = 0;
this->CustomMaximumFailedTestOutputSize = 0;
- this->MemoryTester = "";
+ this->MemoryTester.clear();
this->MemoryTesterDynamicOptions.clear();
this->MemoryTesterOptions.clear();
this->MemoryTesterStyle = UNKNOWN;
- this->MemoryTesterOutputFile = "";
+ this->MemoryTesterOutputFile.clear();
this->DefectCount = 0;
}
@@ -157,15 +162,13 @@ int cmCTestMemCheckHandler::PostProcessHandler()
void cmCTestMemCheckHandler::GenerateTestCommand(
std::vector<std::string>& args, int test)
{
- std::vector<std::string>::size_type pp;
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 (pp = 0; pp < this->MemoryTesterDynamicOptions.size(); pp++) {
- std::string arg = this->MemoryTesterDynamicOptions[pp];
+ for (std::string arg : this->MemoryTesterDynamicOptions) {
std::string::size_type pos = arg.find("??");
if (pos != std::string::npos) {
arg.replace(pos, 2, index);
@@ -177,21 +180,21 @@ 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 (pp = 0; pp < this->MemoryTesterOptions.size(); pp++) {
+ for (std::string const& arg : this->MemoryTesterOptions) {
if (!memTesterEnvironmentVariable.empty()) {
// If we are using env to pass options, append all the options to
// this string with space separation.
- memTesterEnvironmentVariable += " " + this->MemoryTesterOptions[pp];
+ memTesterEnvironmentVariable += " " + arg;
}
// for regular options just add them to args and memcheckcommand
// which is just used for display
else {
- args.push_back(this->MemoryTesterOptions[pp]);
+ args.push_back(arg);
memcheckcommand += " \"";
- memcheckcommand += this->MemoryTesterOptions[pp];
+ memcheckcommand += arg;
memcheckcommand += "\"";
}
}
@@ -228,9 +231,9 @@ void cmCTestMemCheckHandler::InitializeResultsVectors()
// define the standard set of errors
//----------------------------------------------------------------------
static const char* cmCTestMemCheckResultStrings[] = {
- "ABR", "ABW", "ABWL", "COR", "EXU", "FFM", "FIM", "FMM",
- "FMR", "FMW", "FUM", "IPR", "IPW", "MAF", "MLK", "MPK",
- "NPR", "ODS", "PAR", "PLK", "UMC", "UMR", CM_NULLPTR
+ "ABR", "ABW", "ABWL", "COR", "EXU", "FFM", "FIM", "FMM",
+ "FMR", "FMW", "FUM", "IPR", "IPW", "MAF", "MLK", "MPK",
+ "NPR", "ODS", "PAR", "PLK", "UMC", "UMR", nullptr
};
static const char* cmCTestMemCheckResultLongStrings[] = {
"Threading Problem",
@@ -255,12 +258,12 @@ void cmCTestMemCheckHandler::InitializeResultsVectors()
"PLK",
"Uninitialized Memory Conditional",
"Uninitialized Memory Read",
- CM_NULLPTR
+ nullptr
};
this->GlobalResults.clear();
- for (int i = 0; cmCTestMemCheckResultStrings[i] != CM_NULLPTR; ++i) {
- this->ResultStrings.push_back(cmCTestMemCheckResultStrings[i]);
- this->ResultStringsLong.push_back(cmCTestMemCheckResultLongStrings[i]);
+ for (int i = 0; cmCTestMemCheckResultStrings[i] != nullptr; ++i) {
+ this->ResultStrings.emplace_back(cmCTestMemCheckResultStrings[i]);
+ this->ResultStringsLong.emplace_back(cmCTestMemCheckResultLongStrings[i]);
this->GlobalResults.push_back(0);
}
}
@@ -291,6 +294,7 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml)
return;
}
this->CTest->StartXML(xml, this->AppendXML);
+ this->CTest->GenerateSubprojectsOutput(xml);
xml.StartElement("DynamicAnalysis");
switch (this->MemoryTesterStyle) {
case cmCTestMemCheckHandler::VALGRIND:
@@ -325,9 +329,8 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml)
xml.Element("StartTestTime", this->StartTestTime);
xml.StartElement("TestList");
cmCTestMemCheckHandler::TestResultsVector::size_type cc;
- for (cc = 0; cc < this->TestResults.size(); cc++) {
- cmCTestTestResult* result = &this->TestResults[cc];
- std::string testPath = result->Path + "/" + result->Name;
+ for (cmCTestTestResult const& result : this->TestResults) {
+ std::string testPath = result.Path + "/" + result.Name;
xml.Element("Test", this->CTest->GetShortPathToFile(testPath.c_str()));
}
xml.EndElement(); // TestList
@@ -335,12 +338,12 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml)
"-- Processing memory checking output:\n", this->Quiet);
size_t total = this->TestResults.size();
for (cc = 0; cc < this->TestResults.size(); cc++) {
- cmCTestTestResult* result = &this->TestResults[cc];
+ cmCTestTestResult const& result = this->TestResults[cc];
std::string memcheckstr;
std::vector<int> memcheckresults(this->ResultStrings.size(), 0);
- bool res = this->ProcessMemCheckOutput(result->Output, memcheckstr,
- memcheckresults);
- if (res && result->Status == cmCTestMemCheckHandler::COMPLETED) {
+ bool res =
+ this->ProcessMemCheckOutput(result.Output, memcheckstr, memcheckresults);
+ if (res && result.Status == cmCTestMemCheckHandler::COMPLETED) {
continue;
}
this->CleanTestOutput(
@@ -363,12 +366,12 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml)
xml.EndElement(); // Results
if (memoryErrors > 0) {
const int maxTestNameWidth = this->CTest->GetMaxTestNameWidth();
- std::string outname = result->Name + " ";
+ std::string outname = result.Name + " ";
outname.resize(maxTestNameWidth + 4, '.');
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, cc + 1
- << "/" << total << " MemCheck: #"
- << result->TestCount << ": " << outname
- << " Defects: " << memoryErrors << std::endl,
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ cc + 1 << "/" << total << " MemCheck: #"
+ << result.TestCount << ": " << outname
+ << " Defects: " << memoryErrors << std::endl,
this->Quiet);
}
xml.StartElement("Log");
@@ -410,8 +413,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);
@@ -419,11 +424,11 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml)
bool cmCTestMemCheckHandler::InitializeMemoryChecking()
{
- this->MemoryTesterEnvironmentVariable = "";
- this->MemoryTester = "";
+ this->MemoryTesterEnvironmentVariable.clear();
+ 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 =
@@ -440,17 +445,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;
@@ -518,7 +521,7 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
this->CTest->GetCTestConfiguration("ValgrindCommandOptions");
}
this->MemoryTesterOptions =
- cmSystemTools::ParseArguments(memoryTesterOptions.c_str());
+ cmSystemTools::ParseArguments(memoryTesterOptions);
this->MemoryTesterOutputFile =
this->CTest->GetBinaryDir() + "/Testing/Temporary/MemoryChecker.??.log";
@@ -526,17 +529,16 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
switch (this->MemoryTesterStyle) {
case cmCTestMemCheckHandler::VALGRIND: {
if (this->MemoryTesterOptions.empty()) {
- this->MemoryTesterOptions.push_back("-q");
- this->MemoryTesterOptions.push_back("--tool=memcheck");
- this->MemoryTesterOptions.push_back("--leak-check=yes");
- this->MemoryTesterOptions.push_back("--show-reachable=yes");
- this->MemoryTesterOptions.push_back("--num-callers=50");
+ this->MemoryTesterOptions.emplace_back("-q");
+ this->MemoryTesterOptions.emplace_back("--tool=memcheck");
+ this->MemoryTesterOptions.emplace_back("--leak-check=yes");
+ this->MemoryTesterOptions.emplace_back("--show-reachable=yes");
+ this->MemoryTesterOptions.emplace_back("--num-callers=50");
}
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(
@@ -544,12 +546,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: {
@@ -557,9 +559,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: "
@@ -586,11 +587,11 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
std::string dpbdFile = this->CTest->GetBinaryDir() +
"/Testing/Temporary/MemoryChecker.??.DPbd";
this->BoundsCheckerDPBDFile = dpbdFile;
- this->MemoryTesterDynamicOptions.push_back("/B");
- this->MemoryTesterDynamicOptions.push_back(dpbdFile);
- this->MemoryTesterDynamicOptions.push_back("/X");
+ this->MemoryTesterDynamicOptions.emplace_back("/B");
+ this->MemoryTesterDynamicOptions.push_back(std::move(dpbdFile));
+ this->MemoryTesterDynamicOptions.emplace_back("/X");
this->MemoryTesterDynamicOptions.push_back(this->MemoryTesterOutputFile);
- this->MemoryTesterOptions.push_back("/M");
+ this->MemoryTesterOptions.emplace_back("/M");
break;
}
// these are almost the same but the env var used is different
@@ -604,8 +605,8 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
// The MemoryTesterDynamicOptions is setup with the -E env
// Then the MemoryTesterEnvironmentVariable gets the
// TSAN_OPTIONS string with the log_path in it.
- this->MemoryTesterDynamicOptions.push_back("-E");
- this->MemoryTesterDynamicOptions.push_back("env");
+ this->MemoryTesterDynamicOptions.emplace_back("-E");
+ this->MemoryTesterDynamicOptions.emplace_back("env");
std::string envVar;
std::string extraOptions;
std::string suppressionsOption;
@@ -725,15 +726,14 @@ bool cmCTestMemCheckHandler::ProcessMemCheckSanitizerOutput(
cmsys::RegularExpression leakWarning("(Direct|Indirect) leak of .*");
int defects = 0;
std::vector<std::string> lines;
- cmSystemTools::Split(str.c_str(), lines);
+ cmsys::SystemTools::Split(str, lines);
std::ostringstream ostr;
- log = "";
- for (std::vector<std::string>::iterator i = lines.begin(); i != lines.end();
- ++i) {
+ log.clear();
+ for (std::string const& l : lines) {
std::string resultFound;
- if (leakWarning.find(*i)) {
+ if (leakWarning.find(l)) {
resultFound = leakWarning.match(1) + " leak";
- } else if (sanitizerWarning.find(*i)) {
+ } else if (sanitizerWarning.find(l)) {
resultFound = sanitizerWarning.match(1);
}
if (!resultFound.empty()) {
@@ -746,7 +746,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckSanitizerOutput(
defects++;
ostr << "<b>" << this->ResultStrings[idx] << "</b> ";
}
- ostr << *i << std::endl;
+ ostr << l << std::endl;
}
log = ostr.str();
this->DefectCount += defects;
@@ -756,18 +756,17 @@ bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput(
const std::string& str, std::string& log, std::vector<int>& results)
{
std::vector<std::string> lines;
- cmSystemTools::Split(str.c_str(), lines);
+ cmsys::SystemTools::Split(str, lines);
std::ostringstream ostr;
- log = "";
+ log.clear();
cmsys::RegularExpression pfW("^\\[[WEI]\\] ([A-Z][A-Z][A-Z][A-Z]*): ");
int defects = 0;
- for (std::vector<std::string>::iterator i = lines.begin(); i != lines.end();
- ++i) {
+ for (std::string const& l : lines) {
std::vector<int>::size_type failure = this->ResultStrings.size();
- if (pfW.find(*i)) {
+ if (pfW.find(l)) {
std::vector<int>::size_type cc;
for (cc = 0; cc < this->ResultStrings.size(); cc++) {
if (pfW.match(1) == this->ResultStrings[cc]) {
@@ -776,8 +775,9 @@ bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput(
}
}
if (cc == this->ResultStrings.size()) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown Purify memory fault: "
- << pfW.match(1) << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown Purify memory fault: " << pfW.match(1)
+ << std::endl);
ostr << "*** Unknown Purify memory fault: " << pfW.match(1)
<< std::endl;
}
@@ -787,7 +787,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckPurifyOutput(
results[failure]++;
defects++;
}
- ostr << *i << std::endl;
+ ostr << l << std::endl;
}
log = ostr.str();
@@ -799,7 +799,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
const std::string& str, std::string& log, std::vector<int>& results)
{
std::vector<std::string> lines;
- cmSystemTools::Split(str.c_str(), lines);
+ cmsys::SystemTools::Split(str, lines);
bool unlimitedOutput = false;
if (str.find("CTEST_FULL_OUTPUT") != std::string::npos ||
this->CustomMaximumFailedTestOutputSize == 0) {
@@ -809,16 +809,16 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
std::string::size_type cc;
std::ostringstream ostr;
- log = "";
+ log.clear();
int defects = 0;
cmsys::RegularExpression valgrindLine("^==[0-9][0-9]*==");
cmsys::RegularExpression vgFIM(
- "== .*Invalid free\\(\\) / delete / delete\\[\\]");
+ R"(== .*Invalid free\(\) / delete / delete\[\])");
cmsys::RegularExpression vgFMM(
- "== .*Mismatched free\\(\\) / delete / delete \\[\\]");
+ R"(== .*Mismatched free\(\) / delete / delete \[\])");
cmsys::RegularExpression vgMLK1(
"== .*[0-9,]+ bytes in [0-9,]+ blocks are definitely lost"
" in loss record [0-9,]+ of [0-9,]+");
@@ -848,7 +848,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;
@@ -907,11 +907,9 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
// Now put all all the non valgrind output into the test output
// This should be last in case it gets truncated by the output
// limiting code
- for (std::vector<std::string::size_type>::iterator i =
- nonValGrindOutput.begin();
- i != nonValGrindOutput.end(); ++i) {
- totalOutputSize += lines[*i].size();
- ostr << lines[*i] << std::endl;
+ for (std::string::size_type i : nonValGrindOutput) {
+ totalOutputSize += lines[i].size();
+ ostr << lines[i] << std::endl;
if (!unlimitedOutput &&
totalOutputSize >
static_cast<size_t>(this->CustomMaximumFailedTestOutputSize)) {
@@ -923,8 +921,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,
+ 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;
@@ -934,10 +935,10 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput(
const std::string& str, std::string& log, std::vector<int>& results)
{
- log = "";
- double sttime = cmSystemTools::GetTime();
+ log.clear();
+ auto sttime = std::chrono::steady_clock::now();
std::vector<std::string> lines;
- cmSystemTools::Split(str.c_str(), lines);
+ cmsys::SystemTools::Split(str, lines);
cmCTestOptionalLog(this->CTest, DEBUG,
"Start test: " << lines.size() << std::endl, this->Quiet);
std::vector<std::string>::size_type cc;
@@ -962,12 +963,15 @@ bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput(
}
}
int defects = 0;
- for (cc = 0; cc < parser.Errors.size(); ++cc) {
- results[parser.Errors[cc]]++;
+ for (int err : parser.Errors) {
+ results[err]++;
defects++;
}
- cmCTestOptionalLog(this->CTest, DEBUG, "End test (elapsed: "
- << (cmSystemTools::GetTime() - sttime) << std::endl,
+ 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
@@ -990,9 +994,8 @@ void cmCTestMemCheckHandler::PostProcessTest(cmCTestTestResult& res, int test)
} else {
std::vector<std::string> files;
this->TestOutputFileNames(test, files);
- for (std::vector<std::string>::iterator i = files.begin();
- i != files.end(); ++i) {
- this->AppendMemTesterOutput(res, *i);
+ for (std::string const& f : files) {
+ this->AppendMemTesterOutput(res, f);
}
}
}
@@ -1072,10 +1075,7 @@ void cmCTestMemCheckHandler::AppendMemTesterOutput(cmCTestTestResult& res,
void cmCTestMemCheckHandler::TestOutputFileNames(
int test, std::vector<std::string>& files)
{
- std::string index;
- std::ostringstream stream;
- stream << test;
- index = stream.str();
+ std::string index = std::to_string(test);
std::string ofile = this->MemoryTesterOutputFile;
std::string::size_type pos = ofile.find("??");
ofile.replace(pos, 2, index);
@@ -1085,16 +1085,16 @@ void cmCTestMemCheckHandler::TestOutputFileNames(
g.FindFiles(ofile);
if (g.GetFiles().empty()) {
std::string log = "Cannot find memory tester output file: " + ofile;
- cmCTestLog(this->CTest, ERROR_MESSAGE, log << std::endl);
- ofile = "";
+ cmCTestLog(this->CTest, WARNING, log << std::endl);
+ ofile.clear();
} else {
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 = "";
+ cmCTestLog(this->CTest, WARNING, log << std::endl);
+ ofile.clear();
}
- files.push_back(ofile);
+ files.push_back(std::move(ofile));
}
diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h
index 333c2e2dd..eda65f7b9 100644
--- a/Source/CTest/cmCTestMemCheckHandler.h
+++ b/Source/CTest/cmCTestMemCheckHandler.h
@@ -3,13 +3,13 @@
#ifndef cmCTestMemCheckHandler_h
#define cmCTestMemCheckHandler_h
-#include "cmConfigure.h"
-
-#include "cmCTestTestHandler.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
+#include "cmCTestTestHandler.h"
+
class cmMakefile;
class cmXMLWriter;
@@ -22,21 +22,20 @@ class cmCTestMemCheckHandler : public cmCTestTestHandler
friend class cmCTestRunTest;
public:
- typedef cmCTestTestHandler Superclass;
+ using Superclass = cmCTestTestHandler;
- void PopulateCustomVectors(cmMakefile* mf) CM_OVERRIDE;
+ void PopulateCustomVectors(cmMakefile* mf) override;
cmCTestMemCheckHandler();
- void Initialize() CM_OVERRIDE;
+ void Initialize() override;
int GetDefectCount();
protected:
- int PreProcessHandler() CM_OVERRIDE;
- int PostProcessHandler() CM_OVERRIDE;
- void GenerateTestCommand(std::vector<std::string>& args,
- int test) CM_OVERRIDE;
+ int PreProcessHandler() override;
+ int PostProcessHandler() override;
+ void GenerateTestCommand(std::vector<std::string>& args, int test) override;
private:
enum
@@ -115,20 +114,20 @@ private:
// this type of checker
void InitializeResultsVectors();
- ///! Initialize memory checking subsystem.
+ //! Initialize memory checking subsystem.
bool InitializeMemoryChecking();
/**
* Generate the Dart compatible output
*/
- void GenerateDartOutput(cmXMLWriter& xml) CM_OVERRIDE;
+ void GenerateDartOutput(cmXMLWriter& xml) override;
std::vector<std::string> CustomPreMemCheck;
std::vector<std::string> CustomPostMemCheck;
//! Parse Valgrind/Purify/Bounds Checker result out of the output
// string. After running, log holds the output and results hold the
- // different memmory errors.
+ // different memory errors.
bool ProcessMemCheckOutput(const std::string& str, std::string& log,
std::vector<int>& results);
bool ProcessMemCheckValgrindOutput(const std::string& str, std::string& log,
@@ -144,11 +143,11 @@ private:
void PostProcessTest(cmCTestTestResult& res, int test);
void PostProcessBoundsCheckerTest(cmCTestTestResult& res, int test);
- ///! append MemoryTesterOutputFile to the test log
+ //! append MemoryTesterOutputFile to the test log
void AppendMemTesterOutput(cmCTestTestHandler::cmCTestTestResult& res,
std::string const& filename);
- ///! generate the output filename for the given test index
+ //! generate the output filename for the given test index
void TestOutputFileNames(int test, std::vector<std::string>& files);
};
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 2c16a0d1e..02d396ebd 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -2,24 +2,47 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestMultiProcessHandler.h"
-#include "cmCTest.h"
-#include "cmCTestRunTest.h"
-#include "cmCTestScriptHandler.h"
-#include "cmCTestTestHandler.h"
-#include "cmSystemTools.h"
-#include "cmWorkingDirectory.h"
-
-#include "cmsys/FStream.hxx"
-#include "cmsys/String.hxx"
-#include "cmsys/SystemInformation.hxx"
#include <algorithm>
+#include <cassert>
+#include <chrono>
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
#include <iomanip>
+#include <iostream>
#include <list>
-#include <math.h>
+#include <memory>
#include <sstream>
#include <stack>
-#include <stdlib.h>
+#include <unordered_map>
#include <utility>
+#include <vector>
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/SystemInformation.hxx"
+
+#include "cm_jsoncpp_value.h"
+#include "cm_jsoncpp_writer.h"
+#include "cm_uv.h"
+
+#include "cmAffinity.h"
+#include "cmAlgorithms.h"
+#include "cmCTest.h"
+#include "cmCTestBinPacker.h"
+#include "cmCTestRunTest.h"
+#include "cmCTestTestHandler.h"
+#include "cmDuration.h"
+#include "cmListFileCache.h"
+#include "cmRange.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmUVSignalHackRAII.h" // IWYU pragma: keep
+#include "cmWorkingDirectory.h"
+
+namespace cmsys {
+class RegularExpression;
+}
class TestComparator
{
@@ -28,7 +51,6 @@ public:
: Handler(handler)
{
}
- ~TestComparator() {}
// Sorts tests in descending order of cost
bool operator()(int index1, int index2) const
@@ -45,16 +67,16 @@ cmCTestMultiProcessHandler::cmCTestMultiProcessHandler()
{
this->ParallelLevel = 1;
this->TestLoad = 0;
+ this->FakeLoadForTesting = 0;
this->Completed = 0;
this->RunningCount = 0;
- this->StopTimePassed = false;
+ this->ProcessorsAvailable = cmAffinity::GetProcessorsAvailable();
+ this->HaveAffinity = this->ProcessorsAvailable.size();
this->HasCycles = false;
this->SerialTestRunning = false;
}
-cmCTestMultiProcessHandler::~cmCTestMultiProcessHandler()
-{
-}
+cmCTestMultiProcessHandler::~cmCTestMultiProcessHandler() = default;
// Set the tests
void cmCTestMultiProcessHandler::SetTests(TestMap& tests,
@@ -64,10 +86,9 @@ void cmCTestMultiProcessHandler::SetTests(TestMap& tests,
this->Properties = properties;
this->Total = this->Tests.size();
// set test run map to false for all
- for (TestMap::iterator i = this->Tests.begin(); i != this->Tests.end();
- ++i) {
- this->TestRunningMap[i->first] = false;
- this->TestFinishMap[i->first] = false;
+ for (auto const& t : this->Tests) {
+ this->TestRunningMap[t.first] = false;
+ this->TestFinishMap[t.first] = false;
}
if (!this->CTest->GetShowOnly()) {
this->ReadCostData();
@@ -88,6 +109,15 @@ void cmCTestMultiProcessHandler::SetParallelLevel(size_t level)
void cmCTestMultiProcessHandler::SetTestLoad(unsigned long load)
{
this->TestLoad = load;
+
+ std::string fake_load_value;
+ if (cmSystemTools::GetEnv("__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING",
+ fake_load_value)) {
+ if (!cmStrToULong(fake_load_value, &this->FakeLoadForTesting)) {
+ cmSystemTools::Error("Failed to parse fake load value: " +
+ fake_load_value);
+ }
+ }
}
void cmCTestMultiProcessHandler::RunTests()
@@ -96,24 +126,43 @@ 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);
+
+ if (!this->StopTimePassed) {
+ assert(this->Completed == this->Total);
+ assert(this->Tests.empty());
}
+ assert(this->AllResourcesAvailable());
+
this->MarkFinished();
this->UpdateCostData();
}
-void cmCTestMultiProcessHandler::StartTestProcess(int test)
+bool cmCTestMultiProcessHandler::StartTestProcess(int test)
{
+ if (this->HaveAffinity && this->Properties[test]->WantAffinity) {
+ size_t needProcessors = this->GetProcessorsUsed(test);
+ if (needProcessors > this->ProcessorsAvailable.size()) {
+ return false;
+ }
+ std::vector<size_t> affinity;
+ affinity.reserve(needProcessors);
+ for (size_t i = 0; i < needProcessors; ++i) {
+ auto p = this->ProcessorsAvailable.begin();
+ affinity.push_back(*p);
+ this->ProcessorsAvailable.erase(p);
+ }
+ this->Properties[test]->Affinity = std::move(affinity);
+ }
+
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"test " << test << "\n", this->Quiet);
this->TestRunningMap[test] = true; // mark the test as running
@@ -121,52 +170,179 @@ 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());
}
testRun->SetIndex(test);
testRun->SetTestProperties(this->Properties[test]);
+ if (this->TestHandler->UseResourceSpec) {
+ testRun->SetUseAllocatedResources(true);
+ testRun->SetAllocatedResources(this->AllocatedResources[test]);
+ }
// Find any failed dependencies for this test. We assume the more common
// scenario has no failed tests, so make it the outer loop.
- for (std::vector<std::string>::const_iterator it = this->Failed->begin();
- it != this->Failed->end(); ++it) {
- if (this->Properties[test]->RequireSuccessDepends.find(*it) !=
- this->Properties[test]->RequireSuccessDepends.end()) {
- testRun->AddFailedDependency(*it);
+ for (std::string const& f : *this->Failed) {
+ if (cmContains(this->Properties[test]->RequireSuccessDepends, f)) {
+ testRun->AddFailedDependency(f);
}
}
+ // Always lock the resources we'll be using, even if we fail to set the
+ // working directory because FinishTestProcess() will try to unlock them
+ this->LockResources(test);
+
+ if (!this->TestsHaveSufficientResources[test]) {
+ testRun->StartFailure("Insufficient resources");
+ this->FinishTestProcess(testRun, false);
+ return false;
+ }
+
cmWorkingDirectory workdir(this->Properties[test]->Directory);
+ if (workdir.Failed()) {
+ testRun->StartFailure("Failed to change working directory to " +
+ this->Properties[test]->Directory + " : " +
+ std::strerror(workdir.GetLastResult()));
+ } else {
+ if (testRun->StartTest(this->Completed, this->Total)) {
+ // Ownership of 'testRun' has moved to another structure.
+ // When the test finishes, FinishTestProcess will be called.
+ return true;
+ }
+ }
- // Lock the resources we'll be using
- this->LockResources(test);
+ // Pass ownership of 'testRun'.
+ this->FinishTestProcess(testRun, false);
+ return false;
+}
- if (testRun->StartTest(this->Total)) {
- this->RunningTests.insert(testRun);
- } else if (testRun->IsStopTimePassed()) {
- this->StopTimePassed = true;
- delete testRun;
+bool cmCTestMultiProcessHandler::AllocateResources(int index)
+{
+ if (!this->TestHandler->UseResourceSpec) {
+ return true;
+ }
+
+ std::map<std::string, std::vector<cmCTestBinPackerAllocation>> allocations;
+ if (!this->TryAllocateResources(index, allocations)) {
+ return false;
+ }
+
+ auto& allocatedResources = this->AllocatedResources[index];
+ allocatedResources.resize(this->Properties[index]->ResourceGroups.size());
+ for (auto const& it : allocations) {
+ for (auto const& alloc : it.second) {
+ bool result = this->ResourceAllocator.AllocateResource(
+ it.first, alloc.Id, alloc.SlotsNeeded);
+ (void)result;
+ assert(result);
+ allocatedResources[alloc.ProcessIndex][it.first].push_back(
+ { alloc.Id, static_cast<unsigned int>(alloc.SlotsNeeded) });
+ }
+ }
+
+ return true;
+}
+
+bool cmCTestMultiProcessHandler::TryAllocateResources(
+ int index,
+ std::map<std::string, std::vector<cmCTestBinPackerAllocation>>& allocations)
+{
+ allocations.clear();
+
+ std::size_t processIndex = 0;
+ for (auto const& process : this->Properties[index]->ResourceGroups) {
+ for (auto const& requirement : process) {
+ for (int i = 0; i < requirement.UnitsNeeded; ++i) {
+ allocations[requirement.ResourceType].push_back(
+ { processIndex, requirement.SlotsNeeded, "" });
+ }
+ }
+ ++processIndex;
+ }
+
+ auto const& availableResources = this->ResourceAllocator.GetResources();
+ for (auto& it : allocations) {
+ if (!availableResources.count(it.first)) {
+ return false;
+ }
+ if (!cmAllocateCTestResourcesRoundRobin(availableResources.at(it.first),
+ it.second)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void cmCTestMultiProcessHandler::DeallocateResources(int index)
+{
+ if (!this->TestHandler->UseResourceSpec) {
return;
- } else {
+ }
- for (TestMap::iterator j = this->Tests.begin(); j != this->Tests.end();
- ++j) {
- j->second.erase(test);
+ {
+ auto& allocatedResources = this->AllocatedResources[index];
+ for (auto const& processAlloc : allocatedResources) {
+ for (auto const& it : processAlloc) {
+ auto resourceType = it.first;
+ for (auto const& it2 : it.second) {
+ bool success = this->ResourceAllocator.DeallocateResource(
+ resourceType, it2.Id, it2.Slots);
+ (void)success;
+ assert(success);
+ }
+ }
}
+ }
+ this->AllocatedResources.erase(index);
+}
- 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);
+bool cmCTestMultiProcessHandler::AllResourcesAvailable()
+{
+ for (auto const& it : this->ResourceAllocator.GetResources()) {
+ for (auto const& it2 : it.second) {
+ if (it2.second.Locked != 0) {
+ return false;
+ }
}
- delete testRun;
+ }
+
+ return true;
+}
+
+void cmCTestMultiProcessHandler::CheckResourcesAvailable()
+{
+ for (auto test : this->SortedTests) {
+ std::map<std::string, std::vector<cmCTestBinPackerAllocation>> allocations;
+ this->TestsHaveSufficientResources[test] =
+ !this->TestHandler->UseResourceSpec ||
+ this->TryAllocateResources(test, allocations);
+ }
+}
+
+bool cmCTestMultiProcessHandler::CheckStopTimePassed()
+{
+ if (!this->StopTimePassed) {
+ 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()) {
+ this->SetStopTimePassed();
+ }
+ }
+ return this->StopTimePassed;
+}
+
+void cmCTestMultiProcessHandler::SetStopTimePassed()
+{
+ if (!this->StopTimePassed) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "The stop time has been passed. "
+ "Stopping all tests."
+ << std::endl);
+ this->StopTimePassed = true;
}
}
@@ -183,10 +359,8 @@ void cmCTestMultiProcessHandler::LockResources(int index)
void cmCTestMultiProcessHandler::UnlockResources(int index)
{
- for (std::set<std::string>::iterator i =
- this->Properties[index]->LockedResources.begin();
- i != this->Properties[index]->LockedResources.end(); ++i) {
- this->LockedResources.erase(*i);
+ for (std::string const& i : this->Properties[index]->LockedResources) {
+ this->LockedResources.erase(i);
}
if (this->Properties[index]->RunSerial) {
this->SerialTestRunning = false;
@@ -208,6 +382,11 @@ inline size_t cmCTestMultiProcessHandler::GetProcessorsUsed(int test)
if (processors > this->ParallelLevel) {
processors = this->ParallelLevel;
}
+ // Cap tests that want affinity to the maximum affinity available.
+ if (this->HaveAffinity && processors > this->HaveAffinity &&
+ this->Properties[test]->WantAffinity) {
+ processors = this->HaveAffinity;
+ }
return processors;
}
@@ -219,27 +398,48 @@ std::string cmCTestMultiProcessHandler::GetName(int test)
bool cmCTestMultiProcessHandler::StartTest(int test)
{
// Check for locked resources
- for (std::set<std::string>::iterator i =
- this->Properties[test]->LockedResources.begin();
- i != this->Properties[test]->LockedResources.end(); ++i) {
- if (this->LockedResources.find(*i) != this->LockedResources.end()) {
+ for (std::string const& i : this->Properties[test]->LockedResources) {
+ if (cmContains(this->LockedResources, i)) {
return false;
}
}
+ // Allocate resources
+ if (this->TestsHaveSufficientResources[test] &&
+ !this->AllocateResources(test)) {
+ this->DeallocateResources(test);
+ return false;
+ }
+
// 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
+ this->DeallocateResources(test);
return false;
}
void cmCTestMultiProcessHandler::StartNextTests()
{
+ if (this->TestLoadRetryTimer.get() != nullptr) {
+ // This timer may be waiting to call StartNextTests again.
+ // Since we have been called it is no longer needed.
+ uv_timer_stop(this->TestLoadRetryTimer);
+ }
+
+ if (this->Tests.empty()) {
+ this->TestLoadRetryTimer.reset();
+ return;
+ }
+
+ if (this->CheckStopTimePassed()) {
+ return;
+ }
+
size_t numToStart = 0;
+
if (this->RunningCount < this->ParallelLevel) {
numToStart = this->ParallelLevel - this->RunningCount;
}
@@ -255,7 +455,6 @@ void cmCTestMultiProcessHandler::StartNextTests()
}
bool allTestsFailedTestLoadCheck = false;
- bool usedFakeLoadForTesting = false;
size_t minProcessorsRequired = this->ParallelLevel;
std::string testWithMinProcessors;
@@ -268,15 +467,11 @@ void cmCTestMultiProcessHandler::StartNextTests()
allTestsFailedTestLoadCheck = true;
// Check for a fake load average value used in testing.
- std::string fake_load_value;
- if (cmSystemTools::GetEnv("__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING",
- fake_load_value)) {
- usedFakeLoadForTesting = true;
- if (!cmSystemTools::StringToULong(fake_load_value.c_str(),
- &systemLoad)) {
- cmSystemTools::Error("Failed to parse fake load value: ",
- fake_load_value.c_str());
- }
+ if (this->FakeLoadForTesting > 0) {
+ systemLoad = this->FakeLoadForTesting;
+ // Drop the fake load for the next iteration to a value low enough
+ // that the next iteration will start tests.
+ this->FakeLoadForTesting = 1;
}
// If it's not set, look up the true load average.
else {
@@ -292,24 +487,24 @@ void cmCTestMultiProcessHandler::StartNextTests()
}
TestList copy = this->SortedTests;
- for (TestList::iterator test = copy.begin(); test != copy.end(); ++test) {
+ for (auto const& test : copy) {
// Take a nap if we're currently performing a RUN_SERIAL test.
if (this->SerialTestRunning) {
break;
}
// We can only start a RUN_SERIAL test if no other tests are also running.
- if (this->Properties[*test]->RunSerial && this->RunningCount > 0) {
+ if (this->Properties[test]->RunSerial && this->RunningCount > 0) {
continue;
}
- size_t processors = GetProcessorsUsed(*test);
+ size_t processors = GetProcessorsUsed(test);
bool testLoadOk = true;
if (this->TestLoad > 0) {
if (processors <= spareLoad) {
- cmCTestLog(this->CTest, DEBUG, "OK to run "
- << GetName(*test) << ", it requires " << processors
- << " procs & system load is: " << systemLoad
- << std::endl);
+ cmCTestLog(this->CTest, DEBUG,
+ "OK to run " << GetName(test) << ", it requires "
+ << processors << " procs & system load is: "
+ << systemLoad << std::endl);
allTestsFailedTestLoadCheck = false;
} else {
testLoadOk = false;
@@ -318,14 +513,10 @@ void cmCTestMultiProcessHandler::StartNextTests()
if (processors <= minProcessorsRequired) {
minProcessorsRequired = processors;
- testWithMinProcessors = GetName(*test);
+ testWithMinProcessors = GetName(test);
}
- if (testLoadOk && processors <= numToStart && this->StartTest(*test)) {
- if (this->StopTimePassed) {
- return;
- }
-
+ if (testLoadOk && processors <= numToStart && this->StartTest(test)) {
numToStart -= processors;
} else if (numToStart == 0) {
break;
@@ -333,10 +524,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,
@@ -348,63 +551,70 @@ void cmCTestMultiProcessHandler::StartNextTests()
}
cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl);
- if (usedFakeLoadForTesting) {
- // Break out of the infinite loop of waiting for our fake load
- // to come down.
- this->StopTimePassed = true;
- } else {
- // Wait between 1 and 5 seconds before trying again.
- cmCTestScriptHandler::SleepInSeconds(cmSystemTools::RandomSeed() % 5 +
- 1);
+ // Wait between 1 and 5 seconds before trying again.
+ unsigned int milliseconds = (cmSystemTools::RandomSeed() % 5 + 1) * 1000;
+ if (this->FakeLoadForTesting) {
+ milliseconds = 10;
}
+ if (this->TestLoadRetryTimer.get() == nullptr) {
+ this->TestLoadRetryTimer.init(this->Loop, this);
+ }
+ this->TestLoadRetryTimer.start(
+ &cmCTestMultiProcessHandler::OnTestLoadRetryCB, milliseconds, 0);
}
}
-bool cmCTestMultiProcessHandler::CheckOutput()
+void cmCTestMultiProcessHandler::OnTestLoadRetryCB(uv_timer_t* timer)
{
- // no more output we are done
- if (this->RunningTests.empty()) {
- return false;
+ auto self = static_cast<cmCTestMultiProcessHandler*>(timer->data);
+ self->StartNextTests();
+}
+
+void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner,
+ bool started)
+{
+ this->Completed++;
+
+ int test = runner->GetIndex();
+ auto properties = runner->GetTestProperties();
+
+ bool testResult = runner->EndTest(this->Completed, this->Total, started);
+ if (runner->TimedOutForStopTime()) {
+ this->SetStopTimePassed();
}
- std::vector<cmCTestRunTest*> finished;
- std::string out, err;
- for (std::set<cmCTestRunTest*>::const_iterator i =
- this->RunningTests.begin();
- i != this->RunningTests.end(); ++i) {
- cmCTestRunTest* p = *i;
- if (!p->CheckOutput()) {
- finished.push_back(p);
+ if (started) {
+ if (!this->StopTimePassed && runner->StartAgain(this->Completed)) {
+ this->Completed--; // remove the completed test because run again
+ return;
}
}
- for (std::vector<cmCTestRunTest*>::iterator i = finished.begin();
- i != finished.end(); ++i) {
- this->Completed++;
- cmCTestRunTest* p = *i;
- int test = p->GetIndex();
- bool testResult = p->EndTest(this->Completed, this->Total, true);
- if (p->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 (TestMap::iterator j = this->Tests.begin(); j != this->Tests.end();
- ++j) {
- j->second.erase(test);
- }
- this->TestFinishMap[test] = true;
- this->TestRunningMap[test] = false;
- this->RunningTests.erase(p);
- this->WriteCheckpoint(test);
- this->UnlockResources(test);
- this->RunningCount -= GetProcessorsUsed(test);
- delete p;
+ 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->DeallocateResources(test);
+ this->UnlockResources(test);
+ this->RunningCount -= GetProcessorsUsed(test);
+
+ for (auto p : properties->Affinity) {
+ this->ProcessorsAvailable.insert(p);
+ }
+ properties->Affinity.clear();
+
+ delete runner;
+ if (started) {
+ this->StartNextTests();
}
- return true;
}
void cmCTestMultiProcessHandler::UpdateCostData()
@@ -416,7 +626,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());
@@ -425,7 +635,7 @@ void cmCTestMultiProcessHandler::UpdateCostData()
if (line == "---") {
break;
}
- std::vector<cmsys::String> parts = cmSystemTools::SplitString(line, ' ');
+ std::vector<std::string> parts = cmSystemTools::SplitString(line, ' ');
// Format: <name> <previous_runs> <avg_cost>
if (parts.size() < 3) {
break;
@@ -451,26 +661,25 @@ void cmCTestMultiProcessHandler::UpdateCostData()
}
// Add all tests not previously listed in the file
- for (PropertiesMap::iterator i = temp.begin(); i != temp.end(); ++i) {
- fout << i->second->Name << " " << i->second->PreviousRuns << " "
- << i->second->Cost << "\n";
+ for (auto const& i : temp) {
+ fout << i.second->Name << " " << i.second->PreviousRuns << " "
+ << i.second->Cost << "\n";
}
// Write list of failed tests
fout << "---\n";
- for (std::vector<std::string>::iterator i = this->Failed->begin();
- i != this->Failed->end(); ++i) {
- fout << *i << "\n";
+ for (std::string const& f : *this->Failed) {
+ fout << f << "\n";
}
fout.close();
- cmSystemTools::RenameFile(tmpout.c_str(), fname.c_str());
+ cmSystemTools::RenameFile(tmpout, fname);
}
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;
@@ -479,7 +688,7 @@ void cmCTestMultiProcessHandler::ReadCostData()
break;
}
- std::vector<cmsys::String> parts = cmSystemTools::SplitString(line, ' ');
+ std::vector<std::string> parts = cmSystemTools::SplitString(line, ' ');
// Probably an older version of the file, will be fixed next run
if (parts.size() < 3) {
@@ -505,7 +714,7 @@ void cmCTestMultiProcessHandler::ReadCostData()
}
// Next part of the file is the failed tests
while (std::getline(fin, line)) {
- if (line != "") {
+ if (!line.empty()) {
this->LastTestsFailed.push_back(line);
}
}
@@ -517,10 +726,9 @@ int cmCTestMultiProcessHandler::SearchByName(std::string const& name)
{
int index = -1;
- for (PropertiesMap::iterator i = this->Properties.begin();
- i != this->Properties.end(); ++i) {
- if (i->second->Name == name) {
- index = i->first;
+ for (auto const& p : this->Properties) {
+ if (p.second->Name == name) {
+ index = p.first;
}
}
return index;
@@ -540,21 +748,18 @@ 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
// of the cost list and queue other tests for further sorting
- for (TestMap::const_iterator i = this->Tests.begin(); i != this->Tests.end();
- ++i) {
- if (std::find(this->LastTestsFailed.begin(), this->LastTestsFailed.end(),
- this->Properties[i->first]->Name) !=
- this->LastTestsFailed.end()) {
+ for (auto const& t : this->Tests) {
+ if (cmContains(this->LastTestsFailed, this->Properties[t.first]->Name)) {
// If the test failed last time, it should be run first.
- this->SortedTests.push_back(i->first);
- alreadySortedTests.insert(i->first);
+ this->SortedTests.push_back(t.first);
+ alreadySortedTests.insert(t.first);
} else {
- topLevel.insert(i->first);
+ topLevel.insert(t.first);
}
}
@@ -563,18 +768,16 @@ 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 (TestSet::const_iterator i = previousSet.begin();
- i != previousSet.end(); ++i) {
- TestSet const& dependencies = this->Tests[*i];
+ for (auto const& i : previousSet) {
+ TestSet const& dependencies = this->Tests[i];
currentSet.insert(dependencies.begin(), dependencies.end());
}
- for (TestSet::const_iterator i = currentSet.begin(); i != currentSet.end();
- ++i) {
- previousSet.erase(*i);
+ for (auto const& i : currentSet) {
+ previousSet.erase(i);
}
}
@@ -583,22 +786,16 @@ void cmCTestMultiProcessHandler::CreateParallelTestCostList()
// Reverse iterate over the different dependency levels (deepest first).
// Sort tests within each level by COST and append them to the cost list.
- for (std::list<TestSet>::reverse_iterator i = priorityStack.rbegin();
- i != priorityStack.rend(); ++i) {
- TestSet const& currentSet = *i;
- TestComparator comp(this);
-
+ for (TestSet const& currentSet : cmReverseRange(priorityStack)) {
TestList sortedCopy;
-
- sortedCopy.insert(sortedCopy.end(), currentSet.begin(), currentSet.end());
-
- std::stable_sort(sortedCopy.begin(), sortedCopy.end(), comp);
-
- for (TestList::const_iterator j = sortedCopy.begin();
- j != sortedCopy.end(); ++j) {
- if (alreadySortedTests.find(*j) == alreadySortedTests.end()) {
- this->SortedTests.push_back(*j);
- alreadySortedTests.insert(*j);
+ cmAppend(sortedCopy, currentSet);
+ std::stable_sort(sortedCopy.begin(), sortedCopy.end(),
+ TestComparator(this));
+
+ for (auto const& j : sortedCopy) {
+ if (!cmContains(alreadySortedTests, j)) {
+ this->SortedTests.push_back(j);
+ alreadySortedTests.insert(j);
}
}
}
@@ -608,10 +805,9 @@ void cmCTestMultiProcessHandler::GetAllTestDependencies(int test,
TestList& dependencies)
{
TestSet const& dependencySet = this->Tests[test];
- for (TestSet::const_iterator i = dependencySet.begin();
- i != dependencySet.end(); ++i) {
- GetAllTestDependencies(*i, dependencies);
- dependencies.push_back(*i);
+ for (int i : dependencySet) {
+ GetAllTestDependencies(i, dependencies);
+ dependencies.push_back(i);
}
}
@@ -619,33 +815,25 @@ void cmCTestMultiProcessHandler::CreateSerialTestCostList()
{
TestList presortedList;
- for (TestMap::iterator i = this->Tests.begin(); i != this->Tests.end();
- ++i) {
- presortedList.push_back(i->first);
+ for (auto const& i : this->Tests) {
+ presortedList.push_back(i.first);
}
- TestComparator comp(this);
- std::stable_sort(presortedList.begin(), presortedList.end(), comp);
+ std::stable_sort(presortedList.begin(), presortedList.end(),
+ TestComparator(this));
TestSet alreadySortedTests;
- for (TestList::const_iterator i = presortedList.begin();
- i != presortedList.end(); ++i) {
- int test = *i;
-
- if (alreadySortedTests.find(test) != alreadySortedTests.end()) {
+ for (int test : presortedList) {
+ if (cmContains(alreadySortedTests, test)) {
continue;
}
TestList dependencies;
GetAllTestDependencies(test, dependencies);
- for (TestList::const_iterator j = dependencies.begin();
- j != dependencies.end(); ++j) {
- int testDependency = *j;
-
- if (alreadySortedTests.find(testDependency) ==
- alreadySortedTests.end()) {
+ for (int testDependency : dependencies) {
+ if (!cmContains(alreadySortedTests, testDependency)) {
alreadySortedTests.insert(testDependency);
this->SortedTests.push_back(testDependency);
}
@@ -673,32 +861,390 @@ void cmCTestMultiProcessHandler::MarkFinished()
cmSystemTools::RemoveFile(fname);
}
+static Json::Value DumpToJsonArray(const std::set<std::string>& values)
+{
+ Json::Value jsonArray = Json::arrayValue;
+ for (auto& it : values) {
+ jsonArray.append(it);
+ }
+ return jsonArray;
+}
+
+static Json::Value DumpToJsonArray(const std::vector<std::string>& values)
+{
+ Json::Value jsonArray = Json::arrayValue;
+ for (auto& it : values) {
+ jsonArray.append(it);
+ }
+ return jsonArray;
+}
+
+static Json::Value DumpRegExToJsonArray(
+ const std::vector<std::pair<cmsys::RegularExpression, std::string>>& values)
+{
+ Json::Value jsonArray = Json::arrayValue;
+ for (auto& it : values) {
+ jsonArray.append(it.second);
+ }
+ return jsonArray;
+}
+
+static Json::Value DumpMeasurementToJsonArray(
+ const std::map<std::string, std::string>& values)
+{
+ Json::Value jsonArray = Json::arrayValue;
+ for (auto& it : values) {
+ Json::Value measurement = Json::objectValue;
+ measurement["measurement"] = it.first;
+ measurement["value"] = it.second;
+ jsonArray.append(measurement);
+ }
+ return jsonArray;
+}
+
+static Json::Value DumpTimeoutAfterMatch(
+ cmCTestTestHandler::cmCTestTestProperties& testProperties)
+{
+ Json::Value timeoutAfterMatch = Json::objectValue;
+ timeoutAfterMatch["timeout"] = testProperties.AlternateTimeout.count();
+ timeoutAfterMatch["regex"] =
+ DumpRegExToJsonArray(testProperties.TimeoutRegularExpressions);
+ return timeoutAfterMatch;
+}
+
+static Json::Value DumpResourceGroupsToJsonArray(
+ const std::vector<
+ std::vector<cmCTestTestHandler::cmCTestTestResourceRequirement>>&
+ resourceGroups)
+{
+ Json::Value jsonResourceGroups = Json::arrayValue;
+ for (auto const& it : resourceGroups) {
+ Json::Value jsonResourceGroup = Json::objectValue;
+ Json::Value requirements = Json::arrayValue;
+ for (auto const& it2 : it) {
+ Json::Value res = Json::objectValue;
+ res[".type"] = it2.ResourceType;
+ // res[".units"] = it2.UnitsNeeded; // Intentionally commented out
+ res["slots"] = it2.SlotsNeeded;
+ requirements.append(res);
+ }
+ jsonResourceGroup["requirements"] = requirements;
+ jsonResourceGroups.append(jsonResourceGroup);
+ }
+ return jsonResourceGroups;
+}
+
+static Json::Value DumpCTestProperty(std::string const& name,
+ Json::Value value)
+{
+ Json::Value property = Json::objectValue;
+ property["name"] = name;
+ property["value"] = std::move(value);
+ return property;
+}
+
+static Json::Value DumpCTestProperties(
+ cmCTestTestHandler::cmCTestTestProperties& testProperties)
+{
+ Json::Value properties = Json::arrayValue;
+ if (!testProperties.AttachOnFail.empty()) {
+ properties.append(DumpCTestProperty(
+ "ATTACHED_FILES_ON_FAIL", DumpToJsonArray(testProperties.AttachOnFail)));
+ }
+ if (!testProperties.AttachedFiles.empty()) {
+ properties.append(DumpCTestProperty(
+ "ATTACHED_FILES", DumpToJsonArray(testProperties.AttachedFiles)));
+ }
+ if (testProperties.Cost != 0.0f) {
+ properties.append(
+ DumpCTestProperty("COST", static_cast<double>(testProperties.Cost)));
+ }
+ if (!testProperties.Depends.empty()) {
+ properties.append(
+ DumpCTestProperty("DEPENDS", DumpToJsonArray(testProperties.Depends)));
+ }
+ if (testProperties.Disabled) {
+ properties.append(DumpCTestProperty("DISABLED", testProperties.Disabled));
+ }
+ if (!testProperties.Environment.empty()) {
+ properties.append(DumpCTestProperty(
+ "ENVIRONMENT", DumpToJsonArray(testProperties.Environment)));
+ }
+ if (!testProperties.ErrorRegularExpressions.empty()) {
+ properties.append(DumpCTestProperty(
+ "FAIL_REGULAR_EXPRESSION",
+ DumpRegExToJsonArray(testProperties.ErrorRegularExpressions)));
+ }
+ if (!testProperties.SkipRegularExpressions.empty()) {
+ properties.append(DumpCTestProperty(
+ "SKIP_REGULAR_EXPRESSION",
+ DumpRegExToJsonArray(testProperties.SkipRegularExpressions)));
+ }
+ if (!testProperties.FixturesCleanup.empty()) {
+ properties.append(DumpCTestProperty(
+ "FIXTURES_CLEANUP", DumpToJsonArray(testProperties.FixturesCleanup)));
+ }
+ if (!testProperties.FixturesRequired.empty()) {
+ properties.append(DumpCTestProperty(
+ "FIXTURES_REQUIRED", DumpToJsonArray(testProperties.FixturesRequired)));
+ }
+ if (!testProperties.FixturesSetup.empty()) {
+ properties.append(DumpCTestProperty(
+ "FIXTURES_SETUP", DumpToJsonArray(testProperties.FixturesSetup)));
+ }
+ if (!testProperties.Labels.empty()) {
+ properties.append(
+ DumpCTestProperty("LABELS", DumpToJsonArray(testProperties.Labels)));
+ }
+ if (!testProperties.Measurements.empty()) {
+ properties.append(DumpCTestProperty(
+ "MEASUREMENT", DumpMeasurementToJsonArray(testProperties.Measurements)));
+ }
+ if (!testProperties.RequiredRegularExpressions.empty()) {
+ properties.append(DumpCTestProperty(
+ "PASS_REGULAR_EXPRESSION",
+ DumpRegExToJsonArray(testProperties.RequiredRegularExpressions)));
+ }
+ if (!testProperties.ResourceGroups.empty()) {
+ properties.append(DumpCTestProperty(
+ "RESOURCE_GROUPS",
+ DumpResourceGroupsToJsonArray(testProperties.ResourceGroups)));
+ }
+ if (testProperties.WantAffinity) {
+ properties.append(
+ DumpCTestProperty("PROCESSOR_AFFINITY", testProperties.WantAffinity));
+ }
+ if (testProperties.Processors != 1) {
+ properties.append(
+ DumpCTestProperty("PROCESSORS", testProperties.Processors));
+ }
+ if (!testProperties.RequiredFiles.empty()) {
+ properties.append(DumpCTestProperty(
+ "REQUIRED_FILES", DumpToJsonArray(testProperties.RequiredFiles)));
+ }
+ if (!testProperties.LockedResources.empty()) {
+ properties.append(DumpCTestProperty(
+ "RESOURCE_LOCK", DumpToJsonArray(testProperties.LockedResources)));
+ }
+ if (testProperties.RunSerial) {
+ properties.append(
+ DumpCTestProperty("RUN_SERIAL", testProperties.RunSerial));
+ }
+ if (testProperties.SkipReturnCode != -1) {
+ properties.append(
+ DumpCTestProperty("SKIP_RETURN_CODE", testProperties.SkipReturnCode));
+ }
+ if (testProperties.ExplicitTimeout) {
+ properties.append(
+ DumpCTestProperty("TIMEOUT", testProperties.Timeout.count()));
+ }
+ if (!testProperties.TimeoutRegularExpressions.empty()) {
+ properties.append(DumpCTestProperty(
+ "TIMEOUT_AFTER_MATCH", DumpTimeoutAfterMatch(testProperties)));
+ }
+ if (testProperties.WillFail) {
+ properties.append(DumpCTestProperty("WILL_FAIL", testProperties.WillFail));
+ }
+ if (!testProperties.Directory.empty()) {
+ properties.append(
+ DumpCTestProperty("WORKING_DIRECTORY", testProperties.Directory));
+ }
+ return properties;
+}
+
+class BacktraceData
+{
+ std::unordered_map<std::string, Json::ArrayIndex> CommandMap;
+ std::unordered_map<std::string, Json::ArrayIndex> FileMap;
+ std::unordered_map<cmListFileContext const*, Json::ArrayIndex> NodeMap;
+ Json::Value Commands = Json::arrayValue;
+ Json::Value Files = Json::arrayValue;
+ Json::Value Nodes = Json::arrayValue;
+
+ Json::ArrayIndex AddCommand(std::string const& command)
+ {
+ auto i = this->CommandMap.find(command);
+ if (i == this->CommandMap.end()) {
+ i = this->CommandMap.emplace(command, this->Commands.size()).first;
+ this->Commands.append(command);
+ }
+ return i->second;
+ }
+
+ Json::ArrayIndex AddFile(std::string const& file)
+ {
+ auto i = this->FileMap.find(file);
+ if (i == this->FileMap.end()) {
+ i = this->FileMap.emplace(file, this->Files.size()).first;
+ this->Files.append(file);
+ }
+ return i->second;
+ }
+
+public:
+ bool Add(cmListFileBacktrace const& bt, Json::ArrayIndex& index);
+ Json::Value Dump();
+};
+
+bool BacktraceData::Add(cmListFileBacktrace const& bt, Json::ArrayIndex& index)
+{
+ if (bt.Empty()) {
+ return false;
+ }
+ cmListFileContext const* top = &bt.Top();
+ auto found = this->NodeMap.find(top);
+ if (found != this->NodeMap.end()) {
+ index = found->second;
+ return true;
+ }
+ Json::Value entry = Json::objectValue;
+ entry["file"] = this->AddFile(top->FilePath);
+ if (top->Line) {
+ entry["line"] = static_cast<int>(top->Line);
+ }
+ if (!top->Name.empty()) {
+ entry["command"] = this->AddCommand(top->Name);
+ }
+ Json::ArrayIndex parent;
+ if (this->Add(bt.Pop(), parent)) {
+ entry["parent"] = parent;
+ }
+ index = this->NodeMap[top] = this->Nodes.size();
+ this->Nodes.append(std::move(entry)); // NOLINT(*)
+ return true;
+}
+
+Json::Value BacktraceData::Dump()
+{
+ Json::Value backtraceGraph;
+ this->CommandMap.clear();
+ this->FileMap.clear();
+ this->NodeMap.clear();
+ backtraceGraph["commands"] = std::move(this->Commands);
+ backtraceGraph["files"] = std::move(this->Files);
+ backtraceGraph["nodes"] = std::move(this->Nodes);
+ return backtraceGraph;
+}
+
+static void AddBacktrace(BacktraceData& backtraceGraph, Json::Value& object,
+ cmListFileBacktrace const& bt)
+{
+ Json::ArrayIndex backtrace;
+ if (backtraceGraph.Add(bt, backtrace)) {
+ object["backtrace"] = backtrace;
+ }
+}
+
+static Json::Value DumpCTestInfo(
+ cmCTestRunTest& testRun,
+ cmCTestTestHandler::cmCTestTestProperties& testProperties,
+ BacktraceData& backtraceGraph)
+{
+ Json::Value testInfo = Json::objectValue;
+ // test name should always be present
+ testInfo["name"] = testProperties.Name;
+ std::string const& config = testRun.GetCTest()->GetConfigType();
+ if (!config.empty()) {
+ testInfo["config"] = config;
+ }
+ std::string const& command = testRun.GetActualCommand();
+ if (!command.empty()) {
+ std::vector<std::string> commandAndArgs;
+ commandAndArgs.push_back(command);
+ const std::vector<std::string>& args = testRun.GetArguments();
+ if (!args.empty()) {
+ commandAndArgs.reserve(args.size() + 1);
+ cmAppend(commandAndArgs, args);
+ }
+ testInfo["command"] = DumpToJsonArray(commandAndArgs);
+ }
+ Json::Value properties = DumpCTestProperties(testProperties);
+ if (!properties.empty()) {
+ testInfo["properties"] = properties;
+ }
+ if (!testProperties.Backtrace.Empty()) {
+ AddBacktrace(backtraceGraph, testInfo, testProperties.Backtrace);
+ }
+ return testInfo;
+}
+
+static Json::Value DumpVersion(int major, int minor)
+{
+ Json::Value version = Json::objectValue;
+ version["major"] = major;
+ version["minor"] = minor;
+ return version;
+}
+
+void cmCTestMultiProcessHandler::PrintOutputAsJson()
+{
+ this->TestHandler->SetMaxIndex(this->FindMaxIndex());
+
+ Json::Value result = Json::objectValue;
+ result["kind"] = "ctestInfo";
+ result["version"] = DumpVersion(1, 0);
+
+ BacktraceData backtraceGraph;
+ Json::Value tests = Json::arrayValue;
+ for (auto& it : this->Properties) {
+ cmCTestTestHandler::cmCTestTestProperties& p = *it.second;
+
+ // Don't worry if this fails, we are only showing the test list, not
+ // running the tests
+ cmWorkingDirectory workdir(p.Directory);
+ cmCTestRunTest testRun(*this);
+ testRun.SetIndex(p.Index);
+ testRun.SetTestProperties(&p);
+ testRun.ComputeArguments();
+
+ // Skip tests not available in this configuration.
+ if (p.Args.size() >= 2 && p.Args[1] == "NOT_AVAILABLE") {
+ continue;
+ }
+
+ Json::Value testInfo = DumpCTestInfo(testRun, p, backtraceGraph);
+ tests.append(testInfo);
+ }
+ result["backtraceGraph"] = backtraceGraph.Dump();
+ result["tests"] = std::move(tests);
+
+ Json::StreamWriterBuilder builder;
+ builder["indentation"] = " ";
+ std::unique_ptr<Json::StreamWriter> jout(builder.newStreamWriter());
+ jout->write(result, &std::cout);
+}
+
// For ShowOnly mode
void cmCTestMultiProcessHandler::PrintTestList()
{
+ if (this->CTest->GetOutputAsJson()) {
+ PrintOutputAsJson();
+ return;
+ }
+
this->TestHandler->SetMaxIndex(this->FindMaxIndex());
int count = 0;
- for (PropertiesMap::iterator it = this->Properties.begin();
- it != this->Properties.end(); ++it) {
+ for (auto& it : this->Properties) {
count++;
- cmCTestTestHandler::cmCTestTestProperties& p = *it->second;
+ cmCTestTestHandler::cmCTestTestProperties& p = *it.second;
+ // Don't worry if this fails, we are only showing the test list, not
+ // running the tests
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
if (!p.Labels.empty()) // print the labels
{
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Labels:",
- this->Quiet);
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Labels:", this->Quiet);
}
- for (std::vector<std::string>::iterator label = p.Labels.begin();
- label != p.Labels.end(); ++label) {
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " " << *label,
+ for (std::string const& label : p.Labels) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " " << label,
this->Quiet);
}
if (!p.Labels.empty()) // print the labels
@@ -729,7 +1275,8 @@ void cmCTestMultiProcessHandler::PrintTestList()
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl, this->Quiet);
}
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ std::endl
<< "Total Tests: " << this->Total << std::endl,
this->Quiet);
}
@@ -737,9 +1284,8 @@ void cmCTestMultiProcessHandler::PrintTestList()
void cmCTestMultiProcessHandler::PrintLabels()
{
std::set<std::string> allLabels;
- for (PropertiesMap::iterator it = this->Properties.begin();
- it != this->Properties.end(); ++it) {
- cmCTestTestHandler::cmCTestTestProperties& p = *it->second;
+ for (auto& it : this->Properties) {
+ cmCTestTestHandler::cmCTestTestProperties& p = *it.second;
allLabels.insert(p.Labels.begin(), p.Labels.end());
}
@@ -750,10 +1296,9 @@ void cmCTestMultiProcessHandler::PrintLabels()
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
"No Labels Exist" << std::endl, this->Quiet);
}
- for (std::set<std::string>::iterator label = allLabels.begin();
- label != allLabels.end(); ++label) {
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " " << *label << std::endl, this->Quiet);
+ for (std::string const& label : allLabels) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " " << label << std::endl,
+ this->Quiet);
}
}
@@ -762,7 +1307,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
<< "----------------------------------------------------------"
@@ -777,7 +1322,7 @@ void cmCTestMultiProcessHandler::CheckResume()
}
fin.close();
}
- } else if (cmSystemTools::FileExists(fname.c_str(), true)) {
+ } else if (cmSystemTools::FileExists(fname, true)) {
cmSystemTools::RemoveFile(fname);
}
}
@@ -794,10 +1339,9 @@ void cmCTestMultiProcessHandler::RemoveTest(int index)
int cmCTestMultiProcessHandler::FindMaxIndex()
{
int max = 0;
- cmCTestMultiProcessHandler::TestMap::iterator i = this->Tests.begin();
- for (; i != this->Tests.end(); ++i) {
- if (i->first > max) {
- max = i->first;
+ for (auto const& i : this->Tests) {
+ if (i.first > max) {
+ max = i.first;
}
}
return max;
@@ -809,10 +1353,9 @@ bool cmCTestMultiProcessHandler::CheckCycles()
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Checking test dependency graph..." << std::endl,
this->Quiet);
- for (TestMap::iterator it = this->Tests.begin(); it != this->Tests.end();
- ++it) {
+ for (auto const& it : this->Tests) {
// DFS from each element to itself
- int root = it->first;
+ int root = it.first;
std::set<int> visited;
std::stack<int> s;
s.push(root);
@@ -820,9 +1363,8 @@ bool cmCTestMultiProcessHandler::CheckCycles()
int test = s.top();
s.pop();
if (visited.insert(test).second) {
- for (TestSet::iterator d = this->Tests[test].begin();
- d != this->Tests[test].end(); ++d) {
- if (*d == root) {
+ for (auto const& d : this->Tests[test]) {
+ if (d == root) {
// cycle exists
cmCTestLog(
this->CTest, ERROR_MESSAGE,
@@ -832,7 +1374,7 @@ bool cmCTestMultiProcessHandler::CheckCycles()
<< "\".\nPlease fix the cycle and run ctest again.\n");
return false;
}
- s.push(*d);
+ s.push(d);
}
}
}
diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h
index dccc2c896..1db4bfdd1 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.h
+++ b/Source/CTest/cmCTestMultiProcessHandler.h
@@ -5,14 +5,22 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmCTestTestHandler.h"
#include <map>
#include <set>
-#include <stddef.h>
#include <string>
#include <vector>
+#include <stddef.h>
+
+#include "cm_uv.h"
+
+#include "cmCTestResourceAllocator.h"
+#include "cmCTestTestHandler.h"
+#include "cmUVHandlePtr.h"
+
class cmCTest;
+struct cmCTestBinPackerAllocation;
+class cmCTestResourceSpec;
class cmCTestRunTest;
/** \class cmCTestMultiProcessHandler
@@ -23,6 +31,7 @@ class cmCTestRunTest;
class cmCTestMultiProcessHandler
{
friend class TestComparator;
+ friend class cmCTestRunTest;
public:
struct TestSet : public std::set<int>
@@ -38,6 +47,11 @@ public:
: public std::map<int, cmCTestTestHandler::cmCTestTestProperties*>
{
};
+ struct ResourceAllocation
+ {
+ std::string Id;
+ unsigned int Slots;
+ };
cmCTestMultiProcessHandler();
virtual ~cmCTestMultiProcessHandler();
@@ -47,6 +61,7 @@ public:
void SetParallelLevel(size_t);
void SetTestLoad(unsigned long load);
virtual void RunTests();
+ void PrintOutputAsJson();
void PrintTestList();
void PrintLabels();
@@ -71,11 +86,19 @@ public:
cmCTestTestHandler* GetTestHandler() { return this->TestHandler; }
void SetQuiet(bool b) { this->Quiet = b; }
+
+ void InitResourceAllocator(const cmCTestResourceSpec& spec)
+ {
+ this->ResourceAllocator.InitializeFromResourceSpec(spec);
+ }
+
+ void CheckResourcesAvailable();
+
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 +118,10 @@ 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);
+
+ static void OnTestLoadRetryCB(uv_timer_t* timer);
+
void RemoveTest(int index);
// Check if we need to resume an interrupted test set
void CheckResume();
@@ -107,8 +131,20 @@ protected:
inline size_t GetProcessorsUsed(int index);
std::string GetName(int index);
+ bool CheckStopTimePassed();
+ void SetStopTimePassed();
+
void LockResources(int index);
void UnlockResources(int index);
+
+ bool AllocateResources(int index);
+ bool TryAllocateResources(
+ int index,
+ std::map<std::string, std::vector<cmCTestBinPackerAllocation>>&
+ allocations);
+ void DeallocateResources(int index);
+ bool AllResourcesAvailable();
+
// map from test number to set of depend tests
TestMap Tests;
TestList SortedTests;
@@ -117,7 +153,9 @@ protected:
// Number of tests that are complete
size_t Completed;
size_t RunningCount;
- bool StopTimePassed;
+ std::set<size_t> ProcessorsAvailable;
+ size_t HaveAffinity;
+ bool StopTimePassed = false;
// list of test properties (indices concurrent to the test map)
PropertiesMap Properties;
std::map<int, bool> TestRunningMap;
@@ -127,10 +165,17 @@ protected:
std::vector<std::string>* Failed;
std::vector<std::string> LastTestsFailed;
std::set<std::string> LockedResources;
+ std::map<int,
+ std::vector<std::map<std::string, std::vector<ResourceAllocation>>>>
+ AllocatedResources;
+ std::map<int, bool> TestsHaveSufficientResources;
+ cmCTestResourceAllocator ResourceAllocator;
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
+ unsigned long FakeLoadForTesting;
+ uv_loop_t Loop;
+ cm::uv_timer_ptr TestLoadRetryTimer;
cmCTestTestHandler* TestHandler;
cmCTest* CTest;
bool HasCycles;
diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx
index c80221634..e2063e178 100644
--- a/Source/CTest/cmCTestP4.cxx
+++ b/Source/CTest/cmCTestP4.cxx
@@ -2,26 +2,28 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestP4.h"
+#include <algorithm>
+#include <ctime>
+#include <ostream>
+#include <utility>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestVC.h"
#include "cmProcessTools.h"
+#include "cmRange.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmsys/RegularExpression.hxx"
-#include <algorithm>
-#include <ostream>
-#include <time.h>
-#include <utility>
-
cmCTestP4::cmCTestP4(cmCTest* ct, std::ostream& log)
: cmCTestGlobalVC(ct, log)
{
this->PriorRev = this->Unknown;
}
-cmCTestP4::~cmCTestP4()
-{
-}
+cmCTestP4::~cmCTestP4() = default;
class cmCTestP4::IdentifyParser : public cmCTestVC::LineParser
{
@@ -37,7 +39,7 @@ private:
std::string& Rev;
cmsys::RegularExpression RegexIdentify;
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (this->RegexIdentify.find(this->Line)) {
this->Rev = this->RegexIdentify.match(1);
@@ -61,7 +63,7 @@ private:
cmsys::RegularExpression RegexIdentify;
cmCTestP4* P4;
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (this->RegexIdentify.find(this->Line)) {
P4->ChangeLists.push_back(this->RegexIdentify.match(1));
@@ -84,7 +86,7 @@ private:
cmsys::RegularExpression RegexUser;
cmCTestP4* P4;
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (this->RegexUser.find(this->Line)) {
User NewUser;
@@ -127,7 +129,7 @@ private:
std::string CurrentPath;
cmsys::RegularExpression RegexDiff;
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (!this->Line.empty() && this->Line[0] == '=' &&
this->RegexDiff.find(this->Line)) {
@@ -145,8 +147,7 @@ private:
cmCTestP4::User cmCTestP4::GetUserData(const std::string& username)
{
- std::map<std::string, cmCTestP4::User>::const_iterator it =
- Users.find(username);
+ auto it = Users.find(username);
if (it == Users.end()) {
std::vector<char const*> p4_users;
@@ -155,7 +156,7 @@ cmCTestP4::User cmCTestP4::GetUserData(const std::string& username)
p4_users.push_back("-m");
p4_users.push_back("1");
p4_users.push_back(username.c_str());
- p4_users.push_back(CM_NULLPTR);
+ p4_users.push_back(nullptr);
UserParser out(this, "users-out> ");
OutputLogger err(this->Log, "users-err> ");
@@ -195,7 +196,7 @@ public:
{
this->SetLog(&P4->Log, prefix);
this->RegexHeader.compile("^Change ([0-9]+) by (.+)@(.+) on (.*)$");
- this->RegexDiff.compile("^\\.\\.\\. (.*)#[0-9]+ ([^ ]+)$");
+ this->RegexDiff.compile(R"(^\.\.\. (.*)#[0-9]+ ([^ ]+)$)");
}
private:
@@ -203,8 +204,8 @@ private:
cmsys::RegularExpression RegexDiff;
cmCTestP4* P4;
- typedef cmCTestP4::Revision Revision;
- typedef cmCTestP4::Change Change;
+ using Revision = cmCTestP4::Revision;
+ using Change = cmCTestP4::Change;
std::vector<Change> Changes;
enum SectionType
{
@@ -217,7 +218,7 @@ private:
SectionType Section;
Revision Rev;
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (this->Line.empty()) {
this->NextSection();
@@ -307,34 +308,30 @@ void cmCTestP4::SetP4Options(std::vector<char const*>& CommandOptions)
{
if (P4Options.empty()) {
const char* p4 = this->CommandLineTool.c_str();
- P4Options.push_back(p4);
+ P4Options.emplace_back(p4);
// The CTEST_P4_CLIENT variable sets the P4 client used when issuing
// Perforce commands, if it's different from the default one.
std::string client = this->CTest->GetCTestConfiguration("P4Client");
if (!client.empty()) {
- P4Options.push_back("-c");
+ P4Options.emplace_back("-c");
P4Options.push_back(client);
}
// Set the message language to be English, in case the P4 admin
// has localized them
- P4Options.push_back("-L");
- P4Options.push_back("en");
+ P4Options.emplace_back("-L");
+ P4Options.emplace_back("en");
// The CTEST_P4_OPTIONS variable adds additional Perforce command line
// options before the main command
std::string opts = this->CTest->GetCTestConfiguration("P4Options");
- std::vector<std::string> args =
- cmSystemTools::ParseArguments(opts.c_str());
-
- P4Options.insert(P4Options.end(), args.begin(), args.end());
+ cmAppend(P4Options, cmSystemTools::ParseArguments(opts));
}
CommandOptions.clear();
- for (std::vector<std::string>::iterator i = P4Options.begin();
- i != P4Options.end(); ++i) {
- CommandOptions.push_back(i->c_str());
+ for (std::string const& o : P4Options) {
+ CommandOptions.push_back(o.c_str());
}
}
@@ -350,7 +347,7 @@ std::string cmCTestP4::GetWorkingRevision()
std::string source = this->SourceDirectory + "/...#have";
p4_identify.push_back(source.c_str());
- p4_identify.push_back(CM_NULLPTR);
+ p4_identify.push_back(nullptr);
std::string rev;
IdentifyParser out(this, "p4_changes-out> ", rev);
@@ -373,8 +370,9 @@ bool cmCTestP4::NoteOldRevision()
{
this->OldRevision = this->GetWorkingRevision();
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: "
- << this->OldRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Old revision of repository is: " << this->OldRevision
+ << "\n");
this->PriorRev.Rev = this->OldRevision;
return true;
}
@@ -383,8 +381,9 @@ bool cmCTestP4::NoteNewRevision()
{
this->NewRevision = this->GetWorkingRevision();
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: "
- << this->NewRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " New revision of repository is: " << this->NewRevision
+ << "\n");
return true;
}
@@ -399,7 +398,8 @@ bool cmCTestP4::LoadRevisions()
// If any revision is unknown it means we couldn't contact the server.
// Do not process updates
if (this->OldRevision == "<unknown>" || this->NewRevision == "<unknown>") {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " At least one of the revisions "
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " At least one of the revisions "
<< "is unknown. No repository changes will be reported.\n");
return false;
}
@@ -411,7 +411,7 @@ bool cmCTestP4::LoadRevisions()
p4_changes.push_back("changes");
p4_changes.push_back(range.c_str());
- p4_changes.push_back(CM_NULLPTR);
+ p4_changes.push_back(nullptr);
ChangesParser out(this, "p4_changes-out> ");
OutputLogger err(this->Log, "p4_changes-err> ");
@@ -425,13 +425,12 @@ bool cmCTestP4::LoadRevisions()
// p4 describe -s ...@1111111,2222222
std::vector<char const*> p4_describe;
- for (std::vector<std::string>::reverse_iterator i = ChangeLists.rbegin();
- i != ChangeLists.rend(); ++i) {
+ for (std::string const& i : cmReverseRange(ChangeLists)) {
SetP4Options(p4_describe);
p4_describe.push_back("describe");
p4_describe.push_back("-s");
- p4_describe.push_back(i->c_str());
- p4_describe.push_back(CM_NULLPTR);
+ p4_describe.push_back(i.c_str());
+ p4_describe.push_back(nullptr);
DescribeParser outDescribe(this, "p4_describe-out> ");
OutputLogger errDescribe(this->Log, "p4_describe-err> ");
@@ -451,7 +450,7 @@ bool cmCTestP4::LoadModifications()
p4_diff.push_back("-dn");
std::string source = this->SourceDirectory + "/...";
p4_diff.push_back(source.c_str());
- p4_diff.push_back(CM_NULLPTR);
+ p4_diff.push_back(nullptr);
DiffParser out(this, "p4_diff-out> ");
OutputLogger err(this->Log, "p4_diff-err> ");
@@ -461,15 +460,14 @@ bool cmCTestP4::LoadModifications()
bool cmCTestP4::UpdateCustom(const std::string& custom)
{
- std::vector<std::string> p4_custom_command;
- cmSystemTools::ExpandListArgument(custom, p4_custom_command, true);
+ std::vector<std::string> p4_custom_command = cmExpandedList(custom, true);
std::vector<char const*> p4_custom;
- for (std::vector<std::string>::const_iterator i = p4_custom_command.begin();
- i != p4_custom_command.end(); ++i) {
- p4_custom.push_back(i->c_str());
+ p4_custom.reserve(p4_custom_command.size() + 1);
+ for (std::string const& i : p4_custom_command) {
+ p4_custom.push_back(i.c_str());
}
- p4_custom.push_back(CM_NULLPTR);
+ p4_custom.push_back(nullptr);
OutputLogger custom_out(this->Log, "p4_customsync-out> ");
OutputLogger custom_err(this->Log, "p4_customsync-err> ");
@@ -501,10 +499,9 @@ bool cmCTestP4::UpdateImpl()
if (opts.empty()) {
opts = this->CTest->GetCTestConfiguration("P4UpdateOptions");
}
- std::vector<std::string> args = cmSystemTools::ParseArguments(opts.c_str());
- for (std::vector<std::string>::const_iterator ai = args.begin();
- ai != args.end(); ++ai) {
- p4_sync.push_back(ai->c_str());
+ std::vector<std::string> args = cmSystemTools::ParseArguments(opts);
+ for (std::string const& arg : args) {
+ p4_sync.push_back(arg.c_str());
}
std::string source = this->SourceDirectory + "/...";
@@ -520,7 +517,7 @@ bool cmCTestP4::UpdateImpl()
}
p4_sync.push_back(source.c_str());
- p4_sync.push_back(CM_NULLPTR);
+ p4_sync.push_back(nullptr);
OutputLogger out(this->Log, "p4_sync-out> ");
OutputLogger err(this->Log, "p4_sync-err> ");
diff --git a/Source/CTest/cmCTestP4.h b/Source/CTest/cmCTestP4.h
index e234efbfb..e19472ee8 100644
--- a/Source/CTest/cmCTestP4.h
+++ b/Source/CTest/cmCTestP4.h
@@ -3,15 +3,15 @@
#ifndef cmCTestP4_h
#define cmCTestP4_h
-#include "cmConfigure.h"
-
-#include "cmCTestGlobalVC.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <map>
#include <string>
#include <vector>
+#include "cmCTestGlobalVC.h"
+
class cmCTest;
/** \class cmCTestP4
@@ -24,7 +24,7 @@ public:
/** Construct with a CTest instance and update log stream. */
cmCTestP4(cmCTest* ctest, std::ostream& log);
- ~cmCTestP4() CM_OVERRIDE;
+ ~cmCTestP4() override;
private:
std::vector<std::string> ChangeLists;
@@ -51,13 +51,13 @@ private:
void SetP4Options(std::vector<char const*>& options);
std::string GetWorkingRevision();
- bool NoteOldRevision() CM_OVERRIDE;
- bool NoteNewRevision() CM_OVERRIDE;
- bool UpdateImpl() CM_OVERRIDE;
+ bool NoteOldRevision() override;
+ bool NoteNewRevision() override;
+ bool UpdateImpl() override;
bool UpdateCustom(const std::string& custom);
- bool LoadRevisions() CM_OVERRIDE;
- bool LoadModifications() CM_OVERRIDE;
+ bool LoadRevisions() override;
+ bool LoadModifications() override;
class ChangesParser;
class DescribeParser;
diff --git a/Source/CTest/cmCTestReadCustomFilesCommand.cxx b/Source/CTest/cmCTestReadCustomFilesCommand.cxx
index b21be872f..ed14d0688 100644
--- a/Source/CTest/cmCTestReadCustomFilesCommand.cxx
+++ b/Source/CTest/cmCTestReadCustomFilesCommand.cxx
@@ -14,9 +14,8 @@ bool cmCTestReadCustomFilesCommand::InitialPass(
return false;
}
- std::vector<std::string>::const_iterator dit;
- for (dit = args.begin(); dit != args.end(); ++dit) {
- this->CTest->ReadCustomConfigurationFileTree(dit->c_str(), this->Makefile);
+ for (std::string const& arg : args) {
+ this->CTest->ReadCustomConfigurationFileTree(arg.c_str(), this->Makefile);
}
return true;
diff --git a/Source/CTest/cmCTestReadCustomFilesCommand.h b/Source/CTest/cmCTestReadCustomFilesCommand.h
index 5989fa0fc..cbb939030 100644
--- a/Source/CTest/cmCTestReadCustomFilesCommand.h
+++ b/Source/CTest/cmCTestReadCustomFilesCommand.h
@@ -3,14 +3,17 @@
#ifndef cmCTestReadCustomFilesCommand_h
#define cmCTestReadCustomFilesCommand_h
-#include "cmConfigure.h"
-
-#include "cmCTestCommand.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
+#include <utility>
#include <vector>
-class cmCommand;
+#include <cm/memory>
+
+#include "cmCTestCommand.h"
+#include "cmCommand.h"
+
class cmExecutionStatus;
/** \class cmCTestReadCustomFiles
@@ -27,11 +30,11 @@ public:
/**
* This is a virtual constructor for the command.
*/
- cmCommand* Clone() CM_OVERRIDE
+ std::unique_ptr<cmCommand> Clone() override
{
- cmCTestReadCustomFilesCommand* ni = new cmCTestReadCustomFilesCommand;
+ auto ni = cm::make_unique<cmCTestReadCustomFilesCommand>();
ni->CTest = this->CTest;
- return ni;
+ return std::unique_ptr<cmCommand>(std::move(ni));
}
/**
@@ -39,7 +42,7 @@ public:
* the CMakeLists.txt file.
*/
bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
+ cmExecutionStatus& status) override;
};
#endif
diff --git a/Source/CTest/cmCTestResourceAllocator.cxx b/Source/CTest/cmCTestResourceAllocator.cxx
new file mode 100644
index 000000000..9d468a7f0
--- /dev/null
+++ b/Source/CTest/cmCTestResourceAllocator.cxx
@@ -0,0 +1,86 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmCTestResourceAllocator.h"
+
+#include <utility>
+#include <vector>
+
+#include "cmCTestResourceSpec.h"
+
+void cmCTestResourceAllocator::InitializeFromResourceSpec(
+ const cmCTestResourceSpec& spec)
+{
+ this->Resources.clear();
+
+ for (auto const& it : spec.LocalSocket.Resources) {
+ auto& res = this->Resources[it.first];
+ for (auto const& specRes : it.second) {
+ res[specRes.Id].Total = specRes.Capacity;
+ res[specRes.Id].Locked = 0;
+ }
+ }
+}
+
+const std::map<std::string,
+ std::map<std::string, cmCTestResourceAllocator::Resource>>&
+cmCTestResourceAllocator::GetResources() const
+{
+ return this->Resources;
+}
+
+bool cmCTestResourceAllocator::AllocateResource(const std::string& name,
+ const std::string& id,
+ unsigned int slots)
+{
+ auto it = this->Resources.find(name);
+ if (it == this->Resources.end()) {
+ return false;
+ }
+
+ auto resIt = it->second.find(id);
+ if (resIt == it->second.end()) {
+ return false;
+ }
+
+ if (resIt->second.Total < resIt->second.Locked + slots) {
+ return false;
+ }
+
+ resIt->second.Locked += slots;
+ return true;
+}
+
+bool cmCTestResourceAllocator::DeallocateResource(const std::string& name,
+ const std::string& id,
+ unsigned int slots)
+{
+ auto it = this->Resources.find(name);
+ if (it == this->Resources.end()) {
+ return false;
+ }
+
+ auto resIt = it->second.find(id);
+ if (resIt == it->second.end()) {
+ return false;
+ }
+
+ if (resIt->second.Locked < slots) {
+ return false;
+ }
+
+ resIt->second.Locked -= slots;
+ return true;
+}
+
+bool cmCTestResourceAllocator::Resource::operator==(
+ const Resource& other) const
+{
+ return this->Total == other.Total && this->Locked == other.Locked;
+}
+
+bool cmCTestResourceAllocator::Resource::operator!=(
+ const Resource& other) const
+{
+ return !(*this == other);
+}
diff --git a/Source/CTest/cmCTestResourceAllocator.h b/Source/CTest/cmCTestResourceAllocator.h
new file mode 100644
index 000000000..9f0b9c95a
--- /dev/null
+++ b/Source/CTest/cmCTestResourceAllocator.h
@@ -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. */
+#ifndef cmCTestResourceAllocator_h
+#define cmCTestResourceAllocator_h
+
+#include <map>
+#include <string>
+
+class cmCTestResourceSpec;
+
+class cmCTestResourceAllocator
+{
+public:
+ struct Resource
+ {
+ unsigned int Total;
+ unsigned int Locked;
+
+ unsigned int Free() const { return this->Total - this->Locked; }
+
+ bool operator==(const Resource& other) const;
+ bool operator!=(const Resource& other) const;
+ };
+
+ void InitializeFromResourceSpec(const cmCTestResourceSpec& spec);
+
+ const std::map<std::string, std::map<std::string, Resource>>& GetResources()
+ const;
+
+ bool AllocateResource(const std::string& name, const std::string& id,
+ unsigned int slots);
+ bool DeallocateResource(const std::string& name, const std::string& id,
+ unsigned int slots);
+
+private:
+ std::map<std::string, std::map<std::string, Resource>> Resources;
+};
+
+#endif
diff --git a/Source/CTest/cmCTestResourceGroupsLexerHelper.cxx b/Source/CTest/cmCTestResourceGroupsLexerHelper.cxx
new file mode 100644
index 000000000..072af42f0
--- /dev/null
+++ b/Source/CTest/cmCTestResourceGroupsLexerHelper.cxx
@@ -0,0 +1,55 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCTestResourceGroupsLexerHelper.h"
+
+#include "cmCTestResourceGroupsLexer.h"
+#include "cmCTestTestHandler.h"
+
+cmCTestResourceGroupsLexerHelper::cmCTestResourceGroupsLexerHelper(
+ std::vector<std::vector<cmCTestTestHandler::cmCTestTestResourceRequirement>>&
+ output)
+ : Output(output)
+{
+}
+
+bool cmCTestResourceGroupsLexerHelper::ParseString(const std::string& value)
+{
+ yyscan_t lexer;
+ cmCTestResourceGroups_yylex_init_extra(this, &lexer);
+
+ auto state = cmCTestResourceGroups_yy_scan_string(value.c_str(), lexer);
+ int retval = cmCTestResourceGroups_yylex(lexer);
+ cmCTestResourceGroups_yy_delete_buffer(state, lexer);
+
+ cmCTestResourceGroups_yylex_destroy(lexer);
+ return retval == 0;
+}
+
+void cmCTestResourceGroupsLexerHelper::SetProcessCount(unsigned int count)
+{
+ this->ProcessCount = count;
+}
+
+void cmCTestResourceGroupsLexerHelper::SetResourceType(const std::string& type)
+{
+ this->ResourceType = type;
+}
+
+void cmCTestResourceGroupsLexerHelper::SetNeededSlots(int count)
+{
+ this->NeededSlots = count;
+}
+
+void cmCTestResourceGroupsLexerHelper::WriteRequirement()
+{
+ this->Process.push_back({ this->ResourceType, this->NeededSlots, 1 });
+}
+
+void cmCTestResourceGroupsLexerHelper::WriteProcess()
+{
+ for (unsigned int i = 0; i < this->ProcessCount; ++i) {
+ this->Output.push_back(this->Process);
+ }
+ this->Process.clear();
+ this->ProcessCount = 1;
+}
diff --git a/Source/CTest/cmCTestResourceGroupsLexerHelper.h b/Source/CTest/cmCTestResourceGroupsLexerHelper.h
new file mode 100644
index 000000000..2cb6cb1c5
--- /dev/null
+++ b/Source/CTest/cmCTestResourceGroupsLexerHelper.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. */
+#ifndef cmCTestResourceGroupsLexerHelper_h
+#define cmCTestResourceGroupsLexerHelper_h
+
+#include <string>
+#include <vector>
+
+#include "cmCTestTestHandler.h"
+
+class cmCTestResourceGroupsLexerHelper
+{
+public:
+ struct ParserType
+ {
+ };
+
+ cmCTestResourceGroupsLexerHelper(
+ std::vector<
+ std::vector<cmCTestTestHandler::cmCTestTestResourceRequirement>>&
+ output);
+ ~cmCTestResourceGroupsLexerHelper() = default;
+
+ bool ParseString(const std::string& value);
+
+ void SetProcessCount(unsigned int count);
+ void SetResourceType(const std::string& type);
+ void SetNeededSlots(int count);
+ void WriteRequirement();
+ void WriteProcess();
+
+private:
+ std::vector<std::vector<cmCTestTestHandler::cmCTestTestResourceRequirement>>&
+ Output;
+
+ unsigned int ProcessCount = 1;
+ std::string ResourceType;
+ int NeededSlots;
+ std::vector<cmCTestTestHandler::cmCTestTestResourceRequirement> Process;
+};
+
+#define YY_EXTRA_TYPE cmCTestResourceGroupsLexerHelper*
+
+#endif
diff --git a/Source/CTest/cmCTestResourceSpec.cxx b/Source/CTest/cmCTestResourceSpec.cxx
new file mode 100644
index 000000000..8f91efb45
--- /dev/null
+++ b/Source/CTest/cmCTestResourceSpec.cxx
@@ -0,0 +1,198 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCTestResourceSpec.h"
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+
+#include "cm_jsoncpp_reader.h"
+#include "cm_jsoncpp_value.h"
+
+static const cmsys::RegularExpression IdentifierRegex{ "^[a-z_][a-z0-9_]*$" };
+static const cmsys::RegularExpression IdRegex{ "^[a-z0-9_]+$" };
+
+cmCTestResourceSpec::ReadFileResult cmCTestResourceSpec::ReadFromJSONFile(
+ const std::string& filename)
+{
+ cmsys::ifstream fin(filename.c_str());
+ if (!fin) {
+ return ReadFileResult::FILE_NOT_FOUND;
+ }
+
+ Json::Value root;
+ Json::CharReaderBuilder builder;
+ if (!Json::parseFromStream(builder, fin, &root, nullptr)) {
+ return ReadFileResult::JSON_PARSE_ERROR;
+ }
+
+ if (!root.isObject()) {
+ return ReadFileResult::INVALID_ROOT;
+ }
+
+ int majorVersion = 1;
+ int minorVersion = 0;
+ if (root.isMember("version")) {
+ auto const& version = root["version"];
+ if (version.isObject()) {
+ if (!version.isMember("major") || !version.isMember("minor")) {
+ return ReadFileResult::INVALID_VERSION;
+ }
+ auto const& major = version["major"];
+ auto const& minor = version["minor"];
+ if (!major.isInt() || !minor.isInt()) {
+ return ReadFileResult::INVALID_VERSION;
+ }
+ majorVersion = major.asInt();
+ minorVersion = minor.asInt();
+ } else {
+ return ReadFileResult::INVALID_VERSION;
+ }
+ } else {
+ return ReadFileResult::NO_VERSION;
+ }
+
+ if (majorVersion != 1 || minorVersion != 0) {
+ return ReadFileResult::UNSUPPORTED_VERSION;
+ }
+
+ auto const& local = root["local"];
+ if (!local.isArray()) {
+ return ReadFileResult::INVALID_SOCKET_SPEC;
+ }
+ if (local.size() > 1) {
+ return ReadFileResult::INVALID_SOCKET_SPEC;
+ }
+
+ if (local.empty()) {
+ this->LocalSocket.Resources.clear();
+ return ReadFileResult::READ_OK;
+ }
+
+ auto const& localSocket = local[0];
+ if (!localSocket.isObject()) {
+ return ReadFileResult::INVALID_SOCKET_SPEC;
+ }
+ std::map<std::string, std::vector<cmCTestResourceSpec::Resource>> resources;
+ cmsys::RegularExpressionMatch match;
+ for (auto const& key : localSocket.getMemberNames()) {
+ if (IdentifierRegex.find(key.c_str(), match)) {
+ auto const& value = localSocket[key];
+ auto& r = resources[key];
+ if (value.isArray()) {
+ for (auto const& item : value) {
+ if (item.isObject()) {
+ cmCTestResourceSpec::Resource resource;
+
+ if (!item.isMember("id")) {
+ return ReadFileResult::INVALID_RESOURCE;
+ }
+ auto const& id = item["id"];
+ if (!id.isString()) {
+ return ReadFileResult::INVALID_RESOURCE;
+ }
+ resource.Id = id.asString();
+ if (!IdRegex.find(resource.Id.c_str(), match)) {
+ return ReadFileResult::INVALID_RESOURCE;
+ }
+
+ if (item.isMember("slots")) {
+ auto const& capacity = item["slots"];
+ if (!capacity.isConvertibleTo(Json::uintValue)) {
+ return ReadFileResult::INVALID_RESOURCE;
+ }
+ resource.Capacity = capacity.asUInt();
+ } else {
+ resource.Capacity = 1;
+ }
+
+ r.push_back(resource);
+ } else {
+ return ReadFileResult::INVALID_RESOURCE;
+ }
+ }
+ } else {
+ return ReadFileResult::INVALID_RESOURCE_TYPE;
+ }
+ }
+ }
+
+ this->LocalSocket.Resources = std::move(resources);
+ return ReadFileResult::READ_OK;
+}
+
+const char* cmCTestResourceSpec::ResultToString(ReadFileResult result)
+{
+ switch (result) {
+ case ReadFileResult::READ_OK:
+ return "OK";
+
+ case ReadFileResult::FILE_NOT_FOUND:
+ return "File not found";
+
+ case ReadFileResult::JSON_PARSE_ERROR:
+ return "JSON parse error";
+
+ case ReadFileResult::INVALID_ROOT:
+ return "Invalid root object";
+
+ case ReadFileResult::NO_VERSION:
+ return "No version specified";
+
+ case ReadFileResult::INVALID_VERSION:
+ return "Invalid version object";
+
+ case ReadFileResult::UNSUPPORTED_VERSION:
+ return "Unsupported version";
+
+ case ReadFileResult::INVALID_SOCKET_SPEC:
+ return "Invalid socket object";
+
+ case ReadFileResult::INVALID_RESOURCE_TYPE:
+ return "Invalid resource type object";
+
+ case ReadFileResult::INVALID_RESOURCE:
+ return "Invalid resource object";
+
+ default:
+ return "Unknown";
+ }
+}
+
+bool cmCTestResourceSpec::operator==(const cmCTestResourceSpec& other) const
+{
+ return this->LocalSocket == other.LocalSocket;
+}
+
+bool cmCTestResourceSpec::operator!=(const cmCTestResourceSpec& other) const
+{
+ return !(*this == other);
+}
+
+bool cmCTestResourceSpec::Socket::operator==(
+ const cmCTestResourceSpec::Socket& other) const
+{
+ return this->Resources == other.Resources;
+}
+
+bool cmCTestResourceSpec::Socket::operator!=(
+ const cmCTestResourceSpec::Socket& other) const
+{
+ return !(*this == other);
+}
+
+bool cmCTestResourceSpec::Resource::operator==(
+ const cmCTestResourceSpec::Resource& other) const
+{
+ return this->Id == other.Id && this->Capacity == other.Capacity;
+}
+
+bool cmCTestResourceSpec::Resource::operator!=(
+ const cmCTestResourceSpec::Resource& other) const
+{
+ return !(*this == other);
+}
diff --git a/Source/CTest/cmCTestResourceSpec.h b/Source/CTest/cmCTestResourceSpec.h
new file mode 100644
index 000000000..cb242c050
--- /dev/null
+++ b/Source/CTest/cmCTestResourceSpec.h
@@ -0,0 +1,55 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCTestResourceSpec_h
+#define cmCTestResourceSpec_h
+
+#include <map>
+#include <string>
+#include <vector>
+
+class cmCTestResourceSpec
+{
+public:
+ class Resource
+ {
+ public:
+ std::string Id;
+ unsigned int Capacity;
+
+ bool operator==(const Resource& other) const;
+ bool operator!=(const Resource& other) const;
+ };
+
+ class Socket
+ {
+ public:
+ std::map<std::string, std::vector<Resource>> Resources;
+
+ bool operator==(const Socket& other) const;
+ bool operator!=(const Socket& other) const;
+ };
+
+ Socket LocalSocket;
+
+ enum class ReadFileResult
+ {
+ READ_OK,
+ FILE_NOT_FOUND,
+ JSON_PARSE_ERROR,
+ INVALID_ROOT,
+ NO_VERSION,
+ INVALID_VERSION,
+ UNSUPPORTED_VERSION,
+ INVALID_SOCKET_SPEC, // Can't be INVALID_SOCKET due to a Windows macro
+ INVALID_RESOURCE_TYPE,
+ INVALID_RESOURCE,
+ };
+
+ ReadFileResult ReadFromJSONFile(const std::string& filename);
+ static const char* ResultToString(ReadFileResult result);
+
+ bool operator==(const cmCTestResourceSpec& other) const;
+ bool operator!=(const cmCTestResourceSpec& other) const;
+};
+
+#endif
diff --git a/Source/CTest/cmCTestRunScriptCommand.cxx b/Source/CTest/cmCTestRunScriptCommand.cxx
index 238284a3f..f59ca57de 100644
--- a/Source/CTest/cmCTestRunScriptCommand.cxx
+++ b/Source/CTest/cmCTestRunScriptCommand.cxx
@@ -5,8 +5,6 @@
#include "cmCTestScriptHandler.h"
#include "cmMakefile.h"
-#include <sstream>
-
class cmExecutionStatus;
bool cmCTestRunScriptCommand::InitialPass(std::vector<std::string> const& args,
@@ -39,10 +37,9 @@ bool cmCTestRunScriptCommand::InitialPass(std::vector<std::string> const& args,
++i;
} else {
int ret;
- cmCTestScriptHandler::RunScript(this->CTest, args[i].c_str(), !np, &ret);
- std::ostringstream str;
- str << ret;
- this->Makefile->AddDefinition(returnVariable, str.str().c_str());
+ cmCTestScriptHandler::RunScript(this->CTest, this->Makefile,
+ args[i].c_str(), !np, &ret);
+ this->Makefile->AddDefinition(returnVariable, std::to_string(ret));
}
}
return true;
diff --git a/Source/CTest/cmCTestRunScriptCommand.h b/Source/CTest/cmCTestRunScriptCommand.h
index 9bd09659d..2d8bde19d 100644
--- a/Source/CTest/cmCTestRunScriptCommand.h
+++ b/Source/CTest/cmCTestRunScriptCommand.h
@@ -3,14 +3,17 @@
#ifndef cmCTestRunScriptCommand_h
#define cmCTestRunScriptCommand_h
-#include "cmConfigure.h"
-
-#include "cmCTestCommand.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
+#include <utility>
#include <vector>
-class cmCommand;
+#include <cm/memory>
+
+#include "cmCTestCommand.h"
+#include "cmCommand.h"
+
class cmExecutionStatus;
/** \class cmCTestRunScript
@@ -27,12 +30,12 @@ public:
/**
* This is a virtual constructor for the command.
*/
- cmCommand* Clone() CM_OVERRIDE
+ std::unique_ptr<cmCommand> Clone() override
{
- cmCTestRunScriptCommand* ni = new cmCTestRunScriptCommand;
+ auto ni = cm::make_unique<cmCTestRunScriptCommand>();
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
- return ni;
+ return std::unique_ptr<cmCommand>(std::move(ni));
}
/**
@@ -40,7 +43,7 @@ public:
* the CMakeLists.txt file.
*/
bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
+ cmExecutionStatus& status) override;
};
#endif
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 0c4269e3d..3091050f3 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -2,273 +2,226 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestRunTest.h"
+#include <chrono>
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstring>
+#include <iomanip>
+#include <ratio>
+#include <sstream>
+#include <utility>
+
+#include <cm/memory>
+
+#include "cmsys/RegularExpression.hxx"
+
#include "cmCTest.h"
#include "cmCTestMemCheckHandler.h"
-#include "cmCTestTestHandler.h"
+#include "cmCTestMultiProcessHandler.h"
#include "cmProcess.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
-#include "cmConfigure.h"
-#include "cm_curl.h"
-#include "cm_zlib.h"
-#include "cmsys/Base64.h"
-#include "cmsys/Process.h"
-#include "cmsys/RegularExpression.hxx"
-#include <iomanip>
-#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 = CM_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;
- this->TestResult.Properties = CM_NULLPTR;
- this->ProcessOutput = "";
- this->CompressedOutput = "";
- this->CompressionRatio = 2;
- this->StopTimePassed = false;
+ this->TestResult.Properties = nullptr;
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()) {
- std::vector<
- std::pair<cmsys::RegularExpression, std::string> >::iterator regIt;
- for (regIt = this->TestProperties->TimeoutRegularExpressions.begin();
- regIt != this->TestProperties->TimeoutRegularExpressions.end();
- ++regIt) {
- if (regIt->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)) {
+ 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
-// is appended to this->CompressedOutput
-void cmCTestRunTest::CompressOutput()
-{
- int ret;
- z_stream strm;
-
- unsigned char* in = reinterpret_cast<unsigned char*>(
- const_cast<char*>(this->ProcessOutput.c_str()));
- // zlib makes the guarantee that this is the maximum output size
- int outSize = static_cast<int>(
- static_cast<double>(this->ProcessOutput.size()) * 1.001 + 13.0);
- unsigned char* out = new unsigned char[outSize];
-
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
- ret = deflateInit(&strm, -1); // default compression level
- if (ret != Z_OK) {
- delete[] out;
- return;
- }
-
- strm.avail_in = static_cast<uInt>(this->ProcessOutput.size());
- strm.next_in = in;
- strm.avail_out = outSize;
- strm.next_out = out;
- ret = deflate(&strm, Z_FINISH);
-
- if (ret != Z_STREAM_END) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Error during output compression. Sending uncompressed output."
- << std::endl);
- delete[] out;
- return;
- }
-
- (void)deflateEnd(&strm);
-
- unsigned char* encoded_buffer =
- new unsigned char[static_cast<int>(outSize * 1.5)];
-
- size_t rlen = cmsysBase64_Encode(out, strm.total_out, encoded_buffer, 1);
-
- this->CompressedOutput.clear();
- for (size_t i = 0; i < rlen; i++) {
- this->CompressedOutput += encoded_buffer[i];
- }
-
- if (strm.total_in) {
- this->CompressionRatio =
- static_cast<double>(strm.total_out) / static_cast<double>(strm.total_in);
- }
-
- delete[] encoded_buffer;
- delete[] out;
}
bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
{
- if ((!this->TestHandler->MemCheck &&
- this->CTest->ShouldCompressTestOutput()) ||
- (this->TestHandler->MemCheck &&
- this->CTest->ShouldCompressTestOutput())) {
- this->CompressOutput();
- }
-
this->WriteLogOutputTop(completed, total);
std::string reason;
bool passed = true;
- int res =
- started ? this->TestProcess->GetProcessStatus() : cmsysProcess_State_Error;
- int retVal = this->TestProcess->GetExitValue();
- std::vector<std::pair<cmsys::RegularExpression, std::string> >::iterator
- passIt;
+ cmProcess::State res =
+ started ? this->TestProcess->GetProcessStatus() : cmProcess::State::Error;
+ if (res != cmProcess::State::Expired) {
+ this->TimeoutIsForStopTime = false;
+ }
+ std::int64_t retVal = this->TestProcess->GetExitValue();
bool forceFail = false;
+ bool forceSkip = false;
bool skipped = false;
bool outputTestErrorsToConsole = false;
if (!this->TestProperties->RequiredRegularExpressions.empty() &&
this->FailedDependencies.empty()) {
bool found = false;
- for (passIt = this->TestProperties->RequiredRegularExpressions.begin();
- passIt != this->TestProperties->RequiredRegularExpressions.end();
- ++passIt) {
- if (passIt->first.find(this->ProcessOutput.c_str())) {
+ for (auto& pass : this->TestProperties->RequiredRegularExpressions) {
+ if (pass.first.find(this->ProcessOutput)) {
found = true;
- reason = "Required regular expression found.";
+ reason = cmStrCat("Required regular expression found. Regex=[",
+ pass.second, ']');
break;
}
}
if (!found) {
- reason = "Required regular expression not found.";
+ reason = "Required regular expression not found. Regex=[";
+ for (auto& pass : this->TestProperties->RequiredRegularExpressions) {
+ reason += pass.second;
+ reason += "\n";
+ }
+ reason += "]";
forceFail = true;
}
- reason += "Regex=[";
- for (passIt = this->TestProperties->RequiredRegularExpressions.begin();
- passIt != this->TestProperties->RequiredRegularExpressions.end();
- ++passIt) {
- reason += passIt->second;
- reason += "\n";
- }
- reason += "]";
}
if (!this->TestProperties->ErrorRegularExpressions.empty() &&
this->FailedDependencies.empty()) {
- for (passIt = this->TestProperties->ErrorRegularExpressions.begin();
- passIt != this->TestProperties->ErrorRegularExpressions.end();
- ++passIt) {
- if (passIt->first.find(this->ProcessOutput.c_str())) {
- reason = "Error regular expression found in output.";
- reason += " Regex=[";
- reason += passIt->second;
- reason += "]";
+ for (auto& fail : this->TestProperties->ErrorRegularExpressions) {
+ if (fail.first.find(this->ProcessOutput)) {
+ reason = cmStrCat("Error regular expression found in output. Regex=[",
+ fail.second, ']');
forceFail = true;
break;
}
}
}
- if (res == cmsysProcess_State_Exited) {
+ if (!this->TestProperties->SkipRegularExpressions.empty() &&
+ this->FailedDependencies.empty()) {
+ for (auto& skip : this->TestProperties->SkipRegularExpressions) {
+ if (skip.first.find(this->ProcessOutput)) {
+ reason = cmStrCat("Skip regular expression found in output. Regex=[",
+ skip.second, ']');
+ forceSkip = true;
+ break;
+ }
+ }
+ }
+ std::ostringstream outputStream;
+ if (res == cmProcess::State::Exited) {
bool success = !forceFail &&
(retVal == 0 ||
!this->TestProperties->RequiredRegularExpressions.empty());
- if (this->TestProperties->SkipReturnCode >= 0 &&
- this->TestProperties->SkipReturnCode == retVal) {
+ if ((this->TestProperties->SkipReturnCode >= 0 &&
+ this->TestProperties->SkipReturnCode == retVal) ||
+ forceSkip) {
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
std::ostringstream s;
- s << "SKIP_RETURN_CODE=" << this->TestProperties->SkipReturnCode;
+ if (forceSkip) {
+ s << "SKIP_REGULAR_EXPRESSION_MATCHED";
+ } else {
+ s << "SKIP_RETURN_CODE=" << this->TestProperties->SkipReturnCode;
+ }
this->TestResult.CompletionStatus = s.str();
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Skipped ");
skipped = true;
- } else if ((success && !this->TestProperties->WillFail) ||
- (!success && this->TestProperties->WillFail)) {
+ } else if (success != this->TestProperties->WillFail) {
this->TestResult.Status = cmCTestTestHandler::COMPLETED;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Passed ");
+ outputStream << " Passed ";
} else {
this->TestResult.Status = cmCTestTestHandler::FAILED;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Failed " << reason);
- outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure;
+ outputStream << "***Failed " << reason;
+ outputTestErrorsToConsole =
+ this->CTest->GetOutputTestOutputOnTestFailure();
}
- } else if (res == cmsysProcess_State_Expired) {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Timeout ");
+ } else if (res == cmProcess::State::Expired) {
+ outputStream << "***Timeout ";
this->TestResult.Status = cmCTestTestHandler::TIMEOUT;
- outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure;
- } else if (res == cmsysProcess_State_Exception) {
- outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Exception: ");
+ outputTestErrorsToConsole =
+ this->CTest->GetOutputTestOutputOnTestFailure();
+ } else if (res == cmProcess::State::Exception) {
+ outputTestErrorsToConsole =
+ this->CTest->GetOutputTestOutputOnTestFailure();
+ outputStream << "***Exception: ";
+ this->TestResult.ExceptionStatus =
+ this->TestProcess->GetExitExceptionString();
switch (this->TestProcess->GetExitException()) {
- case cmsysProcess_Exception_Fault:
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "SegFault");
+ case cmProcess::Exception::Fault:
+ outputStream << "SegFault";
this->TestResult.Status = cmCTestTestHandler::SEGFAULT;
break;
- case cmsysProcess_Exception_Illegal:
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "Illegal");
+ case cmProcess::Exception::Illegal:
+ outputStream << "Illegal";
this->TestResult.Status = cmCTestTestHandler::ILLEGAL;
break;
- case cmsysProcess_Exception_Interrupt:
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "Interrupt");
+ case cmProcess::Exception::Interrupt:
+ outputStream << "Interrupt";
this->TestResult.Status = cmCTestTestHandler::INTERRUPT;
break;
- case cmsysProcess_Exception_Numerical:
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "Numerical");
+ case cmProcess::Exception::Numerical:
+ outputStream << "Numerical";
this->TestResult.Status = cmCTestTestHandler::NUMERICAL;
break;
default:
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "Other");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ this->TestResult.ExceptionStatus);
this->TestResult.Status = cmCTestTestHandler::OTHER_FAULT;
}
} else if ("Disabled" == this->TestResult.CompletionStatus) {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Not Run (Disabled) ");
- } else // cmsysProcess_State_Error
+ outputStream << "***Not Run (Disabled) ";
+ } else // cmProcess::State::Error
{
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Not Run ");
+ outputStream << "***Not Run ";
}
passed = this->TestResult.Status == cmCTestTestHandler::COMPLETED;
char buf[1024];
- sprintf(buf, "%6.2f sec", this->TestProcess->GetTotalTime());
- cmCTestLog(this->CTest, HANDLER_OUTPUT, buf << "\n");
+ sprintf(buf, "%6.2f sec", this->TestProcess->GetTotalTime().count());
+ outputStream << buf << "\n";
+
+ if (this->CTest->GetTestProgressOutput()) {
+ if (!passed) {
+ // If the test did not pass, reprint test name and error
+ std::string output = GetTestPrefix(completed, total);
+ std::string testName = this->TestProperties->Name;
+ const int maxTestNameWidth = this->CTest->GetMaxTestNameWidth();
+ testName.resize(maxTestNameWidth + 4, '.');
+
+ output += testName;
+ output += outputStream.str();
+ outputStream.str("");
+ outputStream.clear();
+ outputStream << output;
+ cmCTestLog(this->CTest, HANDLER_TEST_PROGRESS_OUTPUT, "\n"); // flush
+ }
+ if (completed == total) {
+ std::string testName =
+ GetTestPrefix(completed, total) + this->TestProperties->Name + "\n";
+ cmCTestLog(this->CTest, HANDLER_TEST_PROGRESS_OUTPUT, testName);
+ }
+ }
+ if (!this->CTest->GetTestProgressOutput() || !passed) {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, outputStream.str());
+ }
if (outputTestErrorsToConsole) {
cmCTestLog(this->CTest, HANDLER_OUTPUT, this->ProcessOutput << std::endl);
@@ -278,11 +231,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
*this->TestHandler->LogFile << "Test time = " << buf << std::endl;
}
- // Set the working directory to the tests directory to process Dart files.
- {
- cmWorkingDirectory workdir(this->TestProperties->Directory);
- this->DartProcessing();
- }
+ this->DartProcessing();
// if this is doing MemCheck then all the output needs to be put into
// Output since that is what is parsed by cmCTestMemCheckHandler
@@ -303,12 +252,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;
@@ -334,10 +287,18 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
// if the test actually started and ran
// record the results in TestResult
if (started) {
- bool compress = !this->TestHandler->MemCheck &&
- this->CompressionRatio < 1 && this->CTest->ShouldCompressTestOutput();
+ std::string compressedOutput;
+ if (!this->TestHandler->MemCheck &&
+ this->CTest->ShouldCompressTestOutput()) {
+ std::string str = this->ProcessOutput;
+ if (this->CTest->CompressString(str)) {
+ compressedOutput = std::move(str);
+ }
+ }
+ bool compress = !compressedOutput.empty() &&
+ compressedOutput.length() < this->ProcessOutput.length();
this->TestResult.Output =
- compress ? this->CompressedOutput : this->ProcessOutput;
+ compress ? compressedOutput : this->ProcessOutput;
this->TestResult.CompressOutput = compress;
this->TestResult.ReturnValue = this->TestProcess->GetExitValue();
if (!skipped) {
@@ -352,11 +313,11 @@ 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;
}
-bool cmCTestRunTest::StartAgain()
+bool cmCTestRunTest::StartAgain(size_t completed)
{
if (!this->RunAgain) {
return false;
@@ -364,7 +325,14 @@ bool cmCTestRunTest::StartAgain()
this->RunAgain = false; // reset
// change to tests directory
cmWorkingDirectory workdir(this->TestProperties->Directory);
- this->StartTest(this->TotalNumberOfTests);
+ if (workdir.Failed()) {
+ this->StartFailure("Failed to change working directory to " +
+ this->TestProperties->Directory + " : " +
+ std::strerror(workdir.GetLastResult()));
+ return true;
+ }
+
+ this->StartTest(completed, this->TotalNumberOfTests);
return true;
}
@@ -388,7 +356,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 =
@@ -402,144 +370,210 @@ void cmCTestRunTest::MemCheckPostProcess()
if (!this->TestHandler->MemCheck) {
return;
}
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index
- << ": process test output now: "
- << this->TestProperties->Name << " "
- << this->TestResult.Name << std::endl,
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ this->Index << ": process test output now: "
+ << this->TestProperties->Name << " "
+ << this->TestResult.Name << std::endl,
this->TestHandler->GetQuiet());
cmCTestMemCheckHandler* handler =
static_cast<cmCTestMemCheckHandler*>(this->TestHandler);
handler->PostProcessTest(this->TestResult, this->Index);
}
+void cmCTestRunTest::StartFailure(std::string const& output)
+{
+ // Still need to log the Start message so the test summary records our
+ // attempt to start this test
+ if (!this->CTest->GetTestProgressOutput()) {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::setw(2 * getNumWidth(this->TotalNumberOfTests) + 8)
+ << "Start "
+ << std::setw(getNumWidth(this->TestHandler->GetMaxIndex()))
+ << this->TestProperties->Index << ": "
+ << this->TestProperties->Name << std::endl);
+ }
+
+ this->ProcessOutput.clear();
+ if (!output.empty()) {
+ *this->TestHandler->LogFile << output << std::endl;
+ cmCTestLog(this->CTest, ERROR_MESSAGE, output << std::endl);
+ }
+
+ this->TestResult.Properties = this->TestProperties;
+ this->TestResult.ExecutionTime = cmDuration::zero();
+ this->TestResult.CompressOutput = false;
+ this->TestResult.ReturnValue = -1;
+ this->TestResult.CompletionStatus = "Failed to start";
+ this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
+ this->TestResult.TestCount = this->TestProperties->Index;
+ this->TestResult.Name = this->TestProperties->Name;
+ this->TestResult.Path = this->TestProperties->Directory;
+ this->TestResult.Output = output;
+ this->TestResult.FullCommandLine.clear();
+ this->TestProcess = cm::make_unique<cmProcess>(*this);
+}
+
+std::string cmCTestRunTest::GetTestPrefix(size_t completed, size_t total) const
+{
+ std::ostringstream outputStream;
+ outputStream << std::setw(getNumWidth(total)) << completed << "/";
+ outputStream << std::setw(getNumWidth(total)) << total << " ";
+
+ if (this->TestHandler->MemCheck) {
+ outputStream << "MemCheck";
+ } else {
+ outputStream << "Test";
+ }
+
+ std::ostringstream indexStr;
+ indexStr << " #" << this->Index << ":";
+ outputStream << std::setw(3 + getNumWidth(this->TestHandler->GetMaxIndex()))
+ << indexStr.str();
+ outputStream << " ";
+
+ return outputStream.str();
+}
+
// Starts the execution of a test. Returns once it has started
-bool cmCTestRunTest::StartTest(size_t total)
+bool cmCTestRunTest::StartTest(size_t completed, size_t total)
{
this->TotalNumberOfTests = total; // save for rerun case
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(2 * getNumWidth(total) + 8)
- << "Start "
- << std::setw(getNumWidth(this->TestHandler->GetMaxIndex()))
- << this->TestProperties->Index << ": "
- << this->TestProperties->Name << std::endl);
+ if (!this->CTest->GetTestProgressOutput()) {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::setw(2 * getNumWidth(total) + 8)
+ << "Start "
+ << std::setw(getNumWidth(this->TestHandler->GetMaxIndex()))
+ << this->TestProperties->Index << ": "
+ << this->TestProperties->Name << std::endl);
+ } else {
+ std::string testName =
+ GetTestPrefix(completed, total) + this->TestProperties->Name + "\n";
+ cmCTestLog(this->CTest, HANDLER_TEST_PROGRESS_OUTPUT, testName);
+ }
+
this->ProcessOutput.clear();
+ this->TestResult.Properties = this->TestProperties;
+ this->TestResult.ExecutionTime = cmDuration::zero();
+ this->TestResult.CompressOutput = false;
+ this->TestResult.ReturnValue = -1;
+ this->TestResult.TestCount = this->TestProperties->Index;
+ this->TestResult.Name = this->TestProperties->Name;
+ this->TestResult.Path = this->TestProperties->Directory;
+
// Return immediately if test is disabled
if (this->TestProperties->Disabled) {
- this->TestResult.Properties = this->TestProperties;
- this->TestResult.ExecutionTime = 0;
- this->TestResult.CompressOutput = false;
- this->TestResult.ReturnValue = -1;
this->TestResult.CompletionStatus = "Disabled";
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
- 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 = "";
+ 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.CompressOutput = false;
- this->TestResult.ReturnValue = -1;
this->TestResult.CompletionStatus = "Failed to start";
this->TestResult.Status = cmCTestTestHandler::BAD_COMMAND;
- this->TestResult.TestCount = this->TestProperties->Index;
- 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::set<std::string>::const_iterator it =
- this->FailedDependencies.begin();
- it != this->FailedDependencies.end(); ++it) {
- msg += " " + *it;
+ for (std::string const& failedDep : this->FailedDependencies) {
+ msg += " " + failedDep;
}
*this->TestHandler->LogFile << msg << std::endl;
cmCTestLog(this->CTest, HANDLER_OUTPUT, msg << std::endl);
this->TestResult.Output = msg;
- this->TestResult.FullCommandLine = "";
+ this->TestResult.FullCommandLine.clear();
this->TestResult.CompletionStatus = "Fixture dependency failed";
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
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.";
- msg += " (Missing \"-C <config>\"?)";
+ msg = "Test not available without configuration. (Missing \"-C "
+ "<config>\"?)";
} else {
- msg = "Test not available in configuration \"";
- msg += this->CTest->GetConfigType();
- msg += "\".";
+ msg = cmStrCat("Test not available in configuration \"",
+ this->CTest->GetConfigType(), "\".");
}
*this->TestHandler->LogFile << msg << std::endl;
cmCTestLog(this->CTest, ERROR_MESSAGE, msg << std::endl);
this->TestResult.Output = msg;
- this->TestResult.FullCommandLine = "";
+ this->TestResult.FullCommandLine.clear();
this->TestResult.CompletionStatus = "Missing Configuration";
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
return false;
}
// Check if all required files exist
- for (std::vector<std::string>::iterator i =
- this->TestProperties->RequiredFiles.begin();
- i != this->TestProperties->RequiredFiles.end(); ++i) {
- std::string file = *i;
-
- if (!cmSystemTools::FileExists(file.c_str())) {
+ for (std::string const& file : this->TestProperties->RequiredFiles) {
+ 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,
"Unable to find required file: " << file << std::endl);
this->TestResult.Output = "Unable to find required file: " + file;
- this->TestResult.FullCommandLine = "";
+ this->TestResult.FullCommandLine.clear();
this->TestResult.CompletionStatus = "Required Files Missing";
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
return false;
}
}
// log and return if we did not find the executable
- if (this->ActualCommand == "") {
+ 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,
"Unable to find executable: " << args[1] << std::endl);
this->TestResult.Output = "Unable to find executable: " + args[1];
- this->TestResult.FullCommandLine = "";
+ this->TestResult.FullCommandLine.clear();
this->TestResult.CompletionStatus = "Unable to find executable";
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
return false;
}
this->StartTime = this->CTest->CurrentTime();
- double timeout = this->ResolveTimeout();
+ auto timeout = this->TestProperties->Timeout;
- if (this->StopTimePassed) {
- return false;
+ this->TimeoutIsForStopTime = 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) {
+ this->TimeoutIsForStopTime = true;
+ timeout = stop_timeout;
+ }
}
+
return this->ForkProcess(timeout, this->TestProperties->ExplicitTimeout,
- &this->TestProperties->Environment);
+ &this->TestProperties->Environment,
+ &this->TestProperties->Affinity);
}
void cmCTestRunTest::ComputeArguments()
{
- this->Arguments.clear(); // reset becaue this might be a rerun
- std::vector<std::string>::const_iterator j =
- this->TestProperties->Args.begin();
+ this->Arguments.clear(); // reset because this might be a rerun
+ auto j = this->TestProperties->Args.begin();
++j; // skip test name
// find the test executable
if (this->TestHandler->MemCheck) {
@@ -554,14 +588,13 @@ 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);
- for (std::vector<std::string>::iterator i = this->Arguments.begin();
- i != this->Arguments.end(); ++i) {
+ for (std::string const& arg : this->Arguments) {
testCommand += " \"";
- testCommand += *i;
+ testCommand += arg;
testCommand += "\"";
}
@@ -574,22 +607,21 @@ void cmCTestRunTest::ComputeArguments()
this->TestResult.FullCommandLine = testCommand;
// Print the test command in verbose mode
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ std::endl
<< this->Index << ": "
<< (this->TestHandler->MemCheck ? "MemCheck" : "Test")
<< " command: " << testCommand << std::endl);
// Print any test-specific env vars in verbose mode
if (!this->TestProperties->Environment.empty()) {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index
- << ": "
- << "Environment variables: " << std::endl);
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ this->Index << ": "
+ << "Environment variables: " << std::endl);
}
- for (std::vector<std::string>::const_iterator e =
- this->TestProperties->Environment.begin();
- e != this->TestProperties->Environment.end(); ++e) {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index << ": " << *e
- << std::endl);
+ for (std::string const& env : this->TestProperties->Environment) {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ this->Index << ": " << env << std::endl);
}
}
@@ -597,10 +629,10 @@ void cmCTestRunTest::DartProcessing()
{
if (!this->ProcessOutput.empty() &&
this->ProcessOutput.find("<DartMeasurement") != std::string::npos) {
- if (this->TestHandler->DartStuff.find(this->ProcessOutput.c_str())) {
+ if (this->TestHandler->DartStuff.find(this->ProcessOutput)) {
this->TestResult.DartString = this->TestHandler->DartStuff.match(1);
// keep searching and replacing until none are left
- while (this->TestHandler->DartStuff1.find(this->ProcessOutput.c_str())) {
+ while (this->TestHandler->DartStuff1.find(this->ProcessOutput)) {
// replace the exact match for the string
cmSystemTools::ReplaceString(
this->ProcessOutput, this->TestHandler->DartStuff1.match(1).c_str(),
@@ -610,97 +642,47 @@ void cmCTestRunTest::DartProcessing()
}
}
-double cmCTestRunTest::ResolveTimeout()
-{
- double timeout = this->TestProperties->Timeout;
-
- if (this->CTest->GetStopTime() == "") {
- return timeout;
- }
- struct tm* lctime;
- time_t current_time = time(CM_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,
- std::vector<std::string>* environment)
+bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
+ std::vector<std::string>* environment,
+ std::vector<size_t>* affinity)
{
- this->TestProcess = new cmProcess;
+ this->TestProcess = cm::make_unique<cmProcess>(*this);
this->TestProcess->SetId(this->Index);
- this->TestProcess->SetWorkingDirectory(
- this->TestProperties->Directory.c_str());
- this->TestProcess->SetCommand(this->ActualCommand.c_str());
+ this->TestProcess->SetWorkingDirectory(this->TestProperties->Directory);
+ this->TestProcess->SetCommand(this->ActualCommand);
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;
- }
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index
- << ": "
- << "Test timeout computed to be: " << timeout << "\n",
+ if (testTimeOut == cmDuration::zero() && explicitTimeout) {
+ timeout = cmDuration::zero();
+ }
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ this->Index << ": "
+ << "Test timeout computed to be: "
+ << cmDurationTo<unsigned int>(timeout)
+ << "\n",
this->TestHandler->GetQuiet());
this->TestProcess->SetTimeout(timeout);
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
cmSystemTools::SaveRestoreEnvironment sre;
#endif
@@ -708,49 +690,89 @@ bool cmCTestRunTest::ForkProcess(double testTimeOut, bool explicitTimeout,
cmSystemTools::AppendEnv(*environment);
}
- return this->TestProcess->StartProcess();
+ if (this->UseAllocatedResources) {
+ this->SetupResourcesEnvironment();
+ } else {
+ cmSystemTools::UnsetEnv("CTEST_RESOURCE_GROUP_COUNT");
+ }
+
+ return this->TestProcess->StartProcess(this->MultiTestHandler.Loop,
+ affinity);
+}
+
+void cmCTestRunTest::SetupResourcesEnvironment()
+{
+ std::string processCount = "CTEST_RESOURCE_GROUP_COUNT=";
+ processCount += std::to_string(this->AllocatedResources.size());
+ cmSystemTools::PutEnv(processCount);
+
+ std::size_t i = 0;
+ for (auto const& process : this->AllocatedResources) {
+ std::string prefix = "CTEST_RESOURCE_GROUP_";
+ prefix += std::to_string(i);
+ std::string resourceList = prefix + '=';
+ prefix += '_';
+ bool firstType = true;
+ for (auto const& it : process) {
+ if (!firstType) {
+ resourceList += ',';
+ }
+ firstType = false;
+ auto resourceType = it.first;
+ resourceList += resourceType;
+ std::string var = prefix + cmSystemTools::UpperCase(resourceType) + '=';
+ bool firstName = true;
+ for (auto const& it2 : it.second) {
+ if (!firstName) {
+ var += ';';
+ }
+ firstName = false;
+ var += "id:" + it2.Id + ",slots:" + std::to_string(it2.Slots);
+ }
+ cmSystemTools::PutEnv(var);
+ }
+ cmSystemTools::PutEnv(resourceList);
+ ++i;
+ }
}
void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total)
{
- // if this is the last or only run of this test
- // then print out completed / total
+ std::ostringstream outputStream;
+
+ // If this is the last or only run of this test, or progress output is
+ // requested, then print out completed / total.
// Only issue is if a test fails and we are running until fail
// then it will never print out the completed / total, same would
// got for run until pass. Trick is when this is called we don't
// yet know if we are passing or failing.
- if (this->NumberOfRunsLeft == 1) {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total))
- << completed << "/");
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total))
- << total << " ");
+ if (this->NumberOfRunsLeft == 1 || this->CTest->GetTestProgressOutput()) {
+ outputStream << std::setw(getNumWidth(total)) << completed << "/";
+ outputStream << std::setw(getNumWidth(total)) << total << " ";
}
// if this is one of several runs of a test just print blank space
// to keep things neat
else {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total))
- << " "
- << " ");
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::setw(getNumWidth(total))
- << " "
- << " ");
+ outputStream << std::setw(getNumWidth(total)) << " ";
+ outputStream << std::setw(getNumWidth(total)) << " ";
}
if (this->TestHandler->MemCheck) {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "MemCheck");
+ outputStream << "MemCheck";
} else {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "Test");
+ outputStream << "Test";
}
std::ostringstream indexStr;
indexStr << " #" << this->Index << ":";
- cmCTestLog(this->CTest, HANDLER_OUTPUT,
- std::setw(3 + getNumWidth(this->TestHandler->GetMaxIndex()))
- << indexStr.str());
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " ");
+ outputStream << std::setw(3 + getNumWidth(this->TestHandler->GetMaxIndex()))
+ << indexStr.str();
+ outputStream << " ";
+
const int maxTestNameWidth = this->CTest->GetMaxTestNameWidth();
std::string outname = this->TestProperties->Name + " ";
outname.resize(maxTestNameWidth + 4, '.');
+ outputStream << outname;
*this->TestHandler->LogFile << this->TestProperties->Index << "/"
<< this->TestHandler->TotalNumberOfTests
@@ -762,9 +784,8 @@ void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total)
<< std::endl;
*this->TestHandler->LogFile << "Command: \"" << this->ActualCommand << "\"";
- for (std::vector<std::string>::iterator i = this->Arguments.begin();
- i != this->Arguments.end(); ++i) {
- *this->TestHandler->LogFile << " \"" << *i << "\"";
+ for (std::string const& arg : this->Arguments) {
+ *this->TestHandler->LogFile << " \"" << arg << "\"";
}
*this->TestHandler->LogFile
<< std::endl
@@ -779,7 +800,15 @@ void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total)
*this->TestHandler->LogFile << this->ProcessOutput << "<end of output>"
<< std::endl;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, outname.c_str());
- cmCTestLog(this->CTest, DEBUG, "Testing " << this->TestProperties->Name
- << " ... ");
+ if (!this->CTest->GetTestProgressOutput()) {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, outputStream.str());
+ }
+
+ 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..f781c7ab0 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -5,15 +5,20 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <map>
+#include <memory>
#include <set>
-#include <stddef.h>
#include <string>
#include <vector>
+#include <stddef.h>
+
+#include "cmCTestMultiProcessHandler.h"
#include "cmCTestTestHandler.h"
+#include "cmDuration.h"
+#include "cmProcess.h"
class cmCTest;
-class cmProcess;
/** \class cmRunTest
* \brief represents a single test to be run
@@ -23,8 +28,7 @@ class cmProcess;
class cmCTestRunTest
{
public:
- cmCTestRunTest(cmCTestTestHandler* handler);
- ~cmCTestRunTest();
+ explicit cmCTestRunTest(cmCTestMultiProcessHandler& multiHandler);
void SetNumberOfRuns(int n) { this->NumberOfRunsLeft = n; }
void SetRunUntilFailOn() { this->RunUntilFail = true; }
@@ -49,21 +53,16 @@ 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();
-
- // Compresses the output, writing to CompressedOutput
- void CompressOutput();
+ void CheckOutput(std::string const& line);
// launch the test process, return whether it started correctly
- bool StartTest(size_t total);
+ bool StartTest(size_t completed, size_t total);
// capture and report the test results
bool EndTest(size_t completed, size_t total, bool started);
// Called by ctest -N to log the command string
@@ -71,44 +70,68 @@ public:
void ComputeWeightedCost();
- bool StartAgain();
+ bool StartAgain(size_t completed);
+
+ void StartFailure(std::string const& output);
+
+ cmCTest* GetCTest() const { return this->CTest; }
+
+ std::string& GetActualCommand() { return this->ActualCommand; }
+
+ const std::vector<std::string>& GetArguments() { return this->Arguments; }
+
+ void FinalizeTest();
+
+ bool TimedOutForStopTime() const { return this->TimeoutIsForStopTime; }
+
+ void SetUseAllocatedResources(bool use)
+ {
+ this->UseAllocatedResources = use;
+ }
+ void SetAllocatedResources(
+ const std::vector<
+ std::map<std::string,
+ std::vector<cmCTestMultiProcessHandler::ResourceAllocation>>>&
+ resources)
+ {
+ this->AllocatedResources = resources;
+ }
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,
- std::vector<std::string>* environment);
+ bool ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
+ std::vector<std::string>* environment,
+ std::vector<size_t>* affinity);
void WriteLogOutputTop(size_t completed, size_t total);
// Run post processing of the process output for MemCheck
void MemCheckPostProcess();
+ void SetupResourcesEnvironment();
+
+ // Returns "completed/total Test #Index: "
+ std::string GetTestPrefix(size_t completed, size_t total) const;
+
cmCTestTestHandler::cmCTestTestProperties* TestProperties;
+ bool TimeoutIsForStopTime = false;
// 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 UseAllocatedResources = false;
+ std::vector<std::map<
+ std::string, std::vector<cmCTestMultiProcessHandler::ResourceAllocation>>>
+ AllocatedResources;
bool RunUntilFail;
int NumberOfRunsLeft;
bool RunAgain;
@@ -117,14 +140,12 @@ private:
inline int getNumWidth(size_t n)
{
- int numWidth = 1;
- if (n >= 10) {
- numWidth = 2;
- }
- if (n >= 100) {
- numWidth = 3;
+ int w = 1;
+ while (n >= 10) {
+ n /= 10;
+ ++w;
}
- return numWidth;
+ return w;
}
#endif
diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx
index f60f78c21..34395c9fe 100644
--- a/Source/CTest/cmCTestSVN.cxx
+++ b/Source/CTest/cmCTestSVN.cxx
@@ -2,19 +2,22 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestSVN.h"
+#include <cstdlib>
+#include <cstring>
+#include <map>
+#include <ostream>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestVC.h"
#include "cmProcessTools.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
#include "cmXMLWriter.h"
-#include "cmsys/RegularExpression.hxx"
-#include <map>
-#include <ostream>
-#include <stdlib.h>
-#include <string.h>
-
struct cmCTestSVN::Revision : public cmCTestVC::Revision
{
cmCTestSVN::SVNInfo* SVNInfo;
@@ -26,9 +29,7 @@ cmCTestSVN::cmCTestSVN(cmCTest* ct, std::ostream& log)
this->PriorRev = this->Unknown;
}
-cmCTestSVN::~cmCTestSVN()
-{
-}
+cmCTestSVN::~cmCTestSVN() = default;
void cmCTestSVN::CleanupImpl()
{
@@ -59,7 +60,7 @@ private:
cmsys::RegularExpression RegexRev;
cmsys::RegularExpression RegexURL;
cmsys::RegularExpression RegexRoot;
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (this->RegexRev.find(this->Line)) {
this->Rev = this->RegexRev.match(1);
@@ -103,16 +104,14 @@ bool cmCTestSVN::NoteOldRevision()
return false;
}
- std::vector<SVNInfo>::iterator itbeg = this->Repositories.begin();
- std::vector<SVNInfo>::iterator itend = this->Repositories.end();
- for (; itbeg != itend; itbeg++) {
- SVNInfo& svninfo = *itbeg;
+ for (SVNInfo& svninfo : this->Repositories) {
svninfo.OldRevision = this->LoadInfo(svninfo);
this->Log << "Revision for repository '" << svninfo.LocalPath
<< "' before update: " << svninfo.OldRevision << "\n";
- cmCTestLog(
- this->CTest, HANDLER_OUTPUT, " Old revision of external repository '"
- << svninfo.LocalPath << "' is: " << svninfo.OldRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Old revision of external repository '"
+ << svninfo.LocalPath << "' is: " << svninfo.OldRevision
+ << "\n");
}
// Set the global old revision to the one of the root
@@ -127,16 +126,14 @@ bool cmCTestSVN::NoteNewRevision()
return false;
}
- std::vector<SVNInfo>::iterator itbeg = this->Repositories.begin();
- std::vector<SVNInfo>::iterator itend = this->Repositories.end();
- for (; itbeg != itend; itbeg++) {
- SVNInfo& svninfo = *itbeg;
+ for (SVNInfo& svninfo : this->Repositories) {
svninfo.NewRevision = this->LoadInfo(svninfo);
this->Log << "Revision for repository '" << svninfo.LocalPath
<< "' after update: " << svninfo.NewRevision << "\n";
- cmCTestLog(
- this->CTest, HANDLER_OUTPUT, " New revision of external repository '"
- << svninfo.LocalPath << "' is: " << svninfo.NewRevision << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " New revision of external repository '"
+ << svninfo.LocalPath << "' is: " << svninfo.NewRevision
+ << "\n");
// svninfo.Root = ""; // uncomment to test GuessBase
this->Log << "Repository '" << svninfo.LocalPath
@@ -148,9 +145,8 @@ bool cmCTestSVN::NoteNewRevision()
// the repository root.
if (!svninfo.Root.empty() &&
cmCTestSVNPathStarts(svninfo.URL, svninfo.Root)) {
- svninfo.Base =
- cmCTest::DecodeURL(svninfo.URL.substr(svninfo.Root.size()));
- svninfo.Base += "/";
+ svninfo.Base = cmStrCat(
+ cmCTest::DecodeURL(svninfo.URL.substr(svninfo.Root.size())), '/');
}
this->Log << "Repository '" << svninfo.LocalPath
<< "' Base = " << svninfo.Base << "\n";
@@ -174,7 +170,7 @@ void cmCTestSVN::GuessBase(SVNInfo& svninfo,
slash = svninfo.URL.find('/', slash + 1)) {
// If the URL suffix is a prefix of at least one path then it is the base.
std::string base = cmCTest::DecodeURL(svninfo.URL.substr(slash));
- for (std::vector<Change>::const_iterator ci = changes.begin();
+ for (auto ci = changes.begin();
svninfo.Base.empty() && ci != changes.end(); ++ci) {
if (cmCTestSVNPathStarts(ci->Path, base)) {
svninfo.Base = base;
@@ -205,7 +201,7 @@ private:
cmCTestSVN* SVN;
cmsys::RegularExpression RegexUpdate;
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (this->RegexUpdate.find(this->Line)) {
this->DoPath(this->RegexUpdate.match(1)[0],
@@ -248,7 +244,7 @@ bool cmCTestSVN::UpdateImpl()
if (opts.empty()) {
opts = this->CTest->GetCTestConfiguration("SVNUpdateOptions");
}
- std::vector<std::string> args = cmSystemTools::ParseArguments(opts.c_str());
+ std::vector<std::string> args = cmSystemTools::ParseArguments(opts);
// Specify the start time for nightly testing.
if (this->CTest->GetTestModel() == cmCTest::NIGHTLY) {
@@ -257,9 +253,8 @@ bool cmCTestSVN::UpdateImpl()
std::vector<char const*> svn_update;
svn_update.push_back("update");
- for (std::vector<std::string>::const_iterator ai = args.begin();
- ai != args.end(); ++ai) {
- svn_update.push_back(ai->c_str());
+ for (std::string const& arg : args) {
+ svn_update.push_back(arg.c_str());
}
UpdateParser out(this, "up-out> ");
@@ -276,21 +271,18 @@ bool cmCTestSVN::RunSVNCommand(std::vector<char const*> const& parameters,
std::vector<char const*> args;
args.push_back(this->CommandLineTool.c_str());
-
- args.insert(args.end(), parameters.begin(), parameters.end());
-
+ cmAppend(args, parameters);
args.push_back("--non-interactive");
std::string userOptions = this->CTest->GetCTestConfiguration("SVNOptions");
std::vector<std::string> parsedUserOptions =
- cmSystemTools::ParseArguments(userOptions.c_str());
- for (std::vector<std::string>::iterator i = parsedUserOptions.begin();
- i != parsedUserOptions.end(); ++i) {
- args.push_back(i->c_str());
+ cmSystemTools::ParseArguments(userOptions);
+ for (std::string const& opt : parsedUserOptions) {
+ args.push_back(opt.c_str());
}
- args.push_back(CM_NULLPTR);
+ args.push_back(nullptr);
if (strcmp(parameters[0], "update") == 0) {
return RunUpdateCommand(&args[0], out, err);
@@ -298,8 +290,9 @@ bool cmCTestSVN::RunSVNCommand(std::vector<char const*> const& parameters,
return RunChild(&args[0], out, err);
}
-class cmCTestSVN::LogParser : public cmCTestVC::OutputLogger,
- private cmXMLParser
+class cmCTestSVN::LogParser
+ : public cmCTestVC::OutputLogger
+ , private cmXMLParser
{
public:
LogParser(cmCTestSVN* svn, const char* prefix, SVNInfo& svninfo)
@@ -309,49 +302,52 @@ public:
{
this->InitializeParser();
}
- ~LogParser() CM_OVERRIDE { this->CleanupParser(); }
+ ~LogParser() override { this->CleanupParser(); }
+
private:
cmCTestSVN* SVN;
cmCTestSVN::SVNInfo& SVNRepo;
- typedef cmCTestSVN::Revision Revision;
- typedef cmCTestSVN::Change Change;
+ using Revision = cmCTestSVN::Revision;
+ using Change = cmCTestSVN::Change;
Revision Rev;
std::vector<Change> Changes;
Change CurChange;
std::vector<char> CData;
- bool ProcessChunk(const char* data, int length) CM_OVERRIDE
+ bool ProcessChunk(const char* data, int length) override
{
this->OutputLogger::ProcessChunk(data, length);
this->ParseChunk(data, length);
return true;
}
- void StartElement(const std::string& name, const char** atts) CM_OVERRIDE
+ void StartElement(const std::string& name, const char** atts) override
{
this->CData.clear();
if (name == "logentry") {
this->Rev = Revision();
this->Rev.SVNInfo = &SVNRepo;
- if (const char* rev = this->FindAttribute(atts, "revision")) {
+ if (const char* rev =
+ cmCTestSVN::LogParser::FindAttribute(atts, "revision")) {
this->Rev.Rev = rev;
}
this->Changes.clear();
} else if (name == "path") {
this->CurChange = Change();
- if (const char* action = this->FindAttribute(atts, "action")) {
+ if (const char* action =
+ cmCTestSVN::LogParser::FindAttribute(atts, "action")) {
this->CurChange.Action = action[0];
}
}
}
- void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
+ void CharacterDataHandler(const char* data, int length) override
{
- this->CData.insert(this->CData.end(), data, data + length);
+ cmAppend(this->CData, data, data + length);
}
- void EndElement(const std::string& name) CM_OVERRIDE
+ void EndElement(const std::string& name) override
{
if (name == "logentry") {
this->SVN->DoRevisionSVN(this->Rev, this->Changes);
@@ -370,7 +366,7 @@ private:
this->CData.clear();
}
- void ReportError(int /*line*/, int /*column*/, const char* msg) CM_OVERRIDE
+ void ReportError(int /*line*/, int /*column*/, const char* msg) override
{
this->SVN->Log << "Error parsing svn log xml: " << msg << "\n";
}
@@ -380,10 +376,7 @@ bool cmCTestSVN::LoadRevisions()
{
bool result = true;
// Get revisions for all the external repositories
- std::vector<SVNInfo>::iterator itbeg = this->Repositories.begin();
- std::vector<SVNInfo>::iterator itend = this->Repositories.end();
- for (; itbeg != itend; itbeg++) {
- SVNInfo& svninfo = *itbeg;
+ for (SVNInfo& svninfo : this->Repositories) {
result = this->LoadRevisions(svninfo) && result;
}
return result;
@@ -421,7 +414,7 @@ void cmCTestSVN::DoRevisionSVN(Revision const& revision,
// Ignore changes in the old revision for external repositories
if (revision.Rev == revision.SVNInfo->OldRevision &&
- revision.SVNInfo->LocalPath != "") {
+ !revision.SVNInfo->LocalPath.empty()) {
return;
}
@@ -441,7 +434,7 @@ public:
private:
cmCTestSVN* SVN;
cmsys::RegularExpression RegexStatus;
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (this->RegexStatus.find(this->Line)) {
this->DoPath(this->RegexStatus.match(1)[0],
@@ -507,7 +500,7 @@ public:
private:
cmCTestSVN* SVN;
cmsys::RegularExpression RegexExternal;
- bool ProcessLine() CM_OVERRIDE
+ bool ProcessLine() override
{
if (this->RegexExternal.find(this->Line)) {
this->DoPath(this->RegexExternal.match(1));
@@ -522,11 +515,11 @@ private:
if (path.size() > this->SVN->SourceDirectory.size() &&
strncmp(path.c_str(), this->SVN->SourceDirectory.c_str(),
this->SVN->SourceDirectory.size()) == 0) {
- local_path = path.c_str() + this->SVN->SourceDirectory.size() + 1;
+ local_path = path.substr(this->SVN->SourceDirectory.size() + 1);
} else {
local_path = path;
}
- this->SVN->Repositories.push_back(SVNInfo(local_path.c_str()));
+ this->SVN->Repositories.emplace_back(local_path);
}
};
@@ -537,7 +530,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
@@ -561,7 +554,7 @@ std::string cmCTestSVN::SVNInfo::BuildLocalPath(std::string const& path) const
// Add path with base prefix removed
if (path.size() > this->Base.size() &&
strncmp(path.c_str(), this->Base.c_str(), this->Base.size()) == 0) {
- local_path += (path.c_str() + this->Base.size());
+ local_path += path.substr(this->Base.size());
} else {
local_path += path;
}
diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h
index 46b077835..b74dc12b0 100644
--- a/Source/CTest/cmCTestSVN.h
+++ b/Source/CTest/cmCTestSVN.h
@@ -3,14 +3,15 @@
#ifndef cmCTestSVN_h
#define cmCTestSVN_h
-#include "cmConfigure.h"
-
-#include "cmCTestGlobalVC.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
+#include <list>
#include <string>
#include <vector>
+#include "cmCTestGlobalVC.h"
+
class cmCTest;
class cmXMLWriter;
@@ -24,14 +25,14 @@ public:
/** Construct with a CTest instance and update log stream. */
cmCTestSVN(cmCTest* ctest, std::ostream& log);
- ~cmCTestSVN() CM_OVERRIDE;
+ ~cmCTestSVN() override;
private:
// Implement cmCTestVC internal API.
- void CleanupImpl() CM_OVERRIDE;
- bool NoteOldRevision() CM_OVERRIDE;
- bool NoteNewRevision() CM_OVERRIDE;
- bool UpdateImpl() CM_OVERRIDE;
+ void CleanupImpl() override;
+ bool NoteOldRevision() override;
+ bool NoteNewRevision() override;
+ bool UpdateImpl() override;
bool RunSVNCommand(std::vector<char const*> const& parameters,
OutputParser* out, OutputParser* err);
@@ -40,7 +41,7 @@ private:
struct SVNInfo
{
- SVNInfo(const char* path)
+ SVNInfo(std::string const& path = std::string())
: LocalPath(path)
{
}
@@ -70,15 +71,16 @@ 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;
std::string LoadInfo(SVNInfo& svninfo);
bool LoadRepositories();
- bool LoadModifications() CM_OVERRIDE;
- bool LoadRevisions() CM_OVERRIDE;
+ bool LoadModifications() override;
+ bool LoadRevisions() override;
bool LoadRevisions(SVNInfo& svninfo);
void GuessBase(SVNInfo& svninfo, std::vector<Change> const& changes);
@@ -86,7 +88,7 @@ private:
void DoRevisionSVN(Revision const& revision,
std::vector<Change> const& changes);
- void WriteXMLGlobal(cmXMLWriter& xml) CM_OVERRIDE;
+ void WriteXMLGlobal(cmXMLWriter& xml) override;
class ExternalParser;
// Parsing helper classes.
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index 1d29dfac2..60facbdf5 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -2,15 +2,20 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestScriptHandler.h"
-#include "cmsys/Directory.hxx"
-#include "cmsys/Process.h"
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
#include <map>
+#include <memory>
+#include <ratio>
#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <utility>
+#include <cm/memory>
+
+#include "cmsys/Directory.hxx"
+#include "cmsys/Process.h"
+
#include "cmCTest.h"
#include "cmCTestBuildCommand.h"
#include "cmCTestCommand.h"
@@ -26,62 +31,39 @@
#include "cmCTestTestCommand.h"
#include "cmCTestUpdateCommand.h"
#include "cmCTestUploadCommand.h"
-#include "cmFunctionBlocker.h"
+#include "cmCommand.h"
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
#ifdef _WIN32
-#include <windows.h>
+# include <windows.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif
-class cmExecutionStatus;
-struct cmListFileFunction;
-
#define CTEST_INITIAL_CMAKE_OUTPUT_FILE_NAME "CTestInitialCMakeOutput.log"
-// used to keep elapsed time up to date
-class cmCTestScriptFunctionBlocker : public cmFunctionBlocker
-{
-public:
- cmCTestScriptFunctionBlocker() {}
- ~cmCTestScriptFunctionBlocker() CM_OVERRIDE {}
- bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
- cmExecutionStatus& /*status*/) CM_OVERRIDE;
- // virtual bool ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf);
- // virtual void ScopeEnded(cmMakefile &mf);
-
- cmCTestScriptHandler* CTestScriptHandler;
-};
-
-// simply update the time and don't block anything
-bool cmCTestScriptFunctionBlocker::IsFunctionBlocked(
- const cmListFileFunction& /*lff*/, cmMakefile& /*mf*/,
- cmExecutionStatus& /*status*/)
-{
- this->CTestScriptHandler->UpdateElapsedTime();
- return false;
-}
-
cmCTestScriptHandler::cmCTestScriptHandler()
{
this->Backup = false;
this->EmptyBinDir = false;
this->EmptyBinDirOnce = false;
- this->Makefile = CM_NULLPTR;
- this->CMake = CM_NULLPTR;
- this->GlobalGenerator = CM_NULLPTR;
+ this->Makefile = nullptr;
+ this->ParentMakefile = nullptr;
+ 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;
}
@@ -93,31 +75,32 @@ void cmCTestScriptHandler::Initialize()
this->EmptyBinDir = false;
this->EmptyBinDirOnce = false;
- this->SourceDir = "";
- this->BinaryDir = "";
- this->BackupSourceDir = "";
- this->BackupBinaryDir = "";
- this->CTestRoot = "";
- this->CVSCheckOut = "";
- this->CTestCmd = "";
- this->UpdateCmd = "";
- this->CTestEnv = "";
- this->InitialCache = "";
- this->CMakeCmd = "";
- this->CMOutFile = "";
+ this->SourceDir.clear();
+ this->BinaryDir.clear();
+ this->BackupSourceDir.clear();
+ this->BackupBinaryDir.clear();
+ this->CTestRoot.clear();
+ this->CVSCheckOut.clear();
+ this->CTestCmd.clear();
+ this->UpdateCmd.clear();
+ this->CTestEnv.clear();
+ this->InitialCache.clear();
+ this->CMakeCmd.clear();
+ this->CMOutFile.clear();
this->ExtraUpdates.clear();
this->MinimumInterval = 20 * 60;
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 = CM_NULLPTR;
+ this->Makefile = nullptr;
+ this->ParentMakefile = nullptr;
delete this->GlobalGenerator;
- this->GlobalGenerator = CM_NULLPTR;
+ this->GlobalGenerator = nullptr;
delete this->CMake;
}
@@ -133,7 +116,7 @@ cmCTestScriptHandler::~cmCTestScriptHandler()
void cmCTestScriptHandler::AddConfigurationScript(const char* script,
bool pscope)
{
- this->ConfigurationScripts.push_back(script);
+ this->ConfigurationScripts.emplace_back(script);
this->ScriptProcessScope.push_back(pscope);
}
@@ -158,20 +141,19 @@ 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);
+ 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);
}
}
-void cmCTestScriptHandler::AddCTestCommand(std::string const& name,
- cmCTestCommand* command)
+void cmCTestScriptHandler::AddCTestCommand(
+ std::string const& name, std::unique_ptr<cmCTestCommand> command)
{
command->CTest = this->CTest;
command->CTestScriptHandler = this;
- this->CMake->GetState()->AddBuiltinCommand(name, command);
+ this->CMake->GetState()->AddBuiltinCommand(name, std::move(command));
}
int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg)
@@ -183,8 +165,9 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg)
argv.push_back("-SR");
argv.push_back(total_script_arg.c_str());
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Executable for CTest is: "
- << cmSystemTools::GetCTestCommand() << "\n");
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Executable for CTest is: " << cmSystemTools::GetCTestCommand()
+ << "\n");
// now pass through all the other arguments
std::vector<std::string>& initArgs =
@@ -193,11 +176,11 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg)
for (size_t i = 1; i < initArgs.size(); ++i) {
argv.push_back(initArgs[i].c_str());
}
- argv.push_back(CM_NULLPTR);
+ argv.push_back(nullptr);
// Now create process object
cmsysProcess* cp = cmsysProcess_New();
- cmsysProcess_SetCommand(cp, &*argv.begin());
+ cmsysProcess_SetCommand(cp, argv.data());
// cmsysProcess_SetWorkingDirectory(cp, dir);
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
// cmsysProcess_SetTimeout(cp, timeout);
@@ -206,20 +189,22 @@ 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");
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Output: " << line << "\n");
if (pipe == cmsysProcess_Pipe_STDERR) {
cmCTestLog(this->CTest, ERROR_MESSAGE, line << "\n");
} 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
- cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+ cmsysProcess_WaitForExit(cp, nullptr);
int result = cmsysProcess_GetState(cp);
int retVal = 0;
bool failed = false;
@@ -227,17 +212,19 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg)
retVal = cmsysProcess_GetExitValue(cp);
} else if (result == cmsysProcess_State_Exception) {
retVal = cmsysProcess_GetExitException(cp);
- cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was an exception: "
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "\tThere was an exception: "
<< cmsysProcess_GetExceptionString(cp) << " " << retVal
<< std::endl);
failed = true;
} else if (result == cmsysProcess_State_Expired) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was a timeout"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "\tThere was a timeout" << std::endl);
failed = true;
} else if (result == cmsysProcess_State_Error) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "\tError executing ctest: "
- << cmsysProcess_GetErrorString(cp) << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "\tError executing ctest: " << cmsysProcess_GetErrorString(cp)
+ << std::endl);
failed = true;
}
cmsysProcess_Delete(cp);
@@ -245,28 +232,18 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg)
std::ostringstream message;
message << "Error running command: [";
message << result << "] ";
- for (std::vector<const char*>::iterator i = argv.begin(); i != argv.end();
- ++i) {
- if (*i) {
- message << *i << " ";
+ for (const char* arg : argv) {
+ if (arg) {
+ message << arg << " ";
}
}
- cmCTestLog(this->CTest, ERROR_MESSAGE, message.str() << argv[0]
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ message.str() << argv[0] << std::endl);
return -1;
}
return retVal;
}
-static void ctestScriptProgressCallback(const char* m, float /*unused*/,
- void* cd)
-{
- cmCTest* ctest = static_cast<cmCTest*>(cd);
- if (m && *m) {
- cmCTestLog(ctest, HANDLER_OUTPUT, "-- " << m << std::endl);
- }
-}
-
void cmCTestScriptHandler::CreateCMake()
{
// create a cmake instance to read the configuration script
@@ -275,7 +252,7 @@ void cmCTestScriptHandler::CreateCMake()
delete this->GlobalGenerator;
delete this->Makefile;
}
- this->CMake = new cmake(cmake::RoleScript);
+ this->CMake = new cmake(cmake::RoleScript, cmState::CTest);
this->CMake->SetHomeDirectory("");
this->CMake->SetHomeOutputDirectory("");
this->CMake->GetCurrentSnapshot().SetDefaultDefinitions();
@@ -287,24 +264,40 @@ void cmCTestScriptHandler::CreateCMake()
snapshot.GetDirectory().SetCurrentSource(cwd);
snapshot.GetDirectory().SetCurrentBinary(cwd);
this->Makefile = new cmMakefile(this->GlobalGenerator, snapshot);
+ if (this->ParentMakefile) {
+ this->Makefile->SetRecursionDepth(
+ this->ParentMakefile->GetRecursionDepth());
+ }
- this->CMake->SetProgressCallback(ctestScriptProgressCallback, this->CTest);
+ this->CMake->SetProgressCallback(
+ [this](const std::string& m, float /*unused*/) {
+ if (!m.empty()) {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT, "-- " << m << std::endl);
+ }
+ });
- this->AddCTestCommand("ctest_build", new cmCTestBuildCommand);
- this->AddCTestCommand("ctest_configure", new cmCTestConfigureCommand);
- this->AddCTestCommand("ctest_coverage", new cmCTestCoverageCommand);
+ this->AddCTestCommand("ctest_build", cm::make_unique<cmCTestBuildCommand>());
+ this->AddCTestCommand("ctest_configure",
+ cm::make_unique<cmCTestConfigureCommand>());
+ this->AddCTestCommand("ctest_coverage",
+ cm::make_unique<cmCTestCoverageCommand>());
this->AddCTestCommand("ctest_empty_binary_directory",
- new cmCTestEmptyBinaryDirectoryCommand);
- this->AddCTestCommand("ctest_memcheck", new cmCTestMemCheckCommand);
+ cm::make_unique<cmCTestEmptyBinaryDirectoryCommand>());
+ this->AddCTestCommand("ctest_memcheck",
+ cm::make_unique<cmCTestMemCheckCommand>());
this->AddCTestCommand("ctest_read_custom_files",
- new cmCTestReadCustomFilesCommand);
- this->AddCTestCommand("ctest_run_script", new cmCTestRunScriptCommand);
- this->AddCTestCommand("ctest_sleep", new cmCTestSleepCommand);
- this->AddCTestCommand("ctest_start", new cmCTestStartCommand);
- this->AddCTestCommand("ctest_submit", new cmCTestSubmitCommand);
- this->AddCTestCommand("ctest_test", new cmCTestTestCommand);
- this->AddCTestCommand("ctest_update", new cmCTestUpdateCommand);
- this->AddCTestCommand("ctest_upload", new cmCTestUploadCommand);
+ cm::make_unique<cmCTestReadCustomFilesCommand>());
+ this->AddCTestCommand("ctest_run_script",
+ cm::make_unique<cmCTestRunScriptCommand>());
+ this->AddCTestCommand("ctest_sleep", cm::make_unique<cmCTestSleepCommand>());
+ this->AddCTestCommand("ctest_start", cm::make_unique<cmCTestStartCommand>());
+ this->AddCTestCommand("ctest_submit",
+ cm::make_unique<cmCTestSubmitCommand>());
+ this->AddCTestCommand("ctest_test", cm::make_unique<cmCTestTestCommand>());
+ this->AddCTestCommand("ctest_update",
+ cm::make_unique<cmCTestUpdateCommand>());
+ this->AddCTestCommand("ctest_upload",
+ cm::make_unique<cmCTestUploadCommand>());
}
// this sets up some variables for the script to use, creates the required
@@ -325,8 +318,8 @@ 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())) {
- cmSystemTools::Error("Cannot find file: ", script.c_str());
+ if (!cmSystemTools::FileExists(script)) {
+ cmSystemTools::Error("Cannot find file: " + script);
return 1;
}
@@ -335,30 +328,29 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg)
this->CreateCMake();
// set a variable with the path to the current script
- this->Makefile->AddDefinition(
- "CTEST_SCRIPT_DIRECTORY", cmSystemTools::GetFilenamePath(script).c_str());
- this->Makefile->AddDefinition(
- "CTEST_SCRIPT_NAME", cmSystemTools::GetFilenameName(script).c_str());
+ this->Makefile->AddDefinition("CTEST_SCRIPT_DIRECTORY",
+ cmSystemTools::GetFilenamePath(script));
+ this->Makefile->AddDefinition("CTEST_SCRIPT_NAME",
+ cmSystemTools::GetFilenameName(script));
this->Makefile->AddDefinition("CTEST_EXECUTABLE_NAME",
- cmSystemTools::GetCTestCommand().c_str());
+ cmSystemTools::GetCTestCommand());
this->Makefile->AddDefinition("CMAKE_EXECUTABLE_NAME",
- cmSystemTools::GetCMakeCommand().c_str());
- this->Makefile->AddDefinition("CTEST_RUN_CURRENT_SCRIPT", true);
+ cmSystemTools::GetCMakeCommand());
+ this->Makefile->AddDefinitionBool("CTEST_RUN_CURRENT_SCRIPT", true);
+ this->SetRunCurrentScript(true);
this->UpdateElapsedTime();
// add the script arg if defined
if (!script_arg.empty()) {
- this->Makefile->AddDefinition("CTEST_SCRIPT_ARG", script_arg.c_str());
+ this->Makefile->AddDefinition("CTEST_SCRIPT_ARG", script_arg);
}
#if defined(__CYGWIN__)
this->Makefile->AddDefinition("CMAKE_LEGACY_CYGWIN_WIN32", "0");
#endif
- // always add a function blocker to update the elapsed time
- cmCTestScriptFunctionBlocker* f = new cmCTestScriptFunctionBlocker();
- f->CTestScriptHandler = this;
- this->Makefile->AddFunctionBlocker(f);
+ // set a callback function to update the elapsed time
+ this->Makefile->OnExecuteCommand([this] { this->UpdateElapsedTime(); });
/* Execute CTestScriptMode.cmake, which loads CMakeDetermineSystem and
CMakeSystemSpecificInformation, so
@@ -367,23 +359,22 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg)
ctest scripting easier. */
std::string systemFile =
this->Makefile->GetModulesFile("CTestScriptMode.cmake");
- if (!this->Makefile->ReadListFile(systemFile.c_str()) ||
+ if (!this->Makefile->ReadListFile(systemFile) ||
cmSystemTools::GetErrorOccuredFlag()) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Error in read:" << systemFile
- << "\n");
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error in read:" << systemFile << "\n");
return 2;
}
// Add definitions of variables passed in on the command line:
const std::map<std::string, std::string>& defs =
this->CTest->GetDefinitions();
- for (std::map<std::string, std::string>::const_iterator it = defs.begin();
- it != defs.end(); ++it) {
- this->Makefile->AddDefinition(it->first, it->second.c_str());
+ for (auto const& d : defs) {
+ this->Makefile->AddDefinition(d.first, d.second);
}
// finally read in the script
- if (!this->Makefile->ReadListFile(script.c_str()) ||
+ if (!this->Makefile->ReadListFile(script) ||
cmSystemTools::GetErrorOccuredFlag()) {
// Reset the error flag so that it can run more than
// one script with an error when you use ctest_run_script.
@@ -394,7 +385,7 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg)
return 0;
}
-// extract variabels from the script to set ivars
+// extract variables from the script to set ivars
int cmCTestScriptHandler::ExtractVariables()
{
// Temporary variables
@@ -442,10 +433,11 @@ int cmCTestScriptHandler::ExtractVariables()
if (updateVal) {
if (this->UpdateCmd.empty()) {
cmSystemTools::Error(
- updateVar, " specified without specifying CTEST_CVS_COMMAND.");
+ std::string(updateVar) +
+ " specified without specifying CTEST_CVS_COMMAND.");
return 12;
}
- this->ExtraUpdates.push_back(updateVal);
+ this->ExtraUpdates.emplace_back(updateVal);
}
}
@@ -459,15 +451,16 @@ int cmCTestScriptHandler::ExtractVariables()
// make sure the required info is here
if (this->SourceDir.empty() || this->BinaryDir.empty() ||
this->CTestCmd.empty()) {
- std::string msg = "CTEST_SOURCE_DIRECTORY = ";
- msg += (!this->SourceDir.empty()) ? this->SourceDir.c_str() : "(Null)";
- msg += "\nCTEST_BINARY_DIRECTORY = ";
- msg += (!this->BinaryDir.empty()) ? this->BinaryDir.c_str() : "(Null)";
- msg += "\nCTEST_COMMAND = ";
- msg += (!this->CTestCmd.empty()) ? this->CTestCmd.c_str() : "(Null)";
+ std::string msg =
+ cmStrCat("CTEST_SOURCE_DIRECTORY = ",
+ (!this->SourceDir.empty()) ? this->SourceDir.c_str() : "(Null)",
+ "\nCTEST_BINARY_DIRECTORY = ",
+ (!this->BinaryDir.empty()) ? this->BinaryDir.c_str() : "(Null)",
+ "\nCTEST_COMMAND = ",
+ (!this->CTestCmd.empty()) ? this->CTestCmd.c_str() : "(Null)");
cmSystemTools::Error(
- "Some required settings in the configuration file were missing:\n",
- msg.c_str());
+ "Some required settings in the configuration file were missing:\n" +
+ msg);
return 4;
}
@@ -503,13 +496,13 @@ void cmCTestScriptHandler::SleepInSeconds(unsigned int secondsToWait)
int cmCTestScriptHandler::RunConfigurationScript(
const std::string& total_script_arg, bool pscope)
{
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
cmSystemTools::SaveRestoreEnvironment sre;
#endif
int result;
- this->ScriptStartTime = cmSystemTools::GetTime();
+ this->ScriptStartTime = std::chrono::steady_clock::now();
// read in the script
if (pscope) {
@@ -525,8 +518,9 @@ int cmCTestScriptHandler::RunConfigurationScript(
return result;
}
- // only run the curent script if we should
- if (this->Makefile && this->Makefile->IsOn("CTEST_RUN_CURRENT_SCRIPT")) {
+ // only run the current script if we should
+ if (this->Makefile && this->Makefile->IsOn("CTEST_RUN_CURRENT_SCRIPT") &&
+ this->ShouldRunCurrentScript) {
return this->RunCurrentScript();
}
return result;
@@ -537,7 +531,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);
@@ -550,32 +544,34 @@ int cmCTestScriptHandler::RunCurrentScript()
// set any environment variables
if (!this->CTestEnv.empty()) {
- std::vector<std::string> envArgs;
- cmSystemTools::ExpandListArgument(this->CTestEnv, envArgs);
+ std::vector<std::string> envArgs = cmExpandedList(this->CTestEnv);
cmSystemTools::AppendEnv(envArgs);
}
// now that we have done most of the error checking finally run the
// dashboard, we may be asked to repeatedly run this dashboard, such as
- // for a continuous, do we ned to run it more than once?
+ // for a continuous, do we need 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 {
@@ -592,18 +588,17 @@ 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 = "";
+ output.clear();
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"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->CVSCheckOut, &output, &output, &retVal, 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());
+ cmSystemTools::Error("Unable to perform cvs checkout:\n" + output);
return 6;
}
}
@@ -615,18 +610,16 @@ int cmCTestScriptHandler::BackupDirectories()
int retVal;
// compute the backup names
- this->BackupSourceDir = this->SourceDir;
- this->BackupSourceDir += "_CMakeBackup";
- this->BackupBinaryDir = this->BinaryDir;
- this->BackupBinaryDir += "_CMakeBackup";
+ this->BackupSourceDir = cmStrCat(this->SourceDir, "_CMakeBackup");
+ this->BackupBinaryDir = cmStrCat(this->BinaryDir, "_CMakeBackup");
// 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);
}
@@ -654,24 +647,20 @@ int cmCTestScriptHandler::PerformExtraUpdates()
// do an initial cvs update as required
command = this->UpdateCmd;
- std::vector<std::string>::iterator it;
- for (it = this->ExtraUpdates.begin(); it != this->ExtraUpdates.end(); ++it) {
- std::vector<std::string> cvsArgs;
- cmSystemTools::ExpandListArgument(*it, cvsArgs);
+ for (std::string const& eu : this->ExtraUpdates) {
+ std::vector<std::string> cvsArgs = cmExpandedList(eu);
if (cvsArgs.size() == 2) {
- std::string fullCommand = command;
- fullCommand += " update ";
- fullCommand += cvsArgs[1];
- output = "";
+ std::string fullCommand = cmStrCat(command, " update ", cvsArgs[1]);
+ output.clear();
retVal = 0;
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Run Update: " << fullCommand << std::endl);
res = cmSystemTools::RunSingleCommand(
- fullCommand.c_str(), &output, &output, &retVal, cvsArgs[0].c_str(),
- this->HandlerVerbose, 0 /*this->TimeOut*/);
+ fullCommand, &output, &output, &retVal, cvsArgs[0].c_str(),
+ this->HandlerVerbose, cmDuration::zero() /*this->TimeOut*/);
if (!res || retVal != 0) {
- cmSystemTools::Error("Unable to perform extra updates:\n", it->c_str(),
- "\nWith output:\n", output.c_str());
+ cmSystemTools::Error(cmStrCat("Unable to perform extra updates:\n", eu,
+ "\nWith output:\n", output));
return 0;
}
}
@@ -710,11 +699,11 @@ 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())) {
- cmSystemTools::Error("Unable to create the binary directory:\n",
- this->BinaryDir.c_str());
+ if (!cmSystemTools::MakeDirectory(this->BinaryDir)) {
+ cmSystemTools::Error("Unable to create the binary directory:\n" +
+ this->BinaryDir);
this->RestoreBackupDirectories();
return 7;
}
@@ -751,8 +740,8 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
// put the initial cache into the bin dir
if (!this->InitialCache.empty()) {
- if (!this->WriteInitialCache(this->BinaryDir.c_str(),
- this->InitialCache.c_str())) {
+ if (!cmCTestScriptHandler::WriteInitialCache(this->BinaryDir.c_str(),
+ this->InitialCache.c_str())) {
this->RestoreBackupDirectories();
return 9;
}
@@ -762,28 +751,26 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
int cmakeFailed = 0;
std::string cmakeFailedOuput;
if (!this->CMakeCmd.empty()) {
- command = this->CMakeCmd;
- command += " \"";
- command += this->SourceDir;
- output = "";
+ command = cmStrCat(this->CMakeCmd, " \"", this->SourceDir);
+ output.clear();
command += "\"";
retVal = 0;
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Run cmake command: " << command << std::endl);
res = cmSystemTools::RunSingleCommand(
- command.c_str(), &output, &output, &retVal, this->BinaryDir.c_str(),
- this->HandlerVerbose, 0 /*this->TimeOut*/);
+ command, &output, &output, &retVal, this->BinaryDir.c_str(),
+ 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;
}
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Write CMake output to file: " << cmakeOutputFile
<< std::endl);
- cmGeneratedFileStream fout(cmakeOutputFile.c_str());
+ cmGeneratedFileStream fout(cmakeOutputFile);
if (fout) {
fout << output.c_str();
} else {
@@ -800,18 +787,17 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
}
// run ctest, it may be more than one command in here
- std::vector<std::string> ctestCommands;
- cmSystemTools::ExpandListArgument(this->CTestCmd, ctestCommands);
+ std::vector<std::string> ctestCommands = cmExpandedList(this->CTestCmd);
// for each variable/argument do a putenv
- for (unsigned i = 0; i < ctestCommands.size(); ++i) {
- command = ctestCommands[i];
- output = "";
+ for (std::string const& ctestCommand : ctestCommands) {
+ command = ctestCommand;
+ output.clear();
retVal = 0;
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Run ctest command: " << command << std::endl);
res = cmSystemTools::RunSingleCommand(
- command.c_str(), &output, &output, &retVal, this->BinaryDir.c_str(),
- this->HandlerVerbose, 0 /*this->TimeOut*/);
+ command, &output, &output, &retVal, this->BinaryDir.c_str(),
+ this->HandlerVerbose, cmDuration::zero() /*this->TimeOut*/);
// did something critical fail in ctest
if (!res || cmakeFailed || retVal & cmCTest::BUILD_ERRORS) {
@@ -833,7 +819,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);
@@ -845,14 +831,13 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
bool cmCTestScriptHandler::WriteInitialCache(const char* directory,
const char* text)
{
- std::string cacheFile = directory;
- cacheFile += "/CMakeCache.txt";
- cmGeneratedFileStream fout(cacheFile.c_str());
+ std::string cacheFile = cmStrCat(directory, "/CMakeCache.txt");
+ cmGeneratedFileStream fout(cacheFile);
if (!fout) {
return false;
}
- if (text != CM_NULLPTR) {
+ if (text != nullptr) {
fout.write(text, strlen(text));
}
@@ -870,10 +855,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
@@ -882,11 +867,13 @@ void cmCTestScriptHandler::RestoreBackupDirectories()
}
}
-bool cmCTestScriptHandler::RunScript(cmCTest* ctest, const char* sname,
- bool InProcess, int* returnValue)
+bool cmCTestScriptHandler::RunScript(cmCTest* ctest, cmMakefile* mf,
+ const char* sname, bool InProcess,
+ int* returnValue)
{
cmCTestScriptHandler* sh = new cmCTestScriptHandler();
sh->SetCTestInstance(ctest);
+ sh->ParentMakefile = mf;
sh->AddConfigurationScript(sname, InProcess);
int res = sh->ProcessHandler();
if (returnValue) {
@@ -909,10 +896,9 @@ bool cmCTestScriptHandler::EmptyBinaryDirectory(const char* sname)
}
// try to avoid deleting directories that we shouldn't
- std::string check = sname;
- check += "/CMakeCache.txt";
+ std::string check = cmStrCat(sname, "/CMakeCache.txt");
- if (!cmSystemTools::FileExists(check.c_str())) {
+ if (!cmSystemTools::FileExists(check)) {
return false;
}
@@ -939,7 +925,7 @@ bool cmCTestScriptHandler::TryToRemoveBinaryDirectoryOnce(
continue;
}
- std::string fullPath = directoryPath + std::string("/") + path;
+ std::string fullPath = cmStrCat(directoryPath, "/", path);
bool isDirectory = cmSystemTools::FileIsDirectory(fullPath) &&
!cmSystemTools::FileIsSymlink(fullPath);
@@ -958,19 +944,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 667870260..d0031990b 100644
--- a/Source/CTest/cmCTestScriptHandler.h
+++ b/Source/CTest/cmCTestScriptHandler.h
@@ -3,13 +3,16 @@
#ifndef cmCTestScriptHandler_h
#define cmCTestScriptHandler_h
-#include "cmConfigure.h"
-
-#include "cmCTestGenericHandler.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+#include <chrono>
+#include <memory>
#include <string>
#include <vector>
+#include "cmCTestGenericHandler.h"
+#include "cmDuration.h"
+
class cmCTest;
class cmCTestCommand;
class cmGlobalGenerator;
@@ -55,7 +58,7 @@ class cmake;
class cmCTestScriptHandler : public cmCTestGenericHandler
{
public:
- typedef cmCTestGenericHandler Superclass;
+ using Superclass = cmCTestGenericHandler;
/**
* Add a script to run, and if is should run in the current process
@@ -65,13 +68,13 @@ public:
/**
* Run a dashboard using a specified confiuration script
*/
- int ProcessHandler() CM_OVERRIDE;
+ int ProcessHandler() override;
/*
* Run a script
*/
- static bool RunScript(cmCTest* ctest, const char* script, bool InProcess,
- int* returnValue);
+ static bool RunScript(cmCTest* ctest, cmMakefile* mf, const char* script,
+ bool InProcess, int* returnValue);
int RunCurrentScript();
/*
@@ -93,17 +96,20 @@ 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() CM_OVERRIDE;
+ ~cmCTestScriptHandler() override;
- void Initialize() CM_OVERRIDE;
+ void Initialize() override;
void CreateCMake();
cmake* GetCMake() { return this->CMake; }
+
+ void SetRunCurrentScript(bool value);
+
private:
// reads in a script
int ReadInScript(const std::string& total_script_arg);
@@ -126,7 +132,8 @@ private:
int RunConfigurationDashboard();
// Add ctest command
- void AddCTestCommand(std::string const& name, cmCTestCommand* command);
+ void AddCTestCommand(std::string const& name,
+ std::unique_ptr<cmCTestCommand> command);
// Try to remove the binary directory once
static bool TryToRemoveBinaryDirectoryOnce(const std::string& directoryPath);
@@ -134,6 +141,8 @@ private:
std::vector<std::string> ConfigurationScripts;
std::vector<bool> ScriptProcessScope;
+ bool ShouldRunCurrentScript;
+
bool Backup;
bool EmptyBinDir;
bool EmptyBinDirOnce;
@@ -156,9 +165,10 @@ private:
double ContinuousDuration;
// what time in seconds did this script start running
- double ScriptStartTime;
+ std::chrono::steady_clock::time_point ScriptStartTime;
cmMakefile* Makefile;
+ cmMakefile* ParentMakefile;
cmGlobalGenerator* GlobalGenerator;
cmake* CMake;
};
diff --git a/Source/CTest/cmCTestSleepCommand.cxx b/Source/CTest/cmCTestSleepCommand.cxx
index 2752cd370..623d3b69c 100644
--- a/Source/CTest/cmCTestSleepCommand.cxx
+++ b/Source/CTest/cmCTestSleepCommand.cxx
@@ -2,9 +2,9 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestSleepCommand.h"
-#include "cmCTestScriptHandler.h"
+#include <cstdlib>
-#include <stdlib.h>
+#include "cmCTestScriptHandler.h"
class cmExecutionStatus;
diff --git a/Source/CTest/cmCTestSleepCommand.h b/Source/CTest/cmCTestSleepCommand.h
index f0b5f1eeb..1c3b8a1e1 100644
--- a/Source/CTest/cmCTestSleepCommand.h
+++ b/Source/CTest/cmCTestSleepCommand.h
@@ -3,14 +3,17 @@
#ifndef cmCTestSleepCommand_h
#define cmCTestSleepCommand_h
-#include "cmConfigure.h"
-
-#include "cmCTestCommand.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
+#include <utility>
#include <vector>
-class cmCommand;
+#include <cm/memory>
+
+#include "cmCTestCommand.h"
+#include "cmCommand.h"
+
class cmExecutionStatus;
/** \class cmCTestSleep
@@ -27,12 +30,12 @@ public:
/**
* This is a virtual constructor for the command.
*/
- cmCommand* Clone() CM_OVERRIDE
+ std::unique_ptr<cmCommand> Clone() override
{
- cmCTestSleepCommand* ni = new cmCTestSleepCommand;
+ auto ni = cm::make_unique<cmCTestSleepCommand>();
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
- return ni;
+ return std::unique_ptr<cmCommand>(std::move(ni));
}
/**
@@ -40,7 +43,7 @@ public:
* the CMakeLists.txt file.
*/
bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
+ cmExecutionStatus& status) override;
};
#endif
diff --git a/Source/CTest/cmCTestStartCommand.cxx b/Source/CTest/cmCTestStartCommand.cxx
index 01a874b45..fe684062d 100644
--- a/Source/CTest/cmCTestStartCommand.cxx
+++ b/Source/CTest/cmCTestStartCommand.cxx
@@ -2,15 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestStartCommand.h"
+#include <cstddef>
+#include <sstream>
+
#include "cmCTest.h"
#include "cmCTestVC.h"
#include "cmGeneratedFileStream.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
-#include <sstream>
-#include <stddef.h>
-
class cmExecutionStatus;
cmCTestStartCommand::cmCTestStartCommand()
@@ -28,41 +28,43 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args,
}
size_t cnt = 0;
- const char* smodel = args[cnt].c_str();
- const char* src_dir = CM_NULLPTR;
- const char* bld_dir = CM_NULLPTR;
-
- cnt++;
+ const char* smodel = nullptr;
+ const char* src_dir = nullptr;
+ const char* bld_dir = nullptr;
- this->CTest->SetSpecificTrack(CM_NULLPTR);
- if (cnt < args.size() - 1) {
- if (args[cnt] == "TRACK") {
+ while (cnt < args.size()) {
+ if (args[cnt] == "GROUP" || args[cnt] == "TRACK") {
cnt++;
- this->CTest->SetSpecificTrack(args[cnt].c_str());
+ if (cnt >= args.size() || args[cnt] == "APPEND" ||
+ args[cnt] == "QUIET") {
+ std::ostringstream e;
+ e << args[cnt - 1] << " argument missing group name";
+ this->SetError(e.str());
+ return false;
+ }
+ this->CTest->SetSpecificGroup(args[cnt].c_str());
cnt++;
- }
- }
-
- if (cnt < args.size()) {
- if (args[cnt] == "APPEND") {
+ } else if (args[cnt] == "APPEND") {
cnt++;
this->CreateNewTag = false;
- }
- }
- if (cnt < args.size()) {
- if (args[cnt] == "QUIET") {
+ } else if (args[cnt] == "QUIET") {
cnt++;
this->Quiet = true;
- }
- }
-
- if (cnt < args.size()) {
- src_dir = args[cnt].c_str();
- cnt++;
- if (cnt < args.size()) {
+ } else if (!smodel) {
+ smodel = args[cnt].c_str();
+ cnt++;
+ } else if (!src_dir) {
+ src_dir = args[cnt].c_str();
+ cnt++;
+ } else if (!bld_dir) {
bld_dir = args[cnt].c_str();
+ cnt++;
+ } else {
+ this->SetError("Too many arguments");
+ return false;
}
}
+
if (!src_dir) {
src_dir = this->Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY");
}
@@ -79,6 +81,11 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args,
"as an argument or set CTEST_BINARY_DIRECTORY");
return false;
}
+ if (!smodel && this->CreateNewTag) {
+ this->SetError("no test model specified and APPEND not specified. Specify "
+ "either a test model or the APPEND argument");
+ return false;
+ }
cmSystemTools::AddKeepPath(src_dir);
cmSystemTools::AddKeepPath(bld_dir);
@@ -92,20 +99,31 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args,
this->CTest->SetCTestConfiguration("BuildDirectory", binaryDir.c_str(),
this->Quiet);
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Run dashboard with model "
- << smodel << std::endl
- << " Source directory: " << src_dir << std::endl
- << " Build directory: " << bld_dir << std::endl,
- this->Quiet);
- const char* track = this->CTest->GetSpecificTrack();
- if (track) {
+ if (smodel) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ "Run dashboard with model "
+ << smodel << std::endl
+ << " Source directory: " << src_dir << std::endl
+ << " Build directory: " << bld_dir << std::endl,
+ this->Quiet);
+ } else {
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Track: " << track << std::endl, this->Quiet);
+ "Run dashboard with "
+ "to-be-determined model"
+ << std::endl
+ << " Source directory: " << src_dir << std::endl
+ << " Build directory: " << bld_dir << std::endl,
+ this->Quiet);
+ }
+ const char* group = this->CTest->GetSpecificGroup();
+ if (group) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Group: " << group << std::endl, this->Quiet);
}
// Log startup actions.
std::string startLogFile = binaryDir + "/Testing/Temporary/LastStart.log";
- cmGeneratedFileStream ofs(startLogFile.c_str());
+ cmGeneratedFileStream ofs(startLogFile);
if (!ofs) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Cannot create log file: LastStart.log" << std::endl);
@@ -126,9 +144,14 @@ 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);
+ int model;
+ if (smodel) {
+ model = cmCTest::GetTestModelFromString(smodel);
+ } else {
+ model = cmCTest::UNKNOWN;
+ }
this->CTest->SetTestModel(model);
this->CTest->SetProduceXML(true);
diff --git a/Source/CTest/cmCTestStartCommand.h b/Source/CTest/cmCTestStartCommand.h
index b4943f92d..b30b1bb44 100644
--- a/Source/CTest/cmCTestStartCommand.h
+++ b/Source/CTest/cmCTestStartCommand.h
@@ -3,15 +3,18 @@
#ifndef cmCTestStartCommand_h
#define cmCTestStartCommand_h
-#include "cmConfigure.h"
-
-#include "cmCTestCommand.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
+#include <utility>
#include <vector>
-class cmCommand;
+#include <cm/memory>
+
+#include "cmCTestCommand.h"
+#include "cmCommand.h"
+
class cmExecutionStatus;
/** \class cmCTestStart
@@ -27,14 +30,14 @@ public:
/**
* This is a virtual constructor for the command.
*/
- cmCommand* Clone() CM_OVERRIDE
+ std::unique_ptr<cmCommand> Clone() override
{
- cmCTestStartCommand* ni = new cmCTestStartCommand;
+ auto ni = cm::make_unique<cmCTestStartCommand>();
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
ni->CreateNewTag = this->CreateNewTag;
ni->Quiet = this->Quiet;
- return ni;
+ return std::unique_ptr<cmCommand>(std::move(ni));
}
/**
@@ -42,7 +45,7 @@ public:
* the CMakeLists.txt file.
*/
bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
+ cmExecutionStatus& status) override;
/**
* Will this invocation of ctest_start create a new TAG file?
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index 409eb51fc..46b00b168 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -2,100 +2,81 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestSubmitCommand.h"
+#include <set>
+#include <sstream>
+#include <utility>
+
+#include <cm/memory>
+
+#include "cm_static_string_view.hxx"
+
+#include "cmAlgorithms.h"
#include "cmCTest.h"
-#include "cmCTestGenericHandler.h"
#include "cmCTestSubmitHandler.h"
+#include "cmCommand.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmRange.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmake.h"
-
-#include <sstream>
class cmExecutionStatus;
-cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
+/**
+ * This is a virtual constructor for the command.
+ */
+std::unique_ptr<cmCommand> cmCTestSubmitCommand::Clone()
{
- const char* ctestDropMethod =
- this->Makefile->GetDefinition("CTEST_DROP_METHOD");
- const char* ctestDropSite = this->Makefile->GetDefinition("CTEST_DROP_SITE");
- const char* ctestDropLocation =
- this->Makefile->GetDefinition("CTEST_DROP_LOCATION");
- const char* ctestTriggerSite =
- this->Makefile->GetDefinition("CTEST_TRIGGER_SITE");
- bool ctestDropSiteCDash = this->Makefile->IsOn("CTEST_DROP_SITE_CDASH");
- const char* ctestProjectName =
- this->Makefile->GetDefinition("CTEST_PROJECT_NAME");
- if (!ctestDropMethod) {
- ctestDropMethod = "http";
- }
-
- if (!ctestDropSite) {
- // error: CDash requires CTEST_DROP_SITE definition
- // in CTestConfig.cmake
- }
- if (!ctestDropLocation) {
- // error: CDash requires CTEST_DROP_LOCATION definition
- // in CTestConfig.cmake
- }
- this->CTest->SetCTestConfiguration("ProjectName", ctestProjectName,
- this->Quiet);
- this->CTest->SetCTestConfiguration("DropMethod", ctestDropMethod,
- this->Quiet);
- this->CTest->SetCTestConfiguration("DropSite", ctestDropSite, this->Quiet);
- this->CTest->SetCTestConfiguration("DropLocation", ctestDropLocation,
- this->Quiet);
+ auto ni = cm::make_unique<cmCTestSubmitCommand>();
+ ni->CTest = this->CTest;
+ ni->CTestScriptHandler = this->CTestScriptHandler;
+ return std::unique_ptr<cmCommand>(std::move(ni));
+}
- this->CTest->SetCTestConfiguration(
- "IsCDash", ctestDropSiteCDash ? "TRUE" : "FALSE", this->Quiet);
+cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
+{
+ const char* submitURL = !this->SubmitURL.empty()
+ ? this->SubmitURL.c_str()
+ : this->Makefile->GetDefinition("CTEST_SUBMIT_URL");
- // Only propagate TriggerSite for non-CDash projects:
- //
- if (!ctestDropSiteCDash) {
- this->CTest->SetCTestConfiguration("TriggerSite", ctestTriggerSite,
- this->Quiet);
+ if (submitURL) {
+ this->CTest->SetCTestConfiguration("SubmitURL", submitURL, this->Quiet);
+ } else {
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "DropMethod", "CTEST_DROP_METHOD", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "DropSiteUser", "CTEST_DROP_SITE_USER", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "DropSitePassword", "CTEST_DROP_SITE_PASSWORD",
+ this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "DropSite", "CTEST_DROP_SITE", this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "DropLocation", "CTEST_DROP_LOCATION", this->Quiet);
}
this->CTest->SetCTestConfigurationFromCMakeVariable(
this->Makefile, "CurlOptions", "CTEST_CURL_OPTIONS", this->Quiet);
- this->CTest->SetCTestConfigurationFromCMakeVariable(
- this->Makefile, "DropSiteUser", "CTEST_DROP_SITE_USER", this->Quiet);
- this->CTest->SetCTestConfigurationFromCMakeVariable(
- this->Makefile, "DropSitePassword", "CTEST_DROP_SITE_PASSWORD",
- this->Quiet);
- this->CTest->SetCTestConfigurationFromCMakeVariable(
- this->Makefile, "ScpCommand", "CTEST_SCP_COMMAND", this->Quiet);
const char* notesFilesVariable =
this->Makefile->GetDefinition("CTEST_NOTES_FILES");
if (notesFilesVariable) {
- std::vector<std::string> notesFiles;
- cmCTest::VectorOfStrings newNotesFiles;
- cmSystemTools::ExpandListArgument(notesFilesVariable, notesFiles);
- newNotesFiles.insert(newNotesFiles.end(), notesFiles.begin(),
- notesFiles.end());
- this->CTest->GenerateNotesFile(newNotesFiles);
+ std::vector<std::string> notesFiles = cmExpandedList(notesFilesVariable);
+ this->CTest->GenerateNotesFile(notesFiles);
}
const char* extraFilesVariable =
this->Makefile->GetDefinition("CTEST_EXTRA_SUBMIT_FILES");
if (extraFilesVariable) {
- std::vector<std::string> extraFiles;
- cmCTest::VectorOfStrings newExtraFiles;
- cmSystemTools::ExpandListArgument(extraFilesVariable, extraFiles);
- newExtraFiles.insert(newExtraFiles.end(), extraFiles.begin(),
- extraFiles.end());
- if (!this->CTest->SubmitExtraFiles(newExtraFiles)) {
+ std::vector<std::string> extraFiles = cmExpandedList(extraFilesVariable);
+ if (!this->CTest->SubmitExtraFiles(extraFiles)) {
this->SetError("problem submitting extra files.");
- return CM_NULLPTR;
+ return nullptr;
}
}
- cmCTestGenericHandler* handler =
- this->CTest->GetInitializedHandler("submit");
- if (!handler) {
- this->SetError("internal CTest error. Cannot instantiate submit handler");
- return CM_NULLPTR;
- }
+ cmCTestSubmitHandler* handler = this->CTest->GetSubmitHandler();
+ handler->Initialize();
// If no FILES or PARTS given, *all* PARTS are submitted by default.
//
@@ -117,38 +98,35 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
// But FILES with no PARTS mentioned should just submit the FILES
// without any of the default parts.
//
- std::set<cmCTest::Part> noParts;
- static_cast<cmCTestSubmitHandler*>(handler)->SelectParts(noParts);
-
- static_cast<cmCTestSubmitHandler*>(handler)->SelectFiles(this->Files);
+ handler->SelectParts(std::set<cmCTest::Part>());
+ handler->SelectFiles(
+ std::set<std::string>(this->Files.begin(), this->Files.end()));
}
// If a PARTS option was given, select only the named parts for submission.
//
if (this->PartsMentioned) {
- static_cast<cmCTestSubmitHandler*>(handler)->SelectParts(this->Parts);
+ auto parts =
+ cmMakeRange(this->Parts).transform([this](std::string const& arg) {
+ return this->CTest->GetPartFromName(arg.c_str());
+ });
+ handler->SelectParts(std::set<cmCTest::Part>(parts.begin(), parts.end()));
}
// Pass along any HTTPHEADER to the handler if this option was given.
if (!this->HttpHeaders.empty()) {
- static_cast<cmCTestSubmitHandler*>(handler)->SetHttpHeaders(
- this->HttpHeaders);
+ handler->SetHttpHeaders(this->HttpHeaders);
}
- static_cast<cmCTestSubmitHandler*>(handler)->SetOption(
- "RetryDelay", this->RetryDelay.c_str());
- static_cast<cmCTestSubmitHandler*>(handler)->SetOption(
- "RetryCount", this->RetryCount.c_str());
- static_cast<cmCTestSubmitHandler*>(handler)->SetOption(
- "InternalTest", this->InternalTest ? "ON" : "OFF");
+ handler->SetOption("RetryDelay", this->RetryDelay.c_str());
+ handler->SetOption("RetryCount", this->RetryCount.c_str());
+ handler->SetOption("InternalTest", this->InternalTest ? "ON" : "OFF");
handler->SetQuiet(this->Quiet);
if (this->CDashUpload) {
- static_cast<cmCTestSubmitHandler*>(handler)->SetOption(
- "CDashUploadFile", this->CDashUploadFile.c_str());
- static_cast<cmCTestSubmitHandler*>(handler)->SetOption(
- "CDashUploadType", this->CDashUploadType.c_str());
+ handler->SetOption("CDashUploadFile", this->CDashUploadFile.c_str());
+ handler->SetOption("CDashUploadType", this->CDashUploadType.c_str());
}
return handler;
}
@@ -157,117 +135,64 @@ bool cmCTestSubmitCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
this->CDashUpload = !args.empty() && args[0] == "CDASH_UPLOAD";
- return this->cmCTestHandlerCommand::InitialPass(args, status);
+
+ bool ret = this->cmCTestHandlerCommand::InitialPass(args, status);
+
+ if (!this->BuildID.empty()) {
+ this->Makefile->AddDefinition(this->BuildID, this->CTest->GetBuildID());
+ }
+
+ return ret;
}
-bool cmCTestSubmitCommand::CheckArgumentKeyword(std::string const& arg)
+void cmCTestSubmitCommand::BindArguments()
{
if (this->CDashUpload) {
// Arguments specific to the CDASH_UPLOAD signature.
- if (arg == "CDASH_UPLOAD") {
- this->ArgumentDoing = ArgumentDoingCDashUpload;
- return true;
- }
-
- if (arg == "CDASH_UPLOAD_TYPE") {
- this->ArgumentDoing = ArgumentDoingCDashUploadType;
- return true;
- }
+ this->Bind("CDASH_UPLOAD", this->CDashUploadFile);
+ this->Bind("CDASH_UPLOAD_TYPE", this->CDashUploadType);
} else {
// Arguments that cannot be used with CDASH_UPLOAD.
- if (arg == "PARTS") {
- this->ArgumentDoing = ArgumentDoingParts;
- this->PartsMentioned = true;
- return true;
- }
-
- if (arg == "FILES") {
- this->ArgumentDoing = ArgumentDoingFiles;
- this->FilesMentioned = true;
- return true;
- }
+ this->Bind("PARTS"_s, this->Parts);
+ this->Bind("FILES"_s, this->Files);
}
// Arguments used by both modes.
- if (arg == "HTTPHEADER") {
- this->ArgumentDoing = ArgumentDoingHttpHeader;
- return true;
- }
-
- if (arg == "RETRY_COUNT") {
- this->ArgumentDoing = ArgumentDoingRetryCount;
- return true;
- }
-
- if (arg == "RETRY_DELAY") {
- this->ArgumentDoing = ArgumentDoingRetryDelay;
- return true;
- }
-
- if (arg == "INTERNAL_TEST_CHECKSUM") {
- this->InternalTest = true;
- return true;
- }
+ this->Bind("BUILD_ID"_s, this->BuildID);
+ this->Bind("HTTPHEADER"_s, this->HttpHeaders);
+ this->Bind("RETRY_COUNT"_s, this->RetryCount);
+ this->Bind("RETRY_DELAY"_s, this->RetryDelay);
+ this->Bind("SUBMIT_URL"_s, this->SubmitURL);
+ this->Bind("INTERNAL_TEST_CHECKSUM", this->InternalTest);
// Look for other arguments.
- return this->Superclass::CheckArgumentKeyword(arg);
+ this->cmCTestHandlerCommand::BindArguments();
}
-bool cmCTestSubmitCommand::CheckArgumentValue(std::string const& arg)
+void cmCTestSubmitCommand::CheckArguments(
+ std::vector<std::string> const& keywords)
{
- // Handle states specific to this command.
- if (this->ArgumentDoing == ArgumentDoingParts) {
+ this->PartsMentioned = !this->Parts.empty() || cmContains(keywords, "PARTS");
+ this->FilesMentioned = !this->Files.empty() || cmContains(keywords, "FILES");
+
+ cmEraseIf(this->Parts, [this](std::string const& arg) -> bool {
cmCTest::Part p = this->CTest->GetPartFromName(arg.c_str());
- if (p != cmCTest::PartCount) {
- this->Parts.insert(p);
- } else {
+ if (p == cmCTest::PartCount) {
std::ostringstream e;
e << "Part name \"" << arg << "\" is invalid.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
- this->ArgumentDoing = ArgumentDoingError;
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return true;
}
- return true;
- }
+ return false;
+ });
- if (this->ArgumentDoing == ArgumentDoingFiles) {
- if (cmSystemTools::FileExists(arg.c_str())) {
- this->Files.insert(arg);
- } else {
+ cmEraseIf(this->Files, [this](std::string const& arg) -> bool {
+ if (!cmSystemTools::FileExists(arg)) {
std::ostringstream e;
e << "File \"" << arg << "\" does not exist. Cannot submit "
<< "a non-existent file.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
- this->ArgumentDoing = ArgumentDoingError;
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return true;
}
- return true;
- }
-
- if (this->ArgumentDoing == ArgumentDoingHttpHeader) {
- this->HttpHeaders.push_back(arg);
- return true;
- }
-
- if (this->ArgumentDoing == ArgumentDoingRetryCount) {
- this->RetryCount = arg;
- return true;
- }
-
- if (this->ArgumentDoing == ArgumentDoingRetryDelay) {
- this->RetryDelay = arg;
- return true;
- }
-
- if (this->ArgumentDoing == ArgumentDoingCDashUpload) {
- this->ArgumentDoing = ArgumentDoingNone;
- this->CDashUploadFile = arg;
- return true;
- }
-
- if (this->ArgumentDoing == ArgumentDoingCDashUploadType) {
- this->ArgumentDoing = ArgumentDoingNone;
- this->CDashUploadType = arg;
- return true;
- }
-
- // Look for other arguments.
- return this->Superclass::CheckArgumentValue(arg);
+ return false;
+ });
}
diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h
index cf65cdc8d..90607713b 100644
--- a/Source/CTest/cmCTestSubmitCommand.h
+++ b/Source/CTest/cmCTestSubmitCommand.h
@@ -3,17 +3,16 @@
#ifndef cmCTestSubmitCommand_h
#define cmCTestSubmitCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmCTest.h"
-#include "cmCTestHandlerCommand.h"
-
-#include <set>
+#include <memory>
#include <string>
#include <vector>
-class cmCTestGenericHandler;
+#include "cmCTestHandlerCommand.h"
+
class cmCommand;
+class cmCTestGenericHandler;
class cmExecutionStatus;
/** \class cmCTestSubmit
@@ -25,66 +24,36 @@ class cmExecutionStatus;
class cmCTestSubmitCommand : public cmCTestHandlerCommand
{
public:
- cmCTestSubmitCommand()
- {
- this->PartsMentioned = false;
- this->FilesMentioned = false;
- this->InternalTest = false;
- this->RetryCount = "";
- this->RetryDelay = "";
- this->CDashUpload = false;
- }
-
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE
- {
- cmCTestSubmitCommand* ni = new cmCTestSubmitCommand;
- ni->CTest = this->CTest;
- ni->CTestScriptHandler = this->CTestScriptHandler;
- return ni;
- }
+ std::unique_ptr<cmCommand> Clone() override;
bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
+ cmExecutionStatus& status) override;
/**
* The name of the command as specified in CMakeList.txt.
*/
- std::string GetName() const CM_OVERRIDE { return "ctest_submit"; }
-
- typedef cmCTestHandlerCommand Superclass;
+ std::string GetName() const override { return "ctest_submit"; }
protected:
- cmCTestGenericHandler* InitializeHandler() CM_OVERRIDE;
+ void BindArguments() override;
+ void CheckArguments(std::vector<std::string> const& keywords) override;
+ cmCTestGenericHandler* InitializeHandler() override;
- bool CheckArgumentKeyword(std::string const& arg) CM_OVERRIDE;
- bool CheckArgumentValue(std::string const& arg) CM_OVERRIDE;
+ bool CDashUpload = false;
+ bool FilesMentioned = false;
+ bool InternalTest = false;
+ bool PartsMentioned = false;
- enum
- {
- ArgumentDoingParts = Superclass::ArgumentDoingLast1,
- ArgumentDoingFiles,
- ArgumentDoingRetryDelay,
- ArgumentDoingRetryCount,
- ArgumentDoingCDashUpload,
- ArgumentDoingCDashUploadType,
- ArgumentDoingHttpHeader,
- ArgumentDoingLast2
- };
-
- bool PartsMentioned;
- std::set<cmCTest::Part> Parts;
- bool FilesMentioned;
- bool InternalTest;
- cmCTest::SetOfStrings Files;
- std::string RetryCount;
- std::string RetryDelay;
- bool CDashUpload;
+ std::string BuildID;
std::string CDashUploadFile;
std::string CDashUploadType;
+ std::string RetryCount;
+ std::string RetryDelay;
+ std::string SubmitURL;
+
+ std::vector<std::string> Files;
std::vector<std::string> HttpHeaders;
+ std::vector<std::string> Parts;
};
#endif
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index 8d62fa156..2ac5af691 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -2,44 +2,36 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestSubmitHandler.h"
+#include <chrono>
+#include <cstdio>
+#include <cstdlib>
+#include <sstream>
+
#include "cm_curl.h"
#include "cm_jsoncpp_reader.h"
#include "cm_jsoncpp_value.h"
-#include "cmsys/Process.h"
-#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
+#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestCurl.h"
#include "cmCTestScriptHandler.h"
+#include "cmCryptoHash.h"
#include "cmCurl.h"
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
-#include "cmProcessOutput.h"
#include "cmState.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmThirdParty.h"
-#include "cmWorkingDirectory.h"
#include "cmXMLParser.h"
#include "cmake.h"
-#if defined(CTEST_USE_XMLRPC)
-#include "cmVersion.h"
-#include "cm_sys_stat.h"
-#include "cm_xmlrpc.h"
-#endif
-
#define SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT 120
-typedef std::vector<char> cmCTestSubmitHandlerVectorOfChar;
+using cmCTestSubmitHandlerVectorOfChar = std::vector<char>;
class cmCTestSubmitHandler::ResponseParser : public cmXMLParser
{
public:
- ResponseParser() { this->Status = STATUS_OK; }
- ~ResponseParser() CM_OVERRIDE {}
-
-public:
enum StatusType
{
STATUS_OK,
@@ -47,10 +39,11 @@ public:
STATUS_ERROR
};
- StatusType Status;
+ StatusType Status = STATUS_OK;
std::string Filename;
std::string MD5;
std::string Message;
+ std::string BuildID;
private:
std::vector<char> CurrentValue;
@@ -65,17 +58,17 @@ private:
}
void StartElement(const std::string& /*name*/,
- const char** /*atts*/) CM_OVERRIDE
+ const char** /*atts*/) override
{
this->CurrentValue.clear();
}
- void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
+ void CharacterDataHandler(const char* data, int length) override
{
- this->CurrentValue.insert(this->CurrentValue.end(), data, data + length);
+ cmAppend(this->CurrentValue, data, data + length);
}
- void EndElement(const std::string& name) CM_OVERRIDE
+ void EndElement(const std::string& name) override
{
if (name == "status") {
std::string status = cmSystemTools::UpperCase(this->GetCurrentValue());
@@ -92,6 +85,8 @@ private:
this->MD5 = this->GetCurrentValue();
} else if (name == "message") {
this->Message = this->GetCurrentValue();
+ } else if (name == "buildId") {
+ this->BuildID = this->GetCurrentValue();
}
}
};
@@ -99,13 +94,10 @@ private:
static size_t cmCTestSubmitHandlerWriteMemoryCallback(void* ptr, size_t size,
size_t nmemb, void* data)
{
- int realsize = (int)(size * nmemb);
-
- cmCTestSubmitHandlerVectorOfChar* vec =
- static_cast<cmCTestSubmitHandlerVectorOfChar*>(data);
+ int realsize = static_cast<int>(size * nmemb);
const char* chPtr = static_cast<char*>(ptr);
- vec->insert(vec->end(), chPtr, chPtr + realsize);
-
+ cmAppend(*static_cast<cmCTestSubmitHandlerVectorOfChar*>(data), chPtr,
+ chPtr + realsize);
return realsize;
}
@@ -114,16 +106,12 @@ static size_t cmCTestSubmitHandlerCurlDebugCallback(CURL* /*unused*/,
char* chPtr, size_t size,
void* data)
{
- cmCTestSubmitHandlerVectorOfChar* vec =
- static_cast<cmCTestSubmitHandlerVectorOfChar*>(data);
- vec->insert(vec->end(), chPtr, chPtr + size);
-
+ cmAppend(*static_cast<cmCTestSubmitHandlerVectorOfChar*>(data), chPtr,
+ chPtr + size);
return size;
}
cmCTestSubmitHandler::cmCTestSubmitHandler()
- : HTTPProxy()
- , FTPProxy()
{
this->Initialize();
}
@@ -135,167 +123,19 @@ void cmCTestSubmitHandler::Initialize()
p = cmCTest::Part(p + 1)) {
this->SubmitPart[p] = true;
}
- this->CDash = false;
this->HasWarnings = false;
this->HasErrors = false;
this->Superclass::Initialize();
- this->HTTPProxy = "";
+ this->HTTPProxy.clear();
this->HTTPProxyType = 0;
- this->HTTPProxyAuth = "";
- this->FTPProxy = "";
- this->FTPProxyType = 0;
- this->LogFile = CM_NULLPTR;
+ this->HTTPProxyAuth.clear();
+ this->LogFile = nullptr;
this->Files.clear();
}
-bool cmCTestSubmitHandler::SubmitUsingFTP(const std::string& localprefix,
- const std::set<std::string>& files,
- const std::string& remoteprefix,
- const std::string& url)
-{
- CURL* curl;
- CURLcode res;
- FILE* ftpfile;
- char error_buffer[1024];
-
- /* In windows, this will init the winsock stuff */
- ::curl_global_init(CURL_GLOBAL_ALL);
-
- cmCTest::SetOfStrings::const_iterator file;
- for (file = files.begin(); file != files.end(); ++file) {
- /* get a curl handle */
- curl = curl_easy_init();
- if (curl) {
- // Using proxy
- if (this->FTPProxyType > 0) {
- curl_easy_setopt(curl, CURLOPT_PROXY, this->FTPProxy.c_str());
- switch (this->FTPProxyType) {
- case 2:
- curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
- break;
- case 3:
- curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
- break;
- default:
- curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
- }
- }
-
- // enable uploading
- ::curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
-
- // if there is little to no activity for too long stop submitting
- ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1);
- ::curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME,
- SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT);
-
- ::curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
-
- std::string local_file = *file;
- if (!cmSystemTools::FileExists(local_file.c_str())) {
- local_file = localprefix + "/" + *file;
- }
- std::string upload_as =
- url + "/" + remoteprefix + cmSystemTools::GetFilenameName(*file);
-
- if (!cmSystemTools::FileExists(local_file.c_str())) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- " Cannot find file: " << local_file << std::endl);
- ::curl_easy_cleanup(curl);
- ::curl_global_cleanup();
- return false;
- }
- unsigned long filelen = cmSystemTools::FileLength(local_file);
-
- ftpfile = cmsys::SystemTools::Fopen(local_file, "rb");
- *this->LogFile << "\tUpload file: " << local_file << " to " << upload_as
- << std::endl;
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " Upload file: " << local_file << " to "
- << upload_as << std::endl,
- this->Quiet);
-
- ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
-
- // specify target
- ::curl_easy_setopt(curl, CURLOPT_URL, upload_as.c_str());
-
- // now specify which file to upload
- ::curl_easy_setopt(curl, CURLOPT_INFILE, ftpfile);
-
- // and give the size of the upload (optional)
- ::curl_easy_setopt(curl, CURLOPT_INFILESIZE, static_cast<long>(filelen));
-
- // and give curl the buffer for errors
- ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer);
-
- // specify handler for output
- ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
- cmCTestSubmitHandlerWriteMemoryCallback);
- ::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
- cmCTestSubmitHandlerCurlDebugCallback);
-
- /* we pass our 'chunk' struct to the callback function */
- cmCTestSubmitHandlerVectorOfChar chunk;
- cmCTestSubmitHandlerVectorOfChar chunkDebug;
- ::curl_easy_setopt(curl, CURLOPT_FILE, (void*)&chunk);
- ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void*)&chunkDebug);
-
- // Now run off and do what you've been told!
- res = ::curl_easy_perform(curl);
-
- if (!chunk.empty()) {
- cmCTestOptionalLog(this->CTest, DEBUG, "CURL output: ["
- << cmCTestLogWrite(&*chunk.begin(), chunk.size())
- << "]" << std::endl,
- this->Quiet);
- }
- if (!chunkDebug.empty()) {
- cmCTestOptionalLog(
- this->CTest, DEBUG, "CURL debug output: ["
- << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]"
- << std::endl,
- this->Quiet);
- }
-
- fclose(ftpfile);
- if (res) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, " Error when uploading file: "
- << local_file << std::endl);
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- " Error message was: " << error_buffer << std::endl);
- *this->LogFile << " Error when uploading file: " << local_file
- << std::endl
- << " Error message was: " << error_buffer << std::endl
- << " Curl output was: ";
- // avoid dereference of empty vector
- if (!chunk.empty()) {
- *this->LogFile << cmCTestLogWrite(&*chunk.begin(), chunk.size());
- cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: ["
- << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
- << std::endl);
- }
- *this->LogFile << std::endl;
- ::curl_easy_cleanup(curl);
- ::curl_global_cleanup();
- return false;
- }
- // always cleanup
- ::curl_easy_cleanup(curl);
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Uploaded: " + local_file << std::endl,
- this->Quiet);
- }
- }
- ::curl_global_cleanup();
- return true;
-}
-
-// Uploading files is simpler
-bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
- const std::set<std::string>& files,
- const std::string& remoteprefix,
- const std::string& url)
+bool cmCTestSubmitHandler::SubmitUsingHTTP(
+ const std::string& localprefix, const std::vector<std::string>& files,
+ const std::string& remoteprefix, const std::string& url)
{
CURL* curl;
CURLcode res;
@@ -303,37 +143,31 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
char error_buffer[1024];
// Set Content-Type to satisfy fussy modsecurity rules.
struct curl_slist* headers =
- ::curl_slist_append(CM_NULLPTR, "Content-Type: text/xml");
+ ::curl_slist_append(nullptr, "Content-Type: text/xml");
// Add any additional headers that the user specified.
- for (std::vector<std::string>::const_iterator h = this->HttpHeaders.begin();
- h != this->HttpHeaders.end(); ++h) {
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Add HTTP Header: \"" << *h << "\"" << std::endl,
+ for (std::string const& h : this->HttpHeaders) {
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ " Add HTTP Header: \"" << h << "\"" << std::endl,
this->Quiet);
- headers = ::curl_slist_append(headers, h->c_str());
+ headers = ::curl_slist_append(headers, h.c_str());
}
/* In windows, this will init the winsock stuff */
::curl_global_init(CURL_GLOBAL_ALL);
- std::string dropMethod(this->CTest->GetCTestConfiguration("DropMethod"));
std::string curlopt(this->CTest->GetCTestConfiguration("CurlOptions"));
- std::vector<std::string> args;
- cmSystemTools::ExpandListArgument(curlopt, args);
+ std::vector<std::string> args = cmExpandedList(curlopt);
bool verifyPeerOff = false;
bool verifyHostOff = false;
- for (std::vector<std::string>::iterator i = args.begin(); i != args.end();
- ++i) {
- if (*i == "CURLOPT_SSL_VERIFYPEER_OFF") {
+ for (std::string const& arg : args) {
+ if (arg == "CURLOPT_SSL_VERIFYPEER_OFF") {
verifyPeerOff = true;
}
- if (*i == "CURLOPT_SSL_VERIFYHOST_OFF") {
+ if (arg == "CURLOPT_SSL_VERIFYHOST_OFF") {
verifyHostOff = true;
}
}
- std::string::size_type kk;
- cmCTest::SetOfStrings::const_iterator file;
- for (file = files.begin(); file != files.end(); ++file) {
+ for (std::string const& file : files) {
/* get a curl handle */
curl = curl_easy_init();
if (curl) {
@@ -388,53 +222,72 @@ 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())) {
- local_file = localprefix + "/" + *file;
+ std::string local_file = file;
+ bool initialize_cdash_buildid = false;
+ if (!cmSystemTools::FileExists(local_file)) {
+ local_file = cmStrCat(localprefix, "/", file);
+ // If this file exists within the local Testing directory we assume
+ // that it will be associated with the current build in CDash.
+ initialize_cdash_buildid = true;
}
std::string remote_file =
- remoteprefix + cmSystemTools::GetFilenameName(*file);
+ remoteprefix + cmSystemTools::GetFilenameName(file);
*this->LogFile << "\tUpload file: " << local_file << " to "
<< remote_file << std::endl;
- std::string ofile;
- for (kk = 0; kk < remote_file.size(); kk++) {
- char c = remote_file[kk];
- char hexCh[4] = { 0, 0, 0, 0 };
- hexCh[0] = c;
- switch (c) {
- case '+':
- case '?':
- case '/':
- case '\\':
- case '&':
- case ' ':
- case '=':
- case '%':
- sprintf(hexCh, "%%%02X", (int)c);
- ofile.append(hexCh);
- break;
- default:
- ofile.append(hexCh);
+ std::string ofile = cmSystemTools::EncodeURL(remote_file);
+ std::string upload_as =
+ cmStrCat(url, ((url.find('?') == std::string::npos) ? '?' : '&'),
+ "FileName=", ofile);
+
+ if (initialize_cdash_buildid) {
+ // Provide extra arguments to CDash so that it can initialize and
+ // return a buildid.
+ cmCTestCurl ctest_curl(this->CTest);
+ upload_as += "&build=";
+ upload_as +=
+ ctest_curl.Escape(this->CTest->GetCTestConfiguration("BuildName"));
+ upload_as += "&site=";
+ upload_as +=
+ ctest_curl.Escape(this->CTest->GetCTestConfiguration("Site"));
+ upload_as += "&stamp=";
+ upload_as += ctest_curl.Escape(this->CTest->GetCurrentTag());
+ upload_as += "-";
+ upload_as += ctest_curl.Escape(this->CTest->GetTestModelString());
+ cmCTestScriptHandler* ch = this->CTest->GetScriptHandler();
+ cmake* cm = ch->GetCMake();
+ if (cm) {
+ const char* subproject =
+ cm->GetState()->GetGlobalProperty("SubProject");
+ if (subproject) {
+ upload_as += "&subproject=";
+ upload_as += ctest_curl.Escape(subproject);
+ }
}
}
- std::string upload_as = url +
- ((url.find('?') == std::string::npos) ? '?' : '&') + "FileName=" +
- ofile;
+
+ // Generate Done.xml right before it is submitted.
+ // The reason for this is two-fold:
+ // 1) It must be generated after some other part has been submitted
+ // so we have a buildId to refer to in its contents.
+ // 2) By generating Done.xml here its timestamp will be as late as
+ // possible. This gives us a more accurate record of how long the
+ // entire build took to complete.
+ if (file == "Done.xml") {
+ this->CTest->GenerateDoneFile();
+ }
upload_as += "&MD5=";
- if (cmSystemTools::IsOn(this->GetOption("InternalTest"))) {
+ if (cmIsOn(this->GetOption("InternalTest"))) {
upload_as += "bad_md5sum";
} else {
- char md5[33];
- cmSystemTools::ComputeFileMD5(local_file, md5);
- md5[32] = 0;
- upload_as += md5;
+ upload_as +=
+ 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);
@@ -454,6 +307,10 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
// specify target
::curl_easy_setopt(curl, CURLOPT_URL, upload_as.c_str());
+ // CURLAUTH_BASIC is default, and here we allow additional methods,
+ // including more secure ones
+ ::curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+
// now specify which file to upload
::curl_easy_setopt(curl, CURLOPT_INFILE, ftpfile);
@@ -472,23 +329,25 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
/* we pass our 'chunk' struct to the callback function */
cmCTestSubmitHandlerVectorOfChar chunk;
cmCTestSubmitHandlerVectorOfChar chunkDebug;
- ::curl_easy_setopt(curl, CURLOPT_FILE, (void*)&chunk);
- ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void*)&chunkDebug);
+ ::curl_easy_setopt(curl, CURLOPT_FILE, &chunk);
+ ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &chunkDebug);
// Now run off and do what you've been told!
res = ::curl_easy_perform(curl);
if (!chunk.empty()) {
- cmCTestOptionalLog(this->CTest, DEBUG, "CURL output: ["
- << cmCTestLogWrite(&*chunk.begin(), chunk.size())
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "CURL output: ["
+ << cmCTestLogWrite(chunk.data(), chunk.size())
<< "]" << std::endl,
this->Quiet);
this->ParseResponse(chunk);
}
if (!chunkDebug.empty()) {
cmCTestOptionalLog(
- this->CTest, DEBUG, "CURL debug output: ["
- << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]"
+ this->CTest, DEBUG,
+ "CURL debug output: ["
+ << cmCTestLogWrite(chunkDebug.data(), chunkDebug.size()) << "]"
<< std::endl,
this->Quiet);
}
@@ -496,30 +355,31 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
// If curl failed for any reason, or checksum fails, wait and retry
//
if (res != CURLE_OK || this->HasErrors) {
- std::string retryDelay = this->GetOption("RetryDelay") == CM_NULLPTR
+ std::string retryDelay = this->GetOption("RetryDelay") == nullptr
? ""
: this->GetOption("RetryDelay");
- std::string retryCount = this->GetOption("RetryCount") == CM_NULLPTR
+ std::string retryCount = this->GetOption("RetryCount") == nullptr
? ""
: this->GetOption("RetryCount");
- int delay = retryDelay == ""
- ? atoi(this->CTest->GetCTestConfiguration("CTestSubmitRetryDelay")
- .c_str())
- : atoi(retryDelay.c_str());
- int count = retryCount == ""
+ 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())
: atoi(retryCount.c_str());
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);
}
@@ -539,11 +399,11 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
res = ::curl_easy_perform(curl);
if (!chunk.empty()) {
- cmCTestOptionalLog(
- this->CTest, DEBUG, "CURL output: ["
- << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
- << std::endl,
- this->Quiet);
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "CURL output: ["
+ << cmCTestLogWrite(chunk.data(), chunk.size())
+ << "]" << std::endl,
+ this->Quiet);
this->ParseResponse(chunk);
}
@@ -555,8 +415,9 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
fclose(ftpfile);
if (res) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, " Error when uploading file: "
- << local_file << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Error when uploading file: " << local_file
+ << std::endl);
cmCTestLog(this->CTest, ERROR_MESSAGE,
" Error message was: " << error_buffer << std::endl);
*this->LogFile << " Error when uploading file: " << local_file
@@ -566,10 +427,11 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
// avoid deref of begin for zero size array
if (!chunk.empty()) {
*this->LogFile << " Curl output was: "
- << cmCTestLogWrite(&*chunk.begin(), chunk.size())
+ << cmCTestLogWrite(chunk.data(), chunk.size())
<< std::endl;
- cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: ["
- << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "CURL output: ["
+ << cmCTestLogWrite(chunk.data(), chunk.size()) << "]"
<< std::endl);
}
::curl_easy_cleanup(curl);
@@ -605,6 +467,7 @@ void cmCTestSubmitHandler::ParseResponse(
" Submission failed: " << parser.Message << std::endl);
return;
}
+ this->CTest->SetBuildID(parser.BuildID);
}
output = cmSystemTools::UpperCase(output);
if (output.find("WARNING") != std::string::npos) {
@@ -615,395 +478,12 @@ void cmCTestSubmitHandler::ParseResponse(
}
if (this->HasWarnings || this->HasErrors) {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Server Response:\n"
- << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Server Response:\n"
+ << cmCTestLogWrite(chunk.data(), chunk.size()) << "\n");
}
}
-bool cmCTestSubmitHandler::TriggerUsingHTTP(const std::set<std::string>& files,
- const std::string& remoteprefix,
- const std::string& url)
-{
- CURL* curl;
- char error_buffer[1024];
-
- /* In windows, this will init the winsock stuff */
- ::curl_global_init(CURL_GLOBAL_ALL);
-
- cmCTest::SetOfStrings::const_iterator file;
- for (file = files.begin(); file != files.end(); ++file) {
- /* get a curl handle */
- curl = curl_easy_init();
- if (curl) {
- // Using proxy
- if (this->HTTPProxyType > 0) {
- curl_easy_setopt(curl, CURLOPT_PROXY, this->HTTPProxy.c_str());
- switch (this->HTTPProxyType) {
- case 2:
- curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
- break;
- case 3:
- curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
- break;
- default:
- curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
- if (!this->HTTPProxyAuth.empty()) {
- curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD,
- this->HTTPProxyAuth.c_str());
- }
- }
- }
-
- ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
-
- // and give curl the buffer for errors
- ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer);
-
- // specify handler for output
- ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
- cmCTestSubmitHandlerWriteMemoryCallback);
- ::curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
- cmCTestSubmitHandlerCurlDebugCallback);
-
- /* we pass our 'chunk' struct to the callback function */
- cmCTestSubmitHandlerVectorOfChar chunk;
- cmCTestSubmitHandlerVectorOfChar chunkDebug;
- ::curl_easy_setopt(curl, CURLOPT_FILE, (void*)&chunk);
- ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void*)&chunkDebug);
-
- std::string rfile = remoteprefix + cmSystemTools::GetFilenameName(*file);
- std::string ofile;
- std::string::iterator kk;
- for (kk = rfile.begin(); kk < rfile.end(); ++kk) {
- char c = *kk;
- char hexCh[4] = { 0, 0, 0, 0 };
- hexCh[0] = c;
- switch (c) {
- case '+':
- case '?':
- case '/':
- case '\\':
- case '&':
- case ' ':
- case '=':
- case '%':
- sprintf(hexCh, "%%%02X", (int)c);
- ofile.append(hexCh);
- break;
- default:
- ofile.append(hexCh);
- }
- }
- std::string turl = url +
- ((url.find('?') == std::string::npos) ? '?' : '&') + "xmlfile=" +
- ofile;
- *this->LogFile << "Trigger url: " << turl << std::endl;
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " Trigger url: " << turl << std::endl, this->Quiet);
- curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
- curl_easy_setopt(curl, CURLOPT_URL, turl.c_str());
- if (curl_easy_perform(curl)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- " Error when triggering: " << turl << std::endl);
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- " Error message was: " << error_buffer << std::endl);
- *this->LogFile << "\tTriggering failed with error: " << error_buffer
- << std::endl
- << " Error message was: " << error_buffer
- << std::endl;
- if (!chunk.empty()) {
- *this->LogFile << " Curl output was: "
- << cmCTestLogWrite(&*chunk.begin(), chunk.size())
- << std::endl;
- cmCTestLog(this->CTest, ERROR_MESSAGE, "CURL output: ["
- << cmCTestLogWrite(&*chunk.begin(), chunk.size()) << "]"
- << std::endl);
- }
- ::curl_easy_cleanup(curl);
- ::curl_global_cleanup();
- return false;
- }
-
- if (!chunk.empty()) {
- cmCTestOptionalLog(this->CTest, DEBUG, "CURL output: ["
- << cmCTestLogWrite(&*chunk.begin(), chunk.size())
- << "]" << std::endl,
- this->Quiet);
- }
- if (!chunkDebug.empty()) {
- cmCTestOptionalLog(
- this->CTest, DEBUG, "CURL debug output: ["
- << cmCTestLogWrite(&*chunkDebug.begin(), chunkDebug.size()) << "]"
- << std::endl,
- this->Quiet);
- }
-
- // always cleanup
- ::curl_easy_cleanup(curl);
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl,
- this->Quiet);
- }
- }
- ::curl_global_cleanup();
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Dart server triggered..." << std::endl, this->Quiet);
- return true;
-}
-
-bool cmCTestSubmitHandler::SubmitUsingSCP(const std::string& scp_command,
- const std::string& localprefix,
- const std::set<std::string>& files,
- const std::string& remoteprefix,
- const std::string& url)
-{
- if (scp_command.empty() || localprefix.empty() || files.empty() ||
- remoteprefix.empty() || url.empty()) {
- return false;
- }
-
- std::vector<const char*> argv;
- argv.push_back(scp_command.c_str()); // Scp command
- argv.push_back(scp_command.c_str()); // Dummy string for file
- argv.push_back(scp_command.c_str()); // Dummy string for remote url
- argv.push_back(CM_NULLPTR);
-
- cmsysProcess* cp = cmsysProcess_New();
- cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
- // cmsysProcess_SetTimeout(cp, timeout);
-
- int problems = 0;
-
- cmCTest::SetOfStrings::const_iterator file;
- for (file = files.begin(); file != files.end(); ++file) {
- int retVal;
-
- std::string lfname = localprefix;
- cmSystemTools::ConvertToUnixSlashes(lfname);
- lfname += "/" + *file;
- lfname = cmSystemTools::ConvertToOutputPath(lfname.c_str());
- argv[1] = lfname.c_str();
- std::string rfname = url + "/" + remoteprefix + *file;
- argv[2] = rfname.c_str();
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Execute \""
- << argv[0] << "\" \"" << argv[1] << "\" \"" << argv[2]
- << "\"" << std::endl,
- this->Quiet);
- *this->LogFile << "Execute \"" << argv[0] << "\" \"" << argv[1] << "\" \""
- << argv[2] << "\"" << std::endl;
-
- cmsysProcess_SetCommand(cp, &*argv.begin());
- cmsysProcess_Execute(cp);
- char* data;
- int length;
- cmProcessOutput processOutput;
- std::string strdata;
-
- while (cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) {
- processOutput.DecodeText(data, length, strdata);
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- cmCTestLogWrite(strdata.c_str(), strdata.size()),
- this->Quiet);
- }
- processOutput.DecodeText(std::string(), strdata);
- if (!strdata.empty()) {
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- cmCTestLogWrite(strdata.c_str(), strdata.size()),
- this->Quiet);
- }
-
- cmsysProcess_WaitForExit(cp, CM_NULLPTR);
-
- int result = cmsysProcess_GetState(cp);
-
- if (result == cmsysProcess_State_Exited) {
- retVal = cmsysProcess_GetExitValue(cp);
- if (retVal != 0) {
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "\tSCP returned: " << retVal << std::endl,
- this->Quiet);
- *this->LogFile << "\tSCP returned: " << retVal << std::endl;
- problems++;
- }
- } else if (result == cmsysProcess_State_Exception) {
- retVal = cmsysProcess_GetExitException(cp);
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "\tThere was an exception: " << retVal << std::endl);
- *this->LogFile << "\tThere was an exception: " << retVal << std::endl;
- problems++;
- } else if (result == cmsysProcess_State_Expired) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "\tThere was a timeout"
- << std::endl);
- *this->LogFile << "\tThere was a timeout" << std::endl;
- problems++;
- } else if (result == cmsysProcess_State_Error) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "\tError executing SCP: "
- << cmsysProcess_GetErrorString(cp) << std::endl);
- *this->LogFile << "\tError executing SCP: "
- << cmsysProcess_GetErrorString(cp) << std::endl;
- problems++;
- }
- }
- cmsysProcess_Delete(cp);
- return problems == 0;
-}
-
-bool cmCTestSubmitHandler::SubmitUsingCP(const std::string& localprefix,
- const std::set<std::string>& files,
- const std::string& remoteprefix,
- const std::string& destination)
-{
- if (localprefix.empty() || files.empty() || remoteprefix.empty() ||
- destination.empty()) {
- /* clang-format off */
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Missing arguments for submit via cp:\n"
- << "\tlocalprefix: " << localprefix << "\n"
- << "\tNumber of files: " << files.size() << "\n"
- << "\tremoteprefix: " << remoteprefix << "\n"
- << "\tdestination: " << destination << std::endl);
- /* clang-format on */
- return false;
- }
-
- cmCTest::SetOfStrings::const_iterator file;
- for (file = files.begin(); file != files.end(); ++file) {
- std::string lfname = localprefix;
- cmSystemTools::ConvertToUnixSlashes(lfname);
- lfname += "/" + *file;
- std::string rfname = destination + "/" + remoteprefix + *file;
- cmSystemTools::CopyFileAlways(lfname, rfname);
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " Copy file: "
- << lfname << " to " << rfname << std::endl,
- this->Quiet);
- }
- std::string tagDoneFile = destination + "/" + remoteprefix + "DONE";
- cmSystemTools::Touch(tagDoneFile, true);
- return true;
-}
-
-#if defined(CTEST_USE_XMLRPC)
-bool cmCTestSubmitHandler::SubmitUsingXMLRPC(
- const std::string& localprefix, const std::set<std::string>& files,
- const std::string& remoteprefix, const std::string& url)
-{
- xmlrpc_env env;
- char ctestString[] = "CTest";
- std::string ctestVersionString = cmVersion::GetCMakeVersion();
- char* ctestVersion = const_cast<char*>(ctestVersionString.c_str());
-
- std::string realURL = url + "/" + remoteprefix + "/Command/";
-
- /* Start up our XML-RPC client library. */
- xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, ctestString, ctestVersion);
-
- /* Initialize our error-handling environment. */
- xmlrpc_env_init(&env);
-
- /* Call the famous server at UserLand. */
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Submitting to: "
- << realURL << " (" << remoteprefix << ")" << std::endl,
- this->Quiet);
- cmCTest::SetOfStrings::const_iterator file;
- for (file = files.begin(); file != files.end(); ++file) {
- xmlrpc_value* result;
-
- std::string local_file = *file;
- if (!cmSystemTools::FileExists(local_file.c_str())) {
- local_file = localprefix + "/" + *file;
- }
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Submit file: " << local_file << std::endl,
- this->Quiet);
- struct stat st;
- if (::stat(local_file.c_str(), &st)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- " Cannot find file: " << local_file << std::endl);
- return false;
- }
-
- // off_t can be bigger than size_t. fread takes size_t.
- // make sure the file is not too big.
- if (static_cast<off_t>(static_cast<size_t>(st.st_size)) !=
- static_cast<off_t>(st.st_size)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, " File too big: " << local_file
- << std::endl);
- return false;
- }
- size_t fileSize = static_cast<size_t>(st.st_size);
- FILE* fp = cmsys::SystemTools::Fopen(local_file, "rb");
- if (!fp) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- " Cannot open file: " << local_file << std::endl);
- return false;
- }
-
- unsigned char* fileBuffer = new unsigned char[fileSize];
- if (fread(fileBuffer, 1, fileSize, fp) != fileSize) {
- delete[] fileBuffer;
- fclose(fp);
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- " Cannot read file: " << local_file << std::endl);
- return false;
- }
- fclose(fp);
-
- char remoteCommand[] = "Submit.put";
- char* pRealURL = const_cast<char*>(realURL.c_str());
- result = xmlrpc_client_call(&env, pRealURL, remoteCommand, "(6)",
- fileBuffer, (xmlrpc_int32)fileSize);
-
- delete[] fileBuffer;
-
- if (env.fault_occurred) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, " Submission problem: "
- << env.fault_string << " (" << env.fault_code << ")"
- << std::endl);
- xmlrpc_env_clean(&env);
- xmlrpc_client_cleanup();
- return false;
- }
-
- /* Dispose of our result value. */
- xmlrpc_DECREF(result);
- }
-
- /* Clean up our error-handling environment. */
- xmlrpc_env_clean(&env);
-
- /* Shutdown our XML-RPC client library. */
- xmlrpc_client_cleanup();
- return true;
-}
-#else
-bool cmCTestSubmitHandler::SubmitUsingXMLRPC(
- std::string const& /*unused*/, std::set<std::string> const& /*unused*/,
- std::string const& /*unused*/, std::string const& /*unused*/)
-{
- return false;
-}
-#endif
-
-void cmCTestSubmitHandler::ConstructCDashURL(std::string& dropMethod,
- std::string& url)
-{
- dropMethod = this->CTest->GetCTestConfiguration("DropMethod");
- url = dropMethod;
- url += "://";
- if (!this->CTest->GetCTestConfiguration("DropSiteUser").empty()) {
- url += this->CTest->GetCTestConfiguration("DropSiteUser");
- cmCTestOptionalLog(
- this->CTest, HANDLER_OUTPUT,
- this->CTest->GetCTestConfiguration("DropSiteUser").c_str(), this->Quiet);
- if (!this->CTest->GetCTestConfiguration("DropSitePassword").empty()) {
- url += ":" + this->CTest->GetCTestConfiguration("DropSitePassword");
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, ":******", this->Quiet);
- }
- url += "@";
- }
- url += this->CTest->GetCTestConfiguration("DropSite") +
- this->CTest->GetCTestConfiguration("DropLocation");
-}
-
int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
std::string const& typeString)
{
@@ -1012,70 +492,75 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
return -1;
}
if (!cmSystemTools::FileExists(file)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Upload file not found: '"
- << file << "'\n");
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Upload file not found: '" << file << "'\n");
return -1;
}
cmCTestCurl curl(this->CTest);
curl.SetQuiet(this->Quiet);
std::string curlopt(this->CTest->GetCTestConfiguration("CurlOptions"));
- std::vector<std::string> args;
- cmSystemTools::ExpandListArgument(curlopt, args);
+ std::vector<std::string> args = cmExpandedList(curlopt);
curl.SetCurlOptions(args);
curl.SetTimeOutSeconds(SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT);
curl.SetHttpHeaders(this->HttpHeaders);
- std::string dropMethod;
- std::string url;
- this->ConstructCDashURL(dropMethod, url);
- std::string::size_type pos = url.find("submit.php?");
- url = url.substr(0, pos + 10);
- if (!(dropMethod == "http" || dropMethod == "https")) {
+ std::string url = this->CTest->GetSubmitURL();
+ std::string fields;
+ std::string::size_type pos = url.find('?');
+ if (pos != std::string::npos) {
+ fields = url.substr(pos + 1);
+ url = url.substr(0, pos);
+ }
+ if (!cmHasLiteralPrefix(url, "http://") &&
+ !cmHasLiteralPrefix(url, "https://")) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Only http and https are supported for CDASH_UPLOAD\n");
return -1;
}
- bool internalTest = cmSystemTools::IsOn(this->GetOption("InternalTest"));
+ bool internalTest = cmIsOn(this->GetOption("InternalTest"));
// Get RETRY_COUNT and RETRY_DELAY values if they were set.
- std::string retryDelayString = this->GetOption("RetryDelay") == CM_NULLPTR
+ std::string retryDelayString = this->GetOption("RetryDelay") == nullptr
? ""
: this->GetOption("RetryDelay");
- std::string retryCountString = this->GetOption("RetryCount") == CM_NULLPTR
+ std::string retryCountString = this->GetOption("RetryCount") == nullptr
? ""
: this->GetOption("RetryCount");
- unsigned long retryDelay = 0;
- if (retryDelayString != "") {
- if (!cmSystemTools::StringToULong(retryDelayString.c_str(), &retryDelay)) {
- cmCTestLog(this->CTest, WARNING, "Invalid value for 'RETRY_DELAY' : "
- << retryDelayString << std::endl);
+ auto retryDelay = std::chrono::seconds(0);
+ if (!retryDelayString.empty()) {
+ unsigned long retryDelayValue = 0;
+ if (!cmStrToULong(retryDelayString, &retryDelayValue)) {
+ cmCTestLog(this->CTest, WARNING,
+ "Invalid value for 'RETRY_DELAY' : " << retryDelayString
+ << std::endl);
+ } else {
+ retryDelay = std::chrono::seconds(retryDelayValue);
}
}
unsigned long retryCount = 0;
- if (retryCountString != "") {
- if (!cmSystemTools::StringToULong(retryCountString.c_str(), &retryCount)) {
- cmCTestLog(this->CTest, WARNING, "Invalid value for 'RETRY_DELAY' : "
- << retryCountString << std::endl);
+ if (!retryCountString.empty()) {
+ if (!cmStrToULong(retryCountString, &retryCount)) {
+ cmCTestLog(this->CTest, WARNING,
+ "Invalid value for 'RETRY_DELAY' : " << retryCountString
+ << std::endl);
}
}
- char md5sum[33];
- md5sum[32] = 0;
- cmSystemTools::ComputeFileMD5(file, md5sum);
+ std::string md5sum =
+ cmSystemTools::ComputeFileHash(file, cmCryptoHash::AlgoMD5);
// 1. request the buildid and check to see if the file
// has already been uploaded
// TODO I added support for subproject. You would need to add
// a "&subproject=subprojectname" to the first POST.
- cmCTestScriptHandler* ch =
- static_cast<cmCTestScriptHandler*>(this->CTest->GetHandler("script"));
+ cmCTestScriptHandler* ch = this->CTest->GetScriptHandler();
cmake* cm = ch->GetCMake();
const char* subproject = cm->GetState()->GetGlobalProperty("SubProject");
// TODO: Encode values for a URL instead of trusting caller.
std::ostringstream str;
- str << "project="
- << curl.Escape(this->CTest->GetCTestConfiguration("ProjectName")) << "&";
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()) << "&"
@@ -1083,12 +568,20 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
<< curl.Escape(this->CTest->GetCTestConfiguration("BuildName")) << "&"
<< "site=" << curl.Escape(this->CTest->GetCTestConfiguration("Site"))
<< "&"
+ << "group=" << curl.Escape(this->CTest->GetTestModelString())
+ << "&"
+ // For now, we send both "track" and "group" to CDash in case we're
+ // submitting to an older instance that still expects the prior
+ // terminology.
<< "track=" << curl.Escape(this->CTest->GetTestModelString()) << "&"
- << "starttime=" << (int)cmSystemTools::GetTime() << "&"
- << "endtime=" << (int)cmSystemTools::GetTime() << "&"
+ << "starttime=" << timeNow << "&"
+ << "endtime=" << timeNow << "&"
<< "datafilesmd5[0]=" << md5sum << "&"
<< "type=" << curl.Escape(typeString);
- std::string fields = str.str();
+ if (!fields.empty()) {
+ fields += '&';
+ }
+ fields += str.str();
cmCTestOptionalLog(this->CTest, DEBUG,
"fields: " << fields << "\nurl:" << url
<< "\nfile: " << file << "\n",
@@ -1100,12 +593,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);
}
@@ -1121,7 +614,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
}
}
if (!internalTest && !requestSucceeded) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Error in HttpRequest\n"
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error in HttpRequest\n"
<< response);
return -1;
}
@@ -1131,7 +625,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
Json::Value json;
Json::Reader reader;
if (!internalTest && !reader.parse(response, json)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "error parsing json string ["
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "error parsing json string ["
<< response << "]\n"
<< reader.getFormattedErrorMessages() << "\n");
return -1;
@@ -1174,12 +669,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);
}
@@ -1198,12 +693,14 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
}
if (!uploadSucceeded) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "error uploading to CDash. "
- << file << " " << url << " " << fstr.str());
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "error uploading to CDash. " << file << " " << url << " "
+ << fstr.str());
return -1;
}
if (!reader.parse(response, json)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "error parsing json string ["
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "error parsing json string ["
<< response << "]\n"
<< reader.getFormattedErrorMessages() << "\n");
return -1;
@@ -1221,11 +718,6 @@ int cmCTestSubmitHandler::ProcessHandler()
if (cdashUploadFile && cdashUploadType) {
return this->HandleCDashUploadFile(cdashUploadFile, cdashUploadType);
}
- std::string iscdash = this->CTest->GetCTestConfiguration("IsCDash");
- // cdash does not need to trigger so just return true
- if (!iscdash.empty()) {
- this->CDash = true;
- }
const std::string& buildDirectory =
this->CTest->GetCTestConfiguration("BuildDirectory");
@@ -1263,46 +755,20 @@ int cmCTestSubmitHandler::ProcessHandler()
}
}
- if (getenv("FTP_PROXY")) {
- this->FTPProxyType = 1;
- this->FTPProxy = getenv("FTP_PROXY");
- if (getenv("FTP_PROXY_PORT")) {
- this->FTPProxy += ":";
- this->FTPProxy += getenv("FTP_PROXY_PORT");
- }
- if (getenv("FTP_PROXY_TYPE")) {
- std::string type = getenv("FTP_PROXY_TYPE");
- // HTTP/SOCKS4/SOCKS5
- if (type == "HTTP") {
- this->FTPProxyType = 1;
- } else if (type == "SOCKS4") {
- this->FTPProxyType = 2;
- } else if (type == "SOCKS5") {
- this->FTPProxyType = 3;
- }
- }
- }
-
if (!this->HTTPProxy.empty()) {
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
" Use HTTP Proxy: " << this->HTTPProxy << std::endl,
this->Quiet);
}
- if (!this->FTPProxy.empty()) {
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Use FTP Proxy: " << this->FTPProxy << std::endl,
- this->Quiet);
- }
cmGeneratedFileStream ofs;
this->StartLogFile("Submit", ofs);
- cmCTest::SetOfStrings files;
+ std::vector<std::string> files;
std::string prefix = this->GetSubmitResultsPrefix();
if (!this->Files.empty()) {
// Submit the explicitly selected files:
- //
- files.insert(this->Files.begin(), this->Files.end());
+ cmAppend(files, this->Files);
}
// Add to the list of files to submit from any selected, existing parts:
@@ -1324,13 +790,11 @@ int cmCTestSubmitHandler::ProcessHandler()
cmCTestOptionalLog(this->CTest, DEBUG,
"Globbing for: " << gpath << std::endl, this->Quiet);
if (cmSystemTools::SimpleGlob(gpath, gfiles, 1)) {
- size_t cc;
- for (cc = 0; cc < gfiles.size(); cc++) {
- gfiles[cc] = gfiles[cc].substr(glen);
+ for (std::string& gfile : gfiles) {
+ gfile = gfile.substr(glen);
cmCTestOptionalLog(this->CTest, DEBUG,
- "Glob file: " << gfiles[cc] << std::endl,
- this->Quiet);
- this->CTest->AddSubmitFile(cmCTest::PartCoverage, gfiles[cc].c_str());
+ "Glob file: " << gfile << std::endl, this->Quiet);
+ this->CTest->AddSubmitFile(cmCTest::PartCoverage, gfile.c_str());
}
} else {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Problem globbing" << std::endl);
@@ -1350,234 +814,67 @@ int cmCTestSubmitHandler::ProcessHandler()
}
// Submit files from this part.
- std::vector<std::string> const& pfiles = this->CTest->GetSubmitFiles(p);
- files.insert(pfiles.begin(), pfiles.end());
+ cmAppend(files, this->CTest->GetSubmitFiles(p));
+ }
+
+ // Make sure files are unique, but preserve order.
+ {
+ // This endPos intermediate is needed to work around non-conformant C++11
+ // standard libraries that have erase(iterator,iterator) instead of
+ // erase(const_iterator,const_iterator).
+ size_t endPos = cmRemoveDuplicates(files) - files.cbegin();
+ files.erase(files.begin() + endPos, files.end());
+ }
+
+ // Submit Done.xml last
+ if (this->SubmitPart[cmCTest::PartDone]) {
+ files.emplace_back("Done.xml");
}
if (ofs) {
ofs << "Upload files:" << std::endl;
int cnt = 0;
- cmCTest::SetOfStrings::iterator it;
- for (it = files.begin(); it != files.end(); ++it) {
- ofs << cnt << "\t" << *it << std::endl;
+ for (std::string const& file : files) {
+ ofs << cnt << "\t" << file << std::endl;
cnt++;
}
}
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Submit files (using "
- << this->CTest->GetCTestConfiguration("DropMethod")
- << ")" << std::endl,
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Submit files\n",
this->Quiet);
- const char* specificTrack = this->CTest->GetSpecificTrack();
- if (specificTrack) {
+ const char* specificGroup = this->CTest->GetSpecificGroup();
+ if (specificGroup) {
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Send to track: " << specificTrack << std::endl,
+ " Send to group: " << specificGroup << std::endl,
this->Quiet);
}
this->SetLogFile(&ofs);
- std::string dropMethod(this->CTest->GetCTestConfiguration("DropMethod"));
-
- if (dropMethod == "" || dropMethod == "ftp") {
- ofs << "Using drop method: FTP" << std::endl;
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Using FTP submit method" << std::endl
- << " Drop site: ftp://",
- this->Quiet);
- std::string url = "ftp://";
- url += cmCTest::MakeURLSafe(
- this->CTest->GetCTestConfiguration("DropSiteUser")) +
- ":" + cmCTest::MakeURLSafe(
- this->CTest->GetCTestConfiguration("DropSitePassword")) +
- "@" + this->CTest->GetCTestConfiguration("DropSite") +
- cmCTest::MakeURLSafe(this->CTest->GetCTestConfiguration("DropLocation"));
- if (!this->CTest->GetCTestConfiguration("DropSiteUser").empty()) {
- cmCTestOptionalLog(
- this->CTest, HANDLER_OUTPUT,
- this->CTest->GetCTestConfiguration("DropSiteUser").c_str(),
- this->Quiet);
- if (!this->CTest->GetCTestConfiguration("DropSitePassword").empty()) {
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, ":******",
- this->Quiet);
- }
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "@", this->Quiet);
- }
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- this->CTest->GetCTestConfiguration("DropSite")
- << this->CTest->GetCTestConfiguration("DropLocation")
- << std::endl,
- this->Quiet);
- if (!this->SubmitUsingFTP(buildDirectory + "/Testing/" +
- this->CTest->GetCurrentTag(),
- files, prefix, url)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- " Problems when submitting via FTP" << std::endl);
- ofs << " Problems when submitting via FTP" << std::endl;
- return -1;
- }
- if (!this->CDash) {
- cmCTestOptionalLog(
- this->CTest, HANDLER_OUTPUT, " Using HTTP trigger method"
- << std::endl
- << " Trigger site: "
- << this->CTest->GetCTestConfiguration("TriggerSite") << std::endl,
- this->Quiet);
- if (!this->TriggerUsingHTTP(
- files, prefix,
- this->CTest->GetCTestConfiguration("TriggerSite"))) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- " Problems when triggering via HTTP" << std::endl);
- ofs << " Problems when triggering via HTTP" << std::endl;
- return -1;
- }
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Submission successful" << std::endl, this->Quiet);
- ofs << " Submission successful" << std::endl;
- return 0;
- }
- } else if (dropMethod == "http" || dropMethod == "https") {
- std::string url = dropMethod;
- url += "://";
- ofs << "Using drop method: " << dropMethod << std::endl;
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Using HTTP submit method" << std::endl
- << " Drop site:" << url,
- this->Quiet);
- if (!this->CTest->GetCTestConfiguration("DropSiteUser").empty()) {
- url += this->CTest->GetCTestConfiguration("DropSiteUser");
- cmCTestOptionalLog(
- this->CTest, HANDLER_OUTPUT,
- this->CTest->GetCTestConfiguration("DropSiteUser").c_str(),
- this->Quiet);
- if (!this->CTest->GetCTestConfiguration("DropSitePassword").empty()) {
- url += ":" + this->CTest->GetCTestConfiguration("DropSitePassword");
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, ":******",
- this->Quiet);
- }
- url += "@";
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "@", this->Quiet);
- }
- url += this->CTest->GetCTestConfiguration("DropSite") +
- this->CTest->GetCTestConfiguration("DropLocation");
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- this->CTest->GetCTestConfiguration("DropSite")
- << this->CTest->GetCTestConfiguration("DropLocation")
- << std::endl,
- this->Quiet);
- if (!this->SubmitUsingHTTP(buildDirectory + "/Testing/" +
- this->CTest->GetCurrentTag(),
- files, prefix, url)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- " Problems when submitting via HTTP" << std::endl);
- ofs << " Problems when submitting via HTTP" << std::endl;
- return -1;
- }
- if (!this->CDash) {
- cmCTestOptionalLog(
- this->CTest, HANDLER_OUTPUT, " Using HTTP trigger method"
- << std::endl
- << " Trigger site: "
- << this->CTest->GetCTestConfiguration("TriggerSite") << std::endl,
- this->Quiet);
- if (!this->TriggerUsingHTTP(
- files, prefix,
- this->CTest->GetCTestConfiguration("TriggerSite"))) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- " Problems when triggering via HTTP" << std::endl);
- ofs << " Problems when triggering via HTTP" << std::endl;
- return -1;
- }
- }
- if (this->HasErrors) {
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Errors occurred during "
- "submission."
- << std::endl);
- ofs << " Errors occurred during submission. " << std::endl;
- } else {
- cmCTestOptionalLog(
- this->CTest, HANDLER_OUTPUT, " Submission successful"
- << (this->HasWarnings ? ", with warnings." : "") << std::endl,
- this->Quiet);
- ofs << " Submission successful"
- << (this->HasWarnings ? ", with warnings." : "") << std::endl;
- }
-
- return 0;
- } else if (dropMethod == "xmlrpc") {
-#if defined(CTEST_USE_XMLRPC)
- ofs << "Using drop method: XML-RPC" << std::endl;
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Using XML-RPC submit method" << std::endl,
- this->Quiet);
- std::string url = this->CTest->GetCTestConfiguration("DropSite");
- prefix = this->CTest->GetCTestConfiguration("DropLocation");
- if (!this->SubmitUsingXMLRPC(buildDirectory + "/Testing/" +
- this->CTest->GetCurrentTag(),
- files, prefix, url)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- " Problems when submitting via XML-RPC" << std::endl);
- ofs << " Problems when submitting via XML-RPC" << std::endl;
- return -1;
- }
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Submission successful" << std::endl, this->Quiet);
- ofs << " Submission successful" << std::endl;
- return 0;
-#else
+ std::string url = this->CTest->GetSubmitURL();
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " SubmitURL: " << url << '\n', this->Quiet);
+ if (!this->SubmitUsingHTTP(buildDirectory + "/Testing/" +
+ this->CTest->GetCurrentTag(),
+ files, prefix, url)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- " Submission method \"xmlrpc\" not compiled into CTest!"
- << std::endl);
+ " Problems when submitting via HTTP\n");
+ ofs << " Problems when submitting via HTTP\n";
return -1;
-#endif
- } else if (dropMethod == "scp") {
- std::string url;
- if (!this->CTest->GetCTestConfiguration("DropSiteUser").empty()) {
- url += this->CTest->GetCTestConfiguration("DropSiteUser") + "@";
- }
- url += this->CTest->GetCTestConfiguration("DropSite") + ":" +
- 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
- cmWorkingDirectory workdir(buildDirectory);
-
- if (!this->SubmitUsingSCP(this->CTest->GetCTestConfiguration("ScpCommand"),
- "Testing/" + this->CTest->GetCurrentTag(), files,
- prefix, url)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- " Problems when submitting via SCP" << std::endl);
- ofs << " Problems when submitting via SCP" << std::endl;
- return -1;
- }
+ }
+ if (this->HasErrors) {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Errors occurred during submission.\n");
+ ofs << " Errors occurred during submission.\n";
+ } else {
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Submission successful" << std::endl, this->Quiet);
- ofs << " Submission successful" << std::endl;
- return 0;
- } else if (dropMethod == "cp") {
- 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
- cmWorkingDirectory workdir(buildDirectory);
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- " Change directory: " << buildDirectory << std::endl,
+ " Submission successful"
+ << (this->HasWarnings ? ", with warnings." : "")
+ << std::endl,
this->Quiet);
-
- if (!this->SubmitUsingCP("Testing/" + this->CTest->GetCurrentTag(), files,
- prefix, location)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- " Problems when submitting via CP" << std::endl);
- ofs << " Problems when submitting via cp" << std::endl;
- return -1;
- }
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Submission successful" << std::endl, this->Quiet);
- ofs << " Submission successful" << std::endl;
- return 0;
+ ofs << " Submission successful"
+ << (this->HasWarnings ? ", with warnings." : "") << std::endl;
}
- cmCTestLog(this->CTest, ERROR_MESSAGE, " Unknown submission method: \""
- << dropMethod << "\"" << std::endl);
- return -1;
+ return 0;
}
std::string cmCTestSubmitHandler::GetSubmitResultsPrefix()
@@ -1600,7 +897,7 @@ void cmCTestSubmitHandler::SelectParts(std::set<cmCTest::Part> const& parts)
}
}
-void cmCTestSubmitHandler::SelectFiles(cmCTest::SetOfStrings const& files)
+void cmCTestSubmitHandler::SelectFiles(std::set<std::string> const& files)
{
this->Files.insert(files.begin(), files.end());
}
diff --git a/Source/CTest/cmCTestSubmitHandler.h b/Source/CTest/cmCTestSubmitHandler.h
index 2923f4f3d..304daaa98 100644
--- a/Source/CTest/cmCTestSubmitHandler.h
+++ b/Source/CTest/cmCTestSubmitHandler.h
@@ -3,16 +3,16 @@
#ifndef cmCTestSubmitHandler_h
#define cmCTestSubmitHandler_h
-#include "cmConfigure.h"
-
-#include "cmCTest.h"
-#include "cmCTestGenericHandler.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <set>
#include <string>
#include <vector>
+#include "cmCTest.h"
+#include "cmCTestGenericHandler.h"
+
/** \class cmCTestSubmitHandler
* \brief Helper class for CTest
*
@@ -22,23 +22,23 @@
class cmCTestSubmitHandler : public cmCTestGenericHandler
{
public:
- typedef cmCTestGenericHandler Superclass;
+ using Superclass = cmCTestGenericHandler;
cmCTestSubmitHandler();
- ~cmCTestSubmitHandler() CM_OVERRIDE { this->LogFile = CM_NULLPTR; }
+ ~cmCTestSubmitHandler() override { this->LogFile = nullptr; }
/*
* The main entry point for this class
*/
- int ProcessHandler() CM_OVERRIDE;
+ int ProcessHandler() override;
- void Initialize() CM_OVERRIDE;
+ void Initialize() override;
/** Specify a set of parts (by name) to submit. */
void SelectParts(std::set<cmCTest::Part> const& parts);
/** Specify a set of files to submit. */
- void SelectFiles(cmCTest::SetOfStrings const& files);
+ void SelectFiles(std::set<std::string> const& files);
// handle the cdash file upload protocol
int HandleCDashUploadFile(std::string const& file, std::string const& type);
@@ -48,40 +48,18 @@ public:
this->HttpHeaders = v;
}
- void ConstructCDashURL(std::string& dropMethod, std::string& url);
-
private:
void SetLogFile(std::ostream* ost) { this->LogFile = ost; }
/**
* Submit file using various ways
*/
- bool SubmitUsingFTP(const std::string& localprefix,
- const std::set<std::string>& files,
- const std::string& remoteprefix, const std::string& url);
bool SubmitUsingHTTP(const std::string& localprefix,
- const std::set<std::string>& files,
+ const std::vector<std::string>& files,
const std::string& remoteprefix,
const std::string& url);
- bool SubmitUsingSCP(const std::string& scp_command,
- const std::string& localprefix,
- const std::set<std::string>& files,
- const std::string& remoteprefix, const std::string& url);
-
- bool SubmitUsingCP(const std::string& localprefix,
- const std::set<std::string>& files,
- const std::string& remoteprefix, const std::string& url);
-
- bool TriggerUsingHTTP(const std::set<std::string>& files,
- const std::string& remoteprefix,
- const std::string& url);
-
- bool SubmitUsingXMLRPC(const std::string& localprefix,
- const std::set<std::string>& files,
- const std::string& remoteprefix,
- const std::string& url);
- typedef std::vector<char> cmCTestSubmitHandlerVectorOfChar;
+ using cmCTestSubmitHandlerVectorOfChar = std::vector<char>;
void ParseResponse(cmCTestSubmitHandlerVectorOfChar chunk);
@@ -92,14 +70,11 @@ private:
std::string HTTPProxy;
int HTTPProxyType;
std::string HTTPProxyAuth;
- std::string FTPProxy;
- int FTPProxyType;
std::ostream* LogFile;
bool SubmitPart[cmCTest::PartCount];
- bool CDash;
bool HasWarnings;
bool HasErrors;
- cmCTest::SetOfStrings Files;
+ std::set<std::string> Files;
std::vector<std::string> HttpHeaders;
};
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index 075b1403a..978421405 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -2,33 +2,37 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestTestCommand.h"
+#include <chrono>
+#include <cstdlib>
+#include <sstream>
+
+#include "cm_static_string_view.hxx"
+
#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
+#include "cmCTestTestHandler.h"
+#include "cmDuration.h"
#include "cmMakefile.h"
-#include "cmSystemTools.h"
+#include "cmStringAlgorithms.h"
-#include <sstream>
-#include <stdlib.h>
-#include <vector>
-
-cmCTestTestCommand::cmCTestTestCommand()
+void cmCTestTestCommand::BindArguments()
{
- this->Arguments[ctt_START] = "START";
- this->Arguments[ctt_END] = "END";
- this->Arguments[ctt_STRIDE] = "STRIDE";
- this->Arguments[ctt_EXCLUDE] = "EXCLUDE";
- this->Arguments[ctt_INCLUDE] = "INCLUDE";
- this->Arguments[ctt_EXCLUDE_LABEL] = "EXCLUDE_LABEL";
- this->Arguments[ctt_INCLUDE_LABEL] = "INCLUDE_LABEL";
- this->Arguments[ctt_EXCLUDE_FIXTURE] = "EXCLUDE_FIXTURE";
- this->Arguments[ctt_EXCLUDE_FIXTURE_SETUP] = "EXCLUDE_FIXTURE_SETUP";
- this->Arguments[ctt_EXCLUDE_FIXTURE_CLEANUP] = "EXCLUDE_FIXTURE_CLEANUP";
- this->Arguments[ctt_PARALLEL_LEVEL] = "PARALLEL_LEVEL";
- this->Arguments[ctt_SCHEDULE_RANDOM] = "SCHEDULE_RANDOM";
- this->Arguments[ctt_STOP_TIME] = "STOP_TIME";
- this->Arguments[ctt_TEST_LOAD] = "TEST_LOAD";
- this->Arguments[ctt_LAST] = CM_NULLPTR;
- this->Last = ctt_LAST;
+ this->cmCTestHandlerCommand::BindArguments();
+ this->Bind("START"_s, this->Start);
+ this->Bind("END"_s, this->End);
+ this->Bind("STRIDE"_s, this->Stride);
+ this->Bind("EXCLUDE"_s, this->Exclude);
+ this->Bind("INCLUDE"_s, this->Include);
+ this->Bind("EXCLUDE_LABEL"_s, this->ExcludeLabel);
+ this->Bind("INCLUDE_LABEL"_s, this->IncludeLabel);
+ this->Bind("EXCLUDE_FIXTURE"_s, this->ExcludeFixture);
+ this->Bind("EXCLUDE_FIXTURE_SETUP"_s, this->ExcludeFixtureSetup);
+ this->Bind("EXCLUDE_FIXTURE_CLEANUP"_s, this->ExcludeFixtureCleanup);
+ this->Bind("PARALLEL_LEVEL"_s, this->ParallelLevel);
+ this->Bind("SCHEDULE_RANDOM"_s, this->ScheduleRandom);
+ this->Bind("STOP_TIME"_s, this->StopTime);
+ this->Bind("TEST_LOAD"_s, this->TestLoad);
+ this->Bind("RESOURCE_SPEC_FILE"_s, this->ResourceSpecFile);
}
cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
@@ -36,69 +40,59 @@ 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);
cmCTestGenericHandler* handler = this->InitializeActualHandler();
- if (this->Values[ctt_START] || this->Values[ctt_END] ||
- this->Values[ctt_STRIDE]) {
- std::ostringstream testsToRunString;
- if (this->Values[ctt_START]) {
- testsToRunString << this->Values[ctt_START];
- }
- testsToRunString << ",";
- if (this->Values[ctt_END]) {
- testsToRunString << this->Values[ctt_END];
- }
- testsToRunString << ",";
- if (this->Values[ctt_STRIDE]) {
- testsToRunString << this->Values[ctt_STRIDE];
- }
- handler->SetOption("TestsToRunInformation",
- testsToRunString.str().c_str());
+ if (!this->Start.empty() || !this->End.empty() || !this->Stride.empty()) {
+ handler->SetOption(
+ "TestsToRunInformation",
+ cmStrCat(this->Start, ',', this->End, ',', this->Stride).c_str());
}
- if (this->Values[ctt_EXCLUDE]) {
- handler->SetOption("ExcludeRegularExpression", this->Values[ctt_EXCLUDE]);
+ if (!this->Exclude.empty()) {
+ handler->SetOption("ExcludeRegularExpression", this->Exclude.c_str());
}
- if (this->Values[ctt_INCLUDE]) {
- handler->SetOption("IncludeRegularExpression", this->Values[ctt_INCLUDE]);
+ if (!this->Include.empty()) {
+ handler->SetOption("IncludeRegularExpression", this->Include.c_str());
}
- if (this->Values[ctt_EXCLUDE_LABEL]) {
+ if (!this->ExcludeLabel.empty()) {
handler->SetOption("ExcludeLabelRegularExpression",
- this->Values[ctt_EXCLUDE_LABEL]);
+ this->ExcludeLabel.c_str());
}
- if (this->Values[ctt_INCLUDE_LABEL]) {
- handler->SetOption("LabelRegularExpression",
- this->Values[ctt_INCLUDE_LABEL]);
+ if (!this->IncludeLabel.empty()) {
+ handler->SetOption("LabelRegularExpression", this->IncludeLabel.c_str());
}
- if (this->Values[ctt_EXCLUDE_FIXTURE]) {
+ if (!this->ExcludeFixture.empty()) {
handler->SetOption("ExcludeFixtureRegularExpression",
- this->Values[ctt_EXCLUDE_FIXTURE]);
+ this->ExcludeFixture.c_str());
}
- if (this->Values[ctt_EXCLUDE_FIXTURE_SETUP]) {
+ if (!this->ExcludeFixtureSetup.empty()) {
handler->SetOption("ExcludeFixtureSetupRegularExpression",
- this->Values[ctt_EXCLUDE_FIXTURE_SETUP]);
+ this->ExcludeFixtureSetup.c_str());
}
- if (this->Values[ctt_EXCLUDE_FIXTURE_CLEANUP]) {
+ if (!this->ExcludeFixtureCleanup.empty()) {
handler->SetOption("ExcludeFixtureCleanupRegularExpression",
- this->Values[ctt_EXCLUDE_FIXTURE_CLEANUP]);
+ this->ExcludeFixtureCleanup.c_str());
+ }
+ if (!this->ParallelLevel.empty()) {
+ handler->SetOption("ParallelLevel", this->ParallelLevel.c_str());
}
- if (this->Values[ctt_PARALLEL_LEVEL]) {
- handler->SetOption("ParallelLevel", this->Values[ctt_PARALLEL_LEVEL]);
+ if (!this->ScheduleRandom.empty()) {
+ handler->SetOption("ScheduleRandom", this->ScheduleRandom.c_str());
}
- if (this->Values[ctt_SCHEDULE_RANDOM]) {
- handler->SetOption("ScheduleRandom", this->Values[ctt_SCHEDULE_RANDOM]);
+ if (!this->ResourceSpecFile.empty()) {
+ handler->SetOption("ResourceSpecFile", this->ResourceSpecFile.c_str());
}
- if (this->Values[ctt_STOP_TIME]) {
- this->CTest->SetStopTime(this->Values[ctt_STOP_TIME]);
+ if (!this->StopTime.empty()) {
+ this->CTest->SetStopTime(this->StopTime);
}
// Test load is determined by: TEST_LOAD argument,
@@ -106,29 +100,38 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
// command line argument... in that order.
unsigned long testLoad;
const char* ctestTestLoad = this->Makefile->GetDefinition("CTEST_TEST_LOAD");
- if (this->Values[ctt_TEST_LOAD] && *this->Values[ctt_TEST_LOAD]) {
- if (!cmSystemTools::StringToULong(this->Values[ctt_TEST_LOAD],
- &testLoad)) {
+ if (!this->TestLoad.empty()) {
+ if (!cmStrToULong(this->TestLoad.c_str(), &testLoad)) {
testLoad = 0;
- cmCTestLog(this->CTest, WARNING, "Invalid value for 'TEST_LOAD' : "
- << this->Values[ctt_TEST_LOAD] << std::endl);
+ cmCTestLog(this->CTest, WARNING,
+ "Invalid value for 'TEST_LOAD' : " << this->TestLoad
+ << std::endl);
}
} else if (ctestTestLoad && *ctestTestLoad) {
- if (!cmSystemTools::StringToULong(ctestTestLoad, &testLoad)) {
+ if (!cmStrToULong(ctestTestLoad, &testLoad)) {
testLoad = 0;
- cmCTestLog(this->CTest, WARNING, "Invalid value for 'CTEST_TEST_LOAD' : "
- << ctestTestLoad << std::endl);
+ cmCTestLog(this->CTest, WARNING,
+ "Invalid value for 'CTEST_TEST_LOAD' : " << ctestTestLoad
+ << std::endl);
}
} else {
testLoad = this->CTest->GetTestLoad();
}
handler->SetTestLoad(testLoad);
+ if (const char* labelsForSubprojects =
+ this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) {
+ this->CTest->SetCTestConfiguration("LabelsForSubprojects",
+ labelsForSubprojects, this->Quiet);
+ }
+
handler->SetQuiet(this->Quiet);
return handler;
}
cmCTestGenericHandler* cmCTestTestCommand::InitializeActualHandler()
{
- return this->CTest->GetInitializedHandler("test");
+ cmCTestTestHandler* handler = this->CTest->GetTestHandler();
+ handler->Initialize();
+ return handler;
}
diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h
index be7e7831f..4019694b2 100644
--- a/Source/CTest/cmCTestTestCommand.h
+++ b/Source/CTest/cmCTestTestCommand.h
@@ -3,14 +3,17 @@
#ifndef cmCTestTestCommand_h
#define cmCTestTestCommand_h
-#include "cmConfigure.h"
-
-#include "cmCTestHandlerCommand.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
+#include <utility>
+
+#include <cm/memory>
+
+#include "cmCTestHandlerCommand.h"
+#include "cmCommand.h"
class cmCTestGenericHandler;
-class cmCommand;
/** \class cmCTestTest
* \brief Run a ctest script
@@ -20,48 +23,42 @@ class cmCommand;
class cmCTestTestCommand : public cmCTestHandlerCommand
{
public:
- cmCTestTestCommand();
-
/**
* This is a virtual constructor for the command.
*/
- cmCommand* Clone() CM_OVERRIDE
+ std::unique_ptr<cmCommand> Clone() override
{
- cmCTestTestCommand* ni = new cmCTestTestCommand;
+ auto ni = cm::make_unique<cmCTestTestCommand>();
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
- return ni;
+ return std::unique_ptr<cmCommand>(std::move(ni));
}
/**
* The name of the command as specified in CMakeList.txt.
*/
- std::string GetName() const CM_OVERRIDE { return "ctest_test"; }
+ std::string GetName() const override { return "ctest_test"; }
protected:
+ void BindArguments() override;
virtual cmCTestGenericHandler* InitializeActualHandler();
- cmCTestGenericHandler* InitializeHandler() CM_OVERRIDE;
+ cmCTestGenericHandler* InitializeHandler() override;
- enum
- {
- ctt_BUILD = ct_LAST,
- ctt_RETURN_VALUE,
- ctt_START,
- ctt_END,
- ctt_STRIDE,
- ctt_EXCLUDE,
- ctt_INCLUDE,
- ctt_EXCLUDE_LABEL,
- ctt_INCLUDE_LABEL,
- ctt_EXCLUDE_FIXTURE,
- ctt_EXCLUDE_FIXTURE_SETUP,
- ctt_EXCLUDE_FIXTURE_CLEANUP,
- ctt_PARALLEL_LEVEL,
- ctt_SCHEDULE_RANDOM,
- ctt_STOP_TIME,
- ctt_TEST_LOAD,
- ctt_LAST
- };
+ std::string Start;
+ std::string End;
+ std::string Stride;
+ std::string Exclude;
+ std::string Include;
+ std::string ExcludeLabel;
+ std::string IncludeLabel;
+ std::string ExcludeFixture;
+ std::string ExcludeFixtureSetup;
+ std::string ExcludeFixtureCleanup;
+ std::string ParallelLevel;
+ std::string ScheduleRandom;
+ std::string StopTime;
+ std::string TestLoad;
+ std::string ResourceSpecFile;
};
#endif
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 674be6052..c8bbb0b13 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -2,81 +2,93 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestTestHandler.h"
-#include "cmsys/Base64.h"
-#include "cmsys/Directory.hxx"
-#include "cmsys/FStream.hxx"
-#include "cmsys/RegularExpression.hxx"
#include <algorithm>
+#include <chrono>
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
#include <functional>
#include <iomanip>
#include <iterator>
#include <set>
#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
+#include <utility>
+
+#include <cm/memory>
+
+#include "cmsys/FStream.hxx"
+#include <cmsys/Base64.h>
+#include <cmsys/Directory.hxx>
+#include <cmsys/RegularExpression.hxx>
+
+#include "cm_utf8.h"
#include "cmAlgorithms.h"
#include "cmCTest.h"
-#include "cmCTestBatchTestHandler.h"
#include "cmCTestMultiProcessHandler.h"
-#include "cmCommand.h"
+#include "cmCTestResourceGroupsLexerHelper.h"
+#include "cmDuration.h"
+#include "cmExecutionStatus.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
#include "cmXMLWriter.h"
-#include "cm_auto_ptr.hxx"
-#include "cm_utf8.h"
#include "cmake.h"
-class cmExecutionStatus;
+namespace {
-class cmCTestSubdirCommand : public cmCommand
+class cmCTestCommand
{
public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE
+ cmCTestCommand(cmCTestTestHandler* testHandler)
+ : TestHandler(testHandler)
{
- cmCTestSubdirCommand* c = new cmCTestSubdirCommand;
- c->TestHandler = this->TestHandler;
- return c;
}
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& /*unused*/) CM_OVERRIDE;
+ virtual ~cmCTestCommand() = default;
+
+ bool operator()(std::vector<cmListFileArgument> const& args,
+ cmExecutionStatus& status)
+ {
+ cmMakefile& mf = status.GetMakefile();
+ std::vector<std::string> expandedArguments;
+ if (!mf.ExpandArguments(args, expandedArguments)) {
+ // There was an error expanding arguments. It was already
+ // reported, so we can skip this command without error.
+ return true;
+ }
+ return this->InitialPass(expandedArguments, status);
+ }
+
+ virtual bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) = 0;
cmCTestTestHandler* TestHandler;
};
-bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& /*unused*/)
+bool cmCTestSubdirCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
- std::vector<std::string>::const_iterator it;
std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
- for (it = args.begin(); it != args.end(); ++it) {
+ for (std::string const& arg : args) {
std::string fname;
- if (cmSystemTools::FileIsFullPath(it->c_str())) {
- fname = *it;
+ if (cmSystemTools::FileIsFullPath(arg)) {
+ fname = arg;
} else {
- fname = cwd;
- fname += "/";
- fname += *it;
+ fname = cmStrCat(cwd, '/', arg);
}
if (!cmSystemTools::FileIsDirectory(fname)) {
@@ -86,6 +98,11 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args,
bool readit = false;
{
cmWorkingDirectory workdir(fname);
+ if (workdir.Failed()) {
+ status.SetError("Failed to change directory to " + fname + " : " +
+ std::strerror(workdir.GetLastResult()));
+ return false;
+ }
const char* testFilename;
if (cmSystemTools::FileExists("CTestTestfile.cmake")) {
// does the CTestTestfile.cmake exist ?
@@ -99,54 +116,28 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args,
}
fname += "/";
fname += testFilename;
- readit = this->Makefile->ReadDependentFile(fname.c_str());
+ readit = status.GetMakefile().ReadDependentFile(fname);
}
if (!readit) {
- std::string m = "Could not find include file: ";
- m += fname;
- this->SetError(m);
+ status.SetError(cmStrCat("Could not find include file: ", fname));
return false;
}
}
return true;
}
-class cmCTestAddSubdirectoryCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE
- {
- cmCTestAddSubdirectoryCommand* c = new cmCTestAddSubdirectoryCommand;
- c->TestHandler = this->TestHandler;
- return c;
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& /*unused*/) CM_OVERRIDE;
-
- cmCTestTestHandler* TestHandler;
-};
-
-bool cmCTestAddSubdirectoryCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus& /*unused*/)
+bool cmCTestAddSubdirectoryCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
- std::string fname = cmSystemTools::GetCurrentWorkingDirectory();
- fname += "/";
- fname += args[0];
+ std::string fname =
+ cmStrCat(cmSystemTools::GetCurrentWorkingDirectory(), '/', args[0]);
- if (!cmSystemTools::FileExists(fname.c_str())) {
+ if (!cmSystemTools::FileExists(fname)) {
// No subdirectory? So what...
return true;
}
@@ -165,71 +156,49 @@ bool cmCTestAddSubdirectoryCommand::InitialPass(
}
fname += "/";
fname += testFilename;
- readit = this->Makefile->ReadDependentFile(fname.c_str());
+ readit = status.GetMakefile().ReadDependentFile(fname);
}
if (!readit) {
- std::string m = "Could not find include file: ";
- m += fname;
- this->SetError(m);
+ status.SetError(cmStrCat("Could not find include file: ", fname));
return false;
}
return true;
}
-class cmCTestAddTestCommand : public cmCommand
+class cmCTestAddTestCommand : public cmCTestCommand
{
public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE
- {
- cmCTestAddTestCommand* c = new cmCTestAddTestCommand;
- c->TestHandler = this->TestHandler;
- return c;
- }
+ using cmCTestCommand::cmCTestCommand;
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
bool InitialPass(std::vector<std::string> const& /*args*/,
- cmExecutionStatus& /*unused*/) CM_OVERRIDE;
-
- cmCTestTestHandler* TestHandler;
+ cmExecutionStatus& /*unused*/) override;
};
bool cmCTestAddTestCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& /*unused*/)
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
return this->TestHandler->AddTest(args);
}
-class cmCTestSetTestsPropertiesCommand : public cmCommand
+class cmCTestSetTestsPropertiesCommand : public cmCTestCommand
{
public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE
- {
- cmCTestSetTestsPropertiesCommand* c = new cmCTestSetTestsPropertiesCommand;
- c->TestHandler = this->TestHandler;
- return c;
- }
+ using cmCTestCommand::cmCTestCommand;
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
bool InitialPass(std::vector<std::string> const& /*args*/,
- cmExecutionStatus& /*unused*/) CM_OVERRIDE;
-
- cmCTestTestHandler* TestHandler;
+ cmExecutionStatus& /*unused*/) override;
};
bool cmCTestSetTestsPropertiesCommand::InitialPass(
@@ -238,6 +207,25 @@ bool cmCTestSetTestsPropertiesCommand::InitialPass(
return this->TestHandler->SetTestsProperties(args);
}
+class cmCTestSetDirectoryPropertiesCommand : public cmCTestCommand
+{
+public:
+ using cmCTestCommand::cmCTestCommand;
+
+ /**
+ * This is called when the command is first encountered in
+ * the CMakeLists.txt file.
+ */
+ bool InitialPass(std::vector<std::string> const& /*unused*/,
+ cmExecutionStatus& /*unused*/) override;
+};
+
+bool cmCTestSetDirectoryPropertiesCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
+{
+ return this->TestHandler->SetDirectoryProperties(args);
+}
+
// get the next number in a string with numbers separated by ,
// pos is the start of the search and pos2 is the end of the search
// pos becomes pos2 after a call to GetNextNumber.
@@ -290,6 +278,8 @@ inline int GetNextRealNumber(std::string const& in, double& val,
return 0;
}
+} // namespace
+
cmCTestTestHandler::cmCTestTestHandler()
{
this->UseUnion = false;
@@ -299,13 +289,14 @@ cmCTestTestHandler::cmCTestTestHandler()
this->UseIncludeRegExpFlag = false;
this->UseExcludeRegExpFlag = false;
this->UseExcludeRegExpFirst = false;
+ this->UseResourceSpec = false;
this->CustomMaximumPassedTestOutputSize = 1 * 1024;
this->CustomMaximumFailedTestOutputSize = 300 * 1024;
this->MemCheck = false;
- this->LogFile = CM_NULLPTR;
+ this->LogFile = nullptr;
// regex to detect <DartMeasurement>...</DartMeasurement>
this->DartStuff.compile("(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)");
@@ -318,13 +309,13 @@ void cmCTestTestHandler::Initialize()
{
this->Superclass::Initialize();
- this->ElapsedTestingTime = -1;
+ this->ElapsedTestingTime = cmDuration();
this->TestResults.clear();
this->CustomTestsIgnore.clear();
- this->StartTest = "";
- this->EndTest = "";
+ this->StartTest.clear();
+ this->EndTest.clear();
this->CustomPreTest.clear();
this->CustomPostTest.clear();
@@ -340,13 +331,13 @@ void cmCTestTestHandler::Initialize()
this->UseExcludeRegExpFirst = false;
this->IncludeLabelRegularExpression = "";
this->ExcludeLabelRegularExpression = "";
- this->IncludeRegExp = "";
- this->ExcludeRegExp = "";
+ this->IncludeRegExp.clear();
+ this->ExcludeRegExp.clear();
this->ExcludeFixtureRegExp.clear();
this->ExcludeFixtureSetupRegExp.clear();
this->ExcludeFixtureCleanupRegExp.clear();
- TestsToRunString = "";
+ TestsToRunString.clear();
this->UseUnion = false;
this->TestList.clear();
}
@@ -387,14 +378,97 @@ int cmCTestTestHandler::PostProcessHandler()
return 1;
}
-// clearly it would be nice if this were broken up into a few smaller
-// functions and commented...
int cmCTestTestHandler::ProcessHandler()
{
+ if (!this->ProcessOptions()) {
+ return -1;
+ }
+
+ this->TestResults.clear();
+
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ (this->MemCheck ? "Memory check" : "Test")
+ << " project "
+ << cmSystemTools::GetCurrentWorkingDirectory()
+ << std::endl,
+ this->Quiet);
+ if (!this->PreProcessHandler()) {
+ return -1;
+ }
+
+ cmGeneratedFileStream mLogFile;
+ this->StartLogFile((this->MemCheck ? "DynamicAnalysis" : "Test"), mLogFile);
+ this->LogFile = &mLogFile;
+
+ std::vector<std::string> passed;
+ std::vector<std::string> failed;
+
+ // start the real time clock
+ auto clock_start = std::chrono::steady_clock::now();
+
+ this->ProcessDirectory(passed, failed);
+
+ auto clock_finish = std::chrono::steady_clock::now();
+
+ if (passed.size() + failed.size() == 0) {
+ if (!this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "No tests were found!!!" << std::endl);
+ }
+ } else {
+ if (this->HandlerVerbose && !passed.empty() &&
+ (this->UseIncludeRegExpFlag || this->UseExcludeRegExpFlag)) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ std::endl
+ << "The following tests passed:" << std::endl,
+ this->Quiet);
+ for (std::string const& j : passed) {
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "\t" << j << std::endl, this->Quiet);
+ }
+ }
+
+ SetOfTests resultsSet(this->TestResults.begin(), this->TestResults.end());
+ std::vector<cmCTestTestHandler::cmCTestTestResult> disabledTests;
+
+ for (cmCTestTestResult const& ft : resultsSet) {
+ if (cmHasLiteralPrefix(ft.CompletionStatus, "SKIP_") ||
+ ft.CompletionStatus == "Disabled") {
+ disabledTests.push_back(ft);
+ }
+ }
+
+ cmDuration durationInSecs = clock_finish - clock_start;
+ this->LogTestSummary(passed, failed, durationInSecs);
+
+ this->LogDisabledTests(disabledTests);
+
+ this->LogFailedTests(failed, resultsSet);
+ }
+
+ if (!this->GenerateXML()) {
+ return 1;
+ }
+
+ if (!this->PostProcessHandler()) {
+ this->LogFile = nullptr;
+ return -1;
+ }
+
+ if (!failed.empty()) {
+ this->LogFile = nullptr;
+ return -1;
+ }
+ this->LogFile = nullptr;
+ return 0;
+}
+
+bool cmCTestTestHandler::ProcessOptions()
+{
// Update internal data structure from generic one
this->SetTestsToRunInformation(this->GetOption("TestsToRunInformation"));
- this->SetUseUnion(cmSystemTools::IsOn(this->GetOption("UseUnion")));
- if (cmSystemTools::IsOn(this->GetOption("ScheduleRandom"))) {
+ this->SetUseUnion(cmIsOn(this->GetOption("UseUnion")));
+ if (cmIsOn(this->GetOption("ScheduleRandom"))) {
this->CTest->SetScheduleType("Random");
}
if (this->GetOption("ParallelLevel")) {
@@ -434,228 +508,225 @@ int cmCTestTestHandler::ProcessHandler()
if (val) {
this->ExcludeFixtureCleanupRegExp = val;
}
- this->SetRerunFailed(cmSystemTools::IsOn(this->GetOption("RerunFailed")));
-
- this->TestResults.clear();
-
- cmCTestOptionalLog(
- this->CTest, HANDLER_OUTPUT, (this->MemCheck ? "Memory check" : "Test")
- << " project " << cmSystemTools::GetCurrentWorkingDirectory()
- << std::endl,
- this->Quiet);
- if (!this->PreProcessHandler()) {
- return -1;
- }
-
- cmGeneratedFileStream mLogFile;
- this->StartLogFile((this->MemCheck ? "DynamicAnalysis" : "Test"), mLogFile);
- this->LogFile = &mLogFile;
-
- std::vector<std::string> passed;
- std::vector<std::string> failed;
- int total;
-
- // start the real time clock
- double clock_start, clock_finish;
- clock_start = cmSystemTools::GetTime();
+ this->SetRerunFailed(cmIsOn(this->GetOption("RerunFailed")));
- this->ProcessDirectory(passed, failed);
-
- clock_finish = cmSystemTools::GetTime();
-
- total = int(passed.size()) + int(failed.size());
-
- if (total == 0) {
- if (!this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels()) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "No tests were found!!!"
+ val = this->GetOption("ResourceSpecFile");
+ if (val) {
+ this->UseResourceSpec = true;
+ auto result = this->ResourceSpec.ReadFromJSONFile(val);
+ if (result != cmCTestResourceSpec::ReadFileResult::READ_OK) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Could not read/parse resource spec file "
+ << val << ": "
+ << cmCTestResourceSpec::ResultToString(result)
<< std::endl);
+ return false;
}
- } else {
- if (this->HandlerVerbose && !passed.empty() &&
- (this->UseIncludeRegExpFlag || this->UseExcludeRegExpFlag)) {
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl
- << "The following tests passed:" << std::endl,
- this->Quiet);
- for (std::vector<std::string>::iterator j = passed.begin();
- j != passed.end(); ++j) {
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "\t" << *j << std::endl, this->Quiet);
- }
- }
+ }
- typedef std::set<cmCTestTestHandler::cmCTestTestResult,
- cmCTestTestResultLess>
- SetOfTests;
- SetOfTests resultsSet(this->TestResults.begin(), this->TestResults.end());
- std::vector<cmCTestTestHandler::cmCTestTestResult> disabledTests;
+ return true;
+}
- for (SetOfTests::iterator ftit = resultsSet.begin();
- ftit != resultsSet.end(); ++ftit) {
- if (cmHasLiteralPrefix(ftit->CompletionStatus, "SKIP_RETURN_CODE=") ||
- ftit->CompletionStatus == "Disabled") {
- disabledTests.push_back(*ftit);
- }
- }
+void cmCTestTestHandler::LogTestSummary(const std::vector<std::string>& passed,
+ const std::vector<std::string>& failed,
+ const cmDuration& durationInSecs)
+{
+ std::size_t total = passed.size() + failed.size();
- float percent = float(passed.size()) * 100.0f / float(total);
- if (!failed.empty() && percent > 99) {
- percent = 99;
- }
+ float percent = float(passed.size()) * 100.0f / float(total);
+ if (!failed.empty() && percent > 99) {
+ percent = 99;
+ }
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl
- << static_cast<int>(percent + .5f) << "% tests passed, "
- << failed.size() << " tests failed out of " << total
- << std::endl);
- if (this->CTest->GetLabelSummary()) {
- this->PrintLabelSummary();
- }
- char realBuf[1024];
- sprintf(realBuf, "%6.2f sec", (double)(clock_finish - clock_start));
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- "\nTotal Test time (real) = " << realBuf << "\n",
- this->Quiet);
+ std::string passColorCode;
+ std::string failedColorCode;
+ if (failed.empty()) {
+ passColorCode = this->CTest->GetColorCode(cmCTest::Color::GREEN);
+ } else {
+ failedColorCode = this->CTest->GetColorCode(cmCTest::Color::RED);
+ }
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::endl
+ << passColorCode << std::lround(percent) << "% tests passed"
+ << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
+ << ", " << failedColorCode << failed.size() << " tests failed"
+ << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
+ << " out of " << total << std::endl);
+ if ((!this->CTest->GetLabelsForSubprojects().empty() &&
+ this->CTest->GetSubprojectSummary())) {
+ this->PrintLabelOrSubprojectSummary(true);
+ }
+ if (this->CTest->GetLabelSummary()) {
+ this->PrintLabelOrSubprojectSummary(false);
+ }
+ char realBuf[1024];
+ sprintf(realBuf, "%6.2f sec", durationInSecs.count());
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ "\nTotal Test time (real) = " << realBuf << "\n",
+ this->Quiet);
+}
- if (!disabledTests.empty()) {
- cmGeneratedFileStream ofs;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl
- << "The following tests did not run:" << std::endl);
- this->StartLogFile("TestsDisabled", ofs);
-
- const char* disabled_reason;
- for (std::vector<cmCTestTestHandler::cmCTestTestResult>::iterator dtit =
- disabledTests.begin();
- dtit != disabledTests.end(); ++dtit) {
- ofs << dtit->TestCount << ":" << dtit->Name << std::endl;
- if (dtit->CompletionStatus == "Disabled") {
- disabled_reason = "Disabled";
- } else {
- disabled_reason = "Skipped";
- }
- cmCTestLog(this->CTest, HANDLER_OUTPUT, "\t"
- << std::setw(3) << dtit->TestCount << " - " << dtit->Name
- << " (" << disabled_reason << ")" << std::endl);
+void cmCTestTestHandler::LogDisabledTests(
+ const std::vector<cmCTestTestResult>& disabledTests)
+{
+ if (!disabledTests.empty()) {
+ cmGeneratedFileStream ofs;
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::endl
+ << "The following tests did not run:" << std::endl);
+ this->StartLogFile("TestsDisabled", ofs);
+
+ const char* disabled_reason;
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ this->CTest->GetColorCode(cmCTest::Color::BLUE));
+ for (cmCTestTestResult const& dt : disabledTests) {
+ ofs << dt.TestCount << ":" << dt.Name << std::endl;
+ if (dt.CompletionStatus == "Disabled") {
+ disabled_reason = "Disabled";
+ } else {
+ disabled_reason = "Skipped";
}
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ "\t" << std::setw(3) << dt.TestCount << " - " << dt.Name
+ << " (" << disabled_reason << ")" << std::endl);
}
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR));
+ }
+}
- if (!failed.empty()) {
- cmGeneratedFileStream ofs;
- cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl
- << "The following tests FAILED:" << std::endl);
- this->StartLogFile("TestsFailed", ofs);
-
- for (SetOfTests::iterator ftit = resultsSet.begin();
- ftit != resultsSet.end(); ++ftit) {
- if (ftit->Status != cmCTestTestHandler::COMPLETED &&
- !cmHasLiteralPrefix(ftit->CompletionStatus, "SKIP_RETURN_CODE=") &&
- ftit->CompletionStatus != "Disabled") {
- ofs << ftit->TestCount << ":" << ftit->Name << std::endl;
- cmCTestLog(
- this->CTest, HANDLER_OUTPUT, "\t"
- << std::setw(3) << ftit->TestCount << " - " << ftit->Name << " ("
- << this->GetTestStatus(ftit->Status) << ")" << std::endl);
+void cmCTestTestHandler::LogFailedTests(const std::vector<std::string>& failed,
+ const SetOfTests& resultsSet)
+{
+ if (!failed.empty()) {
+ cmGeneratedFileStream ofs;
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::endl
+ << "The following tests FAILED:" << std::endl);
+ this->StartLogFile("TestsFailed", ofs);
+
+ for (cmCTestTestResult const& ft : resultsSet) {
+ if (ft.Status != cmCTestTestHandler::COMPLETED &&
+ !cmHasLiteralPrefix(ft.CompletionStatus, "SKIP_") &&
+ ft.CompletionStatus != "Disabled") {
+ ofs << ft.TestCount << ":" << ft.Name << std::endl;
+ auto testColor = cmCTest::Color::RED;
+ if (this->GetTestStatus(ft) == "Not Run") {
+ testColor = cmCTest::Color::YELLOW;
}
+ cmCTestLog(
+ this->CTest, HANDLER_OUTPUT,
+ "\t" << this->CTest->GetColorCode(testColor) << std::setw(3)
+ << ft.TestCount << " - " << ft.Name << " ("
+ << this->GetTestStatus(ft) << ")"
+ << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)
+ << std::endl);
}
}
}
+}
+bool cmCTestTestHandler::GenerateXML()
+{
if (this->CTest->GetProduceXML()) {
cmGeneratedFileStream xmlfile;
if (!this->StartResultingXML(
(this->MemCheck ? cmCTest::PartMemCheck : cmCTest::PartTest),
(this->MemCheck ? "DynamicAnalysis" : "Test"), xmlfile)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create "
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot create "
<< (this->MemCheck ? "memory check" : "testing")
<< " XML file" << std::endl);
- this->LogFile = CM_NULLPTR;
- return 1;
+ this->LogFile = nullptr;
+ return false;
}
cmXMLWriter xml(xmlfile);
this->GenerateDartOutput(xml);
}
- if (!this->PostProcessHandler()) {
- this->LogFile = CM_NULLPTR;
- return -1;
- }
-
- if (!failed.empty()) {
- this->LogFile = CM_NULLPTR;
- return -1;
- }
- this->LogFile = CM_NULLPTR;
- return 0;
+ return true;
}
-void cmCTestTestHandler::PrintLabelSummary()
+void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject)
{
- cmCTestTestHandler::ListOfTests::iterator it = this->TestList.begin();
+ // collect subproject labels
+ std::vector<std::string> subprojects =
+ this->CTest->GetLabelsForSubprojects();
std::map<std::string, double> labelTimes;
std::map<std::string, int> labelCounts;
std::set<std::string> labels;
- // initialize maps
std::string::size_type maxlen = 0;
- for (; it != this->TestList.end(); ++it) {
- cmCTestTestProperties& p = *it;
- if (!p.Labels.empty()) {
- for (std::vector<std::string>::iterator l = p.Labels.begin();
- l != p.Labels.end(); ++l) {
- if ((*l).size() > maxlen) {
- maxlen = (*l).size();
+ // initialize maps
+ for (cmCTestTestProperties& p : this->TestList) {
+ for (std::string const& l : p.Labels) {
+ // first check to see if the current label is a subproject label
+ bool isSubprojectLabel = false;
+ auto subproject = std::find(subprojects.begin(), subprojects.end(), l);
+ if (subproject != subprojects.end()) {
+ isSubprojectLabel = true;
+ }
+ // if we are doing sub projects and this label is one, then use it
+ // if we are not doing sub projects and the label is not one use it
+ if (doSubProject == isSubprojectLabel) {
+ if (l.size() > maxlen) {
+ maxlen = l.size();
}
- labels.insert(*l);
- labelTimes[*l] = 0;
- labelCounts[*l] = 0;
+ labels.insert(l);
+ labelTimes[l] = 0;
+ labelCounts[l] = 0;
}
}
}
- cmCTestTestHandler::TestResultsVector::iterator ri =
- this->TestResults.begin();
// fill maps
- for (; ri != this->TestResults.end(); ++ri) {
- cmCTestTestResult& result = *ri;
+ for (cmCTestTestResult& result : this->TestResults) {
cmCTestTestProperties& p = *result.Properties;
- if (!p.Labels.empty()) {
- for (std::vector<std::string>::iterator l = p.Labels.begin();
- l != p.Labels.end(); ++l) {
- labelTimes[*l] += result.ExecutionTime;
- ++labelCounts[*l];
+ for (std::string const& l : p.Labels) {
+ // only use labels found in labels
+ if (cmContains(labels, l)) {
+ labelTimes[l] +=
+ result.ExecutionTime.count() * result.Properties->Processors;
+ ++labelCounts[l];
}
}
}
+ // if no labels are found return and print nothing
+ if (labels.empty()) {
+ return;
+ }
// now print times
- if (!labels.empty()) {
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\nLabel Time Summary:",
- this->Quiet);
+ if (doSubProject) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ "\nSubproject Time Summary:", this->Quiet);
+ } else {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ "\nLabel Time Summary:", this->Quiet);
}
- for (std::set<std::string>::const_iterator i = labels.begin();
- i != labels.end(); ++i) {
- std::string label = *i;
+ for (std::string const& i : labels) {
+ std::string label = i;
label.resize(maxlen + 3, ' ');
char buf[1024];
- sprintf(buf, "%6.2f sec", labelTimes[*i]);
+ sprintf(buf, "%6.2f sec*proc", labelTimes[i]);
std::ostringstream labelCountStr;
- labelCountStr << "(" << labelCounts[*i] << " test";
- if (labelCounts[*i] > 1) {
+ labelCountStr << "(" << labelCounts[i] << " test";
+ if (labelCounts[i] > 1) {
labelCountStr << "s";
}
labelCountStr << ")";
-
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n"
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ "\n"
<< label << " = " << buf << " "
<< labelCountStr.str(),
this->Quiet);
if (this->LogFile) {
- *this->LogFile << "\n" << *i << " = " << buf << "\n";
+ *this->LogFile << "\n" << i << " = " << buf << "\n";
}
}
- if (!labels.empty()) {
- if (this->LogFile) {
- *this->LogFile << "\n";
- }
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n", this->Quiet);
+ if (this->LogFile) {
+ *this->LogFile << "\n";
}
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\n", this->Quiet);
}
void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it)
@@ -673,9 +744,8 @@ void cmCTestTestHandler::CheckLabelFilterInclude(cmCTestTestProperties& it)
// check to see if the label regular expression matches
bool found = false; // assume it does not match
// loop over all labels and look for match
- for (std::vector<std::string>::iterator l = it.Labels.begin();
- l != it.Labels.end(); ++l) {
- if (this->IncludeLabelRegularExpression.find(*l)) {
+ for (std::string const& l : it.Labels) {
+ if (this->IncludeLabelRegularExpression.find(l)) {
found = true;
}
}
@@ -699,9 +769,8 @@ void cmCTestTestHandler::CheckLabelFilterExclude(cmCTestTestProperties& it)
// check to see if the label regular expression matches
bool found = false; // assume it does not match
// loop over all labels and look for match
- for (std::vector<std::string>::iterator l = it.Labels.begin();
- l != it.Labels.end(); ++l) {
- if (this->ExcludeLabelRegularExpression.find(*l)) {
+ for (std::string const& l : it.Labels) {
+ if (this->ExcludeLabelRegularExpression.find(l)) {
found = true;
}
}
@@ -730,16 +799,15 @@ void cmCTestTestHandler::ComputeTestList()
cmCTestTestHandler::ListOfTests::size_type tmsize = this->TestList.size();
// how many tests are in based on RegExp?
int inREcnt = 0;
- cmCTestTestHandler::ListOfTests::iterator it;
- for (it = this->TestList.begin(); it != this->TestList.end(); it++) {
- this->CheckLabelFilter(*it);
- if (it->IsInBasedOnREOptions) {
+ for (cmCTestTestProperties& tp : this->TestList) {
+ this->CheckLabelFilter(tp);
+ if (tp.IsInBasedOnREOptions) {
inREcnt++;
}
}
// expand the test list based on the union flag
if (this->UseUnion) {
- this->ExpandTestsToRunInformation((int)tmsize);
+ this->ExpandTestsToRunInformation(static_cast<int>(tmsize));
} else {
this->ExpandTestsToRunInformation(inREcnt);
}
@@ -748,31 +816,28 @@ void cmCTestTestHandler::ComputeTestList()
inREcnt = 0;
std::string last_directory;
ListOfTests finalList;
- for (it = this->TestList.begin(); it != this->TestList.end(); it++) {
+ for (cmCTestTestProperties& tp : this->TestList) {
cnt++;
- if (it->IsInBasedOnREOptions) {
+ if (tp.IsInBasedOnREOptions) {
inREcnt++;
}
if (this->UseUnion) {
// if it is not in the list and not in the regexp then skip
- if ((!this->TestsToRun.empty() &&
- std::find(this->TestsToRun.begin(), this->TestsToRun.end(), cnt) ==
- this->TestsToRun.end()) &&
- !it->IsInBasedOnREOptions) {
+ if ((!this->TestsToRun.empty() && !cmContains(this->TestsToRun, cnt)) &&
+ !tp.IsInBasedOnREOptions) {
continue;
}
} else {
// is this test in the list of tests to run? If not then skip it
if ((!this->TestsToRun.empty() &&
- std::find(this->TestsToRun.begin(), this->TestsToRun.end(),
- inREcnt) == this->TestsToRun.end()) ||
- !it->IsInBasedOnREOptions) {
+ !cmContains(this->TestsToRun, inREcnt)) ||
+ !tp.IsInBasedOnREOptions) {
continue;
}
}
- it->Index = cnt; // save the index into the test list for this test
- finalList.push_back(*it);
+ tp.Index = cnt; // save the index into the test list for this test
+ finalList.push_back(tp);
}
UpdateForFixtures(finalList);
@@ -789,21 +854,18 @@ void cmCTestTestHandler::ComputeTestListForRerunFailed()
{
this->ExpandTestsToRunInformationForRerunFailed();
- cmCTestTestHandler::ListOfTests::iterator it;
ListOfTests finalList;
int cnt = 0;
- for (it = this->TestList.begin(); it != this->TestList.end(); it++) {
+ for (cmCTestTestProperties& tp : this->TestList) {
cnt++;
// if this test is not in our list of tests to run, then skip it.
- if ((!this->TestsToRun.empty() &&
- std::find(this->TestsToRun.begin(), this->TestsToRun.end(), cnt) ==
- this->TestsToRun.end())) {
+ if (!this->TestsToRun.empty() && !cmContains(this->TestsToRun, cnt)) {
continue;
}
- it->Index = cnt;
- finalList.push_back(*it);
+ tp.Index = cnt;
+ finalList.push_back(tp);
}
UpdateForFixtures(finalList);
@@ -847,34 +909,27 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
// Prepare some maps to help us find setup and cleanup tests for
// any given fixture
- typedef ListOfTests::const_iterator TestIterator;
- typedef std::multimap<std::string, TestIterator> FixtureDependencies;
- typedef FixtureDependencies::const_iterator FixtureDepsIterator;
+ using TestIterator = ListOfTests::const_iterator;
+ using FixtureDependencies = std::multimap<std::string, TestIterator>;
+ using FixtureDepsIterator = FixtureDependencies::const_iterator;
FixtureDependencies fixtureSetups;
FixtureDependencies fixtureCleanups;
- for (ListOfTests::const_iterator it = this->TestList.begin();
- it != this->TestList.end(); ++it) {
+ for (auto it = this->TestList.begin(); it != this->TestList.end(); ++it) {
const cmCTestTestProperties& p = *it;
- const std::set<std::string>& setups = p.FixturesSetup;
- for (std::set<std::string>::const_iterator depsIt = setups.begin();
- depsIt != setups.end(); ++depsIt) {
- fixtureSetups.insert(std::make_pair(*depsIt, it));
+ for (std::string const& deps : p.FixturesSetup) {
+ fixtureSetups.insert(std::make_pair(deps, it));
}
- const std::set<std::string>& cleanups = p.FixturesCleanup;
- for (std::set<std::string>::const_iterator depsIt = cleanups.begin();
- depsIt != cleanups.end(); ++depsIt) {
- fixtureCleanups.insert(std::make_pair(*depsIt, it));
+ for (std::string const& deps : p.FixturesCleanup) {
+ fixtureCleanups.insert(std::make_pair(deps, it));
}
}
// Prepare fast lookup of tests already included in our list of tests
std::set<std::string> addedTests;
- for (ListOfTests::const_iterator it = tests.begin(); it != tests.end();
- ++it) {
- const cmCTestTestProperties& p = *it;
+ for (cmCTestTestProperties const& p : tests) {
addedTests.insert(p.Name);
}
@@ -882,8 +937,8 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
// tests array for tests which require that fixture and tests which are
// setups for that fixture. They are needed at the end to populate
// dependencies of the cleanup tests in our final list of tests.
- std::map<std::string, std::vector<size_t> > fixtureRequirements;
- std::map<std::string, std::vector<size_t> > setupFixturesAdded;
+ std::map<std::string, std::vector<size_t>> fixtureRequirements;
+ std::map<std::string, std::vector<size_t>> setupFixturesAdded;
// Use integer index for iteration because we append to
// the tests vector as we go
@@ -908,10 +963,7 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
// Must copy the set of fixtures required because we may invalidate
// the tests array by appending to it
std::set<std::string> fixtures = tests[i].FixturesRequired;
- for (std::set<std::string>::const_iterator fixturesIt = fixtures.begin();
- fixturesIt != fixtures.end(); ++fixturesIt) {
-
- const std::string& requiredFixtureName = *fixturesIt;
+ for (std::string const& requiredFixtureName : fixtures) {
if (requiredFixtureName.empty()) {
continue;
}
@@ -924,12 +976,10 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
// cleanup tests depend on this test case later.
std::pair<FixtureDepsIterator, FixtureDepsIterator> setupRange =
fixtureSetups.equal_range(requiredFixtureName);
- for (FixtureDepsIterator sIt = setupRange.first;
- sIt != setupRange.second; ++sIt) {
+ for (auto sIt = setupRange.first; sIt != setupRange.second; ++sIt) {
const std::string& setupTestName = sIt->second->Name;
tests[i].RequireSuccessDepends.insert(setupTestName);
- if (std::find(tests[i].Depends.begin(), tests[i].Depends.end(),
- setupTestName) == tests[i].Depends.end()) {
+ if (!cmContains(tests[i].Depends, setupTestName)) {
tests[i].Depends.push_back(setupTestName);
}
}
@@ -949,8 +999,7 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
!excludeSetupRegex.find(requiredFixtureName)) {
std::pair<FixtureDepsIterator, FixtureDepsIterator> fixtureRange =
fixtureSetups.equal_range(requiredFixtureName);
- for (FixtureDepsIterator it = fixtureRange.first;
- it != fixtureRange.second; ++it) {
+ for (auto it = fixtureRange.first; it != fixtureRange.second; ++it) {
ListOfTests::const_iterator lotIt = it->second;
const cmCTestTestProperties& p = *lotIt;
@@ -981,8 +1030,7 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
!excludeCleanupRegex.find(requiredFixtureName)) {
std::pair<FixtureDepsIterator, FixtureDepsIterator> fixtureRange =
fixtureCleanups.equal_range(requiredFixtureName);
- for (FixtureDepsIterator it = fixtureRange.first;
- it != fixtureRange.second; ++it) {
+ for (auto it = fixtureRange.first; it != fixtureRange.second; ++it) {
ListOfTests::const_iterator lotIt = it->second;
const cmCTestTestProperties& p = *lotIt;
@@ -1010,11 +1058,7 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
}
// 2. Record all setup fixtures included in the final list of tests
- for (std::set<std::string>::const_iterator fixturesIt =
- tests[i].FixturesSetup.begin();
- fixturesIt != tests[i].FixturesSetup.end(); ++fixturesIt) {
-
- const std::string& setupFixtureName = *fixturesIt;
+ for (std::string const& setupFixtureName : tests[i].FixturesSetup) {
if (setupFixtureName.empty()) {
continue;
}
@@ -1028,25 +1072,18 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
// setup tests for that fixture. The latter is required to handle the
// pathological case where setup and cleanup tests are in the test set
// but no other test has that fixture as a requirement.
- for (ListOfTests::iterator tIt = tests.begin(); tIt != tests.end(); ++tIt) {
- cmCTestTestProperties& p = *tIt;
+ for (cmCTestTestProperties& p : tests) {
const std::set<std::string>& cleanups = p.FixturesCleanup;
- for (std::set<std::string>::const_iterator fIt = cleanups.begin();
- fIt != cleanups.end(); ++fIt) {
- const std::string& fixture = *fIt;
-
+ for (std::string const& fixture : cleanups) {
// This cleanup test could be part of the original test list that was
// passed in. It is then possible that no other test requires the
// fIt fixture, so we have to check for this.
- std::map<std::string, std::vector<size_t> >::const_iterator cIt =
- fixtureRequirements.find(fixture);
+ auto cIt = fixtureRequirements.find(fixture);
if (cIt != fixtureRequirements.end()) {
const std::vector<size_t>& indices = cIt->second;
- for (std::vector<size_t>::const_iterator indexIt = indices.begin();
- indexIt != indices.end(); ++indexIt) {
- const std::string& reqTestName = tests[*indexIt].Name;
- if (std::find(p.Depends.begin(), p.Depends.end(), reqTestName) ==
- p.Depends.end()) {
+ for (size_t index : indices) {
+ const std::string& reqTestName = tests[index].Name;
+ if (!cmContains(p.Depends, reqTestName)) {
p.Depends.push_back(reqTestName);
}
}
@@ -1057,11 +1094,9 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
cIt = setupFixturesAdded.find(fixture);
if (cIt != setupFixturesAdded.end()) {
const std::vector<size_t>& indices = cIt->second;
- for (std::vector<size_t>::const_iterator indexIt = indices.begin();
- indexIt != indices.end(); ++indexIt) {
- const std::string& setupTestName = tests[*indexIt].Name;
- if (std::find(p.Depends.begin(), p.Depends.end(), setupTestName) ==
- p.Depends.end()) {
+ for (size_t index : indices) {
+ const std::string& setupTestName = tests[index].Name;
+ if (!cmContains(p.Depends, setupTestName)) {
p.Depends.push_back(setupTestName);
}
}
@@ -1069,18 +1104,17 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const
}
}
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Added "
- << fixtureTestsAdded
- << " tests to meet fixture requirements" << std::endl,
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Added " << fixtureTestsAdded
+ << " tests to meet fixture requirements"
+ << std::endl,
this->Quiet);
}
void cmCTestTestHandler::UpdateMaxTestNameWidth()
{
std::string::size_type max = this->CTest->GetMaxTestNameWidth();
- for (cmCTestTestHandler::ListOfTests::iterator it = this->TestList.begin();
- it != this->TestList.end(); it++) {
- cmCTestTestProperties& p = *it;
+ for (cmCTestTestProperties& p : this->TestList) {
if (max < p.Name.size()) {
max = p.Name.size();
}
@@ -1101,8 +1135,9 @@ bool cmCTestTestHandler::GetValue(const char* tag, int& value,
fin >> value;
ret = cmSystemTools::GetLineFromStream(fin, line); // read blank line
} else {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: "
- << tag << " found [" << line << "]" << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "parse error: missing tag: " << tag << " found [" << line << "]"
+ << std::endl);
ret = false;
}
return ret;
@@ -1118,8 +1153,9 @@ bool cmCTestTestHandler::GetValue(const char* tag, double& value,
fin >> value;
ret = cmSystemTools::GetLineFromStream(fin, line); // read blank line
} else {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: "
- << tag << " found [" << line << "]" << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "parse error: missing tag: " << tag << " found [" << line << "]"
+ << std::endl);
ret = false;
}
return ret;
@@ -1144,8 +1180,9 @@ bool cmCTestTestHandler::GetValue(const char* tag, bool& value,
#endif
ret = cmSystemTools::GetLineFromStream(fin, line); // read blank line
} else {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: "
- << tag << " found [" << line << "]" << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "parse error: missing tag: " << tag << " found [" << line << "]"
+ << std::endl);
ret = false;
}
return ret;
@@ -1161,8 +1198,9 @@ bool cmCTestTestHandler::GetValue(const char* tag, size_t& value,
fin >> value;
ret = cmSystemTools::GetLineFromStream(fin, line); // read blank line
} else {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: "
- << tag << " found [" << line << "]" << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "parse error: missing tag: " << tag << " found [" << line << "]"
+ << std::endl);
ret = false;
}
return ret;
@@ -1177,8 +1215,9 @@ bool cmCTestTestHandler::GetValue(const char* tag, std::string& value,
if (line == tag) {
ret = cmSystemTools::GetLineFromStream(fin, value);
} else {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "parse error: missing tag: "
- << tag << " found [" << line << "]" << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "parse error: missing tag: " << tag << " found [" << line << "]"
+ << std::endl);
ret = false;
}
return ret;
@@ -1189,12 +1228,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);
@@ -1204,6 +1241,9 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed,
} else {
parallel->SetTestLoad(this->CTest->GetTestLoad());
}
+ if (this->UseResourceSpec) {
+ parallel->InitResourceAllocator(this->ResourceSpec);
+ }
*this->LogFile
<< "Start testing: " << this->CTest->CurrentTime() << std::endl
@@ -1215,41 +1255,39 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed,
bool randomSchedule = this->CTest->GetScheduleType() == "Random";
if (randomSchedule) {
- srand((unsigned)time(CM_NULLPTR));
+ srand(static_cast<unsigned>(time(nullptr)));
}
- for (ListOfTests::iterator it = this->TestList.begin();
- it != this->TestList.end(); ++it) {
- cmCTestTestProperties& p = *it;
+ for (cmCTestTestProperties& p : this->TestList) {
cmCTestMultiProcessHandler::TestSet depends;
if (randomSchedule) {
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();
}
if (!p.Depends.empty()) {
- for (std::vector<std::string>::iterator i = p.Depends.begin();
- i != p.Depends.end(); ++i) {
- for (ListOfTests::iterator it2 = this->TestList.begin();
- it2 != this->TestList.end(); ++it2) {
- if (it2->Name == *i) {
- depends.insert(it2->Index);
+ for (std::string const& i : p.Depends) {
+ for (cmCTestTestProperties const& it2 : this->TestList) {
+ if (it2.Name == i) {
+ depends.insert(it2.Index);
break; // break out of test loop as name can only match 1
}
}
}
}
- tests[it->Index] = depends;
- properties[it->Index] = &*it;
+ tests[p.Index] = depends;
+ properties[p.Index] = &p;
}
parallel->SetTests(tests, properties);
parallel->SetPassFailVectors(&passed, &failed);
this->TestResults.clear();
parallel->SetTestResults(&this->TestResults);
+ parallel->CheckResourcesAvailable();
if (this->CTest->ShouldPrintLabels()) {
parallel->PrintLabels();
@@ -1260,8 +1298,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;
}
@@ -1277,83 +1316,85 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
}
this->CTest->StartXML(xml, this->AppendXML);
+ this->CTest->GenerateSubprojectsOutput(xml);
xml.StartElement("Testing");
xml.Element("StartDateTime", this->StartTest);
xml.Element("StartTestTime", this->StartTestTime);
xml.StartElement("TestList");
- cmCTestTestHandler::TestResultsVector::size_type cc;
- for (cc = 0; cc < this->TestResults.size(); cc++) {
- cmCTestTestResult* result = &this->TestResults[cc];
- std::string testPath = result->Path + "/" + result->Name;
+ for (cmCTestTestResult const& result : this->TestResults) {
+ std::string testPath = result.Path + "/" + result.Name;
xml.Element("Test", this->CTest->GetShortPathToFile(testPath.c_str()));
}
xml.EndElement(); // TestList
- for (cc = 0; cc < this->TestResults.size(); cc++) {
- cmCTestTestResult* result = &this->TestResults[cc];
+ for (cmCTestTestResult& result : this->TestResults) {
this->WriteTestResultHeader(xml, result);
xml.StartElement("Results");
- if (result->Status != cmCTestTestHandler::NOT_RUN) {
- if (result->Status != cmCTestTestHandler::COMPLETED ||
- result->ReturnValue) {
+ if (result.Status != cmCTestTestHandler::NOT_RUN) {
+ if (result.Status != cmCTestTestHandler::COMPLETED ||
+ result.ReturnValue) {
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "text/string");
xml.Attribute("name", "Exit Code");
- xml.Element("Value", this->GetTestStatus(result->Status));
+ xml.Element("Value", this->GetTestStatus(result));
xml.EndElement(); // NamedMeasurement
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "text/string");
xml.Attribute("name", "Exit Value");
- xml.Element("Value", result->ReturnValue);
+ xml.Element("Value", result.ReturnValue);
xml.EndElement(); // NamedMeasurement
}
- this->GenerateRegressionImages(xml, result->DartString);
+ this->GenerateRegressionImages(xml, result.DartString);
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()) {
+ if (!result.Reason.empty()) {
const char* reasonType = "Pass Reason";
- if (result->Status != cmCTestTestHandler::COMPLETED) {
+ if (result.Status != cmCTestTestHandler::COMPLETED) {
reasonType = "Fail Reason";
}
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "text/string");
xml.Attribute("name", reasonType);
- xml.Element("Value", result->Reason);
+ xml.Element("Value", result.Reason);
xml.EndElement(); // NamedMeasurement
}
}
xml.StartElement("NamedMeasurement");
+ xml.Attribute("type", "numeric/double");
+ xml.Attribute("name", "Processors");
+ xml.Element("Value", result.Properties->Processors);
+ xml.EndElement(); // NamedMeasurement
+
+ xml.StartElement("NamedMeasurement");
xml.Attribute("type", "text/string");
xml.Attribute("name", "Completion Status");
- xml.Element("Value", result->CompletionStatus);
+ xml.Element("Value", result.CompletionStatus);
xml.EndElement(); // NamedMeasurement
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "text/string");
xml.Attribute("name", "Command Line");
- xml.Element("Value", result->FullCommandLine);
+ xml.Element("Value", result.FullCommandLine);
xml.EndElement(); // NamedMeasurement
- std::map<std::string, std::string>::iterator measureIt;
- for (measureIt = result->Properties->Measurements.begin();
- measureIt != result->Properties->Measurements.end(); ++measureIt) {
+ for (auto const& measure : result.Properties->Measurements) {
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "text/string");
- xml.Attribute("name", measureIt->first);
- xml.Element("Value", measureIt->second);
+ xml.Attribute("name", measure.first);
+ xml.Element("Value", measure.second);
xml.EndElement(); // NamedMeasurement
}
xml.StartElement("Measurement");
xml.StartElement("Value");
- if (result->CompressOutput) {
+ if (result.CompressOutput) {
xml.Attribute("encoding", "base64");
xml.Attribute("compression", "gzip");
}
- xml.Content(result->Output);
+ xml.Content(result.Output);
xml.EndElement(); // Value
xml.EndElement(); // Measurement
xml.EndElement(); // Results
@@ -1364,39 +1405,40 @@ 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);
}
void cmCTestTestHandler::WriteTestResultHeader(cmXMLWriter& xml,
- cmCTestTestResult* result)
+ cmCTestTestResult const& result)
{
xml.StartElement("Test");
- if (result->Status == cmCTestTestHandler::COMPLETED) {
+ if (result.Status == cmCTestTestHandler::COMPLETED) {
xml.Attribute("Status", "passed");
- } else if (result->Status == cmCTestTestHandler::NOT_RUN) {
+ } else if (result.Status == cmCTestTestHandler::NOT_RUN) {
xml.Attribute("Status", "notrun");
} else {
xml.Attribute("Status", "failed");
}
- std::string testPath = result->Path + "/" + result->Name;
- xml.Element("Name", result->Name);
- xml.Element("Path", this->CTest->GetShortPathToFile(result->Path.c_str()));
+ std::string testPath = result.Path + "/" + result.Name;
+ xml.Element("Name", result.Name);
+ xml.Element("Path", this->CTest->GetShortPathToFile(result.Path.c_str()));
xml.Element("FullName", this->CTest->GetShortPathToFile(testPath.c_str()));
- xml.Element("FullCommandLine", result->FullCommandLine);
+ xml.Element("FullCommandLine", result.FullCommandLine);
}
void cmCTestTestHandler::WriteTestResultFooter(cmXMLWriter& xml,
- cmCTestTestResult* result)
+ cmCTestTestResult const& result)
{
- if (!result->Properties->Labels.empty()) {
+ if (!result.Properties->Labels.empty()) {
xml.StartElement("Labels");
- std::vector<std::string> const& labels = result->Properties->Labels;
- for (std::vector<std::string>::const_iterator li = labels.begin();
- li != labels.end(); ++li) {
- xml.Element("Label", *li);
+ std::vector<std::string> const& labels = result.Properties->Labels;
+ for (std::string const& label : labels) {
+ xml.Element("Label", label);
}
xml.EndElement(); // Labels
}
@@ -1405,20 +1447,18 @@ void cmCTestTestHandler::WriteTestResultFooter(cmXMLWriter& xml,
}
void cmCTestTestHandler::AttachFiles(cmXMLWriter& xml,
- cmCTestTestResult* result)
+ cmCTestTestResult& result)
{
- if (result->Status != cmCTestTestHandler::COMPLETED &&
- !result->Properties->AttachOnFail.empty()) {
- result->Properties->AttachedFiles.insert(
- result->Properties->AttachedFiles.end(),
- result->Properties->AttachOnFail.begin(),
- result->Properties->AttachOnFail.end());
- }
- for (std::vector<std::string>::const_iterator file =
- result->Properties->AttachedFiles.begin();
- file != result->Properties->AttachedFiles.end(); ++file) {
- const std::string& base64 = this->CTest->Base64GzipEncodeFile(*file);
- std::string fname = cmSystemTools::GetFilenameName(*file);
+ if (result.Status != cmCTestTestHandler::COMPLETED &&
+ !result.Properties->AttachOnFail.empty()) {
+ result.Properties->AttachedFiles.insert(
+ result.Properties->AttachedFiles.end(),
+ result.Properties->AttachOnFail.begin(),
+ result.Properties->AttachOnFail.end());
+ }
+ for (std::string const& file : result.Properties->AttachedFiles) {
+ const std::string& base64 = this->CTest->Base64GzipEncodeFile(file);
+ std::string const fname = cmSystemTools::GetFilenameName(file);
xml.StartElement("NamedMeasurement");
xml.Attribute("name", "Attached File");
xml.Attribute("encoding", "base64");
@@ -1432,18 +1472,16 @@ void cmCTestTestHandler::AttachFiles(cmXMLWriter& xml,
int cmCTestTestHandler::ExecuteCommands(std::vector<std::string>& vec)
{
- std::vector<std::string>::iterator it;
- for (it = vec.begin(); it != vec.end(); ++it) {
+ for (std::string const& it : vec) {
int retVal = 0;
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Run command: " << *it << std::endl, this->Quiet);
- if (!cmSystemTools::RunSingleCommand(it->c_str(), CM_NULLPTR, CM_NULLPTR,
- &retVal, CM_NULLPTR,
- cmSystemTools::OUTPUT_MERGE
+ "Run command: " << it << std::endl, this->Quiet);
+ if (!cmSystemTools::RunSingleCommand(it, nullptr, nullptr, &retVal,
+ nullptr, cmSystemTools::OUTPUT_MERGE
/*this->Verbose*/) ||
retVal != 0) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Problem running command: " << *it << std::endl);
+ "Problem running command: " << it << std::endl);
return 0;
}
}
@@ -1476,55 +1514,37 @@ void cmCTestTestHandler::AddConfigurations(
}
tempPath = filepath + filename;
attempted.push_back(tempPath);
- attemptedConfigs.push_back("");
+ attemptedConfigs.emplace_back();
if (!ctest->GetConfigType().empty()) {
- tempPath = filepath;
- tempPath += ctest->GetConfigType();
- tempPath += "/";
- tempPath += filename;
+ tempPath = cmStrCat(filepath, ctest->GetConfigType(), '/', filename);
attempted.push_back(tempPath);
attemptedConfigs.push_back(ctest->GetConfigType());
// If the file is an OSX bundle then the configtype
// will be at the start of the path
- tempPath = ctest->GetConfigType();
- tempPath += "/";
- tempPath += filepath;
- tempPath += filename;
+ tempPath = cmStrCat(ctest->GetConfigType(), '/', filepath, filename);
attempted.push_back(tempPath);
attemptedConfigs.push_back(ctest->GetConfigType());
} else {
// no config specified - try some options...
- tempPath = filepath;
- tempPath += "Release/";
- tempPath += filename;
+ tempPath = cmStrCat(filepath, "Release/", filename);
attempted.push_back(tempPath);
- attemptedConfigs.push_back("Release");
- tempPath = filepath;
- tempPath += "Debug/";
- tempPath += filename;
+ attemptedConfigs.emplace_back("Release");
+ tempPath = cmStrCat(filepath, "Debug/", filename);
attempted.push_back(tempPath);
- attemptedConfigs.push_back("Debug");
- tempPath = filepath;
- tempPath += "MinSizeRel/";
- tempPath += filename;
+ attemptedConfigs.emplace_back("Debug");
+ tempPath = cmStrCat(filepath, "MinSizeRel/", filename);
attempted.push_back(tempPath);
- attemptedConfigs.push_back("MinSizeRel");
- tempPath = filepath;
- tempPath += "RelWithDebInfo/";
- tempPath += filename;
+ attemptedConfigs.emplace_back("MinSizeRel");
+ tempPath = cmStrCat(filepath, "RelWithDebInfo/", filename);
attempted.push_back(tempPath);
- attemptedConfigs.push_back("RelWithDebInfo");
- tempPath = filepath;
- tempPath += "Deployment/";
- tempPath += filename;
+ attemptedConfigs.emplace_back("RelWithDebInfo");
+ tempPath = cmStrCat(filepath, "Deployment/", filename);
attempted.push_back(tempPath);
- attemptedConfigs.push_back("Deployment");
- tempPath = filepath;
- tempPath += "Development/";
- tempPath += filename;
+ attemptedConfigs.emplace_back("Deployment");
+ tempPath = cmStrCat(filepath, "Development/", filename);
attempted.push_back(tempPath);
- attemptedConfigs.push_back("Deployment");
+ attemptedConfigs.emplace_back("Deployment");
}
}
@@ -1554,11 +1574,9 @@ std::string cmCTestTestHandler::FindExecutable(
// if extraPaths are provided and we were not passed a full path, try them,
// try any extra paths
if (filepath.empty()) {
- for (unsigned int i = 0; i < extraPaths.size(); ++i) {
- std::string filepathExtra =
- cmSystemTools::GetFilenamePath(extraPaths[i]);
- std::string filenameExtra =
- cmSystemTools::GetFilenameName(extraPaths[i]);
+ for (std::string const& extraPath : extraPaths) {
+ std::string filepathExtra = cmSystemTools::GetFilenamePath(extraPath);
+ std::string filenameExtra = cmSystemTools::GetFilenameName(extraPath);
cmCTestTestHandler::AddConfigurations(ctest, attempted, attemptedConfigs,
filepathExtra, filenameExtra);
}
@@ -1570,7 +1588,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];
@@ -1578,9 +1596,9 @@ std::string cmCTestTestHandler::FindExecutable(
// then try with the exe extension
else {
failed.push_back(attempted[ai]);
- tempPath = attempted[ai];
- tempPath += cmSystemTools::GetExecutableExtension();
- if (cmSystemTools::FileExists(tempPath.c_str()) &&
+ tempPath =
+ cmStrCat(attempted[ai], cmSystemTools::GetExecutableExtension());
+ if (cmSystemTools::FileExists(tempPath) &&
!cmSystemTools::FileIsDirectory(tempPath)) {
fullPath = cmSystemTools::CollapseFullPath(tempPath);
resultingConfig = attemptedConfigs[ai];
@@ -1593,25 +1611,33 @@ std::string cmCTestTestHandler::FindExecutable(
// if everything else failed, check the users path, but only if a full path
// wasn't specified
if (fullPath.empty() && filepath.empty()) {
- std::string path = cmSystemTools::FindProgram(filename.c_str());
- if (path != "") {
- resultingConfig = "";
+ std::string const path = cmSystemTools::FindProgram(filename.c_str());
+ if (!path.empty()) {
+ resultingConfig.clear();
return path;
}
}
if (fullPath.empty()) {
- cmCTestLog(ctest, HANDLER_OUTPUT, "Could not find executable "
+ cmCTestLog(ctest, HANDLER_OUTPUT,
+ "Could not find executable "
<< testCommand << "\n"
<< "Looked in the following places:\n");
- for (std::vector<std::string>::iterator i = failed.begin();
- i != failed.end(); ++i) {
- cmCTestLog(ctest, HANDLER_OUTPUT, *i << "\n");
+ for (std::string const& f : failed) {
+ cmCTestLog(ctest, HANDLER_OUTPUT, f << "\n");
}
}
return fullPath;
}
+bool cmCTestTestHandler::ParseResourceGroupsProperty(
+ const std::string& val,
+ std::vector<std::vector<cmCTestTestResourceRequirement>>& resourceGroups)
+{
+ cmCTestResourceGroupsLexerHelper lexer(resourceGroups);
+ return lexer.ParseString(val);
+}
+
void cmCTestTestHandler::GetListOfTests()
{
if (!this->IncludeLabelRegExp.empty()) {
@@ -1630,35 +1656,32 @@ void cmCTestTestHandler::GetListOfTests()
}
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Constructing a list of tests" << std::endl, this->Quiet);
- cmake cm(cmake::RoleScript);
+ cmake cm(cmake::RoleScript, cmState::CTest);
cm.SetHomeDirectory("");
cm.SetHomeOutputDirectory("");
cm.GetCurrentSnapshot().SetDefaultDefinitions();
cmGlobalGenerator gg(&cm);
- CM_AUTO_PTR<cmMakefile> mf(new cmMakefile(&gg, cm.GetCurrentSnapshot()));
- mf->AddDefinition("CTEST_CONFIGURATION_TYPE",
- this->CTest->GetConfigType().c_str());
+ cmMakefile mf(&gg, cm.GetCurrentSnapshot());
+ mf.AddDefinition("CTEST_CONFIGURATION_TYPE", this->CTest->GetConfigType());
// Add handler for ADD_TEST
- cmCTestAddTestCommand* newCom1 = new cmCTestAddTestCommand;
- newCom1->TestHandler = this;
- cm.GetState()->AddBuiltinCommand("add_test", newCom1);
+ cm.GetState()->AddBuiltinCommand("add_test", cmCTestAddTestCommand(this));
// Add handler for SUBDIRS
- cmCTestSubdirCommand* newCom2 = new cmCTestSubdirCommand;
- newCom2->TestHandler = this;
- cm.GetState()->AddBuiltinCommand("subdirs", newCom2);
+ cm.GetState()->AddBuiltinCommand("subdirs", cmCTestSubdirCommand);
// Add handler for ADD_SUBDIRECTORY
- cmCTestAddSubdirectoryCommand* newCom3 = new cmCTestAddSubdirectoryCommand;
- newCom3->TestHandler = this;
- cm.GetState()->AddBuiltinCommand("add_subdirectory", newCom3);
+ cm.GetState()->AddBuiltinCommand("add_subdirectory",
+ cmCTestAddSubdirectoryCommand);
// Add handler for SET_TESTS_PROPERTIES
- cmCTestSetTestsPropertiesCommand* newCom4 =
- new cmCTestSetTestsPropertiesCommand;
- newCom4->TestHandler = this;
- cm.GetState()->AddBuiltinCommand("set_tests_properties", newCom4);
+ cm.GetState()->AddBuiltinCommand("set_tests_properties",
+ cmCTestSetTestsPropertiesCommand(this));
+
+ // Add handler for SET_DIRECTORY_PROPERTIES
+ cm.GetState()->RemoveBuiltinCommand("set_directory_properties");
+ cm.GetState()->AddBuiltinCommand("set_directory_properties",
+ cmCTestSetDirectoryPropertiesCommand(this));
const char* testFilename;
if (cmSystemTools::FileExists("CTestTestfile.cmake")) {
@@ -1671,7 +1694,7 @@ void cmCTestTestHandler::GetListOfTests()
return;
}
- if (!mf->ReadListFile(testFilename)) {
+ if (!mf.ReadListFile(testFilename)) {
return;
}
if (cmSystemTools::GetErrorOccuredFlag()) {
@@ -1693,17 +1716,20 @@ void cmCTestTestHandler::UseExcludeRegExp()
this->UseExcludeRegExpFirst = !this->UseIncludeRegExpFlag;
}
-const char* cmCTestTestHandler::GetTestStatus(int status)
+std::string cmCTestTestHandler::GetTestStatus(cmCTestTestResult const& result)
{
static const char* statuses[] = { "Not Run", "Timeout", "SEGFAULT",
"ILLEGAL", "INTERRUPT", "NUMERICAL",
"OTHER_FAULT", "Failed", "BAD_COMMAND",
"Completed" };
-
+ int status = result.Status;
if (status < cmCTestTestHandler::NOT_RUN ||
status > cmCTestTestHandler::COMPLETED) {
return "No Status";
}
+ if (status == cmCTestTestHandler::OTHER_FAULT) {
+ return result.ExceptionStatus;
+ }
return statuses[status];
}
@@ -1762,8 +1788,7 @@ void cmCTestTestHandler::ExpandTestsToRunInformation(size_t numTests)
std::sort(this->TestsToRun.begin(), this->TestsToRun.end(),
std::less<int>());
// remove duplicates
- std::vector<int>::iterator new_end =
- std::unique(this->TestsToRun.begin(), this->TestsToRun.end());
+ auto new_end = std::unique(this->TestsToRun.begin(), this->TestsToRun.end());
this->TestsToRun.erase(new_end, this->TestsToRun.end());
}
@@ -1774,8 +1799,8 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed()
cmsys::Directory directory;
if (directory.Load(dirName) == 0) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Unable to read the contents of "
- << dirName << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unable to read the contents of " << dirName << std::endl);
return;
}
@@ -1792,7 +1817,7 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed()
if (fileNameSubstring != pattern) {
continue;
}
- if (logName == "") {
+ if (logName.empty()) {
logName = fileName;
} else {
// if multiple matching logs were found we use the most recently
@@ -1808,10 +1833,10 @@ 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);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ lastTestsFailedLog << " does not exist!" << std::endl);
}
return;
}
@@ -1833,7 +1858,8 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed()
ifs.close();
} else if (!this->CTest->GetShowOnly() &&
!this->CTest->ShouldPrintLabels()) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Problem reading file: "
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Problem reading file: "
<< lastTestsFailedLog
<< " while generating list of previously failed tests."
<< std::endl);
@@ -1921,7 +1947,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);
@@ -1942,11 +1968,12 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml,
xml.Element("Value", "Image " + filename + " is empty");
xml.EndElement();
} else {
- cmsys::ifstream ifs(filename.c_str(), std::ios::in
+ cmsys::ifstream ifs(filename.c_str(),
+ std::ios::in
#ifdef _WIN32
| std::ios::binary
#endif
- );
+ );
unsigned char* file_buffer = new unsigned char[len + 1];
ifs.read(reinterpret_cast<char*>(file_buffer), len);
unsigned char* encoded_buffer = new unsigned char[static_cast<int>(
@@ -1983,9 +2010,9 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml,
xml.Attribute("text", "text/string");
xml.Element("Value", "File " + filename + " not found");
xml.EndElement();
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "File \""
- << filename << "\" not found." << std::endl,
- this->Quiet);
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_OUTPUT,
+ "File \"" << filename << "\" not found." << std::endl, this->Quiet);
}
cxml.erase(measurementfile.start(),
measurementfile.end() - measurementfile.start());
@@ -2086,134 +2113,156 @@ bool cmCTestTestHandler::SetTestsProperties(
break;
}
std::string val = *it;
- std::vector<std::string>::const_iterator tit;
- for (tit = tests.begin(); tit != tests.end(); ++tit) {
- cmCTestTestHandler::ListOfTests::iterator rtit;
- for (rtit = this->TestList.begin(); rtit != this->TestList.end();
- ++rtit) {
- if (*tit == rtit->Name) {
+ for (std::string const& t : tests) {
+ for (cmCTestTestProperties& rt : this->TestList) {
+ if (t == rt.Name) {
+ if (key == "_BACKTRACE_TRIPLES") {
+ std::vector<std::string> triples;
+ // allow empty args in the triples
+ cmExpandList(val, triples, true);
+
+ // Ensure we have complete triples otherwise the data is corrupt.
+ if (triples.size() % 3 == 0) {
+ cmState state;
+ rt.Backtrace = cmListFileBacktrace(state.CreateBaseSnapshot());
+
+ // the first entry represents the top of the trace so we need to
+ // reconstruct the backtrace in reverse
+ for (size_t i = triples.size(); i >= 3; i -= 3) {
+ cmListFileContext fc;
+ fc.FilePath = triples[i - 3];
+ long line = 0;
+ if (!cmStrToLong(triples[i - 2], &line)) {
+ line = 0;
+ }
+ fc.Line = line;
+ fc.Name = triples[i - 1];
+ rt.Backtrace = rt.Backtrace.Push(fc);
+ }
+ }
+ }
if (key == "WILL_FAIL") {
- rtit->WillFail = cmSystemTools::IsOn(val.c_str());
+ rt.WillFail = cmIsOn(val);
}
if (key == "DISABLED") {
- rtit->Disabled = cmSystemTools::IsOn(val.c_str());
+ rt.Disabled = cmIsOn(val);
}
if (key == "ATTACHED_FILES") {
- cmSystemTools::ExpandListArgument(val, rtit->AttachedFiles);
+ cmExpandList(val, rt.AttachedFiles);
}
if (key == "ATTACHED_FILES_ON_FAIL") {
- cmSystemTools::ExpandListArgument(val, rtit->AttachOnFail);
+ cmExpandList(val, rt.AttachOnFail);
}
if (key == "RESOURCE_LOCK") {
- std::vector<std::string> lval;
- cmSystemTools::ExpandListArgument(val, lval);
+ std::vector<std::string> lval = cmExpandedList(val);
- rtit->LockedResources.insert(lval.begin(), lval.end());
+ rt.LockedResources.insert(lval.begin(), lval.end());
}
if (key == "FIXTURES_SETUP") {
- std::vector<std::string> lval;
- cmSystemTools::ExpandListArgument(val, lval);
+ std::vector<std::string> lval = cmExpandedList(val);
- rtit->FixturesSetup.insert(lval.begin(), lval.end());
+ rt.FixturesSetup.insert(lval.begin(), lval.end());
}
if (key == "FIXTURES_CLEANUP") {
- std::vector<std::string> lval;
- cmSystemTools::ExpandListArgument(val, lval);
+ std::vector<std::string> lval = cmExpandedList(val);
- rtit->FixturesCleanup.insert(lval.begin(), lval.end());
+ rt.FixturesCleanup.insert(lval.begin(), lval.end());
}
if (key == "FIXTURES_REQUIRED") {
- std::vector<std::string> lval;
- cmSystemTools::ExpandListArgument(val, lval);
+ std::vector<std::string> lval = cmExpandedList(val);
- rtit->FixturesRequired.insert(lval.begin(), lval.end());
+ rt.FixturesRequired.insert(lval.begin(), lval.end());
}
if (key == "TIMEOUT") {
- rtit->Timeout = atof(val.c_str());
- rtit->ExplicitTimeout = true;
+ rt.Timeout = cmDuration(atof(val.c_str()));
+ rt.ExplicitTimeout = true;
}
if (key == "COST") {
- rtit->Cost = static_cast<float>(atof(val.c_str()));
+ rt.Cost = static_cast<float>(atof(val.c_str()));
}
if (key == "REQUIRED_FILES") {
- cmSystemTools::ExpandListArgument(val, rtit->RequiredFiles);
+ cmExpandList(val, rt.RequiredFiles);
}
if (key == "RUN_SERIAL") {
- rtit->RunSerial = cmSystemTools::IsOn(val.c_str());
+ rt.RunSerial = cmIsOn(val);
}
if (key == "FAIL_REGULAR_EXPRESSION") {
- std::vector<std::string> lval;
- cmSystemTools::ExpandListArgument(val, lval);
- std::vector<std::string>::iterator crit;
- for (crit = lval.begin(); crit != lval.end(); ++crit) {
- rtit->ErrorRegularExpressions.push_back(
- std::pair<cmsys::RegularExpression, std::string>(
- cmsys::RegularExpression(crit->c_str()),
- std::string(*crit)));
+ std::vector<std::string> lval = cmExpandedList(val);
+ for (std::string const& cr : lval) {
+ rt.ErrorRegularExpressions.emplace_back(cr, cr);
+ }
+ }
+ if (key == "SKIP_REGULAR_EXPRESSION") {
+ std::vector<std::string> lval = cmExpandedList(val);
+ for (std::string const& cr : lval) {
+ rt.SkipRegularExpressions.emplace_back(cr, cr);
}
}
if (key == "PROCESSORS") {
- rtit->Processors = atoi(val.c_str());
- if (rtit->Processors < 1) {
- rtit->Processors = 1;
+ rt.Processors = atoi(val.c_str());
+ if (rt.Processors < 1) {
+ rt.Processors = 1;
+ }
+ }
+ if (key == "PROCESSOR_AFFINITY") {
+ rt.WantAffinity = cmIsOn(val);
+ }
+ if (key == "RESOURCE_GROUPS") {
+ if (!ParseResourceGroupsProperty(val, rt.ResourceGroups)) {
+ return false;
}
}
if (key == "SKIP_RETURN_CODE") {
- rtit->SkipReturnCode = atoi(val.c_str());
- if (rtit->SkipReturnCode < 0 || rtit->SkipReturnCode > 255) {
- rtit->SkipReturnCode = -1;
+ rt.SkipReturnCode = atoi(val.c_str());
+ if (rt.SkipReturnCode < 0 || rt.SkipReturnCode > 255) {
+ rt.SkipReturnCode = -1;
}
}
if (key == "DEPENDS") {
- cmSystemTools::ExpandListArgument(val, rtit->Depends);
+ cmExpandList(val, rt.Depends);
}
if (key == "ENVIRONMENT") {
- cmSystemTools::ExpandListArgument(val, rtit->Environment);
+ cmExpandList(val, rt.Environment);
}
if (key == "LABELS") {
- cmSystemTools::ExpandListArgument(val, rtit->Labels);
+ std::vector<std::string> Labels = cmExpandedList(val);
+ rt.Labels.insert(rt.Labels.end(), Labels.begin(), Labels.end());
+ // sort the array
+ std::sort(rt.Labels.begin(), rt.Labels.end());
+ // remove duplicates
+ auto new_end = std::unique(rt.Labels.begin(), rt.Labels.end());
+ rt.Labels.erase(new_end, rt.Labels.end());
}
if (key == "MEASUREMENT") {
size_t pos = val.find_first_of('=');
if (pos != std::string::npos) {
std::string mKey = val.substr(0, pos);
- const char* mVal = val.c_str() + pos + 1;
- rtit->Measurements[mKey] = mVal;
+ std::string mVal = val.substr(pos + 1);
+ rt.Measurements[mKey] = std::move(mVal);
} else {
- rtit->Measurements[val] = "1";
+ rt.Measurements[val] = "1";
}
}
if (key == "PASS_REGULAR_EXPRESSION") {
- std::vector<std::string> lval;
- cmSystemTools::ExpandListArgument(val, lval);
- std::vector<std::string>::iterator crit;
- for (crit = lval.begin(); crit != lval.end(); ++crit) {
- rtit->RequiredRegularExpressions.push_back(
- std::pair<cmsys::RegularExpression, std::string>(
- cmsys::RegularExpression(crit->c_str()),
- std::string(*crit)));
+ std::vector<std::string> lval = cmExpandedList(val);
+ for (std::string const& cr : lval) {
+ rt.RequiredRegularExpressions.emplace_back(cr, cr);
}
}
if (key == "WORKING_DIRECTORY") {
- rtit->Directory = val;
+ rt.Directory = val;
}
if (key == "TIMEOUT_AFTER_MATCH") {
- std::vector<std::string> propArgs;
- cmSystemTools::ExpandListArgument(val, propArgs);
+ std::vector<std::string> propArgs = cmExpandedList(val);
if (propArgs.size() != 2) {
cmCTestLog(this->CTest, WARNING,
"TIMEOUT_AFTER_MATCH expects two arguments, found "
<< propArgs.size() << std::endl);
} else {
- rtit->AlternateTimeout = atof(propArgs[0].c_str());
- std::vector<std::string> lval;
- cmSystemTools::ExpandListArgument(propArgs[1], lval);
- std::vector<std::string>::iterator crit;
- for (crit = lval.begin(); crit != lval.end(); ++crit) {
- rtit->TimeoutRegularExpressions.push_back(
- std::pair<cmsys::RegularExpression, std::string>(
- cmsys::RegularExpression(crit->c_str()),
- std::string(*crit)));
+ rt.AlternateTimeout = cmDuration(atof(propArgs[0].c_str()));
+ std::vector<std::string> lval = cmExpandedList(propArgs[1]);
+ for (std::string const& cr : lval) {
+ rt.TimeoutRegularExpressions.emplace_back(cr, cr);
}
}
}
@@ -2224,6 +2273,51 @@ bool cmCTestTestHandler::SetTestsProperties(
return true;
}
+bool cmCTestTestHandler::SetDirectoryProperties(
+ const std::vector<std::string>& args)
+{
+ std::vector<std::string>::const_iterator it;
+ std::vector<std::string> tests;
+ bool found = false;
+ for (it = args.begin(); it != args.end(); ++it) {
+ if (*it == "PROPERTIES") {
+ found = true;
+ break;
+ }
+ tests.push_back(*it);
+ }
+
+ if (!found) {
+ return false;
+ }
+ ++it; // skip PROPERTIES
+ for (; it != args.end(); ++it) {
+ std::string key = *it;
+ ++it;
+ if (it == args.end()) {
+ break;
+ }
+ std::string val = *it;
+ for (cmCTestTestProperties& rt : this->TestList) {
+ std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+ if (cwd == rt.Directory) {
+ if (key == "LABELS") {
+ std::vector<std::string> DirectoryLabels = cmExpandedList(val);
+ rt.Labels.insert(rt.Labels.end(), DirectoryLabels.begin(),
+ DirectoryLabels.end());
+
+ // sort the array
+ std::sort(rt.Labels.begin(), rt.Labels.end());
+ // remove duplicates
+ auto new_end = std::unique(rt.Labels.begin(), rt.Labels.end());
+ rt.Labels.erase(new_end, rt.Labels.end());
+ }
+ }
+ }
+ }
+ return true;
+}
+
bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args)
{
const std::string& testname = args[0];
@@ -2231,7 +2325,7 @@ bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args)
this->Quiet);
if (this->UseExcludeRegExpFlag && this->UseExcludeRegExpFirst &&
- this->ExcludeTestsRegularExpression.find(testname.c_str())) {
+ this->ExcludeTestsRegularExpression.find(testname)) {
return true;
}
if (this->MemCheck) {
@@ -2278,19 +2372,34 @@ 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;
+ test.WantAffinity = false;
test.SkipReturnCode = -1;
test.PreviousRuns = 0;
if (this->UseIncludeRegExpFlag &&
- !this->IncludeTestsRegularExpression.find(testname.c_str())) {
+ !this->IncludeTestsRegularExpression.find(testname)) {
test.IsInBasedOnREOptions = false;
} else if (this->UseExcludeRegExpFlag && !this->UseExcludeRegExpFirst &&
- this->ExcludeTestsRegularExpression.find(testname.c_str())) {
+ this->ExcludeTestsRegularExpression.find(testname)) {
test.IsInBasedOnREOptions = false;
}
this->TestList.push_back(test);
return true;
}
+
+bool cmCTestTestHandler::cmCTestTestResourceRequirement::operator==(
+ const cmCTestTestResourceRequirement& other) const
+{
+ return this->ResourceType == other.ResourceType &&
+ this->SlotsNeeded == other.SlotsNeeded &&
+ this->UnitsNeeded == other.UnitsNeeded;
+}
+
+bool cmCTestTestHandler::cmCTestTestResourceRequirement::operator!=(
+ const cmCTestTestResourceRequirement& other) const
+{
+ return !(*this == other);
+}
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 0edcb143a..eab75d0eb 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -3,19 +3,26 @@
#ifndef cmCTestTestHandler_h
#define cmCTestTestHandler_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmCTestGenericHandler.h"
-
-#include "cmsys/RegularExpression.hxx"
+#include <chrono>
+#include <cstdint>
#include <iosfwd>
#include <map>
#include <set>
-#include <stddef.h>
#include <string>
#include <utility>
#include <vector>
+#include <stddef.h>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmCTestGenericHandler.h"
+#include "cmCTestResourceSpec.h"
+#include "cmDuration.h"
+#include "cmListFileCache.h"
+
class cmCTest;
class cmMakefile;
class cmXMLWriter;
@@ -28,18 +35,17 @@ class cmCTestTestHandler : public cmCTestGenericHandler
{
friend class cmCTestRunTest;
friend class cmCTestMultiProcessHandler;
- friend class cmCTestBatchTestHandler;
public:
- typedef cmCTestGenericHandler Superclass;
+ using Superclass = cmCTestGenericHandler;
/**
* The main entry point for this class
*/
- int ProcessHandler() CM_OVERRIDE;
+ 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.
*/
@@ -54,9 +60,9 @@ public:
/**
* This method is called when reading CTest custom file
*/
- void PopulateCustomVectors(cmMakefile* mf) CM_OVERRIDE;
+ void PopulateCustomVectors(cmMakefile* mf) override;
- ///! Control the use of the regular expresisons, call these methods to turn
+ //! Control the use of the regular expresisons, call these methods to turn
/// them on
void UseIncludeRegExp();
void UseExcludeRegExp();
@@ -75,7 +81,7 @@ public:
this->CustomMaximumFailedTestOutputSize = n;
}
- ///! pass the -I argument down
+ //! pass the -I argument down
void SetTestsToRunInformation(const char*);
cmCTestTestHandler();
@@ -90,7 +96,22 @@ public:
*/
bool SetTestsProperties(const std::vector<std::string>& args);
- void Initialize() CM_OVERRIDE;
+ /**
+ * Set directory properties
+ */
+ bool SetDirectoryProperties(const std::vector<std::string>& args);
+
+ void Initialize() override;
+
+ struct cmCTestTestResourceRequirement
+ {
+ std::string ResourceType;
+ int SlotsNeeded;
+ int UnitsNeeded;
+
+ bool operator==(const cmCTestTestResourceRequirement& other) const;
+ bool operator!=(const cmCTestTestResourceRequirement& other) const;
+ };
// NOTE: This struct is Saved/Restored
// in cmCTestTestHandler, if you add to this class
@@ -105,11 +126,13 @@ public:
std::vector<std::string> Depends;
std::vector<std::string> AttachedFiles;
std::vector<std::string> AttachOnFail;
- std::vector<std::pair<cmsys::RegularExpression, std::string> >
+ std::vector<std::pair<cmsys::RegularExpression, std::string>>
ErrorRegularExpressions;
- std::vector<std::pair<cmsys::RegularExpression, std::string> >
+ std::vector<std::pair<cmsys::RegularExpression, std::string>>
RequiredRegularExpressions;
- std::vector<std::pair<cmsys::RegularExpression, std::string> >
+ std::vector<std::pair<cmsys::RegularExpression, std::string>>
+ SkipRegularExpressions;
+ std::vector<std::pair<cmsys::RegularExpression, std::string>>
TimeoutRegularExpressions;
std::map<std::string, std::string> Measurements;
bool IsInBasedOnREOptions;
@@ -118,12 +141,14 @@ 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;
+ bool WantAffinity;
+ std::vector<size_t> Affinity;
// return code of test which will mark test as "not run"
int SkipReturnCode;
std::vector<std::string> Environment;
@@ -133,6 +158,9 @@ public:
std::set<std::string> FixturesCleanup;
std::set<std::string> FixturesRequired;
std::set<std::string> RequireSuccessDepends;
+ std::vector<std::vector<cmCTestTestResourceRequirement>> ResourceGroups;
+ // Private test generator properties used to track backtraces
+ cmListFileBacktrace Backtrace;
};
struct cmCTestTestResult
@@ -141,9 +169,10 @@ public:
std::string Path;
std::string Reason;
std::string FullCommandLine;
- double ExecutionTime;
- int ReturnValue;
+ cmDuration ExecutionTime;
+ std::int64_t ReturnValue;
int Status;
+ std::string ExceptionStatus;
bool CompressOutput;
std::string CompletionStatus;
std::string Output;
@@ -173,33 +202,51 @@ public:
std::vector<std::string>& extraPaths,
std::vector<std::string>& failed);
- typedef std::vector<cmCTestTestProperties> ListOfTests;
+ static bool ParseResourceGroupsProperty(
+ const std::string& val,
+ std::vector<std::vector<cmCTestTestResourceRequirement>>& resourceGroups);
+
+ using ListOfTests = std::vector<cmCTestTestProperties>;
protected:
+ using SetOfTests =
+ std::set<cmCTestTestHandler::cmCTestTestResult, cmCTestTestResultLess>;
+
// compute a final test list
virtual int PreProcessHandler();
virtual int PostProcessHandler();
virtual void GenerateTestCommand(std::vector<std::string>& args, int test);
int ExecuteCommands(std::vector<std::string>& vec);
- void WriteTestResultHeader(cmXMLWriter& xml, cmCTestTestResult* result);
- void WriteTestResultFooter(cmXMLWriter& xml, cmCTestTestResult* result);
+ bool ProcessOptions();
+ void LogTestSummary(const std::vector<std::string>& passed,
+ const std::vector<std::string>& failed,
+ const cmDuration& durationInSecs);
+ void LogDisabledTests(const std::vector<cmCTestTestResult>& disabledTests);
+ void LogFailedTests(const std::vector<std::string>& failed,
+ const SetOfTests& resultsSet);
+ bool GenerateXML();
+
+ void WriteTestResultHeader(cmXMLWriter& xml,
+ cmCTestTestResult const& result);
+ void WriteTestResultFooter(cmXMLWriter& xml,
+ cmCTestTestResult const& result);
// Write attached test files into the xml
- void AttachFiles(cmXMLWriter& xml, cmCTestTestResult* result);
+ void AttachFiles(cmXMLWriter& xml, cmCTestTestResult& result);
//! Clean test output to specified length
bool CleanTestOutput(std::string& output, size_t length);
- double ElapsedTestingTime;
+ cmDuration ElapsedTestingTime;
- typedef std::vector<cmCTestTestResult> TestResultsVector;
+ using TestResultsVector = std::vector<cmCTestTestResult>;
TestResultsVector TestResults;
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;
@@ -226,7 +273,8 @@ private:
*/
virtual void GenerateDartOutput(cmXMLWriter& xml);
- void PrintLabelSummary();
+ void PrintLabelOrSubprojectSummary(bool isSubProject);
+
/**
* Run the tests for a directory and any subdirectories
*/
@@ -262,7 +310,7 @@ private:
*/
std::string FindTheExecutable(const char* exe);
- const char* GetTestStatus(int status);
+ std::string GetTestStatus(cmCTestTestResult const&);
void ExpandTestsToRunInformation(size_t numPossibleTests);
void ExpandTestsToRunInformationForRerunFailed();
@@ -288,6 +336,9 @@ private:
cmsys::RegularExpression IncludeTestsRegularExpression;
cmsys::RegularExpression ExcludeTestsRegularExpression;
+ bool UseResourceSpec;
+ cmCTestResourceSpec ResourceSpec;
+
void GenerateRegressionImages(cmXMLWriter& xml, const std::string& dart);
cmsys::RegularExpression DartStuff1;
void CheckLabelFilter(cmCTestTestProperties& it);
diff --git a/Source/CTest/cmCTestUpdateCommand.cxx b/Source/CTest/cmCTestUpdateCommand.cxx
index 8c037545f..673eb9ac1 100644
--- a/Source/CTest/cmCTestUpdateCommand.cxx
+++ b/Source/CTest/cmCTestUpdateCommand.cxx
@@ -3,18 +3,15 @@
#include "cmCTestUpdateCommand.h"
#include "cmCTest.h"
-#include "cmCTestGenericHandler.h"
+#include "cmCTestUpdateHandler.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
-#include <vector>
-
cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler()
{
- if (this->Values[ct_SOURCE]) {
+ if (!this->Source.empty()) {
this->CTest->SetCTestConfiguration(
- "SourceDirectory",
- cmSystemTools::CollapseFullPath(this->Values[ct_SOURCE]).c_str(),
+ "SourceDirectory", cmSystemTools::CollapseFullPath(this->Source).c_str(),
this->Quiet);
} else {
this->CTest->SetCTestConfiguration(
@@ -62,6 +59,9 @@ cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler()
this->Makefile, "UpdateVersionOnly", "CTEST_UPDATE_VERSION_ONLY",
this->Quiet);
this->CTest->SetCTestConfigurationFromCMakeVariable(
+ this->Makefile, "UpdateVersionOverride", "CTEST_UPDATE_VERSION_OVERRIDE",
+ this->Quiet);
+ this->CTest->SetCTestConfigurationFromCMakeVariable(
this->Makefile, "HGCommand", "CTEST_HG_COMMAND", this->Quiet);
this->CTest->SetCTestConfigurationFromCMakeVariable(
this->Makefile, "HGUpdateOptions", "CTEST_HG_UPDATE_OPTIONS", this->Quiet);
@@ -74,16 +74,12 @@ cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler()
this->CTest->SetCTestConfigurationFromCMakeVariable(
this->Makefile, "P4Options", "CTEST_P4_OPTIONS", this->Quiet);
- cmCTestGenericHandler* handler =
- this->CTest->GetInitializedHandler("update");
- if (!handler) {
- this->SetError("internal CTest error. Cannot instantiate update handler");
- return CM_NULLPTR;
- }
+ cmCTestUpdateHandler* handler = this->CTest->GetUpdateHandler();
+ handler->Initialize();
handler->SetCommand(this);
if (source_dir.empty()) {
this->SetError("source directory not specified. Please use SOURCE tag");
- return CM_NULLPTR;
+ return nullptr;
}
handler->SetOption("SourceDirectory", source_dir.c_str());
handler->SetQuiet(this->Quiet);
diff --git a/Source/CTest/cmCTestUpdateCommand.h b/Source/CTest/cmCTestUpdateCommand.h
index 3b8f0a641..5555c1637 100644
--- a/Source/CTest/cmCTestUpdateCommand.h
+++ b/Source/CTest/cmCTestUpdateCommand.h
@@ -3,14 +3,17 @@
#ifndef cmCTestUpdateCommand_h
#define cmCTestUpdateCommand_h
-#include "cmConfigure.h"
-
-#include "cmCTestHandlerCommand.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
+#include <utility>
+
+#include <cm/memory>
+
+#include "cmCTestHandlerCommand.h"
+#include "cmCommand.h"
class cmCTestGenericHandler;
-class cmCommand;
/** \class cmCTestUpdate
* \brief Run a ctest script
@@ -20,26 +23,24 @@ class cmCommand;
class cmCTestUpdateCommand : public cmCTestHandlerCommand
{
public:
- cmCTestUpdateCommand() {}
-
/**
* This is a virtual constructor for the command.
*/
- cmCommand* Clone() CM_OVERRIDE
+ std::unique_ptr<cmCommand> Clone() override
{
- cmCTestUpdateCommand* ni = new cmCTestUpdateCommand;
+ auto ni = cm::make_unique<cmCTestUpdateCommand>();
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
- return ni;
+ return std::unique_ptr<cmCommand>(std::move(ni));
}
/**
* The name of the command as specified in CMakeList.txt.
*/
- std::string GetName() const CM_OVERRIDE { return "ctest_update"; }
+ std::string GetName() const override { return "ctest_update"; }
protected:
- cmCTestGenericHandler* InitializeHandler() CM_OVERRIDE;
+ cmCTestGenericHandler* InitializeHandler() override;
};
#endif
diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx
index e08a9b7bd..f30ba2bd2 100644
--- a/Source/CTest/cmCTestUpdateHandler.cxx
+++ b/Source/CTest/cmCTestUpdateHandler.cxx
@@ -2,6 +2,11 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestUpdateHandler.h"
+#include <chrono>
+#include <sstream>
+
+#include <cm/memory>
+
#include "cmCLocaleEnvironmentScope.h"
#include "cmCTest.h"
#include "cmCTestBZR.h"
@@ -12,13 +17,11 @@
#include "cmCTestSVN.h"
#include "cmCTestVC.h"
#include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
#include "cmXMLWriter.h"
-#include "cm_auto_ptr.hxx"
-#include <sstream>
-
static const char* cmCTestUpdateHandlerUpdateStrings[] = {
"Unknown", "CVS", "SVN", "BZR", "GIT", "HG", "P4"
};
@@ -32,20 +35,19 @@ static const char* cmCTestUpdateHandlerUpdateToString(int type)
return cmCTestUpdateHandlerUpdateStrings[type];
}
-cmCTestUpdateHandler::cmCTestUpdateHandler()
-{
-}
+cmCTestUpdateHandler::cmCTestUpdateHandler() = default;
void cmCTestUpdateHandler::Initialize()
{
this->Superclass::Initialize();
- this->UpdateCommand = "";
+ this->UpdateCommand.clear();
this->UpdateType = e_CVS;
}
int cmCTestUpdateHandler::DetermineType(const char* cmd, const char* type)
{
- cmCTestOptionalLog(this->CTest, DEBUG, "Determine update type from command: "
+ cmCTestOptionalLog(this->CTest, DEBUG,
+ "Determine update type from command: "
<< cmd << " and type: " << type << std::endl,
this->Quiet);
if (type && *type) {
@@ -128,34 +130,35 @@ int cmCTestUpdateHandler::ProcessHandler()
return -1;
}
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Use "
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
+ " Use "
<< cmCTestUpdateHandlerUpdateToString(this->UpdateType)
<< " repository type" << std::endl;
, this->Quiet);
// Create an object to interact with the VCS tool.
- CM_AUTO_PTR<cmCTestVC> vc;
+ std::unique_ptr<cmCTestVC> vc;
switch (this->UpdateType) {
case e_CVS:
- vc.reset(new cmCTestCVS(this->CTest, ofs));
+ vc = cm::make_unique<cmCTestCVS>(this->CTest, ofs);
break;
case e_SVN:
- vc.reset(new cmCTestSVN(this->CTest, ofs));
+ vc = cm::make_unique<cmCTestSVN>(this->CTest, ofs);
break;
case e_BZR:
- vc.reset(new cmCTestBZR(this->CTest, ofs));
+ vc = cm::make_unique<cmCTestBZR>(this->CTest, ofs);
break;
case e_GIT:
- vc.reset(new cmCTestGIT(this->CTest, ofs));
+ vc = cm::make_unique<cmCTestGIT>(this->CTest, ofs);
break;
case e_HG:
- vc.reset(new cmCTestHG(this->CTest, ofs));
+ vc = cm::make_unique<cmCTestHG>(this->CTest, ofs);
break;
case e_P4:
- vc.reset(new cmCTestP4(this->CTest, ofs));
+ vc = cm::make_unique<cmCTestP4>(this->CTest, ofs);
break;
default:
- vc.reset(new cmCTestVC(this->CTest, ofs));
+ vc = cm::make_unique<cmCTestVC>(this->CTest, ofs);
break;
}
vc->SetCommandLineTool(this->UpdateCommand);
@@ -169,14 +172,13 @@ int cmCTestUpdateHandler::ProcessHandler()
//
cmGeneratedFileStream os;
if (!this->StartResultingXML(cmCTest::PartUpdate, "Update", os)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open log file"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot open log file" << std::endl);
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 =
@@ -190,13 +192,18 @@ int cmCTestUpdateHandler::ProcessHandler()
std::string("ctest-") + cmVersion::GetCMakeVersion());
xml.Element("Site", this->CTest->GetCTestConfiguration("Site"));
xml.Element("BuildName", buildname);
- xml.Element("BuildStamp", this->CTest->GetCurrentTag() + "-" +
+ xml.Element("BuildStamp",
+ this->CTest->GetCurrentTag() + "-" +
this->CTest->GetTestModelString());
xml.Element("StartDateTime", start_time);
xml.Element("StartTime", start_time_time);
xml.Element("UpdateCommand", vc->GetUpdateCommandLine());
xml.Element("UpdateType",
cmCTestUpdateHandlerUpdateToString(this->UpdateType));
+ std::string changeId = this->CTest->GetCTestConfiguration("ChangeId");
+ if (!changeId.empty()) {
+ xml.Element("ChangeId", changeId);
+ }
bool loadedMods = vc->WriteXML(xml);
@@ -208,9 +215,9 @@ int cmCTestUpdateHandler::ProcessHandler()
this->Quiet);
}
if (int numModified = vc->GetPathCount(cmCTestVC::PathModified)) {
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, " Found "
- << numModified << " locally modified files\n",
- this->Quiet);
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_OUTPUT,
+ " Found " << numModified << " locally modified files\n", this->Quiet);
localModifications += numModified;
}
if (int numConflicting = vc->GetPathCount(cmCTestVC::PathConflicting)) {
@@ -223,11 +230,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) {
@@ -240,8 +247,9 @@ int cmCTestUpdateHandler::ProcessHandler()
if (!updated) {
xml.Content("Update command failed:\n");
xml.Content(vc->GetUpdateCommandLine());
- cmCTestLog(this->CTest, HANDLER_OUTPUT, " Update command failed: "
- << vc->GetUpdateCommandLine() << "\n");
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ " Update command failed: " << vc->GetUpdateCommandLine()
+ << "\n");
}
xml.EndElement(); // UpdateReturnStatus
xml.EndElement(); // Update
@@ -256,37 +264,31 @@ 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())) {
+ sourceDirectory = cmStrCat(dir, "/CVS");
+ if (cmSystemTools::FileExists(sourceDirectory)) {
return cmCTestUpdateHandler::e_CVS;
}
- sourceDirectory = dir;
- sourceDirectory += "/.bzr";
- if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
+ sourceDirectory = cmStrCat(dir, "/.bzr");
+ if (cmSystemTools::FileExists(sourceDirectory)) {
return cmCTestUpdateHandler::e_BZR;
}
- sourceDirectory = dir;
- sourceDirectory += "/.git";
- if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
+ sourceDirectory = cmStrCat(dir, "/.git");
+ if (cmSystemTools::FileExists(sourceDirectory)) {
return cmCTestUpdateHandler::e_GIT;
}
- sourceDirectory = dir;
- sourceDirectory += "/.hg";
- if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
+ sourceDirectory = cmStrCat(dir, "/.hg");
+ if (cmSystemTools::FileExists(sourceDirectory)) {
return cmCTestUpdateHandler::e_HG;
}
- sourceDirectory = dir;
- sourceDirectory += "/.p4";
- if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
+ sourceDirectory = cmStrCat(dir, "/.p4");
+ if (cmSystemTools::FileExists(sourceDirectory)) {
return cmCTestUpdateHandler::e_P4;
}
- sourceDirectory = dir;
- sourceDirectory += "/.p4config";
- if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
+ sourceDirectory = cmStrCat(dir, "/.p4config");
+ if (cmSystemTools::FileExists(sourceDirectory)) {
return cmCTestUpdateHandler::e_P4;
}
return cmCTestUpdateHandler::e_UNKNOWN;
@@ -309,7 +311,7 @@ bool cmCTestUpdateHandler::SelectVCS()
// If no update command was specified, lookup one for this VCS tool.
if (this->UpdateCommand.empty()) {
- const char* key = CM_NULLPTR;
+ const char* key = nullptr;
switch (this->UpdateType) {
case e_CVS:
key = "CVSCommand";
diff --git a/Source/CTest/cmCTestUpdateHandler.h b/Source/CTest/cmCTestUpdateHandler.h
index 0cd284421..afc0e3d80 100644
--- a/Source/CTest/cmCTestUpdateHandler.h
+++ b/Source/CTest/cmCTestUpdateHandler.h
@@ -3,14 +3,14 @@
#ifndef cmCTestUpdateHandler_h
#define cmCTestUpdateHandler_h
-#include "cmConfigure.h"
-
-#include "cmCTestGenericHandler.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <utility>
#include <vector>
+#include "cmCTestGenericHandler.h"
+
/** \class cmCTestUpdateHandler
* \brief A class that handles ctest -S invocations
*
@@ -18,12 +18,12 @@
class cmCTestUpdateHandler : public cmCTestGenericHandler
{
public:
- typedef cmCTestGenericHandler Superclass;
+ using Superclass = cmCTestGenericHandler;
/*
* The main entry point for this class
*/
- int ProcessHandler() CM_OVERRIDE;
+ int ProcessHandler() override;
cmCTestUpdateHandler();
@@ -42,7 +42,7 @@ public:
/**
* Initialize handler
*/
- void Initialize() CM_OVERRIDE;
+ void Initialize() override;
private:
// Some structures needed for update
diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx
index 717117a5f..d0e3848a0 100644
--- a/Source/CTest/cmCTestUploadCommand.cxx
+++ b/Source/CTest/cmCTestUploadCommand.cxx
@@ -2,67 +2,46 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestUploadCommand.h"
+#include <set>
#include <sstream>
#include <vector>
+#include "cm_static_string_view.hxx"
+
+#include "cmAlgorithms.h"
#include "cmCTest.h"
-#include "cmCTestGenericHandler.h"
#include "cmCTestUploadHandler.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmSystemTools.h"
-#include "cmake.h"
-cmCTestGenericHandler* cmCTestUploadCommand::InitializeHandler()
+void cmCTestUploadCommand::BindArguments()
{
- cmCTestGenericHandler* handler =
- this->CTest->GetInitializedHandler("upload");
- if (!handler) {
- this->SetError("internal CTest error. Cannot instantiate upload handler");
- return CM_NULLPTR;
- }
- static_cast<cmCTestUploadHandler*>(handler)->SetFiles(this->Files);
-
- handler->SetQuiet(this->Quiet);
- return handler;
+ this->Bind("FILES"_s, this->Files);
+ this->Bind("QUIET"_s, this->Quiet);
+ this->Bind("CAPTURE_CMAKE_ERROR"_s, this->CaptureCMakeError);
}
-bool cmCTestUploadCommand::CheckArgumentKeyword(std::string const& arg)
+void cmCTestUploadCommand::CheckArguments(std::vector<std::string> const&)
{
- if (arg == "FILES") {
- this->ArgumentDoing = ArgumentDoingFiles;
- return true;
- }
- if (arg == "QUIET") {
- this->ArgumentDoing = ArgumentDoingNone;
- this->Quiet = true;
- return true;
- }
- if (arg == "CAPTURE_CMAKE_ERROR") {
- this->ArgumentDoing = ArgumentDoingCaptureCMakeError;
- return true;
- }
- return false;
-}
-
-bool cmCTestUploadCommand::CheckArgumentValue(std::string const& arg)
-{
- if (this->ArgumentDoing == ArgumentDoingCaptureCMakeError) {
- this->Values[ct_CAPTURE_CMAKE_ERROR] = arg.c_str();
- return true;
- }
- if (this->ArgumentDoing == ArgumentDoingFiles) {
- if (cmSystemTools::FileExists(arg.c_str())) {
- this->Files.insert(arg);
+ cmEraseIf(this->Files, [this](std::string const& arg) -> bool {
+ if (!cmSystemTools::FileExists(arg)) {
+ std::ostringstream e;
+ e << "File \"" << arg << "\" does not exist. Cannot submit "
+ << "a non-existent file.";
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return true;
}
- std::ostringstream e;
- e << "File \"" << arg << "\" does not exist. Cannot submit "
- << "a non-existent file.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
- this->ArgumentDoing = ArgumentDoingError;
return false;
- }
+ });
+}
- // Look for other arguments.
- return this->Superclass::CheckArgumentValue(arg);
+cmCTestGenericHandler* cmCTestUploadCommand::InitializeHandler()
+{
+ cmCTestUploadHandler* handler = this->CTest->GetUploadHandler();
+ handler->Initialize();
+ handler->SetFiles(
+ std::set<std::string>(this->Files.begin(), this->Files.end()));
+ handler->SetQuiet(this->Quiet);
+ return handler;
}
diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h
index 6e721796a..8334a9e08 100644
--- a/Source/CTest/cmCTestUploadCommand.h
+++ b/Source/CTest/cmCTestUploadCommand.h
@@ -3,15 +3,18 @@
#ifndef cmCTestUploadCommand_h
#define cmCTestUploadCommand_h
-#include "cmConfigure.h"
-
-#include "cmCTest.h"
-#include "cmCTestHandlerCommand.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm/memory>
+
+#include "cmCTestHandlerCommand.h"
+#include "cmCommand.h"
class cmCTestGenericHandler;
-class cmCommand;
/** \class cmCTestUpload
* \brief Run a ctest script
@@ -22,40 +25,28 @@ class cmCommand;
class cmCTestUploadCommand : public cmCTestHandlerCommand
{
public:
- cmCTestUploadCommand() {}
-
/**
* This is a virtual constructor for the command.
*/
- cmCommand* Clone() CM_OVERRIDE
+ std::unique_ptr<cmCommand> Clone() override
{
- cmCTestUploadCommand* ni = new cmCTestUploadCommand;
+ auto ni = cm::make_unique<cmCTestUploadCommand>();
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
- return ni;
+ return std::unique_ptr<cmCommand>(std::move(ni));
}
/**
* The name of the command as specified in CMakeList.txt.
*/
- std::string GetName() const CM_OVERRIDE { return "ctest_upload"; }
-
- typedef cmCTestHandlerCommand Superclass;
+ std::string GetName() const override { return "ctest_upload"; }
protected:
- cmCTestGenericHandler* InitializeHandler() CM_OVERRIDE;
-
- bool CheckArgumentKeyword(std::string const& arg) CM_OVERRIDE;
- bool CheckArgumentValue(std::string const& arg) CM_OVERRIDE;
-
- enum
- {
- ArgumentDoingFiles = Superclass::ArgumentDoingLast1,
- ArgumentDoingCaptureCMakeError,
- ArgumentDoingLast2
- };
+ void BindArguments() override;
+ void CheckArguments(std::vector<std::string> const&) override;
+ cmCTestGenericHandler* InitializeHandler() override;
- cmCTest::SetOfStrings Files;
+ std::vector<std::string> Files;
};
#endif
diff --git a/Source/CTest/cmCTestUploadHandler.cxx b/Source/CTest/cmCTestUploadHandler.cxx
index 05a39840d..9d92aad03 100644
--- a/Source/CTest/cmCTestUploadHandler.cxx
+++ b/Source/CTest/cmCTestUploadHandler.cxx
@@ -2,14 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestUploadHandler.h"
+#include <ostream>
+#include <string>
+
+#include "cmCTest.h"
#include "cmGeneratedFileStream.h"
#include "cmVersion.h"
#include "cmXMLWriter.h"
-#include <ostream>
-#include <set>
-#include <string>
-
cmCTestUploadHandler::cmCTestUploadHandler()
{
this->Initialize();
@@ -21,7 +21,7 @@ void cmCTestUploadHandler::Initialize()
this->Files.clear();
}
-void cmCTestUploadHandler::SetFiles(const cmCTest::SetOfStrings& files)
+void cmCTestUploadHandler::SetFiles(std::set<std::string> const& files)
{
this->Files = files;
}
@@ -31,13 +31,12 @@ int cmCTestUploadHandler::ProcessHandler()
cmGeneratedFileStream ofs;
if (!this->CTest->OpenOutputFile(this->CTest->GetCurrentTag(), "Upload.xml",
ofs)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open Upload.xml file"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot open Upload.xml file" << std::endl);
return -1;
}
std::string buildname =
cmCTest::SafeBuildIdField(this->CTest->GetCTestConfiguration("BuildName"));
- cmCTest::SetOfStrings::const_iterator it;
cmXMLWriter xml(ofs);
xml.StartDocument();
@@ -47,22 +46,23 @@ int cmCTestUploadHandler::ProcessHandler()
"<file:///Dart/Source/Server/XSL/Build.xsl> \"");
xml.StartElement("Site");
xml.Attribute("BuildName", buildname);
- xml.Attribute("BuildStamp", this->CTest->GetCurrentTag() + "-" +
+ xml.Attribute("BuildStamp",
+ this->CTest->GetCurrentTag() + "-" +
this->CTest->GetTestModelString());
xml.Attribute("Name", this->CTest->GetCTestConfiguration("Site"));
xml.Attribute("Generator",
- std::string("ctest") + cmVersion::GetCMakeVersion());
+ std::string("ctest-") + cmVersion::GetCMakeVersion());
this->CTest->AddSiteProperties(xml);
xml.StartElement("Upload");
- for (it = this->Files.begin(); it != this->Files.end(); it++) {
+ for (std::string const& file : this->Files) {
cmCTestOptionalLog(this->CTest, OUTPUT,
- "\tUpload file: " << *it << std::endl, this->Quiet);
+ "\tUpload file: " << file << std::endl, this->Quiet);
xml.StartElement("File");
- xml.Attribute("filename", *it);
+ xml.Attribute("filename", file);
xml.StartElement("Content");
xml.Attribute("encoding", "base64");
- xml.Content(this->CTest->Base64EncodeFile(*it));
+ xml.Content(this->CTest->Base64EncodeFile(file));
xml.EndElement(); // Content
xml.EndElement(); // File
}
diff --git a/Source/CTest/cmCTestUploadHandler.h b/Source/CTest/cmCTestUploadHandler.h
index 1e8d3c801..dde14df16 100644
--- a/Source/CTest/cmCTestUploadHandler.h
+++ b/Source/CTest/cmCTestUploadHandler.h
@@ -3,9 +3,11 @@
#ifndef cmCTestUploadHandler_h
#define cmCTestUploadHandler_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <set>
+#include <string>
-#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
/** \class cmCTestUploadHandler
@@ -17,23 +19,22 @@
class cmCTestUploadHandler : public cmCTestGenericHandler
{
public:
- typedef cmCTestGenericHandler Superclass;
+ using Superclass = cmCTestGenericHandler;
cmCTestUploadHandler();
- ~cmCTestUploadHandler() CM_OVERRIDE {}
/*
* The main entry point for this class
*/
- int ProcessHandler() CM_OVERRIDE;
+ int ProcessHandler() override;
- void Initialize() CM_OVERRIDE;
+ void Initialize() override;
/** Specify a set of files to submit. */
- void SetFiles(cmCTest::SetOfStrings const& files);
+ void SetFiles(std::set<std::string> const& files);
private:
- cmCTest::SetOfStrings Files;
+ std::set<std::string> Files;
};
#endif
diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx
index fb2742e08..6026c69bb 100644
--- a/Source/CTest/cmCTestVC.cxx
+++ b/Source/CTest/cmCTestVC.cxx
@@ -2,16 +2,18 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestVC.h"
+#include <cstdio>
+#include <ctime>
+#include <sstream>
+#include <vector>
+
+#include "cmsys/Process.h"
+
#include "cmCTest.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLWriter.h"
-#include "cmsys/Process.h"
-#include <sstream>
-#include <stdio.h>
-#include <time.h>
-#include <vector>
-
cmCTestVC::cmCTestVC(cmCTest* ct, std::ostream& log)
: CTest(ct)
, Log(log)
@@ -24,9 +26,7 @@ cmCTestVC::cmCTestVC(cmCTest* ct, std::ostream& log)
this->Unknown.Rev = "Unknown";
}
-cmCTestVC::~cmCTestVC()
-{
-}
+cmCTestVC::~cmCTestVC() = default;
void cmCTestVC::SetCommandLineTool(std::string const& tool)
{
@@ -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;
@@ -56,11 +56,11 @@ bool cmCTestVC::InitialCheckout(const char* command)
// Construct the initial checkout command line.
std::vector<std::string> args = cmSystemTools::ParseArguments(command);
std::vector<char const*> vc_co;
- for (std::vector<std::string>::const_iterator ai = args.begin();
- ai != args.end(); ++ai) {
- vc_co.push_back(ai->c_str());
+ vc_co.reserve(args.size() + 1);
+ for (std::string const& arg : args) {
+ vc_co.push_back(arg.c_str());
}
- vc_co.push_back(CM_NULLPTR);
+ vc_co.push_back(nullptr);
// Run the initial checkout command and log its output.
this->Log << "--- Begin Initial Checkout ---\n";
@@ -69,8 +69,8 @@ bool cmCTestVC::InitialCheckout(const char* command)
bool result = this->RunChild(&vc_co[0], &out, &err, parent.c_str());
this->Log << "--- End Initial Checkout ---\n";
if (!result) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Initial checkout failed!"
- << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Initial checkout failed!" << std::endl);
}
return result;
}
@@ -79,13 +79,13 @@ bool cmCTestVC::RunChild(char const* const* cmd, OutputParser* out,
OutputParser* err, const char* workDir,
Encoding encoding)
{
- this->Log << this->ComputeCommandLine(cmd) << "\n";
+ this->Log << cmCTestVC::ComputeCommandLine(cmd) << "\n";
cmsysProcess* cp = cmsysProcess_New();
cmsysProcess_SetCommand(cp, cmd);
workDir = workDir ? workDir : this->SourceDirectory.c_str();
cmsysProcess_SetWorkingDirectory(cp, workDir);
- this->RunProcess(cp, out, err, encoding);
+ cmCTestVC::RunProcess(cp, out, err, encoding);
int result = cmsysProcess_GetExitValue(cp);
cmsysProcess_Delete(cp);
return result == 0;
@@ -113,7 +113,7 @@ bool cmCTestVC::RunUpdateCommand(char const* const* cmd, OutputParser* out,
}
// Run the command.
- return this->RunChild(cmd, out, err, CM_NULLPTR, encoding);
+ return this->RunChild(cmd, out, err, nullptr, encoding);
}
std::string cmCTestVC::GetNightlyTime()
@@ -143,10 +143,18 @@ void cmCTestVC::CleanupImpl()
bool cmCTestVC::Update()
{
bool result = true;
+
+ // Use the explicitly specified version.
+ std::string versionOverride =
+ this->CTest->GetCTestConfiguration("UpdateVersionOverride");
+ if (!versionOverride.empty()) {
+ this->SetNewRevision(versionOverride);
+ return true;
+ }
+
// if update version only is on then do not actually update,
// just note the current version and finish
- if (!cmSystemTools::IsOn(
- this->CTest->GetCTestConfiguration("UpdateVersionOnly").c_str())) {
+ if (!cmIsOn(this->CTest->GetCTestConfiguration("UpdateVersionOnly"))) {
result = this->NoteOldRevision() && result;
this->Log << "--- Begin Update ---\n";
result = this->UpdateImpl() && result;
@@ -168,6 +176,11 @@ bool cmCTestVC::NoteNewRevision()
return true;
}
+void cmCTestVC::SetNewRevision(std::string const& /*unused*/)
+{
+ // We do nothing by default.
+}
+
bool cmCTestVC::UpdateImpl()
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
diff --git a/Source/CTest/cmCTestVC.h b/Source/CTest/cmCTestVC.h
index 6400bcda3..2a4765d28 100644
--- a/Source/CTest/cmCTestVC.h
+++ b/Source/CTest/cmCTestVC.h
@@ -3,7 +3,7 @@
#ifndef cmCTestVC_h
#define cmCTestVC_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
@@ -70,6 +70,7 @@ protected:
virtual bool NoteOldRevision();
virtual bool UpdateImpl();
virtual bool NoteNewRevision();
+ virtual void SetNewRevision(std::string const& revision);
virtual bool WriteXMLUpdates(cmXMLWriter& xml);
#if defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x510
@@ -100,8 +101,8 @@ protected:
Revision const* PriorRev;
File()
: Status(PathUpdated)
- , Rev(CM_NULLPTR)
- , PriorRev(CM_NULLPTR)
+ , Rev(nullptr)
+ , PriorRev(nullptr)
{
}
File(PathStatus status, Revision const* rev, Revision const* priorRev)
@@ -117,12 +118,12 @@ protected:
/** Run a command line and send output to given parsers. */
bool RunChild(char const* const* cmd, OutputParser* out, OutputParser* err,
- const char* workDir = CM_NULLPTR,
+ const char* workDir = nullptr,
Encoding encoding = cmProcessOutput::Auto);
/** Run VC update command line and send output to given parsers. */
bool RunUpdateCommand(char const* const* cmd, OutputParser* out,
- OutputParser* err = CM_NULLPTR,
+ OutputParser* err = nullptr,
Encoding encoding = cmProcessOutput::Auto);
/** Write xml element for one file. */
diff --git a/Source/CTest/cmParseBlanketJSCoverage.cxx b/Source/CTest/cmParseBlanketJSCoverage.cxx
index 83a7b75eb..409025f80 100644
--- a/Source/CTest/cmParseBlanketJSCoverage.cxx
+++ b/Source/CTest/cmParseBlanketJSCoverage.cxx
@@ -2,25 +2,26 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmParseBlanketJSCoverage.h"
+#include <cstdio>
+#include <cstdlib>
+
+#include "cmsys/FStream.hxx"
+
#include "cmCTest.h"
#include "cmCTestCoverageHandler.h"
#include "cmSystemTools.h"
-#include "cmsys/FStream.hxx"
-#include <stdio.h>
-#include <stdlib.h>
-
class cmParseBlanketJSCoverage::JSONParser
{
public:
- typedef cmCTestCoverageHandlerContainer::SingleFileCoverageVector
- FileLinesType;
+ using FileLinesType =
+ cmCTestCoverageHandlerContainer::SingleFileCoverageVector;
JSONParser(cmCTestCoverageHandlerContainer& cont)
: Coverage(cont)
{
}
- virtual ~JSONParser() {}
+ virtual ~JSONParser() = default;
std::string getValue(std::string const& line, int type)
{
@@ -110,19 +111,18 @@ cmParseBlanketJSCoverage::cmParseBlanketJSCoverage(
{
}
-bool cmParseBlanketJSCoverage::LoadCoverageData(std::vector<std::string> files)
+bool cmParseBlanketJSCoverage::LoadCoverageData(
+ std::vector<std::string> const& files)
{
- size_t i = 0;
- std::string path;
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Found " << files.size() << " Files" << std::endl,
this->Coverage.Quiet);
- for (i = 0; i < files.size(); i++) {
+ for (std::string const& file : files) {
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
- "Reading JSON File " << files[i] << std::endl,
+ "Reading JSON File " << file << std::endl,
this->Coverage.Quiet);
- if (!this->ReadJSONFile(files[i])) {
+ if (!this->ReadJSONFile(file)) {
return false;
}
}
diff --git a/Source/CTest/cmParseBlanketJSCoverage.h b/Source/CTest/cmParseBlanketJSCoverage.h
index 696121f21..cd1b225e5 100644
--- a/Source/CTest/cmParseBlanketJSCoverage.h
+++ b/Source/CTest/cmParseBlanketJSCoverage.h
@@ -29,7 +29,7 @@ class cmParseBlanketJSCoverage
public:
cmParseBlanketJSCoverage(cmCTestCoverageHandlerContainer& cont,
cmCTest* ctest);
- bool LoadCoverageData(std::vector<std::string> files);
+ bool LoadCoverageData(std::vector<std::string> const& files);
// Read the JSON output
bool ReadJSONFile(std::string const& file);
diff --git a/Source/CTest/cmParseCacheCoverage.cxx b/Source/CTest/cmParseCacheCoverage.cxx
index 629010cf1..8c4da7577 100644
--- a/Source/CTest/cmParseCacheCoverage.cxx
+++ b/Source/CTest/cmParseCacheCoverage.cxx
@@ -1,15 +1,17 @@
#include "cmParseCacheCoverage.h"
-#include "cmCTest.h"
-#include "cmCTestCoverageHandler.h"
-#include "cmSystemTools.h"
+#include <cstdio>
+#include <cstdlib>
+#include <map>
+#include <utility>
#include "cmsys/Directory.hxx"
#include "cmsys/FStream.hxx"
-#include <map>
-#include <stdio.h>
-#include <stdlib.h>
-#include <utility>
+
+#include "cmCTest.h"
+#include "cmCTestCoverageHandler.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
cmParseCacheCoverage::cmParseCacheCoverage(
cmCTestCoverageHandlerContainer& cont, cmCTest* ctest)
@@ -30,9 +32,7 @@ bool cmParseCacheCoverage::LoadCoverageData(const char* d)
for (i = 0; i < numf; i++) {
std::string file = dir.GetFile(i);
if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) {
- std::string path = d;
- path += "/";
- path += file;
+ std::string path = cmStrCat(d, '/', file);
if (cmSystemTools::GetFilenameLastExtension(path) == ".cmcov") {
if (!this->ReadCMCovFile(path.c_str())) {
return false;
@@ -48,15 +48,12 @@ void cmParseCacheCoverage::RemoveUnCoveredFiles()
{
// loop over the coverage data computed and remove all files
// that only have -1 or 0 for the lines.
- cmCTestCoverageHandlerContainer::TotalCoverageMap::iterator ci =
- this->Coverage.TotalCoverage.begin();
+ auto ci = this->Coverage.TotalCoverage.begin();
while (ci != this->Coverage.TotalCoverage.end()) {
cmCTestCoverageHandlerContainer::SingleFileCoverageVector& v = ci->second;
bool nothing = true;
- for (cmCTestCoverageHandlerContainer::SingleFileCoverageVector::iterator
- i = v.begin();
- i != v.end(); ++i) {
- if (*i > 0) {
+ for (int i : v) {
+ if (i > 0) {
nothing = false;
break;
}
@@ -102,10 +99,11 @@ bool cmParseCacheCoverage::ReadCMCovFile(const char* file)
std::string line;
std::vector<std::string> separateLine;
if (!cmSystemTools::GetLineFromStream(in, line)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Empty file : "
- << file << " referenced in this line of cmcov data:\n"
- "["
- << line << "]\n");
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Empty file : " << file
+ << " referenced in this line of cmcov data:\n"
+ "["
+ << line << "]\n");
return false;
}
separateLine.clear();
@@ -114,8 +112,9 @@ bool cmParseCacheCoverage::ReadCMCovFile(const char* file)
separateLine[1] != "Line" || separateLine[2] != "RtnLine" ||
separateLine[3] != "Code") {
cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Bad first line of cmcov file : " << file << " line:\n"
- "["
+ "Bad first line of cmcov file : " << file
+ << " line:\n"
+ "["
<< line << "]\n");
}
std::string routine;
@@ -130,8 +129,9 @@ bool cmParseCacheCoverage::ReadCMCovFile(const char* file)
if (separateLine.size() < 4) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Bad line of cmcov file expected at least 4 found: "
- << separateLine.size() << " " << file << " line:\n"
- "["
+ << separateLine.size() << " " << file
+ << " line:\n"
+ "["
<< line << "]\n");
for (std::string::size_type i = 0; i < separateLine.size(); ++i) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "" << separateLine[1] << " ");
@@ -148,7 +148,7 @@ bool cmParseCacheCoverage::ReadCMCovFile(const char* file)
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Could not find mumps file for routine: " << routine
<< "\n");
- filepath = "";
+ filepath.clear();
continue; // move to next line
}
}
@@ -156,8 +156,8 @@ bool cmParseCacheCoverage::ReadCMCovFile(const char* file)
else {
// Totals in arg 0 marks the end of a routine
if (separateLine[0].substr(0, 6) == "Totals") {
- routine = ""; // at the end of this routine
- filepath = "";
+ routine.clear(); // at the end of this routine
+ filepath.clear();
continue; // move to next line
}
}
diff --git a/Source/CTest/cmParseCacheCoverage.h b/Source/CTest/cmParseCacheCoverage.h
index 005d27258..e89b9e454 100644
--- a/Source/CTest/cmParseCacheCoverage.h
+++ b/Source/CTest/cmParseCacheCoverage.h
@@ -3,13 +3,13 @@
#ifndef cmParseCacheCoverage_h
#define cmParseCacheCoverage_h
-#include "cmConfigure.h"
-
-#include "cmParseMumpsCoverage.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
+#include "cmParseMumpsCoverage.h"
+
class cmCTest;
class cmCTestCoverageHandlerContainer;
@@ -26,7 +26,7 @@ public:
protected:
// implement virtual from parent
- bool LoadCoverageData(const char* dir) CM_OVERRIDE;
+ bool LoadCoverageData(const char* dir) override;
// remove files with no coverage
void RemoveUnCoveredFiles();
// Read a single mcov file
diff --git a/Source/CTest/cmParseCoberturaCoverage.cxx b/Source/CTest/cmParseCoberturaCoverage.cxx
index ba55cd7b2..05da84e2e 100644
--- a/Source/CTest/cmParseCoberturaCoverage.cxx
+++ b/Source/CTest/cmParseCoberturaCoverage.cxx
@@ -1,34 +1,28 @@
#include "cmParseCoberturaCoverage.h"
+#include <cstdlib>
+#include <cstring>
+
+#include "cmsys/FStream.hxx"
+
#include "cmCTest.h"
#include "cmCTestCoverageHandler.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
-#include "cmConfigure.h"
-#include "cmsys/FStream.hxx"
-#include <stdlib.h>
-#include <string.h>
-
class cmParseCoberturaCoverage::XMLParser : public cmXMLParser
{
public:
XMLParser(cmCTest* ctest, cmCTestCoverageHandlerContainer& cont)
- : CTest(ctest)
+ : FilePaths{ cont.SourceDir, cont.BinaryDir }
+ , CTest(ctest)
, Coverage(cont)
{
- this->InSources = false;
- this->InSource = false;
- this->SkipThisClass = false;
- this->FilePaths.push_back(this->Coverage.SourceDir);
- this->FilePaths.push_back(this->Coverage.BinaryDir);
- this->CurFileName = "";
}
- ~XMLParser() CM_OVERRIDE {}
-
protected:
- void EndElement(const std::string& name) CM_OVERRIDE
+ void EndElement(const std::string& name) override
{
if (name == "source") {
this->InSource = false;
@@ -39,7 +33,7 @@ protected:
}
}
- void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
+ void CharacterDataHandler(const char* data, int length) override
{
std::string tmp;
tmp.insert(0, data, length);
@@ -51,7 +45,7 @@ protected:
}
}
- void StartElement(const std::string& name, const char** atts) CM_OVERRIDE
+ void StartElement(const std::string& name, const char** atts) override
{
std::string FoundSource;
std::string finalpath;
@@ -68,23 +62,23 @@ protected:
<< std::endl,
this->Coverage.Quiet);
std::string filename = atts[tagCount + 1];
- this->CurFileName = "";
+ this->CurFileName.clear();
// Check if this is an absolute path that falls within our
// source or binary directories.
- for (size_t i = 0; i < FilePaths.size(); i++) {
- if (filename.find(FilePaths[i]) == 0) {
+ for (std::string const& filePath : FilePaths) {
+ if (filename.find(filePath) == 0) {
this->CurFileName = filename;
break;
}
}
- if (this->CurFileName == "") {
+ if (this->CurFileName.empty()) {
// Check if this is a path that is relative to our source or
// binary directories.
- for (size_t i = 0; i < FilePaths.size(); i++) {
- finalpath = FilePaths[i] + "/" + filename;
- if (cmSystemTools::FileExists(finalpath.c_str())) {
+ for (std::string const& filePath : FilePaths) {
+ finalpath = cmStrCat(filePath, "/", filename);
+ if (cmSystemTools::FileExists(finalpath)) {
this->CurFileName = finalpath;
break;
}
@@ -92,9 +86,9 @@ protected:
}
cmsys::ifstream fin(this->CurFileName.c_str());
- if (this->CurFileName == "" || !fin) {
+ if (this->CurFileName.empty() || !fin) {
this->CurFileName =
- this->Coverage.BinaryDir + "/" + atts[tagCount + 1];
+ cmStrCat(this->Coverage.BinaryDir, "/", atts[tagCount + 1]);
fin.open(this->CurFileName.c_str());
if (!fin) {
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
@@ -145,12 +139,12 @@ protected:
}
private:
- bool InSources;
- bool InSource;
- bool SkipThisClass;
+ bool InSources = false;
+ bool InSource = false;
+ bool SkipThisClass = false;
std::vector<std::string> FilePaths;
- typedef cmCTestCoverageHandlerContainer::SingleFileCoverageVector
- FileLinesType;
+ using FileLinesType =
+ cmCTestCoverageHandlerContainer::SingleFileCoverageVector;
cmCTest* CTest;
cmCTestCoverageHandlerContainer& Coverage;
std::string CurFileName;
diff --git a/Source/CTest/cmParseDelphiCoverage.cxx b/Source/CTest/cmParseDelphiCoverage.cxx
index 4b781a6db..016e90c02 100644
--- a/Source/CTest/cmParseDelphiCoverage.cxx
+++ b/Source/CTest/cmParseDelphiCoverage.cxx
@@ -1,26 +1,27 @@
#include "cmParseDelphiCoverage.h"
-#include "cmCTest.h"
-#include "cmCTestCoverageHandler.h"
-#include "cmSystemTools.h"
+#include <cstdio>
+#include <cstdlib>
#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
-#include <stdio.h>
-#include <stdlib.h>
+
+#include "cmCTest.h"
+#include "cmCTestCoverageHandler.h"
+#include "cmSystemTools.h"
class cmParseDelphiCoverage::HTMLParser
{
public:
- typedef cmCTestCoverageHandlerContainer::SingleFileCoverageVector
- FileLinesType;
+ using FileLinesType =
+ cmCTestCoverageHandlerContainer::SingleFileCoverageVector;
HTMLParser(cmCTest* ctest, cmCTestCoverageHandlerContainer& cont)
: CTest(ctest)
, Coverage(cont)
{
}
- virtual ~HTMLParser() {}
+ virtual ~HTMLParser() = default;
bool initializeDelphiFile(
std::string const& filename,
@@ -44,7 +45,7 @@ public:
// Check that the begin is the first non-space string on the line
if ((beginPos == line.find_first_not_of(' ')) &&
beginPos != std::string::npos) {
- beginSet.push_back("begin");
+ beginSet.emplace_back("begin");
coverageVector.push_back(-1);
continue;
}
@@ -71,7 +72,8 @@ public:
}
}
// Based up what was found, add a line to the coverageVector
- if (!beginSet.empty() && line != "" && !blockComFlag && !lineComFlag) {
+ if (!beginSet.empty() && !line.empty() && !blockComFlag &&
+ !lineComFlag) {
coverageVector.push_back(0);
} else {
coverageVector.push_back(-1);
@@ -107,8 +109,9 @@ public:
while (true) {
lastoffset = line.find('(', pos);
if (lastoffset == std::string::npos) {
- cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, endnamepos
- << "File not found " << lastoffset << std::endl,
+ cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ endnamepos << "File not found " << lastoffset
+ << std::endl,
this->Coverage.Quiet);
return false;
}
diff --git a/Source/CTest/cmParseGTMCoverage.cxx b/Source/CTest/cmParseGTMCoverage.cxx
index e4ee699c4..1dc5b7038 100644
--- a/Source/CTest/cmParseGTMCoverage.cxx
+++ b/Source/CTest/cmParseGTMCoverage.cxx
@@ -1,15 +1,17 @@
#include "cmParseGTMCoverage.h"
-#include "cmCTest.h"
-#include "cmCTestCoverageHandler.h"
-#include "cmSystemTools.h"
+#include <cstdio>
+#include <cstdlib>
+#include <map>
+#include <vector>
#include "cmsys/Directory.hxx"
#include "cmsys/FStream.hxx"
-#include <map>
-#include <stdio.h>
-#include <stdlib.h>
-#include <vector>
+
+#include "cmCTest.h"
+#include "cmCTestCoverageHandler.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
cmParseGTMCoverage::cmParseGTMCoverage(cmCTestCoverageHandlerContainer& cont,
cmCTest* ctest)
@@ -30,9 +32,7 @@ bool cmParseGTMCoverage::LoadCoverageData(const char* d)
for (i = 0; i < numf; i++) {
std::string file = dir.GetFile(i);
if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) {
- std::string path = d;
- path += "/";
- path += file;
+ std::string path = cmStrCat(d, '/', file);
if (cmSystemTools::GetFilenameLastExtension(path) == ".mcov") {
if (!this->ReadMCovFile(path.c_str())) {
return false;
@@ -75,7 +75,8 @@ bool cmParseGTMCoverage::ReadMCovFile(const char* file)
this->Coverage.TotalCoverage[lastpath][lastoffset + linenumber] +=
count;
} else {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Can not find mumps file : "
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Can not find mumps file : "
<< lastroutine
<< " referenced in this line of mcov data:\n"
"["
@@ -85,6 +86,10 @@ bool cmParseGTMCoverage::ReadMCovFile(const char* file)
}
// Find the full path to the file
bool found = this->FindMumpsFile(routine, filepath);
+ if (!found && cmHasLiteralSuffix(routine, "%")) {
+ routine.erase(0, 1);
+ found = this->FindMumpsFile(routine, filepath);
+ }
if (found) {
int lineoffset = 0;
if (this->FindFunctionInMumpsFile(filepath, function, lineoffset)) {
@@ -93,7 +98,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 {
@@ -102,9 +107,11 @@ bool cmParseGTMCoverage::ReadMCovFile(const char* file)
lastoffset = lineoffset;
}
} else {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Can not find mumps file : "
- << routine << " referenced in this line of mcov data:\n"
- "["
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Can not find mumps file : "
+ << routine
+ << " referenced in this line of mcov data:\n"
+ "["
<< line << "]\n");
}
lastfunction = function;
@@ -144,8 +151,9 @@ bool cmParseGTMCoverage::FindFunctionInMumpsFile(std::string const& filepath,
linenum++; // move to next line count
}
lineoffset = 0;
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Could not find entry point : "
- << function << " in " << filepath << "\n");
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Could not find entry point : " << function << " in " << filepath
+ << "\n");
return false;
}
@@ -156,7 +164,7 @@ bool cmParseGTMCoverage::ParseMCOVLine(std::string const& line,
{
// this method parses lines from the .mcov file
// each line has ^COVERAGE(...) in it, and there
- // are several varients of coverage lines:
+ // are several variants of coverage lines:
//
// ^COVERAGE("DIC11","PR1",0)="2:0:0:0"
// ( file , entry, line ) = "number_executed:timing_info"
@@ -182,14 +190,14 @@ bool cmParseGTMCoverage::ParseMCOVLine(std::string const& line,
// save the argument into the argument vector
args.push_back(arg);
// start on a new argument
- arg = "";
+ arg.clear();
// if we are at the end of the ), then finish while loop
if (cur == ')') {
done = true;
}
} else {
- // all chars except ", (, and % get stored in the arg string
- if (cur != '\"' && cur != '(' && cur != '%') {
+ // all chars except " and ( get stored in the arg string
+ if (cur != '\"' && cur != '(') {
arg.append(1, line[pos]);
}
}
@@ -221,8 +229,8 @@ bool cmParseGTMCoverage::ParseMCOVLine(std::string const& line,
}
// less then two arguments is an error
if (args.size() < 2) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Error parsing mcov line: ["
- << line << "]\n");
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error parsing mcov line: [" << line << "]\n");
return false;
}
routine = args[0]; // the routine is the first argument
@@ -233,8 +241,8 @@ bool cmParseGTMCoverage::ParseMCOVLine(std::string const& line,
// To avoid double counting of line 0 of each entry point,
// Don't count the lines that do not give an explicit line
// number.
- routine = "";
- function = "";
+ routine.clear();
+ function.clear();
} else {
// this is the format for this line
// ^COVERAGE("%RSEL","SRC",count)
diff --git a/Source/CTest/cmParseGTMCoverage.h b/Source/CTest/cmParseGTMCoverage.h
index c4949d416..fe0ae0bfd 100644
--- a/Source/CTest/cmParseGTMCoverage.h
+++ b/Source/CTest/cmParseGTMCoverage.h
@@ -3,12 +3,12 @@
#ifndef cmParseGTMCoverage_h
#define cmParseGTMCoverage_h
-#include "cmConfigure.h"
-
-#include "cmParseMumpsCoverage.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
+#include "cmParseMumpsCoverage.h"
+
class cmCTest;
class cmCTestCoverageHandlerContainer;
@@ -25,7 +25,7 @@ public:
protected:
// implement virtual from parent
- bool LoadCoverageData(const char* dir) CM_OVERRIDE;
+ bool LoadCoverageData(const char* dir) override;
// Read a single mcov file
bool ReadMCovFile(const char* f);
// find out what line in a mumps file (filepath) the given entry point
diff --git a/Source/CTest/cmParseJacocoCoverage.cxx b/Source/CTest/cmParseJacocoCoverage.cxx
index d15864a79..9cf30dfcb 100644
--- a/Source/CTest/cmParseJacocoCoverage.cxx
+++ b/Source/CTest/cmParseJacocoCoverage.cxx
@@ -1,18 +1,18 @@
#include "cmParseJacocoCoverage.h"
-#include "cmConfigure.h"
+#include <cstdlib>
+#include <cstring>
+
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
#include "cmCTest.h"
#include "cmCTestCoverageHandler.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
-#include "cmsys/Directory.hxx"
-#include "cmsys/FStream.hxx"
-#include "cmsys/Glob.hxx"
-#include <stdlib.h>
-#include <string.h>
-
class cmParseJacocoCoverage::XMLParser : public cmXMLParser
{
public:
@@ -20,28 +20,25 @@ public:
: CTest(ctest)
, Coverage(cont)
{
- this->FilePath = "";
- this->PackagePath = "";
- this->PackageName = "";
}
- ~XMLParser() CM_OVERRIDE {}
-
protected:
- void EndElement(const std::string& /*name*/) CM_OVERRIDE {}
+ void EndElement(const std::string& /*name*/) override {}
- void StartElement(const std::string& name, const char** atts) CM_OVERRIDE
+ void StartElement(const std::string& name, const char** atts) override
{
if (name == "package") {
this->PackageName = atts[1];
- this->PackagePath = "";
+ this->PackagePath.clear();
} else if (name == "sourcefile") {
+ this->FilePath.clear();
std::string fileName = atts[1];
- if (this->PackagePath == "") {
+ if (this->PackagePath.empty()) {
if (!this->FindPackagePath(fileName)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot find file: "
- << this->PackageName << "/" << fileName << std::endl);
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot find file: " << this->PackageName << "/"
+ << fileName << std::endl);
this->Coverage.Error++;
return;
}
@@ -108,9 +105,7 @@ protected:
std::string const& baseDir)
{
// Search for the file in the baseDir and its subdirectories.
- std::string packageGlob = baseDir;
- packageGlob += "/";
- packageGlob += fileName;
+ std::string packageGlob = cmStrCat(baseDir, '/', fileName);
cmsys::Glob gl;
gl.RecurseOn();
gl.RecurseThroughSymlinksOn();
@@ -121,10 +116,9 @@ protected:
}
// Check if any of the locations found match our package.
- for (std::vector<std::string>::const_iterator fi = files.begin();
- fi != files.end(); ++fi) {
- std::string dir = cmsys::SystemTools::GetParentDirectory(*fi);
- if (cmsys::SystemTools::StringEndsWith(dir, this->PackageName.c_str())) {
+ for (std::string const& f : files) {
+ std::string dir = cmsys::SystemTools::GetParentDirectory(f);
+ if (cmHasSuffix(dir, this->PackageName)) {
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Found package directory for " << fileName << ": "
<< dir << std::endl,
@@ -140,8 +134,8 @@ private:
std::string FilePath;
std::string PackagePath;
std::string PackageName;
- typedef cmCTestCoverageHandlerContainer::SingleFileCoverageVector
- FileLinesType;
+ using FileLinesType =
+ cmCTestCoverageHandlerContainer::SingleFileCoverageVector;
cmCTest* CTest;
cmCTestCoverageHandlerContainer& Coverage;
};
diff --git a/Source/CTest/cmParseMumpsCoverage.cxx b/Source/CTest/cmParseMumpsCoverage.cxx
index eb29f55c0..b16f1014a 100644
--- a/Source/CTest/cmParseMumpsCoverage.cxx
+++ b/Source/CTest/cmParseMumpsCoverage.cxx
@@ -1,17 +1,18 @@
#include "cmParseMumpsCoverage.h"
-#include "cmCTest.h"
-#include "cmCTestCoverageHandler.h"
-#include "cmSystemTools.h"
-
-#include "cmConfigure.h"
-#include "cmsys/FStream.hxx"
-#include "cmsys/Glob.hxx"
#include <map>
#include <string>
#include <utility>
#include <vector>
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+
+#include "cmCTest.h"
+#include "cmCTestCoverageHandler.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
cmParseMumpsCoverage::cmParseMumpsCoverage(
cmCTestCoverageHandlerContainer& cont, cmCTest* ctest)
: Coverage(cont)
@@ -19,9 +20,7 @@ cmParseMumpsCoverage::cmParseMumpsCoverage(
{
}
-cmParseMumpsCoverage::~cmParseMumpsCoverage()
-{
-}
+cmParseMumpsCoverage::~cmParseMumpsCoverage() = default;
bool cmParseMumpsCoverage::ReadCoverageFile(const char* file)
{
@@ -110,17 +109,14 @@ bool cmParseMumpsCoverage::LoadPackages(const char* d)
{
cmsys::Glob glob;
glob.RecurseOn();
- std::string pat = d;
- pat += "/*.m";
+ std::string pat = cmStrCat(d, "/*.m");
glob.FindFiles(pat);
- std::vector<std::string>& files = glob.GetFiles();
- std::vector<std::string>::iterator fileIt;
- for (fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
- std::string name = cmSystemTools::GetFilenameName(*fileIt);
- this->RoutineToDirectory[name.substr(0, name.size() - 2)] = *fileIt;
- // initialze each file, this is left out until CDash is fixed
+ for (std::string& file : glob.GetFiles()) {
+ std::string name = cmSystemTools::GetFilenameName(file);
+ this->RoutineToDirectory[name.substr(0, name.size() - 2)] = file;
+ // initialize each file, this is left out until CDash is fixed
// to handle large numbers of files
- this->InitializeMumpsFile(*fileIt);
+ this->InitializeMumpsFile(file);
}
return true;
}
@@ -128,15 +124,14 @@ bool cmParseMumpsCoverage::LoadPackages(const char* d)
bool cmParseMumpsCoverage::FindMumpsFile(std::string const& routine,
std::string& filepath)
{
- std::map<std::string, std::string>::iterator i =
- this->RoutineToDirectory.find(routine);
+ auto i = this->RoutineToDirectory.find(routine);
if (i != this->RoutineToDirectory.end()) {
filepath = i->second;
return true;
}
// try some alternate names
- const char* tryname[] = { "GUX", "GTM", "ONT", CM_NULLPTR };
- for (int k = 0; tryname[k] != CM_NULLPTR; k++) {
+ const char* tryname[] = { "GUX", "GTM", "ONT", nullptr };
+ for (int k = 0; tryname[k] != nullptr; k++) {
std::string routine2 = routine + tryname[k];
i = this->RoutineToDirectory.find(routine2);
if (i != this->RoutineToDirectory.end()) {
diff --git a/Source/CTest/cmParsePHPCoverage.cxx b/Source/CTest/cmParsePHPCoverage.cxx
index 761ebec65..a494b92b9 100644
--- a/Source/CTest/cmParsePHPCoverage.cxx
+++ b/Source/CTest/cmParsePHPCoverage.cxx
@@ -1,13 +1,15 @@
#include "cmParsePHPCoverage.h"
-#include "cmCTest.h"
-#include "cmCTestCoverageHandler.h"
-#include "cmSystemTools.h"
+#include <cstdlib>
+#include <cstring>
#include "cmsys/Directory.hxx"
#include "cmsys/FStream.hxx"
-#include <stdlib.h>
-#include <string.h>
+
+#include "cmCTest.h"
+#include "cmCTestCoverageHandler.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
/*
To setup coverage for php.
@@ -153,7 +155,8 @@ bool cmParsePHPCoverage::ReadFileInformation(std::istream& in)
delete[] s;
// read close quote
if (in.get(c) && c != '"') {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "failed to read close quote\n"
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "failed to read close quote\n"
<< "read [" << c << "]\n");
return false;
}
@@ -184,8 +187,8 @@ bool cmParsePHPCoverage::ReadPHPData(const char* file)
}
for (int i = 0; i < size; i++) {
if (!this->ReadFileInformation(in)) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "Failed to read file #" << i
- << "\n");
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Failed to read file #" << i << "\n");
return false;
}
in.get(c);
@@ -209,9 +212,7 @@ bool cmParsePHPCoverage::ReadPHPCoverageDirectory(const char* d)
for (i = 0; i < numf; i++) {
std::string file = dir.GetFile(i);
if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) {
- std::string path = d;
- path += "/";
- path += file;
+ std::string path = cmStrCat(d, '/', file);
if (!this->ReadPHPData(path.c_str())) {
return false;
}
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index f4ec6da29..87f7147bc 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -2,26 +2,39 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmProcess.h"
-#include "cmConfigure.h"
-#include "cmProcessOutput.h"
-#include "cmSystemTools.h"
+#include <csignal>
#include <iostream>
+#include <string>
-cmProcess::cmProcess()
+#include "cmsys/Process.h"
+
+#include "cmAlgorithms.h"
+#include "cmCTest.h"
+#include "cmCTestRunTest.h"
+#include "cmCTestTestHandler.h"
+#include "cmGetPipes.h"
+#include "cmStringAlgorithms.h"
+#if defined(_WIN32)
+# include "cm_kwiml.h"
+#endif
+#include <utility>
+
+#define CM_PROCESS_BUF_SIZE 65536
+
+cmProcess::cmProcess(cmCTestRunTest& runner)
+ : Runner(runner)
+ , Conv(cmProcessOutput::UTF8, CM_PROCESS_BUF_SIZE)
{
- this->Process = CM_NULLPTR;
- this->Timeout = 0;
- this->TotalTime = 0;
+ 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)
+cmProcess::~cmProcess() = default;
+
+void cmProcess::SetCommand(std::string const& command)
{
this->Command = command;
}
@@ -31,32 +44,121 @@ void cmProcess::SetCommandArguments(std::vector<std::string> const& args)
this->Arguments = args;
}
-bool cmProcess::StartProcess()
+void cmProcess::SetWorkingDirectory(std::string const& dir)
{
+ this->WorkingDirectory = dir;
+}
+
+bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity)
+{
+ 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());
// now put the command arguments in
- for (std::vector<std::string>::iterator i = this->Arguments.begin();
- i != this->Arguments.end(); ++i) {
- this->ProcessArgs.push_back(i->c_str());
+ for (std::string const& arg : this->Arguments) {
+ this->ProcessArgs.push_back(arg.c_str());
+ }
+ this->ProcessArgs.push_back(nullptr); // null terminate the list
+
+ 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 = cmGetPipes(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_INHERIT_FD;
+ stdio[0].data.fd = 0;
+ 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;
+#if !defined(CMAKE_USE_SYSTEM_LIBUV)
+ std::vector<char> cpumask;
+ if (affinity && !affinity->empty()) {
+ cpumask.resize(static_cast<size_t>(uv_cpumask_size()), 0);
+ for (auto p : *affinity) {
+ cpumask[p] = 1;
+ }
+ options.cpumask = cpumask.data();
+ options.cpumask_size = cpumask.size();
+ } else {
+ options.cpumask = nullptr;
+ options.cpumask_size = 0;
+ }
+#else
+ static_cast<void>(affinity);
+#endif
+
+ 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;
}
- this->ProcessArgs.push_back(CM_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());
+
+ 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)
@@ -65,7 +167,7 @@ bool cmProcess::Buffer::GetLine(std::string& line)
for (size_type sz = this->size(); this->Last != sz; ++this->Last) {
if ((*this)[this->Last] == '\n' || (*this)[this->Last] == '\0') {
// Extract the range first..last as a line.
- const char* text = &*this->begin() + this->First;
+ const char* text = this->data() + this->First;
size_type length = this->Last - this->First;
while (length && text[length - 1] == '\r') {
length--;
@@ -95,7 +197,7 @@ bool cmProcess::Buffer::GetLast(std::string& line)
{
// Return the partial last line, if any.
if (!this->empty()) {
- line.assign(&*this->begin(), this->size());
+ line.assign(this->data(), this->size());
this->First = this->Last = 0;
this->clear();
return true;
@@ -103,140 +205,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);
+ cmAppend(this->Output, strdata);
+
+ 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);
}
- // No more data. Wait for process exit.
- if (!cmsysProcess_WaitForExit(this->Process, &timeout)) {
- return cmsysProcess_Pipe_Timeout;
+ 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);
+ }
+
+ *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 = 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()
+{
+ 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];
+ const char* fmt = "Exit code 0x%" KWIML_INT_PRIx64 "\n";
+ _snprintf(buf, 1024, fmt, 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 = cmStrCat("Signal ", this->Signal);
+ }
+#endif
+ return exception_str;
}
diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h
index 86e905aca..2c24f2df0 100644
--- a/Source/CTest/cmProcess.h
+++ b/Source/CTest/cmProcess.h
@@ -5,10 +5,21 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmsys/Process.h"
+#include <chrono>
#include <string>
#include <vector>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "cm_uv.h"
+
+#include "cmDuration.h"
+#include "cmProcessOutput.h"
+#include "cmUVHandlePtr.h"
+
+class cmCTestRunTest;
+
/** \class cmProcess
* \brief run a process with c++
*
@@ -17,41 +28,80 @@
class cmProcess
{
public:
- cmProcess();
+ explicit cmProcess(cmCTestRunTest& runner);
~cmProcess();
- const char* GetCommand() { return this->Command.c_str(); }
- void SetCommand(const char* command);
+ void SetCommand(std::string const& 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 SetWorkingDirectory(std::string const& dir);
+ 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, std::vector<size_t>* affinity);
- // return the process status
- int GetProcessStatus();
- // Report the status of the program
- int ReportStatus();
+ enum class State
+ {
+ Starting,
+ Error,
+ Exception,
+ Executing,
+ Exited,
+ Expired,
+ Killed,
+ Disowned
+ };
+
+ 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();
- /**
- * 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);
+ int64_t GetExitValue() { return this->ExitValue; }
+ cmDuration GetTotalTime() { return this->TotalTime; }
+
+ enum class Exception
+ {
+ None,
+ Fault,
+ Illegal,
+ Interrupt,
+ Numerical,
+ Other
+ };
+
+ Exception GetExitException();
+ std::string GetExitExceptionString();
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.
@@ -73,7 +123,7 @@ private:
std::vector<std::string> Arguments;
std::vector<const char*> ProcessArgs;
int Id;
- int ExitValue;
+ int64_t ExitValue;
};
#endif
diff --git a/Source/Checks/Curses.cmake b/Source/Checks/Curses.cmake
new file mode 100644
index 000000000..2942b666a
--- /dev/null
+++ b/Source/Checks/Curses.cmake
@@ -0,0 +1,41 @@
+message(STATUS "Checking for curses support")
+
+# Try compiling a simple project using curses.
+# Pass in any cache entries that the user may have set.
+set(CMakeCheckCurses_ARGS "")
+foreach(v
+ CURSES_INCLUDE_PATH
+ CURSES_CURSES_LIBRARY
+ CURSES_NCURSES_LIBRARY
+ CURSES_EXTRA_LIBRARY
+ CURSES_FORM_LIBRARY
+ )
+ if(${v})
+ list(APPEND CMakeCheckCurses_ARGS -D${v}=${${v}})
+ endif()
+endforeach()
+file(REMOVE_RECURSE "${CMake_BINARY_DIR}/Source/Checks/Curses-build")
+try_compile(CMakeCheckCurses_COMPILED
+ ${CMake_BINARY_DIR}/Source/Checks/Curses-build
+ ${CMake_SOURCE_DIR}/Source/Checks/Curses
+ CheckCurses # project name
+ CheckCurses # target name
+ CMAKE_FLAGS
+ "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS}"
+ ${CMakeCheckCurses_ARGS}
+ OUTPUT_VARIABLE CMakeCheckCurses_OUTPUT
+ )
+
+# Convert result from cache entry to normal variable.
+set(CMakeCheckCurses_COMPILED "${CMakeCheckCurses_COMPILED}")
+unset(CMakeCheckCurses_COMPILED CACHE)
+
+if(CMakeCheckCurses_COMPILED)
+ message(STATUS "Checking for curses support - Success")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Checking for curses support passed with the following output:\n${CMakeCheckCurses_OUTPUT}\n\n")
+else()
+ message(STATUS "Checking for curses support - Failed")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Checking for curses support failed with the following output:\n${CMakeCheckCurses_OUTPUT}\n\n")
+endif()
diff --git a/Source/Checks/Curses/CMakeLists.txt b/Source/Checks/Curses/CMakeLists.txt
new file mode 100644
index 000000000..17318a33b
--- /dev/null
+++ b/Source/Checks/Curses/CMakeLists.txt
@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION 3.1)
+if(POLICY CMP0060)
+ cmake_policy(SET CMP0060 NEW)
+endif()
+project(CheckCurses C)
+
+set(CURSES_NEED_NCURSES TRUE)
+find_package(Curses)
+if(NOT CURSES_FOUND)
+ return()
+endif()
+include_directories(${CURSES_INCLUDE_DIRS})
+add_executable(CheckCurses CheckCurses.c)
+target_link_libraries(CheckCurses ${CURSES_LIBRARIES})
+
+foreach(h
+ CURSES_HAVE_CURSES_H
+ CURSES_HAVE_NCURSES_H
+ CURSES_HAVE_NCURSES_NCURSES_H
+ CURSES_HAVE_NCURSES_CURSES_H
+ )
+ if(${h})
+ target_compile_definitions(CheckCurses PRIVATE ${h})
+ endif()
+endforeach()
diff --git a/Source/Checks/Curses/CheckCurses.c b/Source/Checks/Curses/CheckCurses.c
new file mode 100644
index 000000000..7d827e6bf
--- /dev/null
+++ b/Source/Checks/Curses/CheckCurses.c
@@ -0,0 +1,15 @@
+#if defined(CURSES_HAVE_NCURSES_H)
+# include <ncurses.h>
+#elif defined(CURSES_HAVE_NCURSES_NCURSES_H)
+# include <ncurses/ncurses.h>
+#elif defined(CURSES_HAVE_NCURSES_CURSES_H)
+# include <ncurses/curses.h>
+#else
+# include <curses.h>
+#endif
+
+int main()
+{
+ curses_version();
+ return 0;
+}
diff --git a/Source/Checks/cm_cxx14_check.cmake b/Source/Checks/cm_cxx14_check.cmake
new file mode 100644
index 000000000..38606b9c9
--- /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|PGI")
+ 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_check.cpp b/Source/Checks/cm_cxx14_check.cpp
new file mode 100644
index 000000000..fff36c916
--- /dev/null
+++ b/Source/Checks/cm_cxx14_check.cpp
@@ -0,0 +1,15 @@
+#include <cstdio>
+#include <iterator>
+#include <memory>
+
+int main()
+{
+ int a[] = { 0, 1, 2 };
+ auto ai = std::cbegin(a);
+
+ int b[] = { 2, 1, 0 };
+ auto bi = std::cend(b);
+
+ std::unique_ptr<int> u(new int(0));
+ return *u + *ai + *(bi - 1);
+}
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_cxx14_cstdio.cpp b/Source/Checks/cm_cxx14_cstdio.cpp
deleted file mode 100644
index f5806a9c6..000000000
--- a/Source/Checks/cm_cxx14_cstdio.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-#include <cstdio>
-int main()
-{
- return 0;
-}
diff --git a/Source/Checks/cm_cxx17_check.cmake b/Source/Checks/cm_cxx17_check.cmake
new file mode 100644
index 000000000..4da2fd7ca
--- /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|PGI")
+ 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..29863b136
--- /dev/null
+++ b/Source/Checks/cm_cxx17_check.cpp
@@ -0,0 +1,34 @@
+#include <cstdio>
+#include <iterator>
+#include <memory>
+#include <optional>
+#include <unordered_map>
+
+#ifdef _MSC_VER
+# include <comdef.h>
+#endif
+
+int main()
+{
+ int a[] = { 0, 1, 2 };
+ auto ai = std::cbegin(a);
+
+ int b[] = { 2, 1, 0 };
+ auto bi = std::cend(b);
+
+ auto ci = std::size(a);
+
+ std::unique_ptr<int> u(new int(0));
+
+#ifdef _MSC_VER
+ // clang-cl has problems instantiating this constructor in C++17 mode
+ // error: indirection requires pointer operand ('const _GUID' invalid)
+ // return *_IID;
+ IUnknownPtr ptr{};
+ IDispatchPtr disp(ptr);
+#endif
+
+ std::optional<int> oi = 0;
+
+ return *u + *ai + *(bi - 1) + (3 - static_cast<int>(ci)) + oi.value();
+}
diff --git a/Source/Checks/cm_cxx_attribute_fallthrough.cxx b/Source/Checks/cm_cxx_attribute_fallthrough.cxx
deleted file mode 100644
index df43625a4..000000000
--- a/Source/Checks/cm_cxx_attribute_fallthrough.cxx
+++ /dev/null
@@ -1,11 +0,0 @@
-int main(int argc, char* argv[])
-{
- int i = 3;
- switch (argc) {
- case 1:
- i = 0;
- __attribute__((fallthrough));
- default:
- return i;
- }
-}
diff --git a/Source/Checks/cm_cxx_auto_ptr.cxx b/Source/Checks/cm_cxx_auto_ptr.cxx
deleted file mode 100644
index d3100fdc8..000000000
--- a/Source/Checks/cm_cxx_auto_ptr.cxx
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <memory>
-
-std::auto_ptr<int> get_auto_ptr()
-{
- std::auto_ptr<int> ptr;
- ptr = std::auto_ptr<int>(new int(0));
- return ptr;
-}
-
-int use_auto_ptr(std::auto_ptr<int> ptr)
-{
- return *ptr;
-}
-
-int main()
-{
- return use_auto_ptr(get_auto_ptr());
-}
diff --git a/Source/Checks/cm_cxx_eq_delete.cxx b/Source/Checks/cm_cxx_eq_delete.cxx
deleted file mode 100644
index 809e4cfcf..000000000
--- a/Source/Checks/cm_cxx_eq_delete.cxx
+++ /dev/null
@@ -1,14 +0,0 @@
-struct Foo
-{
- Foo() {}
- ~Foo() {}
- Foo(Foo const&) = delete;
- Foo& operator=(Foo const&) = delete;
- int test() const { return 0; }
-};
-
-int main()
-{
- Foo const foo;
- return foo.test();
-}
diff --git a/Source/Checks/cm_cxx_fallthrough.cxx b/Source/Checks/cm_cxx_fallthrough.cxx
deleted file mode 100644
index 7b35a5f29..000000000
--- a/Source/Checks/cm_cxx_fallthrough.cxx
+++ /dev/null
@@ -1,11 +0,0 @@
-int main(int argc, char* argv[])
-{
- 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 3b0802579..fb68ed78c 100644
--- a/Source/Checks/cm_cxx_features.cmake
+++ b/Source/Checks/cm_cxx_features.cmake
@@ -14,10 +14,20 @@ function(cm_check_cxx_feature name)
CMAKE_FLAGS ${maybe_cxx_standard}
OUTPUT_VARIABLE OUTPUT
)
+ set(check_output "${OUTPUT}")
# Filter out MSBuild output that looks like a warning.
- string(REGEX REPLACE " +0 Warning\\(s\\)" "" check_output "${OUTPUT}")
+ string(REGEX REPLACE " +0 Warning\\(s\\)" "" check_output "${check_output}")
+ # Filter out warnings caused by user flags.
+ string(REGEX REPLACE "[^\n]*warning:[^\n]*-Winvalid-command-line-argument[^\n]*" "" check_output "${check_output}")
+ # Filter out warnings caused by local configuration.
+ string(REGEX REPLACE "[^\n]*warning:[^\n]*directory not found for option[^\n]*" "" check_output "${check_output}")
+ string(REGEX REPLACE "[^\n]*warning:[^\n]*object file compiled with -mlong-branch which is no longer needed[^\n]*" "" check_output "${check_output}")
+ # Filter out other warnings unrelated to feature checks.
+ string(REGEX REPLACE "[^\n]*warning:[^\n]*sprintf\\(\\) is often misused, please use snprintf[^\n]*" "" check_output "${check_output}")
+ # Filter out xcodebuild warnings.
+ string(REGEX REPLACE "[^\n]* xcodebuild\\[[0-9]*:[0-9]*\\] warning: [^\n]*" "" check_output "${check_output}")
# If using the feature causes warnings, treat it as broken/unavailable.
- if(check_output MATCHES "[Ww]arning")
+ if(check_output MATCHES "(^|[ :])[Ww][Aa][Rr][Nn][Ii][Nn][Gg]")
set(CMake_HAVE_CXX_${FEATURE} OFF CACHE INTERNAL "TRY_COMPILE" FORCE)
endif()
if(CMake_HAVE_CXX_${FEATURE})
@@ -38,21 +48,8 @@ function(cm_check_cxx_feature name)
endif()
endfunction()
-cm_check_cxx_feature(auto_ptr)
-cm_check_cxx_feature(eq_delete)
-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)
endif()
-cm_check_cxx_feature(nullptr)
-cm_check_cxx_feature(override)
cm_check_cxx_feature(unique_ptr)
-cm_check_cxx_feature(unordered_map)
-cm_check_cxx_feature(unordered_set)
diff --git a/Source/Checks/cm_cxx_gnu_fallthrough.cxx b/Source/Checks/cm_cxx_gnu_fallthrough.cxx
deleted file mode 100644
index 602109405..000000000
--- a/Source/Checks/cm_cxx_gnu_fallthrough.cxx
+++ /dev/null
@@ -1,11 +0,0 @@
-int main(int argc, char* argv[])
-{
- int i = 3;
- switch (argc) {
- case 1:
- i = 0;
- [[gnu::fallthrough]];
- default:
- return i;
- }
-}
diff --git a/Source/Checks/cm_cxx_nullptr.cxx b/Source/Checks/cm_cxx_nullptr.cxx
deleted file mode 100644
index 500684aee..000000000
--- a/Source/Checks/cm_cxx_nullptr.cxx
+++ /dev/null
@@ -1,14 +0,0 @@
-int test(int)
-{
- return -1;
-}
-
-int test(int*)
-{
- return 0;
-}
-
-int main()
-{
- return test(nullptr);
-}
diff --git a/Source/Checks/cm_cxx_override.cxx b/Source/Checks/cm_cxx_override.cxx
deleted file mode 100644
index 5a33fbb78..000000000
--- a/Source/Checks/cm_cxx_override.cxx
+++ /dev/null
@@ -1,24 +0,0 @@
-struct Foo
-{
- Foo() {}
- virtual ~Foo() {}
- virtual int test() const = 0;
-};
-
-struct Bar : Foo
-{
- Bar() {}
- ~Bar() override {}
- int test() const override { return 0; }
-};
-
-int test(Foo const& foo)
-{
- return foo.test();
-}
-
-int main()
-{
- Bar const bar;
- return test(bar);
-}
diff --git a/Source/Checks/cm_cxx_unordered_map.cxx b/Source/Checks/cm_cxx_unordered_map.cxx
deleted file mode 100644
index be3de252b..000000000
--- a/Source/Checks/cm_cxx_unordered_map.cxx
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <unordered_map>
-int main()
-{
- std::unordered_map<int, int> map;
- map[0] = 0;
- return 0;
-}
diff --git a/Source/Checks/cm_cxx_unordered_set.cxx b/Source/Checks/cm_cxx_unordered_set.cxx
deleted file mode 100644
index de4bb7765..000000000
--- a/Source/Checks/cm_cxx_unordered_set.cxx
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <unordered_set>
-int main()
-{
- std::unordered_set<int> set;
- set.insert(0);
- return 0;
-}
diff --git a/Source/CursesDialog/CMakeLists.txt b/Source/CursesDialog/CMakeLists.txt
index c5ac1f1a6..700971751 100644
--- a/Source/CursesDialog/CMakeLists.txt
+++ b/Source/CursesDialog/CMakeLists.txt
@@ -1,32 +1,28 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# 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
- )
-
-if( NOT CMAKE_USE_SYSTEM_FORM )
- include_directories(${CMake_SOURCE_DIR}/Source/CursesDialog/form
- ${CMake_BINARY_DIR}/Source/CursesDialog/form)
-endif()
-include_directories(${CURSES_INCLUDE_PATH})
-
-
-add_executable(ccmake ${CURSES_SRCS} )
+add_executable(ccmake
+ ccmake.cxx
+ cmCursesBoolWidget.cxx
+ cmCursesCacheEntryComposite.cxx
+ cmCursesDummyWidget.cxx
+ cmCursesFilePathWidget.cxx
+ cmCursesForm.cxx
+ cmCursesLabelWidget.cxx
+ cmCursesLongMessageForm.cxx
+ cmCursesMainForm.cxx
+ cmCursesOptionsWidget.cxx
+ cmCursesPathWidget.cxx
+ cmCursesStringWidget.cxx
+ cmCursesWidget.cxx
+ )
+target_include_directories(ccmake PRIVATE ${CURSES_INCLUDE_PATH})
target_link_libraries(ccmake CMakeLib)
if(CMAKE_USE_SYSTEM_FORM)
+ find_path(CURSES_FORM_INCLUDE_DIR NAMES form.h HINTS ${CURSES_INCLUDE_PATH} ${CURSES_INCLUDE_PATH}/ncurses)
+ if(CURSES_FORM_INCLUDE_DIR)
+ target_include_directories(ccmake PRIVATE ${CURSES_FORM_INCLUDE_DIR})
+ endif()
target_link_libraries(ccmake
${CURSES_FORM_LIBRARY}
${CURSES_LIBRARY}
diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx
index 28a0e95b9..9e9dfbd19 100644
--- a/Source/CursesDialog/ccmake.cxx
+++ b/Source/CursesDialog/ccmake.cxx
@@ -1,47 +1,50 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmConfigure.h"
+
+#include <csignal>
+#include <cstring>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "cmsys/Encoding.hxx"
#include "cmCursesForm.h"
#include "cmCursesMainForm.h"
#include "cmCursesStandardIncludes.h"
#include "cmDocumentation.h"
-#include "cmDocumentationEntry.h"
+#include "cmDocumentationEntry.h" // IWYU pragma: keep
+#include "cmState.h"
#include "cmSystemTools.h"
#include "cmake.h"
-#include "cmsys/Encoding.hxx"
-#include <iostream>
-#include <signal.h>
-#include <string.h>
-#include <string>
-#include <vector>
-
static const char* cmDocumentationName[][2] = {
- { CM_NULLPTR, " ccmake - Curses Interface for CMake." },
- { CM_NULLPTR, CM_NULLPTR }
+ { nullptr, " ccmake - Curses Interface for CMake." },
+ { nullptr, nullptr }
};
static const char* cmDocumentationUsage[][2] = {
- { CM_NULLPTR, " ccmake <path-to-source>\n"
- " ccmake <path-to-existing-build>" },
- { CM_NULLPTR,
+ { nullptr,
+ " ccmake <path-to-source>\n"
+ " ccmake <path-to-existing-build>" },
+ { nullptr,
"Specify a source directory to (re-)generate a build system for "
"it in the current working directory. Specify an existing build "
"directory to re-generate its build system." },
- { CM_NULLPTR, CM_NULLPTR }
+ { nullptr, nullptr }
};
static const char* cmDocumentationUsageNote[][2] = {
- { CM_NULLPTR, "Run 'ccmake --help' for more information." },
- { CM_NULLPTR, CM_NULLPTR }
+ { nullptr, "Run 'ccmake --help' for more information." },
+ { nullptr, nullptr }
};
-static const char* cmDocumentationOptions[]
- [2] = { CMAKE_STANDARD_OPTIONS_TABLE,
- { CM_NULLPTR, CM_NULLPTR } };
+static const char* cmDocumentationOptions[][2] = {
+ CMAKE_STANDARD_OPTIONS_TABLE,
+ { nullptr, nullptr }
+};
-cmCursesForm* cmCursesForm::CurrentForm = CM_NULLPTR;
+cmCursesForm* cmCursesForm::CurrentForm = nullptr;
extern "C" {
@@ -54,7 +57,8 @@ void onsig(int /*unused*/)
cbreak(); /* nl- or cr not needed */
keypad(stdscr, true); /* Use key symbols as KEY_DOWN */
refresh();
- int x, y;
+ int x;
+ int y;
getmaxyx(stdscr, y, x);
cmCursesForm::CurrentForm->Render(1, 1, x, y);
cmCursesForm::CurrentForm->UpdateStatusBar();
@@ -63,37 +67,31 @@ void onsig(int /*unused*/)
}
}
-void CMakeMessageHandler(const char* message, const char* title,
- bool& /*unused*/, void* clientData)
-{
- cmCursesForm* self = static_cast<cmCursesForm*>(clientData);
- self->AddError(message, title);
-}
-
int main(int argc, char const* const* argv)
{
+ cmSystemTools::EnsureStdPipes();
cmsys::Encoding::CommandLineArguments encoding_args =
cmsys::Encoding::CommandLineArguments::Main(argc, argv);
argc = encoding_args.argc();
argv = encoding_args.argv();
+ cmSystemTools::InitializeLibUV();
cmSystemTools::FindCMakeResources(argv[0]);
cmDocumentation doc;
doc.addCMakeStandardDocSections();
if (doc.CheckOptions(argc, argv)) {
- cmake hcm(cmake::RoleInternal);
+ cmake hcm(cmake::RoleInternal, cmState::Unknown);
hcm.SetHomeDirectory("");
hcm.SetHomeOutputDirectory("");
hcm.AddCMakePaths();
- std::vector<cmDocumentationEntry> generators;
- hcm.GetGeneratorDocumentation(generators);
+ auto generators = hcm.GetGeneratorsDocumentation();
doc.SetName("ccmake");
doc.SetSection("Name", cmDocumentationName);
doc.SetSection("Usage", cmDocumentationUsage);
if (argc == 1) {
doc.AppendSection("Usage", cmDocumentationUsageNote);
}
- doc.SetSection("Generators", generators);
+ doc.AppendSection("Generators", generators);
doc.PrependSection("Options", cmDocumentationOptions);
return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1;
}
@@ -106,7 +104,7 @@ int main(int argc, char const* const* argv)
if (strcmp(argv[j], "-debug") == 0) {
debug = true;
} else {
- args.push_back(argv[j]);
+ args.emplace_back(argv[j]);
}
}
@@ -131,7 +129,8 @@ int main(int argc, char const* const* argv)
signal(SIGWINCH, onsig);
- int x, y;
+ int x;
+ int y;
getmaxyx(stdscr, y, x);
if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) {
endwin();
@@ -154,7 +153,10 @@ int main(int argc, char const* const* argv)
return 1;
}
- cmSystemTools::SetMessageCallback(CMakeMessageHandler, myform);
+ cmSystemTools::SetMessageCallback(
+ [myform](const std::string& message, const char* title) {
+ myform->AddError(message, title);
+ });
cmCursesForm::CurrentForm = myform;
@@ -169,7 +171,7 @@ int main(int argc, char const* const* argv)
touchwin(stdscr);
endwin();
delete cmCursesForm::CurrentForm;
- cmCursesForm::CurrentForm = CM_NULLPTR;
+ cmCursesForm::CurrentForm = nullptr;
std::cout << std::endl << std::endl;
diff --git a/Source/CursesDialog/cmCursesBoolWidget.cxx b/Source/CursesDialog/cmCursesBoolWidget.cxx
index 80a5b5b9c..97b081128 100644
--- a/Source/CursesDialog/cmCursesBoolWidget.cxx
+++ b/Source/CursesDialog/cmCursesBoolWidget.cxx
@@ -2,11 +2,11 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesBoolWidget.h"
+#include <string>
+
#include "cmCursesWidget.h"
#include "cmStateTypes.h"
-#include <string>
-
cmCursesBoolWidget::cmCursesBoolWidget(int width, int height, int left,
int top)
: cmCursesWidget(width, height, left, top)
diff --git a/Source/CursesDialog/cmCursesBoolWidget.h b/Source/CursesDialog/cmCursesBoolWidget.h
index 90bcc2209..8c9625635 100644
--- a/Source/CursesDialog/cmCursesBoolWidget.h
+++ b/Source/CursesDialog/cmCursesBoolWidget.h
@@ -3,7 +3,7 @@
#ifndef cmCursesBoolWidget_h
#define cmCursesBoolWidget_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include "cmCursesStandardIncludes.h"
#include "cmCursesWidget.h"
@@ -12,16 +12,17 @@ class cmCursesMainForm;
class cmCursesBoolWidget : public cmCursesWidget
{
- CM_DISABLE_COPY(cmCursesBoolWidget)
-
public:
cmCursesBoolWidget(int width, int height, int left, int top);
+ cmCursesBoolWidget(cmCursesBoolWidget const&) = delete;
+ cmCursesBoolWidget& operator=(cmCursesBoolWidget const&) = delete;
+
// Description:
// Handle user input. Called by the container of this widget
// when this widget has focus. Returns true if the input was
// handled.
- bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE;
+ bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) override;
// Description:
// Set/Get the value (on/off).
diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
index d071c9178..4d3131b07 100644
--- a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
+++ b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
@@ -2,6 +2,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesCacheEntryComposite.h"
+#include <cassert>
+#include <utility>
+#include <vector>
+
+#include <cm/memory>
+
#include "cmCursesBoolWidget.h"
#include "cmCursesFilePathWidget.h"
#include "cmCursesLabelWidget.h"
@@ -11,11 +17,8 @@
#include "cmCursesWidget.h"
#include "cmState.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmake.h"
-
-#include <assert.h>
-#include <vector>
cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
const std::string& key, int labelwidth, int entrywidth)
@@ -23,68 +26,70 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
, LabelWidth(labelwidth)
, EntryWidth(entrywidth)
{
- this->Label = new cmCursesLabelWidget(this->LabelWidth, 1, 1, 1, key);
- this->IsNewLabel = new cmCursesLabelWidget(1, 1, 1, 1, " ");
- this->Entry = CM_NULLPTR;
- this->Entry = new cmCursesStringWidget(this->EntryWidth, 1, 1, 1);
+ this->Label =
+ cm::make_unique<cmCursesLabelWidget>(this->LabelWidth, 1, 1, 1, key);
+ this->IsNewLabel = cm::make_unique<cmCursesLabelWidget>(1, 1, 1, 1, " ");
+ this->Entry =
+ cm::make_unique<cmCursesStringWidget>(this->EntryWidth, 1, 1, 1);
}
cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
- const std::string& key, cmake* cm, bool isNew, int labelwidth,
+ const std::string& key, cmState* state, bool isNew, int labelwidth,
int entrywidth)
: Key(key)
, LabelWidth(labelwidth)
, EntryWidth(entrywidth)
{
- this->Label = new cmCursesLabelWidget(this->LabelWidth, 1, 1, 1, key);
+ this->Label =
+ cm::make_unique<cmCursesLabelWidget>(this->LabelWidth, 1, 1, 1, key);
if (isNew) {
- this->IsNewLabel = new cmCursesLabelWidget(1, 1, 1, 1, "*");
+ this->IsNewLabel = cm::make_unique<cmCursesLabelWidget>(1, 1, 1, 1, "*");
} else {
- this->IsNewLabel = new cmCursesLabelWidget(1, 1, 1, 1, " ");
+ this->IsNewLabel = cm::make_unique<cmCursesLabelWidget>(1, 1, 1, 1, " ");
}
- this->Entry = CM_NULLPTR;
- const char* value = cm->GetState()->GetCacheEntryValue(key);
+ const char* value = state->GetCacheEntryValue(key);
assert(value);
- switch (cm->GetState()->GetCacheEntryType(key)) {
- case cmStateEnums::BOOL:
- this->Entry = new cmCursesBoolWidget(this->EntryWidth, 1, 1, 1);
- if (cmSystemTools::IsOn(value)) {
- static_cast<cmCursesBoolWidget*>(this->Entry)->SetValueAsBool(true);
- } else {
- static_cast<cmCursesBoolWidget*>(this->Entry)->SetValueAsBool(false);
- }
+ switch (state->GetCacheEntryType(key)) {
+ case cmStateEnums::BOOL: {
+ auto bw = cm::make_unique<cmCursesBoolWidget>(this->EntryWidth, 1, 1, 1);
+ bw->SetValueAsBool(cmIsOn(value));
+ this->Entry = std::move(bw);
break;
- case cmStateEnums::PATH:
- this->Entry = new cmCursesPathWidget(this->EntryWidth, 1, 1, 1);
- static_cast<cmCursesPathWidget*>(this->Entry)->SetString(value);
+ }
+ case cmStateEnums::PATH: {
+ auto pw = cm::make_unique<cmCursesPathWidget>(this->EntryWidth, 1, 1, 1);
+ pw->SetString(value);
+ this->Entry = std::move(pw);
break;
- case cmStateEnums::FILEPATH:
- this->Entry = new cmCursesFilePathWidget(this->EntryWidth, 1, 1, 1);
- static_cast<cmCursesFilePathWidget*>(this->Entry)->SetString(value);
+ }
+ case cmStateEnums::FILEPATH: {
+ auto fpw =
+ cm::make_unique<cmCursesFilePathWidget>(this->EntryWidth, 1, 1, 1);
+ fpw->SetString(value);
+ this->Entry = std::move(fpw);
break;
+ }
case cmStateEnums::STRING: {
- const char* stringsProp =
- cm->GetState()->GetCacheEntryProperty(key, "STRINGS");
+ const char* stringsProp = state->GetCacheEntryProperty(key, "STRINGS");
if (stringsProp) {
- cmCursesOptionsWidget* ow =
- new cmCursesOptionsWidget(this->EntryWidth, 1, 1, 1);
- this->Entry = ow;
- std::vector<std::string> options;
- cmSystemTools::ExpandListArgument(stringsProp, options);
- for (std::vector<std::string>::iterator si = options.begin();
- si != options.end(); ++si) {
- ow->AddOption(*si);
+ auto ow =
+ cm::make_unique<cmCursesOptionsWidget>(this->EntryWidth, 1, 1, 1);
+ for (std::string const& opt : cmExpandedList(stringsProp)) {
+ ow->AddOption(opt);
}
ow->SetOption(value);
+ this->Entry = std::move(ow);
} else {
- this->Entry = new cmCursesStringWidget(this->EntryWidth, 1, 1, 1);
- static_cast<cmCursesStringWidget*>(this->Entry)->SetString(value);
+ auto sw =
+ cm::make_unique<cmCursesStringWidget>(this->EntryWidth, 1, 1, 1);
+ sw->SetString(value);
+ this->Entry = std::move(sw);
}
break;
}
case cmStateEnums::UNINITIALIZED:
- cmSystemTools::Error("Found an undefined variable: ", key.c_str());
+ cmSystemTools::Error("Found an undefined variable: " + key);
break;
default:
// TODO : put warning message here
@@ -92,17 +97,12 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
}
}
-cmCursesCacheEntryComposite::~cmCursesCacheEntryComposite()
-{
- delete this->Label;
- delete this->IsNewLabel;
- delete this->Entry;
-}
+cmCursesCacheEntryComposite::~cmCursesCacheEntryComposite() = default;
const char* cmCursesCacheEntryComposite::GetValue()
{
if (this->Label) {
return this->Label->GetValue();
}
- return CM_NULLPTR;
+ return nullptr;
}
diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.h b/Source/CursesDialog/cmCursesCacheEntryComposite.h
index 3c500785d..a71136331 100644
--- a/Source/CursesDialog/cmCursesCacheEntryComposite.h
+++ b/Source/CursesDialog/cmCursesCacheEntryComposite.h
@@ -3,32 +3,40 @@
#ifndef cmCursesCacheEntryComposite_h
#define cmCursesCacheEntryComposite_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+#include <memory>
#include <string>
class cmCursesLabelWidget;
class cmCursesWidget;
-class cmake;
+class cmState;
class cmCursesCacheEntryComposite
{
- CM_DISABLE_COPY(cmCursesCacheEntryComposite)
-
public:
cmCursesCacheEntryComposite(const std::string& key, int labelwidth,
int entrywidth);
- cmCursesCacheEntryComposite(const std::string& key, cmake* cm, bool isNew,
- int labelwidth, int entrywidth);
+ cmCursesCacheEntryComposite(const std::string& key, cmState* state,
+ bool isNew, int labelwidth, int entrywidth);
~cmCursesCacheEntryComposite();
+
+ cmCursesCacheEntryComposite(cmCursesCacheEntryComposite const&) = delete;
+ cmCursesCacheEntryComposite& operator=(cmCursesCacheEntryComposite const&) =
+ delete;
+
+ cmCursesCacheEntryComposite(cmCursesCacheEntryComposite&&) = default;
+ cmCursesCacheEntryComposite& operator=(cmCursesCacheEntryComposite&&) =
+ default;
+
const char* GetValue();
friend class cmCursesMainForm;
protected:
- cmCursesLabelWidget* Label;
- cmCursesLabelWidget* IsNewLabel;
- cmCursesWidget* Entry;
+ std::unique_ptr<cmCursesLabelWidget> Label;
+ std::unique_ptr<cmCursesLabelWidget> IsNewLabel;
+ std::unique_ptr<cmCursesWidget> Entry;
std::string Key;
int LabelWidth;
int EntryWidth;
diff --git a/Source/CursesDialog/cmCursesDummyWidget.h b/Source/CursesDialog/cmCursesDummyWidget.h
index d9bb6babc..07b7288ab 100644
--- a/Source/CursesDialog/cmCursesDummyWidget.h
+++ b/Source/CursesDialog/cmCursesDummyWidget.h
@@ -3,7 +3,7 @@
#ifndef cmCursesDummyWidget_h
#define cmCursesDummyWidget_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include "cmCursesStandardIncludes.h"
#include "cmCursesWidget.h"
@@ -12,16 +12,17 @@ class cmCursesMainForm;
class cmCursesDummyWidget : public cmCursesWidget
{
- CM_DISABLE_COPY(cmCursesDummyWidget)
-
public:
cmCursesDummyWidget(int width, int height, int left, int top);
+ cmCursesDummyWidget(cmCursesDummyWidget const&) = delete;
+ cmCursesDummyWidget& operator=(cmCursesDummyWidget const&) = delete;
+
// Description:
// Handle user input. Called by the container of this widget
// when this widget has focus. Returns true if the input was
// handled.
- bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE;
+ bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) override;
};
#endif // cmCursesDummyWidget_h
diff --git a/Source/CursesDialog/cmCursesFilePathWidget.h b/Source/CursesDialog/cmCursesFilePathWidget.h
index 6ad535b99..3f71259d5 100644
--- a/Source/CursesDialog/cmCursesFilePathWidget.h
+++ b/Source/CursesDialog/cmCursesFilePathWidget.h
@@ -3,16 +3,17 @@
#ifndef cmCursesFilePathWidget_h
#define cmCursesFilePathWidget_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include "cmCursesPathWidget.h"
class cmCursesFilePathWidget : public cmCursesPathWidget
{
- CM_DISABLE_COPY(cmCursesFilePathWidget)
-
public:
cmCursesFilePathWidget(int width, int height, int left, int top);
+
+ cmCursesFilePathWidget(cmCursesFilePathWidget const&) = delete;
+ cmCursesFilePathWidget& operator=(cmCursesFilePathWidget const&) = delete;
};
#endif // cmCursesFilePathWidget_h
diff --git a/Source/CursesDialog/cmCursesForm.cxx b/Source/CursesDialog/cmCursesForm.cxx
index 06c1e9c70..bd65c4a08 100644
--- a/Source/CursesDialog/cmCursesForm.cxx
+++ b/Source/CursesDialog/cmCursesForm.cxx
@@ -7,7 +7,7 @@ bool cmCursesForm::Debug = false;
cmCursesForm::cmCursesForm()
{
- this->Form = CM_NULLPTR;
+ this->Form = nullptr;
}
cmCursesForm::~cmCursesForm()
@@ -15,7 +15,7 @@ cmCursesForm::~cmCursesForm()
if (this->Form) {
unpost_form(this->Form);
free_form(this->Form);
- this->Form = CM_NULLPTR;
+ this->Form = nullptr;
}
}
diff --git a/Source/CursesDialog/cmCursesForm.h b/Source/CursesDialog/cmCursesForm.h
index 553105c76..e3626e66a 100644
--- a/Source/CursesDialog/cmCursesForm.h
+++ b/Source/CursesDialog/cmCursesForm.h
@@ -3,20 +3,23 @@
#ifndef cmCursesForm_h
#define cmCursesForm_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmCursesStandardIncludes.h"
+#include <string>
#include "cmsys/FStream.hxx"
+#include "cmCursesStandardIncludes.h"
+
class cmCursesForm
{
- CM_DISABLE_COPY(cmCursesForm)
-
public:
cmCursesForm();
virtual ~cmCursesForm();
+ cmCursesForm(cmCursesForm const&) = delete;
+ cmCursesForm& operator=(cmCursesForm const&) = delete;
+
// Description:
// Handle user input.
virtual void HandleInput() = 0;
@@ -33,7 +36,7 @@ public:
// Description:
// During a CMake run, an error handle should add errors
// to be displayed afterwards.
- virtual void AddError(const char*, const char*) {}
+ virtual void AddError(const std::string&, const char*) {}
// Description:
// Turn debugging on. This will create ccmakelog.txt.
diff --git a/Source/CursesDialog/cmCursesLabelWidget.cxx b/Source/CursesDialog/cmCursesLabelWidget.cxx
index 1dfd4ce47..83aea5a2c 100644
--- a/Source/CursesDialog/cmCursesLabelWidget.cxx
+++ b/Source/CursesDialog/cmCursesLabelWidget.cxx
@@ -14,9 +14,7 @@ cmCursesLabelWidget::cmCursesLabelWidget(int width, int height, int left,
this->SetValue(name);
}
-cmCursesLabelWidget::~cmCursesLabelWidget()
-{
-}
+cmCursesLabelWidget::~cmCursesLabelWidget() = default;
bool cmCursesLabelWidget::HandleInput(int& /*key*/, cmCursesMainForm* /*fm*/,
WINDOW* /*w*/)
diff --git a/Source/CursesDialog/cmCursesLabelWidget.h b/Source/CursesDialog/cmCursesLabelWidget.h
index 267de7c8c..9e7568187 100644
--- a/Source/CursesDialog/cmCursesLabelWidget.h
+++ b/Source/CursesDialog/cmCursesLabelWidget.h
@@ -3,29 +3,30 @@
#ifndef cmCursesLabelWidget_h
#define cmCursesLabelWidget_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
#include "cmCursesStandardIncludes.h"
#include "cmCursesWidget.h"
-#include <string>
-
class cmCursesMainForm;
class cmCursesLabelWidget : public cmCursesWidget
{
- CM_DISABLE_COPY(cmCursesLabelWidget)
-
public:
cmCursesLabelWidget(int width, int height, int left, int top,
const std::string& name);
- ~cmCursesLabelWidget() CM_OVERRIDE;
+ ~cmCursesLabelWidget() override;
+
+ cmCursesLabelWidget(cmCursesLabelWidget const&) = delete;
+ cmCursesLabelWidget& operator=(cmCursesLabelWidget const&) = delete;
// Description:
// Handle user input. Called by the container of this widget
// when this widget has focus. Returns true if the input was
// handled
- bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE;
+ bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) override;
};
#endif // cmCursesLabelWidget_h
diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx
index 7fb065d30..e2d8d06b4 100644
--- a/Source/CursesDialog/cmCursesLongMessageForm.cxx
+++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx
@@ -2,14 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesLongMessageForm.h"
+#include <cstdio>
+#include <cstring>
+
#include "cmCursesForm.h"
#include "cmCursesMainForm.h"
#include "cmCursesStandardIncludes.h"
#include "cmVersion.h"
-#include <stdio.h>
-#include <string.h>
-
inline int ctrl(int z)
{
return (z & 037);
@@ -19,15 +19,14 @@ cmCursesLongMessageForm::cmCursesLongMessageForm(
std::vector<std::string> const& messages, const char* title)
{
// Append all messages into on big string
- std::vector<std::string>::const_iterator it;
- for (it = messages.begin(); it != messages.end(); it++) {
- this->Messages += (*it);
+ for (std::string const& message : messages) {
+ this->Messages += message;
// Add one blank line after each message
this->Messages += "\n\n";
}
this->Title = title;
- this->Fields[0] = CM_NULLPTR;
- this->Fields[1] = CM_NULLPTR;
+ this->Fields[0] = nullptr;
+ this->Fields[1] = nullptr;
}
cmCursesLongMessageForm::~cmCursesLongMessageForm()
@@ -39,11 +38,12 @@ cmCursesLongMessageForm::~cmCursesLongMessageForm()
void cmCursesLongMessageForm::UpdateStatusBar()
{
- int x, y;
+ int x;
+ int y;
getmaxyx(stdscr, y, x);
char bar[cmCursesMainForm::MAX_WIDTH];
- size_t size = strlen(this->Title.c_str());
+ size_t size = this->Title.size();
if (size >= cmCursesMainForm::MAX_WIDTH) {
size = cmCursesMainForm::MAX_WIDTH - 1;
}
@@ -82,7 +82,8 @@ void cmCursesLongMessageForm::UpdateStatusBar()
void cmCursesLongMessageForm::PrintKeys()
{
- int x, y;
+ int x;
+ int y;
getmaxyx(stdscr, y, x);
if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) {
return;
@@ -99,13 +100,14 @@ void cmCursesLongMessageForm::PrintKeys()
void cmCursesLongMessageForm::Render(int /*left*/, int /*top*/, int /*width*/,
int /*height*/)
{
- int x, y;
+ int x;
+ int y;
getmaxyx(stdscr, y, x);
if (this->Form) {
unpost_form(this->Form);
free_form(this->Form);
- this->Form = CM_NULLPTR;
+ this->Form = nullptr;
}
const char* msg = this->Messages.c_str();
@@ -114,7 +116,7 @@ void cmCursesLongMessageForm::Render(int /*left*/, int /*top*/, int /*width*/,
if (this->Fields[0]) {
free_field(this->Fields[0]);
- this->Fields[0] = CM_NULLPTR;
+ this->Fields[0] = nullptr;
}
this->Fields[0] = new_field(y - 6, x - 2, 1, 1, 0, 0);
diff --git a/Source/CursesDialog/cmCursesLongMessageForm.h b/Source/CursesDialog/cmCursesLongMessageForm.h
index cd8e0953a..42f9c710b 100644
--- a/Source/CursesDialog/cmCursesLongMessageForm.h
+++ b/Source/CursesDialog/cmCursesLongMessageForm.h
@@ -3,31 +3,32 @@
#ifndef cmCursesLongMessageForm_h
#define cmCursesLongMessageForm_h
-#include "cmConfigure.h"
-
-#include "cmCursesForm.h"
-#include "cmCursesStandardIncludes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
+#include "cmCursesForm.h"
+#include "cmCursesStandardIncludes.h"
+
class cmCursesLongMessageForm : public cmCursesForm
{
- CM_DISABLE_COPY(cmCursesLongMessageForm)
-
public:
cmCursesLongMessageForm(std::vector<std::string> const& messages,
const char* title);
- ~cmCursesLongMessageForm() CM_OVERRIDE;
+ ~cmCursesLongMessageForm() override;
+
+ cmCursesLongMessageForm(cmCursesLongMessageForm const&) = delete;
+ cmCursesLongMessageForm& operator=(cmCursesLongMessageForm const&) = delete;
// Description:
// Handle user input.
- void HandleInput() CM_OVERRIDE;
+ void HandleInput() override;
// Description:
// Display form. Use a window of size width x height, starting
// at top, left.
- void Render(int left, int top, int width, int height) CM_OVERRIDE;
+ void Render(int left, int top, int width, int height) override;
// Description:
// This method should normally called only by the form.
@@ -37,7 +38,7 @@ public:
// Description:
// This method should normally called only by the form.
// The only exception is during a resize.
- void UpdateStatusBar() CM_OVERRIDE;
+ void UpdateStatusBar() override;
protected:
std::string Messages;
diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx
index 026320a1f..6b71e8a10 100644
--- a/Source/CursesDialog/cmCursesMainForm.cxx
+++ b/Source/CursesDialog/cmCursesMainForm.cxx
@@ -2,7 +2,13 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesMainForm.h"
-#include "cmAlgorithms.h"
+#include <algorithm>
+#include <cstdio>
+#include <cstring>
+#include <utility>
+
+#include <cm/memory>
+
#include "cmCursesCacheEntryComposite.h"
#include "cmCursesDummyWidget.h"
#include "cmCursesForm.h"
@@ -13,44 +19,39 @@
#include "cmCursesWidget.h"
#include "cmState.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
#include "cmake.h"
-#include <stdio.h>
-#include <string.h>
-
inline int ctrl(int z)
{
return (z & 037);
}
-cmCursesMainForm::cmCursesMainForm(std::vector<std::string> const& args,
+cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args,
int initWidth)
- : Args(args)
+ : Args(std::move(args))
, InitialWidth(initWidth)
{
this->NumberOfPages = 0;
- this->Fields = CM_NULLPTR;
- this->Entries = CM_NULLPTR;
this->AdvancedMode = false;
this->NumberOfVisibleEntries = 0;
this->OkToGenerate = false;
- this->HelpMessage.push_back(
+ this->HelpMessage.emplace_back(
"Welcome to ccmake, curses based user interface for CMake.");
- this->HelpMessage.push_back("");
- this->HelpMessage.push_back(s_ConstHelpMessage);
- this->CMakeInstance = new cmake(cmake::RoleProject);
+ this->HelpMessage.emplace_back();
+ this->HelpMessage.emplace_back(s_ConstHelpMessage);
+ this->CMakeInstance =
+ cm::make_unique<cmake>(cmake::RoleProject, cmState::Project);
this->CMakeInstance->SetCMakeEditCommand(
cmSystemTools::GetCMakeCursesCommand());
// create the arguments for the cmake object
- std::string whereCMake = cmSystemTools::GetProgramPath(this->Args[0]);
- whereCMake += "/cmake";
+ std::string whereCMake =
+ cmStrCat(cmSystemTools::GetProgramPath(this->Args[0]), "/cmake");
this->Args[0] = whereCMake;
this->CMakeInstance->SetArgs(this->Args);
- this->SearchString = "";
- this->OldSearchString = "";
this->SearchMode = false;
}
@@ -59,36 +60,17 @@ cmCursesMainForm::~cmCursesMainForm()
if (this->Form) {
unpost_form(this->Form);
free_form(this->Form);
- this->Form = CM_NULLPTR;
- }
- delete[] this->Fields;
-
- // Clean-up composites
- if (this->Entries) {
- cmDeleteAll(*this->Entries);
- }
- delete this->Entries;
- if (this->CMakeInstance) {
- delete this->CMakeInstance;
- this->CMakeInstance = CM_NULLPTR;
+ this->Form = nullptr;
}
}
// See if a cache entry is in the list of entries in the ui.
bool cmCursesMainForm::LookForCacheEntry(const std::string& key)
{
- if (!this->Entries) {
- return false;
- }
-
- std::vector<cmCursesCacheEntryComposite*>::iterator it;
- for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
- if (key == (*it)->Key) {
- return true;
- }
- }
-
- return false;
+ return std::any_of(this->Entries.begin(), this->Entries.end(),
+ [&key](cmCursesCacheEntryComposite const& entry) {
+ return key == entry.Key;
+ });
}
// Create new cmCursesCacheEntryComposite entries from the cache
@@ -96,19 +78,17 @@ void cmCursesMainForm::InitializeUI()
{
// Create a vector of cmCursesCacheEntryComposite's
// which contain labels, entries and new entry markers
- std::vector<cmCursesCacheEntryComposite*>* newEntries =
- new std::vector<cmCursesCacheEntryComposite*>;
+ std::vector<cmCursesCacheEntryComposite> newEntries;
std::vector<std::string> cacheKeys =
this->CMakeInstance->GetState()->GetCacheEntryKeys();
- newEntries->reserve(cacheKeys.size());
+ newEntries.reserve(cacheKeys.size());
// Count non-internal and non-static entries
int count = 0;
- for (std::vector<std::string>::const_iterator it = cacheKeys.begin();
- it != cacheKeys.end(); ++it) {
+ for (std::string const& key : cacheKeys) {
cmStateEnums::CacheEntryType t =
- this->CMakeInstance->GetState()->GetCacheEntryType(*it);
+ this->CMakeInstance->GetState()->GetCacheEntryType(key);
if (t != cmStateEnums::INTERNAL && t != cmStateEnums::STATIC &&
t != cmStateEnums::UNINITIALIZED) {
++count;
@@ -117,58 +97,49 @@ void cmCursesMainForm::InitializeUI()
int entrywidth = this->InitialWidth - 35;
- cmCursesCacheEntryComposite* comp;
if (count == 0) {
// If cache is empty, display a label saying so and a
// dummy entry widget (does not respond to input)
- comp = new cmCursesCacheEntryComposite("EMPTY CACHE", 30, 30);
- comp->Entry = new cmCursesDummyWidget(1, 1, 1, 1);
- newEntries->push_back(comp);
+ cmCursesCacheEntryComposite comp("EMPTY CACHE", 30, 30);
+ comp.Entry = cm::make_unique<cmCursesDummyWidget>(1, 1, 1, 1);
+ newEntries.emplace_back(std::move(comp));
} else {
// Create the composites.
// First add entries which are new
- for (std::vector<std::string>::const_iterator it = cacheKeys.begin();
- it != cacheKeys.end(); ++it) {
- std::string key = *it;
+ for (std::string const& key : cacheKeys) {
cmStateEnums::CacheEntryType t =
- this->CMakeInstance->GetState()->GetCacheEntryType(*it);
+ this->CMakeInstance->GetState()->GetCacheEntryType(key);
if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC ||
t == cmStateEnums::UNINITIALIZED) {
continue;
}
if (!this->LookForCacheEntry(key)) {
- newEntries->push_back(new cmCursesCacheEntryComposite(
- key, this->CMakeInstance, true, 30, entrywidth));
+ newEntries.emplace_back(key, this->CMakeInstance->GetState(), true, 30,
+ entrywidth);
this->OkToGenerate = false;
}
}
// then add entries which are old
- for (std::vector<std::string>::const_iterator it = cacheKeys.begin();
- it != cacheKeys.end(); ++it) {
- std::string key = *it;
+ for (std::string const& key : cacheKeys) {
cmStateEnums::CacheEntryType t =
- this->CMakeInstance->GetState()->GetCacheEntryType(*it);
+ this->CMakeInstance->GetState()->GetCacheEntryType(key);
if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC ||
t == cmStateEnums::UNINITIALIZED) {
continue;
}
if (this->LookForCacheEntry(key)) {
- newEntries->push_back(new cmCursesCacheEntryComposite(
- key, this->CMakeInstance, false, 30, entrywidth));
+ newEntries.emplace_back(key, this->CMakeInstance->GetState(), false,
+ 30, entrywidth);
}
}
}
- // Clean old entries
- if (this->Entries) {
- cmDeleteAll(*this->Entries);
- }
- delete this->Entries;
- this->Entries = newEntries;
+ // Replace old entries
+ this->Entries = std::move(newEntries);
// Compute fields from composites
this->RePost();
@@ -180,21 +151,20 @@ void cmCursesMainForm::RePost()
if (this->Form) {
unpost_form(this->Form);
free_form(this->Form);
- this->Form = CM_NULLPTR;
+ this->Form = nullptr;
}
- delete[] this->Fields;
+ this->Fields.clear();
if (this->AdvancedMode) {
- this->NumberOfVisibleEntries = this->Entries->size();
+ this->NumberOfVisibleEntries = this->Entries.size();
} else {
// If normal mode, count only non-advanced entries
this->NumberOfVisibleEntries = 0;
- std::vector<cmCursesCacheEntryComposite*>::iterator it;
- for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
+ for (cmCursesCacheEntryComposite& entry : this->Entries) {
const char* existingValue =
- this->CMakeInstance->GetState()->GetCacheEntryValue((*it)->GetValue());
+ this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue());
bool advanced =
this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
- (*it)->GetValue(), "ADVANCED");
+ entry.GetValue(), "ADVANCED");
if (!existingValue || (!this->AdvancedMode && advanced)) {
continue;
}
@@ -207,39 +177,32 @@ void cmCursesMainForm::RePost()
}
// Assign the fields: 3 for each entry: label, new entry marker
// ('*' or ' ') and entry widget
- this->Fields = new FIELD*[3 * this->NumberOfVisibleEntries + 1];
- size_t cc;
- for (cc = 0; cc < 3 * this->NumberOfVisibleEntries + 1; cc++) {
- this->Fields[cc] = CM_NULLPTR;
- }
+ this->Fields.reserve(3 * this->NumberOfVisibleEntries + 1);
// Assign fields
- int j = 0;
- std::vector<cmCursesCacheEntryComposite*>::iterator it;
- for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
+ for (cmCursesCacheEntryComposite& entry : this->Entries) {
const char* existingValue =
- this->CMakeInstance->GetState()->GetCacheEntryValue((*it)->GetValue());
+ this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue());
bool advanced =
this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
- (*it)->GetValue(), "ADVANCED");
+ entry.GetValue(), "ADVANCED");
if (!existingValue || (!this->AdvancedMode && advanced)) {
continue;
}
- this->Fields[3 * j] = (*it)->Label->Field;
- this->Fields[3 * j + 1] = (*it)->IsNewLabel->Field;
- this->Fields[3 * j + 2] = (*it)->Entry->Field;
- j++;
+ this->Fields.push_back(entry.Label->Field);
+ this->Fields.push_back(entry.IsNewLabel->Field);
+ this->Fields.push_back(entry.Entry->Field);
}
// if no cache entries there should still be one dummy field
- if (j == 0) {
- it = this->Entries->begin();
- this->Fields[0] = (*it)->Label->Field;
- this->Fields[1] = (*it)->IsNewLabel->Field;
- this->Fields[2] = (*it)->Entry->Field;
+ if (this->Fields.empty()) {
+ const auto& front = this->Entries.front();
+ this->Fields.push_back(front.Label->Field);
+ this->Fields.push_back(front.IsNewLabel->Field);
+ this->Fields.push_back(front.Entry->Field);
this->NumberOfVisibleEntries = 1;
}
// Has to be null terminated.
- this->Fields[3 * this->NumberOfVisibleEntries] = CM_NULLPTR;
+ this->Fields.push_back(nullptr);
}
void cmCursesMainForm::Render(int left, int top, int width, int height)
@@ -259,7 +222,7 @@ void cmCursesMainForm::Render(int left, int top, int width, int height)
// Delete the previous form
unpost_form(this->Form);
free_form(this->Form);
- this->Form = CM_NULLPTR;
+ this->Form = nullptr;
}
// Wrong window size
@@ -272,17 +235,16 @@ void cmCursesMainForm::Render(int left, int top, int width, int height)
height -= 7;
if (this->AdvancedMode) {
- this->NumberOfVisibleEntries = this->Entries->size();
+ this->NumberOfVisibleEntries = this->Entries.size();
} else {
// If normal, display only non-advanced entries
this->NumberOfVisibleEntries = 0;
- std::vector<cmCursesCacheEntryComposite*>::iterator it;
- for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
+ for (cmCursesCacheEntryComposite& entry : this->Entries) {
const char* existingValue =
- this->CMakeInstance->GetState()->GetCacheEntryValue((*it)->GetValue());
+ this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue());
bool advanced =
this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
- (*it)->GetValue(), "ADVANCED");
+ entry.GetValue(), "ADVANCED");
if (!existingValue || (!this->AdvancedMode && advanced)) {
continue;
}
@@ -295,13 +257,12 @@ void cmCursesMainForm::Render(int left, int top, int width, int height)
if (height > 0) {
bool isNewPage;
int i = 0;
- std::vector<cmCursesCacheEntryComposite*>::iterator it;
- for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
+ for (cmCursesCacheEntryComposite& entry : this->Entries) {
const char* existingValue =
- this->CMakeInstance->GetState()->GetCacheEntryValue((*it)->GetValue());
+ this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue());
bool advanced =
this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
- (*it)->GetValue(), "ADVANCED");
+ entry.GetValue(), "ADVANCED");
if (!existingValue || (!this->AdvancedMode && advanced)) {
continue;
}
@@ -312,16 +273,16 @@ void cmCursesMainForm::Render(int left, int top, int width, int height)
if (isNewPage) {
this->NumberOfPages++;
}
- (*it)->Label->Move(left, top + row - 1, isNewPage);
- (*it)->IsNewLabel->Move(left + 32, top + row - 1, false);
- (*it)->Entry->Move(left + 33, top + row - 1, false);
- (*it)->Entry->SetPage(this->NumberOfPages);
+ entry.Label->Move(left, top + row - 1, isNewPage);
+ entry.IsNewLabel->Move(left + 32, top + row - 1, false);
+ entry.Entry->Move(left + 33, top + row - 1, false);
+ entry.Entry->SetPage(this->NumberOfPages);
i++;
}
}
// Post the form
- this->Form = new_form(this->Fields);
+ this->Form = new_form(this->Fields.data());
post_form(this->Form);
// Update toolbar
this->UpdateStatusBar();
@@ -333,7 +294,8 @@ void cmCursesMainForm::Render(int left, int top, int width, int height)
void cmCursesMainForm::PrintKeys(int process /* = 0 */)
{
- int x, y;
+ int x;
+ int y;
getmaxyx(stdscr, y, x);
if (x < cmCursesMainForm::MIN_WIDTH || x < this->InitialWidth ||
y < cmCursesMainForm::MIN_HEIGHT) {
@@ -341,23 +303,21 @@ void cmCursesMainForm::PrintKeys(int process /* = 0 */)
}
// Give the current widget (if it exists), a chance to print keys
- cmCursesWidget* cw = CM_NULLPTR;
+ cmCursesWidget* cw = nullptr;
if (this->Form) {
FIELD* currentField = current_field(this->Form);
cw = reinterpret_cast<cmCursesWidget*>(field_userptr(currentField));
}
char fmt_s[] = "%s";
- if (cw == CM_NULLPTR || !cw->PrintKeys()) {
+ if (cw == nullptr || !cw->PrintKeys()) {
char firstLine[512] = "";
char secondLine[512] = "";
char thirdLine[512] = "";
if (process) {
- const char* clearLine =
- " ";
- strcpy(firstLine, clearLine);
- strcpy(secondLine, clearLine);
- strcpy(thirdLine, clearLine);
+ memset(firstLine, ' ', 68);
+ memset(secondLine, ' ', 68);
+ memset(thirdLine, ' ', 68);
} else {
if (this->OkToGenerate) {
sprintf(firstLine,
@@ -372,15 +332,16 @@ void cmCursesMainForm::PrintKeys(int process /* = 0 */)
sprintf(thirdLine, toggleKeyInstruction,
this->AdvancedMode ? "On" : "Off");
}
- sprintf(secondLine, "Press [h] for help "
- "Press [q] to quit without generating");
+ sprintf(secondLine,
+ "Press [h] for help "
+ "Press [q] to quit without generating");
}
curses_move(y - 4, 0);
char fmt[512] =
"Press [enter] to edit option Press [d] to delete an entry";
if (process) {
- strcpy(fmt, " ");
+ memset(fmt, ' ', 57);
}
printw(fmt_s, fmt);
curses_move(y - 3, 0);
@@ -405,7 +366,8 @@ void cmCursesMainForm::PrintKeys(int process /* = 0 */)
// on the status bar. Designed for a width of 80 chars.
void cmCursesMainForm::UpdateStatusBar(const char* message)
{
- int x, y;
+ int x;
+ int y;
getmaxyx(stdscr, y, x);
// If window size is too small, display error and return
if (x < cmCursesMainForm::MIN_WIDTH || x < this->InitialWidth ||
@@ -413,9 +375,10 @@ void cmCursesMainForm::UpdateStatusBar(const char* message)
curses_clear();
curses_move(0, 0);
char fmt[] = "Window is too small. A size of at least %dx%d is required.";
- printw(fmt, (cmCursesMainForm::MIN_WIDTH < this->InitialWidth
- ? this->InitialWidth
- : cmCursesMainForm::MIN_WIDTH),
+ printw(fmt,
+ (cmCursesMainForm::MIN_WIDTH < this->InitialWidth
+ ? this->InitialWidth
+ : cmCursesMainForm::MIN_WIDTH),
cmCursesMainForm::MIN_HEIGHT);
touchwin(stdscr);
wrefresh(stdscr);
@@ -425,7 +388,7 @@ void cmCursesMainForm::UpdateStatusBar(const char* message)
// Get the key of the current entry
FIELD* cur = current_field(this->Form);
int findex = field_index(cur);
- cmCursesWidget* lbl = CM_NULLPTR;
+ cmCursesWidget* lbl = nullptr;
if (findex >= 0) {
lbl = reinterpret_cast<cmCursesWidget*>(
field_userptr(this->Fields[findex - 2]));
@@ -456,41 +419,27 @@ void cmCursesMainForm::UpdateStatusBar(const char* message)
// Join the key, help string and pad with spaces
// (or truncate) as necessary
char bar[cmCursesMainForm::MAX_WIDTH];
- size_t i, curFieldLen = strlen(curField);
+ size_t curFieldLen = strlen(curField);
size_t helpLen = strlen(help);
- size_t width;
- if (x < cmCursesMainForm::MAX_WIDTH) {
- width = x;
- } else {
- width = cmCursesMainForm::MAX_WIDTH;
- }
+ size_t width = std::min<size_t>(x, cmCursesMainForm::MAX_WIDTH);
if (message) {
curField = message;
curFieldLen = strlen(message);
+ strncpy(bar, curField, width);
if (curFieldLen < width) {
- strcpy(bar, curField);
- for (i = curFieldLen; i < width; ++i) {
- bar[i] = ' ';
- }
- } else {
- strncpy(bar, curField, width);
+ memset(bar + curFieldLen, ' ', width - curFieldLen);
}
} else {
- if (curFieldLen >= width) {
- strncpy(bar, curField, width);
- } else {
- strcpy(bar, curField);
+ strncpy(bar, curField, width);
+ if (curFieldLen < width) {
bar[curFieldLen] = ':';
bar[curFieldLen + 1] = ' ';
- if (curFieldLen + helpLen + 2 >= width) {
- strncpy(bar + curFieldLen + 2, help, width - curFieldLen - 2);
- } else {
- strcpy(bar + curFieldLen + 2, help);
- for (i = curFieldLen + helpLen + 2; i < width; ++i) {
- bar[i] = ' ';
- }
+ strncpy(bar + curFieldLen + 2, help, width - curFieldLen - 2);
+ if (curFieldLen + helpLen + 2 < width) {
+ memset(bar + curFieldLen + helpLen + 2, ' ',
+ width - (curFieldLen + helpLen + 2));
}
}
}
@@ -503,9 +452,7 @@ void cmCursesMainForm::UpdateStatusBar(const char* message)
char vertmp[128];
sprintf(vertmp, "CMake Version %s", cmVersion::GetCMakeVersion());
size_t sideSpace = (width - strlen(vertmp));
- for (i = 0; i < sideSpace; i++) {
- version[i] = ' ';
- }
+ memset(version, ' ', sideSpace);
sprintf(version + sideSpace, "%s", vertmp);
version[width] = '\0';
@@ -520,21 +467,17 @@ void cmCursesMainForm::UpdateStatusBar(const char* message)
pos_form_cursor(this->Form);
}
-void cmCursesMainForm::UpdateProgress(const char* msg, float prog, void* vp)
+void cmCursesMainForm::UpdateProgress(const std::string& msg, float prog)
{
- cmCursesMainForm* cm = static_cast<cmCursesMainForm*>(vp);
- if (!cm) {
- return;
- }
char tmp[1024];
const char* cmsg = tmp;
if (prog >= 0) {
- sprintf(tmp, "%s %i%%", msg, (int)(100 * prog));
+ sprintf(tmp, "%s %i%%", msg.c_str(), static_cast<int>(100 * prog));
} else {
- cmsg = msg;
+ cmsg = msg.c_str();
}
- cm->UpdateStatusBar(cmsg);
- cm->PrintKeys(1);
+ this->UpdateStatusBar(cmsg);
+ this->PrintKeys(1);
curses_move(1, 1);
touchwin(stdscr);
refresh();
@@ -542,7 +485,8 @@ void cmCursesMainForm::UpdateProgress(const char* msg, float prog, void* vp)
int cmCursesMainForm::Configure(int noconfigure)
{
- int xi, yi;
+ int xi;
+ int yi;
getmaxyx(stdscr, yi, xi);
curses_move(1, 1);
@@ -550,14 +494,16 @@ int cmCursesMainForm::Configure(int noconfigure)
this->PrintKeys(1);
touchwin(stdscr);
refresh();
- this->CMakeInstance->SetProgressCallback(cmCursesMainForm::UpdateProgress,
- this);
+ this->CMakeInstance->SetProgressCallback(
+ [this](const std::string& msg, float prog) {
+ this->UpdateProgress(msg, prog);
+ });
// always save the current gui values to disk
this->FillCacheManagerFromUI();
this->CMakeInstance->SaveCache(
this->CMakeInstance->GetHomeOutputDirectory());
- this->LoadCache(CM_NULLPTR);
+ this->LoadCache(nullptr);
// Get rid of previous errors
this->Errors = std::vector<std::string>();
@@ -574,7 +520,7 @@ int cmCursesMainForm::Configure(int noconfigure)
} else {
retVal = this->CMakeInstance->Configure();
}
- this->CMakeInstance->SetProgressCallback(CM_NULLPTR, CM_NULLPTR);
+ this->CMakeInstance->SetProgressCallback(nullptr);
keypad(stdscr, true); /* Use key symbols as KEY_DOWN */
@@ -583,12 +529,14 @@ int cmCursesMainForm::Configure(int noconfigure)
if (cmSystemTools::GetErrorOccuredFlag()) {
this->OkToGenerate = false;
}
- int xx, yy;
+ int xx;
+ int yy;
getmaxyx(stdscr, yy, xx);
- cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm(
- this->Errors, cmSystemTools::GetErrorOccuredFlag()
- ? "Errors occurred during the last pass."
- : "CMake produced the following output.");
+ cmCursesLongMessageForm* msgs =
+ new cmCursesLongMessageForm(this->Errors,
+ cmSystemTools::GetErrorOccuredFlag()
+ ? "Errors occurred during the last pass."
+ : "CMake produced the following output.");
// reset error condition
cmSystemTools::ResetErrorOccuredFlag();
CurrentForm = msgs;
@@ -611,7 +559,8 @@ int cmCursesMainForm::Configure(int noconfigure)
int cmCursesMainForm::Generate()
{
- int xi, yi;
+ int xi;
+ int yi;
getmaxyx(stdscr, yi, xi);
curses_move(1, 1);
@@ -619,8 +568,10 @@ int cmCursesMainForm::Generate()
this->PrintKeys(1);
touchwin(stdscr);
refresh();
- this->CMakeInstance->SetProgressCallback(cmCursesMainForm::UpdateProgress,
- this);
+ this->CMakeInstance->SetProgressCallback(
+ [this](const std::string& msg, float prog) {
+ this->UpdateProgress(msg, prog);
+ });
// Get rid of previous errors
this->Errors = std::vector<std::string>();
@@ -628,7 +579,7 @@ int cmCursesMainForm::Generate()
// run the generate process
int retVal = this->CMakeInstance->Generate();
- this->CMakeInstance->SetProgressCallback(CM_NULLPTR, CM_NULLPTR);
+ this->CMakeInstance->SetProgressCallback(nullptr);
keypad(stdscr, true); /* Use key symbols as KEY_DOWN */
if (retVal != 0 || !this->Errors.empty()) {
@@ -638,7 +589,8 @@ int cmCursesMainForm::Generate()
}
// reset error condition
cmSystemTools::ResetErrorOccuredFlag();
- int xx, yy;
+ int xx;
+ int yy;
getmaxyx(stdscr, yy, xx);
const char* title = "Messages during last pass.";
if (cmSystemTools::GetErrorOccuredFlag()) {
@@ -664,9 +616,10 @@ int cmCursesMainForm::Generate()
return 0;
}
-void cmCursesMainForm::AddError(const char* message, const char* /*unused*/)
+void cmCursesMainForm::AddError(const std::string& message,
+ const char* /*unused*/)
{
- this->Errors.push_back(message);
+ this->Errors.emplace_back(message);
}
void cmCursesMainForm::RemoveEntry(const char* value)
@@ -675,28 +628,29 @@ void cmCursesMainForm::RemoveEntry(const char* value)
return;
}
- std::vector<cmCursesCacheEntryComposite*>::iterator it;
- for (it = this->Entries->begin(); it != this->Entries->end(); ++it) {
- const char* val = (*it)->GetValue();
- if (val && !strcmp(value, val)) {
- this->CMakeInstance->UnwatchUnusedCli(value);
- this->Entries->erase(it);
- break;
- }
+ auto removeIt =
+ std::find_if(this->Entries.begin(), this->Entries.end(),
+ [value](cmCursesCacheEntryComposite& entry) -> bool {
+ const char* val = entry.GetValue();
+ return val != nullptr && !strcmp(value, val);
+ });
+
+ if (removeIt != this->Entries.end()) {
+ this->CMakeInstance->UnwatchUnusedCli(value);
+ this->Entries.erase(removeIt);
}
}
// copy from the list box to the cache manager
void cmCursesMainForm::FillCacheManagerFromUI()
{
- size_t size = this->Entries->size();
- for (size_t i = 0; i < size; i++) {
- std::string cacheKey = (*this->Entries)[i]->Key;
+ for (cmCursesCacheEntryComposite& entry : this->Entries) {
+ const std::string& cacheKey = entry.Key;
const char* existingValue =
this->CMakeInstance->GetState()->GetCacheEntryValue(cacheKey);
if (existingValue) {
std::string oldValue = existingValue;
- std::string newValue = (*this->Entries)[i]->Entry->GetValue();
+ std::string newValue = entry.Entry->GetValue();
std::string fixedOldValue;
std::string fixedNewValue;
cmStateEnums::CacheEntryType t =
@@ -723,7 +677,7 @@ void cmCursesMainForm::FixValue(cmStateEnums::CacheEntryType type,
cmSystemTools::ConvertToUnixSlashes(out);
}
if (type == cmStateEnums::BOOL) {
- if (cmSystemTools::IsOff(out.c_str())) {
+ if (cmIsOff(out)) {
out = "OFF";
} else {
out = "ON";
@@ -733,7 +687,8 @@ void cmCursesMainForm::FixValue(cmStateEnums::CacheEntryType type,
void cmCursesMainForm::HandleInput()
{
- int x = 0, y = 0;
+ int x = 0;
+ int y = 0;
if (!this->Form) {
return;
@@ -781,7 +736,7 @@ void cmCursesMainForm::HandleInput()
this->JumpToCacheEntry(this->SearchString.c_str());
this->OldSearchString = this->SearchString;
}
- this->SearchString = "";
+ this->SearchString.clear();
}
/*
else if ( key == KEY_ESCAPE )
@@ -797,7 +752,7 @@ void cmCursesMainForm::HandleInput()
}
} else if (key == ctrl('h') || key == KEY_BACKSPACE || key == KEY_DC) {
if (!this->SearchString.empty()) {
- this->SearchString.resize(this->SearchString.size() - 1);
+ this->SearchString.pop_back();
}
}
} else if (currentWidget && !this->SearchMode) {
@@ -877,7 +832,7 @@ void cmCursesMainForm::HandleInput()
cmCursesWidget* lbl = reinterpret_cast<cmCursesWidget*>(
field_userptr(this->Fields[findex - 2]));
const char* curField = lbl->GetValue();
- const char* helpString = CM_NULLPTR;
+ const char* helpString = nullptr;
const char* existingValue =
this->CMakeInstance->GetState()->GetCacheEntryValue(curField);
@@ -886,17 +841,9 @@ void cmCursesMainForm::HandleInput()
curField, "HELPSTRING");
}
if (helpString) {
- char* message = new char
- [strlen(curField) + strlen(helpString) +
- strlen(
- "Current option is: \n Help string for this option is: \n") +
- 10];
- sprintf(
- message,
- "Current option is: %s\nHelp string for this option is: %s\n",
- curField, helpString);
- this->HelpMessage[1] = message;
- delete[] message;
+ this->HelpMessage[1] =
+ cmStrCat("Current option is: ", curField, '\n',
+ "Help string for this option is: ", helpString, '\n');
} else {
this->HelpMessage[1] = "";
}
@@ -962,7 +909,7 @@ void cmCursesMainForm::HandleInput()
// (findex always corresponds to the value field)
FIELD* nextCur;
if (findex == 2) {
- nextCur = CM_NULLPTR;
+ nextCur = nullptr;
} else if (findex == 3 * this->NumberOfVisibleEntries - 1) {
nextCur = this->Fields[findex - 5];
} else {
@@ -992,17 +939,14 @@ void cmCursesMainForm::HandleInput()
if (nextCur) {
// make the next or prev. current field after deletion
- nextCur = CM_NULLPTR;
- std::vector<cmCursesCacheEntryComposite*>::iterator it;
- for (it = this->Entries->begin(); it != this->Entries->end();
- ++it) {
- if (nextVal == (*it)->Key) {
- nextCur = (*it)->Entry->Field;
- }
- }
-
- if (nextCur) {
- set_current_field(this->Form, nextCur);
+ auto nextEntryIt = std::find_if(
+ this->Entries.begin(), this->Entries.end(),
+ [&nextVal](cmCursesCacheEntryComposite const& entry) {
+ return nextVal == entry.Key;
+ });
+
+ if (nextEntryIt != this->Entries.end()) {
+ set_current_field(this->Form, nextEntryIt->Entry->Field);
}
}
}
@@ -1041,7 +985,7 @@ void cmCursesMainForm::JumpToCacheEntry(const char* astr)
int findex = start_index;
for (;;) {
if (!str.empty()) {
- cmCursesWidget* lbl = CM_NULLPTR;
+ cmCursesWidget* lbl = nullptr;
if (findex >= 0) {
lbl = reinterpret_cast<cmCursesWidget*>(
field_userptr(this->Fields[findex - 2]));
diff --git a/Source/CursesDialog/cmCursesMainForm.h b/Source/CursesDialog/cmCursesMainForm.h
index e35cf3ed7..b8769b7cf 100644
--- a/Source/CursesDialog/cmCursesMainForm.h
+++ b/Source/CursesDialog/cmCursesMainForm.h
@@ -3,17 +3,18 @@
#ifndef cmCursesMainForm_h
#define cmCursesMainForm_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "cmCursesCacheEntryComposite.h"
#include "cmCursesForm.h"
#include "cmCursesStandardIncludes.h"
#include "cmStateTypes.h"
-#include <stddef.h>
-#include <string>
-#include <vector>
-
-class cmCursesCacheEntryComposite;
class cmake;
/** \class cmCursesMainForm
@@ -23,11 +24,12 @@ class cmake;
*/
class cmCursesMainForm : public cmCursesForm
{
- CM_DISABLE_COPY(cmCursesMainForm)
-
public:
- cmCursesMainForm(std::vector<std::string> const& args, int initwidth);
- ~cmCursesMainForm() CM_OVERRIDE;
+ cmCursesMainForm(std::vector<std::string> args, int initwidth);
+ ~cmCursesMainForm() override;
+
+ cmCursesMainForm(cmCursesMainForm const&) = delete;
+ cmCursesMainForm& operator=(cmCursesMainForm const&) = delete;
/**
* Set the widgets which represent the cache entries.
@@ -37,13 +39,13 @@ public:
/**
* Handle user input.
*/
- void HandleInput() CM_OVERRIDE;
+ void HandleInput() override;
/**
* Display form. Use a window of size width x height, starting
* at top, left.
*/
- void Render(int left, int top, int width, int height) CM_OVERRIDE;
+ void Render(int left, int top, int width, int height) override;
/**
* Returns true if an entry with the given key is in the
@@ -64,7 +66,7 @@ public:
* exception is during a resize. The optional argument specifies the
* string to be displayed in the status bar.
*/
- void UpdateStatusBar() CM_OVERRIDE { this->UpdateStatusBar(CM_NULLPTR); }
+ void UpdateStatusBar() override { this->UpdateStatusBar(nullptr); }
virtual void UpdateStatusBar(const char* message);
/**
@@ -80,7 +82,7 @@ public:
* During a CMake run, an error handle should add errors
* to be displayed afterwards.
*/
- void AddError(const char* message, const char* title) CM_OVERRIDE;
+ void AddError(const std::string& message, const char* title) override;
/**
* Used to do a configure. If argument is specified, it does only the check
@@ -101,8 +103,7 @@ public:
/**
* Progress callback
*/
- static void UpdateProgressOld(const char* msg, float prog, void*);
- static void UpdateProgress(const char* msg, float prog, void*);
+ void UpdateProgress(const std::string& msg, float prog);
protected:
// Copy the cache values from the user interface to the actual
@@ -122,10 +123,10 @@ protected:
void JumpToCacheEntry(const char* str);
// Copies of cache entries stored in the user interface
- std::vector<cmCursesCacheEntryComposite*>* Entries;
+ std::vector<cmCursesCacheEntryComposite> Entries;
// Errors produced during last run of cmake
std::vector<std::string> Errors;
- // Command line argumens to be passed to cmake each time
+ // Command line arguments to be passed to cmake each time
// it is run
std::vector<std::string> Args;
// Message displayed when user presses 'h'
@@ -136,11 +137,7 @@ protected:
static const char* s_ConstHelpMessage;
// Fields displayed. Includes labels, new entry markers, entries
- FIELD** Fields;
- // Where is source of current project
- std::string WhereSource;
- // Where is cmake executable
- std::string WhereCMake;
+ std::vector<FIELD*> Fields;
// Number of entries shown (depends on mode -normal or advanced-)
size_t NumberOfVisibleEntries;
bool AdvancedMode;
@@ -150,7 +147,7 @@ protected:
int NumberOfPages;
int InitialWidth;
- cmake* CMakeInstance;
+ std::unique_ptr<cmake> CMakeInstance;
std::string SearchString;
std::string OldSearchString;
diff --git a/Source/CursesDialog/cmCursesOptionsWidget.cxx b/Source/CursesDialog/cmCursesOptionsWidget.cxx
index d26a98f86..eb773ad0f 100644
--- a/Source/CursesDialog/cmCursesOptionsWidget.cxx
+++ b/Source/CursesDialog/cmCursesOptionsWidget.cxx
@@ -23,6 +23,9 @@ cmCursesOptionsWidget::cmCursesOptionsWidget(int width, int height, int left,
bool cmCursesOptionsWidget::HandleInput(int& key, cmCursesMainForm* /*fm*/,
WINDOW* w)
{
+ if (this->Options.empty()) {
+ return false;
+ }
switch (key) {
case 10: // 10 == enter
case KEY_ENTER:
@@ -75,9 +78,8 @@ void cmCursesOptionsWidget::SetOption(const std::string& value)
this->CurrentOption = 0; // default to 0 index
this->SetValue(value);
int index = 0;
- for (std::vector<std::string>::iterator i = this->Options.begin();
- i != this->Options.end(); ++i) {
- if (*i == value) {
+ for (auto const& opt : this->Options) {
+ if (opt == value) {
this->CurrentOption = index;
}
index++;
diff --git a/Source/CursesDialog/cmCursesOptionsWidget.h b/Source/CursesDialog/cmCursesOptionsWidget.h
index 7f4416f95..0de8e6407 100644
--- a/Source/CursesDialog/cmCursesOptionsWidget.h
+++ b/Source/CursesDialog/cmCursesOptionsWidget.h
@@ -3,28 +3,29 @@
#ifndef cmCursesOptionsWidget_h
#define cmCursesOptionsWidget_h
-#include "cmConfigure.h"
-
-#include "cmCursesStandardIncludes.h"
-#include "cmCursesWidget.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
+#include "cmCursesStandardIncludes.h"
+#include "cmCursesWidget.h"
+
class cmCursesMainForm;
class cmCursesOptionsWidget : public cmCursesWidget
{
- CM_DISABLE_COPY(cmCursesOptionsWidget)
-
public:
cmCursesOptionsWidget(int width, int height, int left, int top);
+ cmCursesOptionsWidget(cmCursesOptionsWidget const&) = delete;
+ cmCursesOptionsWidget& operator=(cmCursesOptionsWidget const&) = delete;
+
// Description:
// Handle user input. Called by the container of this widget
// when this widget has focus. Returns true if the input was
// handled.
- bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE;
+ bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) override;
void SetOption(const std::string&);
void AddOption(std::string const&);
void NextOption();
diff --git a/Source/CursesDialog/cmCursesPathWidget.cxx b/Source/CursesDialog/cmCursesPathWidget.cxx
index 05c3279c3..bb3808e89 100644
--- a/Source/CursesDialog/cmCursesPathWidget.cxx
+++ b/Source/CursesDialog/cmCursesPathWidget.cxx
@@ -2,13 +2,13 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesPathWidget.h"
+#include <vector>
+
#include "cmCursesMainForm.h"
#include "cmCursesStringWidget.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
-#include <vector>
-
cmCursesPathWidget::cmCursesPathWidget(int width, int height, int left,
int top)
: cmCursesStringWidget(width, height, left, top)
diff --git a/Source/CursesDialog/cmCursesPathWidget.h b/Source/CursesDialog/cmCursesPathWidget.h
index ae6c16d02..fb365e9c5 100644
--- a/Source/CursesDialog/cmCursesPathWidget.h
+++ b/Source/CursesDialog/cmCursesPathWidget.h
@@ -3,29 +3,30 @@
#ifndef cmCursesPathWidget_h
#define cmCursesPathWidget_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
#include "cmCursesStandardIncludes.h"
#include "cmCursesStringWidget.h"
-#include <string>
-
class cmCursesMainForm;
class cmCursesPathWidget : public cmCursesStringWidget
{
- CM_DISABLE_COPY(cmCursesPathWidget)
-
public:
cmCursesPathWidget(int width, int height, int left, int top);
+ cmCursesPathWidget(cmCursesPathWidget const&) = delete;
+ cmCursesPathWidget& operator=(cmCursesPathWidget const&) = delete;
+
/**
* This method is called when different keys are pressed. The
* subclass can have a special implementation handler for this.
*/
- void OnTab(cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE;
- void OnReturn(cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE;
- void OnType(int& key, cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE;
+ void OnTab(cmCursesMainForm* fm, WINDOW* w) override;
+ void OnReturn(cmCursesMainForm* fm, WINDOW* w) override;
+ void OnType(int& key, cmCursesMainForm* fm, WINDOW* w) override;
protected:
std::string LastString;
diff --git a/Source/CursesDialog/cmCursesStandardIncludes.h b/Source/CursesDialog/cmCursesStandardIncludes.h
index 5c5950483..5b0ad5824 100644
--- a/Source/CursesDialog/cmCursesStandardIncludes.h
+++ b/Source/CursesDialog/cmCursesStandardIncludes.h
@@ -3,11 +3,16 @@
#ifndef cmCursesStandardIncludes_h
#define cmCursesStandardIncludes_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+// Record whether __attribute__ is currently defined. See purpose below.
+#ifndef __attribute__
+# define cm_no__attribute__
+#endif
#if defined(__hpux)
-#define _BOOL_DEFINED
-#include <sys/time.h>
+# define _BOOL_DEFINED
+# include <sys/time.h>
#endif
#include <form.h>
@@ -29,4 +34,12 @@ inline void curses_clear()
#undef erase
#undef clear
+// The curses headers on some platforms (e.g. Solaris) may
+// define __attribute__ as a macro. This breaks C++ headers
+// in some cases, so undefine it now.
+#if defined(cm_no__attribute__) && defined(__attribute__)
+# undef __attribute__
+#endif
+#undef cm_no__attribute__
+
#endif // cmCursesStandardIncludes_h
diff --git a/Source/CursesDialog/cmCursesStringWidget.cxx b/Source/CursesDialog/cmCursesStringWidget.cxx
index ff189f01e..6296af20b 100644
--- a/Source/CursesDialog/cmCursesStringWidget.cxx
+++ b/Source/CursesDialog/cmCursesStringWidget.cxx
@@ -2,15 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesStringWidget.h"
+#include <cstdio>
+
#include "cmCursesForm.h"
#include "cmCursesMainForm.h"
#include "cmCursesStandardIncludes.h"
#include "cmCursesWidget.h"
#include "cmStateTypes.h"
-#include <stdio.h>
-#include <string.h>
-
inline int ctrl(int z)
{
return (z & 037);
@@ -35,13 +34,13 @@ void cmCursesStringWidget::OnTab(cmCursesMainForm* /*unused*/,
void cmCursesStringWidget::OnReturn(cmCursesMainForm* fm, WINDOW* /*unused*/)
{
- FORM* form = fm->GetForm();
if (this->InEdit) {
cmCursesForm::LogMessage("String widget leaving edit.");
this->InEdit = false;
fm->PrintKeys();
- delete[] this->OriginalString;
+ this->OriginalString.clear();
// trick to force forms to update the field buffer
+ FORM* form = fm->GetForm();
form_driver(form, REQ_NEXT_FIELD);
form_driver(form, REQ_PREV_FIELD);
this->Done = true;
@@ -49,9 +48,7 @@ void cmCursesStringWidget::OnReturn(cmCursesMainForm* fm, WINDOW* /*unused*/)
cmCursesForm::LogMessage("String widget entering edit.");
this->InEdit = true;
fm->PrintKeys();
- char* buf = field_buffer(this->Field, 0);
- this->OriginalString = new char[strlen(buf) + 1];
- strcpy(this->OriginalString, buf);
+ this->OriginalString = field_buffer(this->Field, 0);
}
}
@@ -64,7 +61,8 @@ void cmCursesStringWidget::OnType(int& key, cmCursesMainForm* fm,
bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm,
WINDOW* w)
{
- int x, y;
+ int x;
+ int y;
FORM* form = fm->GetForm();
// when not in edit mode, edit mode is entered by pressing enter or i (vim
@@ -74,7 +72,7 @@ bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm,
return false;
}
- this->OriginalString = CM_NULLPTR;
+ this->OriginalString.clear();
this->Done = false;
char debugMessage[128];
@@ -112,7 +110,7 @@ bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm,
key == ctrl('p') || key == KEY_NPAGE || key == ctrl('d') ||
key == KEY_PPAGE || key == ctrl('u')) {
this->InEdit = false;
- delete[] this->OriginalString;
+ this->OriginalString.clear();
// trick to force forms to update the field buffer
form_driver(form, REQ_NEXT_FIELD);
form_driver(form, REQ_PREV_FIELD);
@@ -124,7 +122,7 @@ bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm,
this->InEdit = false;
fm->PrintKeys();
this->SetString(this->OriginalString);
- delete[] this->OriginalString;
+ this->OriginalString.clear();
touchwin(w);
wrefresh(w);
return true;
@@ -179,32 +177,26 @@ const char* cmCursesStringWidget::GetValue()
bool cmCursesStringWidget::PrintKeys()
{
- int x, y;
+ int x;
+ int y;
getmaxyx(stdscr, y, x);
if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) {
return false;
}
if (this->InEdit) {
char fmt_s[] = "%s";
- char firstLine[512];
// Clean the toolbar
- for (int i = 0; i < 512; i++) {
- firstLine[i] = ' ';
- }
- firstLine[511] = '\0';
curses_move(y - 4, 0);
- printw(fmt_s, firstLine);
- curses_move(y - 3, 0);
- printw(fmt_s, firstLine);
- curses_move(y - 2, 0);
- printw(fmt_s, firstLine);
- curses_move(y - 1, 0);
- printw(fmt_s, firstLine);
-
+ clrtoeol();
curses_move(y - 3, 0);
printw(fmt_s, "Editing option, press [enter] to confirm");
+ clrtoeol();
curses_move(y - 2, 0);
printw(fmt_s, " press [esc] to cancel");
+ clrtoeol();
+ curses_move(y - 1, 0);
+ clrtoeol();
+
return true;
}
return false;
diff --git a/Source/CursesDialog/cmCursesStringWidget.h b/Source/CursesDialog/cmCursesStringWidget.h
index 5eb33666d..ce06c6da7 100644
--- a/Source/CursesDialog/cmCursesStringWidget.h
+++ b/Source/CursesDialog/cmCursesStringWidget.h
@@ -3,13 +3,13 @@
#ifndef cmCursesStringWidget_h
#define cmCursesStringWidget_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
#include "cmCursesStandardIncludes.h"
#include "cmCursesWidget.h"
-#include <string>
-
class cmCursesMainForm;
/** \class cmCursesStringWidget
@@ -20,8 +20,6 @@ class cmCursesMainForm;
class cmCursesStringWidget : public cmCursesWidget
{
- CM_DISABLE_COPY(cmCursesStringWidget)
-
public:
cmCursesStringWidget(int width, int height, int left, int top);
@@ -30,14 +28,14 @@ public:
* when this widget has focus. Returns true if the input was
* handled.
*/
- bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) CM_OVERRIDE;
+ bool HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) override;
/**
* Set/Get the string.
*/
void SetString(const std::string& value);
const char* GetString();
- const char* GetValue() CM_OVERRIDE;
+ const char* GetValue() override;
/**
* Set/Get InEdit flag. Can be used to tell the widget to leave
@@ -59,12 +57,12 @@ public:
* in the toolbar and return true. Otherwise, return false
* and the parent widget will print.
*/
- bool PrintKeys() CM_OVERRIDE;
+ bool PrintKeys() override;
protected:
// true if the widget is in edit mode
bool InEdit;
- char* OriginalString;
+ std::string OriginalString;
bool Done;
};
diff --git a/Source/CursesDialog/cmCursesWidget.cxx b/Source/CursesDialog/cmCursesWidget.cxx
index 054f27e29..cc07411d4 100644
--- a/Source/CursesDialog/cmCursesWidget.cxx
+++ b/Source/CursesDialog/cmCursesWidget.cxx
@@ -14,7 +14,7 @@ cmCursesWidget::~cmCursesWidget()
{
if (this->Field) {
free_field(this->Field);
- this->Field = CM_NULLPTR;
+ this->Field = nullptr;
}
}
diff --git a/Source/CursesDialog/cmCursesWidget.h b/Source/CursesDialog/cmCursesWidget.h
index 3470d7096..9d03c6e42 100644
--- a/Source/CursesDialog/cmCursesWidget.h
+++ b/Source/CursesDialog/cmCursesWidget.h
@@ -3,23 +3,24 @@
#ifndef cmCursesWidget_h
#define cmCursesWidget_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
#include "cmCursesStandardIncludes.h"
#include "cmStateTypes.h"
-#include <string>
-
class cmCursesMainForm;
class cmCursesWidget
{
- CM_DISABLE_COPY(cmCursesWidget)
-
public:
cmCursesWidget(int width, int height, int left, int top);
virtual ~cmCursesWidget();
+ cmCursesWidget(cmCursesWidget const&) = delete;
+ cmCursesWidget& operator=(cmCursesWidget const&) = delete;
+
/**
* Handle user input. Called by the container of this widget
* when this widget has focus. Returns true if the input was
diff --git a/Source/CursesDialog/form/.gitattributes b/Source/CursesDialog/form/.gitattributes
index 62d728cf6..12ede74cd 100644
--- a/Source/CursesDialog/form/.gitattributes
+++ b/Source/CursesDialog/form/.gitattributes
@@ -1 +1 @@
-* -format.clang-format
+* -format.clang-format-6.0
diff --git a/Source/CursesDialog/form/CMakeLists.txt b/Source/CursesDialog/form/CMakeLists.txt
index 0677043a9..b468f5b31 100644
--- a/Source/CursesDialog/form/CMakeLists.txt
+++ b/Source/CursesDialog/form/CMakeLists.txt
@@ -3,12 +3,9 @@
project(CMAKE_FORM)
-include_regular_expression("^.*$")
-include_directories(${CURSES_INCLUDE_PATH} "${CMAKE_CURRENT_BINARY_DIR}")
-
configure_file(cmFormConfigure.h.in "${CMAKE_CURRENT_BINARY_DIR}/cmFormConfigure.h")
-set( FORM_SRCS
+add_library(cmForm
fld_arg.c
fld_attr.c
fld_current.c
@@ -49,10 +46,16 @@ set( FORM_SRCS
fty_num.c
fty_regex.c
)
-
-include_directories(${CMAKE_FORM_SOURCE_DIR})
-add_library(cmForm ${FORM_SRCS} )
+
+target_include_directories(cmForm
+ PUBLIC
+ ${CURSES_INCLUDE_PATH}
+ ${CMAKE_FORM_BINARY_DIR}
+ ${CMAKE_FORM_SOURCE_DIR}
+ )
+
target_link_libraries(cmForm ${CURSES_LIBRARY})
+
if(CURSES_EXTRA_LIBRARY)
target_link_libraries(cmForm ${CURSES_EXTRA_LIBRARY})
endif()
diff --git a/Source/CursesDialog/form/frm_post.c b/Source/CursesDialog/form/frm_post.c
index 924fe6a9e..fc0a35946 100644
--- a/Source/CursesDialog/form/frm_post.c
+++ b/Source/CursesDialog/form/frm_post.c
@@ -67,7 +67,7 @@ int post_form(FORM * form)
if ((form->cols > width) || (form->rows > height))
RETURN(E_NO_ROOM);
- /* reset form->curpage to an invald value. This forces Set_Form_Page
+ /* reset form->curpage to an invalid value. This forces Set_Form_Page
to do the page initialization which is required by post_form.
*/
page = form->curpage;
diff --git a/Source/LexerParser/.gitattributes b/Source/LexerParser/.gitattributes
index 47eedfb4b..bf7024978 100644
--- a/Source/LexerParser/.gitattributes
+++ b/Source/LexerParser/.gitattributes
@@ -2,6 +2,8 @@
/cmCommandArgumentLexer.h generated
/cmCommandArgumentParser.cxx generated
/cmCommandArgumentParserTokens.h generated
+/cmCTestResourceGroupsLexer.cxx generated
+/cmCTestResourceGroupsLexer.h generated
/cmDependsJavaLexer.cxx generated
/cmDependsJavaLexer.h generated
/cmDependsJavaParser.cxx generated
diff --git a/Source/LexerParser/cmCTestResourceGroupsLexer.cxx b/Source/LexerParser/cmCTestResourceGroupsLexer.cxx
new file mode 100644
index 000000000..de07c4693
--- /dev/null
+++ b/Source/LexerParser/cmCTestResourceGroupsLexer.cxx
@@ -0,0 +1,2224 @@
+#include "cmStandardLexer.h"
+
+#define FLEXINT_H 1
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 4
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+#ifdef yy_create_buffer
+#define cmCTestResourceGroups_yy_create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer cmCTestResourceGroups_yy_create_buffer
+#endif
+
+#ifdef yy_delete_buffer
+#define cmCTestResourceGroups_yy_delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer cmCTestResourceGroups_yy_delete_buffer
+#endif
+
+#ifdef yy_scan_buffer
+#define cmCTestResourceGroups_yy_scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer cmCTestResourceGroups_yy_scan_buffer
+#endif
+
+#ifdef yy_scan_string
+#define cmCTestResourceGroups_yy_scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string cmCTestResourceGroups_yy_scan_string
+#endif
+
+#ifdef yy_scan_bytes
+#define cmCTestResourceGroups_yy_scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes cmCTestResourceGroups_yy_scan_bytes
+#endif
+
+#ifdef yy_init_buffer
+#define cmCTestResourceGroups_yy_init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer cmCTestResourceGroups_yy_init_buffer
+#endif
+
+#ifdef yy_flush_buffer
+#define cmCTestResourceGroups_yy_flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer cmCTestResourceGroups_yy_flush_buffer
+#endif
+
+#ifdef yy_load_buffer_state
+#define cmCTestResourceGroups_yy_load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state cmCTestResourceGroups_yy_load_buffer_state
+#endif
+
+#ifdef yy_switch_to_buffer
+#define cmCTestResourceGroups_yy_switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer cmCTestResourceGroups_yy_switch_to_buffer
+#endif
+
+#ifdef yypush_buffer_state
+#define cmCTestResourceGroups_yypush_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state cmCTestResourceGroups_yypush_buffer_state
+#endif
+
+#ifdef yypop_buffer_state
+#define cmCTestResourceGroups_yypop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state cmCTestResourceGroups_yypop_buffer_state
+#endif
+
+#ifdef yyensure_buffer_stack
+#define cmCTestResourceGroups_yyensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack cmCTestResourceGroups_yyensure_buffer_stack
+#endif
+
+#ifdef yylex
+#define cmCTestResourceGroups_yylex_ALREADY_DEFINED
+#else
+#define yylex cmCTestResourceGroups_yylex
+#endif
+
+#ifdef yyrestart
+#define cmCTestResourceGroups_yyrestart_ALREADY_DEFINED
+#else
+#define yyrestart cmCTestResourceGroups_yyrestart
+#endif
+
+#ifdef yylex_init
+#define cmCTestResourceGroups_yylex_init_ALREADY_DEFINED
+#else
+#define yylex_init cmCTestResourceGroups_yylex_init
+#endif
+
+#ifdef yylex_init_extra
+#define cmCTestResourceGroups_yylex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra cmCTestResourceGroups_yylex_init_extra
+#endif
+
+#ifdef yylex_destroy
+#define cmCTestResourceGroups_yylex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy cmCTestResourceGroups_yylex_destroy
+#endif
+
+#ifdef yyget_debug
+#define cmCTestResourceGroups_yyget_debug_ALREADY_DEFINED
+#else
+#define yyget_debug cmCTestResourceGroups_yyget_debug
+#endif
+
+#ifdef yyset_debug
+#define cmCTestResourceGroups_yyset_debug_ALREADY_DEFINED
+#else
+#define yyset_debug cmCTestResourceGroups_yyset_debug
+#endif
+
+#ifdef yyget_extra
+#define cmCTestResourceGroups_yyget_extra_ALREADY_DEFINED
+#else
+#define yyget_extra cmCTestResourceGroups_yyget_extra
+#endif
+
+#ifdef yyset_extra
+#define cmCTestResourceGroups_yyset_extra_ALREADY_DEFINED
+#else
+#define yyset_extra cmCTestResourceGroups_yyset_extra
+#endif
+
+#ifdef yyget_in
+#define cmCTestResourceGroups_yyget_in_ALREADY_DEFINED
+#else
+#define yyget_in cmCTestResourceGroups_yyget_in
+#endif
+
+#ifdef yyset_in
+#define cmCTestResourceGroups_yyset_in_ALREADY_DEFINED
+#else
+#define yyset_in cmCTestResourceGroups_yyset_in
+#endif
+
+#ifdef yyget_out
+#define cmCTestResourceGroups_yyget_out_ALREADY_DEFINED
+#else
+#define yyget_out cmCTestResourceGroups_yyget_out
+#endif
+
+#ifdef yyset_out
+#define cmCTestResourceGroups_yyset_out_ALREADY_DEFINED
+#else
+#define yyset_out cmCTestResourceGroups_yyset_out
+#endif
+
+#ifdef yyget_leng
+#define cmCTestResourceGroups_yyget_leng_ALREADY_DEFINED
+#else
+#define yyget_leng cmCTestResourceGroups_yyget_leng
+#endif
+
+#ifdef yyget_text
+#define cmCTestResourceGroups_yyget_text_ALREADY_DEFINED
+#else
+#define yyget_text cmCTestResourceGroups_yyget_text
+#endif
+
+#ifdef yyget_lineno
+#define cmCTestResourceGroups_yyget_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno cmCTestResourceGroups_yyget_lineno
+#endif
+
+#ifdef yyset_lineno
+#define cmCTestResourceGroups_yyset_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno cmCTestResourceGroups_yyset_lineno
+#endif
+
+#ifdef yyget_column
+#define cmCTestResourceGroups_yyget_column_ALREADY_DEFINED
+#else
+#define yyget_column cmCTestResourceGroups_yyget_column
+#endif
+
+#ifdef yyset_column
+#define cmCTestResourceGroups_yyset_column_ALREADY_DEFINED
+#else
+#define yyset_column cmCTestResourceGroups_yyset_column
+#endif
+
+#ifdef yywrap
+#define cmCTestResourceGroups_yywrap_ALREADY_DEFINED
+#else
+#define yywrap cmCTestResourceGroups_yywrap
+#endif
+
+#ifdef yyalloc
+#define cmCTestResourceGroups_yyalloc_ALREADY_DEFINED
+#else
+#define yyalloc cmCTestResourceGroups_yyalloc
+#endif
+
+#ifdef yyrealloc
+#define cmCTestResourceGroups_yyrealloc_ALREADY_DEFINED
+#else
+#define yyrealloc cmCTestResourceGroups_yyrealloc
+#endif
+
+#ifdef yyfree
+#define cmCTestResourceGroups_yyfree_ALREADY_DEFINED
+#else
+#define yyfree cmCTestResourceGroups_yyfree
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#ifndef SIZE_MAX
+#define SIZE_MAX (~(size_t)0)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+/* begin standard C++ headers. */
+
+/* TODO: this is always defined, so inline it */
+#define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
+#else
+#define yynoreturn
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an
+ * integer in range [0..255] for use as an array index.
+ */
+#define YY_SC_TO_UI(c) ((YY_CHAR) (c))
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+ are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin , yyscanner )
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ #define YY_LESS_LINENO(n)
+ #define YY_LINENO_REWIND_TO(ptr)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = yyg->yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ int yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+ : NULL)
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void yyrestart ( FILE *input_file , yyscan_t yyscanner );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
+void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+void yypop_buffer_state ( yyscan_t yyscanner );
+
+static void yyensure_buffer_stack ( yyscan_t yyscanner );
+static void yy_load_buffer_state ( yyscan_t yyscanner );
+static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner );
+#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner)
+
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
+
+void *yyalloc ( yy_size_t , yyscan_t yyscanner );
+void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
+void yyfree ( void * , yyscan_t yyscanner );
+
+#define yy_new_buffer yy_create_buffer
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ yyensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ yyensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define cmCTestResourceGroups_yywrap(yyscanner) (/*CONSTCOND*/1)
+#define YY_SKIP_YYWRAP
+typedef flex_uint8_t YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state ( yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans ( yy_state_type current_state , yyscan_t yyscanner);
+static int yy_get_next_buffer ( yyscan_t yyscanner );
+static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yyg->yytext_ptr = yy_bp; \
+ yyleng = (int) (yy_cp - yy_bp); \
+ yyg->yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yyg->yy_c_buf_p = yy_cp;
+#define YY_NUM_RULES 8
+#define YY_END_OF_BUFFER 9
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static const flex_int16_t yy_accept[29] =
+ { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 9, 7, 2, 5, 7, 4, 6, 3,
+ 2, 5, 0, 1, 4, 6, 3, 0
+ } ;
+
+static const YY_CHAR yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 3, 1, 1, 1, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 5, 6, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 7, 1, 7, 7, 7, 7,
+
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static const YY_CHAR yy_meta[8] =
+ { 0,
+ 1, 1, 1, 2, 2, 1, 2
+ } ;
+
+static const flex_int16_t yy_base[30] =
+ { 0,
+ 0, 0, 0, 0, 7, 0, 31, 12, 17, 0,
+ 0, 0, 34, 36, 29, 26, 26, 27, 23, 24,
+ 23, 20, 20, 36, 21, 16, 13, 36, 14
+ } ;
+
+static const flex_int16_t yy_def[30] =
+ { 0,
+ 28, 1, 1, 1, 28, 5, 1, 5, 5, 9,
+ 5, 5, 28, 28, 28, 28, 29, 28, 28, 28,
+ 28, 28, 29, 28, 28, 28, 28, 0, 28
+ } ;
+
+static const flex_int16_t yy_nxt[44] =
+ { 0,
+ 14, 14, 14, 15, 14, 16, 17, 14, 14, 18,
+ 14, 14, 19, 14, 14, 23, 27, 16, 17, 14,
+ 20, 26, 14, 25, 24, 22, 21, 27, 26, 25,
+ 24, 22, 21, 28, 14, 13, 28, 28, 28, 28,
+ 28, 28, 28
+ } ;
+
+static const flex_int16_t yy_chk[44] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 5, 5, 5,
+ 5, 5, 5, 5, 8, 29, 27, 8, 8, 9,
+ 9, 26, 9, 25, 23, 22, 21, 20, 19, 18,
+ 17, 16, 15, 13, 7, 28, 28, 28, 28, 28,
+ 28, 28, 28
+ } ;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+/*
+
+This file must be translated to C++ and modified to build everywhere.
+
+Run flex >= 2.6 like this:
+
+ flex --nounistd -DFLEXINT_H --noline --header-file=cmCTestResourceGroupsLexer.h -ocmCTestResourceGroupsLexer.cxx cmCTestResourceGroupsLexer.in.l
+
+Modify cmCTestResourceGroupsLexer.cxx:
+ - remove trailing whitespace: sed -i 's/\s*$//' cmCTestResourceGroupsLexer.h cmCTestResourceGroupsLexer.cxx
+ - remove blank lines at end of file: sed -i '${/^$/d;}' cmCTestResourceGroupsLexer.h cmCTestResourceGroupsLexer.cxx
+ - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmCTestResourceGroupsLexer.cxx
+
+*/
+
+/* IWYU pragma: no_forward_declare yyguts_t */
+
+#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+
+#include "cmCTestResourceGroupsLexerHelper.h"
+
+#include <string>
+
+#include <cstddef>
+
+/*--------------------------------------------------------------------------*/
+
+#define INITIAL 0
+#define RESOURCE_GROUPS_START 1
+#define RESOURCE_GROUPS_END 2
+#define RESOURCE_START 3
+#define RESOURCE_COUNT 4
+#define RESOURCE_END 5
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+ {
+
+ /* User-defined. Not touched by flex. */
+ YY_EXTRA_TYPE yyextra_r;
+
+ /* The rest are the same as the globals declared in the non-reentrant scanner. */
+ FILE *yyin_r, *yyout_r;
+ size_t yy_buffer_stack_top; /**< index of top of stack. */
+ size_t yy_buffer_stack_max; /**< capacity of stack. */
+ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+ char yy_hold_char;
+ int yy_n_chars;
+ int yyleng_r;
+ char *yy_c_buf_p;
+ int yy_init;
+ int yy_start;
+ int yy_did_buffer_switch_on_eof;
+ int yy_start_stack_ptr;
+ int yy_start_stack_depth;
+ int *yy_start_stack;
+ yy_state_type yy_last_accepting_state;
+ char* yy_last_accepting_cpos;
+
+ int yylineno_r;
+ int yy_flex_debug_r;
+
+ char *yytext_r;
+ int yy_more_flag;
+ int yy_more_len;
+
+ }; /* end struct yyguts_t */
+
+static int yy_init_globals ( yyscan_t yyscanner );
+
+int yylex_init (yyscan_t* scanner);
+
+int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy ( yyscan_t yyscanner );
+
+int yyget_debug ( yyscan_t yyscanner );
+
+void yyset_debug ( int debug_flag , yyscan_t yyscanner );
+
+YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
+
+void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
+
+FILE *yyget_in ( yyscan_t yyscanner );
+
+void yyset_in ( FILE * _in_str , yyscan_t yyscanner );
+
+FILE *yyget_out ( yyscan_t yyscanner );
+
+void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
+
+ int yyget_leng ( yyscan_t yyscanner );
+
+char *yyget_text ( yyscan_t yyscanner );
+
+int yyget_lineno ( yyscan_t yyscanner );
+
+void yyset_lineno ( int _line_number , yyscan_t yyscanner );
+
+int yyget_column ( yyscan_t yyscanner );
+
+void yyset_column ( int _column_no , yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap ( yyscan_t yyscanner );
+#else
+extern int yywrap ( yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+
+ static void yyunput ( int c, char *buf_ptr , yyscan_t yyscanner);
+
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput ( yyscan_t yyscanner );
+#else
+static int input ( yyscan_t yyscanner );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ int n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (yyscan_t yyscanner);
+
+#define YY_DECL int yylex (yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK /*LINTED*/break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ int yy_act;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( !yyg->yy_init )
+ {
+ yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yyg->yy_start )
+ yyg->yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner);
+ }
+
+ yy_load_buffer_state( yyscanner );
+ }
+
+ {
+
+ while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yyg->yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yyg->yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yyg->yy_start;
+yy_match:
+ do
+ {
+ YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 29 )
+ yy_c = yy_meta[yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 36 );
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yyg->yy_hold_char;
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+{
+ BEGIN(RESOURCE_COUNT);
+ yyextra->SetResourceType(std::string(yytext, yyleng - 1));
+}
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+{
+ BEGIN(RESOURCE_GROUPS_END);
+ std::size_t len = yyleng;
+ yyextra->SetProcessCount(std::stoll(yytext, &len, 10));
+}
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+{
+ BEGIN(RESOURCE_END);
+ std::size_t len = yyleng;
+ yyextra->SetNeededSlots(std::stoll(yytext, &len, 10));
+ yyextra->WriteRequirement();
+}
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+{
+ BEGIN(RESOURCE_START);
+}
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+{
+ BEGIN(RESOURCE_GROUPS_START);
+}
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+{
+ BEGIN(RESOURCE_GROUPS_START);
+ yyextra->WriteProcess();
+}
+ YY_BREAK
+case YY_STATE_EOF(RESOURCE_START):
+case YY_STATE_EOF(RESOURCE_GROUPS_END):
+case YY_STATE_EOF(RESOURCE_END):
+{
+ yyextra->WriteProcess();
+ return 0;
+}
+ YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(RESOURCE_GROUPS_START):
+{
+ return 0;
+}
+ YY_BREAK
+case YY_STATE_EOF(RESOURCE_COUNT):
+{
+ return 1;
+}
+ YY_BREAK
+case 7:
+/* rule 7 can match eol */
+YY_RULE_SETUP
+{
+ return 1;
+}
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+YY_FATAL_ERROR( "flex scanner jammed" );
+ YY_BREAK
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yyg->yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yyg->yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yyg->yy_c_buf_p;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yyg->yy_did_buffer_switch_on_eof = 0;
+
+ if ( yywrap( yyscanner ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p =
+ yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yyg->yy_c_buf_p =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+ } /* end of user's declarations */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = yyg->yytext_ptr;
+ int number_to_move, i;
+ int ret_val;
+
+ if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1);
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
+
+ int yy_c_buf_p_offset =
+ (int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yyrealloc( (void *) b->yy_ch_buf,
+ (yy_size_t) (b->yy_buf_size + 2) , yyscanner );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = NULL;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ yyg->yy_n_chars, num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ if ( yyg->yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart( yyin , yyscanner);
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
+ (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ /* "- 2" to take care of EOB's */
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
+ }
+
+ yyg->yy_n_chars += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+ yy_state_type yy_current_state;
+ char *yy_cp;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_current_state = yyg->yy_start;
+
+ for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+ {
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 29 )
+ yy_c = yy_meta[yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+ int yy_is_jam;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+ char *yy_cp = yyg->yy_c_buf_p;
+
+ YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 29 )
+ yy_c = yy_meta[yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+ yy_is_jam = (yy_current_state == 28);
+
+ (void)yyg;
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_UNPUT
+
+ static void yyunput (int c, char * yy_bp , yyscan_t yyscanner)
+{
+ char *yy_cp;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_cp = yyg->yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yyg->yy_hold_char;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ int number_to_move = yyg->yy_n_chars + 2;
+ char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+ char *source =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+ yyg->yy_n_chars = (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+ yyg->yytext_ptr = yy_bp;
+ yyg->yy_hold_char = *yy_cp;
+ yyg->yy_c_buf_p = yy_cp;
+}
+
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (yyscan_t yyscanner)
+#else
+ static int input (yyscan_t yyscanner)
+#endif
+
+{
+ int c;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+ if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ /* This was really a NUL. */
+ *yyg->yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr);
+ ++yyg->yy_c_buf_p;
+
+ switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart( yyin , yyscanner);
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap( yyscanner ) )
+ return 0;
+
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput(yyscanner);
+#else
+ return input(yyscanner);
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */
+ *yyg->yy_c_buf_p = '\0'; /* preserve yytext */
+ yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void yyrestart (FILE * input_file , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! YY_CURRENT_BUFFER ){
+ yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner);
+ }
+
+ yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner);
+ yy_load_buffer_state( yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
+ */
+ yyensure_buffer_stack (yyscanner);
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ yy_load_buffer_state( yyscanner );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void yy_load_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer( b, file , yyscanner);
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * @param yyscanner The scanner object.
+ */
+ void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yyfree( (void *) b->yy_ch_buf , yyscanner );
+
+ yyfree( (void *) b , yyscanner );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
+
+{
+ int oerrno = errno;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_flush_buffer( b , yyscanner);
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+ void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ yy_load_buffer_state( yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ * @param yyscanner The scanner object.
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (new_buffer == NULL)
+ return;
+
+ yyensure_buffer_stack(yyscanner);
+
+ /* This block is copied from yy_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ yyg->yy_buffer_stack_top++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state( yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ * @param yyscanner The scanner object.
+ */
+void yypop_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner);
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if (yyg->yy_buffer_stack_top > 0)
+ --yyg->yy_buffer_stack_top;
+
+ if (YY_CURRENT_BUFFER) {
+ yy_load_buffer_state( yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (yyscan_t yyscanner)
+{
+ yy_size_t num_to_alloc;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (!yyg->yy_buffer_stack) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ yyg->yy_buffer_stack_top = 0;
+ return;
+ }
+
+ if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ yy_size_t grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
+ (yyg->yy_buffer_stack,
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ /* zero only the new slots.*/
+ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return NULL;
+
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = NULL;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer( b , yyscanner );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner)
+{
+
+ return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = (yy_size_t) (_yybytes_len + 2);
+ buf = (char *) yyalloc( n , yyscanner );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer( buf, n , yyscanner);
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+ fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = yyg->yy_hold_char; \
+ yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+ yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+ *yyg->yy_c_buf_p = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_lineno (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_column (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_in (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_out (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int yyget_leng (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *yyget_text (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param _line_number line number
+ * @param yyscanner The scanner object.
+ */
+void yyset_lineno (int _line_number , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* lineno is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ YY_FATAL_ERROR( "yyset_lineno called with no buffer" );
+
+ yylineno = _line_number;
+}
+
+/** Set the current column.
+ * @param _column_no column number
+ * @param yyscanner The scanner object.
+ */
+void yyset_column (int _column_no , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* column is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ YY_FATAL_ERROR( "yyset_column called with no buffer" );
+
+ yycolumn = _column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param _in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE * _in_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyin = _in_str ;
+}
+
+void yyset_out (FILE * _out_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyout = _out_str ;
+}
+
+int yyget_debug (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yy_flex_debug;
+}
+
+void yyset_debug (int _bdebug , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yy_flex_debug = _bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+/* User-visible API */
+
+/* yylex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+int yylex_init(yyscan_t* ptr_yy_globals)
+{
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* yylex_init_extra has the same functionality as yylex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to yyalloc in
+ * the yyextra field.
+ */
+int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals )
+{
+ struct yyguts_t dummy_yyguts;
+
+ yyset_extra (yy_user_defined, &dummy_yyguts);
+
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in
+ yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ yyset_extra (yy_user_defined, *ptr_yy_globals);
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from yylex_destroy(), so don't allocate here.
+ */
+
+ yyg->yy_buffer_stack = NULL;
+ yyg->yy_buffer_stack_top = 0;
+ yyg->yy_buffer_stack_max = 0;
+ yyg->yy_c_buf_p = NULL;
+ yyg->yy_init = 0;
+ yyg->yy_start = 0;
+
+ yyg->yy_start_stack_ptr = 0;
+ yyg->yy_start_stack_depth = 0;
+ yyg->yy_start_stack = NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
+#else
+ yyin = NULL;
+ yyout = NULL;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * yylex_init()
+ */
+ return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ yypop_buffer_state(yyscanner);
+ }
+
+ /* Destroy the stack itself. */
+ yyfree(yyg->yy_buffer_stack , yyscanner);
+ yyg->yy_buffer_stack = NULL;
+
+ /* Destroy the start condition stack. */
+ yyfree( yyg->yy_start_stack , yyscanner );
+ yyg->yy_start_stack = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * yylex() is called, initialization will occur. */
+ yy_init_globals( yyscanner);
+
+ /* Destroy the main struct (reentrant only). */
+ yyfree ( yyscanner , yyscanner );
+ yyscanner = NULL;
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+
+ int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (const char * s , yyscan_t yyscanner)
+{
+ int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *yyalloc (yy_size_t size , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+ return malloc(size);
+}
+
+void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return realloc(ptr, size);
+}
+
+void yyfree (void * ptr , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ (void)yyg;
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+/*--------------------------------------------------------------------------*/
+
+#endif /* __clang_analyzer__ */
diff --git a/Source/LexerParser/cmCTestResourceGroupsLexer.h b/Source/LexerParser/cmCTestResourceGroupsLexer.h
new file mode 100644
index 000000000..e323a5089
--- /dev/null
+++ b/Source/LexerParser/cmCTestResourceGroupsLexer.h
@@ -0,0 +1,692 @@
+#ifndef cmCTestResourceGroups_yyHEADER_H
+#define cmCTestResourceGroups_yyHEADER_H 1
+#define cmCTestResourceGroups_yyIN_HEADER 1
+
+#define FLEXINT_H 1
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 4
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+#ifdef yy_create_buffer
+#define cmCTestResourceGroups_yy_create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer cmCTestResourceGroups_yy_create_buffer
+#endif
+
+#ifdef yy_delete_buffer
+#define cmCTestResourceGroups_yy_delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer cmCTestResourceGroups_yy_delete_buffer
+#endif
+
+#ifdef yy_scan_buffer
+#define cmCTestResourceGroups_yy_scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer cmCTestResourceGroups_yy_scan_buffer
+#endif
+
+#ifdef yy_scan_string
+#define cmCTestResourceGroups_yy_scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string cmCTestResourceGroups_yy_scan_string
+#endif
+
+#ifdef yy_scan_bytes
+#define cmCTestResourceGroups_yy_scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes cmCTestResourceGroups_yy_scan_bytes
+#endif
+
+#ifdef yy_init_buffer
+#define cmCTestResourceGroups_yy_init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer cmCTestResourceGroups_yy_init_buffer
+#endif
+
+#ifdef yy_flush_buffer
+#define cmCTestResourceGroups_yy_flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer cmCTestResourceGroups_yy_flush_buffer
+#endif
+
+#ifdef yy_load_buffer_state
+#define cmCTestResourceGroups_yy_load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state cmCTestResourceGroups_yy_load_buffer_state
+#endif
+
+#ifdef yy_switch_to_buffer
+#define cmCTestResourceGroups_yy_switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer cmCTestResourceGroups_yy_switch_to_buffer
+#endif
+
+#ifdef yypush_buffer_state
+#define cmCTestResourceGroups_yypush_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state cmCTestResourceGroups_yypush_buffer_state
+#endif
+
+#ifdef yypop_buffer_state
+#define cmCTestResourceGroups_yypop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state cmCTestResourceGroups_yypop_buffer_state
+#endif
+
+#ifdef yyensure_buffer_stack
+#define cmCTestResourceGroups_yyensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack cmCTestResourceGroups_yyensure_buffer_stack
+#endif
+
+#ifdef yylex
+#define cmCTestResourceGroups_yylex_ALREADY_DEFINED
+#else
+#define yylex cmCTestResourceGroups_yylex
+#endif
+
+#ifdef yyrestart
+#define cmCTestResourceGroups_yyrestart_ALREADY_DEFINED
+#else
+#define yyrestart cmCTestResourceGroups_yyrestart
+#endif
+
+#ifdef yylex_init
+#define cmCTestResourceGroups_yylex_init_ALREADY_DEFINED
+#else
+#define yylex_init cmCTestResourceGroups_yylex_init
+#endif
+
+#ifdef yylex_init_extra
+#define cmCTestResourceGroups_yylex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra cmCTestResourceGroups_yylex_init_extra
+#endif
+
+#ifdef yylex_destroy
+#define cmCTestResourceGroups_yylex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy cmCTestResourceGroups_yylex_destroy
+#endif
+
+#ifdef yyget_debug
+#define cmCTestResourceGroups_yyget_debug_ALREADY_DEFINED
+#else
+#define yyget_debug cmCTestResourceGroups_yyget_debug
+#endif
+
+#ifdef yyset_debug
+#define cmCTestResourceGroups_yyset_debug_ALREADY_DEFINED
+#else
+#define yyset_debug cmCTestResourceGroups_yyset_debug
+#endif
+
+#ifdef yyget_extra
+#define cmCTestResourceGroups_yyget_extra_ALREADY_DEFINED
+#else
+#define yyget_extra cmCTestResourceGroups_yyget_extra
+#endif
+
+#ifdef yyset_extra
+#define cmCTestResourceGroups_yyset_extra_ALREADY_DEFINED
+#else
+#define yyset_extra cmCTestResourceGroups_yyset_extra
+#endif
+
+#ifdef yyget_in
+#define cmCTestResourceGroups_yyget_in_ALREADY_DEFINED
+#else
+#define yyget_in cmCTestResourceGroups_yyget_in
+#endif
+
+#ifdef yyset_in
+#define cmCTestResourceGroups_yyset_in_ALREADY_DEFINED
+#else
+#define yyset_in cmCTestResourceGroups_yyset_in
+#endif
+
+#ifdef yyget_out
+#define cmCTestResourceGroups_yyget_out_ALREADY_DEFINED
+#else
+#define yyget_out cmCTestResourceGroups_yyget_out
+#endif
+
+#ifdef yyset_out
+#define cmCTestResourceGroups_yyset_out_ALREADY_DEFINED
+#else
+#define yyset_out cmCTestResourceGroups_yyset_out
+#endif
+
+#ifdef yyget_leng
+#define cmCTestResourceGroups_yyget_leng_ALREADY_DEFINED
+#else
+#define yyget_leng cmCTestResourceGroups_yyget_leng
+#endif
+
+#ifdef yyget_text
+#define cmCTestResourceGroups_yyget_text_ALREADY_DEFINED
+#else
+#define yyget_text cmCTestResourceGroups_yyget_text
+#endif
+
+#ifdef yyget_lineno
+#define cmCTestResourceGroups_yyget_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno cmCTestResourceGroups_yyget_lineno
+#endif
+
+#ifdef yyset_lineno
+#define cmCTestResourceGroups_yyset_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno cmCTestResourceGroups_yyset_lineno
+#endif
+
+#ifdef yyget_column
+#define cmCTestResourceGroups_yyget_column_ALREADY_DEFINED
+#else
+#define yyget_column cmCTestResourceGroups_yyget_column
+#endif
+
+#ifdef yyset_column
+#define cmCTestResourceGroups_yyset_column_ALREADY_DEFINED
+#else
+#define yyset_column cmCTestResourceGroups_yyset_column
+#endif
+
+#ifdef yywrap
+#define cmCTestResourceGroups_yywrap_ALREADY_DEFINED
+#else
+#define yywrap cmCTestResourceGroups_yywrap
+#endif
+
+#ifdef yyalloc
+#define cmCTestResourceGroups_yyalloc_ALREADY_DEFINED
+#else
+#define yyalloc cmCTestResourceGroups_yyalloc
+#endif
+
+#ifdef yyrealloc
+#define cmCTestResourceGroups_yyrealloc_ALREADY_DEFINED
+#else
+#define yyrealloc cmCTestResourceGroups_yyrealloc
+#endif
+
+#ifdef yyfree
+#define cmCTestResourceGroups_yyfree_ALREADY_DEFINED
+#else
+#define yyfree cmCTestResourceGroups_yyfree
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#ifndef SIZE_MAX
+#define SIZE_MAX (~(size_t)0)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+/* begin standard C++ headers. */
+
+/* TODO: this is always defined, so inline it */
+#define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
+#else
+#define yynoreturn
+#endif
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+ are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ int yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+void yyrestart ( FILE *input_file , yyscan_t yyscanner );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
+void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+void yypop_buffer_state ( yyscan_t yyscanner );
+
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
+
+void *yyalloc ( yy_size_t , yyscan_t yyscanner );
+void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
+void yyfree ( void * , yyscan_t yyscanner );
+
+/* Begin user sect3 */
+
+#define cmCTestResourceGroups_yywrap(yyscanner) (/*CONSTCOND*/1)
+#define YY_SKIP_YYWRAP
+
+#define yytext_ptr yytext_r
+
+#ifdef YY_HEADER_EXPORT_START_CONDITIONS
+#define INITIAL 0
+#define RESOURCE_GROUPS_START 1
+#define RESOURCE_GROUPS_END 2
+#define RESOURCE_START 3
+#define RESOURCE_COUNT 4
+#define RESOURCE_END 5
+
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+int yylex_init (yyscan_t* scanner);
+
+int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy ( yyscan_t yyscanner );
+
+int yyget_debug ( yyscan_t yyscanner );
+
+void yyset_debug ( int debug_flag , yyscan_t yyscanner );
+
+YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
+
+void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
+
+FILE *yyget_in ( yyscan_t yyscanner );
+
+void yyset_in ( FILE * _in_str , yyscan_t yyscanner );
+
+FILE *yyget_out ( yyscan_t yyscanner );
+
+void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
+
+ int yyget_leng ( yyscan_t yyscanner );
+
+char *yyget_text ( yyscan_t yyscanner );
+
+int yyget_lineno ( yyscan_t yyscanner );
+
+void yyset_lineno ( int _line_number , yyscan_t yyscanner );
+
+int yyget_column ( yyscan_t yyscanner );
+
+void yyset_column ( int _column_no , yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap ( yyscan_t yyscanner );
+#else
+extern int yywrap ( yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (yyscan_t yyscanner);
+
+#define YY_DECL int yylex (yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+#undef YY_NEW_FILE
+#undef YY_FLUSH_BUFFER
+#undef yy_set_bol
+#undef yy_new_buffer
+#undef yy_set_interactive
+#undef YY_DO_BEFORE_ACTION
+
+#ifdef YY_DECL_IS_OURS
+#undef YY_DECL_IS_OURS
+#undef YY_DECL
+#endif
+
+#ifndef cmCTestResourceGroups_yy_create_buffer_ALREADY_DEFINED
+#undef yy_create_buffer
+#endif
+#ifndef cmCTestResourceGroups_yy_delete_buffer_ALREADY_DEFINED
+#undef yy_delete_buffer
+#endif
+#ifndef cmCTestResourceGroups_yy_scan_buffer_ALREADY_DEFINED
+#undef yy_scan_buffer
+#endif
+#ifndef cmCTestResourceGroups_yy_scan_string_ALREADY_DEFINED
+#undef yy_scan_string
+#endif
+#ifndef cmCTestResourceGroups_yy_scan_bytes_ALREADY_DEFINED
+#undef yy_scan_bytes
+#endif
+#ifndef cmCTestResourceGroups_yy_init_buffer_ALREADY_DEFINED
+#undef yy_init_buffer
+#endif
+#ifndef cmCTestResourceGroups_yy_flush_buffer_ALREADY_DEFINED
+#undef yy_flush_buffer
+#endif
+#ifndef cmCTestResourceGroups_yy_load_buffer_state_ALREADY_DEFINED
+#undef yy_load_buffer_state
+#endif
+#ifndef cmCTestResourceGroups_yy_switch_to_buffer_ALREADY_DEFINED
+#undef yy_switch_to_buffer
+#endif
+#ifndef cmCTestResourceGroups_yypush_buffer_state_ALREADY_DEFINED
+#undef yypush_buffer_state
+#endif
+#ifndef cmCTestResourceGroups_yypop_buffer_state_ALREADY_DEFINED
+#undef yypop_buffer_state
+#endif
+#ifndef cmCTestResourceGroups_yyensure_buffer_stack_ALREADY_DEFINED
+#undef yyensure_buffer_stack
+#endif
+#ifndef cmCTestResourceGroups_yylex_ALREADY_DEFINED
+#undef yylex
+#endif
+#ifndef cmCTestResourceGroups_yyrestart_ALREADY_DEFINED
+#undef yyrestart
+#endif
+#ifndef cmCTestResourceGroups_yylex_init_ALREADY_DEFINED
+#undef yylex_init
+#endif
+#ifndef cmCTestResourceGroups_yylex_init_extra_ALREADY_DEFINED
+#undef yylex_init_extra
+#endif
+#ifndef cmCTestResourceGroups_yylex_destroy_ALREADY_DEFINED
+#undef yylex_destroy
+#endif
+#ifndef cmCTestResourceGroups_yyget_debug_ALREADY_DEFINED
+#undef yyget_debug
+#endif
+#ifndef cmCTestResourceGroups_yyset_debug_ALREADY_DEFINED
+#undef yyset_debug
+#endif
+#ifndef cmCTestResourceGroups_yyget_extra_ALREADY_DEFINED
+#undef yyget_extra
+#endif
+#ifndef cmCTestResourceGroups_yyset_extra_ALREADY_DEFINED
+#undef yyset_extra
+#endif
+#ifndef cmCTestResourceGroups_yyget_in_ALREADY_DEFINED
+#undef yyget_in
+#endif
+#ifndef cmCTestResourceGroups_yyset_in_ALREADY_DEFINED
+#undef yyset_in
+#endif
+#ifndef cmCTestResourceGroups_yyget_out_ALREADY_DEFINED
+#undef yyget_out
+#endif
+#ifndef cmCTestResourceGroups_yyset_out_ALREADY_DEFINED
+#undef yyset_out
+#endif
+#ifndef cmCTestResourceGroups_yyget_leng_ALREADY_DEFINED
+#undef yyget_leng
+#endif
+#ifndef cmCTestResourceGroups_yyget_text_ALREADY_DEFINED
+#undef yyget_text
+#endif
+#ifndef cmCTestResourceGroups_yyget_lineno_ALREADY_DEFINED
+#undef yyget_lineno
+#endif
+#ifndef cmCTestResourceGroups_yyset_lineno_ALREADY_DEFINED
+#undef yyset_lineno
+#endif
+#ifndef cmCTestResourceGroups_yyget_column_ALREADY_DEFINED
+#undef yyget_column
+#endif
+#ifndef cmCTestResourceGroups_yyset_column_ALREADY_DEFINED
+#undef yyset_column
+#endif
+#ifndef cmCTestResourceGroups_yywrap_ALREADY_DEFINED
+#undef yywrap
+#endif
+#ifndef cmCTestResourceGroups_yyget_lval_ALREADY_DEFINED
+#undef yyget_lval
+#endif
+#ifndef cmCTestResourceGroups_yyset_lval_ALREADY_DEFINED
+#undef yyset_lval
+#endif
+#ifndef cmCTestResourceGroups_yyget_lloc_ALREADY_DEFINED
+#undef yyget_lloc
+#endif
+#ifndef cmCTestResourceGroups_yyset_lloc_ALREADY_DEFINED
+#undef yyset_lloc
+#endif
+#ifndef cmCTestResourceGroups_yyalloc_ALREADY_DEFINED
+#undef yyalloc
+#endif
+#ifndef cmCTestResourceGroups_yyrealloc_ALREADY_DEFINED
+#undef yyrealloc
+#endif
+#ifndef cmCTestResourceGroups_yyfree_ALREADY_DEFINED
+#undef yyfree
+#endif
+#ifndef cmCTestResourceGroups_yytext_ALREADY_DEFINED
+#undef yytext
+#endif
+#ifndef cmCTestResourceGroups_yyleng_ALREADY_DEFINED
+#undef yyleng
+#endif
+#ifndef cmCTestResourceGroups_yyin_ALREADY_DEFINED
+#undef yyin
+#endif
+#ifndef cmCTestResourceGroups_yyout_ALREADY_DEFINED
+#undef yyout
+#endif
+#ifndef cmCTestResourceGroups_yy_flex_debug_ALREADY_DEFINED
+#undef yy_flex_debug
+#endif
+#ifndef cmCTestResourceGroups_yylineno_ALREADY_DEFINED
+#undef yylineno
+#endif
+#ifndef cmCTestResourceGroups_yytables_fload_ALREADY_DEFINED
+#undef yytables_fload
+#endif
+#ifndef cmCTestResourceGroups_yytables_destroy_ALREADY_DEFINED
+#undef yytables_destroy
+#endif
+#ifndef cmCTestResourceGroups_yyTABLES_NAME_ALREADY_DEFINED
+#undef yyTABLES_NAME
+#endif
+
+#undef cmCTestResourceGroups_yyIN_HEADER
+#endif /* cmCTestResourceGroups_yyHEADER_H */
diff --git a/Source/LexerParser/cmCTestResourceGroupsLexer.in.l b/Source/LexerParser/cmCTestResourceGroupsLexer.in.l
new file mode 100644
index 000000000..2aabea48d
--- /dev/null
+++ b/Source/LexerParser/cmCTestResourceGroupsLexer.in.l
@@ -0,0 +1,102 @@
+%{
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+/*
+
+This file must be translated to C++ and modified to build everywhere.
+
+Run flex >= 2.6 like this:
+
+ flex --nounistd -DFLEXINT_H --noline --header-file=cmCTestResourceGroupsLexer.h -ocmCTestResourceGroupsLexer.cxx cmCTestResourceGroupsLexer.in.l
+
+Modify cmCTestResourceGroupsLexer.cxx:
+ - remove trailing whitespace: sed -i 's/\s*$//' cmCTestResourceGroupsLexer.h cmCTestResourceGroupsLexer.cxx
+ - remove blank lines at end of file: sed -i '${/^$/d;}' cmCTestResourceGroupsLexer.h cmCTestResourceGroupsLexer.cxx
+ - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmCTestResourceGroupsLexer.cxx
+
+*/
+
+/* IWYU pragma: no_forward_declare yyguts_t */
+
+#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+
+#include "cmCTestResourceGroupsLexerHelper.h"
+
+#include <string>
+
+#include <cstddef>
+
+/*--------------------------------------------------------------------------*/
+%}
+
+%option prefix="cmCTestResourceGroups_yy"
+
+%option reentrant
+%option noyywrap
+%option nodefault
+%pointer
+
+%s RESOURCE_GROUPS_START
+%s RESOURCE_GROUPS_END
+%s RESOURCE_START
+%s RESOURCE_COUNT
+%s RESOURCE_END
+
+NUMBER [0-9]+
+IDENTIFIER [a-z_][a-z0-9_]*
+
+%%
+
+<INITIAL,RESOURCE_GROUPS_START,RESOURCE_START>{IDENTIFIER}: {
+ BEGIN(RESOURCE_COUNT);
+ yyextra->SetResourceType(std::string(yytext, yyleng - 1));
+}
+
+<INITIAL,RESOURCE_GROUPS_START>{NUMBER} {
+ BEGIN(RESOURCE_GROUPS_END);
+ std::size_t len = yyleng;
+ yyextra->SetProcessCount(std::stoll(yytext, &len, 10));
+}
+
+<RESOURCE_COUNT>{NUMBER} {
+ BEGIN(RESOURCE_END);
+ std::size_t len = yyleng;
+ yyextra->SetNeededSlots(std::stoll(yytext, &len, 10));
+ yyextra->WriteRequirement();
+}
+
+<RESOURCE_GROUPS_END,RESOURCE_END>,+ {
+ BEGIN(RESOURCE_START);
+}
+
+<INITIAL,RESOURCE_GROUPS_START,RESOURCE_START>;+ {
+ BEGIN(RESOURCE_GROUPS_START);
+}
+
+<RESOURCE_GROUPS_END,RESOURCE_END>;+ {
+ BEGIN(RESOURCE_GROUPS_START);
+ yyextra->WriteProcess();
+}
+
+<RESOURCE_START,RESOURCE_GROUPS_END,RESOURCE_END><<EOF>> {
+ yyextra->WriteProcess();
+ return 0;
+}
+
+<INITIAL,RESOURCE_GROUPS_START><<EOF>> {
+ return 0;
+}
+
+<<EOF>> {
+ return 1;
+}
+
+.|\n {
+ return 1;
+}
+
+%%
+
+/*--------------------------------------------------------------------------*/
+
+#endif /* __clang_analyzer__ */
diff --git a/Source/LexerParser/cmCommandArgumentLexer.cxx b/Source/LexerParser/cmCommandArgumentLexer.cxx
index 12dce3758..58799123f 100644
--- a/Source/LexerParser/cmCommandArgumentLexer.cxx
+++ b/Source/LexerParser/cmCommandArgumentLexer.cxx
@@ -1,7 +1,4 @@
#include "cmStandardLexer.h"
-#line 2 "cmCommandArgumentLexer.cxx"
-
-#line 4 "cmCommandArgumentLexer.cxx"
#define FLEXINT_H 1
#define YY_INT_ALIGNED short int
@@ -11,11 +8,221 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6
-#define YY_FLEX_SUBMINOR_VERSION 1
+#define YY_FLEX_SUBMINOR_VERSION 4
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
+#ifdef yy_create_buffer
+#define cmCommandArgument_yy_create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer cmCommandArgument_yy_create_buffer
+#endif
+
+#ifdef yy_delete_buffer
+#define cmCommandArgument_yy_delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer cmCommandArgument_yy_delete_buffer
+#endif
+
+#ifdef yy_scan_buffer
+#define cmCommandArgument_yy_scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer cmCommandArgument_yy_scan_buffer
+#endif
+
+#ifdef yy_scan_string
+#define cmCommandArgument_yy_scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string cmCommandArgument_yy_scan_string
+#endif
+
+#ifdef yy_scan_bytes
+#define cmCommandArgument_yy_scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes cmCommandArgument_yy_scan_bytes
+#endif
+
+#ifdef yy_init_buffer
+#define cmCommandArgument_yy_init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer cmCommandArgument_yy_init_buffer
+#endif
+
+#ifdef yy_flush_buffer
+#define cmCommandArgument_yy_flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer cmCommandArgument_yy_flush_buffer
+#endif
+
+#ifdef yy_load_buffer_state
+#define cmCommandArgument_yy_load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state cmCommandArgument_yy_load_buffer_state
+#endif
+
+#ifdef yy_switch_to_buffer
+#define cmCommandArgument_yy_switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer cmCommandArgument_yy_switch_to_buffer
+#endif
+
+#ifdef yypush_buffer_state
+#define cmCommandArgument_yypush_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state cmCommandArgument_yypush_buffer_state
+#endif
+
+#ifdef yypop_buffer_state
+#define cmCommandArgument_yypop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state cmCommandArgument_yypop_buffer_state
+#endif
+
+#ifdef yyensure_buffer_stack
+#define cmCommandArgument_yyensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack cmCommandArgument_yyensure_buffer_stack
+#endif
+
+#ifdef yylex
+#define cmCommandArgument_yylex_ALREADY_DEFINED
+#else
+#define yylex cmCommandArgument_yylex
+#endif
+
+#ifdef yyrestart
+#define cmCommandArgument_yyrestart_ALREADY_DEFINED
+#else
+#define yyrestart cmCommandArgument_yyrestart
+#endif
+
+#ifdef yylex_init
+#define cmCommandArgument_yylex_init_ALREADY_DEFINED
+#else
+#define yylex_init cmCommandArgument_yylex_init
+#endif
+
+#ifdef yylex_init_extra
+#define cmCommandArgument_yylex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra cmCommandArgument_yylex_init_extra
+#endif
+
+#ifdef yylex_destroy
+#define cmCommandArgument_yylex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy cmCommandArgument_yylex_destroy
+#endif
+
+#ifdef yyget_debug
+#define cmCommandArgument_yyget_debug_ALREADY_DEFINED
+#else
+#define yyget_debug cmCommandArgument_yyget_debug
+#endif
+
+#ifdef yyset_debug
+#define cmCommandArgument_yyset_debug_ALREADY_DEFINED
+#else
+#define yyset_debug cmCommandArgument_yyset_debug
+#endif
+
+#ifdef yyget_extra
+#define cmCommandArgument_yyget_extra_ALREADY_DEFINED
+#else
+#define yyget_extra cmCommandArgument_yyget_extra
+#endif
+
+#ifdef yyset_extra
+#define cmCommandArgument_yyset_extra_ALREADY_DEFINED
+#else
+#define yyset_extra cmCommandArgument_yyset_extra
+#endif
+
+#ifdef yyget_in
+#define cmCommandArgument_yyget_in_ALREADY_DEFINED
+#else
+#define yyget_in cmCommandArgument_yyget_in
+#endif
+
+#ifdef yyset_in
+#define cmCommandArgument_yyset_in_ALREADY_DEFINED
+#else
+#define yyset_in cmCommandArgument_yyset_in
+#endif
+
+#ifdef yyget_out
+#define cmCommandArgument_yyget_out_ALREADY_DEFINED
+#else
+#define yyget_out cmCommandArgument_yyget_out
+#endif
+
+#ifdef yyset_out
+#define cmCommandArgument_yyset_out_ALREADY_DEFINED
+#else
+#define yyset_out cmCommandArgument_yyset_out
+#endif
+
+#ifdef yyget_leng
+#define cmCommandArgument_yyget_leng_ALREADY_DEFINED
+#else
+#define yyget_leng cmCommandArgument_yyget_leng
+#endif
+
+#ifdef yyget_text
+#define cmCommandArgument_yyget_text_ALREADY_DEFINED
+#else
+#define yyget_text cmCommandArgument_yyget_text
+#endif
+
+#ifdef yyget_lineno
+#define cmCommandArgument_yyget_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno cmCommandArgument_yyget_lineno
+#endif
+
+#ifdef yyset_lineno
+#define cmCommandArgument_yyset_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno cmCommandArgument_yyset_lineno
+#endif
+
+#ifdef yyget_column
+#define cmCommandArgument_yyget_column_ALREADY_DEFINED
+#else
+#define yyget_column cmCommandArgument_yyget_column
+#endif
+
+#ifdef yyset_column
+#define cmCommandArgument_yyset_column_ALREADY_DEFINED
+#else
+#define yyset_column cmCommandArgument_yyset_column
+#endif
+
+#ifdef yywrap
+#define cmCommandArgument_yywrap_ALREADY_DEFINED
+#else
+#define yywrap cmCommandArgument_yywrap
+#endif
+
+#ifdef yyalloc
+#define cmCommandArgument_yyalloc_ALREADY_DEFINED
+#else
+#define yyalloc cmCommandArgument_yyalloc
+#endif
+
+#ifdef yyrealloc
+#define cmCommandArgument_yyrealloc_ALREADY_DEFINED
+#else
+#define yyrealloc cmCommandArgument_yyrealloc
+#endif
+
+#ifdef yyfree
+#define cmCommandArgument_yyfree_ALREADY_DEFINED
+#else
+#define yyfree cmCommandArgument_yyfree
+#endif
+
/* First, we deal with platform-specific or compiler-specific issues. */
/* begin standard C headers. */
@@ -86,10 +293,16 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
+#ifndef SIZE_MAX
+#define SIZE_MAX (~(size_t)0)
+#endif
+
#endif /* ! C99 */
#endif /* ! FLEXINT_H */
+/* begin standard C++ headers. */
+
/* TODO: this is always defined, so inline it */
#define yyconst const
@@ -102,12 +315,10 @@ typedef unsigned int flex_uint32_t;
/* Returned upon end-of-file. */
#define YY_NULL 0
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index. If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
+/* Promotes a possibly negative, possibly signed char to an
+ * integer in range [0..255] for use as an array index.
*/
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+#define YY_SC_TO_UI(c) ((YY_CHAR) (c))
/* An opaque pointer. */
#ifndef YY_TYPEDEF_YY_SCANNER_T
@@ -131,20 +342,16 @@ typedef void* yyscan_t;
* definition of BEGIN.
*/
#define BEGIN yyg->yy_start = 1 + 2 *
-
/* Translate the current start state into a value that can be later handed
* to BEGIN to return to the state. The YYSTATE alias is for lex
* compatibility.
*/
#define YY_START ((yyg->yy_start - 1) / 2)
#define YYSTATE YY_START
-
/* Action number for EOF rule of a given start state. */
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE cmCommandArgument_yyrestart(yyin ,yyscanner )
-
+#define YY_NEW_FILE yyrestart( yyin , yyscanner )
#define YY_END_OF_BUFFER_CHAR 0
/* Size of default input buffer. */
@@ -194,7 +401,6 @@ typedef size_t yy_size_t;
YY_DO_BEFORE_ACTION; /* set up yytext again */ \
} \
while ( 0 )
-
#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
#ifndef YY_STRUCT_YY_BUFFER_STATE
@@ -254,7 +460,7 @@ struct yy_buffer_state
* possible backing-up.
*
* When we actually see the EOF, we change the status to "new"
- * (via cmCommandArgument_yyrestart()), so that the user can continue scanning by
+ * (via yyrestart()), so that the user can continue scanning by
* just pointing yyin at a new input file.
*/
#define YY_BUFFER_EOF_PENDING 2
@@ -271,73 +477,67 @@ struct yy_buffer_state
#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
: NULL)
-
/* Same as previous macro, but useful when we know that the buffer stack is not
* NULL or when we need an lvalue. For internal use only.
*/
#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
-void cmCommandArgument_yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void cmCommandArgument_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmCommandArgument_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void cmCommandArgument_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmCommandArgument_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmCommandArgument_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void cmCommandArgument_yypop_buffer_state (yyscan_t yyscanner );
-
-static void cmCommandArgument_yyensure_buffer_stack (yyscan_t yyscanner );
-static void cmCommandArgument_yy_load_buffer_state (yyscan_t yyscanner );
-static void cmCommandArgument_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+void yyrestart ( FILE *input_file , yyscan_t yyscanner );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
+void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+void yypop_buffer_state ( yyscan_t yyscanner );
-#define YY_FLUSH_BUFFER cmCommandArgument_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+static void yyensure_buffer_stack ( yyscan_t yyscanner );
+static void yy_load_buffer_state ( yyscan_t yyscanner );
+static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner );
+#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner)
-YY_BUFFER_STATE cmCommandArgument_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmCommandArgument_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmCommandArgument_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
-void *cmCommandArgument_yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *cmCommandArgument_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void cmCommandArgument_yyfree (void * ,yyscan_t yyscanner );
-
-#define yy_new_buffer cmCommandArgument_yy_create_buffer
+void *yyalloc ( yy_size_t , yyscan_t yyscanner );
+void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
+void yyfree ( void * , yyscan_t yyscanner );
+#define yy_new_buffer yy_create_buffer
#define yy_set_interactive(is_interactive) \
{ \
if ( ! YY_CURRENT_BUFFER ){ \
- cmCommandArgument_yyensure_buffer_stack (yyscanner); \
+ yyensure_buffer_stack (yyscanner); \
YY_CURRENT_BUFFER_LVALUE = \
- cmCommandArgument_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
} \
YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
}
-
#define yy_set_bol(at_bol) \
{ \
if ( ! YY_CURRENT_BUFFER ){\
- cmCommandArgument_yyensure_buffer_stack (yyscanner); \
+ yyensure_buffer_stack (yyscanner); \
YY_CURRENT_BUFFER_LVALUE = \
- cmCommandArgument_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
} \
YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
}
-
#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
/* Begin user sect3 */
#define cmCommandArgument_yywrap(yyscanner) (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
-
-typedef unsigned char YY_CHAR;
+typedef flex_uint8_t YY_CHAR;
typedef int yy_state_type;
#define yytext_ptr yytext_r
-static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
-static int yy_get_next_buffer (yyscan_t yyscanner );
-static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
+static yy_state_type yy_get_previous_state ( yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans ( yy_state_type current_state , yyscan_t yyscanner);
+static int yy_get_next_buffer ( yyscan_t yyscanner );
+static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner );
/* Done after the current pattern has been matched and before the
* corresponding action - sets up yytext.
@@ -348,7 +548,6 @@ static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
yyg->yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
-
#define YY_NUM_RULES 14
#define YY_END_OF_BUFFER 15
/* This struct is not used in this scanner,
@@ -358,14 +557,14 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[30] =
+static const flex_int16_t yy_accept[30] =
{ 0,
0, 0, 0, 0, 0, 0, 15, 9, 10, 7,
6, 14, 11, 5, 12, 13, 9, 0, 0, 4,
7, 0, 8, 2, 0, 3, 0, 1, 0
} ;
-static yyconst YY_CHAR yy_ec[256] =
+static const YY_CHAR yy_ec[256] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -397,13 +596,13 @@ static yyconst YY_CHAR yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst YY_CHAR yy_meta[12] =
+static const YY_CHAR yy_meta[12] =
{ 0,
1, 2, 3, 4, 3, 4, 4, 4, 3, 5,
3
} ;
-static yyconst flex_uint16_t yy_base[35] =
+static const flex_int16_t yy_base[35] =
{ 0,
0, 0, 31, 30, 29, 28, 36, 0, 6, 16,
0, 41, 41, 41, 0, 41, 0, 22, 22, 41,
@@ -411,7 +610,7 @@ static yyconst flex_uint16_t yy_base[35] =
21, 26, 9, 30
} ;
-static yyconst flex_int16_t yy_def[35] =
+static const flex_int16_t yy_def[35] =
{ 0,
29, 1, 1, 1, 1, 1, 29, 30, 31, 32,
33, 29, 29, 29, 34, 29, 30, 31, 18, 29,
@@ -419,7 +618,7 @@ static yyconst flex_int16_t yy_def[35] =
29, 29, 29, 29
} ;
-static yyconst flex_uint16_t yy_nxt[53] =
+static const flex_int16_t yy_nxt[53] =
{ 0,
8, 8, 9, 10, 11, 10, 10, 10, 12, 13,
14, 19, 22, 28, 27, 20, 17, 17, 17, 17,
@@ -429,7 +628,7 @@ static yyconst flex_uint16_t yy_nxt[53] =
29, 29
} ;
-static yyconst flex_int16_t yy_chk[53] =
+static const flex_int16_t yy_chk[53] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 9, 33, 27, 25, 9, 10, 10, 21, 21,
@@ -446,8 +645,6 @@ static yyconst flex_int16_t yy_chk[53] =
#define yymore() yymore_used_but_not_detected
#define YY_MORE_ADJ 0
#define YY_RESTORE_YY_MORE_OFFSET
-#line 1 "cmCommandArgumentLexer.in.l"
-#line 2 "cmCommandArgumentLexer.in.l"
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
/*
@@ -456,32 +653,37 @@ This file must be translated to C++ and modified to build everywhere.
Run flex >= 2.6 like this:
- flex --nounistd -DFLEXINT_H --prefix=cmCommandArgument_yy --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l
+ flex --nounistd -DFLEXINT_H --noline --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l
Modify cmCommandArgumentLexer.cxx:
- - remove trailing whitespace: sed -i 's/\s*$//' cmCommandArgumentLexer.h cmCommandArgumentLexer.cxx
- - remove blank lines at end of file
- - #include "cmStandardLexer.h" at the top
- - add cast in cmCommandArgument_yy_scan_bytes for loop condition of _yybytes_len to size_t
+ - remove trailing whitespace: sed -i 's/\s*$//' cmCommandArgumentLexer.h cmCommandArgumentLexer.cxx
+ - remove blank lines at end of file: sed -i '${/^$/d;}' cmCommandArgumentLexer.h cmCommandArgumentLexer.cxx
+ - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmCommandArgumentLexer.cxx
*/
/* IWYU pragma: no_forward_declare yyguts_t */
+#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+
#include "cmCommandArgumentParserHelper.h"
/* Replace the lexer input function. */
#undef YY_INPUT
#define YY_INPUT(buf, result, max_size) \
- { result = yyextra->LexInput(buf, max_size); }
+ do { result = yyextra->LexInput(buf, max_size); } while (0)
/* 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 = "\\";
-
-#line 484 "cmCommandArgumentLexer.cxx"
+/*--------------------------------------------------------------------------*/
#define INITIAL 0
#define ESCAPES 1
@@ -525,44 +727,44 @@ struct yyguts_t
}; /* end struct yyguts_t */
-static int yy_init_globals (yyscan_t yyscanner );
+static int yy_init_globals ( yyscan_t yyscanner );
-int cmCommandArgument_yylex_init (yyscan_t* scanner);
+int yylex_init (yyscan_t* scanner);
-int cmCommandArgument_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
-int cmCommandArgument_yylex_destroy (yyscan_t yyscanner );
+int yylex_destroy ( yyscan_t yyscanner );
-int cmCommandArgument_yyget_debug (yyscan_t yyscanner );
+int yyget_debug ( yyscan_t yyscanner );
-void cmCommandArgument_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+void yyset_debug ( int debug_flag , yyscan_t yyscanner );
-YY_EXTRA_TYPE cmCommandArgument_yyget_extra (yyscan_t yyscanner );
+YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
-void cmCommandArgument_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
-FILE *cmCommandArgument_yyget_in (yyscan_t yyscanner );
+FILE *yyget_in ( yyscan_t yyscanner );
-void cmCommandArgument_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
+void yyset_in ( FILE * _in_str , yyscan_t yyscanner );
-FILE *cmCommandArgument_yyget_out (yyscan_t yyscanner );
+FILE *yyget_out ( yyscan_t yyscanner );
-void cmCommandArgument_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
+void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
- int cmCommandArgument_yyget_leng (yyscan_t yyscanner );
+ int yyget_leng ( yyscan_t yyscanner );
-char *cmCommandArgument_yyget_text (yyscan_t yyscanner );
+char *yyget_text ( yyscan_t yyscanner );
-int cmCommandArgument_yyget_lineno (yyscan_t yyscanner );
+int yyget_lineno ( yyscan_t yyscanner );
-void cmCommandArgument_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+void yyset_lineno ( int _line_number , yyscan_t yyscanner );
-int cmCommandArgument_yyget_column (yyscan_t yyscanner );
+int yyget_column ( yyscan_t yyscanner );
-void cmCommandArgument_yyset_column (int _column_no ,yyscan_t yyscanner );
+void yyset_column ( int _column_no , yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -570,9 +772,9 @@ void cmCommandArgument_yyset_column (int _column_no ,yyscan_t yyscanner );
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
-extern "C" int cmCommandArgument_yywrap (yyscan_t yyscanner );
+extern "C" int yywrap ( yyscan_t yyscanner );
#else
-extern int cmCommandArgument_yywrap (yyscan_t yyscanner );
+extern int yywrap ( yyscan_t yyscanner );
#endif
#endif
@@ -581,19 +783,18 @@ extern int cmCommandArgument_yywrap (yyscan_t yyscanner );
#endif
#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
#endif
#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
#endif
#ifndef YY_NO_INPUT
-
#ifdef __cplusplus
-static int yyinput (yyscan_t yyscanner );
+static int yyinput ( yyscan_t yyscanner );
#else
-static int input (yyscan_t yyscanner );
+static int input ( yyscan_t yyscanner );
#endif
#endif
@@ -624,7 +825,7 @@ static int input (yyscan_t yyscanner );
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
- size_t n; \
+ int n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@@ -637,7 +838,7 @@ static int input (yyscan_t yyscanner );
else \
{ \
errno=0; \
- while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \
{ \
if( errno != EINTR) \
{ \
@@ -678,9 +879,9 @@ static int input (yyscan_t yyscanner );
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
-extern int cmCommandArgument_yylex (yyscan_t yyscanner);
+extern int yylex (yyscan_t yyscanner);
-#define YY_DECL int cmCommandArgument_yylex (yyscan_t yyscanner)
+#define YY_DECL int yylex (yyscan_t yyscanner)
#endif /* !YY_DECL */
/* Code executed at the beginning of each rule, after yytext and yyleng
@@ -725,19 +926,15 @@ YY_DECL
yyout = stdout;
if ( ! YY_CURRENT_BUFFER ) {
- cmCommandArgument_yyensure_buffer_stack (yyscanner);
+ yyensure_buffer_stack (yyscanner);
YY_CURRENT_BUFFER_LVALUE =
- cmCommandArgument_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner);
}
- cmCommandArgument_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
}
{
-#line 42 "cmCommandArgumentLexer.in.l"
-
-
-#line 740 "cmCommandArgumentLexer.cxx"
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
@@ -765,9 +962,9 @@ yy_match:
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 30 )
- yy_c = yy_meta[(unsigned int) yy_c];
+ yy_c = yy_meta[yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
++yy_cp;
}
while ( yy_base[yy_current_state] != 41 );
@@ -796,7 +993,6 @@ do_action: /* This label is used only to access EOF actions. */
case 1:
YY_RULE_SETUP
-#line 44 "cmCommandArgumentLexer.in.l"
{
//std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
yyextra->AllocateParserType(yylvalp, yytext+1, strlen(yytext)-2);
@@ -805,7 +1001,6 @@ YY_RULE_SETUP
YY_BREAK
case 2:
YY_RULE_SETUP
-#line 50 "cmCommandArgumentLexer.in.l"
{
//std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
yyextra->AllocateParserType(yylvalp, yytext+1, strlen(yytext)-2);
@@ -814,7 +1009,6 @@ YY_RULE_SETUP
YY_BREAK
case 3:
YY_RULE_SETUP
-#line 56 "cmCommandArgumentLexer.in.l"
{
//std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
yyextra->AllocateParserType(yylvalp, yytext+1, strlen(yytext)-2);
@@ -823,37 +1017,33 @@ YY_RULE_SETUP
YY_BREAK
case 4:
YY_RULE_SETUP
-#line 62 "cmCommandArgumentLexer.in.l"
{
//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
case 5:
YY_RULE_SETUP
-#line 69 "cmCommandArgumentLexer.in.l"
{
//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
case 6:
YY_RULE_SETUP
-#line 76 "cmCommandArgumentLexer.in.l"
{
//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
case 7:
YY_RULE_SETUP
-#line 83 "cmCommandArgumentLexer.in.l"
{
//std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
@@ -862,7 +1052,6 @@ YY_RULE_SETUP
YY_BREAK
case 8:
YY_RULE_SETUP
-#line 89 "cmCommandArgumentLexer.in.l"
{
if ( !yyextra->HandleEscapeSymbol(yylvalp, *(yytext+1)) )
{
@@ -874,7 +1063,6 @@ YY_RULE_SETUP
case 9:
/* rule 9 can match eol */
YY_RULE_SETUP
-#line 97 "cmCommandArgumentLexer.in.l"
{
//std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
@@ -883,46 +1071,40 @@ YY_RULE_SETUP
YY_BREAK
case 10:
YY_RULE_SETUP
-#line 103 "cmCommandArgumentLexer.in.l"
{
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->DOLLARVariable;
+ yylvalp->str = DOLLARVariable;
return cal_DOLLAR;
}
YY_BREAK
case 11:
YY_RULE_SETUP
-#line 109 "cmCommandArgumentLexer.in.l"
{
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->LCURLYVariable;
+ yylvalp->str = LCURLYVariable;
return cal_LCURLY;
}
YY_BREAK
case 12:
YY_RULE_SETUP
-#line 115 "cmCommandArgumentLexer.in.l"
{
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->BSLASHVariable;
+ yylvalp->str = BSLASHVariable;
return cal_BSLASH;
}
YY_BREAK
case 13:
YY_RULE_SETUP
-#line 121 "cmCommandArgumentLexer.in.l"
{
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->BSLASHVariable;
+ yylvalp->str = BSLASHVariable;
return cal_SYMBOL;
}
YY_BREAK
case 14:
YY_RULE_SETUP
-#line 127 "cmCommandArgumentLexer.in.l"
ECHO;
YY_BREAK
-#line 925 "cmCommandArgumentLexer.cxx"
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(ESCAPES):
case YY_STATE_EOF(NOESCAPES):
@@ -942,7 +1124,7 @@ case YY_STATE_EOF(NOESCAPES):
/* We're scanning a new file or input source. It's
* possible that this happened because the user
* just pointed yyin at a new source and called
- * cmCommandArgument_yylex(). If so, then we have to assure
+ * yylex(). If so, then we have to assure
* consistency between YY_CURRENT_BUFFER and our
* globals. Here is the right place to do so, because
* this is the first action (other than possibly a
@@ -1002,7 +1184,7 @@ case YY_STATE_EOF(NOESCAPES):
{
yyg->yy_did_buffer_switch_on_eof = 0;
- if ( cmCommandArgument_yywrap(yyscanner ) )
+ if ( yywrap( yyscanner ) )
{
/* Note: because we've taken care in
* yy_get_next_buffer() to have set up
@@ -1056,7 +1238,7 @@ case YY_STATE_EOF(NOESCAPES):
} /* end of action switch */
} /* end of scanning one token */
} /* end of user's declarations */
-} /* end of cmCommandArgument_yylex */
+} /* end of yylex */
/* yy_get_next_buffer - try to read in a new buffer
*
@@ -1070,7 +1252,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
char *source = yyg->yytext_ptr;
- yy_size_t number_to_move, i;
+ int number_to_move, i;
int ret_val;
if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
@@ -1099,7 +1281,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
/* Try to read more data. */
/* First move last chars to start of buffer. */
- number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1);
for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++);
@@ -1135,7 +1317,8 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
b->yy_ch_buf = (char *)
/* Include room in for 2 EOB chars. */
- cmCommandArgument_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+ yyrealloc( (void *) b->yy_ch_buf,
+ (yy_size_t) (b->yy_buf_size + 2) , yyscanner );
}
else
/* Can't grow it, we don't own it. */
@@ -1167,7 +1350,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ( number_to_move == YY_MORE_ADJ )
{
ret_val = EOB_ACT_END_OF_FILE;
- cmCommandArgument_yyrestart(yyin ,yyscanner);
+ yyrestart( yyin , yyscanner);
}
else
@@ -1181,12 +1364,15 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
ret_val = EOB_ACT_CONTINUE_SCAN;
- if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
/* Extend the array by 50%, plus the number we really need. */
int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) cmCommandArgument_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
+ (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner );
if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ /* "- 2" to take care of EOB's */
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
}
yyg->yy_n_chars += number_to_move;
@@ -1220,9 +1406,9 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 30 )
- yy_c = yy_meta[(unsigned int) yy_c];
+ yy_c = yy_meta[yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
}
return yy_current_state;
@@ -1249,9 +1435,9 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 30 )
- yy_c = yy_meta[(unsigned int) yy_c];
+ yy_c = yy_meta[yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
yy_is_jam = (yy_current_state == 29);
(void)yyg;
@@ -1287,7 +1473,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{ /* need more input */
- int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+ int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr);
++yyg->yy_c_buf_p;
switch ( yy_get_next_buffer( yyscanner ) )
@@ -1304,13 +1490,13 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
*/
/* Reset buffer status. */
- cmCommandArgument_yyrestart(yyin ,yyscanner);
+ yyrestart( yyin , yyscanner);
/*FALLTHROUGH*/
case EOB_ACT_END_OF_FILE:
{
- if ( cmCommandArgument_yywrap(yyscanner ) )
+ if ( yywrap( yyscanner ) )
return 0;
if ( ! yyg->yy_did_buffer_switch_on_eof )
@@ -1342,34 +1528,34 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @note This function does not reset the start condition to @c INITIAL .
*/
- void cmCommandArgument_yyrestart (FILE * input_file , yyscan_t yyscanner)
+ void yyrestart (FILE * input_file , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if ( ! YY_CURRENT_BUFFER ){
- cmCommandArgument_yyensure_buffer_stack (yyscanner);
+ yyensure_buffer_stack (yyscanner);
YY_CURRENT_BUFFER_LVALUE =
- cmCommandArgument_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner);
}
- cmCommandArgument_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
- cmCommandArgument_yy_load_buffer_state(yyscanner );
+ yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner);
+ yy_load_buffer_state( yyscanner );
}
/** Switch to a different input buffer.
* @param new_buffer The new input buffer.
* @param yyscanner The scanner object.
*/
- void cmCommandArgument_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* TODO. We should be able to replace this entire function body
* with
- * cmCommandArgument_yypop_buffer_state();
- * cmCommandArgument_yypush_buffer_state(new_buffer);
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
*/
- cmCommandArgument_yyensure_buffer_stack (yyscanner);
+ yyensure_buffer_stack (yyscanner);
if ( YY_CURRENT_BUFFER == new_buffer )
return;
@@ -1382,17 +1568,17 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
}
YY_CURRENT_BUFFER_LVALUE = new_buffer;
- cmCommandArgument_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
/* We don't actually know whether we did this switch during
- * EOF (cmCommandArgument_yywrap()) processing, but the only time this flag
- * is looked at is after cmCommandArgument_yywrap() is called, so it's safe
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
* to go ahead and always set it.
*/
yyg->yy_did_buffer_switch_on_eof = 1;
}
-static void cmCommandArgument_yy_load_buffer_state (yyscan_t yyscanner)
+static void yy_load_buffer_state (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
@@ -1407,35 +1593,35 @@ static void cmCommandArgument_yy_load_buffer_state (yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @return the allocated buffer state.
*/
- YY_BUFFER_STATE cmCommandArgument_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
- b = (YY_BUFFER_STATE) cmCommandArgument_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner );
if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmCommandArgument_yy_create_buffer()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
- b->yy_buf_size = (yy_size_t)size;
+ b->yy_buf_size = size;
/* yy_ch_buf has to be 2 characters longer than the size given because
* we need to put in 2 end-of-buffer characters.
*/
- b->yy_ch_buf = (char *) cmCommandArgument_yyalloc(b->yy_buf_size + 2 ,yyscanner );
+ b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner );
if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmCommandArgument_yy_create_buffer()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
b->yy_is_our_buffer = 1;
- cmCommandArgument_yy_init_buffer(b,file ,yyscanner);
+ yy_init_buffer( b, file , yyscanner);
return b;
}
/** Destroy the buffer.
- * @param b a buffer created with cmCommandArgument_yy_create_buffer()
+ * @param b a buffer created with yy_create_buffer()
* @param yyscanner The scanner object.
*/
- void cmCommandArgument_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+ void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -1446,28 +1632,28 @@ static void cmCommandArgument_yy_load_buffer_state (yyscan_t yyscanner)
YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
if ( b->yy_is_our_buffer )
- cmCommandArgument_yyfree((void *) b->yy_ch_buf ,yyscanner );
+ yyfree( (void *) b->yy_ch_buf , yyscanner );
- cmCommandArgument_yyfree((void *) b ,yyscanner );
+ yyfree( (void *) b , yyscanner );
}
/* Initializes or reinitializes a buffer.
* This function is sometimes called more than once on the same buffer,
- * such as during a cmCommandArgument_yyrestart() or at EOF.
+ * such as during a yyrestart() or at EOF.
*/
- static void cmCommandArgument_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
{
int oerrno = errno;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- cmCommandArgument_yy_flush_buffer(b ,yyscanner);
+ yy_flush_buffer( b , yyscanner);
b->yy_input_file = file;
b->yy_fill_buffer = 1;
- /* If b is the current buffer, then cmCommandArgument_yy_init_buffer was _probably_
- * called from cmCommandArgument_yyrestart() or through yy_get_next_buffer.
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
* In that case, we don't want to reset the lineno or column.
*/
if (b != YY_CURRENT_BUFFER){
@@ -1484,7 +1670,7 @@ static void cmCommandArgument_yy_load_buffer_state (yyscan_t yyscanner)
* @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
* @param yyscanner The scanner object.
*/
- void cmCommandArgument_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+ void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if ( ! b )
@@ -1505,7 +1691,7 @@ static void cmCommandArgument_yy_load_buffer_state (yyscan_t yyscanner)
b->yy_buffer_status = YY_BUFFER_NEW;
if ( b == YY_CURRENT_BUFFER )
- cmCommandArgument_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
}
/** Pushes the new state onto the stack. The new state becomes
@@ -1514,15 +1700,15 @@ static void cmCommandArgument_yy_load_buffer_state (yyscan_t yyscanner)
* @param new_buffer The new state.
* @param yyscanner The scanner object.
*/
-void cmCommandArgument_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (new_buffer == NULL)
return;
- cmCommandArgument_yyensure_buffer_stack(yyscanner);
+ yyensure_buffer_stack(yyscanner);
- /* This block is copied from cmCommandArgument_yy_switch_to_buffer. */
+ /* This block is copied from yy_switch_to_buffer. */
if ( YY_CURRENT_BUFFER )
{
/* Flush out information for old buffer. */
@@ -1536,8 +1722,8 @@ void cmCommandArgument_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_
yyg->yy_buffer_stack_top++;
YY_CURRENT_BUFFER_LVALUE = new_buffer;
- /* copied from cmCommandArgument_yy_switch_to_buffer. */
- cmCommandArgument_yy_load_buffer_state(yyscanner );
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state( yyscanner );
yyg->yy_did_buffer_switch_on_eof = 1;
}
@@ -1545,19 +1731,19 @@ void cmCommandArgument_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_
* The next element becomes the new top.
* @param yyscanner The scanner object.
*/
-void cmCommandArgument_yypop_buffer_state (yyscan_t yyscanner)
+void yypop_buffer_state (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (!YY_CURRENT_BUFFER)
return;
- cmCommandArgument_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+ yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner);
YY_CURRENT_BUFFER_LVALUE = NULL;
if (yyg->yy_buffer_stack_top > 0)
--yyg->yy_buffer_stack_top;
if (YY_CURRENT_BUFFER) {
- cmCommandArgument_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
yyg->yy_did_buffer_switch_on_eof = 1;
}
}
@@ -1565,9 +1751,9 @@ void cmCommandArgument_yypop_buffer_state (yyscan_t yyscanner)
/* Allocates the stack if it does not exist.
* Guarantees space for at least one push.
*/
-static void cmCommandArgument_yyensure_buffer_stack (yyscan_t yyscanner)
+static void yyensure_buffer_stack (yyscan_t yyscanner)
{
- int num_to_alloc;
+ yy_size_t num_to_alloc;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (!yyg->yy_buffer_stack) {
@@ -1577,11 +1763,11 @@ static void cmCommandArgument_yyensure_buffer_stack (yyscan_t yyscanner)
* immediate realloc on the next call.
*/
num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmCommandArgument_yyalloc
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
(num_to_alloc * sizeof(struct yy_buffer_state*)
, yyscanner);
if ( ! yyg->yy_buffer_stack )
- YY_FATAL_ERROR( "out of dynamic memory in cmCommandArgument_yyensure_buffer_stack()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
@@ -1596,12 +1782,12 @@ static void cmCommandArgument_yyensure_buffer_stack (yyscan_t yyscanner)
yy_size_t grow_size = 8 /* arbitrary grow size */;
num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmCommandArgument_yyrealloc
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
(yyg->yy_buffer_stack,
num_to_alloc * sizeof(struct yy_buffer_state*)
, yyscanner);
if ( ! yyg->yy_buffer_stack )
- YY_FATAL_ERROR( "out of dynamic memory in cmCommandArgument_yyensure_buffer_stack()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
/* zero only the new slots.*/
memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
@@ -1615,7 +1801,7 @@ static void cmCommandArgument_yyensure_buffer_stack (yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
-YY_BUFFER_STATE cmCommandArgument_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
@@ -1625,11 +1811,11 @@ YY_BUFFER_STATE cmCommandArgument_yy_scan_buffer (char * base, yy_size_t size
/* They forgot to leave room for the EOB's. */
return NULL;
- b = (YY_BUFFER_STATE) cmCommandArgument_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner );
if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmCommandArgument_yy_scan_buffer()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
- b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */
b->yy_buf_pos = b->yy_ch_buf = base;
b->yy_is_our_buffer = 0;
b->yy_input_file = NULL;
@@ -1639,53 +1825,53 @@ YY_BUFFER_STATE cmCommandArgument_yy_scan_buffer (char * base, yy_size_t size
b->yy_fill_buffer = 0;
b->yy_buffer_status = YY_BUFFER_NEW;
- cmCommandArgument_yy_switch_to_buffer(b ,yyscanner );
+ yy_switch_to_buffer( b , yyscanner );
return b;
}
-/** Setup the input buffer state to scan a string. The next call to cmCommandArgument_yylex() will
+/** Setup the input buffer state to scan a string. The next call to yylex() will
* scan from a @e copy of @a str.
* @param yystr a NUL-terminated string to scan
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
* @note If you want to scan bytes that may contain NUL values, then use
- * cmCommandArgument_yy_scan_bytes() instead.
+ * yy_scan_bytes() instead.
*/
-YY_BUFFER_STATE cmCommandArgument_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner)
{
- return cmCommandArgument_yy_scan_bytes(yystr,(int) strlen(yystr) ,yyscanner);
+ return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner);
}
-/** Setup the input buffer state to scan the given bytes. The next call to cmCommandArgument_yylex() will
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
* scan from a @e copy of @a bytes.
* @param yybytes the byte buffer to scan
* @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
-YY_BUFFER_STATE cmCommandArgument_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
char *buf;
yy_size_t n;
- yy_size_t i;
+ int i;
/* Get memory for full buffer, including space for trailing EOB's. */
- n = (yy_size_t) _yybytes_len + 2;
- buf = (char *) cmCommandArgument_yyalloc(n ,yyscanner );
+ n = (yy_size_t) (_yybytes_len + 2);
+ buf = (char *) yyalloc( n , yyscanner );
if ( ! buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmCommandArgument_yy_scan_bytes()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
- for ( i = 0; i < (size_t)_yybytes_len; ++i )
+ for ( i = 0; i < _yybytes_len; ++i )
buf[i] = yybytes[i];
buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
- b = cmCommandArgument_yy_scan_buffer(buf,n ,yyscanner);
+ b = yy_scan_buffer( buf, n , yyscanner);
if ( ! b )
- YY_FATAL_ERROR( "bad buffer in cmCommandArgument_yy_scan_bytes()" );
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
/* It's okay to grow etc. this buffer, and we should throw it
* away when we're done.
@@ -1699,11 +1885,11 @@ YY_BUFFER_STATE cmCommandArgument_yy_scan_bytes (yyconst char * yybytes, int _
#define YY_EXIT_FAILURE 2
#endif
-static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
- (void) fprintf( stderr, "%s\n", msg );
+ fprintf( stderr, "%s\n", msg );
exit( YY_EXIT_FAILURE );
}
@@ -1729,7 +1915,7 @@ static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
/** Get the user-defined data for this scanner.
* @param yyscanner The scanner object.
*/
-YY_EXTRA_TYPE cmCommandArgument_yyget_extra (yyscan_t yyscanner)
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyextra;
@@ -1738,7 +1924,7 @@ YY_EXTRA_TYPE cmCommandArgument_yyget_extra (yyscan_t yyscanner)
/** Get the current line number.
* @param yyscanner The scanner object.
*/
-int cmCommandArgument_yyget_lineno (yyscan_t yyscanner)
+int yyget_lineno (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -1751,7 +1937,7 @@ int cmCommandArgument_yyget_lineno (yyscan_t yyscanner)
/** Get the current column number.
* @param yyscanner The scanner object.
*/
-int cmCommandArgument_yyget_column (yyscan_t yyscanner)
+int yyget_column (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -1764,7 +1950,7 @@ int cmCommandArgument_yyget_column (yyscan_t yyscanner)
/** Get the input stream.
* @param yyscanner The scanner object.
*/
-FILE *cmCommandArgument_yyget_in (yyscan_t yyscanner)
+FILE *yyget_in (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyin;
@@ -1773,7 +1959,7 @@ FILE *cmCommandArgument_yyget_in (yyscan_t yyscanner)
/** Get the output stream.
* @param yyscanner The scanner object.
*/
-FILE *cmCommandArgument_yyget_out (yyscan_t yyscanner)
+FILE *yyget_out (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyout;
@@ -1782,7 +1968,7 @@ FILE *cmCommandArgument_yyget_out (yyscan_t yyscanner)
/** Get the length of the current token.
* @param yyscanner The scanner object.
*/
-int cmCommandArgument_yyget_leng (yyscan_t yyscanner)
+int yyget_leng (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyleng;
@@ -1792,7 +1978,7 @@ int cmCommandArgument_yyget_leng (yyscan_t yyscanner)
* @param yyscanner The scanner object.
*/
-char *cmCommandArgument_yyget_text (yyscan_t yyscanner)
+char *yyget_text (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yytext;
@@ -1802,7 +1988,7 @@ char *cmCommandArgument_yyget_text (yyscan_t yyscanner)
* @param user_defined The data to be associated with this scanner.
* @param yyscanner The scanner object.
*/
-void cmCommandArgument_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
+void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyextra = user_defined ;
@@ -1812,13 +1998,13 @@ void cmCommandArgument_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yysca
* @param _line_number line number
* @param yyscanner The scanner object.
*/
-void cmCommandArgument_yyset_lineno (int _line_number , yyscan_t yyscanner)
+void yyset_lineno (int _line_number , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* lineno is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
- YY_FATAL_ERROR( "cmCommandArgument_yyset_lineno called with no buffer" );
+ YY_FATAL_ERROR( "yyset_lineno called with no buffer" );
yylineno = _line_number;
}
@@ -1827,13 +2013,13 @@ void cmCommandArgument_yyset_lineno (int _line_number , yyscan_t yyscanner)
* @param _column_no column number
* @param yyscanner The scanner object.
*/
-void cmCommandArgument_yyset_column (int _column_no , yyscan_t yyscanner)
+void yyset_column (int _column_no , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* column is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
- YY_FATAL_ERROR( "cmCommandArgument_yyset_column called with no buffer" );
+ YY_FATAL_ERROR( "yyset_column called with no buffer" );
yycolumn = _column_no;
}
@@ -1842,27 +2028,27 @@ void cmCommandArgument_yyset_column (int _column_no , yyscan_t yyscanner)
* input buffer.
* @param _in_str A readable stream.
* @param yyscanner The scanner object.
- * @see cmCommandArgument_yy_switch_to_buffer
+ * @see yy_switch_to_buffer
*/
-void cmCommandArgument_yyset_in (FILE * _in_str , yyscan_t yyscanner)
+void yyset_in (FILE * _in_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyin = _in_str ;
}
-void cmCommandArgument_yyset_out (FILE * _out_str , yyscan_t yyscanner)
+void yyset_out (FILE * _out_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyout = _out_str ;
}
-int cmCommandArgument_yyget_debug (yyscan_t yyscanner)
+int yyget_debug (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yy_flex_debug;
}
-void cmCommandArgument_yyset_debug (int _bdebug , yyscan_t yyscanner)
+void yyset_debug (int _bdebug , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yy_flex_debug = _bdebug ;
@@ -1872,20 +2058,18 @@ void cmCommandArgument_yyset_debug (int _bdebug , yyscan_t yyscanner)
/* User-visible API */
-/* cmCommandArgument_yylex_init is special because it creates the scanner itself, so it is
+/* yylex_init is special because it creates the scanner itself, so it is
* the ONLY reentrant function that doesn't take the scanner as the last argument.
* That's why we explicitly handle the declaration, instead of using our macros.
*/
-
-int cmCommandArgument_yylex_init(yyscan_t* ptr_yy_globals)
-
+int yylex_init(yyscan_t* ptr_yy_globals)
{
if (ptr_yy_globals == NULL){
errno = EINVAL;
return 1;
}
- *ptr_yy_globals = (yyscan_t) cmCommandArgument_yyalloc ( sizeof( struct yyguts_t ), NULL );
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
if (*ptr_yy_globals == NULL){
errno = ENOMEM;
@@ -1898,27 +2082,25 @@ int cmCommandArgument_yylex_init(yyscan_t* ptr_yy_globals)
return yy_init_globals ( *ptr_yy_globals );
}
-/* cmCommandArgument_yylex_init_extra has the same functionality as cmCommandArgument_yylex_init, but follows the
+/* yylex_init_extra has the same functionality as yylex_init, but follows the
* convention of taking the scanner as the last argument. Note however, that
* this is a *pointer* to a scanner, as it will be allocated by this call (and
* is the reason, too, why this function also must handle its own declaration).
- * The user defined value in the first argument will be available to cmCommandArgument_yyalloc in
+ * The user defined value in the first argument will be available to yyalloc in
* the yyextra field.
*/
-
-int cmCommandArgument_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
-
+int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals )
{
struct yyguts_t dummy_yyguts;
- cmCommandArgument_yyset_extra (yy_user_defined, &dummy_yyguts);
+ yyset_extra (yy_user_defined, &dummy_yyguts);
if (ptr_yy_globals == NULL){
errno = EINVAL;
return 1;
}
- *ptr_yy_globals = (yyscan_t) cmCommandArgument_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
if (*ptr_yy_globals == NULL){
errno = ENOMEM;
@@ -1929,7 +2111,7 @@ int cmCommandArgument_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* p
yy_init_globals. Leave at 0x00 for releases. */
memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
- cmCommandArgument_yyset_extra (yy_user_defined, *ptr_yy_globals);
+ yyset_extra (yy_user_defined, *ptr_yy_globals);
return yy_init_globals ( *ptr_yy_globals );
}
@@ -1938,7 +2120,7 @@ static int yy_init_globals (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* Initialization is the same as for the non-reentrant scanner.
- * This function is called from cmCommandArgument_yylex_destroy(), so don't allocate here.
+ * This function is called from yylex_destroy(), so don't allocate here.
*/
yyg->yy_buffer_stack = NULL;
@@ -1962,37 +2144,37 @@ static int yy_init_globals (yyscan_t yyscanner)
#endif
/* For future reference: Set errno on error, since we are called by
- * cmCommandArgument_yylex_init()
+ * yylex_init()
*/
return 0;
}
-/* cmCommandArgument_yylex_destroy is for both reentrant and non-reentrant scanners. */
-int cmCommandArgument_yylex_destroy (yyscan_t yyscanner)
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* Pop the buffer stack, destroying each element. */
while(YY_CURRENT_BUFFER){
- cmCommandArgument_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+ yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner );
YY_CURRENT_BUFFER_LVALUE = NULL;
- cmCommandArgument_yypop_buffer_state(yyscanner);
+ yypop_buffer_state(yyscanner);
}
/* Destroy the stack itself. */
- cmCommandArgument_yyfree(yyg->yy_buffer_stack ,yyscanner);
+ yyfree(yyg->yy_buffer_stack , yyscanner);
yyg->yy_buffer_stack = NULL;
/* Destroy the start condition stack. */
- cmCommandArgument_yyfree(yyg->yy_start_stack ,yyscanner );
+ yyfree( yyg->yy_start_stack , yyscanner );
yyg->yy_start_stack = NULL;
/* Reset the globals. This is important in a non-reentrant scanner so the next time
- * cmCommandArgument_yylex() is called, initialization will occur. */
+ * yylex() is called, initialization will occur. */
yy_init_globals( yyscanner);
/* Destroy the main struct (reentrant only). */
- cmCommandArgument_yyfree ( yyscanner , yyscanner );
+ yyfree ( yyscanner , yyscanner );
yyscanner = NULL;
return 0;
}
@@ -2002,7 +2184,7 @@ int cmCommandArgument_yylex_destroy (yyscan_t yyscanner)
*/
#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
@@ -2014,7 +2196,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca
#endif
#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+static int yy_flex_strlen (const char * s , yyscan_t yyscanner)
{
int n;
for ( n = 0; s[n]; ++n )
@@ -2024,14 +2206,14 @@ static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
}
#endif
-void *cmCommandArgument_yyalloc (yy_size_t size , yyscan_t yyscanner)
+void *yyalloc (yy_size_t size , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
return malloc(size);
}
-void *cmCommandArgument_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
+void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
@@ -2046,19 +2228,15 @@ void *cmCommandArgument_yyrealloc (void * ptr, yy_size_t size , yyscan_t yysca
return realloc(ptr, size);
}
-void cmCommandArgument_yyfree (void * ptr , yyscan_t yyscanner)
+void yyfree (void * ptr , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
- free( (char *) ptr ); /* see cmCommandArgument_yyrealloc() for (char *) cast */
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
}
#define YYTABLES_NAME "yytables"
-#line 127 "cmCommandArgumentLexer.in.l"
-
-
-
/*--------------------------------------------------------------------------*/
void cmCommandArgument_SetupEscapes(yyscan_t yyscanner, bool noEscapes)
{
@@ -2070,3 +2248,5 @@ void cmCommandArgument_SetupEscapes(yyscan_t yyscanner, bool noEscapes)
BEGIN(ESCAPES);
}
}
+
+#endif /* __clang_analyzer__ */
diff --git a/Source/LexerParser/cmCommandArgumentLexer.h b/Source/LexerParser/cmCommandArgumentLexer.h
index 82e87b557..567751349 100644
--- a/Source/LexerParser/cmCommandArgumentLexer.h
+++ b/Source/LexerParser/cmCommandArgumentLexer.h
@@ -2,10 +2,6 @@
#define cmCommandArgument_yyHEADER_H 1
#define cmCommandArgument_yyIN_HEADER 1
-#line 6 "cmCommandArgumentLexer.h"
-
-#line 8 "cmCommandArgumentLexer.h"
-
#define FLEXINT_H 1
#define YY_INT_ALIGNED short int
@@ -14,11 +10,221 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6
-#define YY_FLEX_SUBMINOR_VERSION 1
+#define YY_FLEX_SUBMINOR_VERSION 4
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
+#ifdef yy_create_buffer
+#define cmCommandArgument_yy_create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer cmCommandArgument_yy_create_buffer
+#endif
+
+#ifdef yy_delete_buffer
+#define cmCommandArgument_yy_delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer cmCommandArgument_yy_delete_buffer
+#endif
+
+#ifdef yy_scan_buffer
+#define cmCommandArgument_yy_scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer cmCommandArgument_yy_scan_buffer
+#endif
+
+#ifdef yy_scan_string
+#define cmCommandArgument_yy_scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string cmCommandArgument_yy_scan_string
+#endif
+
+#ifdef yy_scan_bytes
+#define cmCommandArgument_yy_scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes cmCommandArgument_yy_scan_bytes
+#endif
+
+#ifdef yy_init_buffer
+#define cmCommandArgument_yy_init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer cmCommandArgument_yy_init_buffer
+#endif
+
+#ifdef yy_flush_buffer
+#define cmCommandArgument_yy_flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer cmCommandArgument_yy_flush_buffer
+#endif
+
+#ifdef yy_load_buffer_state
+#define cmCommandArgument_yy_load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state cmCommandArgument_yy_load_buffer_state
+#endif
+
+#ifdef yy_switch_to_buffer
+#define cmCommandArgument_yy_switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer cmCommandArgument_yy_switch_to_buffer
+#endif
+
+#ifdef yypush_buffer_state
+#define cmCommandArgument_yypush_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state cmCommandArgument_yypush_buffer_state
+#endif
+
+#ifdef yypop_buffer_state
+#define cmCommandArgument_yypop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state cmCommandArgument_yypop_buffer_state
+#endif
+
+#ifdef yyensure_buffer_stack
+#define cmCommandArgument_yyensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack cmCommandArgument_yyensure_buffer_stack
+#endif
+
+#ifdef yylex
+#define cmCommandArgument_yylex_ALREADY_DEFINED
+#else
+#define yylex cmCommandArgument_yylex
+#endif
+
+#ifdef yyrestart
+#define cmCommandArgument_yyrestart_ALREADY_DEFINED
+#else
+#define yyrestart cmCommandArgument_yyrestart
+#endif
+
+#ifdef yylex_init
+#define cmCommandArgument_yylex_init_ALREADY_DEFINED
+#else
+#define yylex_init cmCommandArgument_yylex_init
+#endif
+
+#ifdef yylex_init_extra
+#define cmCommandArgument_yylex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra cmCommandArgument_yylex_init_extra
+#endif
+
+#ifdef yylex_destroy
+#define cmCommandArgument_yylex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy cmCommandArgument_yylex_destroy
+#endif
+
+#ifdef yyget_debug
+#define cmCommandArgument_yyget_debug_ALREADY_DEFINED
+#else
+#define yyget_debug cmCommandArgument_yyget_debug
+#endif
+
+#ifdef yyset_debug
+#define cmCommandArgument_yyset_debug_ALREADY_DEFINED
+#else
+#define yyset_debug cmCommandArgument_yyset_debug
+#endif
+
+#ifdef yyget_extra
+#define cmCommandArgument_yyget_extra_ALREADY_DEFINED
+#else
+#define yyget_extra cmCommandArgument_yyget_extra
+#endif
+
+#ifdef yyset_extra
+#define cmCommandArgument_yyset_extra_ALREADY_DEFINED
+#else
+#define yyset_extra cmCommandArgument_yyset_extra
+#endif
+
+#ifdef yyget_in
+#define cmCommandArgument_yyget_in_ALREADY_DEFINED
+#else
+#define yyget_in cmCommandArgument_yyget_in
+#endif
+
+#ifdef yyset_in
+#define cmCommandArgument_yyset_in_ALREADY_DEFINED
+#else
+#define yyset_in cmCommandArgument_yyset_in
+#endif
+
+#ifdef yyget_out
+#define cmCommandArgument_yyget_out_ALREADY_DEFINED
+#else
+#define yyget_out cmCommandArgument_yyget_out
+#endif
+
+#ifdef yyset_out
+#define cmCommandArgument_yyset_out_ALREADY_DEFINED
+#else
+#define yyset_out cmCommandArgument_yyset_out
+#endif
+
+#ifdef yyget_leng
+#define cmCommandArgument_yyget_leng_ALREADY_DEFINED
+#else
+#define yyget_leng cmCommandArgument_yyget_leng
+#endif
+
+#ifdef yyget_text
+#define cmCommandArgument_yyget_text_ALREADY_DEFINED
+#else
+#define yyget_text cmCommandArgument_yyget_text
+#endif
+
+#ifdef yyget_lineno
+#define cmCommandArgument_yyget_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno cmCommandArgument_yyget_lineno
+#endif
+
+#ifdef yyset_lineno
+#define cmCommandArgument_yyset_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno cmCommandArgument_yyset_lineno
+#endif
+
+#ifdef yyget_column
+#define cmCommandArgument_yyget_column_ALREADY_DEFINED
+#else
+#define yyget_column cmCommandArgument_yyget_column
+#endif
+
+#ifdef yyset_column
+#define cmCommandArgument_yyset_column_ALREADY_DEFINED
+#else
+#define yyset_column cmCommandArgument_yyset_column
+#endif
+
+#ifdef yywrap
+#define cmCommandArgument_yywrap_ALREADY_DEFINED
+#else
+#define yywrap cmCommandArgument_yywrap
+#endif
+
+#ifdef yyalloc
+#define cmCommandArgument_yyalloc_ALREADY_DEFINED
+#else
+#define yyalloc cmCommandArgument_yyalloc
+#endif
+
+#ifdef yyrealloc
+#define cmCommandArgument_yyrealloc_ALREADY_DEFINED
+#else
+#define yyrealloc cmCommandArgument_yyrealloc
+#endif
+
+#ifdef yyfree
+#define cmCommandArgument_yyfree_ALREADY_DEFINED
+#else
+#define yyfree cmCommandArgument_yyfree
+#endif
+
/* First, we deal with platform-specific or compiler-specific issues. */
/* begin standard C headers. */
@@ -89,10 +295,16 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
+#ifndef SIZE_MAX
+#define SIZE_MAX (~(size_t)0)
+#endif
+
#endif /* ! C99 */
#endif /* ! FLEXINT_H */
+/* begin standard C++ headers. */
+
/* TODO: this is always defined, so inline it */
#define yyconst const
@@ -193,21 +405,21 @@ struct yy_buffer_state
};
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-void cmCommandArgument_yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void cmCommandArgument_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmCommandArgument_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void cmCommandArgument_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmCommandArgument_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmCommandArgument_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void cmCommandArgument_yypop_buffer_state (yyscan_t yyscanner );
+void yyrestart ( FILE *input_file , yyscan_t yyscanner );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
+void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+void yypop_buffer_state ( yyscan_t yyscanner );
-YY_BUFFER_STATE cmCommandArgument_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmCommandArgument_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmCommandArgument_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
-void *cmCommandArgument_yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *cmCommandArgument_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void cmCommandArgument_yyfree (void * ,yyscan_t yyscanner );
+void *yyalloc ( yy_size_t , yyscan_t yyscanner );
+void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
+void yyfree ( void * , yyscan_t yyscanner );
/* Begin user sect3 */
@@ -227,42 +439,42 @@ void cmCommandArgument_yyfree (void * ,yyscan_t yyscanner );
#define YY_EXTRA_TYPE void *
#endif
-int cmCommandArgument_yylex_init (yyscan_t* scanner);
+int yylex_init (yyscan_t* scanner);
-int cmCommandArgument_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
-int cmCommandArgument_yylex_destroy (yyscan_t yyscanner );
+int yylex_destroy ( yyscan_t yyscanner );
-int cmCommandArgument_yyget_debug (yyscan_t yyscanner );
+int yyget_debug ( yyscan_t yyscanner );
-void cmCommandArgument_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+void yyset_debug ( int debug_flag , yyscan_t yyscanner );
-YY_EXTRA_TYPE cmCommandArgument_yyget_extra (yyscan_t yyscanner );
+YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
-void cmCommandArgument_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
-FILE *cmCommandArgument_yyget_in (yyscan_t yyscanner );
+FILE *yyget_in ( yyscan_t yyscanner );
-void cmCommandArgument_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
+void yyset_in ( FILE * _in_str , yyscan_t yyscanner );
-FILE *cmCommandArgument_yyget_out (yyscan_t yyscanner );
+FILE *yyget_out ( yyscan_t yyscanner );
-void cmCommandArgument_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
+void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
- int cmCommandArgument_yyget_leng (yyscan_t yyscanner );
+ int yyget_leng ( yyscan_t yyscanner );
-char *cmCommandArgument_yyget_text (yyscan_t yyscanner );
+char *yyget_text ( yyscan_t yyscanner );
-int cmCommandArgument_yyget_lineno (yyscan_t yyscanner );
+int yyget_lineno ( yyscan_t yyscanner );
-void cmCommandArgument_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+void yyset_lineno ( int _line_number , yyscan_t yyscanner );
-int cmCommandArgument_yyget_column (yyscan_t yyscanner );
+int yyget_column ( yyscan_t yyscanner );
-void cmCommandArgument_yyset_column (int _column_no ,yyscan_t yyscanner );
+void yyset_column ( int _column_no , yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -270,18 +482,18 @@ void cmCommandArgument_yyset_column (int _column_no ,yyscan_t yyscanner );
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
-extern "C" int cmCommandArgument_yywrap (yyscan_t yyscanner );
+extern "C" int yywrap ( yyscan_t yyscanner );
#else
-extern int cmCommandArgument_yywrap (yyscan_t yyscanner );
+extern int yywrap ( yyscan_t yyscanner );
#endif
#endif
#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
#endif
#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
#endif
#ifndef YY_NO_INPUT
@@ -309,9 +521,9 @@ static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
-extern int cmCommandArgument_yylex (yyscan_t yyscanner);
+extern int yylex (yyscan_t yyscanner);
-#define YY_DECL int cmCommandArgument_yylex (yyscan_t yyscanner)
+#define YY_DECL int yylex (yyscan_t yyscanner)
#endif /* !YY_DECL */
/* yy_get_previous_state - get the state just before the EOB char was reached */
@@ -328,9 +540,150 @@ extern int cmCommandArgument_yylex (yyscan_t yyscanner);
#undef YY_DECL
#endif
-#line 127 "cmCommandArgumentLexer.in.l"
-
+#ifndef cmCommandArgument_yy_create_buffer_ALREADY_DEFINED
+#undef yy_create_buffer
+#endif
+#ifndef cmCommandArgument_yy_delete_buffer_ALREADY_DEFINED
+#undef yy_delete_buffer
+#endif
+#ifndef cmCommandArgument_yy_scan_buffer_ALREADY_DEFINED
+#undef yy_scan_buffer
+#endif
+#ifndef cmCommandArgument_yy_scan_string_ALREADY_DEFINED
+#undef yy_scan_string
+#endif
+#ifndef cmCommandArgument_yy_scan_bytes_ALREADY_DEFINED
+#undef yy_scan_bytes
+#endif
+#ifndef cmCommandArgument_yy_init_buffer_ALREADY_DEFINED
+#undef yy_init_buffer
+#endif
+#ifndef cmCommandArgument_yy_flush_buffer_ALREADY_DEFINED
+#undef yy_flush_buffer
+#endif
+#ifndef cmCommandArgument_yy_load_buffer_state_ALREADY_DEFINED
+#undef yy_load_buffer_state
+#endif
+#ifndef cmCommandArgument_yy_switch_to_buffer_ALREADY_DEFINED
+#undef yy_switch_to_buffer
+#endif
+#ifndef cmCommandArgument_yypush_buffer_state_ALREADY_DEFINED
+#undef yypush_buffer_state
+#endif
+#ifndef cmCommandArgument_yypop_buffer_state_ALREADY_DEFINED
+#undef yypop_buffer_state
+#endif
+#ifndef cmCommandArgument_yyensure_buffer_stack_ALREADY_DEFINED
+#undef yyensure_buffer_stack
+#endif
+#ifndef cmCommandArgument_yylex_ALREADY_DEFINED
+#undef yylex
+#endif
+#ifndef cmCommandArgument_yyrestart_ALREADY_DEFINED
+#undef yyrestart
+#endif
+#ifndef cmCommandArgument_yylex_init_ALREADY_DEFINED
+#undef yylex_init
+#endif
+#ifndef cmCommandArgument_yylex_init_extra_ALREADY_DEFINED
+#undef yylex_init_extra
+#endif
+#ifndef cmCommandArgument_yylex_destroy_ALREADY_DEFINED
+#undef yylex_destroy
+#endif
+#ifndef cmCommandArgument_yyget_debug_ALREADY_DEFINED
+#undef yyget_debug
+#endif
+#ifndef cmCommandArgument_yyset_debug_ALREADY_DEFINED
+#undef yyset_debug
+#endif
+#ifndef cmCommandArgument_yyget_extra_ALREADY_DEFINED
+#undef yyget_extra
+#endif
+#ifndef cmCommandArgument_yyset_extra_ALREADY_DEFINED
+#undef yyset_extra
+#endif
+#ifndef cmCommandArgument_yyget_in_ALREADY_DEFINED
+#undef yyget_in
+#endif
+#ifndef cmCommandArgument_yyset_in_ALREADY_DEFINED
+#undef yyset_in
+#endif
+#ifndef cmCommandArgument_yyget_out_ALREADY_DEFINED
+#undef yyget_out
+#endif
+#ifndef cmCommandArgument_yyset_out_ALREADY_DEFINED
+#undef yyset_out
+#endif
+#ifndef cmCommandArgument_yyget_leng_ALREADY_DEFINED
+#undef yyget_leng
+#endif
+#ifndef cmCommandArgument_yyget_text_ALREADY_DEFINED
+#undef yyget_text
+#endif
+#ifndef cmCommandArgument_yyget_lineno_ALREADY_DEFINED
+#undef yyget_lineno
+#endif
+#ifndef cmCommandArgument_yyset_lineno_ALREADY_DEFINED
+#undef yyset_lineno
+#endif
+#ifndef cmCommandArgument_yyget_column_ALREADY_DEFINED
+#undef yyget_column
+#endif
+#ifndef cmCommandArgument_yyset_column_ALREADY_DEFINED
+#undef yyset_column
+#endif
+#ifndef cmCommandArgument_yywrap_ALREADY_DEFINED
+#undef yywrap
+#endif
+#ifndef cmCommandArgument_yyget_lval_ALREADY_DEFINED
+#undef yyget_lval
+#endif
+#ifndef cmCommandArgument_yyset_lval_ALREADY_DEFINED
+#undef yyset_lval
+#endif
+#ifndef cmCommandArgument_yyget_lloc_ALREADY_DEFINED
+#undef yyget_lloc
+#endif
+#ifndef cmCommandArgument_yyset_lloc_ALREADY_DEFINED
+#undef yyset_lloc
+#endif
+#ifndef cmCommandArgument_yyalloc_ALREADY_DEFINED
+#undef yyalloc
+#endif
+#ifndef cmCommandArgument_yyrealloc_ALREADY_DEFINED
+#undef yyrealloc
+#endif
+#ifndef cmCommandArgument_yyfree_ALREADY_DEFINED
+#undef yyfree
+#endif
+#ifndef cmCommandArgument_yytext_ALREADY_DEFINED
+#undef yytext
+#endif
+#ifndef cmCommandArgument_yyleng_ALREADY_DEFINED
+#undef yyleng
+#endif
+#ifndef cmCommandArgument_yyin_ALREADY_DEFINED
+#undef yyin
+#endif
+#ifndef cmCommandArgument_yyout_ALREADY_DEFINED
+#undef yyout
+#endif
+#ifndef cmCommandArgument_yy_flex_debug_ALREADY_DEFINED
+#undef yy_flex_debug
+#endif
+#ifndef cmCommandArgument_yylineno_ALREADY_DEFINED
+#undef yylineno
+#endif
+#ifndef cmCommandArgument_yytables_fload_ALREADY_DEFINED
+#undef yytables_fload
+#endif
+#ifndef cmCommandArgument_yytables_destroy_ALREADY_DEFINED
+#undef yytables_destroy
+#endif
+#ifndef cmCommandArgument_yyTABLES_NAME_ALREADY_DEFINED
+#undef yyTABLES_NAME
+#endif
-#line 335 "cmCommandArgumentLexer.h"
#undef cmCommandArgument_yyIN_HEADER
#endif /* cmCommandArgument_yyHEADER_H */
diff --git a/Source/LexerParser/cmCommandArgumentLexer.in.l b/Source/LexerParser/cmCommandArgumentLexer.in.l
index e3a80948c..010d54bf5 100644
--- a/Source/LexerParser/cmCommandArgumentLexer.in.l
+++ b/Source/LexerParser/cmCommandArgumentLexer.in.l
@@ -7,31 +7,41 @@ This file must be translated to C++ and modified to build everywhere.
Run flex >= 2.6 like this:
- flex --nounistd -DFLEXINT_H --prefix=cmCommandArgument_yy --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l
+ flex --nounistd -DFLEXINT_H --noline --header-file=cmCommandArgumentLexer.h -ocmCommandArgumentLexer.cxx cmCommandArgumentLexer.in.l
Modify cmCommandArgumentLexer.cxx:
- - remove trailing whitespace: sed -i 's/\s*$//' cmCommandArgumentLexer.h cmCommandArgumentLexer.cxx
- - remove blank lines at end of file
- - #include "cmStandardLexer.h" at the top
- - add cast in yy_scan_bytes for loop condition of _yybytes_len to size_t
+ - remove trailing whitespace: sed -i 's/\s*$//' cmCommandArgumentLexer.h cmCommandArgumentLexer.cxx
+ - remove blank lines at end of file: sed -i '${/^$/d;}' cmCommandArgumentLexer.h cmCommandArgumentLexer.cxx
+ - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmCommandArgumentLexer.cxx
*/
/* IWYU pragma: no_forward_declare yyguts_t */
+#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+
#include "cmCommandArgumentParserHelper.h"
/* Replace the lexer input function. */
#undef YY_INPUT
#define YY_INPUT(buf, result, max_size) \
- { result = yyextra->LexInput(buf, max_size); }
+ do { result = yyextra->LexInput(buf, max_size); } while (0)
/* 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 = "\\";
+
/*--------------------------------------------------------------------------*/
%}
+%option prefix="cmCommandArgument_yy"
+
%option reentrant
%option noyywrap
%option nounput
@@ -62,21 +72,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;
}
@@ -102,25 +112,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;
}
@@ -137,3 +147,5 @@ void cmCommandArgument_SetupEscapes(yyscan_t yyscanner, bool noEscapes)
BEGIN(ESCAPES);
}
}
+
+#endif /* __clang_analyzer__ */
diff --git a/Source/LexerParser/cmCommandArgumentParser.cxx b/Source/LexerParser/cmCommandArgumentParser.cxx
index aed0826c0..ae7fb42ea 100644
--- a/Source/LexerParser/cmCommandArgumentParser.cxx
+++ b/Source/LexerParser/cmCommandArgumentParser.cxx
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4. */
+/* A Bison parser, made by GNU Bison 3.3.2. */
/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+ Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -40,11 +41,14 @@
define necessary library symbols; they are noted "INFRINGES ON
USER NAME SPACE" below. */
+/* Undocumented macros, especially those whose name start with YY_,
+ are private implementation details. Do not rely on them. */
+
/* Identify Bison output. */
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "3.0.4"
+#define YYBISON_VERSION "3.3.2"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -67,8 +71,8 @@
#define yynerrs cmCommandArgument_yynerrs
-/* Copy the first part of user declarations. */
-#line 1 "cmCommandArgumentParser.y" /* yacc.c:339 */
+/* First part of user prologue. */
+#line 1 "cmCommandArgumentParser.y" /* yacc.c:337 */
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
@@ -126,14 +130,20 @@ static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message);
# pragma warning (disable: 4244) /* loss of precision */
# pragma warning (disable: 4702) /* unreachable code */
#endif
+#if defined(__GNUC__) && __GNUC__ >= 8
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif
-#line 131 "cmCommandArgumentParser.cxx" /* yacc.c:339 */
-
+#line 138 "cmCommandArgumentParser.cxx" /* yacc.c:337 */
# ifndef YY_NULLPTR
-# if defined __cplusplus && 201103L <= __cplusplus
-# define YY_NULLPTR nullptr
+# if defined __cplusplus
+# if 201103L <= __cplusplus
+# define YY_NULLPTR nullptr
+# else
+# define YY_NULLPTR 0
+# endif
# else
-# define YY_NULLPTR 0
+# define YY_NULLPTR ((void*)0)
# endif
# endif
@@ -198,9 +208,7 @@ int cmCommandArgument_yyparse (yyscan_t yyscanner);
#endif /* !YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED */
-/* Copy the second part of user declarations. */
-#line 204 "cmCommandArgumentParser.cxx" /* yacc.c:358 */
#ifdef short
# undef short
@@ -221,13 +229,13 @@ typedef signed char yytype_int8;
#ifdef YYTYPE_UINT16
typedef YYTYPE_UINT16 yytype_uint16;
#else
-typedef unsigned short int yytype_uint16;
+typedef unsigned short yytype_uint16;
#endif
#ifdef YYTYPE_INT16
typedef YYTYPE_INT16 yytype_int16;
#else
-typedef short int yytype_int16;
+typedef short yytype_int16;
#endif
#ifndef YYSIZE_T
@@ -239,7 +247,7 @@ typedef short int yytype_int16;
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
-# define YYSIZE_T unsigned int
+# define YYSIZE_T unsigned
# endif
#endif
@@ -275,15 +283,6 @@ typedef short int yytype_int16;
# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
#endif
-#if !defined _Noreturn \
- && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
-# if defined _MSC_VER && 1200 <= _MSC_VER
-# define _Noreturn __declspec (noreturn)
-# else
-# define _Noreturn YY_ATTRIBUTE ((__noreturn__))
-# endif
-#endif
-
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
# define YYUSE(E) ((void) (E))
@@ -291,7 +290,7 @@ typedef short int yytype_int16;
# define YYUSE(E) /* empty */
#endif
-#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
_Pragma ("GCC diagnostic push") \
@@ -453,16 +452,16 @@ union yyalloc
/* YYNSTATES -- Number of states. */
#define YYNSTATES 33
-/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
- by yylex, with out-of-bounds checking. */
#define YYUNDEFTOK 2
#define YYMAXUTOK 269
+/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, with out-of-bounds checking. */
#define YYTRANSLATE(YYX) \
- ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+ ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
- as returned by yylex, without out-of-bounds checking. */
+ as returned by yylex. */
static const yytype_uint8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -498,9 +497,9 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 96, 96, 102, 105, 110, 113, 118, 121, 126,
- 129, 132, 135, 138, 141, 146, 149, 152, 155, 160,
- 163, 168, 171, 176, 179
+ 0, 99, 99, 105, 108, 113, 116, 121, 124, 129,
+ 132, 135, 138, 141, 144, 149, 152, 155, 158, 163,
+ 166, 171, 174, 179, 182
};
#endif
@@ -630,22 +629,22 @@ static const yytype_uint8 yyr2[] =
#define YYRECOVERING() (!!yyerrstatus)
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- YYPOPSTACK (yylen); \
- yystate = *yyssp; \
- goto yybackup; \
- } \
- else \
- { \
- yyerror (yyscanner, YY_("syntax error: cannot back up")); \
- YYERROR; \
- } \
-while (0)
+#define YYBACKUP(Token, Value) \
+ do \
+ if (yychar == YYEMPTY) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ YYPOPSTACK (yylen); \
+ yystate = *yyssp; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (yyscanner, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+ while (0)
/* Error token number */
#define YYTERROR 1
@@ -685,38 +684,38 @@ do { \
} while (0)
-/*----------------------------------------.
-| Print this symbol's value on YYOUTPUT. |
-`----------------------------------------*/
+/*-----------------------------------.
+| Print this symbol's value on YYO. |
+`-----------------------------------*/
static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
- FILE *yyo = yyoutput;
- YYUSE (yyo);
+ FILE *yyoutput = yyo;
+ YYUSE (yyoutput);
YYUSE (yyscanner);
if (!yyvaluep)
return;
# ifdef YYPRINT
if (yytype < YYNTOKENS)
- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+ YYPRINT (yyo, yytoknum[yytype], *yyvaluep);
# endif
YYUSE (yytype);
}
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
+/*---------------------------.
+| Print this symbol on YYO. |
+`---------------------------*/
static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
- YYFPRINTF (yyoutput, "%s %s (",
+ YYFPRINTF (yyo, "%s %s (",
yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
- yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
- YYFPRINTF (yyoutput, ")");
+ yy_symbol_value_print (yyo, yytype, yyvaluep, yyscanner);
+ YYFPRINTF (yyo, ")");
}
/*------------------------------------------------------------------.
@@ -750,7 +749,7 @@ do { \
static void
yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
{
- unsigned long int yylno = yyrline[yyrule];
+ unsigned long yylno = yyrline[yyrule];
int yynrhs = yyr2[yyrule];
int yyi;
YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
@@ -761,7 +760,7 @@ yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yysca
YYFPRINTF (stderr, " $%d = ", yyi + 1);
yy_symbol_print (stderr,
yystos[yyssp[yyi + 1 - yynrhs]],
- &(yyvsp[(yyi + 1) - (yynrhs)])
+ &yyvsp[(yyi + 1) - (yynrhs)]
, yyscanner);
YYFPRINTF (stderr, "\n");
}
@@ -865,7 +864,10 @@ yytnamerr (char *yyres, const char *yystr)
case '\\':
if (*++yyp != '\\')
goto do_not_strip_quotes;
- /* Fall through. */
+ else
+ goto append;
+
+ append:
default:
if (yyres)
yyres[yyn] = *yyp;
@@ -883,7 +885,7 @@ yytnamerr (char *yyres, const char *yystr)
if (! yyres)
return yystrlen (yystr);
- return yystpcpy (yyres, yystr) - yyres;
+ return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres);
}
# endif
@@ -961,10 +963,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
yyarg[yycount++] = yytname[yyx];
{
YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
- if (! (yysize <= yysize1
- && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+ yysize = yysize1;
+ else
return 2;
- yysize = yysize1;
}
}
}
@@ -976,6 +978,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
case N: \
yyformat = S; \
break
+ default: /* Avoid compiler warnings. */
YYCASE_(0, YY_("syntax error"));
YYCASE_(1, YY_("syntax error, unexpected %s"));
YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
@@ -987,9 +990,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
{
YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
- if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+ yysize = yysize1;
+ else
return 2;
- yysize = yysize1;
}
if (*yymsg_alloc < yysize)
@@ -1120,23 +1124,31 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
yychar = YYEMPTY; /* Cause a token to be read. */
goto yysetstate;
+
/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate. |
+| yynewstate -- push a new state, which is found in yystate. |
`------------------------------------------------------------*/
- yynewstate:
+yynewstate:
/* In all cases, when you get here, the value and location stacks
have just been pushed. So pushing a state here evens the stacks. */
yyssp++;
- yysetstate:
- *yyssp = yystate;
+
+/*--------------------------------------------------------------------.
+| yynewstate -- set current state (the top of the stack) to yystate. |
+`--------------------------------------------------------------------*/
+yysetstate:
+ *yyssp = (yytype_int16) yystate;
if (yyss + yystacksize - 1 <= yyssp)
+#if !defined yyoverflow && !defined YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+#else
{
/* Get the current used size of the three stacks, in elements. */
- YYSIZE_T yysize = yyssp - yyss + 1;
+ YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1);
-#ifdef yyoverflow
+# if defined yyoverflow
{
/* Give user a chance to reallocate the stack. Use copies of
these so that the &'s don't force the real ones into
@@ -1152,14 +1164,10 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
&yyss1, yysize * sizeof (*yyssp),
&yyvs1, yysize * sizeof (*yyvsp),
&yystacksize);
-
yyss = yyss1;
yyvs = yyvs1;
}
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
- goto yyexhaustedlab;
-# else
+# else /* defined YYSTACK_RELOCATE */
/* Extend the stack our own way. */
if (YYMAXDEPTH <= yystacksize)
goto yyexhaustedlab;
@@ -1175,22 +1183,22 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
goto yyexhaustedlab;
YYSTACK_RELOCATE (yyss_alloc, yyss);
YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-# undef YYSTACK_RELOCATE
+# undef YYSTACK_RELOCATE
if (yyss1 != yyssa)
YYSTACK_FREE (yyss1);
}
# endif
-#endif /* no yyoverflow */
yyssp = yyss + yysize - 1;
yyvsp = yyvs + yysize - 1;
YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long int) yystacksize));
+ (unsigned long) yystacksize));
if (yyss + yystacksize - 1 <= yyssp)
YYABORT;
}
+#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
@@ -1199,11 +1207,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
goto yybackup;
+
/*-----------.
| yybackup. |
`-----------*/
yybackup:
-
/* Do appropriate processing given the current state. Read a
lookahead token if we need one and don't already have one. */
@@ -1276,7 +1284,7 @@ yydefault:
/*-----------------------------.
-| yyreduce -- Do a reduction. |
+| yyreduce -- do a reduction. |
`-----------------------------*/
yyreduce:
/* yyn is the number of a rule to reduce with. */
@@ -1297,192 +1305,192 @@ yyreduce:
switch (yyn)
{
case 2:
-#line 96 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 99 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = 0;
yyGetParser->SetResult((yyvsp[0].str));
}
-#line 1306 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1314 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 3:
-#line 102 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 105 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1314 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1322 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 4:
-#line 105 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 108 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
}
-#line 1322 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1330 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 5:
-#line 110 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 113 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = 0;
}
-#line 1330 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1338 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 6:
-#line 113 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 116 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
}
-#line 1338 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1346 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 7:
-#line 118 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 121 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1346 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1354 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 8:
-#line 121 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 124 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1354 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1362 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 9:
-#line 126 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 129 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1362 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1370 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 10:
-#line 129 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 132 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1370 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1378 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 11:
-#line 132 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 135 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1378 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1386 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 12:
-#line 135 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 138 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1386 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1394 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 13:
-#line 138 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 141 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1394 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1402 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 14:
-#line 141 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 144 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1402 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1410 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 15:
-#line 146 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 149 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str));
}
-#line 1410 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1418 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 16:
-#line 149 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 152 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str));
}
-#line 1418 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1426 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 17:
-#line 152 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 155 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str));
}
-#line 1426 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1434 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 18:
-#line 155 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 158 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str));
}
-#line 1434 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1442 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 19:
-#line 160 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 163 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1442 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1450 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 20:
-#line 163 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 166 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = (yyvsp[-1].str);
}
-#line 1450 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1458 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 21:
-#line 168 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 171 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = 0;
}
-#line 1458 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1466 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 22:
-#line 171 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 174 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str));
}
-#line 1466 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1474 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 23:
-#line 176 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 179 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1474 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1482 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
case 24:
-#line 179 "cmCommandArgumentParser.y" /* yacc.c:1646 */
+#line 182 "cmCommandArgumentParser.y" /* yacc.c:1652 */
{
(yyval.str) = (yyvsp[0].str);
}
-#line 1482 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1490 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
break;
-#line 1486 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */
+#line 1494 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -1507,14 +1515,13 @@ yyreduce:
/* Now 'shift' the result of the reduction. Determine what state
that goes to, based on the state we popped back to and the rule
number reduced by. */
-
- yyn = yyr1[yyn];
-
- yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
- if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
- yystate = yytable[yystate];
- else
- yystate = yydefgoto[yyn - YYNTOKENS];
+ {
+ const int yylhs = yyr1[yyn] - YYNTOKENS;
+ const int yyi = yypgoto[yylhs] + *yyssp;
+ yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp
+ ? yytable[yyi]
+ : yydefgoto[yylhs]);
+ }
goto yynewstate;
@@ -1598,12 +1605,10 @@ yyerrlab:
| yyerrorlab -- error raised explicitly by YYERROR. |
`---------------------------------------------------*/
yyerrorlab:
-
- /* Pacify compilers like GCC when the user code never invokes
- YYERROR and the label yyerrorlab therefore never appears in user
- code. */
- if (/*CONSTCOND*/ 0)
- goto yyerrorlab;
+ /* Pacify compilers when the user code never invokes YYERROR and the
+ label yyerrorlab therefore never appears in user code. */
+ if (0)
+ YYERROR;
/* Do not reclaim the symbols of the rule whose action triggered
this YYERROR. */
@@ -1666,6 +1671,7 @@ yyacceptlab:
yyresult = 0;
goto yyreturn;
+
/*-----------------------------------.
| yyabortlab -- YYABORT comes here. |
`-----------------------------------*/
@@ -1673,6 +1679,7 @@ yyabortlab:
yyresult = 1;
goto yyreturn;
+
#if !defined yyoverflow || YYERROR_VERBOSE
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
@@ -1683,6 +1690,10 @@ yyexhaustedlab:
/* Fall through. */
#endif
+
+/*-----------------------------------------------------.
+| yyreturn -- parsing is finished, return the result. |
+`-----------------------------------------------------*/
yyreturn:
if (yychar != YYEMPTY)
{
@@ -1712,7 +1723,7 @@ yyreturn:
#endif
return yyresult;
}
-#line 184 "cmCommandArgumentParser.y" /* yacc.c:1906 */
+#line 187 "cmCommandArgumentParser.y" /* yacc.c:1918 */
/* End of grammar */
diff --git a/Source/LexerParser/cmCommandArgumentParser.y b/Source/LexerParser/cmCommandArgumentParser.y
index 55a88dffa..0c6aad547 100644
--- a/Source/LexerParser/cmCommandArgumentParser.y
+++ b/Source/LexerParser/cmCommandArgumentParser.y
@@ -55,6 +55,9 @@ static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message);
# pragma warning (disable: 4244) /* loss of precision */
# pragma warning (disable: 4702) /* unreachable code */
#endif
+#if defined(__GNUC__) && __GNUC__ >= 8
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif
%}
/* Generate a reentrant parser object. */
diff --git a/Source/LexerParser/cmCommandArgumentParserTokens.h b/Source/LexerParser/cmCommandArgumentParserTokens.h
index 3172182d7..56c9794f9 100644
--- a/Source/LexerParser/cmCommandArgumentParserTokens.h
+++ b/Source/LexerParser/cmCommandArgumentParserTokens.h
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4. */
+/* A Bison parser, made by GNU Bison 3.3.2. */
/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+ Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,6 +31,9 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
+/* Undocumented macros, especially those whose name start with YY_,
+ are private implementation details. Do not rely on them. */
+
#ifndef YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED
# define YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED
/* Debug traces. */
diff --git a/Source/LexerParser/cmDependsJavaLexer.cxx b/Source/LexerParser/cmDependsJavaLexer.cxx
index 8159f47bb..d703e3c95 100644
--- a/Source/LexerParser/cmDependsJavaLexer.cxx
+++ b/Source/LexerParser/cmDependsJavaLexer.cxx
@@ -1,7 +1,4 @@
#include "cmStandardLexer.h"
-#line 2 "cmDependsJavaLexer.cxx"
-
-#line 4 "cmDependsJavaLexer.cxx"
#define FLEXINT_H 1
#define YY_INT_ALIGNED short int
@@ -11,11 +8,221 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6
-#define YY_FLEX_SUBMINOR_VERSION 1
+#define YY_FLEX_SUBMINOR_VERSION 4
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
+#ifdef yy_create_buffer
+#define cmDependsJava_yy_create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer cmDependsJava_yy_create_buffer
+#endif
+
+#ifdef yy_delete_buffer
+#define cmDependsJava_yy_delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer cmDependsJava_yy_delete_buffer
+#endif
+
+#ifdef yy_scan_buffer
+#define cmDependsJava_yy_scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer cmDependsJava_yy_scan_buffer
+#endif
+
+#ifdef yy_scan_string
+#define cmDependsJava_yy_scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string cmDependsJava_yy_scan_string
+#endif
+
+#ifdef yy_scan_bytes
+#define cmDependsJava_yy_scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes cmDependsJava_yy_scan_bytes
+#endif
+
+#ifdef yy_init_buffer
+#define cmDependsJava_yy_init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer cmDependsJava_yy_init_buffer
+#endif
+
+#ifdef yy_flush_buffer
+#define cmDependsJava_yy_flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer cmDependsJava_yy_flush_buffer
+#endif
+
+#ifdef yy_load_buffer_state
+#define cmDependsJava_yy_load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state cmDependsJava_yy_load_buffer_state
+#endif
+
+#ifdef yy_switch_to_buffer
+#define cmDependsJava_yy_switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer cmDependsJava_yy_switch_to_buffer
+#endif
+
+#ifdef yypush_buffer_state
+#define cmDependsJava_yypush_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state cmDependsJava_yypush_buffer_state
+#endif
+
+#ifdef yypop_buffer_state
+#define cmDependsJava_yypop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state cmDependsJava_yypop_buffer_state
+#endif
+
+#ifdef yyensure_buffer_stack
+#define cmDependsJava_yyensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack cmDependsJava_yyensure_buffer_stack
+#endif
+
+#ifdef yylex
+#define cmDependsJava_yylex_ALREADY_DEFINED
+#else
+#define yylex cmDependsJava_yylex
+#endif
+
+#ifdef yyrestart
+#define cmDependsJava_yyrestart_ALREADY_DEFINED
+#else
+#define yyrestart cmDependsJava_yyrestart
+#endif
+
+#ifdef yylex_init
+#define cmDependsJava_yylex_init_ALREADY_DEFINED
+#else
+#define yylex_init cmDependsJava_yylex_init
+#endif
+
+#ifdef yylex_init_extra
+#define cmDependsJava_yylex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra cmDependsJava_yylex_init_extra
+#endif
+
+#ifdef yylex_destroy
+#define cmDependsJava_yylex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy cmDependsJava_yylex_destroy
+#endif
+
+#ifdef yyget_debug
+#define cmDependsJava_yyget_debug_ALREADY_DEFINED
+#else
+#define yyget_debug cmDependsJava_yyget_debug
+#endif
+
+#ifdef yyset_debug
+#define cmDependsJava_yyset_debug_ALREADY_DEFINED
+#else
+#define yyset_debug cmDependsJava_yyset_debug
+#endif
+
+#ifdef yyget_extra
+#define cmDependsJava_yyget_extra_ALREADY_DEFINED
+#else
+#define yyget_extra cmDependsJava_yyget_extra
+#endif
+
+#ifdef yyset_extra
+#define cmDependsJava_yyset_extra_ALREADY_DEFINED
+#else
+#define yyset_extra cmDependsJava_yyset_extra
+#endif
+
+#ifdef yyget_in
+#define cmDependsJava_yyget_in_ALREADY_DEFINED
+#else
+#define yyget_in cmDependsJava_yyget_in
+#endif
+
+#ifdef yyset_in
+#define cmDependsJava_yyset_in_ALREADY_DEFINED
+#else
+#define yyset_in cmDependsJava_yyset_in
+#endif
+
+#ifdef yyget_out
+#define cmDependsJava_yyget_out_ALREADY_DEFINED
+#else
+#define yyget_out cmDependsJava_yyget_out
+#endif
+
+#ifdef yyset_out
+#define cmDependsJava_yyset_out_ALREADY_DEFINED
+#else
+#define yyset_out cmDependsJava_yyset_out
+#endif
+
+#ifdef yyget_leng
+#define cmDependsJava_yyget_leng_ALREADY_DEFINED
+#else
+#define yyget_leng cmDependsJava_yyget_leng
+#endif
+
+#ifdef yyget_text
+#define cmDependsJava_yyget_text_ALREADY_DEFINED
+#else
+#define yyget_text cmDependsJava_yyget_text
+#endif
+
+#ifdef yyget_lineno
+#define cmDependsJava_yyget_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno cmDependsJava_yyget_lineno
+#endif
+
+#ifdef yyset_lineno
+#define cmDependsJava_yyset_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno cmDependsJava_yyset_lineno
+#endif
+
+#ifdef yyget_column
+#define cmDependsJava_yyget_column_ALREADY_DEFINED
+#else
+#define yyget_column cmDependsJava_yyget_column
+#endif
+
+#ifdef yyset_column
+#define cmDependsJava_yyset_column_ALREADY_DEFINED
+#else
+#define yyset_column cmDependsJava_yyset_column
+#endif
+
+#ifdef yywrap
+#define cmDependsJava_yywrap_ALREADY_DEFINED
+#else
+#define yywrap cmDependsJava_yywrap
+#endif
+
+#ifdef yyalloc
+#define cmDependsJava_yyalloc_ALREADY_DEFINED
+#else
+#define yyalloc cmDependsJava_yyalloc
+#endif
+
+#ifdef yyrealloc
+#define cmDependsJava_yyrealloc_ALREADY_DEFINED
+#else
+#define yyrealloc cmDependsJava_yyrealloc
+#endif
+
+#ifdef yyfree
+#define cmDependsJava_yyfree_ALREADY_DEFINED
+#else
+#define yyfree cmDependsJava_yyfree
+#endif
+
/* First, we deal with platform-specific or compiler-specific issues. */
/* begin standard C headers. */
@@ -86,10 +293,16 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
+#ifndef SIZE_MAX
+#define SIZE_MAX (~(size_t)0)
+#endif
+
#endif /* ! C99 */
#endif /* ! FLEXINT_H */
+/* begin standard C++ headers. */
+
/* TODO: this is always defined, so inline it */
#define yyconst const
@@ -102,12 +315,10 @@ typedef unsigned int flex_uint32_t;
/* Returned upon end-of-file. */
#define YY_NULL 0
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index. If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
+/* Promotes a possibly negative, possibly signed char to an
+ * integer in range [0..255] for use as an array index.
*/
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+#define YY_SC_TO_UI(c) ((YY_CHAR) (c))
/* An opaque pointer. */
#ifndef YY_TYPEDEF_YY_SCANNER_T
@@ -131,20 +342,16 @@ typedef void* yyscan_t;
* definition of BEGIN.
*/
#define BEGIN yyg->yy_start = 1 + 2 *
-
/* Translate the current start state into a value that can be later handed
* to BEGIN to return to the state. The YYSTATE alias is for lex
* compatibility.
*/
#define YY_START ((yyg->yy_start - 1) / 2)
#define YYSTATE YY_START
-
/* Action number for EOF rule of a given start state. */
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE cmDependsJava_yyrestart(yyin ,yyscanner )
-
+#define YY_NEW_FILE yyrestart( yyin , yyscanner )
#define YY_END_OF_BUFFER_CHAR 0
/* Size of default input buffer. */
@@ -194,7 +401,6 @@ typedef size_t yy_size_t;
YY_DO_BEFORE_ACTION; /* set up yytext again */ \
} \
while ( 0 )
-
#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
#ifndef YY_STRUCT_YY_BUFFER_STATE
@@ -254,7 +460,7 @@ struct yy_buffer_state
* possible backing-up.
*
* When we actually see the EOF, we change the status to "new"
- * (via cmDependsJava_yyrestart()), so that the user can continue scanning by
+ * (via yyrestart()), so that the user can continue scanning by
* just pointing yyin at a new input file.
*/
#define YY_BUFFER_EOF_PENDING 2
@@ -271,73 +477,67 @@ struct yy_buffer_state
#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
: NULL)
-
/* Same as previous macro, but useful when we know that the buffer stack is not
* NULL or when we need an lvalue. For internal use only.
*/
#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
-void cmDependsJava_yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void cmDependsJava_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmDependsJava_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void cmDependsJava_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmDependsJava_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmDependsJava_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void cmDependsJava_yypop_buffer_state (yyscan_t yyscanner );
-
-static void cmDependsJava_yyensure_buffer_stack (yyscan_t yyscanner );
-static void cmDependsJava_yy_load_buffer_state (yyscan_t yyscanner );
-static void cmDependsJava_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
-
-#define YY_FLUSH_BUFFER cmDependsJava_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+void yyrestart ( FILE *input_file , yyscan_t yyscanner );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
+void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+void yypop_buffer_state ( yyscan_t yyscanner );
-YY_BUFFER_STATE cmDependsJava_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmDependsJava_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmDependsJava_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+static void yyensure_buffer_stack ( yyscan_t yyscanner );
+static void yy_load_buffer_state ( yyscan_t yyscanner );
+static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner );
+#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner)
-void *cmDependsJava_yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *cmDependsJava_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void cmDependsJava_yyfree (void * ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
-#define yy_new_buffer cmDependsJava_yy_create_buffer
+void *yyalloc ( yy_size_t , yyscan_t yyscanner );
+void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
+void yyfree ( void * , yyscan_t yyscanner );
+#define yy_new_buffer yy_create_buffer
#define yy_set_interactive(is_interactive) \
{ \
if ( ! YY_CURRENT_BUFFER ){ \
- cmDependsJava_yyensure_buffer_stack (yyscanner); \
+ yyensure_buffer_stack (yyscanner); \
YY_CURRENT_BUFFER_LVALUE = \
- cmDependsJava_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
} \
YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
}
-
#define yy_set_bol(at_bol) \
{ \
if ( ! YY_CURRENT_BUFFER ){\
- cmDependsJava_yyensure_buffer_stack (yyscanner); \
+ yyensure_buffer_stack (yyscanner); \
YY_CURRENT_BUFFER_LVALUE = \
- cmDependsJava_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
} \
YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
}
-
#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
/* Begin user sect3 */
#define cmDependsJava_yywrap(yyscanner) (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
-
-typedef unsigned char YY_CHAR;
+typedef flex_uint8_t YY_CHAR;
typedef int yy_state_type;
#define yytext_ptr yytext_r
-static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
-static int yy_get_next_buffer (yyscan_t yyscanner );
-static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
+static yy_state_type yy_get_previous_state ( yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans ( yy_state_type current_state , yyscan_t yyscanner);
+static int yy_get_next_buffer ( yyscan_t yyscanner );
+static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner );
/* Done after the current pattern has been matched and before the
* corresponding action - sets up yytext.
@@ -348,7 +548,6 @@ static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
yyg->yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
-
#define YY_NUM_RULES 111
#define YY_END_OF_BUFFER 112
/* This struct is not used in this scanner,
@@ -358,7 +557,7 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[327] =
+static const flex_int16_t yy_accept[327] =
{ 0,
0, 0, 0, 0, 0, 0, 112, 110, 109, 109,
77, 4, 73, 94, 60, 110, 93, 92, 105, 99,
@@ -398,7 +597,7 @@ static yyconst flex_int16_t yy_accept[327] =
27, 29, 107, 107, 45, 0
} ;
-static yyconst YY_CHAR yy_ec[256] =
+static const YY_CHAR yy_ec[256] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
1, 2, 2, 1, 1, 1, 1, 1, 1, 1,
@@ -430,7 +629,7 @@ static yyconst YY_CHAR yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst YY_CHAR yy_meta[65] =
+static const YY_CHAR yy_meta[65] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 2, 1,
1, 1, 1, 1, 1, 1, 1, 3, 3, 3,
@@ -441,7 +640,7 @@ static yyconst YY_CHAR yy_meta[65] =
1, 1, 1, 1
} ;
-static yyconst flex_uint16_t yy_base[334] =
+static const flex_int16_t yy_base[334] =
{ 0,
0, 0, 401, 400, 62, 63, 411, 414, 414, 414,
386, 414, 414, 385, 61, 374, 414, 414, 383, 57,
@@ -482,7 +681,7 @@ static yyconst flex_uint16_t yy_base[334] =
232, 96, 235
} ;
-static yyconst flex_int16_t yy_def[334] =
+static const flex_int16_t yy_def[334] =
{ 0,
326, 1, 327, 327, 328, 328, 326, 326, 326, 326,
326, 326, 326, 326, 326, 329, 326, 326, 326, 326,
@@ -523,7 +722,7 @@ static yyconst flex_int16_t yy_def[334] =
326, 326, 326
} ;
-static yyconst flex_uint16_t yy_nxt[479] =
+static const flex_int16_t yy_nxt[479] =
{ 0,
8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 26,
@@ -579,7 +778,7 @@ static yyconst flex_uint16_t yy_nxt[479] =
326, 326, 326, 326, 326, 326, 326, 326
} ;
-static yyconst flex_int16_t yy_chk[479] =
+static const flex_int16_t yy_chk[479] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -642,8 +841,6 @@ static yyconst flex_int16_t yy_chk[479] =
#define yymore() yymore_used_but_not_detected
#define YY_MORE_ADJ 0
#define YY_RESTORE_YY_MORE_OFFSET
-#line 1 "cmDependsJavaLexer.in.l"
-#line 2 "cmDependsJavaLexer.in.l"
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
/*
@@ -652,18 +849,19 @@ This file must be translated to C++ and modified to build everywhere.
Run flex >= 2.6 like this:
- flex --nounistd -DFLEXINT_H --prefix=cmDependsJava_yy --header-file=cmDependsJavaLexer.h -ocmDependsJavaLexer.cxx cmDependsJavaLexer.in.l
+ flex --nounistd -DFLEXINT_H --noline --header-file=cmDependsJavaLexer.h -ocmDependsJavaLexer.cxx cmDependsJavaLexer.in.l
Modify cmDependsJavaLexer.cxx:
- - remove trailing whitespace: sed -i 's/\s*$//' cmDependsJavaLexer.h cmDependsJavaLexer.cxx
- - remove blank lines at end of file
- - #include "cmStandardLexer.h" at the top
- - add cast in cmDependsJava_yy_scan_bytes for loop condition of _yybytes_len to size_t
+ - remove trailing whitespace: sed -i 's/\s*$//' cmDependsJavaLexer.h cmDependsJavaLexer.cxx
+ - remove blank lines at end of file: sed -i '${/^$/d;}' cmDependsJavaLexer.h cmDependsJavaLexer.cxx
+ - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmDependsJavaLexer.cxx
*/
/* IWYU pragma: no_forward_declare yyguts_t */
+#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+
#include <iostream>
#include "cmDependsJavaParserHelper.h"
@@ -671,7 +869,7 @@ Modify cmDependsJavaLexer.cxx:
/* Replace the lexer input function. */
#undef YY_INPUT
#define YY_INPUT(buf, result, max_size) \
- { result = yyextra->LexInput(buf, max_size); }
+ do { result = yyextra->LexInput(buf, max_size); } while (0)
/* Include the set of tokens from the parser. */
#include "cmDependsJavaParserTokens.h"
@@ -682,9 +880,6 @@ Modify cmDependsJavaLexer.cxx:
/*--------------------------------------------------------------------------*/
-
-#line 686 "cmDependsJavaLexer.cxx"
-
#define INITIAL 0
#define comment 1
#define string 2
@@ -727,44 +922,44 @@ struct yyguts_t
}; /* end struct yyguts_t */
-static int yy_init_globals (yyscan_t yyscanner );
+static int yy_init_globals ( yyscan_t yyscanner );
-int cmDependsJava_yylex_init (yyscan_t* scanner);
+int yylex_init (yyscan_t* scanner);
-int cmDependsJava_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
-int cmDependsJava_yylex_destroy (yyscan_t yyscanner );
+int yylex_destroy ( yyscan_t yyscanner );
-int cmDependsJava_yyget_debug (yyscan_t yyscanner );
+int yyget_debug ( yyscan_t yyscanner );
-void cmDependsJava_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+void yyset_debug ( int debug_flag , yyscan_t yyscanner );
-YY_EXTRA_TYPE cmDependsJava_yyget_extra (yyscan_t yyscanner );
+YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
-void cmDependsJava_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
-FILE *cmDependsJava_yyget_in (yyscan_t yyscanner );
+FILE *yyget_in ( yyscan_t yyscanner );
-void cmDependsJava_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
+void yyset_in ( FILE * _in_str , yyscan_t yyscanner );
-FILE *cmDependsJava_yyget_out (yyscan_t yyscanner );
+FILE *yyget_out ( yyscan_t yyscanner );
-void cmDependsJava_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
+void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
- int cmDependsJava_yyget_leng (yyscan_t yyscanner );
+ int yyget_leng ( yyscan_t yyscanner );
-char *cmDependsJava_yyget_text (yyscan_t yyscanner );
+char *yyget_text ( yyscan_t yyscanner );
-int cmDependsJava_yyget_lineno (yyscan_t yyscanner );
+int yyget_lineno ( yyscan_t yyscanner );
-void cmDependsJava_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+void yyset_lineno ( int _line_number , yyscan_t yyscanner );
-int cmDependsJava_yyget_column (yyscan_t yyscanner );
+int yyget_column ( yyscan_t yyscanner );
-void cmDependsJava_yyset_column (int _column_no ,yyscan_t yyscanner );
+void yyset_column ( int _column_no , yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -772,32 +967,31 @@ void cmDependsJava_yyset_column (int _column_no ,yyscan_t yyscanner );
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
-extern "C" int cmDependsJava_yywrap (yyscan_t yyscanner );
+extern "C" int yywrap ( yyscan_t yyscanner );
#else
-extern int cmDependsJava_yywrap (yyscan_t yyscanner );
+extern int yywrap ( yyscan_t yyscanner );
#endif
#endif
#ifndef YY_NO_UNPUT
- static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner);
+ static void yyunput ( int c, char *buf_ptr , yyscan_t yyscanner);
#endif
#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
#endif
#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
#endif
#ifndef YY_NO_INPUT
-
#ifdef __cplusplus
-static int yyinput (yyscan_t yyscanner );
+static int yyinput ( yyscan_t yyscanner );
#else
-static int input (yyscan_t yyscanner );
+static int input ( yyscan_t yyscanner );
#endif
#endif
@@ -828,7 +1022,7 @@ static int input (yyscan_t yyscanner );
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
- size_t n; \
+ int n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@@ -841,7 +1035,7 @@ static int input (yyscan_t yyscanner );
else \
{ \
errno=0; \
- while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \
{ \
if( errno != EINTR) \
{ \
@@ -882,9 +1076,9 @@ static int input (yyscan_t yyscanner );
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
-extern int cmDependsJava_yylex (yyscan_t yyscanner);
+extern int yylex (yyscan_t yyscanner);
-#define YY_DECL int cmDependsJava_yylex (yyscan_t yyscanner)
+#define YY_DECL int yylex (yyscan_t yyscanner)
#endif /* !YY_DECL */
/* Code executed at the beginning of each rule, after yytext and yyleng
@@ -929,18 +1123,15 @@ YY_DECL
yyout = stdout;
if ( ! YY_CURRENT_BUFFER ) {
- cmDependsJava_yyensure_buffer_stack (yyscanner);
+ yyensure_buffer_stack (yyscanner);
YY_CURRENT_BUFFER_LVALUE =
- cmDependsJava_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner);
}
- cmDependsJava_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
}
{
-#line 48 "cmDependsJavaLexer.in.l"
-
-#line 943 "cmDependsJavaLexer.cxx"
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
@@ -968,9 +1159,9 @@ yy_match:
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 327 )
- yy_c = yy_meta[(unsigned int) yy_c];
+ yy_c = yy_meta[yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
++yy_cp;
}
while ( yy_base[yy_current_state] != 414 );
@@ -999,539 +1190,432 @@ do_action: /* This label is used only to access EOF actions. */
case 1:
YY_RULE_SETUP
-#line 49 "cmDependsJavaLexer.in.l"
{ BEGIN(comment); }
YY_BREAK
case 2:
YY_RULE_SETUP
-#line 50 "cmDependsJavaLexer.in.l"
{ BEGIN(INITIAL); }
YY_BREAK
case 3:
/* rule 3 can match eol */
YY_RULE_SETUP
-#line 51 "cmDependsJavaLexer.in.l"
{}
YY_BREAK
case 4:
YY_RULE_SETUP
-#line 53 "cmDependsJavaLexer.in.l"
{ BEGIN(string); }
YY_BREAK
case 5:
YY_RULE_SETUP
-#line 54 "cmDependsJavaLexer.in.l"
{ BEGIN(INITIAL); return jp_STRINGLITERAL; }
YY_BREAK
case 6:
YY_RULE_SETUP
-#line 55 "cmDependsJavaLexer.in.l"
{}
YY_BREAK
case 7:
YY_RULE_SETUP
-#line 57 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_ABSTRACT; }
YY_BREAK
case 8:
YY_RULE_SETUP
-#line 58 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_ASSERT; }
YY_BREAK
case 9:
YY_RULE_SETUP
-#line 59 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_BOOLEAN_TYPE; }
YY_BREAK
case 10:
YY_RULE_SETUP
-#line 60 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_BREAK; }
YY_BREAK
case 11:
YY_RULE_SETUP
-#line 61 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_BYTE_TYPE; }
YY_BREAK
case 12:
YY_RULE_SETUP
-#line 62 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_CASE; }
YY_BREAK
case 13:
YY_RULE_SETUP
-#line 63 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_CATCH; }
YY_BREAK
case 14:
YY_RULE_SETUP
-#line 64 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_CHAR_TYPE; }
YY_BREAK
case 15:
YY_RULE_SETUP
-#line 65 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_CLASS; }
YY_BREAK
case 16:
YY_RULE_SETUP
-#line 66 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_CONTINUE; }
YY_BREAK
case 17:
YY_RULE_SETUP
-#line 67 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_DEFAULT; }
YY_BREAK
case 18:
YY_RULE_SETUP
-#line 68 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_DO; }
YY_BREAK
case 19:
YY_RULE_SETUP
-#line 69 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_DOUBLE_TYPE; }
YY_BREAK
case 20:
YY_RULE_SETUP
-#line 70 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_ELSE; }
YY_BREAK
case 21:
YY_RULE_SETUP
-#line 71 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_EXTENDS; }
YY_BREAK
case 22:
YY_RULE_SETUP
-#line 72 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_FINAL; }
YY_BREAK
case 23:
YY_RULE_SETUP
-#line 73 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_FINALLY; }
YY_BREAK
case 24:
YY_RULE_SETUP
-#line 74 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_FLOAT_TYPE; }
YY_BREAK
case 25:
YY_RULE_SETUP
-#line 75 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_FOR; }
YY_BREAK
case 26:
YY_RULE_SETUP
-#line 76 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_IF; }
YY_BREAK
case 27:
YY_RULE_SETUP
-#line 77 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_IMPLEMENTS; }
YY_BREAK
case 28:
YY_RULE_SETUP
-#line 78 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_IMPORT; }
YY_BREAK
case 29:
YY_RULE_SETUP
-#line 79 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_INSTANCEOF; }
YY_BREAK
case 30:
YY_RULE_SETUP
-#line 80 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_INT_TYPE; }
YY_BREAK
case 31:
YY_RULE_SETUP
-#line 81 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_INTERFACE; }
YY_BREAK
case 32:
YY_RULE_SETUP
-#line 82 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_LONG_TYPE; }
YY_BREAK
case 33:
YY_RULE_SETUP
-#line 83 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_NATIVE; }
YY_BREAK
case 34:
YY_RULE_SETUP
-#line 84 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_NEW; }
YY_BREAK
case 35:
YY_RULE_SETUP
-#line 85 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_PACKAGE; }
YY_BREAK
case 36:
YY_RULE_SETUP
-#line 86 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_PRIVATE; }
YY_BREAK
case 37:
YY_RULE_SETUP
-#line 87 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_PROTECTED; }
YY_BREAK
case 38:
YY_RULE_SETUP
-#line 88 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_PUBLIC; }
YY_BREAK
case 39:
YY_RULE_SETUP
-#line 89 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_RETURN; }
YY_BREAK
case 40:
YY_RULE_SETUP
-#line 90 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_SHORT_TYPE; }
YY_BREAK
case 41:
YY_RULE_SETUP
-#line 91 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_STATIC; }
YY_BREAK
case 42:
YY_RULE_SETUP
-#line 92 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_STRICTFP; }
YY_BREAK
case 43:
YY_RULE_SETUP
-#line 93 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_SUPER; }
YY_BREAK
case 44:
YY_RULE_SETUP
-#line 94 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_SWITCH; }
YY_BREAK
case 45:
YY_RULE_SETUP
-#line 95 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_SYNCHRONIZED; }
YY_BREAK
case 46:
YY_RULE_SETUP
-#line 96 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_THIS; }
YY_BREAK
case 47:
YY_RULE_SETUP
-#line 97 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_THROW; }
YY_BREAK
case 48:
YY_RULE_SETUP
-#line 98 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_THROWS; }
YY_BREAK
case 49:
YY_RULE_SETUP
-#line 99 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_TRANSIENT; }
YY_BREAK
case 50:
YY_RULE_SETUP
-#line 100 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_TRY; }
YY_BREAK
case 51:
YY_RULE_SETUP
-#line 101 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_VOID; }
YY_BREAK
case 52:
YY_RULE_SETUP
-#line 102 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_VOLATILE; }
YY_BREAK
case 53:
YY_RULE_SETUP
-#line 103 "cmDependsJavaLexer.in.l"
{ KEYWORD; return jp_WHILE; }
YY_BREAK
case 54:
YY_RULE_SETUP
-#line 105 "cmDependsJavaLexer.in.l"
{ PRIMITIVE; return jp_BOOLEANLITERAL; }
YY_BREAK
case 55:
/* rule 55 can match eol */
YY_RULE_SETUP
-#line 106 "cmDependsJavaLexer.in.l"
{ PRIMITIVE; return jp_CHARACTERLITERAL; }
YY_BREAK
case 56:
YY_RULE_SETUP
-#line 107 "cmDependsJavaLexer.in.l"
{ PRIMITIVE; return jp_DECIMALINTEGERLITERAL; }
YY_BREAK
case 57:
YY_RULE_SETUP
-#line 108 "cmDependsJavaLexer.in.l"
{ PRIMITIVE; return jp_FLOATINGPOINTLITERAL; }
YY_BREAK
case 58:
YY_RULE_SETUP
-#line 109 "cmDependsJavaLexer.in.l"
{ PRIMITIVE; return jp_HEXINTEGERLITERAL; }
YY_BREAK
case 59:
YY_RULE_SETUP
-#line 110 "cmDependsJavaLexer.in.l"
{ PRIMITIVE; return jp_NULLLITERAL; }
YY_BREAK
case 60:
YY_RULE_SETUP
-#line 112 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_AND; }
YY_BREAK
case 61:
YY_RULE_SETUP
-#line 113 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_ANDAND; }
YY_BREAK
case 62:
YY_RULE_SETUP
-#line 114 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_ANDEQUALS; }
YY_BREAK
case 63:
YY_RULE_SETUP
-#line 115 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_BRACKETEND; }
YY_BREAK
case 64:
YY_RULE_SETUP
-#line 116 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_BRACKETSTART; }
YY_BREAK
case 65:
YY_RULE_SETUP
-#line 117 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_CARROT; }
YY_BREAK
case 66:
YY_RULE_SETUP
-#line 118 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_CARROTEQUALS; }
YY_BREAK
case 67:
YY_RULE_SETUP
-#line 119 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_COLON; }
YY_BREAK
case 68:
YY_RULE_SETUP
-#line 120 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_COMMA; }
YY_BREAK
case 69:
YY_RULE_SETUP
-#line 121 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_CURLYEND; }
YY_BREAK
case 70:
YY_RULE_SETUP
-#line 122 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_CURLYSTART; }
YY_BREAK
case 71:
YY_RULE_SETUP
-#line 123 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_DIVIDE; }
YY_BREAK
case 72:
YY_RULE_SETUP
-#line 124 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_DIVIDEEQUALS; }
YY_BREAK
case 73:
YY_RULE_SETUP
-#line 125 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_DOLLAR; }
YY_BREAK
case 74:
YY_RULE_SETUP
-#line 126 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_DOT; }
YY_BREAK
case 75:
YY_RULE_SETUP
-#line 127 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_EQUALS; }
YY_BREAK
case 76:
YY_RULE_SETUP
-#line 128 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_EQUALSEQUALS; }
YY_BREAK
case 77:
YY_RULE_SETUP
-#line 129 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_EXCLAMATION; }
YY_BREAK
case 78:
YY_RULE_SETUP
-#line 130 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_EXCLAMATIONEQUALS; }
YY_BREAK
case 79:
YY_RULE_SETUP
-#line 131 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_GREATER; }
YY_BREAK
case 80:
YY_RULE_SETUP
-#line 132 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_GTEQUALS; }
YY_BREAK
case 81:
YY_RULE_SETUP
-#line 133 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_GTGT; }
YY_BREAK
case 82:
YY_RULE_SETUP
-#line 134 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_GTGTEQUALS; }
YY_BREAK
case 83:
YY_RULE_SETUP
-#line 135 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_GTGTGT; }
YY_BREAK
case 84:
YY_RULE_SETUP
-#line 136 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_GTGTGTEQUALS; }
YY_BREAK
case 85:
YY_RULE_SETUP
-#line 137 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_LESLESEQUALS; }
YY_BREAK
case 86:
YY_RULE_SETUP
-#line 138 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_LESSTHAN; }
YY_BREAK
case 87:
YY_RULE_SETUP
-#line 139 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_LTEQUALS; }
YY_BREAK
case 88:
YY_RULE_SETUP
-#line 140 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_LTLT; }
YY_BREAK
case 89:
YY_RULE_SETUP
-#line 141 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_MINUS; }
YY_BREAK
case 90:
YY_RULE_SETUP
-#line 142 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_MINUSEQUALS; }
YY_BREAK
case 91:
YY_RULE_SETUP
-#line 143 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_MINUSMINUS; }
YY_BREAK
case 92:
YY_RULE_SETUP
-#line 144 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PAREEND; }
YY_BREAK
case 93:
YY_RULE_SETUP
-#line 145 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PARESTART; }
YY_BREAK
case 94:
YY_RULE_SETUP
-#line 146 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PERCENT; }
YY_BREAK
case 95:
YY_RULE_SETUP
-#line 147 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PERCENTEQUALS; }
YY_BREAK
case 96:
YY_RULE_SETUP
-#line 148 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PIPE; }
YY_BREAK
case 97:
YY_RULE_SETUP
-#line 149 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PIPEEQUALS; }
YY_BREAK
case 98:
YY_RULE_SETUP
-#line 150 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PIPEPIPE; }
YY_BREAK
case 99:
YY_RULE_SETUP
-#line 151 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PLUS; }
YY_BREAK
case 100:
YY_RULE_SETUP
-#line 152 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PLUSEQUALS; }
YY_BREAK
case 101:
YY_RULE_SETUP
-#line 153 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_PLUSPLUS; }
YY_BREAK
case 102:
YY_RULE_SETUP
-#line 154 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_QUESTION; }
YY_BREAK
case 103:
YY_RULE_SETUP
-#line 155 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_SEMICOL; }
YY_BREAK
case 104:
YY_RULE_SETUP
-#line 156 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_TILDE; }
YY_BREAK
case 105:
YY_RULE_SETUP
-#line 157 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_TIMES; }
YY_BREAK
case 106:
YY_RULE_SETUP
-#line 158 "cmDependsJavaLexer.in.l"
{ SYMBOL; return jp_TIMESEQUALS; }
YY_BREAK
case 107:
YY_RULE_SETUP
-#line 160 "cmDependsJavaLexer.in.l"
{
yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
return jp_NAME;
@@ -1540,18 +1624,15 @@ YY_RULE_SETUP
case 108:
/* rule 108 can match eol */
YY_RULE_SETUP
-#line 165 "cmDependsJavaLexer.in.l"
{ }
YY_BREAK
case 109:
/* rule 109 can match eol */
YY_RULE_SETUP
-#line 166 "cmDependsJavaLexer.in.l"
{ }
YY_BREAK
case 110:
YY_RULE_SETUP
-#line 167 "cmDependsJavaLexer.in.l"
{
std::cerr << "Unknown character: " << yytext[0]
<< " (" << (int)yytext[0] << ")" << std::endl;
@@ -1561,10 +1642,8 @@ YY_RULE_SETUP
YY_BREAK
case 111:
YY_RULE_SETUP
-#line 174 "cmDependsJavaLexer.in.l"
ECHO;
YY_BREAK
-#line 1567 "cmDependsJavaLexer.cxx"
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(comment):
case YY_STATE_EOF(string):
@@ -1584,7 +1663,7 @@ case YY_STATE_EOF(string):
/* We're scanning a new file or input source. It's
* possible that this happened because the user
* just pointed yyin at a new source and called
- * cmDependsJava_yylex(). If so, then we have to assure
+ * yylex(). If so, then we have to assure
* consistency between YY_CURRENT_BUFFER and our
* globals. Here is the right place to do so, because
* this is the first action (other than possibly a
@@ -1644,7 +1723,7 @@ case YY_STATE_EOF(string):
{
yyg->yy_did_buffer_switch_on_eof = 0;
- if ( cmDependsJava_yywrap(yyscanner ) )
+ if ( yywrap( yyscanner ) )
{
/* Note: because we've taken care in
* yy_get_next_buffer() to have set up
@@ -1698,7 +1777,7 @@ case YY_STATE_EOF(string):
} /* end of action switch */
} /* end of scanning one token */
} /* end of user's declarations */
-} /* end of cmDependsJava_yylex */
+} /* end of yylex */
/* yy_get_next_buffer - try to read in a new buffer
*
@@ -1712,7 +1791,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
char *source = yyg->yytext_ptr;
- yy_size_t number_to_move, i;
+ int number_to_move, i;
int ret_val;
if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
@@ -1741,7 +1820,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
/* Try to read more data. */
/* First move last chars to start of buffer. */
- number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1);
for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++);
@@ -1777,7 +1856,8 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
b->yy_ch_buf = (char *)
/* Include room in for 2 EOB chars. */
- cmDependsJava_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+ yyrealloc( (void *) b->yy_ch_buf,
+ (yy_size_t) (b->yy_buf_size + 2) , yyscanner );
}
else
/* Can't grow it, we don't own it. */
@@ -1809,7 +1889,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ( number_to_move == YY_MORE_ADJ )
{
ret_val = EOB_ACT_END_OF_FILE;
- cmDependsJava_yyrestart(yyin ,yyscanner);
+ yyrestart( yyin , yyscanner);
}
else
@@ -1823,12 +1903,15 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
ret_val = EOB_ACT_CONTINUE_SCAN;
- if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
/* Extend the array by 50%, plus the number we really need. */
int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) cmDependsJava_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
+ (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner );
if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ /* "- 2" to take care of EOB's */
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
}
yyg->yy_n_chars += number_to_move;
@@ -1862,9 +1945,9 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 327 )
- yy_c = yy_meta[(unsigned int) yy_c];
+ yy_c = yy_meta[yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
}
return yy_current_state;
@@ -1891,9 +1974,9 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 327 )
- yy_c = yy_meta[(unsigned int) yy_c];
+ yy_c = yy_meta[yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
yy_is_jam = (yy_current_state == 326);
(void)yyg;
@@ -1967,7 +2050,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{ /* need more input */
- int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+ int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr);
++yyg->yy_c_buf_p;
switch ( yy_get_next_buffer( yyscanner ) )
@@ -1984,13 +2067,13 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
*/
/* Reset buffer status. */
- cmDependsJava_yyrestart(yyin ,yyscanner);
+ yyrestart( yyin , yyscanner);
/*FALLTHROUGH*/
case EOB_ACT_END_OF_FILE:
{
- if ( cmDependsJava_yywrap(yyscanner ) )
+ if ( yywrap( yyscanner ) )
return 0;
if ( ! yyg->yy_did_buffer_switch_on_eof )
@@ -2022,34 +2105,34 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @note This function does not reset the start condition to @c INITIAL .
*/
- void cmDependsJava_yyrestart (FILE * input_file , yyscan_t yyscanner)
+ void yyrestart (FILE * input_file , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if ( ! YY_CURRENT_BUFFER ){
- cmDependsJava_yyensure_buffer_stack (yyscanner);
+ yyensure_buffer_stack (yyscanner);
YY_CURRENT_BUFFER_LVALUE =
- cmDependsJava_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner);
}
- cmDependsJava_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
- cmDependsJava_yy_load_buffer_state(yyscanner );
+ yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner);
+ yy_load_buffer_state( yyscanner );
}
/** Switch to a different input buffer.
* @param new_buffer The new input buffer.
* @param yyscanner The scanner object.
*/
- void cmDependsJava_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* TODO. We should be able to replace this entire function body
* with
- * cmDependsJava_yypop_buffer_state();
- * cmDependsJava_yypush_buffer_state(new_buffer);
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
*/
- cmDependsJava_yyensure_buffer_stack (yyscanner);
+ yyensure_buffer_stack (yyscanner);
if ( YY_CURRENT_BUFFER == new_buffer )
return;
@@ -2062,17 +2145,17 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
}
YY_CURRENT_BUFFER_LVALUE = new_buffer;
- cmDependsJava_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
/* We don't actually know whether we did this switch during
- * EOF (cmDependsJava_yywrap()) processing, but the only time this flag
- * is looked at is after cmDependsJava_yywrap() is called, so it's safe
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
* to go ahead and always set it.
*/
yyg->yy_did_buffer_switch_on_eof = 1;
}
-static void cmDependsJava_yy_load_buffer_state (yyscan_t yyscanner)
+static void yy_load_buffer_state (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
@@ -2087,35 +2170,35 @@ static void cmDependsJava_yy_load_buffer_state (yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @return the allocated buffer state.
*/
- YY_BUFFER_STATE cmDependsJava_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
- b = (YY_BUFFER_STATE) cmDependsJava_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner );
if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmDependsJava_yy_create_buffer()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
- b->yy_buf_size = (yy_size_t)size;
+ b->yy_buf_size = size;
/* yy_ch_buf has to be 2 characters longer than the size given because
* we need to put in 2 end-of-buffer characters.
*/
- b->yy_ch_buf = (char *) cmDependsJava_yyalloc(b->yy_buf_size + 2 ,yyscanner );
+ b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner );
if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmDependsJava_yy_create_buffer()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
b->yy_is_our_buffer = 1;
- cmDependsJava_yy_init_buffer(b,file ,yyscanner);
+ yy_init_buffer( b, file , yyscanner);
return b;
}
/** Destroy the buffer.
- * @param b a buffer created with cmDependsJava_yy_create_buffer()
+ * @param b a buffer created with yy_create_buffer()
* @param yyscanner The scanner object.
*/
- void cmDependsJava_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+ void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -2126,28 +2209,28 @@ static void cmDependsJava_yy_load_buffer_state (yyscan_t yyscanner)
YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
if ( b->yy_is_our_buffer )
- cmDependsJava_yyfree((void *) b->yy_ch_buf ,yyscanner );
+ yyfree( (void *) b->yy_ch_buf , yyscanner );
- cmDependsJava_yyfree((void *) b ,yyscanner );
+ yyfree( (void *) b , yyscanner );
}
/* Initializes or reinitializes a buffer.
* This function is sometimes called more than once on the same buffer,
- * such as during a cmDependsJava_yyrestart() or at EOF.
+ * such as during a yyrestart() or at EOF.
*/
- static void cmDependsJava_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
{
int oerrno = errno;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- cmDependsJava_yy_flush_buffer(b ,yyscanner);
+ yy_flush_buffer( b , yyscanner);
b->yy_input_file = file;
b->yy_fill_buffer = 1;
- /* If b is the current buffer, then cmDependsJava_yy_init_buffer was _probably_
- * called from cmDependsJava_yyrestart() or through yy_get_next_buffer.
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
* In that case, we don't want to reset the lineno or column.
*/
if (b != YY_CURRENT_BUFFER){
@@ -2164,7 +2247,7 @@ static void cmDependsJava_yy_load_buffer_state (yyscan_t yyscanner)
* @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
* @param yyscanner The scanner object.
*/
- void cmDependsJava_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+ void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if ( ! b )
@@ -2185,7 +2268,7 @@ static void cmDependsJava_yy_load_buffer_state (yyscan_t yyscanner)
b->yy_buffer_status = YY_BUFFER_NEW;
if ( b == YY_CURRENT_BUFFER )
- cmDependsJava_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
}
/** Pushes the new state onto the stack. The new state becomes
@@ -2194,15 +2277,15 @@ static void cmDependsJava_yy_load_buffer_state (yyscan_t yyscanner)
* @param new_buffer The new state.
* @param yyscanner The scanner object.
*/
-void cmDependsJava_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (new_buffer == NULL)
return;
- cmDependsJava_yyensure_buffer_stack(yyscanner);
+ yyensure_buffer_stack(yyscanner);
- /* This block is copied from cmDependsJava_yy_switch_to_buffer. */
+ /* This block is copied from yy_switch_to_buffer. */
if ( YY_CURRENT_BUFFER )
{
/* Flush out information for old buffer. */
@@ -2216,8 +2299,8 @@ void cmDependsJava_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yy
yyg->yy_buffer_stack_top++;
YY_CURRENT_BUFFER_LVALUE = new_buffer;
- /* copied from cmDependsJava_yy_switch_to_buffer. */
- cmDependsJava_yy_load_buffer_state(yyscanner );
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state( yyscanner );
yyg->yy_did_buffer_switch_on_eof = 1;
}
@@ -2225,19 +2308,19 @@ void cmDependsJava_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yy
* The next element becomes the new top.
* @param yyscanner The scanner object.
*/
-void cmDependsJava_yypop_buffer_state (yyscan_t yyscanner)
+void yypop_buffer_state (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (!YY_CURRENT_BUFFER)
return;
- cmDependsJava_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+ yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner);
YY_CURRENT_BUFFER_LVALUE = NULL;
if (yyg->yy_buffer_stack_top > 0)
--yyg->yy_buffer_stack_top;
if (YY_CURRENT_BUFFER) {
- cmDependsJava_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
yyg->yy_did_buffer_switch_on_eof = 1;
}
}
@@ -2245,9 +2328,9 @@ void cmDependsJava_yypop_buffer_state (yyscan_t yyscanner)
/* Allocates the stack if it does not exist.
* Guarantees space for at least one push.
*/
-static void cmDependsJava_yyensure_buffer_stack (yyscan_t yyscanner)
+static void yyensure_buffer_stack (yyscan_t yyscanner)
{
- int num_to_alloc;
+ yy_size_t num_to_alloc;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (!yyg->yy_buffer_stack) {
@@ -2257,11 +2340,11 @@ static void cmDependsJava_yyensure_buffer_stack (yyscan_t yyscanner)
* immediate realloc on the next call.
*/
num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmDependsJava_yyalloc
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
(num_to_alloc * sizeof(struct yy_buffer_state*)
, yyscanner);
if ( ! yyg->yy_buffer_stack )
- YY_FATAL_ERROR( "out of dynamic memory in cmDependsJava_yyensure_buffer_stack()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
@@ -2276,12 +2359,12 @@ static void cmDependsJava_yyensure_buffer_stack (yyscan_t yyscanner)
yy_size_t grow_size = 8 /* arbitrary grow size */;
num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmDependsJava_yyrealloc
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
(yyg->yy_buffer_stack,
num_to_alloc * sizeof(struct yy_buffer_state*)
, yyscanner);
if ( ! yyg->yy_buffer_stack )
- YY_FATAL_ERROR( "out of dynamic memory in cmDependsJava_yyensure_buffer_stack()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
/* zero only the new slots.*/
memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
@@ -2295,7 +2378,7 @@ static void cmDependsJava_yyensure_buffer_stack (yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
-YY_BUFFER_STATE cmDependsJava_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
@@ -2305,11 +2388,11 @@ YY_BUFFER_STATE cmDependsJava_yy_scan_buffer (char * base, yy_size_t size , yy
/* They forgot to leave room for the EOB's. */
return NULL;
- b = (YY_BUFFER_STATE) cmDependsJava_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner );
if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmDependsJava_yy_scan_buffer()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
- b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */
b->yy_buf_pos = b->yy_ch_buf = base;
b->yy_is_our_buffer = 0;
b->yy_input_file = NULL;
@@ -2319,53 +2402,53 @@ YY_BUFFER_STATE cmDependsJava_yy_scan_buffer (char * base, yy_size_t size , yy
b->yy_fill_buffer = 0;
b->yy_buffer_status = YY_BUFFER_NEW;
- cmDependsJava_yy_switch_to_buffer(b ,yyscanner );
+ yy_switch_to_buffer( b , yyscanner );
return b;
}
-/** Setup the input buffer state to scan a string. The next call to cmDependsJava_yylex() will
+/** Setup the input buffer state to scan a string. The next call to yylex() will
* scan from a @e copy of @a str.
* @param yystr a NUL-terminated string to scan
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
* @note If you want to scan bytes that may contain NUL values, then use
- * cmDependsJava_yy_scan_bytes() instead.
+ * yy_scan_bytes() instead.
*/
-YY_BUFFER_STATE cmDependsJava_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner)
{
- return cmDependsJava_yy_scan_bytes(yystr,(int) strlen(yystr) ,yyscanner);
+ return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner);
}
-/** Setup the input buffer state to scan the given bytes. The next call to cmDependsJava_yylex() will
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
* scan from a @e copy of @a bytes.
* @param yybytes the byte buffer to scan
* @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
-YY_BUFFER_STATE cmDependsJava_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
char *buf;
yy_size_t n;
- yy_size_t i;
+ int i;
/* Get memory for full buffer, including space for trailing EOB's. */
- n = (yy_size_t) _yybytes_len + 2;
- buf = (char *) cmDependsJava_yyalloc(n ,yyscanner );
+ n = (yy_size_t) (_yybytes_len + 2);
+ buf = (char *) yyalloc( n , yyscanner );
if ( ! buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmDependsJava_yy_scan_bytes()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
- for ( i = 0; i < (size_t)_yybytes_len; ++i )
+ for ( i = 0; i < _yybytes_len; ++i )
buf[i] = yybytes[i];
buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
- b = cmDependsJava_yy_scan_buffer(buf,n ,yyscanner);
+ b = yy_scan_buffer( buf, n , yyscanner);
if ( ! b )
- YY_FATAL_ERROR( "bad buffer in cmDependsJava_yy_scan_bytes()" );
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
/* It's okay to grow etc. this buffer, and we should throw it
* away when we're done.
@@ -2379,11 +2462,11 @@ YY_BUFFER_STATE cmDependsJava_yy_scan_bytes (yyconst char * yybytes, int _yyby
#define YY_EXIT_FAILURE 2
#endif
-static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
- (void) fprintf( stderr, "%s\n", msg );
+ fprintf( stderr, "%s\n", msg );
exit( YY_EXIT_FAILURE );
}
@@ -2409,7 +2492,7 @@ static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
/** Get the user-defined data for this scanner.
* @param yyscanner The scanner object.
*/
-YY_EXTRA_TYPE cmDependsJava_yyget_extra (yyscan_t yyscanner)
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyextra;
@@ -2418,7 +2501,7 @@ YY_EXTRA_TYPE cmDependsJava_yyget_extra (yyscan_t yyscanner)
/** Get the current line number.
* @param yyscanner The scanner object.
*/
-int cmDependsJava_yyget_lineno (yyscan_t yyscanner)
+int yyget_lineno (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -2431,7 +2514,7 @@ int cmDependsJava_yyget_lineno (yyscan_t yyscanner)
/** Get the current column number.
* @param yyscanner The scanner object.
*/
-int cmDependsJava_yyget_column (yyscan_t yyscanner)
+int yyget_column (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -2444,7 +2527,7 @@ int cmDependsJava_yyget_column (yyscan_t yyscanner)
/** Get the input stream.
* @param yyscanner The scanner object.
*/
-FILE *cmDependsJava_yyget_in (yyscan_t yyscanner)
+FILE *yyget_in (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyin;
@@ -2453,7 +2536,7 @@ FILE *cmDependsJava_yyget_in (yyscan_t yyscanner)
/** Get the output stream.
* @param yyscanner The scanner object.
*/
-FILE *cmDependsJava_yyget_out (yyscan_t yyscanner)
+FILE *yyget_out (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyout;
@@ -2462,7 +2545,7 @@ FILE *cmDependsJava_yyget_out (yyscan_t yyscanner)
/** Get the length of the current token.
* @param yyscanner The scanner object.
*/
-int cmDependsJava_yyget_leng (yyscan_t yyscanner)
+int yyget_leng (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyleng;
@@ -2472,7 +2555,7 @@ int cmDependsJava_yyget_leng (yyscan_t yyscanner)
* @param yyscanner The scanner object.
*/
-char *cmDependsJava_yyget_text (yyscan_t yyscanner)
+char *yyget_text (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yytext;
@@ -2482,7 +2565,7 @@ char *cmDependsJava_yyget_text (yyscan_t yyscanner)
* @param user_defined The data to be associated with this scanner.
* @param yyscanner The scanner object.
*/
-void cmDependsJava_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
+void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyextra = user_defined ;
@@ -2492,13 +2575,13 @@ void cmDependsJava_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner
* @param _line_number line number
* @param yyscanner The scanner object.
*/
-void cmDependsJava_yyset_lineno (int _line_number , yyscan_t yyscanner)
+void yyset_lineno (int _line_number , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* lineno is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
- YY_FATAL_ERROR( "cmDependsJava_yyset_lineno called with no buffer" );
+ YY_FATAL_ERROR( "yyset_lineno called with no buffer" );
yylineno = _line_number;
}
@@ -2507,13 +2590,13 @@ void cmDependsJava_yyset_lineno (int _line_number , yyscan_t yyscanner)
* @param _column_no column number
* @param yyscanner The scanner object.
*/
-void cmDependsJava_yyset_column (int _column_no , yyscan_t yyscanner)
+void yyset_column (int _column_no , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* column is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
- YY_FATAL_ERROR( "cmDependsJava_yyset_column called with no buffer" );
+ YY_FATAL_ERROR( "yyset_column called with no buffer" );
yycolumn = _column_no;
}
@@ -2522,27 +2605,27 @@ void cmDependsJava_yyset_column (int _column_no , yyscan_t yyscanner)
* input buffer.
* @param _in_str A readable stream.
* @param yyscanner The scanner object.
- * @see cmDependsJava_yy_switch_to_buffer
+ * @see yy_switch_to_buffer
*/
-void cmDependsJava_yyset_in (FILE * _in_str , yyscan_t yyscanner)
+void yyset_in (FILE * _in_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyin = _in_str ;
}
-void cmDependsJava_yyset_out (FILE * _out_str , yyscan_t yyscanner)
+void yyset_out (FILE * _out_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyout = _out_str ;
}
-int cmDependsJava_yyget_debug (yyscan_t yyscanner)
+int yyget_debug (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yy_flex_debug;
}
-void cmDependsJava_yyset_debug (int _bdebug , yyscan_t yyscanner)
+void yyset_debug (int _bdebug , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yy_flex_debug = _bdebug ;
@@ -2552,20 +2635,18 @@ void cmDependsJava_yyset_debug (int _bdebug , yyscan_t yyscanner)
/* User-visible API */
-/* cmDependsJava_yylex_init is special because it creates the scanner itself, so it is
+/* yylex_init is special because it creates the scanner itself, so it is
* the ONLY reentrant function that doesn't take the scanner as the last argument.
* That's why we explicitly handle the declaration, instead of using our macros.
*/
-
-int cmDependsJava_yylex_init(yyscan_t* ptr_yy_globals)
-
+int yylex_init(yyscan_t* ptr_yy_globals)
{
if (ptr_yy_globals == NULL){
errno = EINVAL;
return 1;
}
- *ptr_yy_globals = (yyscan_t) cmDependsJava_yyalloc ( sizeof( struct yyguts_t ), NULL );
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
if (*ptr_yy_globals == NULL){
errno = ENOMEM;
@@ -2578,27 +2659,25 @@ int cmDependsJava_yylex_init(yyscan_t* ptr_yy_globals)
return yy_init_globals ( *ptr_yy_globals );
}
-/* cmDependsJava_yylex_init_extra has the same functionality as cmDependsJava_yylex_init, but follows the
+/* yylex_init_extra has the same functionality as yylex_init, but follows the
* convention of taking the scanner as the last argument. Note however, that
* this is a *pointer* to a scanner, as it will be allocated by this call (and
* is the reason, too, why this function also must handle its own declaration).
- * The user defined value in the first argument will be available to cmDependsJava_yyalloc in
+ * The user defined value in the first argument will be available to yyalloc in
* the yyextra field.
*/
-
-int cmDependsJava_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
-
+int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals )
{
struct yyguts_t dummy_yyguts;
- cmDependsJava_yyset_extra (yy_user_defined, &dummy_yyguts);
+ yyset_extra (yy_user_defined, &dummy_yyguts);
if (ptr_yy_globals == NULL){
errno = EINVAL;
return 1;
}
- *ptr_yy_globals = (yyscan_t) cmDependsJava_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
if (*ptr_yy_globals == NULL){
errno = ENOMEM;
@@ -2609,7 +2688,7 @@ int cmDependsJava_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_y
yy_init_globals. Leave at 0x00 for releases. */
memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
- cmDependsJava_yyset_extra (yy_user_defined, *ptr_yy_globals);
+ yyset_extra (yy_user_defined, *ptr_yy_globals);
return yy_init_globals ( *ptr_yy_globals );
}
@@ -2618,7 +2697,7 @@ static int yy_init_globals (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* Initialization is the same as for the non-reentrant scanner.
- * This function is called from cmDependsJava_yylex_destroy(), so don't allocate here.
+ * This function is called from yylex_destroy(), so don't allocate here.
*/
yyg->yy_buffer_stack = NULL;
@@ -2642,37 +2721,37 @@ static int yy_init_globals (yyscan_t yyscanner)
#endif
/* For future reference: Set errno on error, since we are called by
- * cmDependsJava_yylex_init()
+ * yylex_init()
*/
return 0;
}
-/* cmDependsJava_yylex_destroy is for both reentrant and non-reentrant scanners. */
-int cmDependsJava_yylex_destroy (yyscan_t yyscanner)
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* Pop the buffer stack, destroying each element. */
while(YY_CURRENT_BUFFER){
- cmDependsJava_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+ yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner );
YY_CURRENT_BUFFER_LVALUE = NULL;
- cmDependsJava_yypop_buffer_state(yyscanner);
+ yypop_buffer_state(yyscanner);
}
/* Destroy the stack itself. */
- cmDependsJava_yyfree(yyg->yy_buffer_stack ,yyscanner);
+ yyfree(yyg->yy_buffer_stack , yyscanner);
yyg->yy_buffer_stack = NULL;
/* Destroy the start condition stack. */
- cmDependsJava_yyfree(yyg->yy_start_stack ,yyscanner );
+ yyfree( yyg->yy_start_stack , yyscanner );
yyg->yy_start_stack = NULL;
/* Reset the globals. This is important in a non-reentrant scanner so the next time
- * cmDependsJava_yylex() is called, initialization will occur. */
+ * yylex() is called, initialization will occur. */
yy_init_globals( yyscanner);
/* Destroy the main struct (reentrant only). */
- cmDependsJava_yyfree ( yyscanner , yyscanner );
+ yyfree ( yyscanner , yyscanner );
yyscanner = NULL;
return 0;
}
@@ -2682,7 +2761,7 @@ int cmDependsJava_yylex_destroy (yyscan_t yyscanner)
*/
#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
@@ -2694,7 +2773,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca
#endif
#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+static int yy_flex_strlen (const char * s , yyscan_t yyscanner)
{
int n;
for ( n = 0; s[n]; ++n )
@@ -2704,14 +2783,14 @@ static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
}
#endif
-void *cmDependsJava_yyalloc (yy_size_t size , yyscan_t yyscanner)
+void *yyalloc (yy_size_t size , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
return malloc(size);
}
-void *cmDependsJava_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
+void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
@@ -2726,13 +2805,15 @@ void *cmDependsJava_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner
return realloc(ptr, size);
}
-void cmDependsJava_yyfree (void * ptr , yyscan_t yyscanner)
+void yyfree (void * ptr , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
- free( (char *) ptr ); /* see cmDependsJava_yyrealloc() for (char *) cast */
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
}
#define YYTABLES_NAME "yytables"
-#line 174 "cmDependsJavaLexer.in.l"
+/*--------------------------------------------------------------------------*/
+
+#endif /* __clang_analyzer__ */
diff --git a/Source/LexerParser/cmDependsJavaLexer.h b/Source/LexerParser/cmDependsJavaLexer.h
index ccadd70b9..f1e87d246 100644
--- a/Source/LexerParser/cmDependsJavaLexer.h
+++ b/Source/LexerParser/cmDependsJavaLexer.h
@@ -2,10 +2,6 @@
#define cmDependsJava_yyHEADER_H 1
#define cmDependsJava_yyIN_HEADER 1
-#line 6 "cmDependsJavaLexer.h"
-
-#line 8 "cmDependsJavaLexer.h"
-
#define FLEXINT_H 1
#define YY_INT_ALIGNED short int
@@ -14,11 +10,221 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6
-#define YY_FLEX_SUBMINOR_VERSION 1
+#define YY_FLEX_SUBMINOR_VERSION 4
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
+#ifdef yy_create_buffer
+#define cmDependsJava_yy_create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer cmDependsJava_yy_create_buffer
+#endif
+
+#ifdef yy_delete_buffer
+#define cmDependsJava_yy_delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer cmDependsJava_yy_delete_buffer
+#endif
+
+#ifdef yy_scan_buffer
+#define cmDependsJava_yy_scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer cmDependsJava_yy_scan_buffer
+#endif
+
+#ifdef yy_scan_string
+#define cmDependsJava_yy_scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string cmDependsJava_yy_scan_string
+#endif
+
+#ifdef yy_scan_bytes
+#define cmDependsJava_yy_scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes cmDependsJava_yy_scan_bytes
+#endif
+
+#ifdef yy_init_buffer
+#define cmDependsJava_yy_init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer cmDependsJava_yy_init_buffer
+#endif
+
+#ifdef yy_flush_buffer
+#define cmDependsJava_yy_flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer cmDependsJava_yy_flush_buffer
+#endif
+
+#ifdef yy_load_buffer_state
+#define cmDependsJava_yy_load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state cmDependsJava_yy_load_buffer_state
+#endif
+
+#ifdef yy_switch_to_buffer
+#define cmDependsJava_yy_switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer cmDependsJava_yy_switch_to_buffer
+#endif
+
+#ifdef yypush_buffer_state
+#define cmDependsJava_yypush_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state cmDependsJava_yypush_buffer_state
+#endif
+
+#ifdef yypop_buffer_state
+#define cmDependsJava_yypop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state cmDependsJava_yypop_buffer_state
+#endif
+
+#ifdef yyensure_buffer_stack
+#define cmDependsJava_yyensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack cmDependsJava_yyensure_buffer_stack
+#endif
+
+#ifdef yylex
+#define cmDependsJava_yylex_ALREADY_DEFINED
+#else
+#define yylex cmDependsJava_yylex
+#endif
+
+#ifdef yyrestart
+#define cmDependsJava_yyrestart_ALREADY_DEFINED
+#else
+#define yyrestart cmDependsJava_yyrestart
+#endif
+
+#ifdef yylex_init
+#define cmDependsJava_yylex_init_ALREADY_DEFINED
+#else
+#define yylex_init cmDependsJava_yylex_init
+#endif
+
+#ifdef yylex_init_extra
+#define cmDependsJava_yylex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra cmDependsJava_yylex_init_extra
+#endif
+
+#ifdef yylex_destroy
+#define cmDependsJava_yylex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy cmDependsJava_yylex_destroy
+#endif
+
+#ifdef yyget_debug
+#define cmDependsJava_yyget_debug_ALREADY_DEFINED
+#else
+#define yyget_debug cmDependsJava_yyget_debug
+#endif
+
+#ifdef yyset_debug
+#define cmDependsJava_yyset_debug_ALREADY_DEFINED
+#else
+#define yyset_debug cmDependsJava_yyset_debug
+#endif
+
+#ifdef yyget_extra
+#define cmDependsJava_yyget_extra_ALREADY_DEFINED
+#else
+#define yyget_extra cmDependsJava_yyget_extra
+#endif
+
+#ifdef yyset_extra
+#define cmDependsJava_yyset_extra_ALREADY_DEFINED
+#else
+#define yyset_extra cmDependsJava_yyset_extra
+#endif
+
+#ifdef yyget_in
+#define cmDependsJava_yyget_in_ALREADY_DEFINED
+#else
+#define yyget_in cmDependsJava_yyget_in
+#endif
+
+#ifdef yyset_in
+#define cmDependsJava_yyset_in_ALREADY_DEFINED
+#else
+#define yyset_in cmDependsJava_yyset_in
+#endif
+
+#ifdef yyget_out
+#define cmDependsJava_yyget_out_ALREADY_DEFINED
+#else
+#define yyget_out cmDependsJava_yyget_out
+#endif
+
+#ifdef yyset_out
+#define cmDependsJava_yyset_out_ALREADY_DEFINED
+#else
+#define yyset_out cmDependsJava_yyset_out
+#endif
+
+#ifdef yyget_leng
+#define cmDependsJava_yyget_leng_ALREADY_DEFINED
+#else
+#define yyget_leng cmDependsJava_yyget_leng
+#endif
+
+#ifdef yyget_text
+#define cmDependsJava_yyget_text_ALREADY_DEFINED
+#else
+#define yyget_text cmDependsJava_yyget_text
+#endif
+
+#ifdef yyget_lineno
+#define cmDependsJava_yyget_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno cmDependsJava_yyget_lineno
+#endif
+
+#ifdef yyset_lineno
+#define cmDependsJava_yyset_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno cmDependsJava_yyset_lineno
+#endif
+
+#ifdef yyget_column
+#define cmDependsJava_yyget_column_ALREADY_DEFINED
+#else
+#define yyget_column cmDependsJava_yyget_column
+#endif
+
+#ifdef yyset_column
+#define cmDependsJava_yyset_column_ALREADY_DEFINED
+#else
+#define yyset_column cmDependsJava_yyset_column
+#endif
+
+#ifdef yywrap
+#define cmDependsJava_yywrap_ALREADY_DEFINED
+#else
+#define yywrap cmDependsJava_yywrap
+#endif
+
+#ifdef yyalloc
+#define cmDependsJava_yyalloc_ALREADY_DEFINED
+#else
+#define yyalloc cmDependsJava_yyalloc
+#endif
+
+#ifdef yyrealloc
+#define cmDependsJava_yyrealloc_ALREADY_DEFINED
+#else
+#define yyrealloc cmDependsJava_yyrealloc
+#endif
+
+#ifdef yyfree
+#define cmDependsJava_yyfree_ALREADY_DEFINED
+#else
+#define yyfree cmDependsJava_yyfree
+#endif
+
/* First, we deal with platform-specific or compiler-specific issues. */
/* begin standard C headers. */
@@ -89,10 +295,16 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
+#ifndef SIZE_MAX
+#define SIZE_MAX (~(size_t)0)
+#endif
+
#endif /* ! C99 */
#endif /* ! FLEXINT_H */
+/* begin standard C++ headers. */
+
/* TODO: this is always defined, so inline it */
#define yyconst const
@@ -193,21 +405,21 @@ struct yy_buffer_state
};
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-void cmDependsJava_yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void cmDependsJava_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmDependsJava_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void cmDependsJava_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmDependsJava_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmDependsJava_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void cmDependsJava_yypop_buffer_state (yyscan_t yyscanner );
+void yyrestart ( FILE *input_file , yyscan_t yyscanner );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
+void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+void yypop_buffer_state ( yyscan_t yyscanner );
-YY_BUFFER_STATE cmDependsJava_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmDependsJava_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmDependsJava_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
-void *cmDependsJava_yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *cmDependsJava_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void cmDependsJava_yyfree (void * ,yyscan_t yyscanner );
+void *yyalloc ( yy_size_t , yyscan_t yyscanner );
+void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
+void yyfree ( void * , yyscan_t yyscanner );
/* Begin user sect3 */
@@ -227,42 +439,42 @@ void cmDependsJava_yyfree (void * ,yyscan_t yyscanner );
#define YY_EXTRA_TYPE void *
#endif
-int cmDependsJava_yylex_init (yyscan_t* scanner);
+int yylex_init (yyscan_t* scanner);
-int cmDependsJava_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
-int cmDependsJava_yylex_destroy (yyscan_t yyscanner );
+int yylex_destroy ( yyscan_t yyscanner );
-int cmDependsJava_yyget_debug (yyscan_t yyscanner );
+int yyget_debug ( yyscan_t yyscanner );
-void cmDependsJava_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+void yyset_debug ( int debug_flag , yyscan_t yyscanner );
-YY_EXTRA_TYPE cmDependsJava_yyget_extra (yyscan_t yyscanner );
+YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
-void cmDependsJava_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
-FILE *cmDependsJava_yyget_in (yyscan_t yyscanner );
+FILE *yyget_in ( yyscan_t yyscanner );
-void cmDependsJava_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
+void yyset_in ( FILE * _in_str , yyscan_t yyscanner );
-FILE *cmDependsJava_yyget_out (yyscan_t yyscanner );
+FILE *yyget_out ( yyscan_t yyscanner );
-void cmDependsJava_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
+void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
- int cmDependsJava_yyget_leng (yyscan_t yyscanner );
+ int yyget_leng ( yyscan_t yyscanner );
-char *cmDependsJava_yyget_text (yyscan_t yyscanner );
+char *yyget_text ( yyscan_t yyscanner );
-int cmDependsJava_yyget_lineno (yyscan_t yyscanner );
+int yyget_lineno ( yyscan_t yyscanner );
-void cmDependsJava_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+void yyset_lineno ( int _line_number , yyscan_t yyscanner );
-int cmDependsJava_yyget_column (yyscan_t yyscanner );
+int yyget_column ( yyscan_t yyscanner );
-void cmDependsJava_yyset_column (int _column_no ,yyscan_t yyscanner );
+void yyset_column ( int _column_no , yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -270,18 +482,18 @@ void cmDependsJava_yyset_column (int _column_no ,yyscan_t yyscanner );
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
-extern "C" int cmDependsJava_yywrap (yyscan_t yyscanner );
+extern "C" int yywrap ( yyscan_t yyscanner );
#else
-extern int cmDependsJava_yywrap (yyscan_t yyscanner );
+extern int yywrap ( yyscan_t yyscanner );
#endif
#endif
#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
#endif
#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
#endif
#ifndef YY_NO_INPUT
@@ -309,9 +521,9 @@ static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
-extern int cmDependsJava_yylex (yyscan_t yyscanner);
+extern int yylex (yyscan_t yyscanner);
-#define YY_DECL int cmDependsJava_yylex (yyscan_t yyscanner)
+#define YY_DECL int yylex (yyscan_t yyscanner)
#endif /* !YY_DECL */
/* yy_get_previous_state - get the state just before the EOB char was reached */
@@ -328,9 +540,150 @@ extern int cmDependsJava_yylex (yyscan_t yyscanner);
#undef YY_DECL
#endif
-#line 174 "cmDependsJavaLexer.in.l"
-
+#ifndef cmDependsJava_yy_create_buffer_ALREADY_DEFINED
+#undef yy_create_buffer
+#endif
+#ifndef cmDependsJava_yy_delete_buffer_ALREADY_DEFINED
+#undef yy_delete_buffer
+#endif
+#ifndef cmDependsJava_yy_scan_buffer_ALREADY_DEFINED
+#undef yy_scan_buffer
+#endif
+#ifndef cmDependsJava_yy_scan_string_ALREADY_DEFINED
+#undef yy_scan_string
+#endif
+#ifndef cmDependsJava_yy_scan_bytes_ALREADY_DEFINED
+#undef yy_scan_bytes
+#endif
+#ifndef cmDependsJava_yy_init_buffer_ALREADY_DEFINED
+#undef yy_init_buffer
+#endif
+#ifndef cmDependsJava_yy_flush_buffer_ALREADY_DEFINED
+#undef yy_flush_buffer
+#endif
+#ifndef cmDependsJava_yy_load_buffer_state_ALREADY_DEFINED
+#undef yy_load_buffer_state
+#endif
+#ifndef cmDependsJava_yy_switch_to_buffer_ALREADY_DEFINED
+#undef yy_switch_to_buffer
+#endif
+#ifndef cmDependsJava_yypush_buffer_state_ALREADY_DEFINED
+#undef yypush_buffer_state
+#endif
+#ifndef cmDependsJava_yypop_buffer_state_ALREADY_DEFINED
+#undef yypop_buffer_state
+#endif
+#ifndef cmDependsJava_yyensure_buffer_stack_ALREADY_DEFINED
+#undef yyensure_buffer_stack
+#endif
+#ifndef cmDependsJava_yylex_ALREADY_DEFINED
+#undef yylex
+#endif
+#ifndef cmDependsJava_yyrestart_ALREADY_DEFINED
+#undef yyrestart
+#endif
+#ifndef cmDependsJava_yylex_init_ALREADY_DEFINED
+#undef yylex_init
+#endif
+#ifndef cmDependsJava_yylex_init_extra_ALREADY_DEFINED
+#undef yylex_init_extra
+#endif
+#ifndef cmDependsJava_yylex_destroy_ALREADY_DEFINED
+#undef yylex_destroy
+#endif
+#ifndef cmDependsJava_yyget_debug_ALREADY_DEFINED
+#undef yyget_debug
+#endif
+#ifndef cmDependsJava_yyset_debug_ALREADY_DEFINED
+#undef yyset_debug
+#endif
+#ifndef cmDependsJava_yyget_extra_ALREADY_DEFINED
+#undef yyget_extra
+#endif
+#ifndef cmDependsJava_yyset_extra_ALREADY_DEFINED
+#undef yyset_extra
+#endif
+#ifndef cmDependsJava_yyget_in_ALREADY_DEFINED
+#undef yyget_in
+#endif
+#ifndef cmDependsJava_yyset_in_ALREADY_DEFINED
+#undef yyset_in
+#endif
+#ifndef cmDependsJava_yyget_out_ALREADY_DEFINED
+#undef yyget_out
+#endif
+#ifndef cmDependsJava_yyset_out_ALREADY_DEFINED
+#undef yyset_out
+#endif
+#ifndef cmDependsJava_yyget_leng_ALREADY_DEFINED
+#undef yyget_leng
+#endif
+#ifndef cmDependsJava_yyget_text_ALREADY_DEFINED
+#undef yyget_text
+#endif
+#ifndef cmDependsJava_yyget_lineno_ALREADY_DEFINED
+#undef yyget_lineno
+#endif
+#ifndef cmDependsJava_yyset_lineno_ALREADY_DEFINED
+#undef yyset_lineno
+#endif
+#ifndef cmDependsJava_yyget_column_ALREADY_DEFINED
+#undef yyget_column
+#endif
+#ifndef cmDependsJava_yyset_column_ALREADY_DEFINED
+#undef yyset_column
+#endif
+#ifndef cmDependsJava_yywrap_ALREADY_DEFINED
+#undef yywrap
+#endif
+#ifndef cmDependsJava_yyget_lval_ALREADY_DEFINED
+#undef yyget_lval
+#endif
+#ifndef cmDependsJava_yyset_lval_ALREADY_DEFINED
+#undef yyset_lval
+#endif
+#ifndef cmDependsJava_yyget_lloc_ALREADY_DEFINED
+#undef yyget_lloc
+#endif
+#ifndef cmDependsJava_yyset_lloc_ALREADY_DEFINED
+#undef yyset_lloc
+#endif
+#ifndef cmDependsJava_yyalloc_ALREADY_DEFINED
+#undef yyalloc
+#endif
+#ifndef cmDependsJava_yyrealloc_ALREADY_DEFINED
+#undef yyrealloc
+#endif
+#ifndef cmDependsJava_yyfree_ALREADY_DEFINED
+#undef yyfree
+#endif
+#ifndef cmDependsJava_yytext_ALREADY_DEFINED
+#undef yytext
+#endif
+#ifndef cmDependsJava_yyleng_ALREADY_DEFINED
+#undef yyleng
+#endif
+#ifndef cmDependsJava_yyin_ALREADY_DEFINED
+#undef yyin
+#endif
+#ifndef cmDependsJava_yyout_ALREADY_DEFINED
+#undef yyout
+#endif
+#ifndef cmDependsJava_yy_flex_debug_ALREADY_DEFINED
+#undef yy_flex_debug
+#endif
+#ifndef cmDependsJava_yylineno_ALREADY_DEFINED
+#undef yylineno
+#endif
+#ifndef cmDependsJava_yytables_fload_ALREADY_DEFINED
+#undef yytables_fload
+#endif
+#ifndef cmDependsJava_yytables_destroy_ALREADY_DEFINED
+#undef yytables_destroy
+#endif
+#ifndef cmDependsJava_yyTABLES_NAME_ALREADY_DEFINED
+#undef yyTABLES_NAME
+#endif
-#line 335 "cmDependsJavaLexer.h"
#undef cmDependsJava_yyIN_HEADER
#endif /* cmDependsJava_yyHEADER_H */
diff --git a/Source/LexerParser/cmDependsJavaLexer.in.l b/Source/LexerParser/cmDependsJavaLexer.in.l
index 8cb42b17a..3dd3c224a 100644
--- a/Source/LexerParser/cmDependsJavaLexer.in.l
+++ b/Source/LexerParser/cmDependsJavaLexer.in.l
@@ -7,18 +7,19 @@ This file must be translated to C++ and modified to build everywhere.
Run flex >= 2.6 like this:
- flex --nounistd -DFLEXINT_H --prefix=cmDependsJava_yy --header-file=cmDependsJavaLexer.h -ocmDependsJavaLexer.cxx cmDependsJavaLexer.in.l
+ flex --nounistd -DFLEXINT_H --noline --header-file=cmDependsJavaLexer.h -ocmDependsJavaLexer.cxx cmDependsJavaLexer.in.l
Modify cmDependsJavaLexer.cxx:
- - remove trailing whitespace: sed -i 's/\s*$//' cmDependsJavaLexer.h cmDependsJavaLexer.cxx
- - remove blank lines at end of file
- - #include "cmStandardLexer.h" at the top
- - add cast in yy_scan_bytes for loop condition of _yybytes_len to size_t
+ - remove trailing whitespace: sed -i 's/\s*$//' cmDependsJavaLexer.h cmDependsJavaLexer.cxx
+ - remove blank lines at end of file: sed -i '${/^$/d;}' cmDependsJavaLexer.h cmDependsJavaLexer.cxx
+ - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmDependsJavaLexer.cxx
*/
/* IWYU pragma: no_forward_declare yyguts_t */
+#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+
#include <iostream>
#include "cmDependsJavaParserHelper.h"
@@ -26,7 +27,7 @@ Modify cmDependsJavaLexer.cxx:
/* Replace the lexer input function. */
#undef YY_INPUT
#define YY_INPUT(buf, result, max_size) \
- { result = yyextra->LexInput(buf, max_size); }
+ do { result = yyextra->LexInput(buf, max_size); } while (0)
/* Include the set of tokens from the parser. */
#include "cmDependsJavaParserTokens.h"
@@ -38,6 +39,8 @@ Modify cmDependsJavaLexer.cxx:
/*--------------------------------------------------------------------------*/
%}
+%option prefix="cmDependsJava_yy"
+
%option reentrant
%option noyywrap
%pointer
@@ -172,3 +175,7 @@ null { PRIMITIVE; return jp_NULLLITERAL; }
}
%%
+
+/*--------------------------------------------------------------------------*/
+
+#endif /* __clang_analyzer__ */
diff --git a/Source/LexerParser/cmDependsJavaParser.cxx b/Source/LexerParser/cmDependsJavaParser.cxx
index bc45d45e1..6c1fb2cb3 100644
--- a/Source/LexerParser/cmDependsJavaParser.cxx
+++ b/Source/LexerParser/cmDependsJavaParser.cxx
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4. */
+/* A Bison parser, made by GNU Bison 3.3.2. */
/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+ Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -40,11 +41,14 @@
define necessary library symbols; they are noted "INFRINGES ON
USER NAME SPACE" below. */
+/* Undocumented macros, especially those whose name start with YY_,
+ are private implementation details. Do not rely on them. */
+
/* Identify Bison output. */
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "3.0.4"
+#define YYBISON_VERSION "3.3.2"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -67,8 +71,8 @@
#define yynerrs cmDependsJava_yynerrs
-/* Copy the first part of user declarations. */
-#line 1 "cmDependsJavaParser.y" /* yacc.c:339 */
+/* First part of user prologue. */
+#line 1 "cmDependsJavaParser.y" /* yacc.c:337 */
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
@@ -107,7 +111,7 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message);
#define YYMAXDEPTH 1000000
-#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp);
+#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp)
#define jpElementStart(cnt) yyGetParser->PrepareElement(&yyval)
#define jpStoreClass(str) yyGetParser->AddClassFound(str); yyGetParser->DeallocateParserType(&(str))
/* Disable some warnings in the generated code. */
@@ -115,14 +119,20 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message);
# pragma warning (disable: 4102) /* Unused goto label. */
# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
#endif
+#if defined(__GNUC__) && __GNUC__ >= 8
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif
-#line 120 "cmDependsJavaParser.cxx" /* yacc.c:339 */
-
+#line 127 "cmDependsJavaParser.cxx" /* yacc.c:337 */
# ifndef YY_NULLPTR
-# if defined __cplusplus && 201103L <= __cplusplus
-# define YY_NULLPTR nullptr
+# if defined __cplusplus
+# if 201103L <= __cplusplus
+# define YY_NULLPTR nullptr
+# else
+# define YY_NULLPTR 0
+# endif
# else
-# define YY_NULLPTR 0
+# define YY_NULLPTR ((void*)0)
# endif
# endif
@@ -369,9 +379,7 @@ int cmDependsJava_yyparse (yyscan_t yyscanner);
#endif /* !YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED */
-/* Copy the second part of user declarations. */
-#line 375 "cmDependsJavaParser.cxx" /* yacc.c:358 */
#ifdef short
# undef short
@@ -392,13 +400,13 @@ typedef signed char yytype_int8;
#ifdef YYTYPE_UINT16
typedef YYTYPE_UINT16 yytype_uint16;
#else
-typedef unsigned short int yytype_uint16;
+typedef unsigned short yytype_uint16;
#endif
#ifdef YYTYPE_INT16
typedef YYTYPE_INT16 yytype_int16;
#else
-typedef short int yytype_int16;
+typedef short yytype_int16;
#endif
#ifndef YYSIZE_T
@@ -410,7 +418,7 @@ typedef short int yytype_int16;
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
-# define YYSIZE_T unsigned int
+# define YYSIZE_T unsigned
# endif
#endif
@@ -446,15 +454,6 @@ typedef short int yytype_int16;
# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
#endif
-#if !defined _Noreturn \
- && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
-# if defined _MSC_VER && 1200 <= _MSC_VER
-# define _Noreturn __declspec (noreturn)
-# else
-# define _Noreturn YY_ATTRIBUTE ((__noreturn__))
-# endif
-#endif
-
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
# define YYUSE(E) ((void) (E))
@@ -462,7 +461,7 @@ typedef short int yytype_int16;
# define YYUSE(E) /* empty */
#endif
-#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
_Pragma ("GCC diagnostic push") \
@@ -624,16 +623,16 @@ union yyalloc
/* YYNSTATES -- Number of states. */
#define YYNSTATES 575
-/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
- by yylex, with out-of-bounds checking. */
#define YYUNDEFTOK 2
#define YYMAXUTOK 360
+/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, with out-of-bounds checking. */
#define YYTRANSLATE(YYX) \
- ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+ ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
- as returned by yylex, without out-of-bounds checking. */
+ as returned by yylex. */
static const yytype_uint8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -679,42 +678,42 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 179, 179, 188, 196, 204, 212, 220, 228, 237,
- 245, 254, 262, 271, 276, 281, 286, 291, 296, 301,
- 306, 312, 320, 329, 339, 348, 357, 365, 375, 381,
- 388, 395, 401, 408, 417, 427, 437, 446, 454, 463,
- 472, 478, 487, 493, 502, 508, 517, 529, 537, 546,
- 558, 571, 579, 587, 596, 604, 613, 613, 613, 614,
- 615, 615, 615, 615, 615, 615, 616, 619, 629, 638,
- 647, 656, 666, 672, 681, 690, 699, 707, 716, 725,
- 731, 740, 748, 756, 764, 773, 781, 790, 796, 804,
- 813, 821, 830, 839, 848, 856, 865, 873, 881, 890,
- 899, 909, 916, 926, 936, 943, 950, 953, 959, 969,
- 979, 989, 995, 1005, 1015, 1025, 1034, 1044, 1055, 1065,
- 1072, 1082, 1091, 1101, 1110, 1120, 1126, 1136, 1145, 1155,
- 1165, 1172, 1181, 1190, 1199, 1208, 1216, 1225, 1234, 1244,
- 1254, 1263, 1273, 1283, 1290, 1299, 1309, 1318, 1328, 1337,
- 1344, 1354, 1363, 1373, 1382, 1391, 1401, 1411, 1420, 1430,
- 1439, 1448, 1457, 1466, 1475, 1485, 1494, 1503, 1512, 1521,
- 1531, 1540, 1549, 1558, 1567, 1576, 1585, 1594, 1603, 1612,
- 1621, 1630, 1640, 1650, 1661, 1671, 1681, 1690, 1699, 1708,
- 1717, 1726, 1735, 1745, 1755, 1765, 1775, 1782, 1789, 1796,
- 1806, 1813, 1823, 1833, 1842, 1852, 1861, 1871, 1878, 1885,
- 1892, 1900, 1907, 1917, 1924, 1934, 1944, 1951, 1961, 1970,
- 1980, 1990, 1999, 2009, 2018, 2028, 2039, 2046, 2053, 2064,
- 2074, 2084, 2094, 2103, 2113, 2120, 2130, 2139, 2149, 2156,
- 2166, 2175, 2185, 2194, 2200, 2209, 2218, 2227, 2236, 2246,
- 2256, 2263, 2273, 2280, 2290, 2299, 2309, 2318, 2327, 2336,
- 2346, 2353, 2363, 2372, 2382, 2392, 2398, 2405, 2415, 2425,
- 2435, 2446, 2456, 2467, 2477, 2488, 2498, 2508, 2517, 2526,
- 2535, 2544, 2554, 2564, 2574, 2583, 2592, 2601, 2610, 2620,
- 2630, 2640, 2649, 2658, 2667, 2677, 2686, 2695, 2702, 2711,
- 2720, 2729, 2739, 2748, 2757, 2767, 2776, 2785, 2794, 2804,
- 2813, 2822, 2831, 2840, 2849, 2859, 2868, 2877, 2887, 2896,
- 2906, 2915, 2925, 2934, 2944, 2953, 2963, 2972, 2982, 2991,
- 3001, 3010, 3020, 3030, 3040, 3049, 3059, 3068, 3077, 3086,
- 3095, 3104, 3113, 3122, 3131, 3140, 3149, 3158, 3168, 3178,
- 3188, 3197
+ 0, 182, 182, 191, 199, 207, 215, 223, 231, 240,
+ 248, 257, 265, 274, 279, 284, 289, 294, 299, 304,
+ 309, 315, 323, 332, 342, 351, 360, 368, 378, 384,
+ 391, 398, 404, 411, 420, 430, 440, 449, 457, 466,
+ 475, 481, 490, 496, 505, 511, 520, 532, 540, 549,
+ 561, 574, 582, 590, 599, 607, 616, 616, 616, 617,
+ 618, 618, 618, 618, 618, 618, 619, 622, 632, 641,
+ 650, 659, 669, 675, 684, 693, 702, 710, 719, 728,
+ 734, 743, 751, 759, 767, 776, 784, 793, 799, 807,
+ 816, 824, 833, 842, 851, 859, 868, 876, 884, 893,
+ 902, 912, 919, 929, 939, 946, 953, 956, 962, 972,
+ 982, 992, 998, 1008, 1018, 1028, 1037, 1047, 1058, 1068,
+ 1075, 1085, 1094, 1104, 1113, 1123, 1129, 1139, 1148, 1158,
+ 1168, 1175, 1184, 1193, 1202, 1211, 1219, 1228, 1237, 1247,
+ 1257, 1266, 1276, 1286, 1293, 1302, 1312, 1321, 1331, 1340,
+ 1347, 1357, 1366, 1376, 1385, 1394, 1404, 1414, 1423, 1433,
+ 1442, 1451, 1460, 1469, 1478, 1488, 1497, 1506, 1515, 1524,
+ 1534, 1543, 1552, 1561, 1570, 1579, 1588, 1597, 1606, 1615,
+ 1624, 1633, 1643, 1653, 1664, 1674, 1684, 1693, 1702, 1711,
+ 1720, 1729, 1738, 1748, 1758, 1768, 1778, 1785, 1792, 1799,
+ 1809, 1816, 1826, 1836, 1845, 1855, 1864, 1874, 1881, 1888,
+ 1895, 1903, 1910, 1920, 1927, 1937, 1947, 1954, 1964, 1973,
+ 1983, 1993, 2002, 2012, 2021, 2031, 2042, 2049, 2056, 2067,
+ 2077, 2087, 2097, 2106, 2116, 2123, 2133, 2142, 2152, 2159,
+ 2169, 2178, 2188, 2197, 2203, 2212, 2221, 2230, 2239, 2249,
+ 2259, 2266, 2276, 2283, 2293, 2302, 2312, 2321, 2330, 2339,
+ 2349, 2356, 2366, 2375, 2385, 2395, 2401, 2408, 2418, 2428,
+ 2438, 2449, 2459, 2470, 2480, 2491, 2501, 2511, 2520, 2529,
+ 2538, 2547, 2557, 2567, 2577, 2586, 2595, 2604, 2613, 2623,
+ 2633, 2643, 2652, 2661, 2670, 2680, 2689, 2698, 2705, 2714,
+ 2723, 2732, 2742, 2751, 2760, 2770, 2779, 2788, 2797, 2807,
+ 2816, 2825, 2834, 2843, 2852, 2862, 2871, 2880, 2890, 2899,
+ 2909, 2918, 2928, 2937, 2947, 2956, 2966, 2975, 2985, 2994,
+ 3004, 3013, 3023, 3033, 3043, 3052, 3062, 3071, 3080, 3089,
+ 3098, 3107, 3116, 3125, 3134, 3143, 3152, 3161, 3171, 3181,
+ 3191, 3200
};
#endif
@@ -1615,22 +1614,22 @@ static const yytype_uint8 yyr2[] =
#define YYRECOVERING() (!!yyerrstatus)
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- YYPOPSTACK (yylen); \
- yystate = *yyssp; \
- goto yybackup; \
- } \
- else \
- { \
- yyerror (yyscanner, YY_("syntax error: cannot back up")); \
- YYERROR; \
- } \
-while (0)
+#define YYBACKUP(Token, Value) \
+ do \
+ if (yychar == YYEMPTY) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ YYPOPSTACK (yylen); \
+ yystate = *yyssp; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (yyscanner, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+ while (0)
/* Error token number */
#define YYTERROR 1
@@ -1670,38 +1669,38 @@ do { \
} while (0)
-/*----------------------------------------.
-| Print this symbol's value on YYOUTPUT. |
-`----------------------------------------*/
+/*-----------------------------------.
+| Print this symbol's value on YYO. |
+`-----------------------------------*/
static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
- FILE *yyo = yyoutput;
- YYUSE (yyo);
+ FILE *yyoutput = yyo;
+ YYUSE (yyoutput);
YYUSE (yyscanner);
if (!yyvaluep)
return;
# ifdef YYPRINT
if (yytype < YYNTOKENS)
- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+ YYPRINT (yyo, yytoknum[yytype], *yyvaluep);
# endif
YYUSE (yytype);
}
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
+/*---------------------------.
+| Print this symbol on YYO. |
+`---------------------------*/
static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
- YYFPRINTF (yyoutput, "%s %s (",
+ YYFPRINTF (yyo, "%s %s (",
yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
- yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
- YYFPRINTF (yyoutput, ")");
+ yy_symbol_value_print (yyo, yytype, yyvaluep, yyscanner);
+ YYFPRINTF (yyo, ")");
}
/*------------------------------------------------------------------.
@@ -1735,7 +1734,7 @@ do { \
static void
yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
{
- unsigned long int yylno = yyrline[yyrule];
+ unsigned long yylno = yyrline[yyrule];
int yynrhs = yyr2[yyrule];
int yyi;
YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
@@ -1746,7 +1745,7 @@ yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yysca
YYFPRINTF (stderr, " $%d = ", yyi + 1);
yy_symbol_print (stderr,
yystos[yyssp[yyi + 1 - yynrhs]],
- &(yyvsp[(yyi + 1) - (yynrhs)])
+ &yyvsp[(yyi + 1) - (yynrhs)]
, yyscanner);
YYFPRINTF (stderr, "\n");
}
@@ -1850,7 +1849,10 @@ yytnamerr (char *yyres, const char *yystr)
case '\\':
if (*++yyp != '\\')
goto do_not_strip_quotes;
- /* Fall through. */
+ else
+ goto append;
+
+ append:
default:
if (yyres)
yyres[yyn] = *yyp;
@@ -1868,7 +1870,7 @@ yytnamerr (char *yyres, const char *yystr)
if (! yyres)
return yystrlen (yystr);
- return yystpcpy (yyres, yystr) - yyres;
+ return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres);
}
# endif
@@ -1946,10 +1948,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
yyarg[yycount++] = yytname[yyx];
{
YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
- if (! (yysize <= yysize1
- && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+ yysize = yysize1;
+ else
return 2;
- yysize = yysize1;
}
}
}
@@ -1961,6 +1963,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
case N: \
yyformat = S; \
break
+ default: /* Avoid compiler warnings. */
YYCASE_(0, YY_("syntax error"));
YYCASE_(1, YY_("syntax error, unexpected %s"));
YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
@@ -1972,9 +1975,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
{
YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
- if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+ yysize = yysize1;
+ else
return 2;
- yysize = yysize1;
}
if (*yymsg_alloc < yysize)
@@ -2105,23 +2109,31 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
yychar = YYEMPTY; /* Cause a token to be read. */
goto yysetstate;
+
/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate. |
+| yynewstate -- push a new state, which is found in yystate. |
`------------------------------------------------------------*/
- yynewstate:
+yynewstate:
/* In all cases, when you get here, the value and location stacks
have just been pushed. So pushing a state here evens the stacks. */
yyssp++;
- yysetstate:
- *yyssp = yystate;
+
+/*--------------------------------------------------------------------.
+| yynewstate -- set current state (the top of the stack) to yystate. |
+`--------------------------------------------------------------------*/
+yysetstate:
+ *yyssp = (yytype_int16) yystate;
if (yyss + yystacksize - 1 <= yyssp)
+#if !defined yyoverflow && !defined YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+#else
{
/* Get the current used size of the three stacks, in elements. */
- YYSIZE_T yysize = yyssp - yyss + 1;
+ YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1);
-#ifdef yyoverflow
+# if defined yyoverflow
{
/* Give user a chance to reallocate the stack. Use copies of
these so that the &'s don't force the real ones into
@@ -2137,14 +2149,10 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
&yyss1, yysize * sizeof (*yyssp),
&yyvs1, yysize * sizeof (*yyvsp),
&yystacksize);
-
yyss = yyss1;
yyvs = yyvs1;
}
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
- goto yyexhaustedlab;
-# else
+# else /* defined YYSTACK_RELOCATE */
/* Extend the stack our own way. */
if (YYMAXDEPTH <= yystacksize)
goto yyexhaustedlab;
@@ -2160,22 +2168,22 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
goto yyexhaustedlab;
YYSTACK_RELOCATE (yyss_alloc, yyss);
YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-# undef YYSTACK_RELOCATE
+# undef YYSTACK_RELOCATE
if (yyss1 != yyssa)
YYSTACK_FREE (yyss1);
}
# endif
-#endif /* no yyoverflow */
yyssp = yyss + yysize - 1;
yyvsp = yyvs + yysize - 1;
YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long int) yystacksize));
+ (unsigned long) yystacksize));
if (yyss + yystacksize - 1 <= yyssp)
YYABORT;
}
+#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
@@ -2184,11 +2192,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
goto yybackup;
+
/*-----------.
| yybackup. |
`-----------*/
yybackup:
-
/* Do appropriate processing given the current state. Read a
lookahead token if we need one and don't already have one. */
@@ -2261,7 +2269,7 @@ yydefault:
/*-----------------------------.
-| yyreduce -- Do a reduction. |
+| yyreduce -- do a reduction. |
`-----------------------------*/
yyreduce:
/* yyn is the number of a rule to reduce with. */
@@ -2282,214 +2290,214 @@ yyreduce:
switch (yyn)
{
case 2:
-#line 180 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 183 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2301 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 3:
-#line 189 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 192 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2304 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2312 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 4:
-#line 197 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 200 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2315 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2323 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 5:
-#line 205 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 208 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2326 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2334 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 6:
-#line 213 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 216 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2337 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2345 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 7:
-#line 221 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 224 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2348 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2356 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 8:
-#line 229 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 232 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2359 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2367 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 9:
-#line 238 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 241 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2370 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2378 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 10:
-#line 246 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 249 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2381 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2389 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 11:
-#line 255 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 258 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2392 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2400 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 12:
-#line 263 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 266 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2403 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2411 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 13:
-#line 272 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 275 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
}
-#line 2411 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2419 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 14:
-#line 277 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 280 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
}
-#line 2419 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2427 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 15:
-#line 282 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 285 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
}
-#line 2427 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2435 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 16:
-#line 287 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 290 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
}
-#line 2435 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2443 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 17:
-#line 292 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 295 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
}
-#line 2443 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2451 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 18:
-#line 297 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 300 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
}
-#line 2451 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2459 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 19:
-#line 302 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 305 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
}
-#line 2459 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2467 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 20:
-#line 307 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 310 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
}
-#line 2467 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2475 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 21:
-#line 313 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 316 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2478 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2486 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 22:
-#line 321 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 324 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2489 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2497 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 23:
-#line 330 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 333 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpStoreClass((yyvsp[0].str));
@@ -2497,44 +2505,44 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2501 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2509 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 24:
-#line 340 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 343 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2512 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2520 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 25:
-#line 349 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 352 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2523 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2531 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 26:
-#line 358 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 361 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2534 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2542 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 27:
-#line 366 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 369 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpStoreClass((yyvsp[-1].str));
@@ -2542,56 +2550,56 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2546 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2554 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 28:
-#line 376 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 379 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
(yyval.str) = (yyvsp[0].str);
}
-#line 2555 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2563 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 29:
-#line 382 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 385 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
(yyval.str) = (yyvsp[0].str);
}
-#line 2564 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2572 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 30:
-#line 389 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 392 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
(yyval.str) = (yyvsp[0].str);
}
-#line 2573 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2581 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 31:
-#line 396 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 399 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
(yyval.str) = (yyvsp[0].str);
}
-#line 2582 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2590 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 32:
-#line 402 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 405 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
(yyval.str) = (yyvsp[0].str);
}
-#line 2591 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2599 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 33:
-#line 409 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 412 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
yyGetParser->AddClassFound((yyvsp[-2].str));
@@ -2599,11 +2607,11 @@ yyreduce:
yyGetParser->DeallocateParserType(&((yyvsp[-2].str)));
(yyval.str) = const_cast<char*>(yyGetParser->GetCurrentCombine());
}
-#line 2603 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2611 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 34:
-#line 418 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 421 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpStoreClass((yyvsp[-2].str));
@@ -2612,11 +2620,11 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2616 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2624 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 35:
-#line 428 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 431 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpStoreClass((yyvsp[-2].str));
@@ -2625,118 +2633,118 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2629 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2637 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 36:
-#line 438 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 441 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2640 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2648 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 37:
-#line 447 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 450 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2651 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2659 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 38:
-#line 455 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 458 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2662 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2670 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 39:
-#line 464 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 467 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2673 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2681 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 40:
-#line 472 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 475 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2683 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2691 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 41:
-#line 479 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 482 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2694 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2702 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 42:
-#line 487 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 490 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2704 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2712 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 43:
-#line 494 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 497 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2715 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2723 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 44:
-#line 502 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 505 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2725 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2733 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 45:
-#line 509 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 512 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2736 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2744 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 46:
-#line 518 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 521 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
yyGetParser->SetCurrentPackage((yyvsp[-1].str));
@@ -2746,33 +2754,33 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2750 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2758 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 47:
-#line 530 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 533 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2761 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2769 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 48:
-#line 538 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 541 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2772 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2780 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 49:
-#line 547 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 550 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
yyGetParser->AddPackagesImport((yyvsp[-1].str));
@@ -2782,11 +2790,11 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2786 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2794 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 50:
-#line 559 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 562 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(5);
std::string str = (yyvsp[-3].str);
@@ -2797,77 +2805,77 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2801 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2809 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 51:
-#line 572 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 575 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2812 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2820 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 52:
-#line 580 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 583 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2823 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2831 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 53:
-#line 588 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 591 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2834 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2842 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 54:
-#line 597 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 600 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2845 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2853 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 55:
-#line 605 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 608 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2856 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2864 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 67:
-#line 620 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 623 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
yyGetParser->StartClass((yyvsp[0].str));
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
}
-#line 2867 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2875 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 68:
-#line 630 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 633 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -2875,11 +2883,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 2879 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2887 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 69:
-#line 639 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 642 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(2);
@@ -2887,11 +2895,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 2891 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2899 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 70:
-#line 648 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 651 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -2899,11 +2907,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 2903 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2911 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 71:
-#line 657 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 660 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
jpCheckEmpty(4);
@@ -2911,226 +2919,226 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 2915 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2923 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 72:
-#line 666 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 669 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2925 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2933 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 73:
-#line 673 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 676 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2936 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2944 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 74:
-#line 682 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 685 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2947 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2955 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 75:
-#line 691 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 694 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2958 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2966 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 76:
-#line 700 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 703 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2969 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2977 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 77:
-#line 708 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 711 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2980 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2988 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 78:
-#line 717 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 720 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 2991 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 2999 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 79:
-#line 725 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 728 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3001 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3009 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 80:
-#line 732 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 735 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3012 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3020 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 81:
-#line 741 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 744 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3023 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3031 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 82:
-#line 749 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 752 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3034 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3042 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 83:
-#line 757 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 760 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3045 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3053 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 84:
-#line 765 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 768 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3056 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3064 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 85:
-#line 774 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 777 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3067 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3075 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 86:
-#line 782 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 785 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3078 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3086 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 87:
-#line 791 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 794 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
}
-#line 3086 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3094 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 88:
-#line 797 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 800 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3097 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3105 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 89:
-#line 805 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 808 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3108 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3116 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 90:
-#line 814 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 817 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3119 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3127 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 91:
-#line 822 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 825 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3130 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3138 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 92:
-#line 831 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 834 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
@@ -3138,77 +3146,77 @@ yyreduce:
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3142 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3150 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 93:
-#line 840 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 843 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3153 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3161 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 94:
-#line 849 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 852 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3164 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3172 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 95:
-#line 857 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 860 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3175 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3183 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 96:
-#line 866 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 869 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3186 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3194 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 97:
-#line 874 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 877 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3197 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3205 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 98:
-#line 882 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 885 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3208 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3216 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 99:
-#line 891 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 894 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
jpCheckEmpty(4);
@@ -3216,11 +3224,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3220 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3228 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 100:
-#line 900 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 903 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
jpCheckEmpty(4);
@@ -3228,22 +3236,22 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3232 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3240 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 101:
-#line 909 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 912 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3243 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3251 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 102:
-#line 917 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 920 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3251,11 +3259,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3255 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3263 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 103:
-#line 927 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 930 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
@@ -3264,40 +3272,40 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3268 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3276 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 104:
-#line 937 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 940 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
}
-#line 3277 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3285 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 105:
-#line 943 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 946 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3288 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3296 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 107:
-#line 954 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 957 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
}
-#line 3297 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3305 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 108:
-#line 960 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 963 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -3305,11 +3313,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3309 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3317 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 109:
-#line 970 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 973 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -3317,11 +3325,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3321 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3329 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 110:
-#line 980 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 983 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -3329,20 +3337,20 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3333 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3341 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 111:
-#line 990 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 993 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
}
-#line 3342 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3350 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 112:
-#line 996 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 999 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -3350,11 +3358,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3354 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3362 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 113:
-#line 1006 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1009 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3362,11 +3370,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3366 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3374 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 114:
-#line 1016 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1019 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -3374,11 +3382,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3378 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3386 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 115:
-#line 1026 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1029 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
jpCheckEmpty(4);
@@ -3386,11 +3394,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3390 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3398 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 116:
-#line 1035 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1038 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(5);
jpCheckEmpty(5);
@@ -3398,11 +3406,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3402 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3410 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 117:
-#line 1045 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1048 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
@@ -3411,11 +3419,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3415 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3423 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 118:
-#line 1056 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1059 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
jpCheckEmpty(4);
@@ -3423,22 +3431,22 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3427 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3435 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 119:
-#line 1065 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1068 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3438 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3446 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 120:
-#line 1073 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1076 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -3446,11 +3454,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3450 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3458 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 121:
-#line 1083 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1086 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(5);
jpCheckEmpty(5);
@@ -3458,11 +3466,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3462 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3470 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 122:
-#line 1092 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1095 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(5);
jpCheckEmpty(5);
@@ -3470,22 +3478,22 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3474 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3482 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 123:
-#line 1102 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1105 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
yyGetParser->StartClass((yyvsp[0].str));
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
jpCheckEmpty(3);
}
-#line 3485 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3493 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 124:
-#line 1111 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1114 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -3493,21 +3501,21 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
yyGetParser->EndClass();
}
-#line 3497 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3505 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 125:
-#line 1120 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1123 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3507 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3515 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 126:
-#line 1127 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1130 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3515,11 +3523,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3519 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3527 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 127:
-#line 1137 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1140 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -3527,11 +3535,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3531 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3539 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 128:
-#line 1146 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1149 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -3539,11 +3547,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3543 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3551 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 129:
-#line 1156 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1159 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -3551,33 +3559,33 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3555 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3563 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 130:
-#line 1165 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1168 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3566 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3574 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 131:
-#line 1173 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1176 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3577 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3585 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 132:
-#line 1182 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1185 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3585,11 +3593,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3589 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3597 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 133:
-#line 1191 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1194 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3597,11 +3605,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3601 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3609 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 134:
-#line 1200 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1203 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3609,22 +3617,22 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3613 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3621 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 135:
-#line 1209 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1212 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3624 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3632 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 136:
-#line 1217 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1220 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3632,22 +3640,22 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3636 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3644 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 137:
-#line 1226 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1229 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3647 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3655 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 138:
-#line 1235 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1238 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3655,11 +3663,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3659 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3667 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 139:
-#line 1245 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1248 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -3667,11 +3675,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3671 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3679 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 140:
-#line 1255 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1258 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3679,11 +3687,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3683 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3691 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 141:
-#line 1264 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1267 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -3691,11 +3699,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3695 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3703 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 142:
-#line 1274 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1277 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -3703,22 +3711,22 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3707 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3715 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 143:
-#line 1283 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1286 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3718 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3726 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 144:
-#line 1291 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1294 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3726,11 +3734,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3730 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3738 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 145:
-#line 1300 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1303 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -3738,11 +3746,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3742 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3750 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 146:
-#line 1310 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1313 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3750,11 +3758,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3754 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3762 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 147:
-#line 1319 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1322 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -3762,33 +3770,33 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3766 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3774 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 148:
-#line 1329 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1332 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3777 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3785 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 149:
-#line 1337 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1340 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 3788 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3796 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 150:
-#line 1345 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1348 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3796,11 +3804,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3800 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3808 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 151:
-#line 1355 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1358 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3808,11 +3816,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3812 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3820 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 152:
-#line 1364 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1367 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(2);
@@ -3820,11 +3828,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3824 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3832 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 153:
-#line 1374 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1377 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3832,11 +3840,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3836 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3844 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 154:
-#line 1383 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1386 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3844,11 +3852,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3848 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3856 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 155:
-#line 1392 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1395 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3856,11 +3864,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3860 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3868 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 156:
-#line 1402 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1405 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(2);
@@ -3868,11 +3876,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3872 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3880 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 157:
-#line 1412 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1415 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(3);
@@ -3880,11 +3888,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3884 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3892 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 158:
-#line 1421 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1424 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(2);
@@ -3892,11 +3900,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3896 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3904 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 159:
-#line 1431 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1434 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3904,11 +3912,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3908 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3916 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 160:
-#line 1440 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1443 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3916,11 +3924,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3920 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3928 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 161:
-#line 1449 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1452 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3928,11 +3936,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3932 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3940 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 162:
-#line 1458 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1461 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3940,11 +3948,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3944 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3952 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 163:
-#line 1467 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1470 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3952,11 +3960,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3956 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3964 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 164:
-#line 1476 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1479 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3964,11 +3972,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3968 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3976 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 165:
-#line 1486 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1489 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3976,11 +3984,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3980 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 3988 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 166:
-#line 1495 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1498 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -3988,11 +3996,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 3992 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4000 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 167:
-#line 1504 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1507 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4000,11 +4008,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4004 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4012 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 168:
-#line 1513 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1516 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4012,11 +4020,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4016 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4024 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 169:
-#line 1522 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1525 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4024,11 +4032,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4028 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4036 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 170:
-#line 1532 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1535 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4036,11 +4044,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4040 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4048 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 171:
-#line 1541 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1544 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4048,11 +4056,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4052 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4060 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 172:
-#line 1550 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1553 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4060,11 +4068,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4064 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4072 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 173:
-#line 1559 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1562 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4072,11 +4080,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4076 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4084 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 174:
-#line 1568 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1571 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4084,11 +4092,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4088 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4096 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 175:
-#line 1577 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1580 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4096,11 +4104,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4100 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4108 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 176:
-#line 1586 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1589 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4108,11 +4116,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4112 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4120 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 177:
-#line 1595 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1598 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4120,11 +4128,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4124 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4132 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 178:
-#line 1604 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1607 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4132,11 +4140,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4136 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4144 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 179:
-#line 1613 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1616 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4144,11 +4152,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4148 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4156 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 180:
-#line 1622 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1625 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4156,11 +4164,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4160 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4168 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 181:
-#line 1631 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1634 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4168,11 +4176,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4172 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4180 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 182:
-#line 1641 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1644 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4180,11 +4188,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4184 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4192 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 183:
-#line 1651 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1654 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[-2].str)));
@@ -4193,11 +4201,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4197 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4205 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 184:
-#line 1662 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1665 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -4205,11 +4213,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4209 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4217 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 185:
-#line 1672 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1675 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -4217,11 +4225,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4221 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4229 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 186:
-#line 1682 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1685 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4229,11 +4237,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4233 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4241 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 187:
-#line 1691 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1694 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4241,11 +4249,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4245 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4253 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 188:
-#line 1700 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1703 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4253,11 +4261,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4257 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4265 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 189:
-#line 1709 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1712 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4265,11 +4273,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4269 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4277 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 190:
-#line 1718 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1721 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4277,11 +4285,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4281 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4289 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 191:
-#line 1727 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1730 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4289,11 +4297,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4301 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 192:
-#line 1736 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1739 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4301,11 +4309,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4305 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4313 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 193:
-#line 1746 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1749 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(5);
jpCheckEmpty(5);
@@ -4313,11 +4321,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4317 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4325 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 194:
-#line 1756 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1759 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(7);
jpCheckEmpty(7);
@@ -4325,11 +4333,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4329 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4337 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 195:
-#line 1766 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1769 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(7);
jpCheckEmpty(7);
@@ -4337,40 +4345,40 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4341 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4349 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 196:
-#line 1776 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1779 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(5);
}
-#line 4350 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4358 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 197:
-#line 1783 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1786 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
}
-#line 4359 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4367 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 198:
-#line 1789 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1792 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4370 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4378 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 199:
-#line 1797 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1800 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4378,22 +4386,22 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4382 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4390 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 200:
-#line 1806 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1809 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4393 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4401 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 201:
-#line 1814 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1817 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -4401,11 +4409,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4405 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4413 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 202:
-#line 1824 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1827 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -4413,11 +4421,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4417 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4425 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 203:
-#line 1834 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1837 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4425,11 +4433,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4429 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4437 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 204:
-#line 1843 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1846 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -4437,11 +4445,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4441 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4449 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 205:
-#line 1853 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1856 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -4449,11 +4457,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4453 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4461 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 206:
-#line 1862 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1865 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -4461,58 +4469,58 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4465 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4473 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 207:
-#line 1872 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1875 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(5);
}
-#line 4474 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4482 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 208:
-#line 1879 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1882 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(5);
}
-#line 4483 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4491 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 209:
-#line 1886 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1889 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(7);
}
-#line 4492 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4500 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 210:
-#line 1894 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1897 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(9);
}
-#line 4501 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4509 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 211:
-#line 1900 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1903 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4512 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4520 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 212:
-#line 1908 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1911 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4520,22 +4528,22 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4524 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4532 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 213:
-#line 1917 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1920 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4535 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4543 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 214:
-#line 1925 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1928 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4543,33 +4551,33 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4547 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4555 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 215:
-#line 1936 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1939 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(9);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4558 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4566 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 216:
-#line 1944 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1947 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4569 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4577 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 217:
-#line 1952 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1955 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4577,11 +4585,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4581 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4589 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 218:
-#line 1962 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1965 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4589,11 +4597,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4593 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4601 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 219:
-#line 1971 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1974 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4601,11 +4609,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4605 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4613 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 220:
-#line 1981 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1984 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4613,11 +4621,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4617 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4625 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 221:
-#line 1991 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 1994 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4625,11 +4633,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4629 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4637 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 222:
-#line 2000 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2003 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -4637,11 +4645,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4641 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4649 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 223:
-#line 2010 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2013 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -4649,11 +4657,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4653 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4661 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 224:
-#line 2019 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2022 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(5);
jpCheckEmpty(5);
@@ -4661,11 +4669,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4665 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4673 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 225:
-#line 2029 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2032 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
@@ -4674,31 +4682,31 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4678 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4686 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 226:
-#line 2039 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2042 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4689 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4697 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 227:
-#line 2047 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2050 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
}
-#line 4698 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4706 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 228:
-#line 2054 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2057 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[-1].str)));
@@ -4707,11 +4715,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4711 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4719 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 229:
-#line 2065 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2068 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -4719,11 +4727,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4723 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4731 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 230:
-#line 2075 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2078 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -4731,11 +4739,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4735 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4743 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 231:
-#line 2085 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2088 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(5);
jpCheckEmpty(5);
@@ -4743,11 +4751,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4747 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4755 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 232:
-#line 2095 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2098 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -4755,11 +4763,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4759 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4767 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 233:
-#line 2104 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2107 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
jpCheckEmpty(4);
@@ -4767,22 +4775,22 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4771 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4779 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 234:
-#line 2113 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2116 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4782 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4790 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 235:
-#line 2121 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2124 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4790,11 +4798,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4794 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4802 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 236:
-#line 2131 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2134 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4802,11 +4810,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4806 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4814 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 237:
-#line 2140 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2143 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -4814,20 +4822,20 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4818 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4826 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 238:
-#line 2150 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2153 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(5);
}
-#line 4827 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4835 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 239:
-#line 2157 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2160 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -4835,11 +4843,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4839 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4847 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 240:
-#line 2167 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2170 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4847,11 +4855,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4851 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4859 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 241:
-#line 2176 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2179 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4859,11 +4867,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4863 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4871 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 242:
-#line 2186 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2189 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4871,20 +4879,20 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4875 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4883 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 243:
-#line 2195 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2198 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
}
-#line 4884 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4892 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 244:
-#line 2201 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2204 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -4892,11 +4900,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4896 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4904 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 245:
-#line 2210 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2213 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4904,11 +4912,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4908 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4916 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 246:
-#line 2219 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2222 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4916,11 +4924,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4920 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4928 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 247:
-#line 2228 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2231 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4928,11 +4936,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4932 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4940 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 248:
-#line 2237 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2240 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4940,11 +4948,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4944 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4952 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 249:
-#line 2247 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2250 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(6);
jpCheckEmpty(6);
@@ -4952,22 +4960,22 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4956 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4964 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 250:
-#line 2256 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2259 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4967 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4975 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 251:
-#line 2264 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2267 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4975,22 +4983,22 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 4979 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4987 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 252:
-#line 2273 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2276 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 4990 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 4998 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 253:
-#line 2281 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2284 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -4998,11 +5006,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5002 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5010 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 254:
-#line 2291 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2294 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5010,11 +5018,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5014 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5022 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 255:
-#line 2300 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2303 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5022,11 +5030,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5026 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5034 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 256:
-#line 2310 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2313 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
jpCheckEmpty(4);
@@ -5034,11 +5042,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5038 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5046 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 257:
-#line 2319 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2322 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
jpCheckEmpty(4);
@@ -5046,11 +5054,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5050 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5058 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 258:
-#line 2328 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2331 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
jpCheckEmpty(4);
@@ -5058,11 +5066,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5062 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5070 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 259:
-#line 2337 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2340 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
jpCheckEmpty(4);
@@ -5070,22 +5078,22 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5074 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5082 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 260:
-#line 2346 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2349 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(0);
(yyval.str) = 0;
yyGetParser->SetCurrentCombine("");
}
-#line 5085 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5093 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 261:
-#line 2354 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2357 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5093,11 +5101,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5097 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5105 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 262:
-#line 2364 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2367 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5105,11 +5113,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5109 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5117 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 263:
-#line 2373 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2376 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -5117,11 +5125,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5121 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5129 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 264:
-#line 2383 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2386 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5129,29 +5137,29 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5133 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5141 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 265:
-#line 2393 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2396 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
}
-#line 5142 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5150 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 266:
-#line 2399 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2402 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
}
-#line 5151 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5159 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 267:
-#line 2406 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2409 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
@@ -5160,11 +5168,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5164 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5172 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 268:
-#line 2416 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2419 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
@@ -5173,11 +5181,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5177 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5185 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 269:
-#line 2426 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2429 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
@@ -5186,11 +5194,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5190 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5198 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 270:
-#line 2436 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2439 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
@@ -5199,11 +5207,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5203 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5211 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 271:
-#line 2447 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2450 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
@@ -5212,11 +5220,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5216 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5224 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 272:
-#line 2457 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2460 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(6);
yyGetParser->DeallocateParserType(&((yyvsp[-5].str)));
@@ -5226,11 +5234,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5230 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5238 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 273:
-#line 2468 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2471 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(6);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
@@ -5239,11 +5247,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5243 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5251 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 274:
-#line 2478 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2481 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(6);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
@@ -5252,11 +5260,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5256 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5264 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 275:
-#line 2489 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2492 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
yyGetParser->DeallocateParserType(&((yyvsp[-3].str)));
@@ -5265,11 +5273,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5269 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5277 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 276:
-#line 2499 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2502 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
jpCheckEmpty(4);
@@ -5277,11 +5285,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5281 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5289 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 277:
-#line 2509 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2512 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5289,11 +5297,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5301 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 278:
-#line 2518 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2521 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
@@ -5301,11 +5309,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5305 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5313 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 279:
-#line 2527 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2530 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5313,11 +5321,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5317 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5325 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 280:
-#line 2536 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2539 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5325,11 +5333,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5329 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5337 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 281:
-#line 2545 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2548 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5337,11 +5345,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5341 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5349 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 282:
-#line 2555 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2558 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -5349,11 +5357,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5353 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5361 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 283:
-#line 2565 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2568 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -5361,11 +5369,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5365 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5373 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 284:
-#line 2575 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2578 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5373,11 +5381,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5377 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5385 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 285:
-#line 2584 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2587 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5385,11 +5393,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5389 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5397 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 286:
-#line 2593 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2596 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -5397,11 +5405,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5401 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5409 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 287:
-#line 2602 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2605 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -5409,11 +5417,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5413 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5421 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 288:
-#line 2611 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2614 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5421,11 +5429,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5425 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5433 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 289:
-#line 2621 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2624 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -5433,11 +5441,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5437 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5445 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 290:
-#line 2631 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2634 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -5445,11 +5453,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5449 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5457 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 291:
-#line 2641 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2644 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5457,11 +5465,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5461 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5469 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 292:
-#line 2650 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2653 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -5469,11 +5477,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5473 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5481 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 293:
-#line 2659 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2662 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(2);
jpCheckEmpty(2);
@@ -5481,11 +5489,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5485 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5493 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 294:
-#line 2668 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2671 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5493,11 +5501,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5497 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5505 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 295:
-#line 2678 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2681 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(5);
jpCheckEmpty(5);
@@ -5505,11 +5513,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5509 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5517 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 296:
-#line 2687 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2690 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(4);
jpCheckEmpty(4);
@@ -5517,20 +5525,20 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5521 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5529 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 297:
-#line 2696 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2699 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(5);
}
-#line 5530 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5538 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 298:
-#line 2703 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2706 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5538,11 +5546,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5542 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5550 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 299:
-#line 2712 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2715 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5550,11 +5558,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5554 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5562 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 300:
-#line 2721 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2724 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5562,11 +5570,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5566 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5574 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 301:
-#line 2730 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2733 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5574,11 +5582,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5578 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5586 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 302:
-#line 2740 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2743 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5586,11 +5594,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5590 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5598 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 303:
-#line 2749 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2752 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5598,11 +5606,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5602 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5610 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 304:
-#line 2758 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2761 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5610,11 +5618,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5614 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5622 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 305:
-#line 2768 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2771 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5622,11 +5630,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5626 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5634 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 306:
-#line 2777 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2780 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5634,11 +5642,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5638 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5646 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 307:
-#line 2786 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2789 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5646,11 +5654,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5650 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5658 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 308:
-#line 2795 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2798 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5658,11 +5666,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5662 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5670 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 309:
-#line 2805 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2808 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5670,11 +5678,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5674 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5682 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 310:
-#line 2814 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2817 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5682,11 +5690,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5686 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5694 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 311:
-#line 2823 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2826 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5694,11 +5702,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5698 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5706 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 312:
-#line 2832 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2835 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5706,11 +5714,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5710 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5718 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 313:
-#line 2841 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2844 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5718,11 +5726,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5722 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5730 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 314:
-#line 2850 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2853 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5730,11 +5738,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5734 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5742 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 315:
-#line 2860 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2863 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5742,11 +5750,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5746 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5754 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 316:
-#line 2869 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2872 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5754,11 +5762,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5758 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5766 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 317:
-#line 2878 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2881 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5766,11 +5774,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5770 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5778 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 318:
-#line 2888 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2891 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5778,11 +5786,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5782 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5790 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 319:
-#line 2897 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2900 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5790,11 +5798,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5794 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5802 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 320:
-#line 2907 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2910 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5802,11 +5810,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5806 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5814 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 321:
-#line 2916 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2919 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5814,11 +5822,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5818 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5826 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 322:
-#line 2926 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2929 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5826,11 +5834,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5830 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5838 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 323:
-#line 2935 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2938 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5838,11 +5846,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5842 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5850 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 324:
-#line 2945 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2948 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5850,11 +5858,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5854 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5862 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 325:
-#line 2954 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2957 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5862,11 +5870,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5866 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5874 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 326:
-#line 2964 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2967 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5874,11 +5882,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5878 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5886 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 327:
-#line 2973 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2976 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5886,11 +5894,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5890 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5898 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 328:
-#line 2983 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2986 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5898,11 +5906,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5902 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5910 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 329:
-#line 2992 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 2995 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(5);
jpCheckEmpty(5);
@@ -5910,11 +5918,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5914 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5922 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 330:
-#line 3002 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3005 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5922,11 +5930,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5926 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5934 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 331:
-#line 3011 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3014 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5934,11 +5942,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5938 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5946 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 332:
-#line 3021 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3024 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpCheckEmpty(3);
@@ -5946,11 +5954,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5950 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5958 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 333:
-#line 3031 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3034 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
yyGetParser->DeallocateParserType(&((yyvsp[0].str)));
@@ -5959,11 +5967,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5963 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5971 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 334:
-#line 3041 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3044 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5971,11 +5979,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5975 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5983 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 335:
-#line 3050 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3053 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5983,11 +5991,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5987 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 5995 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 336:
-#line 3060 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3063 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -5995,11 +6003,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 5999 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6007 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 337:
-#line 3069 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3072 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -6007,11 +6015,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6011 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6019 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 338:
-#line 3078 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3081 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -6019,11 +6027,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6023 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6031 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 339:
-#line 3087 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3090 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -6031,11 +6039,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6035 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6043 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 340:
-#line 3096 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3099 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -6043,11 +6051,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6047 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6055 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 341:
-#line 3105 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3108 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -6055,11 +6063,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6059 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6067 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 342:
-#line 3114 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3117 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -6067,11 +6075,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6071 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6079 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 343:
-#line 3123 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3126 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -6079,11 +6087,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6083 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6091 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 344:
-#line 3132 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3135 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -6091,11 +6099,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6095 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6103 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 345:
-#line 3141 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3144 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -6103,11 +6111,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6107 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6115 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 346:
-#line 3150 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3153 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -6115,11 +6123,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6119 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6127 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 347:
-#line 3159 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3162 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -6127,11 +6135,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6131 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6139 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 348:
-#line 3169 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3172 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -6139,11 +6147,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6143 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6151 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 349:
-#line 3179 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3182 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -6151,11 +6159,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6155 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6163 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 350:
-#line 3189 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3192 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(1);
jpCheckEmpty(1);
@@ -6163,11 +6171,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6167 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6175 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
case 351:
-#line 3198 "cmDependsJavaParser.y" /* yacc.c:1646 */
+#line 3201 "cmDependsJavaParser.y" /* yacc.c:1652 */
{
jpElementStart(3);
jpStoreClass((yyvsp[-2].str));
@@ -6176,11 +6184,11 @@ yyreduce:
yyGetParser->SetCurrentCombine("");
}
-#line 6180 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6188 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
break;
-#line 6184 "cmDependsJavaParser.cxx" /* yacc.c:1646 */
+#line 6192 "cmDependsJavaParser.cxx" /* yacc.c:1652 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -6205,14 +6213,13 @@ yyreduce:
/* Now 'shift' the result of the reduction. Determine what state
that goes to, based on the state we popped back to and the rule
number reduced by. */
-
- yyn = yyr1[yyn];
-
- yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
- if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
- yystate = yytable[yystate];
- else
- yystate = yydefgoto[yyn - YYNTOKENS];
+ {
+ const int yylhs = yyr1[yyn] - YYNTOKENS;
+ const int yyi = yypgoto[yylhs] + *yyssp;
+ yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp
+ ? yytable[yyi]
+ : yydefgoto[yylhs]);
+ }
goto yynewstate;
@@ -6296,12 +6303,10 @@ yyerrlab:
| yyerrorlab -- error raised explicitly by YYERROR. |
`---------------------------------------------------*/
yyerrorlab:
-
- /* Pacify compilers like GCC when the user code never invokes
- YYERROR and the label yyerrorlab therefore never appears in user
- code. */
- if (/*CONSTCOND*/ 0)
- goto yyerrorlab;
+ /* Pacify compilers when the user code never invokes YYERROR and the
+ label yyerrorlab therefore never appears in user code. */
+ if (0)
+ YYERROR;
/* Do not reclaim the symbols of the rule whose action triggered
this YYERROR. */
@@ -6364,6 +6369,7 @@ yyacceptlab:
yyresult = 0;
goto yyreturn;
+
/*-----------------------------------.
| yyabortlab -- YYABORT comes here. |
`-----------------------------------*/
@@ -6371,6 +6377,7 @@ yyabortlab:
yyresult = 1;
goto yyreturn;
+
#if !defined yyoverflow || YYERROR_VERBOSE
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
@@ -6381,6 +6388,10 @@ yyexhaustedlab:
/* Fall through. */
#endif
+
+/*-----------------------------------------------------.
+| yyreturn -- parsing is finished, return the result. |
+`-----------------------------------------------------*/
yyreturn:
if (yychar != YYEMPTY)
{
@@ -6410,7 +6421,7 @@ yyreturn:
#endif
return yyresult;
}
-#line 3207 "cmDependsJavaParser.y" /* yacc.c:1906 */
+#line 3210 "cmDependsJavaParser.y" /* yacc.c:1918 */
/* End of grammar */
diff --git a/Source/LexerParser/cmDependsJavaParser.y b/Source/LexerParser/cmDependsJavaParser.y
index f7eb22818..d15cffc56 100644
--- a/Source/LexerParser/cmDependsJavaParser.y
+++ b/Source/LexerParser/cmDependsJavaParser.y
@@ -36,7 +36,7 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message);
#define YYMAXDEPTH 1000000
-#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp);
+#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp)
#define jpElementStart(cnt) yyGetParser->PrepareElement(&yyval)
#define jpStoreClass(str) yyGetParser->AddClassFound(str); yyGetParser->DeallocateParserType(&(str))
/* Disable some warnings in the generated code. */
@@ -44,6 +44,9 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message);
# pragma warning (disable: 4102) /* Unused goto label. */
# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
#endif
+#if defined(__GNUC__) && __GNUC__ >= 8
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif
%}
/* Generate a reentrant parser object. */
diff --git a/Source/LexerParser/cmDependsJavaParserTokens.h b/Source/LexerParser/cmDependsJavaParserTokens.h
index 7f18f1dd8..6bbc0848d 100644
--- a/Source/LexerParser/cmDependsJavaParserTokens.h
+++ b/Source/LexerParser/cmDependsJavaParserTokens.h
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4. */
+/* A Bison parser, made by GNU Bison 3.3.2. */
/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+ Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,6 +31,9 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
+/* Undocumented macros, especially those whose name start with YY_,
+ are private implementation details. Do not rely on them. */
+
#ifndef YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED
# define YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED
/* Debug traces. */
diff --git a/Source/LexerParser/cmExprLexer.cxx b/Source/LexerParser/cmExprLexer.cxx
index fb6f0db98..72e59b689 100644
--- a/Source/LexerParser/cmExprLexer.cxx
+++ b/Source/LexerParser/cmExprLexer.cxx
@@ -1,7 +1,4 @@
#include "cmStandardLexer.h"
-#line 2 "cmExprLexer.cxx"
-
-#line 4 "cmExprLexer.cxx"
#define FLEXINT_H 1
#define YY_INT_ALIGNED short int
@@ -11,11 +8,221 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6
-#define YY_FLEX_SUBMINOR_VERSION 1
+#define YY_FLEX_SUBMINOR_VERSION 4
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
+#ifdef yy_create_buffer
+#define cmExpr_yy_create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer cmExpr_yy_create_buffer
+#endif
+
+#ifdef yy_delete_buffer
+#define cmExpr_yy_delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer cmExpr_yy_delete_buffer
+#endif
+
+#ifdef yy_scan_buffer
+#define cmExpr_yy_scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer cmExpr_yy_scan_buffer
+#endif
+
+#ifdef yy_scan_string
+#define cmExpr_yy_scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string cmExpr_yy_scan_string
+#endif
+
+#ifdef yy_scan_bytes
+#define cmExpr_yy_scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes cmExpr_yy_scan_bytes
+#endif
+
+#ifdef yy_init_buffer
+#define cmExpr_yy_init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer cmExpr_yy_init_buffer
+#endif
+
+#ifdef yy_flush_buffer
+#define cmExpr_yy_flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer cmExpr_yy_flush_buffer
+#endif
+
+#ifdef yy_load_buffer_state
+#define cmExpr_yy_load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state cmExpr_yy_load_buffer_state
+#endif
+
+#ifdef yy_switch_to_buffer
+#define cmExpr_yy_switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer cmExpr_yy_switch_to_buffer
+#endif
+
+#ifdef yypush_buffer_state
+#define cmExpr_yypush_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state cmExpr_yypush_buffer_state
+#endif
+
+#ifdef yypop_buffer_state
+#define cmExpr_yypop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state cmExpr_yypop_buffer_state
+#endif
+
+#ifdef yyensure_buffer_stack
+#define cmExpr_yyensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack cmExpr_yyensure_buffer_stack
+#endif
+
+#ifdef yylex
+#define cmExpr_yylex_ALREADY_DEFINED
+#else
+#define yylex cmExpr_yylex
+#endif
+
+#ifdef yyrestart
+#define cmExpr_yyrestart_ALREADY_DEFINED
+#else
+#define yyrestart cmExpr_yyrestart
+#endif
+
+#ifdef yylex_init
+#define cmExpr_yylex_init_ALREADY_DEFINED
+#else
+#define yylex_init cmExpr_yylex_init
+#endif
+
+#ifdef yylex_init_extra
+#define cmExpr_yylex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra cmExpr_yylex_init_extra
+#endif
+
+#ifdef yylex_destroy
+#define cmExpr_yylex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy cmExpr_yylex_destroy
+#endif
+
+#ifdef yyget_debug
+#define cmExpr_yyget_debug_ALREADY_DEFINED
+#else
+#define yyget_debug cmExpr_yyget_debug
+#endif
+
+#ifdef yyset_debug
+#define cmExpr_yyset_debug_ALREADY_DEFINED
+#else
+#define yyset_debug cmExpr_yyset_debug
+#endif
+
+#ifdef yyget_extra
+#define cmExpr_yyget_extra_ALREADY_DEFINED
+#else
+#define yyget_extra cmExpr_yyget_extra
+#endif
+
+#ifdef yyset_extra
+#define cmExpr_yyset_extra_ALREADY_DEFINED
+#else
+#define yyset_extra cmExpr_yyset_extra
+#endif
+
+#ifdef yyget_in
+#define cmExpr_yyget_in_ALREADY_DEFINED
+#else
+#define yyget_in cmExpr_yyget_in
+#endif
+
+#ifdef yyset_in
+#define cmExpr_yyset_in_ALREADY_DEFINED
+#else
+#define yyset_in cmExpr_yyset_in
+#endif
+
+#ifdef yyget_out
+#define cmExpr_yyget_out_ALREADY_DEFINED
+#else
+#define yyget_out cmExpr_yyget_out
+#endif
+
+#ifdef yyset_out
+#define cmExpr_yyset_out_ALREADY_DEFINED
+#else
+#define yyset_out cmExpr_yyset_out
+#endif
+
+#ifdef yyget_leng
+#define cmExpr_yyget_leng_ALREADY_DEFINED
+#else
+#define yyget_leng cmExpr_yyget_leng
+#endif
+
+#ifdef yyget_text
+#define cmExpr_yyget_text_ALREADY_DEFINED
+#else
+#define yyget_text cmExpr_yyget_text
+#endif
+
+#ifdef yyget_lineno
+#define cmExpr_yyget_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno cmExpr_yyget_lineno
+#endif
+
+#ifdef yyset_lineno
+#define cmExpr_yyset_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno cmExpr_yyset_lineno
+#endif
+
+#ifdef yyget_column
+#define cmExpr_yyget_column_ALREADY_DEFINED
+#else
+#define yyget_column cmExpr_yyget_column
+#endif
+
+#ifdef yyset_column
+#define cmExpr_yyset_column_ALREADY_DEFINED
+#else
+#define yyset_column cmExpr_yyset_column
+#endif
+
+#ifdef yywrap
+#define cmExpr_yywrap_ALREADY_DEFINED
+#else
+#define yywrap cmExpr_yywrap
+#endif
+
+#ifdef yyalloc
+#define cmExpr_yyalloc_ALREADY_DEFINED
+#else
+#define yyalloc cmExpr_yyalloc
+#endif
+
+#ifdef yyrealloc
+#define cmExpr_yyrealloc_ALREADY_DEFINED
+#else
+#define yyrealloc cmExpr_yyrealloc
+#endif
+
+#ifdef yyfree
+#define cmExpr_yyfree_ALREADY_DEFINED
+#else
+#define yyfree cmExpr_yyfree
+#endif
+
/* First, we deal with platform-specific or compiler-specific issues. */
/* begin standard C headers. */
@@ -86,10 +293,16 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
+#ifndef SIZE_MAX
+#define SIZE_MAX (~(size_t)0)
+#endif
+
#endif /* ! C99 */
#endif /* ! FLEXINT_H */
+/* begin standard C++ headers. */
+
/* TODO: this is always defined, so inline it */
#define yyconst const
@@ -102,12 +315,10 @@ typedef unsigned int flex_uint32_t;
/* Returned upon end-of-file. */
#define YY_NULL 0
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index. If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
+/* Promotes a possibly negative, possibly signed char to an
+ * integer in range [0..255] for use as an array index.
*/
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+#define YY_SC_TO_UI(c) ((YY_CHAR) (c))
/* An opaque pointer. */
#ifndef YY_TYPEDEF_YY_SCANNER_T
@@ -131,20 +342,16 @@ typedef void* yyscan_t;
* definition of BEGIN.
*/
#define BEGIN yyg->yy_start = 1 + 2 *
-
/* Translate the current start state into a value that can be later handed
* to BEGIN to return to the state. The YYSTATE alias is for lex
* compatibility.
*/
#define YY_START ((yyg->yy_start - 1) / 2)
#define YYSTATE YY_START
-
/* Action number for EOF rule of a given start state. */
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE cmExpr_yyrestart(yyin ,yyscanner )
-
+#define YY_NEW_FILE yyrestart( yyin , yyscanner )
#define YY_END_OF_BUFFER_CHAR 0
/* Size of default input buffer. */
@@ -194,7 +401,6 @@ typedef size_t yy_size_t;
YY_DO_BEFORE_ACTION; /* set up yytext again */ \
} \
while ( 0 )
-
#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
#ifndef YY_STRUCT_YY_BUFFER_STATE
@@ -254,7 +460,7 @@ struct yy_buffer_state
* possible backing-up.
*
* When we actually see the EOF, we change the status to "new"
- * (via cmExpr_yyrestart()), so that the user can continue scanning by
+ * (via yyrestart()), so that the user can continue scanning by
* just pointing yyin at a new input file.
*/
#define YY_BUFFER_EOF_PENDING 2
@@ -271,73 +477,67 @@ struct yy_buffer_state
#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
: NULL)
-
/* Same as previous macro, but useful when we know that the buffer stack is not
* NULL or when we need an lvalue. For internal use only.
*/
#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
-void cmExpr_yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void cmExpr_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmExpr_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void cmExpr_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmExpr_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmExpr_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void cmExpr_yypop_buffer_state (yyscan_t yyscanner );
-
-static void cmExpr_yyensure_buffer_stack (yyscan_t yyscanner );
-static void cmExpr_yy_load_buffer_state (yyscan_t yyscanner );
-static void cmExpr_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
-
-#define YY_FLUSH_BUFFER cmExpr_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+void yyrestart ( FILE *input_file , yyscan_t yyscanner );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
+void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+void yypop_buffer_state ( yyscan_t yyscanner );
-YY_BUFFER_STATE cmExpr_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmExpr_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmExpr_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+static void yyensure_buffer_stack ( yyscan_t yyscanner );
+static void yy_load_buffer_state ( yyscan_t yyscanner );
+static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner );
+#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner)
-void *cmExpr_yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *cmExpr_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void cmExpr_yyfree (void * ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
-#define yy_new_buffer cmExpr_yy_create_buffer
+void *yyalloc ( yy_size_t , yyscan_t yyscanner );
+void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
+void yyfree ( void * , yyscan_t yyscanner );
+#define yy_new_buffer yy_create_buffer
#define yy_set_interactive(is_interactive) \
{ \
if ( ! YY_CURRENT_BUFFER ){ \
- cmExpr_yyensure_buffer_stack (yyscanner); \
+ yyensure_buffer_stack (yyscanner); \
YY_CURRENT_BUFFER_LVALUE = \
- cmExpr_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
} \
YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
}
-
#define yy_set_bol(at_bol) \
{ \
if ( ! YY_CURRENT_BUFFER ){\
- cmExpr_yyensure_buffer_stack (yyscanner); \
+ yyensure_buffer_stack (yyscanner); \
YY_CURRENT_BUFFER_LVALUE = \
- cmExpr_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
} \
YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
}
-
#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
/* Begin user sect3 */
#define cmExpr_yywrap(yyscanner) (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
-
-typedef unsigned char YY_CHAR;
+typedef flex_uint8_t YY_CHAR;
typedef int yy_state_type;
#define yytext_ptr yytext_r
-static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
-static int yy_get_next_buffer (yyscan_t yyscanner );
-static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
+static yy_state_type yy_get_previous_state ( yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans ( yy_state_type current_state , yyscan_t yyscanner);
+static int yy_get_next_buffer ( yyscan_t yyscanner );
+static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner );
/* Done after the current pattern has been matched and before the
* corresponding action - sets up yytext.
@@ -348,9 +548,8 @@ static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
yyg->yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 15
-#define YY_END_OF_BUFFER 16
+#define YY_NUM_RULES 18
+#define YY_END_OF_BUFFER 19
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -358,29 +557,29 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[23] =
+static const flex_int16_t yy_accept[29] =
{ 0,
- 0, 0, 16, 15, 6, 8, 13, 14, 4, 2,
- 3, 5, 1, 15, 15, 9, 7, 10, 1, 11,
- 12, 0
+ 0, 0, 19, 17, 1, 18, 8, 10, 15, 16,
+ 6, 4, 5, 7, 2, 2, 17, 17, 11, 9,
+ 12, 2, 0, 13, 14, 3, 3, 0
} ;
-static yyconst YY_CHAR yy_ec[256] =
+static const YY_CHAR yy_ec[256] =
{ 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 1, 1, 1, 4, 5, 1, 6,
+ 7, 8, 9, 1, 10, 1, 11, 12, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 1, 1, 14,
+ 1, 15, 1, 1, 16, 16, 16, 16, 16, 16,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 2, 3, 1, 4,
- 5, 6, 7, 1, 8, 1, 9, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 1, 1, 11,
- 1, 12, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 13, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 17, 1, 1,
+ 1, 1, 1, 18, 1, 1, 16, 16, 16, 16,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 14, 1, 15, 1, 1, 1, 1,
+ 16, 16, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 17,
+ 1, 1, 1, 19, 1, 20, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -397,40 +596,46 @@ static yyconst YY_CHAR yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst YY_CHAR yy_meta[16] =
+static const YY_CHAR yy_meta[21] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1
+ 1, 2, 2, 1, 1, 3, 4, 1, 1, 1
} ;
-static yyconst flex_uint16_t yy_base[23] =
+static const flex_int16_t yy_base[32] =
{ 0,
- 0, 0, 20, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 9, 7, 5, 21, 21, 21, 6, 21,
- 21, 21
+ 0, 0, 34, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 16, 9, 18, 11, 35, 35,
+ 35, 11, 0, 35, 35, 0, 0, 35, 23, 26,
+ 28
} ;
-static yyconst flex_int16_t yy_def[23] =
+static const flex_int16_t yy_def[32] =
{ 0,
- 22, 1, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 0
+ 28, 1, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 29, 28, 28, 28, 28, 28,
+ 28, 28, 30, 28, 28, 31, 31, 0, 28, 28,
+ 28
} ;
-static yyconst flex_uint16_t yy_nxt[37] =
+static const flex_int16_t yy_nxt[56] =
{ 0,
4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 21, 20, 19, 22,
- 3, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22
+ 14, 15, 16, 17, 18, 4, 4, 19, 20, 21,
+ 22, 22, 22, 22, 22, 25, 22, 26, 26, 27,
+ 27, 24, 23, 28, 3, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28
} ;
-static yyconst flex_int16_t yy_chk[37] =
+static const flex_int16_t yy_chk[56] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 19, 15, 14, 13, 3,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 16, 16, 22, 22, 29, 18, 29, 30, 30, 31,
+ 31, 17, 15, 3, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28
} ;
/* The intent behind this definition is that it'll catch
@@ -440,8 +645,6 @@ static yyconst flex_int16_t yy_chk[37] =
#define yymore() yymore_used_but_not_detected
#define YY_MORE_ADJ 0
#define YY_RESTORE_YY_MORE_OFFSET
-#line 1 "cmExprLexer.in.l"
-#line 2 "cmExprLexer.in.l"
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
/*
@@ -450,30 +653,32 @@ This file must be translated to C++ and modified to build everywhere.
Run flex >= 2.6 like this:
- flex --nounistd -DFLEXINT_H --prefix=cmExpr_yy --header-file=cmExprLexer.h -ocmExprLexer.cxx cmExprLexer.in.l
+ flex --nounistd -DFLEXINT_H --noline --header-file=cmExprLexer.h -ocmExprLexer.cxx cmExprLexer.in.l
Modify cmExprLexer.cxx:
- - remove trailing whitespace: sed -i 's/\s*$//' cmExprLexer.h cmExprLexer.cxx
- - remove blank lines at end of file
- - #include "cmStandardLexer.h" at the top
- - add cast in cmExpr_yy_scan_bytes for loop condition of _yybytes_len to size_t
+ - remove trailing whitespace: sed -i 's/\s*$//' cmExprLexer.h cmExprLexer.cxx
+ - remove blank lines at end of file: sed -i '${/^$/d;}' cmExprLexer.h cmExprLexer.cxx
+ - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmExprLexer.cxx
*/
/* IWYU pragma: no_forward_declare yyguts_t */
+#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+
#include "cmExprParserHelper.h"
/* Replace the lexer input function. */
#undef YY_INPUT
#define YY_INPUT(buf, result, max_size) \
- { result = yyextra->LexInput(buf, max_size); }
+ do { result = yyextra->LexInput(buf, max_size); } while (0)
/* Include the set of tokens from the parser. */
#include "cmExprParserTokens.h"
+#include <string>
+
/*--------------------------------------------------------------------------*/
-#line 476 "cmExprLexer.cxx"
#define INITIAL 0
@@ -515,44 +720,44 @@ struct yyguts_t
}; /* end struct yyguts_t */
-static int yy_init_globals (yyscan_t yyscanner );
+static int yy_init_globals ( yyscan_t yyscanner );
-int cmExpr_yylex_init (yyscan_t* scanner);
+int yylex_init (yyscan_t* scanner);
-int cmExpr_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
-int cmExpr_yylex_destroy (yyscan_t yyscanner );
+int yylex_destroy ( yyscan_t yyscanner );
-int cmExpr_yyget_debug (yyscan_t yyscanner );
+int yyget_debug ( yyscan_t yyscanner );
-void cmExpr_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+void yyset_debug ( int debug_flag , yyscan_t yyscanner );
-YY_EXTRA_TYPE cmExpr_yyget_extra (yyscan_t yyscanner );
+YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
-void cmExpr_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
-FILE *cmExpr_yyget_in (yyscan_t yyscanner );
+FILE *yyget_in ( yyscan_t yyscanner );
-void cmExpr_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
+void yyset_in ( FILE * _in_str , yyscan_t yyscanner );
-FILE *cmExpr_yyget_out (yyscan_t yyscanner );
+FILE *yyget_out ( yyscan_t yyscanner );
-void cmExpr_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
+void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
- int cmExpr_yyget_leng (yyscan_t yyscanner );
+ int yyget_leng ( yyscan_t yyscanner );
-char *cmExpr_yyget_text (yyscan_t yyscanner );
+char *yyget_text ( yyscan_t yyscanner );
-int cmExpr_yyget_lineno (yyscan_t yyscanner );
+int yyget_lineno ( yyscan_t yyscanner );
-void cmExpr_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+void yyset_lineno ( int _line_number , yyscan_t yyscanner );
-int cmExpr_yyget_column (yyscan_t yyscanner );
+int yyget_column ( yyscan_t yyscanner );
-void cmExpr_yyset_column (int _column_no ,yyscan_t yyscanner );
+void yyset_column ( int _column_no , yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -560,32 +765,31 @@ void cmExpr_yyset_column (int _column_no ,yyscan_t yyscanner );
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
-extern "C" int cmExpr_yywrap (yyscan_t yyscanner );
+extern "C" int yywrap ( yyscan_t yyscanner );
#else
-extern int cmExpr_yywrap (yyscan_t yyscanner );
+extern int yywrap ( yyscan_t yyscanner );
#endif
#endif
#ifndef YY_NO_UNPUT
- static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner);
+ static void yyunput ( int c, char *buf_ptr , yyscan_t yyscanner);
#endif
#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
#endif
#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
#endif
#ifndef YY_NO_INPUT
-
#ifdef __cplusplus
-static int yyinput (yyscan_t yyscanner );
+static int yyinput ( yyscan_t yyscanner );
#else
-static int input (yyscan_t yyscanner );
+static int input ( yyscan_t yyscanner );
#endif
#endif
@@ -616,7 +820,7 @@ static int input (yyscan_t yyscanner );
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
- size_t n; \
+ int n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@@ -629,7 +833,7 @@ static int input (yyscan_t yyscanner );
else \
{ \
errno=0; \
- while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \
{ \
if( errno != EINTR) \
{ \
@@ -670,9 +874,9 @@ static int input (yyscan_t yyscanner );
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
-extern int cmExpr_yylex (yyscan_t yyscanner);
+extern int yylex (yyscan_t yyscanner);
-#define YY_DECL int cmExpr_yylex (yyscan_t yyscanner)
+#define YY_DECL int yylex (yyscan_t yyscanner)
#endif /* !YY_DECL */
/* Code executed at the beginning of each rule, after yytext and yyleng
@@ -717,19 +921,15 @@ YY_DECL
yyout = stdout;
if ( ! YY_CURRENT_BUFFER ) {
- cmExpr_yyensure_buffer_stack (yyscanner);
+ yyensure_buffer_stack (yyscanner);
YY_CURRENT_BUFFER_LVALUE =
- cmExpr_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner);
}
- cmExpr_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
}
{
-#line 39 "cmExprLexer.in.l"
-
-
-#line 732 "cmExprLexer.cxx"
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
@@ -756,13 +956,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 23 )
- yy_c = yy_meta[(unsigned int) yy_c];
+ if ( yy_current_state >= 29 )
+ yy_c = yy_meta[yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
++yy_cp;
}
- while ( yy_base[yy_current_state] != 21 );
+ while ( yy_base[yy_current_state] != 35 );
yy_find_action:
yy_act = yy_accept[yy_current_state];
@@ -788,80 +988,76 @@ do_action: /* This label is used only to access EOF actions. */
case 1:
YY_RULE_SETUP
-#line 41 "cmExprLexer.in.l"
-{ yylvalp->Number = atoi(yytext); return exp_NUMBER; }
+{}
YY_BREAK
case 2:
YY_RULE_SETUP
-#line 43 "cmExprLexer.in.l"
-{ return exp_PLUS; }
+{ yylvalp->Number = std::stoll(yytext, nullptr, 10); return exp_NUMBER; }
YY_BREAK
case 3:
YY_RULE_SETUP
-#line 44 "cmExprLexer.in.l"
-{ return exp_MINUS; }
+{ yylvalp->Number = std::stoll(yytext, nullptr, 16); return exp_NUMBER; }
YY_BREAK
case 4:
YY_RULE_SETUP
-#line 45 "cmExprLexer.in.l"
-{ return exp_TIMES; }
+{ return exp_PLUS; }
YY_BREAK
case 5:
YY_RULE_SETUP
-#line 46 "cmExprLexer.in.l"
-{ return exp_DIVIDE; }
+{ return exp_MINUS; }
YY_BREAK
case 6:
YY_RULE_SETUP
-#line 47 "cmExprLexer.in.l"
-{ return exp_MOD; }
+{ return exp_TIMES; }
YY_BREAK
case 7:
YY_RULE_SETUP
-#line 48 "cmExprLexer.in.l"
-{ return exp_OR; }
+{ return exp_DIVIDE; }
YY_BREAK
case 8:
YY_RULE_SETUP
-#line 49 "cmExprLexer.in.l"
-{ return exp_AND; }
+{ return exp_MOD; }
YY_BREAK
case 9:
YY_RULE_SETUP
-#line 50 "cmExprLexer.in.l"
-{ return exp_XOR; }
+{ return exp_OR; }
YY_BREAK
case 10:
YY_RULE_SETUP
-#line 51 "cmExprLexer.in.l"
-{ return exp_NOT; }
+{ return exp_AND; }
YY_BREAK
case 11:
YY_RULE_SETUP
-#line 52 "cmExprLexer.in.l"
-{ return exp_SHIFTLEFT; }
+{ return exp_XOR; }
YY_BREAK
case 12:
YY_RULE_SETUP
-#line 53 "cmExprLexer.in.l"
-{ return exp_SHIFTRIGHT; }
+{ return exp_NOT; }
YY_BREAK
case 13:
YY_RULE_SETUP
-#line 54 "cmExprLexer.in.l"
-{ return exp_OPENPARENT; }
+{ return exp_SHIFTLEFT; }
YY_BREAK
case 14:
YY_RULE_SETUP
-#line 55 "cmExprLexer.in.l"
-{ return exp_CLOSEPARENT; }
+{ return exp_SHIFTRIGHT; }
YY_BREAK
case 15:
YY_RULE_SETUP
-#line 57 "cmExprLexer.in.l"
+{ return exp_OPENPARENT; }
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+{ return exp_CLOSEPARENT; }
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+{ yyextra->UnexpectedChar(yytext[0]); }
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
ECHO;
YY_BREAK
-#line 864 "cmExprLexer.cxx"
case YY_STATE_EOF(INITIAL):
yyterminate();
@@ -879,7 +1075,7 @@ case YY_STATE_EOF(INITIAL):
/* We're scanning a new file or input source. It's
* possible that this happened because the user
* just pointed yyin at a new source and called
- * cmExpr_yylex(). If so, then we have to assure
+ * yylex(). If so, then we have to assure
* consistency between YY_CURRENT_BUFFER and our
* globals. Here is the right place to do so, because
* this is the first action (other than possibly a
@@ -939,7 +1135,7 @@ case YY_STATE_EOF(INITIAL):
{
yyg->yy_did_buffer_switch_on_eof = 0;
- if ( cmExpr_yywrap(yyscanner ) )
+ if ( yywrap( yyscanner ) )
{
/* Note: because we've taken care in
* yy_get_next_buffer() to have set up
@@ -993,7 +1189,7 @@ case YY_STATE_EOF(INITIAL):
} /* end of action switch */
} /* end of scanning one token */
} /* end of user's declarations */
-} /* end of cmExpr_yylex */
+} /* end of yylex */
/* yy_get_next_buffer - try to read in a new buffer
*
@@ -1007,7 +1203,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
char *source = yyg->yytext_ptr;
- yy_size_t number_to_move, i;
+ int number_to_move, i;
int ret_val;
if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
@@ -1036,7 +1232,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
/* Try to read more data. */
/* First move last chars to start of buffer. */
- number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1);
for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++);
@@ -1072,7 +1268,8 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
b->yy_ch_buf = (char *)
/* Include room in for 2 EOB chars. */
- cmExpr_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+ yyrealloc( (void *) b->yy_ch_buf,
+ (yy_size_t) (b->yy_buf_size + 2) , yyscanner );
}
else
/* Can't grow it, we don't own it. */
@@ -1104,7 +1301,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ( number_to_move == YY_MORE_ADJ )
{
ret_val = EOB_ACT_END_OF_FILE;
- cmExpr_yyrestart(yyin ,yyscanner);
+ yyrestart( yyin , yyscanner);
}
else
@@ -1118,12 +1315,15 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
ret_val = EOB_ACT_CONTINUE_SCAN;
- if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
/* Extend the array by 50%, plus the number we really need. */
int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) cmExpr_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
+ (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner );
if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ /* "- 2" to take care of EOB's */
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
}
yyg->yy_n_chars += number_to_move;
@@ -1156,10 +1356,10 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 23 )
- yy_c = yy_meta[(unsigned int) yy_c];
+ if ( yy_current_state >= 29 )
+ yy_c = yy_meta[yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
}
return yy_current_state;
@@ -1185,11 +1385,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 23 )
- yy_c = yy_meta[(unsigned int) yy_c];
+ if ( yy_current_state >= 29 )
+ yy_c = yy_meta[yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
- yy_is_jam = (yy_current_state == 22);
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+ yy_is_jam = (yy_current_state == 28);
(void)yyg;
return yy_is_jam ? 0 : yy_current_state;
@@ -1262,7 +1462,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{ /* need more input */
- int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+ int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr);
++yyg->yy_c_buf_p;
switch ( yy_get_next_buffer( yyscanner ) )
@@ -1279,13 +1479,13 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
*/
/* Reset buffer status. */
- cmExpr_yyrestart(yyin ,yyscanner);
+ yyrestart( yyin , yyscanner);
/*FALLTHROUGH*/
case EOB_ACT_END_OF_FILE:
{
- if ( cmExpr_yywrap(yyscanner ) )
+ if ( yywrap( yyscanner ) )
return 0;
if ( ! yyg->yy_did_buffer_switch_on_eof )
@@ -1317,34 +1517,34 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @note This function does not reset the start condition to @c INITIAL .
*/
- void cmExpr_yyrestart (FILE * input_file , yyscan_t yyscanner)
+ void yyrestart (FILE * input_file , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if ( ! YY_CURRENT_BUFFER ){
- cmExpr_yyensure_buffer_stack (yyscanner);
+ yyensure_buffer_stack (yyscanner);
YY_CURRENT_BUFFER_LVALUE =
- cmExpr_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner);
}
- cmExpr_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
- cmExpr_yy_load_buffer_state(yyscanner );
+ yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner);
+ yy_load_buffer_state( yyscanner );
}
/** Switch to a different input buffer.
* @param new_buffer The new input buffer.
* @param yyscanner The scanner object.
*/
- void cmExpr_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* TODO. We should be able to replace this entire function body
* with
- * cmExpr_yypop_buffer_state();
- * cmExpr_yypush_buffer_state(new_buffer);
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
*/
- cmExpr_yyensure_buffer_stack (yyscanner);
+ yyensure_buffer_stack (yyscanner);
if ( YY_CURRENT_BUFFER == new_buffer )
return;
@@ -1357,17 +1557,17 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
}
YY_CURRENT_BUFFER_LVALUE = new_buffer;
- cmExpr_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
/* We don't actually know whether we did this switch during
- * EOF (cmExpr_yywrap()) processing, but the only time this flag
- * is looked at is after cmExpr_yywrap() is called, so it's safe
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
* to go ahead and always set it.
*/
yyg->yy_did_buffer_switch_on_eof = 1;
}
-static void cmExpr_yy_load_buffer_state (yyscan_t yyscanner)
+static void yy_load_buffer_state (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
@@ -1382,35 +1582,35 @@ static void cmExpr_yy_load_buffer_state (yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @return the allocated buffer state.
*/
- YY_BUFFER_STATE cmExpr_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
- b = (YY_BUFFER_STATE) cmExpr_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner );
if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmExpr_yy_create_buffer()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
- b->yy_buf_size = (yy_size_t)size;
+ b->yy_buf_size = size;
/* yy_ch_buf has to be 2 characters longer than the size given because
* we need to put in 2 end-of-buffer characters.
*/
- b->yy_ch_buf = (char *) cmExpr_yyalloc(b->yy_buf_size + 2 ,yyscanner );
+ b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner );
if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmExpr_yy_create_buffer()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
b->yy_is_our_buffer = 1;
- cmExpr_yy_init_buffer(b,file ,yyscanner);
+ yy_init_buffer( b, file , yyscanner);
return b;
}
/** Destroy the buffer.
- * @param b a buffer created with cmExpr_yy_create_buffer()
+ * @param b a buffer created with yy_create_buffer()
* @param yyscanner The scanner object.
*/
- void cmExpr_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+ void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -1421,28 +1621,28 @@ static void cmExpr_yy_load_buffer_state (yyscan_t yyscanner)
YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
if ( b->yy_is_our_buffer )
- cmExpr_yyfree((void *) b->yy_ch_buf ,yyscanner );
+ yyfree( (void *) b->yy_ch_buf , yyscanner );
- cmExpr_yyfree((void *) b ,yyscanner );
+ yyfree( (void *) b , yyscanner );
}
/* Initializes or reinitializes a buffer.
* This function is sometimes called more than once on the same buffer,
- * such as during a cmExpr_yyrestart() or at EOF.
+ * such as during a yyrestart() or at EOF.
*/
- static void cmExpr_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
{
int oerrno = errno;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- cmExpr_yy_flush_buffer(b ,yyscanner);
+ yy_flush_buffer( b , yyscanner);
b->yy_input_file = file;
b->yy_fill_buffer = 1;
- /* If b is the current buffer, then cmExpr_yy_init_buffer was _probably_
- * called from cmExpr_yyrestart() or through yy_get_next_buffer.
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
* In that case, we don't want to reset the lineno or column.
*/
if (b != YY_CURRENT_BUFFER){
@@ -1459,7 +1659,7 @@ static void cmExpr_yy_load_buffer_state (yyscan_t yyscanner)
* @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
* @param yyscanner The scanner object.
*/
- void cmExpr_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+ void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if ( ! b )
@@ -1480,7 +1680,7 @@ static void cmExpr_yy_load_buffer_state (yyscan_t yyscanner)
b->yy_buffer_status = YY_BUFFER_NEW;
if ( b == YY_CURRENT_BUFFER )
- cmExpr_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
}
/** Pushes the new state onto the stack. The new state becomes
@@ -1489,15 +1689,15 @@ static void cmExpr_yy_load_buffer_state (yyscan_t yyscanner)
* @param new_buffer The new state.
* @param yyscanner The scanner object.
*/
-void cmExpr_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (new_buffer == NULL)
return;
- cmExpr_yyensure_buffer_stack(yyscanner);
+ yyensure_buffer_stack(yyscanner);
- /* This block is copied from cmExpr_yy_switch_to_buffer. */
+ /* This block is copied from yy_switch_to_buffer. */
if ( YY_CURRENT_BUFFER )
{
/* Flush out information for old buffer. */
@@ -1511,8 +1711,8 @@ void cmExpr_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner
yyg->yy_buffer_stack_top++;
YY_CURRENT_BUFFER_LVALUE = new_buffer;
- /* copied from cmExpr_yy_switch_to_buffer. */
- cmExpr_yy_load_buffer_state(yyscanner );
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state( yyscanner );
yyg->yy_did_buffer_switch_on_eof = 1;
}
@@ -1520,19 +1720,19 @@ void cmExpr_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner
* The next element becomes the new top.
* @param yyscanner The scanner object.
*/
-void cmExpr_yypop_buffer_state (yyscan_t yyscanner)
+void yypop_buffer_state (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (!YY_CURRENT_BUFFER)
return;
- cmExpr_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+ yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner);
YY_CURRENT_BUFFER_LVALUE = NULL;
if (yyg->yy_buffer_stack_top > 0)
--yyg->yy_buffer_stack_top;
if (YY_CURRENT_BUFFER) {
- cmExpr_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
yyg->yy_did_buffer_switch_on_eof = 1;
}
}
@@ -1540,9 +1740,9 @@ void cmExpr_yypop_buffer_state (yyscan_t yyscanner)
/* Allocates the stack if it does not exist.
* Guarantees space for at least one push.
*/
-static void cmExpr_yyensure_buffer_stack (yyscan_t yyscanner)
+static void yyensure_buffer_stack (yyscan_t yyscanner)
{
- int num_to_alloc;
+ yy_size_t num_to_alloc;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (!yyg->yy_buffer_stack) {
@@ -1552,11 +1752,11 @@ static void cmExpr_yyensure_buffer_stack (yyscan_t yyscanner)
* immediate realloc on the next call.
*/
num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmExpr_yyalloc
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
(num_to_alloc * sizeof(struct yy_buffer_state*)
, yyscanner);
if ( ! yyg->yy_buffer_stack )
- YY_FATAL_ERROR( "out of dynamic memory in cmExpr_yyensure_buffer_stack()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
@@ -1571,12 +1771,12 @@ static void cmExpr_yyensure_buffer_stack (yyscan_t yyscanner)
yy_size_t grow_size = 8 /* arbitrary grow size */;
num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmExpr_yyrealloc
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
(yyg->yy_buffer_stack,
num_to_alloc * sizeof(struct yy_buffer_state*)
, yyscanner);
if ( ! yyg->yy_buffer_stack )
- YY_FATAL_ERROR( "out of dynamic memory in cmExpr_yyensure_buffer_stack()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
/* zero only the new slots.*/
memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
@@ -1590,7 +1790,7 @@ static void cmExpr_yyensure_buffer_stack (yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
-YY_BUFFER_STATE cmExpr_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
@@ -1600,11 +1800,11 @@ YY_BUFFER_STATE cmExpr_yy_scan_buffer (char * base, yy_size_t size , yyscan_t
/* They forgot to leave room for the EOB's. */
return NULL;
- b = (YY_BUFFER_STATE) cmExpr_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner );
if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmExpr_yy_scan_buffer()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
- b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */
b->yy_buf_pos = b->yy_ch_buf = base;
b->yy_is_our_buffer = 0;
b->yy_input_file = NULL;
@@ -1614,53 +1814,53 @@ YY_BUFFER_STATE cmExpr_yy_scan_buffer (char * base, yy_size_t size , yyscan_t
b->yy_fill_buffer = 0;
b->yy_buffer_status = YY_BUFFER_NEW;
- cmExpr_yy_switch_to_buffer(b ,yyscanner );
+ yy_switch_to_buffer( b , yyscanner );
return b;
}
-/** Setup the input buffer state to scan a string. The next call to cmExpr_yylex() will
+/** Setup the input buffer state to scan a string. The next call to yylex() will
* scan from a @e copy of @a str.
* @param yystr a NUL-terminated string to scan
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
* @note If you want to scan bytes that may contain NUL values, then use
- * cmExpr_yy_scan_bytes() instead.
+ * yy_scan_bytes() instead.
*/
-YY_BUFFER_STATE cmExpr_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner)
{
- return cmExpr_yy_scan_bytes(yystr,(int) strlen(yystr) ,yyscanner);
+ return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner);
}
-/** Setup the input buffer state to scan the given bytes. The next call to cmExpr_yylex() will
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
* scan from a @e copy of @a bytes.
* @param yybytes the byte buffer to scan
* @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
-YY_BUFFER_STATE cmExpr_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
char *buf;
yy_size_t n;
- yy_size_t i;
+ int i;
/* Get memory for full buffer, including space for trailing EOB's. */
- n = (yy_size_t) _yybytes_len + 2;
- buf = (char *) cmExpr_yyalloc(n ,yyscanner );
+ n = (yy_size_t) (_yybytes_len + 2);
+ buf = (char *) yyalloc( n , yyscanner );
if ( ! buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmExpr_yy_scan_bytes()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
- for ( i = 0; i < (size_t)_yybytes_len; ++i )
+ for ( i = 0; i < _yybytes_len; ++i )
buf[i] = yybytes[i];
buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
- b = cmExpr_yy_scan_buffer(buf,n ,yyscanner);
+ b = yy_scan_buffer( buf, n , yyscanner);
if ( ! b )
- YY_FATAL_ERROR( "bad buffer in cmExpr_yy_scan_bytes()" );
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
/* It's okay to grow etc. this buffer, and we should throw it
* away when we're done.
@@ -1674,11 +1874,11 @@ YY_BUFFER_STATE cmExpr_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len
#define YY_EXIT_FAILURE 2
#endif
-static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
- (void) fprintf( stderr, "%s\n", msg );
+ fprintf( stderr, "%s\n", msg );
exit( YY_EXIT_FAILURE );
}
@@ -1704,7 +1904,7 @@ static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
/** Get the user-defined data for this scanner.
* @param yyscanner The scanner object.
*/
-YY_EXTRA_TYPE cmExpr_yyget_extra (yyscan_t yyscanner)
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyextra;
@@ -1713,7 +1913,7 @@ YY_EXTRA_TYPE cmExpr_yyget_extra (yyscan_t yyscanner)
/** Get the current line number.
* @param yyscanner The scanner object.
*/
-int cmExpr_yyget_lineno (yyscan_t yyscanner)
+int yyget_lineno (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -1726,7 +1926,7 @@ int cmExpr_yyget_lineno (yyscan_t yyscanner)
/** Get the current column number.
* @param yyscanner The scanner object.
*/
-int cmExpr_yyget_column (yyscan_t yyscanner)
+int yyget_column (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -1739,7 +1939,7 @@ int cmExpr_yyget_column (yyscan_t yyscanner)
/** Get the input stream.
* @param yyscanner The scanner object.
*/
-FILE *cmExpr_yyget_in (yyscan_t yyscanner)
+FILE *yyget_in (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyin;
@@ -1748,7 +1948,7 @@ FILE *cmExpr_yyget_in (yyscan_t yyscanner)
/** Get the output stream.
* @param yyscanner The scanner object.
*/
-FILE *cmExpr_yyget_out (yyscan_t yyscanner)
+FILE *yyget_out (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyout;
@@ -1757,7 +1957,7 @@ FILE *cmExpr_yyget_out (yyscan_t yyscanner)
/** Get the length of the current token.
* @param yyscanner The scanner object.
*/
-int cmExpr_yyget_leng (yyscan_t yyscanner)
+int yyget_leng (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyleng;
@@ -1767,7 +1967,7 @@ int cmExpr_yyget_leng (yyscan_t yyscanner)
* @param yyscanner The scanner object.
*/
-char *cmExpr_yyget_text (yyscan_t yyscanner)
+char *yyget_text (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yytext;
@@ -1777,7 +1977,7 @@ char *cmExpr_yyget_text (yyscan_t yyscanner)
* @param user_defined The data to be associated with this scanner.
* @param yyscanner The scanner object.
*/
-void cmExpr_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
+void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyextra = user_defined ;
@@ -1787,13 +1987,13 @@ void cmExpr_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
* @param _line_number line number
* @param yyscanner The scanner object.
*/
-void cmExpr_yyset_lineno (int _line_number , yyscan_t yyscanner)
+void yyset_lineno (int _line_number , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* lineno is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
- YY_FATAL_ERROR( "cmExpr_yyset_lineno called with no buffer" );
+ YY_FATAL_ERROR( "yyset_lineno called with no buffer" );
yylineno = _line_number;
}
@@ -1802,13 +2002,13 @@ void cmExpr_yyset_lineno (int _line_number , yyscan_t yyscanner)
* @param _column_no column number
* @param yyscanner The scanner object.
*/
-void cmExpr_yyset_column (int _column_no , yyscan_t yyscanner)
+void yyset_column (int _column_no , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* column is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
- YY_FATAL_ERROR( "cmExpr_yyset_column called with no buffer" );
+ YY_FATAL_ERROR( "yyset_column called with no buffer" );
yycolumn = _column_no;
}
@@ -1817,27 +2017,27 @@ void cmExpr_yyset_column (int _column_no , yyscan_t yyscanner)
* input buffer.
* @param _in_str A readable stream.
* @param yyscanner The scanner object.
- * @see cmExpr_yy_switch_to_buffer
+ * @see yy_switch_to_buffer
*/
-void cmExpr_yyset_in (FILE * _in_str , yyscan_t yyscanner)
+void yyset_in (FILE * _in_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyin = _in_str ;
}
-void cmExpr_yyset_out (FILE * _out_str , yyscan_t yyscanner)
+void yyset_out (FILE * _out_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyout = _out_str ;
}
-int cmExpr_yyget_debug (yyscan_t yyscanner)
+int yyget_debug (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yy_flex_debug;
}
-void cmExpr_yyset_debug (int _bdebug , yyscan_t yyscanner)
+void yyset_debug (int _bdebug , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yy_flex_debug = _bdebug ;
@@ -1847,20 +2047,18 @@ void cmExpr_yyset_debug (int _bdebug , yyscan_t yyscanner)
/* User-visible API */
-/* cmExpr_yylex_init is special because it creates the scanner itself, so it is
+/* yylex_init is special because it creates the scanner itself, so it is
* the ONLY reentrant function that doesn't take the scanner as the last argument.
* That's why we explicitly handle the declaration, instead of using our macros.
*/
-
-int cmExpr_yylex_init(yyscan_t* ptr_yy_globals)
-
+int yylex_init(yyscan_t* ptr_yy_globals)
{
if (ptr_yy_globals == NULL){
errno = EINVAL;
return 1;
}
- *ptr_yy_globals = (yyscan_t) cmExpr_yyalloc ( sizeof( struct yyguts_t ), NULL );
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
if (*ptr_yy_globals == NULL){
errno = ENOMEM;
@@ -1873,27 +2071,25 @@ int cmExpr_yylex_init(yyscan_t* ptr_yy_globals)
return yy_init_globals ( *ptr_yy_globals );
}
-/* cmExpr_yylex_init_extra has the same functionality as cmExpr_yylex_init, but follows the
+/* yylex_init_extra has the same functionality as yylex_init, but follows the
* convention of taking the scanner as the last argument. Note however, that
* this is a *pointer* to a scanner, as it will be allocated by this call (and
* is the reason, too, why this function also must handle its own declaration).
- * The user defined value in the first argument will be available to cmExpr_yyalloc in
+ * The user defined value in the first argument will be available to yyalloc in
* the yyextra field.
*/
-
-int cmExpr_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
-
+int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals )
{
struct yyguts_t dummy_yyguts;
- cmExpr_yyset_extra (yy_user_defined, &dummy_yyguts);
+ yyset_extra (yy_user_defined, &dummy_yyguts);
if (ptr_yy_globals == NULL){
errno = EINVAL;
return 1;
}
- *ptr_yy_globals = (yyscan_t) cmExpr_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
if (*ptr_yy_globals == NULL){
errno = ENOMEM;
@@ -1904,7 +2100,7 @@ int cmExpr_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globa
yy_init_globals. Leave at 0x00 for releases. */
memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
- cmExpr_yyset_extra (yy_user_defined, *ptr_yy_globals);
+ yyset_extra (yy_user_defined, *ptr_yy_globals);
return yy_init_globals ( *ptr_yy_globals );
}
@@ -1913,7 +2109,7 @@ static int yy_init_globals (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* Initialization is the same as for the non-reentrant scanner.
- * This function is called from cmExpr_yylex_destroy(), so don't allocate here.
+ * This function is called from yylex_destroy(), so don't allocate here.
*/
yyg->yy_buffer_stack = NULL;
@@ -1937,37 +2133,37 @@ static int yy_init_globals (yyscan_t yyscanner)
#endif
/* For future reference: Set errno on error, since we are called by
- * cmExpr_yylex_init()
+ * yylex_init()
*/
return 0;
}
-/* cmExpr_yylex_destroy is for both reentrant and non-reentrant scanners. */
-int cmExpr_yylex_destroy (yyscan_t yyscanner)
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* Pop the buffer stack, destroying each element. */
while(YY_CURRENT_BUFFER){
- cmExpr_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+ yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner );
YY_CURRENT_BUFFER_LVALUE = NULL;
- cmExpr_yypop_buffer_state(yyscanner);
+ yypop_buffer_state(yyscanner);
}
/* Destroy the stack itself. */
- cmExpr_yyfree(yyg->yy_buffer_stack ,yyscanner);
+ yyfree(yyg->yy_buffer_stack , yyscanner);
yyg->yy_buffer_stack = NULL;
/* Destroy the start condition stack. */
- cmExpr_yyfree(yyg->yy_start_stack ,yyscanner );
+ yyfree( yyg->yy_start_stack , yyscanner );
yyg->yy_start_stack = NULL;
/* Reset the globals. This is important in a non-reentrant scanner so the next time
- * cmExpr_yylex() is called, initialization will occur. */
+ * yylex() is called, initialization will occur. */
yy_init_globals( yyscanner);
/* Destroy the main struct (reentrant only). */
- cmExpr_yyfree ( yyscanner , yyscanner );
+ yyfree ( yyscanner , yyscanner );
yyscanner = NULL;
return 0;
}
@@ -1977,7 +2173,7 @@ int cmExpr_yylex_destroy (yyscan_t yyscanner)
*/
#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
@@ -1989,7 +2185,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca
#endif
#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+static int yy_flex_strlen (const char * s , yyscan_t yyscanner)
{
int n;
for ( n = 0; s[n]; ++n )
@@ -1999,14 +2195,14 @@ static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
}
#endif
-void *cmExpr_yyalloc (yy_size_t size , yyscan_t yyscanner)
+void *yyalloc (yy_size_t size , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
return malloc(size);
}
-void *cmExpr_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
+void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
@@ -2021,13 +2217,15 @@ void *cmExpr_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
return realloc(ptr, size);
}
-void cmExpr_yyfree (void * ptr , yyscan_t yyscanner)
+void yyfree (void * ptr , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
- free( (char *) ptr ); /* see cmExpr_yyrealloc() for (char *) cast */
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
}
#define YYTABLES_NAME "yytables"
-#line 57 "cmExprLexer.in.l"
+/*--------------------------------------------------------------------------*/
+
+#endif /* __clang_analyzer__ */
diff --git a/Source/LexerParser/cmExprLexer.h b/Source/LexerParser/cmExprLexer.h
index 835a7a36a..b55ee92e5 100644
--- a/Source/LexerParser/cmExprLexer.h
+++ b/Source/LexerParser/cmExprLexer.h
@@ -2,10 +2,6 @@
#define cmExpr_yyHEADER_H 1
#define cmExpr_yyIN_HEADER 1
-#line 6 "cmExprLexer.h"
-
-#line 8 "cmExprLexer.h"
-
#define FLEXINT_H 1
#define YY_INT_ALIGNED short int
@@ -14,11 +10,221 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6
-#define YY_FLEX_SUBMINOR_VERSION 1
+#define YY_FLEX_SUBMINOR_VERSION 4
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
+#ifdef yy_create_buffer
+#define cmExpr_yy_create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer cmExpr_yy_create_buffer
+#endif
+
+#ifdef yy_delete_buffer
+#define cmExpr_yy_delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer cmExpr_yy_delete_buffer
+#endif
+
+#ifdef yy_scan_buffer
+#define cmExpr_yy_scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer cmExpr_yy_scan_buffer
+#endif
+
+#ifdef yy_scan_string
+#define cmExpr_yy_scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string cmExpr_yy_scan_string
+#endif
+
+#ifdef yy_scan_bytes
+#define cmExpr_yy_scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes cmExpr_yy_scan_bytes
+#endif
+
+#ifdef yy_init_buffer
+#define cmExpr_yy_init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer cmExpr_yy_init_buffer
+#endif
+
+#ifdef yy_flush_buffer
+#define cmExpr_yy_flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer cmExpr_yy_flush_buffer
+#endif
+
+#ifdef yy_load_buffer_state
+#define cmExpr_yy_load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state cmExpr_yy_load_buffer_state
+#endif
+
+#ifdef yy_switch_to_buffer
+#define cmExpr_yy_switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer cmExpr_yy_switch_to_buffer
+#endif
+
+#ifdef yypush_buffer_state
+#define cmExpr_yypush_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state cmExpr_yypush_buffer_state
+#endif
+
+#ifdef yypop_buffer_state
+#define cmExpr_yypop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state cmExpr_yypop_buffer_state
+#endif
+
+#ifdef yyensure_buffer_stack
+#define cmExpr_yyensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack cmExpr_yyensure_buffer_stack
+#endif
+
+#ifdef yylex
+#define cmExpr_yylex_ALREADY_DEFINED
+#else
+#define yylex cmExpr_yylex
+#endif
+
+#ifdef yyrestart
+#define cmExpr_yyrestart_ALREADY_DEFINED
+#else
+#define yyrestart cmExpr_yyrestart
+#endif
+
+#ifdef yylex_init
+#define cmExpr_yylex_init_ALREADY_DEFINED
+#else
+#define yylex_init cmExpr_yylex_init
+#endif
+
+#ifdef yylex_init_extra
+#define cmExpr_yylex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra cmExpr_yylex_init_extra
+#endif
+
+#ifdef yylex_destroy
+#define cmExpr_yylex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy cmExpr_yylex_destroy
+#endif
+
+#ifdef yyget_debug
+#define cmExpr_yyget_debug_ALREADY_DEFINED
+#else
+#define yyget_debug cmExpr_yyget_debug
+#endif
+
+#ifdef yyset_debug
+#define cmExpr_yyset_debug_ALREADY_DEFINED
+#else
+#define yyset_debug cmExpr_yyset_debug
+#endif
+
+#ifdef yyget_extra
+#define cmExpr_yyget_extra_ALREADY_DEFINED
+#else
+#define yyget_extra cmExpr_yyget_extra
+#endif
+
+#ifdef yyset_extra
+#define cmExpr_yyset_extra_ALREADY_DEFINED
+#else
+#define yyset_extra cmExpr_yyset_extra
+#endif
+
+#ifdef yyget_in
+#define cmExpr_yyget_in_ALREADY_DEFINED
+#else
+#define yyget_in cmExpr_yyget_in
+#endif
+
+#ifdef yyset_in
+#define cmExpr_yyset_in_ALREADY_DEFINED
+#else
+#define yyset_in cmExpr_yyset_in
+#endif
+
+#ifdef yyget_out
+#define cmExpr_yyget_out_ALREADY_DEFINED
+#else
+#define yyget_out cmExpr_yyget_out
+#endif
+
+#ifdef yyset_out
+#define cmExpr_yyset_out_ALREADY_DEFINED
+#else
+#define yyset_out cmExpr_yyset_out
+#endif
+
+#ifdef yyget_leng
+#define cmExpr_yyget_leng_ALREADY_DEFINED
+#else
+#define yyget_leng cmExpr_yyget_leng
+#endif
+
+#ifdef yyget_text
+#define cmExpr_yyget_text_ALREADY_DEFINED
+#else
+#define yyget_text cmExpr_yyget_text
+#endif
+
+#ifdef yyget_lineno
+#define cmExpr_yyget_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno cmExpr_yyget_lineno
+#endif
+
+#ifdef yyset_lineno
+#define cmExpr_yyset_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno cmExpr_yyset_lineno
+#endif
+
+#ifdef yyget_column
+#define cmExpr_yyget_column_ALREADY_DEFINED
+#else
+#define yyget_column cmExpr_yyget_column
+#endif
+
+#ifdef yyset_column
+#define cmExpr_yyset_column_ALREADY_DEFINED
+#else
+#define yyset_column cmExpr_yyset_column
+#endif
+
+#ifdef yywrap
+#define cmExpr_yywrap_ALREADY_DEFINED
+#else
+#define yywrap cmExpr_yywrap
+#endif
+
+#ifdef yyalloc
+#define cmExpr_yyalloc_ALREADY_DEFINED
+#else
+#define yyalloc cmExpr_yyalloc
+#endif
+
+#ifdef yyrealloc
+#define cmExpr_yyrealloc_ALREADY_DEFINED
+#else
+#define yyrealloc cmExpr_yyrealloc
+#endif
+
+#ifdef yyfree
+#define cmExpr_yyfree_ALREADY_DEFINED
+#else
+#define yyfree cmExpr_yyfree
+#endif
+
/* First, we deal with platform-specific or compiler-specific issues. */
/* begin standard C headers. */
@@ -89,10 +295,16 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
+#ifndef SIZE_MAX
+#define SIZE_MAX (~(size_t)0)
+#endif
+
#endif /* ! C99 */
#endif /* ! FLEXINT_H */
+/* begin standard C++ headers. */
+
/* TODO: this is always defined, so inline it */
#define yyconst const
@@ -193,21 +405,21 @@ struct yy_buffer_state
};
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-void cmExpr_yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void cmExpr_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmExpr_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void cmExpr_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmExpr_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmExpr_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void cmExpr_yypop_buffer_state (yyscan_t yyscanner );
+void yyrestart ( FILE *input_file , yyscan_t yyscanner );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
+void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+void yypop_buffer_state ( yyscan_t yyscanner );
-YY_BUFFER_STATE cmExpr_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmExpr_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmExpr_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
-void *cmExpr_yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *cmExpr_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void cmExpr_yyfree (void * ,yyscan_t yyscanner );
+void *yyalloc ( yy_size_t , yyscan_t yyscanner );
+void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
+void yyfree ( void * , yyscan_t yyscanner );
/* Begin user sect3 */
@@ -225,42 +437,42 @@ void cmExpr_yyfree (void * ,yyscan_t yyscanner );
#define YY_EXTRA_TYPE void *
#endif
-int cmExpr_yylex_init (yyscan_t* scanner);
+int yylex_init (yyscan_t* scanner);
-int cmExpr_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
-int cmExpr_yylex_destroy (yyscan_t yyscanner );
+int yylex_destroy ( yyscan_t yyscanner );
-int cmExpr_yyget_debug (yyscan_t yyscanner );
+int yyget_debug ( yyscan_t yyscanner );
-void cmExpr_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+void yyset_debug ( int debug_flag , yyscan_t yyscanner );
-YY_EXTRA_TYPE cmExpr_yyget_extra (yyscan_t yyscanner );
+YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
-void cmExpr_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
-FILE *cmExpr_yyget_in (yyscan_t yyscanner );
+FILE *yyget_in ( yyscan_t yyscanner );
-void cmExpr_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
+void yyset_in ( FILE * _in_str , yyscan_t yyscanner );
-FILE *cmExpr_yyget_out (yyscan_t yyscanner );
+FILE *yyget_out ( yyscan_t yyscanner );
-void cmExpr_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
+void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
- int cmExpr_yyget_leng (yyscan_t yyscanner );
+ int yyget_leng ( yyscan_t yyscanner );
-char *cmExpr_yyget_text (yyscan_t yyscanner );
+char *yyget_text ( yyscan_t yyscanner );
-int cmExpr_yyget_lineno (yyscan_t yyscanner );
+int yyget_lineno ( yyscan_t yyscanner );
-void cmExpr_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+void yyset_lineno ( int _line_number , yyscan_t yyscanner );
-int cmExpr_yyget_column (yyscan_t yyscanner );
+int yyget_column ( yyscan_t yyscanner );
-void cmExpr_yyset_column (int _column_no ,yyscan_t yyscanner );
+void yyset_column ( int _column_no , yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -268,18 +480,18 @@ void cmExpr_yyset_column (int _column_no ,yyscan_t yyscanner );
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
-extern "C" int cmExpr_yywrap (yyscan_t yyscanner );
+extern "C" int yywrap ( yyscan_t yyscanner );
#else
-extern int cmExpr_yywrap (yyscan_t yyscanner );
+extern int yywrap ( yyscan_t yyscanner );
#endif
#endif
#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
#endif
#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
#endif
#ifndef YY_NO_INPUT
@@ -307,9 +519,9 @@ static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
-extern int cmExpr_yylex (yyscan_t yyscanner);
+extern int yylex (yyscan_t yyscanner);
-#define YY_DECL int cmExpr_yylex (yyscan_t yyscanner)
+#define YY_DECL int yylex (yyscan_t yyscanner)
#endif /* !YY_DECL */
/* yy_get_previous_state - get the state just before the EOB char was reached */
@@ -326,9 +538,150 @@ extern int cmExpr_yylex (yyscan_t yyscanner);
#undef YY_DECL
#endif
-#line 57 "cmExprLexer.in.l"
-
+#ifndef cmExpr_yy_create_buffer_ALREADY_DEFINED
+#undef yy_create_buffer
+#endif
+#ifndef cmExpr_yy_delete_buffer_ALREADY_DEFINED
+#undef yy_delete_buffer
+#endif
+#ifndef cmExpr_yy_scan_buffer_ALREADY_DEFINED
+#undef yy_scan_buffer
+#endif
+#ifndef cmExpr_yy_scan_string_ALREADY_DEFINED
+#undef yy_scan_string
+#endif
+#ifndef cmExpr_yy_scan_bytes_ALREADY_DEFINED
+#undef yy_scan_bytes
+#endif
+#ifndef cmExpr_yy_init_buffer_ALREADY_DEFINED
+#undef yy_init_buffer
+#endif
+#ifndef cmExpr_yy_flush_buffer_ALREADY_DEFINED
+#undef yy_flush_buffer
+#endif
+#ifndef cmExpr_yy_load_buffer_state_ALREADY_DEFINED
+#undef yy_load_buffer_state
+#endif
+#ifndef cmExpr_yy_switch_to_buffer_ALREADY_DEFINED
+#undef yy_switch_to_buffer
+#endif
+#ifndef cmExpr_yypush_buffer_state_ALREADY_DEFINED
+#undef yypush_buffer_state
+#endif
+#ifndef cmExpr_yypop_buffer_state_ALREADY_DEFINED
+#undef yypop_buffer_state
+#endif
+#ifndef cmExpr_yyensure_buffer_stack_ALREADY_DEFINED
+#undef yyensure_buffer_stack
+#endif
+#ifndef cmExpr_yylex_ALREADY_DEFINED
+#undef yylex
+#endif
+#ifndef cmExpr_yyrestart_ALREADY_DEFINED
+#undef yyrestart
+#endif
+#ifndef cmExpr_yylex_init_ALREADY_DEFINED
+#undef yylex_init
+#endif
+#ifndef cmExpr_yylex_init_extra_ALREADY_DEFINED
+#undef yylex_init_extra
+#endif
+#ifndef cmExpr_yylex_destroy_ALREADY_DEFINED
+#undef yylex_destroy
+#endif
+#ifndef cmExpr_yyget_debug_ALREADY_DEFINED
+#undef yyget_debug
+#endif
+#ifndef cmExpr_yyset_debug_ALREADY_DEFINED
+#undef yyset_debug
+#endif
+#ifndef cmExpr_yyget_extra_ALREADY_DEFINED
+#undef yyget_extra
+#endif
+#ifndef cmExpr_yyset_extra_ALREADY_DEFINED
+#undef yyset_extra
+#endif
+#ifndef cmExpr_yyget_in_ALREADY_DEFINED
+#undef yyget_in
+#endif
+#ifndef cmExpr_yyset_in_ALREADY_DEFINED
+#undef yyset_in
+#endif
+#ifndef cmExpr_yyget_out_ALREADY_DEFINED
+#undef yyget_out
+#endif
+#ifndef cmExpr_yyset_out_ALREADY_DEFINED
+#undef yyset_out
+#endif
+#ifndef cmExpr_yyget_leng_ALREADY_DEFINED
+#undef yyget_leng
+#endif
+#ifndef cmExpr_yyget_text_ALREADY_DEFINED
+#undef yyget_text
+#endif
+#ifndef cmExpr_yyget_lineno_ALREADY_DEFINED
+#undef yyget_lineno
+#endif
+#ifndef cmExpr_yyset_lineno_ALREADY_DEFINED
+#undef yyset_lineno
+#endif
+#ifndef cmExpr_yyget_column_ALREADY_DEFINED
+#undef yyget_column
+#endif
+#ifndef cmExpr_yyset_column_ALREADY_DEFINED
+#undef yyset_column
+#endif
+#ifndef cmExpr_yywrap_ALREADY_DEFINED
+#undef yywrap
+#endif
+#ifndef cmExpr_yyget_lval_ALREADY_DEFINED
+#undef yyget_lval
+#endif
+#ifndef cmExpr_yyset_lval_ALREADY_DEFINED
+#undef yyset_lval
+#endif
+#ifndef cmExpr_yyget_lloc_ALREADY_DEFINED
+#undef yyget_lloc
+#endif
+#ifndef cmExpr_yyset_lloc_ALREADY_DEFINED
+#undef yyset_lloc
+#endif
+#ifndef cmExpr_yyalloc_ALREADY_DEFINED
+#undef yyalloc
+#endif
+#ifndef cmExpr_yyrealloc_ALREADY_DEFINED
+#undef yyrealloc
+#endif
+#ifndef cmExpr_yyfree_ALREADY_DEFINED
+#undef yyfree
+#endif
+#ifndef cmExpr_yytext_ALREADY_DEFINED
+#undef yytext
+#endif
+#ifndef cmExpr_yyleng_ALREADY_DEFINED
+#undef yyleng
+#endif
+#ifndef cmExpr_yyin_ALREADY_DEFINED
+#undef yyin
+#endif
+#ifndef cmExpr_yyout_ALREADY_DEFINED
+#undef yyout
+#endif
+#ifndef cmExpr_yy_flex_debug_ALREADY_DEFINED
+#undef yy_flex_debug
+#endif
+#ifndef cmExpr_yylineno_ALREADY_DEFINED
+#undef yylineno
+#endif
+#ifndef cmExpr_yytables_fload_ALREADY_DEFINED
+#undef yytables_fload
+#endif
+#ifndef cmExpr_yytables_destroy_ALREADY_DEFINED
+#undef yytables_destroy
+#endif
+#ifndef cmExpr_yyTABLES_NAME_ALREADY_DEFINED
+#undef yyTABLES_NAME
+#endif
-#line 333 "cmExprLexer.h"
#undef cmExpr_yyIN_HEADER
#endif /* cmExpr_yyHEADER_H */
diff --git a/Source/LexerParser/cmExprLexer.in.l b/Source/LexerParser/cmExprLexer.in.l
index 25ddba460..f8a422431 100644
--- a/Source/LexerParser/cmExprLexer.in.l
+++ b/Source/LexerParser/cmExprLexer.in.l
@@ -7,38 +7,45 @@ This file must be translated to C++ and modified to build everywhere.
Run flex >= 2.6 like this:
- flex --nounistd -DFLEXINT_H --prefix=cmExpr_yy --header-file=cmExprLexer.h -ocmExprLexer.cxx cmExprLexer.in.l
+ flex --nounistd -DFLEXINT_H --noline --header-file=cmExprLexer.h -ocmExprLexer.cxx cmExprLexer.in.l
Modify cmExprLexer.cxx:
- - remove trailing whitespace: sed -i 's/\s*$//' cmExprLexer.h cmExprLexer.cxx
- - remove blank lines at end of file
- - #include "cmStandardLexer.h" at the top
- - add cast in yy_scan_bytes for loop condition of _yybytes_len to size_t
+ - remove trailing whitespace: sed -i 's/\s*$//' cmExprLexer.h cmExprLexer.cxx
+ - remove blank lines at end of file: sed -i '${/^$/d;}' cmExprLexer.h cmExprLexer.cxx
+ - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmExprLexer.cxx
*/
/* IWYU pragma: no_forward_declare yyguts_t */
+#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+
#include "cmExprParserHelper.h"
/* Replace the lexer input function. */
#undef YY_INPUT
#define YY_INPUT(buf, result, max_size) \
- { result = yyextra->LexInput(buf, max_size); }
+ do { result = yyextra->LexInput(buf, max_size); } while (0)
/* Include the set of tokens from the parser. */
#include "cmExprParserTokens.h"
+#include <string>
+
/*--------------------------------------------------------------------------*/
%}
+%option prefix="cmExpr_yy"
+
%option reentrant
%option noyywrap
%pointer
%%
+[ \t] {}
-[0-9][0-9]* { yylvalp->Number = atoi(yytext); return exp_NUMBER; }
+[0-9][0-9]* { yylvalp->Number = std::stoll(yytext, nullptr, 10); return exp_NUMBER; }
+0[xX][0-9a-fA-F][0-9a-fA-F]* { yylvalp->Number = std::stoll(yytext, nullptr, 16); return exp_NUMBER; }
"+" { return exp_PLUS; }
"-" { return exp_MINUS; }
@@ -53,5 +60,10 @@ Modify cmExprLexer.cxx:
">>" { return exp_SHIFTRIGHT; }
"(" { return exp_OPENPARENT; }
")" { return exp_CLOSEPARENT; }
+. { yyextra->UnexpectedChar(yytext[0]); }
%%
+
+/*--------------------------------------------------------------------------*/
+
+#endif /* __clang_analyzer__ */
diff --git a/Source/LexerParser/cmExprParser.cxx b/Source/LexerParser/cmExprParser.cxx
index 67664a5f5..8416e7249 100644
--- a/Source/LexerParser/cmExprParser.cxx
+++ b/Source/LexerParser/cmExprParser.cxx
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4. */
+/* A Bison parser, made by GNU Bison 3.3.2. */
/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+ Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -40,11 +41,14 @@
define necessary library symbols; they are noted "INFRINGES ON
USER NAME SPACE" below. */
+/* Undocumented macros, especially those whose name start with YY_,
+ are private implementation details. Do not rely on them. */
+
/* Identify Bison output. */
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "3.0.4"
+#define YYBISON_VERSION "3.3.2"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -67,8 +71,8 @@
#define yynerrs cmExpr_yynerrs
-/* Copy the first part of user declarations. */
-#line 1 "cmExprParser.y" /* yacc.c:339 */
+/* First part of user prologue. */
+#line 1 "cmExprParser.y" /* yacc.c:337 */
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
@@ -89,6 +93,7 @@ Modify cmExprParser.cxx:
#include <stdlib.h>
#include <string.h>
+#include <stdexcept>
/*-------------------------------------------------------------------------*/
#define YYDEBUG 1
@@ -107,14 +112,20 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message);
# pragma warning (disable: 4102) /* Unused goto label. */
# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
#endif
+#if defined(__GNUC__) && __GNUC__ >= 8
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif
-#line 112 "cmExprParser.cxx" /* yacc.c:339 */
-
+#line 120 "cmExprParser.cxx" /* yacc.c:337 */
# ifndef YY_NULLPTR
-# if defined __cplusplus && 201103L <= __cplusplus
-# define YY_NULLPTR nullptr
+# if defined __cplusplus
+# if 201103L <= __cplusplus
+# define YY_NULLPTR nullptr
+# else
+# define YY_NULLPTR 0
+# endif
# else
-# define YY_NULLPTR 0
+# define YY_NULLPTR ((void*)0)
# endif
# endif
@@ -183,9 +194,7 @@ int cmExpr_yyparse (yyscan_t yyscanner);
#endif /* !YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED */
-/* Copy the second part of user declarations. */
-#line 189 "cmExprParser.cxx" /* yacc.c:358 */
#ifdef short
# undef short
@@ -206,13 +215,13 @@ typedef signed char yytype_int8;
#ifdef YYTYPE_UINT16
typedef YYTYPE_UINT16 yytype_uint16;
#else
-typedef unsigned short int yytype_uint16;
+typedef unsigned short yytype_uint16;
#endif
#ifdef YYTYPE_INT16
typedef YYTYPE_INT16 yytype_int16;
#else
-typedef short int yytype_int16;
+typedef short yytype_int16;
#endif
#ifndef YYSIZE_T
@@ -224,7 +233,7 @@ typedef short int yytype_int16;
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
-# define YYSIZE_T unsigned int
+# define YYSIZE_T unsigned
# endif
#endif
@@ -260,15 +269,6 @@ typedef short int yytype_int16;
# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
#endif
-#if !defined _Noreturn \
- && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
-# if defined _MSC_VER && 1200 <= _MSC_VER
-# define _Noreturn __declspec (noreturn)
-# else
-# define _Noreturn YY_ATTRIBUTE ((__noreturn__))
-# endif
-#endif
-
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
# define YYUSE(E) ((void) (E))
@@ -276,7 +276,7 @@ typedef short int yytype_int16;
# define YYUSE(E) /* empty */
#endif
-#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
_Pragma ("GCC diagnostic push") \
@@ -425,29 +425,29 @@ union yyalloc
#endif /* !YYCOPY_NEEDED */
/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 17
+#define YYFINAL 19
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 30
+#define YYLAST 34
/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS 17
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 10
/* YYNRULES -- Number of rules. */
-#define YYNRULES 23
+#define YYNRULES 24
/* YYNSTATES -- Number of states. */
-#define YYNSTATES 39
+#define YYNSTATES 41
-/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
- by yylex, with out-of-bounds checking. */
#define YYUNDEFTOK 2
#define YYMAXUTOK 271
+/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, with out-of-bounds checking. */
#define YYTRANSLATE(YYX) \
- ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+ ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
- as returned by yylex, without out-of-bounds checking. */
+ as returned by yylex. */
static const yytype_uint8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -484,9 +484,9 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 73, 73, 78, 81, 86, 89, 94, 97, 102,
- 105, 108, 113, 116, 119, 124, 127, 130, 133, 138,
- 141, 144, 149, 152
+ 0, 77, 77, 82, 85, 90, 93, 98, 101, 106,
+ 109, 112, 117, 120, 123, 128, 131, 134, 140, 145,
+ 148, 151, 154, 159, 162
};
#endif
@@ -513,10 +513,10 @@ static const yytype_uint16 yytoknum[] =
};
# endif
-#define YYPACT_NINF -8
+#define YYPACT_NINF -11
#define yypact_value_is_default(Yystate) \
- (!!((Yystate) == (-8)))
+ (!!((Yystate) == (-11)))
#define YYTABLE_NINF -1
@@ -527,10 +527,11 @@ static const yytype_uint16 yytoknum[] =
STATE-NUM. */
static const yytype_int8 yypact[] =
{
- 0, 0, 0, 0, -8, 2, -7, -5, 8, 3,
- 10, 1, -8, -8, -8, -8, 6, -8, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, -8, -5,
- 8, 3, 10, 10, 1, 1, -8, -8, -8
+ 1, 1, 1, 1, 1, -11, 6, -10, -4, 9,
+ 4, 11, 2, -11, -11, -11, -11, 7, -11, -11,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ -11, -4, 9, 4, 11, 11, 2, 2, -11, -11,
+ -11
};
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -538,22 +539,23 @@ static const yytype_int8 yypact[] =
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
- 0, 0, 0, 0, 22, 0, 2, 3, 5, 7,
- 9, 12, 15, 19, 20, 21, 0, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 23, 4,
- 6, 8, 10, 11, 13, 14, 16, 17, 18
+ 0, 0, 0, 0, 0, 23, 0, 2, 3, 5,
+ 7, 9, 12, 15, 19, 20, 21, 0, 22, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 24, 4, 6, 8, 10, 11, 13, 14, 16, 17,
+ 18
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int8 yypgoto[] =
{
- -8, -8, 12, 5, 11, 9, -2, 4, -1, -8
+ -11, -11, 22, 10, 8, 12, -3, -2, -1, -11
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int8 yydefgoto[] =
{
- -1, 5, 6, 7, 8, 9, 10, 11, 12, 13
+ -1, 6, 7, 8, 9, 10, 11, 12, 13, 14
};
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
@@ -561,28 +563,29 @@ static const yytype_int8 yydefgoto[] =
number is the opposite. If YYTABLE_NINF, syntax error. */
static const yytype_uint8 yytable[] =
{
- 14, 15, 17, 1, 2, 18, 25, 26, 27, 19,
- 3, 21, 22, 23, 24, 16, 4, 28, 18, 32,
- 33, 20, 0, 29, 36, 37, 38, 34, 35, 31,
- 30
+ 15, 16, 20, 18, 1, 2, 19, 27, 28, 29,
+ 21, 3, 23, 24, 25, 26, 4, 5, 30, 20,
+ 34, 35, 22, 36, 37, 17, 38, 39, 40, 32,
+ 31, 0, 0, 0, 33
};
static const yytype_int8 yycheck[] =
{
- 1, 2, 0, 3, 4, 12, 5, 6, 7, 14,
- 10, 8, 9, 3, 4, 3, 16, 11, 12, 21,
- 22, 13, -1, 18, 25, 26, 27, 23, 24, 20,
- 19
+ 1, 2, 12, 4, 3, 4, 0, 5, 6, 7,
+ 14, 10, 8, 9, 3, 4, 15, 16, 11, 12,
+ 23, 24, 13, 25, 26, 3, 27, 28, 29, 21,
+ 20, -1, -1, -1, 22
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 3, 4, 10, 16, 18, 19, 20, 21, 22,
- 23, 24, 25, 26, 25, 25, 19, 0, 12, 14,
- 13, 8, 9, 3, 4, 5, 6, 7, 11, 20,
- 21, 22, 23, 23, 24, 24, 25, 25, 25
+ 0, 3, 4, 10, 15, 16, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 25, 25, 19, 25, 0,
+ 12, 14, 13, 8, 9, 3, 4, 5, 6, 7,
+ 11, 20, 21, 22, 23, 23, 24, 24, 25, 25,
+ 25
};
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
@@ -590,7 +593,7 @@ static const yytype_uint8 yyr1[] =
{
0, 17, 18, 19, 19, 20, 20, 21, 21, 22,
22, 22, 23, 23, 23, 24, 24, 24, 24, 25,
- 25, 25, 26, 26
+ 25, 25, 25, 26, 26
};
/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
@@ -598,7 +601,7 @@ static const yytype_uint8 yyr2[] =
{
0, 2, 1, 1, 3, 1, 3, 1, 3, 1,
3, 3, 1, 3, 3, 1, 3, 3, 3, 1,
- 2, 2, 1, 3
+ 2, 2, 2, 1, 3
};
@@ -614,22 +617,22 @@ static const yytype_uint8 yyr2[] =
#define YYRECOVERING() (!!yyerrstatus)
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- YYPOPSTACK (yylen); \
- yystate = *yyssp; \
- goto yybackup; \
- } \
- else \
- { \
- yyerror (yyscanner, YY_("syntax error: cannot back up")); \
- YYERROR; \
- } \
-while (0)
+#define YYBACKUP(Token, Value) \
+ do \
+ if (yychar == YYEMPTY) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ YYPOPSTACK (yylen); \
+ yystate = *yyssp; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (yyscanner, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+ while (0)
/* Error token number */
#define YYTERROR 1
@@ -669,38 +672,38 @@ do { \
} while (0)
-/*----------------------------------------.
-| Print this symbol's value on YYOUTPUT. |
-`----------------------------------------*/
+/*-----------------------------------.
+| Print this symbol's value on YYO. |
+`-----------------------------------*/
static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
- FILE *yyo = yyoutput;
- YYUSE (yyo);
+ FILE *yyoutput = yyo;
+ YYUSE (yyoutput);
YYUSE (yyscanner);
if (!yyvaluep)
return;
# ifdef YYPRINT
if (yytype < YYNTOKENS)
- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+ YYPRINT (yyo, yytoknum[yytype], *yyvaluep);
# endif
YYUSE (yytype);
}
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
+/*---------------------------.
+| Print this symbol on YYO. |
+`---------------------------*/
static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
- YYFPRINTF (yyoutput, "%s %s (",
+ YYFPRINTF (yyo, "%s %s (",
yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
- yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
- YYFPRINTF (yyoutput, ")");
+ yy_symbol_value_print (yyo, yytype, yyvaluep, yyscanner);
+ YYFPRINTF (yyo, ")");
}
/*------------------------------------------------------------------.
@@ -734,7 +737,7 @@ do { \
static void
yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
{
- unsigned long int yylno = yyrline[yyrule];
+ unsigned long yylno = yyrline[yyrule];
int yynrhs = yyr2[yyrule];
int yyi;
YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
@@ -745,7 +748,7 @@ yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yysca
YYFPRINTF (stderr, " $%d = ", yyi + 1);
yy_symbol_print (stderr,
yystos[yyssp[yyi + 1 - yynrhs]],
- &(yyvsp[(yyi + 1) - (yynrhs)])
+ &yyvsp[(yyi + 1) - (yynrhs)]
, yyscanner);
YYFPRINTF (stderr, "\n");
}
@@ -849,7 +852,10 @@ yytnamerr (char *yyres, const char *yystr)
case '\\':
if (*++yyp != '\\')
goto do_not_strip_quotes;
- /* Fall through. */
+ else
+ goto append;
+
+ append:
default:
if (yyres)
yyres[yyn] = *yyp;
@@ -867,7 +873,7 @@ yytnamerr (char *yyres, const char *yystr)
if (! yyres)
return yystrlen (yystr);
- return yystpcpy (yyres, yystr) - yyres;
+ return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres);
}
# endif
@@ -945,10 +951,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
yyarg[yycount++] = yytname[yyx];
{
YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
- if (! (yysize <= yysize1
- && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+ yysize = yysize1;
+ else
return 2;
- yysize = yysize1;
}
}
}
@@ -960,6 +966,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
case N: \
yyformat = S; \
break
+ default: /* Avoid compiler warnings. */
YYCASE_(0, YY_("syntax error"));
YYCASE_(1, YY_("syntax error, unexpected %s"));
YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
@@ -971,9 +978,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
{
YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
- if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+ yysize = yysize1;
+ else
return 2;
- yysize = yysize1;
}
if (*yymsg_alloc < yysize)
@@ -1104,23 +1112,31 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
yychar = YYEMPTY; /* Cause a token to be read. */
goto yysetstate;
+
/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate. |
+| yynewstate -- push a new state, which is found in yystate. |
`------------------------------------------------------------*/
- yynewstate:
+yynewstate:
/* In all cases, when you get here, the value and location stacks
have just been pushed. So pushing a state here evens the stacks. */
yyssp++;
- yysetstate:
- *yyssp = yystate;
+
+/*--------------------------------------------------------------------.
+| yynewstate -- set current state (the top of the stack) to yystate. |
+`--------------------------------------------------------------------*/
+yysetstate:
+ *yyssp = (yytype_int16) yystate;
if (yyss + yystacksize - 1 <= yyssp)
+#if !defined yyoverflow && !defined YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+#else
{
/* Get the current used size of the three stacks, in elements. */
- YYSIZE_T yysize = yyssp - yyss + 1;
+ YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1);
-#ifdef yyoverflow
+# if defined yyoverflow
{
/* Give user a chance to reallocate the stack. Use copies of
these so that the &'s don't force the real ones into
@@ -1136,14 +1152,10 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
&yyss1, yysize * sizeof (*yyssp),
&yyvs1, yysize * sizeof (*yyvsp),
&yystacksize);
-
yyss = yyss1;
yyvs = yyvs1;
}
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
- goto yyexhaustedlab;
-# else
+# else /* defined YYSTACK_RELOCATE */
/* Extend the stack our own way. */
if (YYMAXDEPTH <= yystacksize)
goto yyexhaustedlab;
@@ -1159,22 +1171,22 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
goto yyexhaustedlab;
YYSTACK_RELOCATE (yyss_alloc, yyss);
YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-# undef YYSTACK_RELOCATE
+# undef YYSTACK_RELOCATE
if (yyss1 != yyssa)
YYSTACK_FREE (yyss1);
}
# endif
-#endif /* no yyoverflow */
yyssp = yyss + yysize - 1;
yyvsp = yyvs + yysize - 1;
YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long int) yystacksize));
+ (unsigned long) yystacksize));
if (yyss + yystacksize - 1 <= yyssp)
YYABORT;
}
+#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
@@ -1183,11 +1195,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
goto yybackup;
+
/*-----------.
| yybackup. |
`-----------*/
yybackup:
-
/* Do appropriate processing given the current state. Read a
lookahead token if we need one and don't already have one. */
@@ -1260,7 +1272,7 @@ yydefault:
/*-----------------------------.
-| yyreduce -- Do a reduction. |
+| yyreduce -- do a reduction. |
`-----------------------------*/
yyreduce:
/* yyn is the number of a rule to reduce with. */
@@ -1281,183 +1293,194 @@ yyreduce:
switch (yyn)
{
case 2:
-#line 73 "cmExprParser.y" /* yacc.c:1646 */
+#line 77 "cmExprParser.y" /* yacc.c:1652 */
{
cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number));
}
-#line 1289 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1301 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 3:
-#line 78 "cmExprParser.y" /* yacc.c:1646 */
+#line 82 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1297 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1309 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 4:
-#line 81 "cmExprParser.y" /* yacc.c:1646 */
+#line 85 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number);
}
-#line 1305 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1317 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 5:
-#line 86 "cmExprParser.y" /* yacc.c:1646 */
+#line 90 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1313 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1325 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 6:
-#line 89 "cmExprParser.y" /* yacc.c:1646 */
+#line 93 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number);
}
-#line 1321 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1333 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 7:
-#line 94 "cmExprParser.y" /* yacc.c:1646 */
+#line 98 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1329 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1341 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 8:
-#line 97 "cmExprParser.y" /* yacc.c:1646 */
+#line 101 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number);
}
-#line 1337 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1349 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 9:
-#line 102 "cmExprParser.y" /* yacc.c:1646 */
+#line 106 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1345 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1357 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 10:
-#line 105 "cmExprParser.y" /* yacc.c:1646 */
+#line 109 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number);
}
-#line 1353 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1365 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 11:
-#line 108 "cmExprParser.y" /* yacc.c:1646 */
+#line 112 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number);
}
-#line 1361 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1373 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 12:
-#line 113 "cmExprParser.y" /* yacc.c:1646 */
+#line 117 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1369 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1381 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 13:
-#line 116 "cmExprParser.y" /* yacc.c:1646 */
+#line 120 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number);
}
-#line 1377 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1389 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 14:
-#line 119 "cmExprParser.y" /* yacc.c:1646 */
+#line 123 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number);
}
-#line 1385 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1397 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 15:
-#line 124 "cmExprParser.y" /* yacc.c:1646 */
+#line 128 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1393 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1405 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 16:
-#line 127 "cmExprParser.y" /* yacc.c:1646 */
+#line 131 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number);
}
-#line 1401 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1413 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 17:
-#line 130 "cmExprParser.y" /* yacc.c:1646 */
+#line 134 "cmExprParser.y" /* yacc.c:1652 */
{
+ if (yyvsp[0].Number == 0) {
+ throw std::overflow_error("divide by zero");
+ }
(yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number);
}
-#line 1409 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1424 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 18:
-#line 133 "cmExprParser.y" /* yacc.c:1646 */
+#line 140 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number);
}
-#line 1417 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1432 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 19:
-#line 138 "cmExprParser.y" /* yacc.c:1646 */
+#line 145 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = (yyvsp[0].Number);
}
-#line 1425 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1440 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 20:
-#line 141 "cmExprParser.y" /* yacc.c:1646 */
+#line 148 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = + (yyvsp[0].Number);
}
-#line 1433 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1448 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 21:
-#line 144 "cmExprParser.y" /* yacc.c:1646 */
+#line 151 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = - (yyvsp[0].Number);
}
-#line 1441 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1456 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 22:
-#line 149 "cmExprParser.y" /* yacc.c:1646 */
+#line 154 "cmExprParser.y" /* yacc.c:1652 */
{
- (yyval.Number) = (yyvsp[0].Number);
+ (yyval.Number) = ~ (yyvsp[0].Number);
}
-#line 1449 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1464 "cmExprParser.cxx" /* yacc.c:1652 */
break;
case 23:
-#line 152 "cmExprParser.y" /* yacc.c:1646 */
+#line 159 "cmExprParser.y" /* yacc.c:1652 */
+ {
+ (yyval.Number) = (yyvsp[0].Number);
+ }
+#line 1472 "cmExprParser.cxx" /* yacc.c:1652 */
+ break;
+
+ case 24:
+#line 162 "cmExprParser.y" /* yacc.c:1652 */
{
(yyval.Number) = (yyvsp[-1].Number);
}
-#line 1457 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1480 "cmExprParser.cxx" /* yacc.c:1652 */
break;
-#line 1461 "cmExprParser.cxx" /* yacc.c:1646 */
+#line 1484 "cmExprParser.cxx" /* yacc.c:1652 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -1482,14 +1505,13 @@ yyreduce:
/* Now 'shift' the result of the reduction. Determine what state
that goes to, based on the state we popped back to and the rule
number reduced by. */
-
- yyn = yyr1[yyn];
-
- yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
- if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
- yystate = yytable[yystate];
- else
- yystate = yydefgoto[yyn - YYNTOKENS];
+ {
+ const int yylhs = yyr1[yyn] - YYNTOKENS;
+ const int yyi = yypgoto[yylhs] + *yyssp;
+ yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp
+ ? yytable[yyi]
+ : yydefgoto[yylhs]);
+ }
goto yynewstate;
@@ -1573,12 +1595,10 @@ yyerrlab:
| yyerrorlab -- error raised explicitly by YYERROR. |
`---------------------------------------------------*/
yyerrorlab:
-
- /* Pacify compilers like GCC when the user code never invokes
- YYERROR and the label yyerrorlab therefore never appears in user
- code. */
- if (/*CONSTCOND*/ 0)
- goto yyerrorlab;
+ /* Pacify compilers when the user code never invokes YYERROR and the
+ label yyerrorlab therefore never appears in user code. */
+ if (0)
+ YYERROR;
/* Do not reclaim the symbols of the rule whose action triggered
this YYERROR. */
@@ -1641,6 +1661,7 @@ yyacceptlab:
yyresult = 0;
goto yyreturn;
+
/*-----------------------------------.
| yyabortlab -- YYABORT comes here. |
`-----------------------------------*/
@@ -1648,6 +1669,7 @@ yyabortlab:
yyresult = 1;
goto yyreturn;
+
#if !defined yyoverflow || YYERROR_VERBOSE
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
@@ -1658,6 +1680,10 @@ yyexhaustedlab:
/* Fall through. */
#endif
+
+/*-----------------------------------------------------.
+| yyreturn -- parsing is finished, return the result. |
+`-----------------------------------------------------*/
yyreturn:
if (yychar != YYEMPTY)
{
@@ -1687,7 +1713,7 @@ yyreturn:
#endif
return yyresult;
}
-#line 157 "cmExprParser.y" /* yacc.c:1906 */
+#line 167 "cmExprParser.y" /* yacc.c:1918 */
/* End of grammar */
diff --git a/Source/LexerParser/cmExprParser.y b/Source/LexerParser/cmExprParser.y
index d1c3a97a7..7ae21188e 100644
--- a/Source/LexerParser/cmExprParser.y
+++ b/Source/LexerParser/cmExprParser.y
@@ -18,6 +18,7 @@ Modify cmExprParser.cxx:
#include <stdlib.h>
#include <string.h>
+#include <stdexcept>
/*-------------------------------------------------------------------------*/
#define YYDEBUG 1
@@ -36,6 +37,9 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message);
# pragma warning (disable: 4102) /* Unused goto label. */
# pragma warning (disable: 4065) /* Switch statement contains default but no case. */
#endif
+#if defined(__GNUC__) && __GNUC__ >= 8
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif
%}
/* Generate a reentrant parser object. */
@@ -128,6 +132,9 @@ term:
$<Number>$ = $<Number>1 * $<Number>3;
}
| term exp_DIVIDE unary {
+ if (yyvsp[0].Number == 0) {
+ throw std::overflow_error("divide by zero");
+ }
$<Number>$ = $<Number>1 / $<Number>3;
}
| term exp_MOD unary {
@@ -144,6 +151,9 @@ unary:
| exp_MINUS unary {
$<Number>$ = - $<Number>2;
}
+| exp_NOT unary {
+ $<Number>$ = ~ $<Number>2;
+ }
factor:
exp_NUMBER {
diff --git a/Source/LexerParser/cmExprParserTokens.h b/Source/LexerParser/cmExprParserTokens.h
index 84b2bbdcd..5ffd7c510 100644
--- a/Source/LexerParser/cmExprParserTokens.h
+++ b/Source/LexerParser/cmExprParserTokens.h
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4. */
+/* A Bison parser, made by GNU Bison 3.3.2. */
/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+ Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,6 +31,9 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
+/* Undocumented macros, especially those whose name start with YY_,
+ are private implementation details. Do not rely on them. */
+
#ifndef YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED
# define YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED
/* Debug traces. */
diff --git a/Source/LexerParser/cmFortranLexer.cxx b/Source/LexerParser/cmFortranLexer.cxx
index 01c09acb7..bcda77c30 100644
--- a/Source/LexerParser/cmFortranLexer.cxx
+++ b/Source/LexerParser/cmFortranLexer.cxx
@@ -1,7 +1,4 @@
#include "cmStandardLexer.h"
-#line 2 "cmFortranLexer.cxx"
-
-#line 4 "cmFortranLexer.cxx"
#define FLEXINT_H 1
#define YY_INT_ALIGNED short int
@@ -11,11 +8,221 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6
-#define YY_FLEX_SUBMINOR_VERSION 1
+#define YY_FLEX_SUBMINOR_VERSION 4
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
+#ifdef yy_create_buffer
+#define cmFortran_yy_create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer cmFortran_yy_create_buffer
+#endif
+
+#ifdef yy_delete_buffer
+#define cmFortran_yy_delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer cmFortran_yy_delete_buffer
+#endif
+
+#ifdef yy_scan_buffer
+#define cmFortran_yy_scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer cmFortran_yy_scan_buffer
+#endif
+
+#ifdef yy_scan_string
+#define cmFortran_yy_scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string cmFortran_yy_scan_string
+#endif
+
+#ifdef yy_scan_bytes
+#define cmFortran_yy_scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes cmFortran_yy_scan_bytes
+#endif
+
+#ifdef yy_init_buffer
+#define cmFortran_yy_init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer cmFortran_yy_init_buffer
+#endif
+
+#ifdef yy_flush_buffer
+#define cmFortran_yy_flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer cmFortran_yy_flush_buffer
+#endif
+
+#ifdef yy_load_buffer_state
+#define cmFortran_yy_load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state cmFortran_yy_load_buffer_state
+#endif
+
+#ifdef yy_switch_to_buffer
+#define cmFortran_yy_switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer cmFortran_yy_switch_to_buffer
+#endif
+
+#ifdef yypush_buffer_state
+#define cmFortran_yypush_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state cmFortran_yypush_buffer_state
+#endif
+
+#ifdef yypop_buffer_state
+#define cmFortran_yypop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state cmFortran_yypop_buffer_state
+#endif
+
+#ifdef yyensure_buffer_stack
+#define cmFortran_yyensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack cmFortran_yyensure_buffer_stack
+#endif
+
+#ifdef yylex
+#define cmFortran_yylex_ALREADY_DEFINED
+#else
+#define yylex cmFortran_yylex
+#endif
+
+#ifdef yyrestart
+#define cmFortran_yyrestart_ALREADY_DEFINED
+#else
+#define yyrestart cmFortran_yyrestart
+#endif
+
+#ifdef yylex_init
+#define cmFortran_yylex_init_ALREADY_DEFINED
+#else
+#define yylex_init cmFortran_yylex_init
+#endif
+
+#ifdef yylex_init_extra
+#define cmFortran_yylex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra cmFortran_yylex_init_extra
+#endif
+
+#ifdef yylex_destroy
+#define cmFortran_yylex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy cmFortran_yylex_destroy
+#endif
+
+#ifdef yyget_debug
+#define cmFortran_yyget_debug_ALREADY_DEFINED
+#else
+#define yyget_debug cmFortran_yyget_debug
+#endif
+
+#ifdef yyset_debug
+#define cmFortran_yyset_debug_ALREADY_DEFINED
+#else
+#define yyset_debug cmFortran_yyset_debug
+#endif
+
+#ifdef yyget_extra
+#define cmFortran_yyget_extra_ALREADY_DEFINED
+#else
+#define yyget_extra cmFortran_yyget_extra
+#endif
+
+#ifdef yyset_extra
+#define cmFortran_yyset_extra_ALREADY_DEFINED
+#else
+#define yyset_extra cmFortran_yyset_extra
+#endif
+
+#ifdef yyget_in
+#define cmFortran_yyget_in_ALREADY_DEFINED
+#else
+#define yyget_in cmFortran_yyget_in
+#endif
+
+#ifdef yyset_in
+#define cmFortran_yyset_in_ALREADY_DEFINED
+#else
+#define yyset_in cmFortran_yyset_in
+#endif
+
+#ifdef yyget_out
+#define cmFortran_yyget_out_ALREADY_DEFINED
+#else
+#define yyget_out cmFortran_yyget_out
+#endif
+
+#ifdef yyset_out
+#define cmFortran_yyset_out_ALREADY_DEFINED
+#else
+#define yyset_out cmFortran_yyset_out
+#endif
+
+#ifdef yyget_leng
+#define cmFortran_yyget_leng_ALREADY_DEFINED
+#else
+#define yyget_leng cmFortran_yyget_leng
+#endif
+
+#ifdef yyget_text
+#define cmFortran_yyget_text_ALREADY_DEFINED
+#else
+#define yyget_text cmFortran_yyget_text
+#endif
+
+#ifdef yyget_lineno
+#define cmFortran_yyget_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno cmFortran_yyget_lineno
+#endif
+
+#ifdef yyset_lineno
+#define cmFortran_yyset_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno cmFortran_yyset_lineno
+#endif
+
+#ifdef yyget_column
+#define cmFortran_yyget_column_ALREADY_DEFINED
+#else
+#define yyget_column cmFortran_yyget_column
+#endif
+
+#ifdef yyset_column
+#define cmFortran_yyset_column_ALREADY_DEFINED
+#else
+#define yyset_column cmFortran_yyset_column
+#endif
+
+#ifdef yywrap
+#define cmFortran_yywrap_ALREADY_DEFINED
+#else
+#define yywrap cmFortran_yywrap
+#endif
+
+#ifdef yyalloc
+#define cmFortran_yyalloc_ALREADY_DEFINED
+#else
+#define yyalloc cmFortran_yyalloc
+#endif
+
+#ifdef yyrealloc
+#define cmFortran_yyrealloc_ALREADY_DEFINED
+#else
+#define yyrealloc cmFortran_yyrealloc
+#endif
+
+#ifdef yyfree
+#define cmFortran_yyfree_ALREADY_DEFINED
+#else
+#define yyfree cmFortran_yyfree
+#endif
+
/* First, we deal with platform-specific or compiler-specific issues. */
/* begin standard C headers. */
@@ -86,10 +293,16 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
+#ifndef SIZE_MAX
+#define SIZE_MAX (~(size_t)0)
+#endif
+
#endif /* ! C99 */
#endif /* ! FLEXINT_H */
+/* begin standard C++ headers. */
+
/* TODO: this is always defined, so inline it */
#define yyconst const
@@ -102,12 +315,10 @@ typedef unsigned int flex_uint32_t;
/* Returned upon end-of-file. */
#define YY_NULL 0
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index. If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
+/* Promotes a possibly negative, possibly signed char to an
+ * integer in range [0..255] for use as an array index.
*/
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+#define YY_SC_TO_UI(c) ((YY_CHAR) (c))
/* An opaque pointer. */
#ifndef YY_TYPEDEF_YY_SCANNER_T
@@ -131,20 +342,16 @@ typedef void* yyscan_t;
* definition of BEGIN.
*/
#define BEGIN yyg->yy_start = 1 + 2 *
-
/* Translate the current start state into a value that can be later handed
* to BEGIN to return to the state. The YYSTATE alias is for lex
* compatibility.
*/
#define YY_START ((yyg->yy_start - 1) / 2)
#define YYSTATE YY_START
-
/* Action number for EOF rule of a given start state. */
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE cmFortran_yyrestart(yyin ,yyscanner )
-
+#define YY_NEW_FILE yyrestart( yyin , yyscanner )
#define YY_END_OF_BUFFER_CHAR 0
/* Size of default input buffer. */
@@ -194,7 +401,6 @@ typedef size_t yy_size_t;
YY_DO_BEFORE_ACTION; /* set up yytext again */ \
} \
while ( 0 )
-
#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
#ifndef YY_STRUCT_YY_BUFFER_STATE
@@ -254,7 +460,7 @@ struct yy_buffer_state
* possible backing-up.
*
* When we actually see the EOF, we change the status to "new"
- * (via cmFortran_yyrestart()), so that the user can continue scanning by
+ * (via yyrestart()), so that the user can continue scanning by
* just pointing yyin at a new input file.
*/
#define YY_BUFFER_EOF_PENDING 2
@@ -271,73 +477,67 @@ struct yy_buffer_state
#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
: NULL)
-
/* Same as previous macro, but useful when we know that the buffer stack is not
* NULL or when we need an lvalue. For internal use only.
*/
#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
-void cmFortran_yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void cmFortran_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmFortran_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void cmFortran_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmFortran_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmFortran_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void cmFortran_yypop_buffer_state (yyscan_t yyscanner );
-
-static void cmFortran_yyensure_buffer_stack (yyscan_t yyscanner );
-static void cmFortran_yy_load_buffer_state (yyscan_t yyscanner );
-static void cmFortran_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
-
-#define YY_FLUSH_BUFFER cmFortran_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+void yyrestart ( FILE *input_file , yyscan_t yyscanner );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
+void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+void yypop_buffer_state ( yyscan_t yyscanner );
-YY_BUFFER_STATE cmFortran_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmFortran_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmFortran_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+static void yyensure_buffer_stack ( yyscan_t yyscanner );
+static void yy_load_buffer_state ( yyscan_t yyscanner );
+static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner );
+#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner)
-void *cmFortran_yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *cmFortran_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void cmFortran_yyfree (void * ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
-#define yy_new_buffer cmFortran_yy_create_buffer
+void *yyalloc ( yy_size_t , yyscan_t yyscanner );
+void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
+void yyfree ( void * , yyscan_t yyscanner );
+#define yy_new_buffer yy_create_buffer
#define yy_set_interactive(is_interactive) \
{ \
if ( ! YY_CURRENT_BUFFER ){ \
- cmFortran_yyensure_buffer_stack (yyscanner); \
+ yyensure_buffer_stack (yyscanner); \
YY_CURRENT_BUFFER_LVALUE = \
- cmFortran_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
} \
YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
}
-
#define yy_set_bol(at_bol) \
{ \
if ( ! YY_CURRENT_BUFFER ){\
- cmFortran_yyensure_buffer_stack (yyscanner); \
+ yyensure_buffer_stack (yyscanner); \
YY_CURRENT_BUFFER_LVALUE = \
- cmFortran_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
} \
YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
}
-
#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
/* Begin user sect3 */
#define cmFortran_yywrap(yyscanner) (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
-
-typedef unsigned char YY_CHAR;
+typedef flex_uint8_t YY_CHAR;
typedef int yy_state_type;
#define yytext_ptr yytext_r
-static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
-static int yy_get_next_buffer (yyscan_t yyscanner );
-static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
+static yy_state_type yy_get_previous_state ( yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans ( yy_state_type current_state , yyscan_t yyscanner);
+static int yy_get_next_buffer ( yyscan_t yyscanner );
+static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner );
/* Done after the current pattern has been matched and before the
* corresponding action - sets up yytext.
@@ -348,7 +548,6 @@ static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
yyg->yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
-
#define YY_NUM_RULES 54
#define YY_END_OF_BUFFER 55
/* This struct is not used in this scanner,
@@ -358,7 +557,7 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[210] =
+static const flex_int16_t yy_accept[210] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55, 49, 51, 50, 53, 1, 49, 33, 2, 47,
@@ -368,16 +567,16 @@ static yyconst flex_int16_t yy_accept[210] =
0, 0, 33, 33, 34, 36, 39, 49, 46, 46,
46, 46, 46, 46, 0, 52, 46, 0, 0, 0,
12, 0, 0, 0, 0, 0, 0, 49, 0, 11,
- 46, 0, 0, 5, 0, 0, 0, 29, 0, 0,
+ 46, 0, 0, 5, 0, 0, 0, 0, 29, 0,
33, 33, 33, 33, 0, 0, 40, 46, 46, 46,
46, 45, 12, 12, 0, 0, 0, 23, 0, 0,
0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
0, 0, 0, 0, 46, 46, 46, 46, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 30, 31, 0, 0, 0, 0, 0, 0, 46, 46,
+ 0, 30, 31, 0, 0, 0, 0, 0, 46, 46,
46, 46, 0, 24, 25, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 32, 27, 0, 0, 20, 0,
+ 0, 0, 0, 0, 20, 32, 27, 0, 0, 0,
46, 46, 43, 46, 0, 26, 21, 0, 0, 0,
19, 0, 0, 18, 28, 0, 0, 41, 46, 46,
17, 22, 0, 7, 38, 7, 15, 0, 46, 46,
@@ -385,7 +584,7 @@ static yyconst flex_int16_t yy_accept[210] =
14, 16, 42, 44, 0, 0, 0, 13, 0
} ;
-static yyconst YY_CHAR yy_ec[256] =
+static const YY_CHAR yy_ec[256] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
@@ -417,7 +616,7 @@ static yyconst YY_CHAR yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst YY_CHAR yy_meta[50] =
+static const YY_CHAR yy_meta[50] =
{ 0,
1, 2, 2, 3, 4, 3, 3, 1, 1, 3,
3, 3, 3, 1, 3, 5, 3, 3, 1, 3,
@@ -426,40 +625,40 @@ static yyconst YY_CHAR yy_meta[50] =
7, 7, 7, 7, 7, 7, 7, 7, 7
} ;
-static yyconst flex_uint16_t yy_base[219] =
+static const flex_int16_t yy_base[219] =
{ 0,
- 0, 48, 0, 49, 513, 56, 52, 57, 62, 68,
- 515, 0, 583, 583, 509, 583, 97, 74, 583, 583,
- 583, 583, 491, 583, 423, 421, 0, 19, 40, 392,
- 36, 47, 86, 146, 88, 186, 413, 235, 275, 583,
- 407, 98, 583, 583, 0, 386, 583, 323, 65, 73,
- 81, 74, 127, 146, 583, 583, 583, 108, 0, 89,
- 120, 92, 362, 116, 161, 583, 0, 167, 371, 0,
- 168, 131, 146, 171, 81, 89, 352, 420, 353, 583,
- 0, 349, 178, 196, 175, 197, 188, 208, 196, 197,
- 256, 262, 324, 330, 337, 143, 0, 151, 220, 56,
-
- 305, 0, 336, 139, 225, 315, 305, 322, 318, 163,
- 320, 268, 266, 369, 583, 340, 347, 350, 350, 351,
- 357, 350, 357, 363, 140, 235, 359, 218, 362, 375,
- 379, 380, 381, 385, 384, 404, 405, 243, 235, 213,
- 583, 583, 405, 407, 410, 171, 410, 409, 419, 418,
- 423, 426, 311, 583, 583, 428, 429, 431, 173, 462,
- 435, 166, 145, 438, 583, 583, 441, 444, 583, 433,
- 448, 89, 0, 438, 450, 583, 583, 452, 457, 487,
- 583, 114, 0, 583, 583, 457, 462, 0, 465, 463,
- 583, 583, 468, 583, 583, 583, 583, 470, 471, 474,
-
- 500, 583, 0, 0, 505, 0, 65, 583, 583, 524,
- 531, 537, 540, 547, 554, 561, 568, 575
+ 0, 48, 0, 49, 464, 56, 52, 57, 62, 68,
+ 466, 0, 468, 468, 462, 468, 74, 81, 468, 468,
+ 468, 468, 447, 468, 442, 440, 0, 19, 41, 427,
+ 47, 41, 90, 119, 97, 158, 455, 207, 247, 468,
+ 454, 101, 468, 468, 0, 455, 468, 105, 430, 423,
+ 62, 67, 119, 151, 468, 468, 468, 121, 0, 90,
+ 93, 110, 431, 112, 142, 468, 0, 160, 295, 0,
+ 162, 411, 123, 102, 408, 405, 446, 344, 447, 468,
+ 0, 444, 170, 174, 420, 421, 132, 404, 95, 404,
+ 180, 186, 192, 228, 297, 397, 0, 168, 144, 52,
+
+ 411, 0, 204, 217, 397, 179, 390, 170, 389, 378,
+ 364, 390, 389, 230, 468, 363, 355, 337, 337, 334,
+ 335, 335, 330, 334, 187, 339, 267, 339, 327, 327,
+ 327, 324, 325, 325, 318, 319, 318, 354, 352, 323,
+ 327, 468, 468, 310, 307, 305, 297, 297, 275, 275,
+ 277, 279, 287, 468, 468, 286, 283, 273, 196, 307,
+ 200, 238, 234, 210, 468, 468, 468, 174, 171, 162,
+ 279, 182, 0, 269, 150, 468, 468, 137, 109, 323,
+ 468, 239, 0, 468, 468, 72, 71, 0, 283, 283,
+ 468, 468, 51, 468, 468, 468, 468, 37, 283, 288,
+
+ 330, 468, 0, 0, 331, 0, 52, 468, 468, 384,
+ 391, 397, 400, 407, 414, 421, 428, 435
} ;
-static yyconst flex_int16_t yy_def[219] =
+static const flex_int16_t yy_def[219] =
{ 0,
209, 1, 1, 1, 1, 1, 210, 210, 210, 210,
209, 211, 209, 209, 212, 209, 211, 209, 209, 209,
209, 209, 209, 209, 209, 211, 213, 213, 213, 213,
- 213, 213, 211, 213, 209, 209, 209, 214, 209, 209,
+ 213, 213, 211, 213, 209, 211, 209, 214, 209, 209,
209, 209, 209, 209, 211, 212, 209, 209, 209, 209,
209, 209, 209, 215, 209, 209, 209, 211, 213, 213,
213, 213, 213, 213, 209, 209, 34, 209, 209, 69,
@@ -482,7 +681,7 @@ static yyconst flex_int16_t yy_def[219] =
209, 209, 209, 209, 209, 209, 209, 209
} ;
-static yyconst flex_uint16_t yy_nxt[633] =
+static const flex_int16_t yy_nxt[518] =
{ 0,
12, 13, 14, 13, 13, 15, 16, 12, 17, 18,
19, 20, 21, 12, 22, 12, 23, 24, 12, 25,
@@ -491,72 +690,59 @@ static yyconst flex_uint16_t yy_nxt[633] =
27, 27, 28, 27, 29, 27, 27, 31, 32, 35,
35, 60, 35, 35, 41, 36, 36, 35, 37, 41,
35, 42, 43, 36, 41, 60, 42, 43, 44, 38,
- 41, 42, 61, 63, 44, 53, 53, 42, 53, 54,
- 39, 39, 64, 55, 63, 208, 61, 65, 66, 68,
- 65, 85, 68, 127, 64, 69, 39, 39, 48, 83,
-
- 84, 48, 83, 86, 127, 87, 90, 85, 88, 95,
- 110, 189, 95, 89, 97, 195, 195, 100, 86, 87,
- 90, 111, 49, 50, 88, 110, 51, 89, 53, 53,
- 97, 53, 54, 100, 52, 111, 55, 96, 49, 50,
- 104, 51, 102, 104, 98, 52, 45, 92, 53, 183,
- 92, 93, 96, 45, 45, 94, 99, 105, 102, 45,
- 98, 67, 65, 66, 45, 65, 45, 45, 68, 104,
- 182, 68, 104, 105, 69, 124, 106, 149, 107, 83,
- 84, 125, 83, 71, 45, 67, 45, 70, 149, 124,
- 70, 106, 107, 45, 45, 136, 125, 114, 108, 45,
-
- 114, 71, 116, 109, 45, 115, 45, 45, 168, 136,
- 179, 72, 73, 119, 108, 74, 75, 109, 116, 168,
- 122, 179, 123, 76, 45, 45, 117, 72, 73, 119,
- 74, 75, 118, 120, 76, 78, 122, 80, 123, 163,
- 121, 117, 78, 78, 118, 164, 126, 162, 78, 120,
- 78, 152, 129, 78, 121, 78, 78, 92, 53, 164,
- 92, 93, 126, 92, 53, 94, 92, 93, 129, 150,
- 139, 94, 138, 78, 78, 79, 79, 80, 79, 79,
+ 41, 42, 208, 61, 44, 48, 64, 42, 48, 202,
+ 39, 39, 53, 53, 63, 53, 54, 61, 64, 127,
+ 55, 65, 66, 201, 65, 63, 39, 39, 68, 49,
+
+ 127, 68, 83, 84, 69, 83, 48, 87, 88, 48,
+ 89, 50, 198, 90, 197, 97, 51, 98, 52, 45,
+ 53, 53, 95, 53, 54, 95, 45, 45, 55, 99,
+ 49, 97, 45, 98, 67, 100, 121, 45, 102, 45,
+ 45, 122, 50, 65, 66, 108, 65, 51, 109, 52,
+ 193, 100, 92, 53, 102, 92, 93, 45, 67, 70,
+ 94, 68, 70, 104, 68, 96, 104, 69, 106, 107,
+ 126, 83, 84, 71, 83, 114, 118, 71, 114, 119,
+ 192, 92, 53, 115, 92, 93, 126, 92, 53, 94,
+ 92, 93, 191, 92, 53, 94, 92, 93, 125, 72,
+
+ 73, 94, 74, 75, 189, 104, 76, 78, 104, 80,
+ 187, 133, 186, 125, 78, 78, 134, 185, 104, 103,
+ 78, 104, 78, 130, 149, 78, 131, 78, 78, 92,
+ 53, 114, 92, 93, 114, 149, 184, 94, 183, 115,
+ 195, 195, 182, 181, 179, 78, 78, 79, 79, 80,
79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
- 81, 79, 79, 79, 79, 79, 79, 81, 81, 81,
-
+ 79, 79, 81, 79, 79, 79, 79, 79, 79, 81,
81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
- 81, 81, 81, 79, 81, 81, 81, 81, 81, 81,
- 81, 81, 81, 81, 48, 92, 53, 48, 92, 93,
- 132, 92, 53, 94, 92, 93, 128, 104, 95, 94,
- 104, 95, 135, 175, 130, 137, 132, 133, 49, 50,
- 131, 103, 51, 113, 134, 80, 112, 175, 135, 130,
- 52, 137, 131, 133, 49, 50, 96, 51, 134, 140,
- 114, 52, 70, 114, 141, 70, 142, 144, 115, 143,
- 146, 96, 145, 147, 140, 101, 103, 148, 47, 151,
- 141, 153, 142, 144, 143, 146, 72, 73, 145, 147,
-
- 74, 75, 154, 148, 151, 155, 153, 157, 76, 156,
- 158, 82, 72, 73, 159, 74, 75, 77, 154, 76,
- 78, 155, 80, 157, 156, 62, 158, 78, 78, 159,
- 160, 161, 165, 78, 166, 78, 167, 169, 78, 170,
- 78, 78, 58, 57, 171, 172, 160, 161, 165, 173,
- 166, 174, 167, 169, 170, 176, 177, 178, 78, 78,
- 171, 172, 181, 180, 184, 173, 180, 174, 185, 186,
- 187, 176, 177, 178, 188, 190, 191, 103, 181, 192,
- 184, 187, 193, 197, 185, 186, 190, 198, 180, 199,
- 188, 180, 191, 200, 201, 192, 202, 203, 193, 197,
-
- 204, 205, 103, 198, 205, 199, 205, 56, 200, 205,
- 201, 47, 202, 203, 209, 37, 204, 209, 206, 209,
- 209, 209, 209, 206, 40, 40, 40, 40, 40, 40,
- 40, 45, 209, 209, 209, 45, 45, 46, 46, 46,
- 46, 46, 46, 46, 59, 209, 59, 79, 79, 79,
+ 81, 81, 81, 81, 81, 79, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 70, 151, 95, 70,
+
+ 171, 95, 172, 173, 174, 188, 190, 199, 180, 203,
+ 103, 180, 151, 200, 204, 178, 171, 190, 172, 173,
+ 174, 188, 103, 199, 180, 203, 177, 180, 200, 176,
+ 204, 205, 205, 175, 205, 205, 72, 73, 103, 74,
+ 75, 96, 170, 76, 78, 169, 80, 168, 206, 206,
+ 167, 78, 78, 166, 165, 164, 163, 78, 162, 78,
+ 161, 160, 78, 159, 78, 78, 158, 157, 156, 155,
+ 154, 153, 152, 150, 148, 147, 146, 145, 144, 143,
+ 142, 141, 78, 78, 40, 40, 40, 40, 40, 40,
+ 40, 45, 140, 139, 138, 45, 45, 46, 46, 46,
+
+ 46, 46, 46, 46, 59, 137, 59, 79, 79, 79,
79, 79, 79, 79, 91, 91, 91, 91, 91, 91,
- 91, 194, 194, 194, 209, 194, 194, 194, 196, 209,
- 196, 209, 196, 196, 196, 207, 207, 207, 207, 207,
- 209, 207, 11, 209, 209, 209, 209, 209, 209, 209,
+ 91, 194, 194, 194, 136, 194, 194, 194, 196, 135,
+ 196, 132, 196, 196, 196, 207, 207, 207, 207, 207,
+ 129, 207, 128, 124, 123, 120, 117, 116, 113, 80,
+ 112, 111, 110, 105, 101, 86, 85, 47, 82, 77,
+ 62, 58, 57, 56, 47, 209, 37, 11, 209, 209,
209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
-
209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
+
209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209
+ 209, 209, 209, 209, 209, 209, 209
} ;
-static yyconst flex_int16_t yy_chk[633] =
+static const flex_int16_t yy_chk[518] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -565,69 +751,56 @@ static yyconst flex_int16_t yy_chk[633] =
1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
4, 28, 2, 4, 7, 2, 4, 6, 6, 8,
6, 7, 7, 6, 9, 28, 8, 8, 9, 6,
- 10, 9, 29, 31, 10, 18, 18, 10, 18, 18,
- 6, 6, 32, 18, 31, 207, 29, 33, 33, 35,
- 33, 49, 35, 100, 32, 35, 6, 6, 17, 42,
-
- 42, 17, 42, 50, 100, 50, 52, 49, 51, 58,
- 75, 172, 58, 51, 60, 182, 182, 62, 50, 50,
- 52, 76, 17, 17, 51, 75, 17, 51, 53, 53,
- 60, 53, 53, 62, 17, 76, 53, 58, 17, 17,
- 104, 17, 64, 104, 61, 17, 34, 54, 54, 163,
- 54, 54, 58, 34, 34, 54, 61, 72, 64, 34,
- 61, 34, 65, 65, 34, 65, 34, 34, 68, 71,
- 162, 68, 71, 72, 68, 96, 73, 125, 73, 83,
- 83, 98, 83, 71, 34, 34, 36, 36, 125, 96,
- 36, 73, 73, 36, 36, 110, 98, 84, 74, 36,
-
- 84, 36, 85, 74, 36, 84, 36, 36, 146, 110,
- 159, 36, 36, 87, 74, 36, 36, 74, 85, 146,
- 89, 159, 90, 36, 36, 36, 86, 36, 36, 87,
- 36, 36, 86, 88, 36, 38, 89, 38, 90, 139,
- 88, 86, 38, 38, 86, 140, 99, 138, 38, 88,
- 38, 128, 105, 38, 88, 38, 38, 91, 91, 140,
- 91, 91, 99, 92, 92, 91, 92, 92, 105, 126,
- 113, 92, 112, 38, 38, 39, 39, 39, 39, 39,
+ 10, 9, 207, 29, 10, 17, 32, 10, 17, 198,
+ 6, 6, 18, 18, 31, 18, 18, 29, 32, 100,
+ 18, 33, 33, 193, 33, 31, 6, 6, 35, 17,
+
+ 100, 35, 42, 42, 35, 42, 48, 51, 51, 48,
+ 52, 17, 187, 52, 186, 60, 17, 61, 17, 34,
+ 53, 53, 58, 53, 53, 58, 34, 34, 53, 61,
+ 48, 60, 34, 61, 34, 62, 89, 34, 64, 34,
+ 34, 89, 48, 65, 65, 74, 65, 48, 74, 48,
+ 179, 62, 54, 54, 64, 54, 54, 34, 34, 36,
+ 54, 68, 36, 71, 68, 58, 71, 68, 73, 73,
+ 99, 83, 83, 36, 83, 84, 87, 71, 84, 87,
+ 178, 91, 91, 84, 91, 91, 99, 92, 92, 91,
+ 92, 92, 175, 93, 93, 92, 93, 93, 98, 36,
+
+ 36, 93, 36, 36, 172, 103, 36, 38, 103, 38,
+ 170, 108, 169, 98, 38, 38, 108, 168, 104, 103,
+ 38, 104, 38, 106, 125, 38, 106, 38, 38, 94,
+ 94, 114, 94, 94, 114, 125, 164, 94, 163, 114,
+ 182, 182, 162, 161, 159, 38, 38, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
-
39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 48, 93, 93, 48, 93, 93,
- 107, 94, 94, 93, 94, 94, 101, 103, 95, 94,
- 103, 95, 109, 153, 106, 111, 107, 108, 48, 48,
- 106, 103, 48, 82, 108, 79, 77, 153, 109, 106,
- 48, 111, 106, 108, 48, 48, 95, 48, 108, 116,
- 114, 48, 69, 114, 117, 69, 118, 120, 114, 119,
- 122, 95, 121, 123, 116, 63, 69, 124, 46, 127,
- 117, 129, 118, 120, 119, 122, 69, 69, 121, 123,
-
- 69, 69, 130, 124, 127, 131, 129, 133, 69, 132,
- 134, 41, 69, 69, 135, 69, 69, 37, 130, 69,
- 78, 131, 78, 133, 132, 30, 134, 78, 78, 135,
- 136, 137, 143, 78, 144, 78, 145, 147, 78, 148,
- 78, 78, 26, 25, 149, 150, 136, 137, 143, 151,
- 144, 152, 145, 147, 148, 156, 157, 158, 78, 78,
- 149, 150, 161, 160, 164, 151, 160, 152, 167, 168,
- 170, 156, 157, 158, 171, 174, 175, 160, 161, 178,
- 164, 170, 179, 186, 167, 168, 174, 187, 180, 189,
- 171, 180, 175, 190, 193, 178, 198, 199, 179, 186,
-
- 200, 201, 180, 187, 201, 189, 205, 23, 190, 205,
- 193, 15, 198, 199, 11, 5, 200, 0, 201, 0,
- 0, 0, 0, 205, 210, 210, 210, 210, 210, 210,
- 210, 211, 0, 0, 0, 211, 211, 212, 212, 212,
- 212, 212, 212, 212, 213, 0, 213, 214, 214, 214,
+ 39, 39, 39, 39, 39, 39, 69, 127, 95, 69,
+
+ 149, 95, 150, 151, 152, 171, 174, 189, 160, 199,
+ 69, 160, 127, 190, 200, 158, 149, 174, 150, 151,
+ 152, 171, 160, 189, 180, 199, 157, 180, 190, 156,
+ 200, 201, 205, 153, 201, 205, 69, 69, 180, 69,
+ 69, 95, 148, 69, 78, 147, 78, 146, 201, 205,
+ 145, 78, 78, 144, 141, 140, 139, 78, 138, 78,
+ 137, 136, 78, 135, 78, 78, 134, 133, 132, 131,
+ 130, 129, 128, 126, 124, 123, 122, 121, 120, 119,
+ 118, 117, 78, 78, 210, 210, 210, 210, 210, 210,
+ 210, 211, 116, 113, 112, 211, 211, 212, 212, 212,
+
+ 212, 212, 212, 212, 213, 111, 213, 214, 214, 214,
214, 214, 214, 214, 215, 215, 215, 215, 215, 215,
- 215, 216, 216, 216, 0, 216, 216, 216, 217, 0,
- 217, 0, 217, 217, 217, 218, 218, 218, 218, 218,
- 0, 218, 209, 209, 209, 209, 209, 209, 209, 209,
+ 215, 216, 216, 216, 110, 216, 216, 216, 217, 109,
+ 217, 107, 217, 217, 217, 218, 218, 218, 218, 218,
+ 105, 218, 101, 96, 90, 88, 86, 85, 82, 79,
+ 77, 76, 75, 72, 63, 50, 49, 46, 41, 37,
+ 30, 26, 25, 23, 15, 11, 5, 209, 209, 209,
209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
-
209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
+
209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209
+ 209, 209, 209, 209, 209, 209, 209
} ;
/* The intent behind this definition is that it'll catch
@@ -637,8 +810,6 @@ static yyconst flex_int16_t yy_chk[633] =
#define yymore() yymore_used_but_not_detected
#define YY_MORE_ADJ 0
#define YY_RESTORE_YY_MORE_OFFSET
-#line 1 "cmFortranLexer.in.l"
-#line 2 "cmFortranLexer.in.l"
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
/*-------------------------------------------------------------------------
@@ -657,18 +828,18 @@ This file must be translated to C++ and modified to build everywhere.
Run flex >= 2.6 like this:
- flex -i --nounistd -DFLEXINT_H --prefix=cmFortran_yy --header-file=cmFortranLexer.h -ocmFortranLexer.cxx cmFortranLexer.in.l
+ flex -i --nounistd -DFLEXINT_H --noline --header-file=cmFortranLexer.h -ocmFortranLexer.cxx cmFortranLexer.in.l
Modify cmFortranLexer.cxx:
- - remove trailing whitespace: sed -i 's/\s*$//' cmFortranLexer.h cmFortranLexer.cxx
- - remove blank lines at end of file
- - #include "cmStandardLexer.h" at the top
- - add cast in cmFortran_yy_scan_bytes for loop condition of _yybytes_len to size_t
-
+ - remove trailing whitespace: sed -i 's/\s*$//' cmFortranLexer.h cmFortranLexer.cxx
+ - remove blank lines at end of file: sed -i '${/^$/d;}' cmFortranLexer.h cmFortranLexer.cxx
+ - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmFortranLexer.cxx
*/
/* IWYU pragma: no_forward_declare yyguts_t */
+#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+
#undef YY_NO_UNPUT
#define cmFortranLexer_cxx
@@ -677,16 +848,13 @@ Modify cmFortranLexer.cxx:
/* Replace the lexer input function. */
#undef YY_INPUT
#define YY_INPUT(buf, result, max_size) \
- { result = cmFortranParser_Input(yyextra, buf, max_size); }
+ do { result = cmFortranParser_Input(yyextra, buf, max_size); } while (0)
/* Include the set of tokens from the parser. */
#include "cmFortranParserTokens.h"
/*--------------------------------------------------------------------------*/
-
-#line 688 "cmFortranLexer.cxx"
-
#define INITIAL 0
#define free_fmt 1
#define fixed_fmt 2
@@ -731,44 +899,44 @@ struct yyguts_t
}; /* end struct yyguts_t */
-static int yy_init_globals (yyscan_t yyscanner );
+static int yy_init_globals ( yyscan_t yyscanner );
-int cmFortran_yylex_init (yyscan_t* scanner);
+int yylex_init (yyscan_t* scanner);
-int cmFortran_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
-int cmFortran_yylex_destroy (yyscan_t yyscanner );
+int yylex_destroy ( yyscan_t yyscanner );
-int cmFortran_yyget_debug (yyscan_t yyscanner );
+int yyget_debug ( yyscan_t yyscanner );
-void cmFortran_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+void yyset_debug ( int debug_flag , yyscan_t yyscanner );
-YY_EXTRA_TYPE cmFortran_yyget_extra (yyscan_t yyscanner );
+YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
-void cmFortran_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
-FILE *cmFortran_yyget_in (yyscan_t yyscanner );
+FILE *yyget_in ( yyscan_t yyscanner );
-void cmFortran_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
+void yyset_in ( FILE * _in_str , yyscan_t yyscanner );
-FILE *cmFortran_yyget_out (yyscan_t yyscanner );
+FILE *yyget_out ( yyscan_t yyscanner );
-void cmFortran_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
+void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
- int cmFortran_yyget_leng (yyscan_t yyscanner );
+ int yyget_leng ( yyscan_t yyscanner );
-char *cmFortran_yyget_text (yyscan_t yyscanner );
+char *yyget_text ( yyscan_t yyscanner );
-int cmFortran_yyget_lineno (yyscan_t yyscanner );
+int yyget_lineno ( yyscan_t yyscanner );
-void cmFortran_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+void yyset_lineno ( int _line_number , yyscan_t yyscanner );
-int cmFortran_yyget_column (yyscan_t yyscanner );
+int yyget_column ( yyscan_t yyscanner );
-void cmFortran_yyset_column (int _column_no ,yyscan_t yyscanner );
+void yyset_column ( int _column_no , yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -776,32 +944,31 @@ void cmFortran_yyset_column (int _column_no ,yyscan_t yyscanner );
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
-extern "C" int cmFortran_yywrap (yyscan_t yyscanner );
+extern "C" int yywrap ( yyscan_t yyscanner );
#else
-extern int cmFortran_yywrap (yyscan_t yyscanner );
+extern int yywrap ( yyscan_t yyscanner );
#endif
#endif
#ifndef YY_NO_UNPUT
- static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner);
+ static void yyunput ( int c, char *buf_ptr , yyscan_t yyscanner);
#endif
#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
#endif
#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
#endif
#ifndef YY_NO_INPUT
-
#ifdef __cplusplus
-static int yyinput (yyscan_t yyscanner );
+static int yyinput ( yyscan_t yyscanner );
#else
-static int input (yyscan_t yyscanner );
+static int input ( yyscan_t yyscanner );
#endif
#endif
@@ -832,7 +999,7 @@ static int input (yyscan_t yyscanner );
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
- size_t n; \
+ int n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@@ -845,7 +1012,7 @@ static int input (yyscan_t yyscanner );
else \
{ \
errno=0; \
- while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \
{ \
if( errno != EINTR) \
{ \
@@ -886,9 +1053,9 @@ static int input (yyscan_t yyscanner );
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
-extern int cmFortran_yylex (yyscan_t yyscanner);
+extern int yylex (yyscan_t yyscanner);
-#define YY_DECL int cmFortran_yylex (yyscan_t yyscanner)
+#define YY_DECL int yylex (yyscan_t yyscanner)
#endif /* !YY_DECL */
/* Code executed at the beginning of each rule, after yytext and yyleng
@@ -936,19 +1103,15 @@ YY_DECL
yyout = stdout;
if ( ! YY_CURRENT_BUFFER ) {
- cmFortran_yyensure_buffer_stack (yyscanner);
+ yyensure_buffer_stack (yyscanner);
YY_CURRENT_BUFFER_LVALUE =
- cmFortran_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner);
}
- cmFortran_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
}
{
-#line 56 "cmFortranLexer.in.l"
-
-
-#line 951 "cmFortranLexer.cxx"
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
@@ -977,12 +1140,12 @@ yy_match:
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 210 )
- yy_c = yy_meta[(unsigned int) yy_c];
+ yy_c = yy_meta[yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
++yy_cp;
}
- while ( yy_base[yy_current_state] != 583 );
+ while ( yy_base[yy_current_state] != 468 );
yy_find_action:
yy_act = yy_accept[yy_current_state];
@@ -1008,7 +1171,6 @@ do_action: /* This label is used only to access EOF actions. */
case 1:
YY_RULE_SETUP
-#line 58 "cmFortranLexer.in.l"
{
cmFortranParser_StringStart(yyextra);
cmFortranParser_SetOldStartcond(yyextra, YY_START);
@@ -1017,7 +1179,6 @@ YY_RULE_SETUP
YY_BREAK
case 2:
YY_RULE_SETUP
-#line 64 "cmFortranLexer.in.l"
{
cmFortranParser_StringStart(yyextra);
cmFortranParser_SetOldStartcond(yyextra, YY_START);
@@ -1025,10 +1186,8 @@ YY_RULE_SETUP
}
YY_BREAK
case 3:
-#line 71 "cmFortranLexer.in.l"
case 4:
YY_RULE_SETUP
-#line 71 "cmFortranLexer.in.l"
{
BEGIN(cmFortranParser_GetOldStartcond(yyextra) );
yylvalp->string = strdup(cmFortranParser_StringEnd(yyextra));
@@ -1037,17 +1196,14 @@ YY_RULE_SETUP
YY_BREAK
case 5:
/* rule 5 can match eol */
-#line 78 "cmFortranLexer.in.l"
case 6:
/* rule 6 can match eol */
YY_RULE_SETUP
-#line 78 "cmFortranLexer.in.l"
/* Ignore (continued strings, free fmt) */
YY_BREAK
case 7:
/* rule 7 can match eol */
YY_RULE_SETUP
-#line 80 "cmFortranLexer.in.l"
{
if (cmFortranParser_GetOldStartcond(yyextra) == fixed_fmt)
; /* Ignore (cont. strings, fixed fmt) */
@@ -1060,7 +1216,6 @@ YY_RULE_SETUP
case 8:
/* rule 8 can match eol */
YY_RULE_SETUP
-#line 90 "cmFortranLexer.in.l"
{
unput ('\n');
BEGIN(INITIAL);
@@ -1069,7 +1224,6 @@ YY_RULE_SETUP
YY_BREAK
case 9:
YY_RULE_SETUP
-#line 96 "cmFortranLexer.in.l"
{
cmFortranParser_StringAppend(yyextra, yytext[0]);
}
@@ -1077,24 +1231,20 @@ YY_RULE_SETUP
case 10:
/* rule 10 can match eol */
YY_RULE_SETUP
-#line 100 "cmFortranLexer.in.l"
{ return EOSTMT; } /* Treat comments like */
YY_BREAK
case 11:
/* rule 11 can match eol */
YY_RULE_SETUP
-#line 101 "cmFortranLexer.in.l"
{ return EOSTMT; } /* empty lines */
YY_BREAK
case 12:
YY_RULE_SETUP
-#line 103 "cmFortranLexer.in.l"
{ return CPP_LINE_DIRECTIVE; }
YY_BREAK
case 13:
/* rule 13 can match eol */
YY_RULE_SETUP
-#line 104 "cmFortranLexer.in.l"
{
yytext[yyleng-1] = 0;
yylvalp->string = strdup(strchr(yytext, '<')+1);
@@ -1103,171 +1253,138 @@ YY_RULE_SETUP
YY_BREAK
case 14:
YY_RULE_SETUP
-#line 109 "cmFortranLexer.in.l"
{ return CPP_INCLUDE; }
YY_BREAK
case 15:
YY_RULE_SETUP
-#line 110 "cmFortranLexer.in.l"
{ return F90PPR_INCLUDE; }
YY_BREAK
case 16:
YY_RULE_SETUP
-#line 111 "cmFortranLexer.in.l"
{ return COCO_INCLUDE; }
YY_BREAK
case 17:
YY_RULE_SETUP
-#line 113 "cmFortranLexer.in.l"
{ return CPP_DEFINE; }
YY_BREAK
case 18:
YY_RULE_SETUP
-#line 114 "cmFortranLexer.in.l"
{ return F90PPR_DEFINE; }
YY_BREAK
case 19:
YY_RULE_SETUP
-#line 116 "cmFortranLexer.in.l"
{ return CPP_UNDEF; }
YY_BREAK
case 20:
YY_RULE_SETUP
-#line 117 "cmFortranLexer.in.l"
{ return F90PPR_UNDEF; }
YY_BREAK
case 21:
YY_RULE_SETUP
-#line 119 "cmFortranLexer.in.l"
{ return CPP_IFDEF; }
YY_BREAK
case 22:
YY_RULE_SETUP
-#line 120 "cmFortranLexer.in.l"
{ return CPP_IFNDEF; }
YY_BREAK
case 23:
YY_RULE_SETUP
-#line 121 "cmFortranLexer.in.l"
{ return CPP_IF; }
YY_BREAK
case 24:
YY_RULE_SETUP
-#line 122 "cmFortranLexer.in.l"
{ return CPP_ELIF; }
YY_BREAK
case 25:
YY_RULE_SETUP
-#line 123 "cmFortranLexer.in.l"
{ return CPP_ELSE; }
YY_BREAK
case 26:
YY_RULE_SETUP
-#line 124 "cmFortranLexer.in.l"
{ return CPP_ENDIF; }
YY_BREAK
case 27:
YY_RULE_SETUP
-#line 126 "cmFortranLexer.in.l"
{ return F90PPR_IFDEF; }
YY_BREAK
case 28:
YY_RULE_SETUP
-#line 127 "cmFortranLexer.in.l"
{ return F90PPR_IFNDEF; }
YY_BREAK
case 29:
YY_RULE_SETUP
-#line 128 "cmFortranLexer.in.l"
{ return F90PPR_IF; }
YY_BREAK
case 30:
YY_RULE_SETUP
-#line 129 "cmFortranLexer.in.l"
{ return F90PPR_ELIF; }
YY_BREAK
case 31:
YY_RULE_SETUP
-#line 130 "cmFortranLexer.in.l"
{ return F90PPR_ELSE; }
YY_BREAK
case 32:
YY_RULE_SETUP
-#line 131 "cmFortranLexer.in.l"
{ return F90PPR_ENDIF; }
YY_BREAK
/* Line continuations, possible involving comments. */
case 33:
/* rule 33 can match eol */
YY_RULE_SETUP
-#line 134 "cmFortranLexer.in.l"
YY_BREAK
case 34:
/* rule 34 can match eol */
YY_RULE_SETUP
-#line 135 "cmFortranLexer.in.l"
YY_BREAK
case 35:
YY_RULE_SETUP
-#line 137 "cmFortranLexer.in.l"
{ return COMMA; }
YY_BREAK
case 36:
YY_RULE_SETUP
-#line 139 "cmFortranLexer.in.l"
{ return DCOLON; }
YY_BREAK
case 37:
YY_RULE_SETUP
-#line 140 "cmFortranLexer.in.l"
{ return COLON; }
YY_BREAK
case 38:
/* rule 38 can match eol */
YY_RULE_SETUP
-#line 142 "cmFortranLexer.in.l"
{ return GARBAGE; }
YY_BREAK
case 39:
YY_RULE_SETUP
-#line 144 "cmFortranLexer.in.l"
{ return ASSIGNMENT_OP; }
YY_BREAK
case 40:
YY_RULE_SETUP
-#line 146 "cmFortranLexer.in.l"
{ return END; }
YY_BREAK
case 41:
YY_RULE_SETUP
-#line 147 "cmFortranLexer.in.l"
{ return INCLUDE; }
YY_BREAK
case 42:
YY_RULE_SETUP
-#line 148 "cmFortranLexer.in.l"
{ return INTERFACE; }
YY_BREAK
case 43:
YY_RULE_SETUP
-#line 149 "cmFortranLexer.in.l"
{ return MODULE; }
YY_BREAK
case 44:
YY_RULE_SETUP
-#line 150 "cmFortranLexer.in.l"
{ return SUBMODULE; }
YY_BREAK
case 45:
YY_RULE_SETUP
-#line 151 "cmFortranLexer.in.l"
{ return USE; }
YY_BREAK
case 46:
YY_RULE_SETUP
-#line 153 "cmFortranLexer.in.l"
{
yylvalp->string = strdup(yytext);
return WORD;
@@ -1275,39 +1392,32 @@ YY_RULE_SETUP
YY_BREAK
case 47:
YY_RULE_SETUP
-#line 158 "cmFortranLexer.in.l"
{ return LPAREN; }
YY_BREAK
case 48:
YY_RULE_SETUP
-#line 159 "cmFortranLexer.in.l"
{ return RPAREN; }
YY_BREAK
case 49:
YY_RULE_SETUP
-#line 161 "cmFortranLexer.in.l"
{ return GARBAGE; }
YY_BREAK
case 50:
/* rule 50 can match eol */
YY_RULE_SETUP
-#line 163 "cmFortranLexer.in.l"
{ return EOSTMT; }
YY_BREAK
case 51:
YY_RULE_SETUP
-#line 166 "cmFortranLexer.in.l"
/* Ignore */
YY_BREAK
case 52:
/* rule 52 can match eol */
YY_RULE_SETUP
-#line 167 "cmFortranLexer.in.l"
/* Ignore line-endings preceded by \ */
YY_BREAK
case 53:
YY_RULE_SETUP
-#line 169 "cmFortranLexer.in.l"
{ return *yytext; }
YY_BREAK
case YY_STATE_EOF(INITIAL):
@@ -1315,7 +1425,6 @@ case YY_STATE_EOF(free_fmt):
case YY_STATE_EOF(fixed_fmt):
case YY_STATE_EOF(str_sq):
case YY_STATE_EOF(str_dq):
-#line 171 "cmFortranLexer.in.l"
{
if(!cmFortranParser_FilePop(yyextra) )
{
@@ -1325,10 +1434,8 @@ case YY_STATE_EOF(str_dq):
YY_BREAK
case 54:
YY_RULE_SETUP
-#line 178 "cmFortranLexer.in.l"
ECHO;
YY_BREAK
-#line 1331 "cmFortranLexer.cxx"
case YY_END_OF_BUFFER:
{
@@ -1344,7 +1451,7 @@ ECHO;
/* We're scanning a new file or input source. It's
* possible that this happened because the user
* just pointed yyin at a new source and called
- * cmFortran_yylex(). If so, then we have to assure
+ * yylex(). If so, then we have to assure
* consistency between YY_CURRENT_BUFFER and our
* globals. Here is the right place to do so, because
* this is the first action (other than possibly a
@@ -1404,7 +1511,7 @@ ECHO;
{
yyg->yy_did_buffer_switch_on_eof = 0;
- if ( cmFortran_yywrap(yyscanner ) )
+ if ( yywrap( yyscanner ) )
{
/* Note: because we've taken care in
* yy_get_next_buffer() to have set up
@@ -1458,7 +1565,7 @@ ECHO;
} /* end of action switch */
} /* end of scanning one token */
} /* end of user's declarations */
-} /* end of cmFortran_yylex */
+} /* end of yylex */
/* yy_get_next_buffer - try to read in a new buffer
*
@@ -1472,7 +1579,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
char *source = yyg->yytext_ptr;
- yy_size_t number_to_move, i;
+ int number_to_move, i;
int ret_val;
if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
@@ -1501,7 +1608,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
/* Try to read more data. */
/* First move last chars to start of buffer. */
- number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1);
for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++);
@@ -1537,7 +1644,8 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
b->yy_ch_buf = (char *)
/* Include room in for 2 EOB chars. */
- cmFortran_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+ yyrealloc( (void *) b->yy_ch_buf,
+ (yy_size_t) (b->yy_buf_size + 2) , yyscanner );
}
else
/* Can't grow it, we don't own it. */
@@ -1569,7 +1677,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ( number_to_move == YY_MORE_ADJ )
{
ret_val = EOB_ACT_END_OF_FILE;
- cmFortran_yyrestart(yyin ,yyscanner);
+ yyrestart( yyin , yyscanner);
}
else
@@ -1583,12 +1691,15 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
ret_val = EOB_ACT_CONTINUE_SCAN;
- if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
/* Extend the array by 50%, plus the number we really need. */
int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) cmFortran_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
+ (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner );
if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ /* "- 2" to take care of EOB's */
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
}
yyg->yy_n_chars += number_to_move;
@@ -1623,9 +1734,9 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 210 )
- yy_c = yy_meta[(unsigned int) yy_c];
+ yy_c = yy_meta[yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
}
return yy_current_state;
@@ -1652,9 +1763,9 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 210 )
- yy_c = yy_meta[(unsigned int) yy_c];
+ yy_c = yy_meta[yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
yy_is_jam = (yy_current_state == 209);
(void)yyg;
@@ -1728,7 +1839,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{ /* need more input */
- int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+ int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr);
++yyg->yy_c_buf_p;
switch ( yy_get_next_buffer( yyscanner ) )
@@ -1745,13 +1856,13 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
*/
/* Reset buffer status. */
- cmFortran_yyrestart(yyin ,yyscanner);
+ yyrestart( yyin , yyscanner);
/*FALLTHROUGH*/
case EOB_ACT_END_OF_FILE:
{
- if ( cmFortran_yywrap(yyscanner ) )
+ if ( yywrap( yyscanner ) )
return 0;
if ( ! yyg->yy_did_buffer_switch_on_eof )
@@ -1785,34 +1896,34 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @note This function does not reset the start condition to @c INITIAL .
*/
- void cmFortran_yyrestart (FILE * input_file , yyscan_t yyscanner)
+ void yyrestart (FILE * input_file , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if ( ! YY_CURRENT_BUFFER ){
- cmFortran_yyensure_buffer_stack (yyscanner);
+ yyensure_buffer_stack (yyscanner);
YY_CURRENT_BUFFER_LVALUE =
- cmFortran_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner);
}
- cmFortran_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
- cmFortran_yy_load_buffer_state(yyscanner );
+ yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner);
+ yy_load_buffer_state( yyscanner );
}
/** Switch to a different input buffer.
* @param new_buffer The new input buffer.
* @param yyscanner The scanner object.
*/
- void cmFortran_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* TODO. We should be able to replace this entire function body
* with
- * cmFortran_yypop_buffer_state();
- * cmFortran_yypush_buffer_state(new_buffer);
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
*/
- cmFortran_yyensure_buffer_stack (yyscanner);
+ yyensure_buffer_stack (yyscanner);
if ( YY_CURRENT_BUFFER == new_buffer )
return;
@@ -1825,17 +1936,17 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
}
YY_CURRENT_BUFFER_LVALUE = new_buffer;
- cmFortran_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
/* We don't actually know whether we did this switch during
- * EOF (cmFortran_yywrap()) processing, but the only time this flag
- * is looked at is after cmFortran_yywrap() is called, so it's safe
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
* to go ahead and always set it.
*/
yyg->yy_did_buffer_switch_on_eof = 1;
}
-static void cmFortran_yy_load_buffer_state (yyscan_t yyscanner)
+static void yy_load_buffer_state (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
@@ -1850,35 +1961,35 @@ static void cmFortran_yy_load_buffer_state (yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @return the allocated buffer state.
*/
- YY_BUFFER_STATE cmFortran_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
- b = (YY_BUFFER_STATE) cmFortran_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner );
if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmFortran_yy_create_buffer()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
- b->yy_buf_size = (yy_size_t)size;
+ b->yy_buf_size = size;
/* yy_ch_buf has to be 2 characters longer than the size given because
* we need to put in 2 end-of-buffer characters.
*/
- b->yy_ch_buf = (char *) cmFortran_yyalloc(b->yy_buf_size + 2 ,yyscanner );
+ b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner );
if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmFortran_yy_create_buffer()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
b->yy_is_our_buffer = 1;
- cmFortran_yy_init_buffer(b,file ,yyscanner);
+ yy_init_buffer( b, file , yyscanner);
return b;
}
/** Destroy the buffer.
- * @param b a buffer created with cmFortran_yy_create_buffer()
+ * @param b a buffer created with yy_create_buffer()
* @param yyscanner The scanner object.
*/
- void cmFortran_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+ void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -1889,28 +2000,28 @@ static void cmFortran_yy_load_buffer_state (yyscan_t yyscanner)
YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
if ( b->yy_is_our_buffer )
- cmFortran_yyfree((void *) b->yy_ch_buf ,yyscanner );
+ yyfree( (void *) b->yy_ch_buf , yyscanner );
- cmFortran_yyfree((void *) b ,yyscanner );
+ yyfree( (void *) b , yyscanner );
}
/* Initializes or reinitializes a buffer.
* This function is sometimes called more than once on the same buffer,
- * such as during a cmFortran_yyrestart() or at EOF.
+ * such as during a yyrestart() or at EOF.
*/
- static void cmFortran_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
{
int oerrno = errno;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- cmFortran_yy_flush_buffer(b ,yyscanner);
+ yy_flush_buffer( b , yyscanner);
b->yy_input_file = file;
b->yy_fill_buffer = 1;
- /* If b is the current buffer, then cmFortran_yy_init_buffer was _probably_
- * called from cmFortran_yyrestart() or through yy_get_next_buffer.
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
* In that case, we don't want to reset the lineno or column.
*/
if (b != YY_CURRENT_BUFFER){
@@ -1927,7 +2038,7 @@ static void cmFortran_yy_load_buffer_state (yyscan_t yyscanner)
* @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
* @param yyscanner The scanner object.
*/
- void cmFortran_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+ void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if ( ! b )
@@ -1948,7 +2059,7 @@ static void cmFortran_yy_load_buffer_state (yyscan_t yyscanner)
b->yy_buffer_status = YY_BUFFER_NEW;
if ( b == YY_CURRENT_BUFFER )
- cmFortran_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
}
/** Pushes the new state onto the stack. The new state becomes
@@ -1957,15 +2068,15 @@ static void cmFortran_yy_load_buffer_state (yyscan_t yyscanner)
* @param new_buffer The new state.
* @param yyscanner The scanner object.
*/
-void cmFortran_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (new_buffer == NULL)
return;
- cmFortran_yyensure_buffer_stack(yyscanner);
+ yyensure_buffer_stack(yyscanner);
- /* This block is copied from cmFortran_yy_switch_to_buffer. */
+ /* This block is copied from yy_switch_to_buffer. */
if ( YY_CURRENT_BUFFER )
{
/* Flush out information for old buffer. */
@@ -1979,8 +2090,8 @@ void cmFortran_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscan
yyg->yy_buffer_stack_top++;
YY_CURRENT_BUFFER_LVALUE = new_buffer;
- /* copied from cmFortran_yy_switch_to_buffer. */
- cmFortran_yy_load_buffer_state(yyscanner );
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state( yyscanner );
yyg->yy_did_buffer_switch_on_eof = 1;
}
@@ -1988,19 +2099,19 @@ void cmFortran_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscan
* The next element becomes the new top.
* @param yyscanner The scanner object.
*/
-void cmFortran_yypop_buffer_state (yyscan_t yyscanner)
+void yypop_buffer_state (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (!YY_CURRENT_BUFFER)
return;
- cmFortran_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+ yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner);
YY_CURRENT_BUFFER_LVALUE = NULL;
if (yyg->yy_buffer_stack_top > 0)
--yyg->yy_buffer_stack_top;
if (YY_CURRENT_BUFFER) {
- cmFortran_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
yyg->yy_did_buffer_switch_on_eof = 1;
}
}
@@ -2008,9 +2119,9 @@ void cmFortran_yypop_buffer_state (yyscan_t yyscanner)
/* Allocates the stack if it does not exist.
* Guarantees space for at least one push.
*/
-static void cmFortran_yyensure_buffer_stack (yyscan_t yyscanner)
+static void yyensure_buffer_stack (yyscan_t yyscanner)
{
- int num_to_alloc;
+ yy_size_t num_to_alloc;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (!yyg->yy_buffer_stack) {
@@ -2020,11 +2131,11 @@ static void cmFortran_yyensure_buffer_stack (yyscan_t yyscanner)
* immediate realloc on the next call.
*/
num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmFortran_yyalloc
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
(num_to_alloc * sizeof(struct yy_buffer_state*)
, yyscanner);
if ( ! yyg->yy_buffer_stack )
- YY_FATAL_ERROR( "out of dynamic memory in cmFortran_yyensure_buffer_stack()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
@@ -2039,12 +2150,12 @@ static void cmFortran_yyensure_buffer_stack (yyscan_t yyscanner)
yy_size_t grow_size = 8 /* arbitrary grow size */;
num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmFortran_yyrealloc
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
(yyg->yy_buffer_stack,
num_to_alloc * sizeof(struct yy_buffer_state*)
, yyscanner);
if ( ! yyg->yy_buffer_stack )
- YY_FATAL_ERROR( "out of dynamic memory in cmFortran_yyensure_buffer_stack()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
/* zero only the new slots.*/
memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
@@ -2058,7 +2169,7 @@ static void cmFortran_yyensure_buffer_stack (yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
-YY_BUFFER_STATE cmFortran_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
@@ -2068,11 +2179,11 @@ YY_BUFFER_STATE cmFortran_yy_scan_buffer (char * base, yy_size_t size , yyscan
/* They forgot to leave room for the EOB's. */
return NULL;
- b = (YY_BUFFER_STATE) cmFortran_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner );
if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmFortran_yy_scan_buffer()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
- b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */
b->yy_buf_pos = b->yy_ch_buf = base;
b->yy_is_our_buffer = 0;
b->yy_input_file = NULL;
@@ -2082,53 +2193,53 @@ YY_BUFFER_STATE cmFortran_yy_scan_buffer (char * base, yy_size_t size , yyscan
b->yy_fill_buffer = 0;
b->yy_buffer_status = YY_BUFFER_NEW;
- cmFortran_yy_switch_to_buffer(b ,yyscanner );
+ yy_switch_to_buffer( b , yyscanner );
return b;
}
-/** Setup the input buffer state to scan a string. The next call to cmFortran_yylex() will
+/** Setup the input buffer state to scan a string. The next call to yylex() will
* scan from a @e copy of @a str.
* @param yystr a NUL-terminated string to scan
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
* @note If you want to scan bytes that may contain NUL values, then use
- * cmFortran_yy_scan_bytes() instead.
+ * yy_scan_bytes() instead.
*/
-YY_BUFFER_STATE cmFortran_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner)
{
- return cmFortran_yy_scan_bytes(yystr,(int) strlen(yystr) ,yyscanner);
+ return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner);
}
-/** Setup the input buffer state to scan the given bytes. The next call to cmFortran_yylex() will
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
* scan from a @e copy of @a bytes.
* @param yybytes the byte buffer to scan
* @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
-YY_BUFFER_STATE cmFortran_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
char *buf;
yy_size_t n;
- yy_size_t i;
+ int i;
/* Get memory for full buffer, including space for trailing EOB's. */
- n = (yy_size_t) _yybytes_len + 2;
- buf = (char *) cmFortran_yyalloc(n ,yyscanner );
+ n = (yy_size_t) (_yybytes_len + 2);
+ buf = (char *) yyalloc( n , yyscanner );
if ( ! buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmFortran_yy_scan_bytes()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
- for ( i = 0; i < (size_t)_yybytes_len; ++i )
+ for ( i = 0; i < _yybytes_len; ++i )
buf[i] = yybytes[i];
buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
- b = cmFortran_yy_scan_buffer(buf,n ,yyscanner);
+ b = yy_scan_buffer( buf, n , yyscanner);
if ( ! b )
- YY_FATAL_ERROR( "bad buffer in cmFortran_yy_scan_bytes()" );
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
/* It's okay to grow etc. this buffer, and we should throw it
* away when we're done.
@@ -2142,11 +2253,11 @@ YY_BUFFER_STATE cmFortran_yy_scan_bytes (yyconst char * yybytes, int _yybytes_
#define YY_EXIT_FAILURE 2
#endif
-static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
- (void) fprintf( stderr, "%s\n", msg );
+ fprintf( stderr, "%s\n", msg );
exit( YY_EXIT_FAILURE );
}
@@ -2172,7 +2283,7 @@ static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
/** Get the user-defined data for this scanner.
* @param yyscanner The scanner object.
*/
-YY_EXTRA_TYPE cmFortran_yyget_extra (yyscan_t yyscanner)
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyextra;
@@ -2181,7 +2292,7 @@ YY_EXTRA_TYPE cmFortran_yyget_extra (yyscan_t yyscanner)
/** Get the current line number.
* @param yyscanner The scanner object.
*/
-int cmFortran_yyget_lineno (yyscan_t yyscanner)
+int yyget_lineno (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -2194,7 +2305,7 @@ int cmFortran_yyget_lineno (yyscan_t yyscanner)
/** Get the current column number.
* @param yyscanner The scanner object.
*/
-int cmFortran_yyget_column (yyscan_t yyscanner)
+int yyget_column (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -2207,7 +2318,7 @@ int cmFortran_yyget_column (yyscan_t yyscanner)
/** Get the input stream.
* @param yyscanner The scanner object.
*/
-FILE *cmFortran_yyget_in (yyscan_t yyscanner)
+FILE *yyget_in (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyin;
@@ -2216,7 +2327,7 @@ FILE *cmFortran_yyget_in (yyscan_t yyscanner)
/** Get the output stream.
* @param yyscanner The scanner object.
*/
-FILE *cmFortran_yyget_out (yyscan_t yyscanner)
+FILE *yyget_out (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyout;
@@ -2225,7 +2336,7 @@ FILE *cmFortran_yyget_out (yyscan_t yyscanner)
/** Get the length of the current token.
* @param yyscanner The scanner object.
*/
-int cmFortran_yyget_leng (yyscan_t yyscanner)
+int yyget_leng (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyleng;
@@ -2235,7 +2346,7 @@ int cmFortran_yyget_leng (yyscan_t yyscanner)
* @param yyscanner The scanner object.
*/
-char *cmFortran_yyget_text (yyscan_t yyscanner)
+char *yyget_text (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yytext;
@@ -2245,7 +2356,7 @@ char *cmFortran_yyget_text (yyscan_t yyscanner)
* @param user_defined The data to be associated with this scanner.
* @param yyscanner The scanner object.
*/
-void cmFortran_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
+void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyextra = user_defined ;
@@ -2255,13 +2366,13 @@ void cmFortran_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
* @param _line_number line number
* @param yyscanner The scanner object.
*/
-void cmFortran_yyset_lineno (int _line_number , yyscan_t yyscanner)
+void yyset_lineno (int _line_number , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* lineno is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
- YY_FATAL_ERROR( "cmFortran_yyset_lineno called with no buffer" );
+ YY_FATAL_ERROR( "yyset_lineno called with no buffer" );
yylineno = _line_number;
}
@@ -2270,13 +2381,13 @@ void cmFortran_yyset_lineno (int _line_number , yyscan_t yyscanner)
* @param _column_no column number
* @param yyscanner The scanner object.
*/
-void cmFortran_yyset_column (int _column_no , yyscan_t yyscanner)
+void yyset_column (int _column_no , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* column is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
- YY_FATAL_ERROR( "cmFortran_yyset_column called with no buffer" );
+ YY_FATAL_ERROR( "yyset_column called with no buffer" );
yycolumn = _column_no;
}
@@ -2285,27 +2396,27 @@ void cmFortran_yyset_column (int _column_no , yyscan_t yyscanner)
* input buffer.
* @param _in_str A readable stream.
* @param yyscanner The scanner object.
- * @see cmFortran_yy_switch_to_buffer
+ * @see yy_switch_to_buffer
*/
-void cmFortran_yyset_in (FILE * _in_str , yyscan_t yyscanner)
+void yyset_in (FILE * _in_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyin = _in_str ;
}
-void cmFortran_yyset_out (FILE * _out_str , yyscan_t yyscanner)
+void yyset_out (FILE * _out_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyout = _out_str ;
}
-int cmFortran_yyget_debug (yyscan_t yyscanner)
+int yyget_debug (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yy_flex_debug;
}
-void cmFortran_yyset_debug (int _bdebug , yyscan_t yyscanner)
+void yyset_debug (int _bdebug , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yy_flex_debug = _bdebug ;
@@ -2315,20 +2426,18 @@ void cmFortran_yyset_debug (int _bdebug , yyscan_t yyscanner)
/* User-visible API */
-/* cmFortran_yylex_init is special because it creates the scanner itself, so it is
+/* yylex_init is special because it creates the scanner itself, so it is
* the ONLY reentrant function that doesn't take the scanner as the last argument.
* That's why we explicitly handle the declaration, instead of using our macros.
*/
-
-int cmFortran_yylex_init(yyscan_t* ptr_yy_globals)
-
+int yylex_init(yyscan_t* ptr_yy_globals)
{
if (ptr_yy_globals == NULL){
errno = EINVAL;
return 1;
}
- *ptr_yy_globals = (yyscan_t) cmFortran_yyalloc ( sizeof( struct yyguts_t ), NULL );
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
if (*ptr_yy_globals == NULL){
errno = ENOMEM;
@@ -2341,27 +2450,25 @@ int cmFortran_yylex_init(yyscan_t* ptr_yy_globals)
return yy_init_globals ( *ptr_yy_globals );
}
-/* cmFortran_yylex_init_extra has the same functionality as cmFortran_yylex_init, but follows the
+/* yylex_init_extra has the same functionality as yylex_init, but follows the
* convention of taking the scanner as the last argument. Note however, that
* this is a *pointer* to a scanner, as it will be allocated by this call (and
* is the reason, too, why this function also must handle its own declaration).
- * The user defined value in the first argument will be available to cmFortran_yyalloc in
+ * The user defined value in the first argument will be available to yyalloc in
* the yyextra field.
*/
-
-int cmFortran_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
-
+int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals )
{
struct yyguts_t dummy_yyguts;
- cmFortran_yyset_extra (yy_user_defined, &dummy_yyguts);
+ yyset_extra (yy_user_defined, &dummy_yyguts);
if (ptr_yy_globals == NULL){
errno = EINVAL;
return 1;
}
- *ptr_yy_globals = (yyscan_t) cmFortran_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
if (*ptr_yy_globals == NULL){
errno = ENOMEM;
@@ -2372,7 +2479,7 @@ int cmFortran_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_gl
yy_init_globals. Leave at 0x00 for releases. */
memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
- cmFortran_yyset_extra (yy_user_defined, *ptr_yy_globals);
+ yyset_extra (yy_user_defined, *ptr_yy_globals);
return yy_init_globals ( *ptr_yy_globals );
}
@@ -2381,7 +2488,7 @@ static int yy_init_globals (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* Initialization is the same as for the non-reentrant scanner.
- * This function is called from cmFortran_yylex_destroy(), so don't allocate here.
+ * This function is called from yylex_destroy(), so don't allocate here.
*/
yyg->yy_buffer_stack = NULL;
@@ -2405,37 +2512,37 @@ static int yy_init_globals (yyscan_t yyscanner)
#endif
/* For future reference: Set errno on error, since we are called by
- * cmFortran_yylex_init()
+ * yylex_init()
*/
return 0;
}
-/* cmFortran_yylex_destroy is for both reentrant and non-reentrant scanners. */
-int cmFortran_yylex_destroy (yyscan_t yyscanner)
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* Pop the buffer stack, destroying each element. */
while(YY_CURRENT_BUFFER){
- cmFortran_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+ yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner );
YY_CURRENT_BUFFER_LVALUE = NULL;
- cmFortran_yypop_buffer_state(yyscanner);
+ yypop_buffer_state(yyscanner);
}
/* Destroy the stack itself. */
- cmFortran_yyfree(yyg->yy_buffer_stack ,yyscanner);
+ yyfree(yyg->yy_buffer_stack , yyscanner);
yyg->yy_buffer_stack = NULL;
/* Destroy the start condition stack. */
- cmFortran_yyfree(yyg->yy_start_stack ,yyscanner );
+ yyfree( yyg->yy_start_stack , yyscanner );
yyg->yy_start_stack = NULL;
/* Reset the globals. This is important in a non-reentrant scanner so the next time
- * cmFortran_yylex() is called, initialization will occur. */
+ * yylex() is called, initialization will occur. */
yy_init_globals( yyscanner);
/* Destroy the main struct (reentrant only). */
- cmFortran_yyfree ( yyscanner , yyscanner );
+ yyfree ( yyscanner , yyscanner );
yyscanner = NULL;
return 0;
}
@@ -2445,7 +2552,7 @@ int cmFortran_yylex_destroy (yyscan_t yyscanner)
*/
#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
@@ -2457,7 +2564,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca
#endif
#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+static int yy_flex_strlen (const char * s , yyscan_t yyscanner)
{
int n;
for ( n = 0; s[n]; ++n )
@@ -2467,14 +2574,14 @@ static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
}
#endif
-void *cmFortran_yyalloc (yy_size_t size , yyscan_t yyscanner)
+void *yyalloc (yy_size_t size , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
return malloc(size);
}
-void *cmFortran_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
+void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
@@ -2489,19 +2596,15 @@ void *cmFortran_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
return realloc(ptr, size);
}
-void cmFortran_yyfree (void * ptr , yyscan_t yyscanner)
+void yyfree (void * ptr , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
- free( (char *) ptr ); /* see cmFortran_yyrealloc() for (char *) cast */
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
}
#define YYTABLES_NAME "yytables"
-#line 178 "cmFortranLexer.in.l"
-
-
-
/*--------------------------------------------------------------------------*/
YY_BUFFER_STATE cmFortranLexer_GetCurrentBuffer(yyscan_t yyscanner)
{
@@ -2509,3 +2612,5 @@ YY_BUFFER_STATE cmFortranLexer_GetCurrentBuffer(yyscan_t yyscanner)
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return YY_CURRENT_BUFFER;
}
+
+#endif /* __clang_analyzer__ */
diff --git a/Source/LexerParser/cmFortranLexer.h b/Source/LexerParser/cmFortranLexer.h
index ddda91965..7bb9b4434 100644
--- a/Source/LexerParser/cmFortranLexer.h
+++ b/Source/LexerParser/cmFortranLexer.h
@@ -2,10 +2,6 @@
#define cmFortran_yyHEADER_H 1
#define cmFortran_yyIN_HEADER 1
-#line 6 "cmFortranLexer.h"
-
-#line 8 "cmFortranLexer.h"
-
#define FLEXINT_H 1
#define YY_INT_ALIGNED short int
@@ -14,11 +10,221 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6
-#define YY_FLEX_SUBMINOR_VERSION 1
+#define YY_FLEX_SUBMINOR_VERSION 4
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
+#ifdef yy_create_buffer
+#define cmFortran_yy_create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer cmFortran_yy_create_buffer
+#endif
+
+#ifdef yy_delete_buffer
+#define cmFortran_yy_delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer cmFortran_yy_delete_buffer
+#endif
+
+#ifdef yy_scan_buffer
+#define cmFortran_yy_scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer cmFortran_yy_scan_buffer
+#endif
+
+#ifdef yy_scan_string
+#define cmFortran_yy_scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string cmFortran_yy_scan_string
+#endif
+
+#ifdef yy_scan_bytes
+#define cmFortran_yy_scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes cmFortran_yy_scan_bytes
+#endif
+
+#ifdef yy_init_buffer
+#define cmFortran_yy_init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer cmFortran_yy_init_buffer
+#endif
+
+#ifdef yy_flush_buffer
+#define cmFortran_yy_flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer cmFortran_yy_flush_buffer
+#endif
+
+#ifdef yy_load_buffer_state
+#define cmFortran_yy_load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state cmFortran_yy_load_buffer_state
+#endif
+
+#ifdef yy_switch_to_buffer
+#define cmFortran_yy_switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer cmFortran_yy_switch_to_buffer
+#endif
+
+#ifdef yypush_buffer_state
+#define cmFortran_yypush_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state cmFortran_yypush_buffer_state
+#endif
+
+#ifdef yypop_buffer_state
+#define cmFortran_yypop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state cmFortran_yypop_buffer_state
+#endif
+
+#ifdef yyensure_buffer_stack
+#define cmFortran_yyensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack cmFortran_yyensure_buffer_stack
+#endif
+
+#ifdef yylex
+#define cmFortran_yylex_ALREADY_DEFINED
+#else
+#define yylex cmFortran_yylex
+#endif
+
+#ifdef yyrestart
+#define cmFortran_yyrestart_ALREADY_DEFINED
+#else
+#define yyrestart cmFortran_yyrestart
+#endif
+
+#ifdef yylex_init
+#define cmFortran_yylex_init_ALREADY_DEFINED
+#else
+#define yylex_init cmFortran_yylex_init
+#endif
+
+#ifdef yylex_init_extra
+#define cmFortran_yylex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra cmFortran_yylex_init_extra
+#endif
+
+#ifdef yylex_destroy
+#define cmFortran_yylex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy cmFortran_yylex_destroy
+#endif
+
+#ifdef yyget_debug
+#define cmFortran_yyget_debug_ALREADY_DEFINED
+#else
+#define yyget_debug cmFortran_yyget_debug
+#endif
+
+#ifdef yyset_debug
+#define cmFortran_yyset_debug_ALREADY_DEFINED
+#else
+#define yyset_debug cmFortran_yyset_debug
+#endif
+
+#ifdef yyget_extra
+#define cmFortran_yyget_extra_ALREADY_DEFINED
+#else
+#define yyget_extra cmFortran_yyget_extra
+#endif
+
+#ifdef yyset_extra
+#define cmFortran_yyset_extra_ALREADY_DEFINED
+#else
+#define yyset_extra cmFortran_yyset_extra
+#endif
+
+#ifdef yyget_in
+#define cmFortran_yyget_in_ALREADY_DEFINED
+#else
+#define yyget_in cmFortran_yyget_in
+#endif
+
+#ifdef yyset_in
+#define cmFortran_yyset_in_ALREADY_DEFINED
+#else
+#define yyset_in cmFortran_yyset_in
+#endif
+
+#ifdef yyget_out
+#define cmFortran_yyget_out_ALREADY_DEFINED
+#else
+#define yyget_out cmFortran_yyget_out
+#endif
+
+#ifdef yyset_out
+#define cmFortran_yyset_out_ALREADY_DEFINED
+#else
+#define yyset_out cmFortran_yyset_out
+#endif
+
+#ifdef yyget_leng
+#define cmFortran_yyget_leng_ALREADY_DEFINED
+#else
+#define yyget_leng cmFortran_yyget_leng
+#endif
+
+#ifdef yyget_text
+#define cmFortran_yyget_text_ALREADY_DEFINED
+#else
+#define yyget_text cmFortran_yyget_text
+#endif
+
+#ifdef yyget_lineno
+#define cmFortran_yyget_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno cmFortran_yyget_lineno
+#endif
+
+#ifdef yyset_lineno
+#define cmFortran_yyset_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno cmFortran_yyset_lineno
+#endif
+
+#ifdef yyget_column
+#define cmFortran_yyget_column_ALREADY_DEFINED
+#else
+#define yyget_column cmFortran_yyget_column
+#endif
+
+#ifdef yyset_column
+#define cmFortran_yyset_column_ALREADY_DEFINED
+#else
+#define yyset_column cmFortran_yyset_column
+#endif
+
+#ifdef yywrap
+#define cmFortran_yywrap_ALREADY_DEFINED
+#else
+#define yywrap cmFortran_yywrap
+#endif
+
+#ifdef yyalloc
+#define cmFortran_yyalloc_ALREADY_DEFINED
+#else
+#define yyalloc cmFortran_yyalloc
+#endif
+
+#ifdef yyrealloc
+#define cmFortran_yyrealloc_ALREADY_DEFINED
+#else
+#define yyrealloc cmFortran_yyrealloc
+#endif
+
+#ifdef yyfree
+#define cmFortran_yyfree_ALREADY_DEFINED
+#else
+#define yyfree cmFortran_yyfree
+#endif
+
/* First, we deal with platform-specific or compiler-specific issues. */
/* begin standard C headers. */
@@ -89,10 +295,16 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
+#ifndef SIZE_MAX
+#define SIZE_MAX (~(size_t)0)
+#endif
+
#endif /* ! C99 */
#endif /* ! FLEXINT_H */
+/* begin standard C++ headers. */
+
/* TODO: this is always defined, so inline it */
#define yyconst const
@@ -193,21 +405,21 @@ struct yy_buffer_state
};
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-void cmFortran_yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void cmFortran_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmFortran_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void cmFortran_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmFortran_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmFortran_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void cmFortran_yypop_buffer_state (yyscan_t yyscanner );
+void yyrestart ( FILE *input_file , yyscan_t yyscanner );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
+void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+void yypop_buffer_state ( yyscan_t yyscanner );
-YY_BUFFER_STATE cmFortran_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmFortran_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmFortran_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
-void *cmFortran_yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *cmFortran_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void cmFortran_yyfree (void * ,yyscan_t yyscanner );
+void *yyalloc ( yy_size_t , yyscan_t yyscanner );
+void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
+void yyfree ( void * , yyscan_t yyscanner );
/* Begin user sect3 */
@@ -229,42 +441,42 @@ void cmFortran_yyfree (void * ,yyscan_t yyscanner );
#define YY_EXTRA_TYPE void *
#endif
-int cmFortran_yylex_init (yyscan_t* scanner);
+int yylex_init (yyscan_t* scanner);
-int cmFortran_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
-int cmFortran_yylex_destroy (yyscan_t yyscanner );
+int yylex_destroy ( yyscan_t yyscanner );
-int cmFortran_yyget_debug (yyscan_t yyscanner );
+int yyget_debug ( yyscan_t yyscanner );
-void cmFortran_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+void yyset_debug ( int debug_flag , yyscan_t yyscanner );
-YY_EXTRA_TYPE cmFortran_yyget_extra (yyscan_t yyscanner );
+YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
-void cmFortran_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
-FILE *cmFortran_yyget_in (yyscan_t yyscanner );
+FILE *yyget_in ( yyscan_t yyscanner );
-void cmFortran_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
+void yyset_in ( FILE * _in_str , yyscan_t yyscanner );
-FILE *cmFortran_yyget_out (yyscan_t yyscanner );
+FILE *yyget_out ( yyscan_t yyscanner );
-void cmFortran_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
+void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
- int cmFortran_yyget_leng (yyscan_t yyscanner );
+ int yyget_leng ( yyscan_t yyscanner );
-char *cmFortran_yyget_text (yyscan_t yyscanner );
+char *yyget_text ( yyscan_t yyscanner );
-int cmFortran_yyget_lineno (yyscan_t yyscanner );
+int yyget_lineno ( yyscan_t yyscanner );
-void cmFortran_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+void yyset_lineno ( int _line_number , yyscan_t yyscanner );
-int cmFortran_yyget_column (yyscan_t yyscanner );
+int yyget_column ( yyscan_t yyscanner );
-void cmFortran_yyset_column (int _column_no ,yyscan_t yyscanner );
+void yyset_column ( int _column_no , yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -272,18 +484,18 @@ void cmFortran_yyset_column (int _column_no ,yyscan_t yyscanner );
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
-extern "C" int cmFortran_yywrap (yyscan_t yyscanner );
+extern "C" int yywrap ( yyscan_t yyscanner );
#else
-extern int cmFortran_yywrap (yyscan_t yyscanner );
+extern int yywrap ( yyscan_t yyscanner );
#endif
#endif
#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
#endif
#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
#endif
#ifndef YY_NO_INPUT
@@ -311,9 +523,9 @@ static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
-extern int cmFortran_yylex (yyscan_t yyscanner);
+extern int yylex (yyscan_t yyscanner);
-#define YY_DECL int cmFortran_yylex (yyscan_t yyscanner)
+#define YY_DECL int yylex (yyscan_t yyscanner)
#endif /* !YY_DECL */
/* yy_get_previous_state - get the state just before the EOB char was reached */
@@ -330,9 +542,150 @@ extern int cmFortran_yylex (yyscan_t yyscanner);
#undef YY_DECL
#endif
-#line 178 "cmFortranLexer.in.l"
-
+#ifndef cmFortran_yy_create_buffer_ALREADY_DEFINED
+#undef yy_create_buffer
+#endif
+#ifndef cmFortran_yy_delete_buffer_ALREADY_DEFINED
+#undef yy_delete_buffer
+#endif
+#ifndef cmFortran_yy_scan_buffer_ALREADY_DEFINED
+#undef yy_scan_buffer
+#endif
+#ifndef cmFortran_yy_scan_string_ALREADY_DEFINED
+#undef yy_scan_string
+#endif
+#ifndef cmFortran_yy_scan_bytes_ALREADY_DEFINED
+#undef yy_scan_bytes
+#endif
+#ifndef cmFortran_yy_init_buffer_ALREADY_DEFINED
+#undef yy_init_buffer
+#endif
+#ifndef cmFortran_yy_flush_buffer_ALREADY_DEFINED
+#undef yy_flush_buffer
+#endif
+#ifndef cmFortran_yy_load_buffer_state_ALREADY_DEFINED
+#undef yy_load_buffer_state
+#endif
+#ifndef cmFortran_yy_switch_to_buffer_ALREADY_DEFINED
+#undef yy_switch_to_buffer
+#endif
+#ifndef cmFortran_yypush_buffer_state_ALREADY_DEFINED
+#undef yypush_buffer_state
+#endif
+#ifndef cmFortran_yypop_buffer_state_ALREADY_DEFINED
+#undef yypop_buffer_state
+#endif
+#ifndef cmFortran_yyensure_buffer_stack_ALREADY_DEFINED
+#undef yyensure_buffer_stack
+#endif
+#ifndef cmFortran_yylex_ALREADY_DEFINED
+#undef yylex
+#endif
+#ifndef cmFortran_yyrestart_ALREADY_DEFINED
+#undef yyrestart
+#endif
+#ifndef cmFortran_yylex_init_ALREADY_DEFINED
+#undef yylex_init
+#endif
+#ifndef cmFortran_yylex_init_extra_ALREADY_DEFINED
+#undef yylex_init_extra
+#endif
+#ifndef cmFortran_yylex_destroy_ALREADY_DEFINED
+#undef yylex_destroy
+#endif
+#ifndef cmFortran_yyget_debug_ALREADY_DEFINED
+#undef yyget_debug
+#endif
+#ifndef cmFortran_yyset_debug_ALREADY_DEFINED
+#undef yyset_debug
+#endif
+#ifndef cmFortran_yyget_extra_ALREADY_DEFINED
+#undef yyget_extra
+#endif
+#ifndef cmFortran_yyset_extra_ALREADY_DEFINED
+#undef yyset_extra
+#endif
+#ifndef cmFortran_yyget_in_ALREADY_DEFINED
+#undef yyget_in
+#endif
+#ifndef cmFortran_yyset_in_ALREADY_DEFINED
+#undef yyset_in
+#endif
+#ifndef cmFortran_yyget_out_ALREADY_DEFINED
+#undef yyget_out
+#endif
+#ifndef cmFortran_yyset_out_ALREADY_DEFINED
+#undef yyset_out
+#endif
+#ifndef cmFortran_yyget_leng_ALREADY_DEFINED
+#undef yyget_leng
+#endif
+#ifndef cmFortran_yyget_text_ALREADY_DEFINED
+#undef yyget_text
+#endif
+#ifndef cmFortran_yyget_lineno_ALREADY_DEFINED
+#undef yyget_lineno
+#endif
+#ifndef cmFortran_yyset_lineno_ALREADY_DEFINED
+#undef yyset_lineno
+#endif
+#ifndef cmFortran_yyget_column_ALREADY_DEFINED
+#undef yyget_column
+#endif
+#ifndef cmFortran_yyset_column_ALREADY_DEFINED
+#undef yyset_column
+#endif
+#ifndef cmFortran_yywrap_ALREADY_DEFINED
+#undef yywrap
+#endif
+#ifndef cmFortran_yyget_lval_ALREADY_DEFINED
+#undef yyget_lval
+#endif
+#ifndef cmFortran_yyset_lval_ALREADY_DEFINED
+#undef yyset_lval
+#endif
+#ifndef cmFortran_yyget_lloc_ALREADY_DEFINED
+#undef yyget_lloc
+#endif
+#ifndef cmFortran_yyset_lloc_ALREADY_DEFINED
+#undef yyset_lloc
+#endif
+#ifndef cmFortran_yyalloc_ALREADY_DEFINED
+#undef yyalloc
+#endif
+#ifndef cmFortran_yyrealloc_ALREADY_DEFINED
+#undef yyrealloc
+#endif
+#ifndef cmFortran_yyfree_ALREADY_DEFINED
+#undef yyfree
+#endif
+#ifndef cmFortran_yytext_ALREADY_DEFINED
+#undef yytext
+#endif
+#ifndef cmFortran_yyleng_ALREADY_DEFINED
+#undef yyleng
+#endif
+#ifndef cmFortran_yyin_ALREADY_DEFINED
+#undef yyin
+#endif
+#ifndef cmFortran_yyout_ALREADY_DEFINED
+#undef yyout
+#endif
+#ifndef cmFortran_yy_flex_debug_ALREADY_DEFINED
+#undef yy_flex_debug
+#endif
+#ifndef cmFortran_yylineno_ALREADY_DEFINED
+#undef yylineno
+#endif
+#ifndef cmFortran_yytables_fload_ALREADY_DEFINED
+#undef yytables_fload
+#endif
+#ifndef cmFortran_yytables_destroy_ALREADY_DEFINED
+#undef yytables_destroy
+#endif
+#ifndef cmFortran_yyTABLES_NAME_ALREADY_DEFINED
+#undef yyTABLES_NAME
+#endif
-#line 337 "cmFortranLexer.h"
#undef cmFortran_yyIN_HEADER
#endif /* cmFortran_yyHEADER_H */
diff --git a/Source/LexerParser/cmFortranLexer.in.l b/Source/LexerParser/cmFortranLexer.in.l
index 112121037..3d38a7dad 100644
--- a/Source/LexerParser/cmFortranLexer.in.l
+++ b/Source/LexerParser/cmFortranLexer.in.l
@@ -17,18 +17,18 @@ This file must be translated to C++ and modified to build everywhere.
Run flex >= 2.6 like this:
- flex -i --nounistd -DFLEXINT_H --prefix=cmFortran_yy --header-file=cmFortranLexer.h -ocmFortranLexer.cxx cmFortranLexer.in.l
+ flex -i --nounistd -DFLEXINT_H --noline --header-file=cmFortranLexer.h -ocmFortranLexer.cxx cmFortranLexer.in.l
Modify cmFortranLexer.cxx:
- - remove trailing whitespace: sed -i 's/\s*$//' cmFortranLexer.h cmFortranLexer.cxx
- - remove blank lines at end of file
- - #include "cmStandardLexer.h" at the top
- - add cast in yy_scan_bytes for loop condition of _yybytes_len to size_t
-
+ - remove trailing whitespace: sed -i 's/\s*$//' cmFortranLexer.h cmFortranLexer.cxx
+ - remove blank lines at end of file: sed -i '${/^$/d;}' cmFortranLexer.h cmFortranLexer.cxx
+ - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmFortranLexer.cxx
*/
/* IWYU pragma: no_forward_declare yyguts_t */
+#ifndef __clang_analyzer__ /* Suppress clang scan-build warnings */
+
#undef YY_NO_UNPUT
#define cmFortranLexer_cxx
@@ -37,7 +37,7 @@ Modify cmFortranLexer.cxx:
/* Replace the lexer input function. */
#undef YY_INPUT
#define YY_INPUT(buf, result, max_size) \
- { result = cmFortranParser_Input(yyextra, buf, max_size); }
+ do { result = cmFortranParser_Input(yyextra, buf, max_size); } while (0)
/* Include the set of tokens from the parser. */
#include "cmFortranParserTokens.h"
@@ -45,6 +45,7 @@ Modify cmFortranLexer.cxx:
/*--------------------------------------------------------------------------*/
%}
+%option prefix="cmFortran_yy"
%option reentrant
%option noyywrap
@@ -147,7 +148,7 @@ $[ \t]*endif { return F90PPR_ENDIF; }
[Ii][Nn][Cc][Ll][Uu][Dd][Ee] { return INCLUDE; }
[Ii][Nn][Tt][Ee][Rr][Ff][Aa][Cc][Ee] { return INTERFACE; }
[Mm][Oo][Dd][Uu][Ll][Ee] { return MODULE; }
-[Ss][Uu][bb][Mm][Oo][Dd][Uu][Ll][Ee] { return SUBMODULE; }
+[Ss][Uu][Bb][Mm][Oo][Dd][Uu][Ll][Ee] { return SUBMODULE; }
[Uu][Ss][Ee] { return USE; }
[a-zA-Z_][a-zA-Z_0-9]* {
@@ -184,3 +185,5 @@ YY_BUFFER_STATE cmFortranLexer_GetCurrentBuffer(yyscan_t yyscanner)
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return YY_CURRENT_BUFFER;
}
+
+#endif /* __clang_analyzer__ */
diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx
index 2b3452f2e..2ca79276d 100644
--- a/Source/LexerParser/cmFortranParser.cxx
+++ b/Source/LexerParser/cmFortranParser.cxx
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4. */
+/* A Bison parser, made by GNU Bison 3.3.2. */
/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+ Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -40,11 +41,14 @@
define necessary library symbols; they are noted "INFRINGES ON
USER NAME SPACE" below. */
+/* Undocumented macros, especially those whose name start with YY_,
+ are private implementation details. Do not rely on them. */
+
/* Identify Bison output. */
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "3.0.4"
+#define YYBISON_VERSION "3.3.2"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -67,8 +71,8 @@
#define yynerrs cmFortran_yynerrs
-/* Copy the first part of user declarations. */
-#line 1 "cmFortranParser.y" /* yacc.c:339 */
+/* First part of user prologue. */
+#line 1 "cmFortranParser.y" /* yacc.c:337 */
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
@@ -127,14 +131,20 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message)
# pragma warning (disable: 4127) /* Conditional expression is constant. */
# pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */
#endif
+#if defined(__GNUC__) && __GNUC__ >= 8
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif
-#line 132 "cmFortranParser.cxx" /* yacc.c:339 */
-
+#line 139 "cmFortranParser.cxx" /* yacc.c:337 */
# ifndef YY_NULLPTR
-# if defined __cplusplus && 201103L <= __cplusplus
-# define YY_NULLPTR nullptr
+# if defined __cplusplus
+# if 201103L <= __cplusplus
+# define YY_NULLPTR nullptr
+# else
+# define YY_NULLPTR 0
+# endif
# else
-# define YY_NULLPTR 0
+# define YY_NULLPTR ((void*)0)
# endif
# endif
@@ -248,11 +258,11 @@ extern int cmFortran_yydebug;
union YYSTYPE
{
-#line 70 "cmFortranParser.y" /* yacc.c:355 */
+#line 73 "cmFortranParser.y" /* yacc.c:352 */
char* string;
-#line 256 "cmFortranParser.cxx" /* yacc.c:355 */
+#line 266 "cmFortranParser.cxx" /* yacc.c:352 */
};
typedef union YYSTYPE YYSTYPE;
@@ -266,9 +276,7 @@ int cmFortran_yyparse (yyscan_t yyscanner);
#endif /* !YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED */
-/* Copy the second part of user declarations. */
-#line 272 "cmFortranParser.cxx" /* yacc.c:358 */
#ifdef short
# undef short
@@ -289,13 +297,13 @@ typedef signed char yytype_int8;
#ifdef YYTYPE_UINT16
typedef YYTYPE_UINT16 yytype_uint16;
#else
-typedef unsigned short int yytype_uint16;
+typedef unsigned short yytype_uint16;
#endif
#ifdef YYTYPE_INT16
typedef YYTYPE_INT16 yytype_int16;
#else
-typedef short int yytype_int16;
+typedef short yytype_int16;
#endif
#ifndef YYSIZE_T
@@ -307,7 +315,7 @@ typedef short int yytype_int16;
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
-# define YYSIZE_T unsigned int
+# define YYSIZE_T unsigned
# endif
#endif
@@ -343,15 +351,6 @@ typedef short int yytype_int16;
# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
#endif
-#if !defined _Noreturn \
- && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
-# if defined _MSC_VER && 1200 <= _MSC_VER
-# define _Noreturn __declspec (noreturn)
-# else
-# define _Noreturn YY_ATTRIBUTE ((__noreturn__))
-# endif
-#endif
-
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
# define YYUSE(E) ((void) (E))
@@ -359,7 +358,7 @@ typedef short int yytype_int16;
# define YYUSE(E) /* empty */
#endif
-#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
_Pragma ("GCC diagnostic push") \
@@ -521,16 +520,16 @@ union yyalloc
/* YYNSTATES -- Number of states. */
#define YYNSTATES 126
-/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
- by yylex, with out-of-bounds checking. */
#define YYUNDEFTOK 2
#define YYMAXUTOK 295
+/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, with out-of-bounds checking. */
#define YYTRANSLATE(YYX) \
- ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+ ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
- as returned by yylex, without out-of-bounds checking. */
+ as returned by yylex. */
static const yytype_uint8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -569,13 +568,13 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 98, 98, 98, 101, 105, 110, 119, 125, 132,
- 137, 141, 146, 154, 159, 164, 169, 174, 179, 184,
- 189, 194, 198, 202, 206, 210, 211, 216, 216, 216,
- 217, 217, 218, 218, 219, 219, 220, 220, 221, 221,
- 222, 222, 223, 223, 224, 224, 225, 225, 228, 229,
- 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
- 240, 241, 242, 243
+ 0, 101, 101, 101, 104, 108, 113, 122, 128, 135,
+ 140, 144, 149, 157, 162, 167, 172, 177, 182, 187,
+ 192, 197, 201, 205, 209, 213, 214, 219, 219, 219,
+ 220, 220, 221, 221, 222, 222, 223, 223, 224, 224,
+ 225, 225, 226, 226, 227, 227, 228, 228, 231, 232,
+ 233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
+ 243, 244, 245, 246
};
#endif
@@ -860,22 +859,22 @@ static const yytype_uint8 yyr2[] =
#define YYRECOVERING() (!!yyerrstatus)
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- YYPOPSTACK (yylen); \
- yystate = *yyssp; \
- goto yybackup; \
- } \
- else \
- { \
- yyerror (yyscanner, YY_("syntax error: cannot back up")); \
- YYERROR; \
- } \
-while (0)
+#define YYBACKUP(Token, Value) \
+ do \
+ if (yychar == YYEMPTY) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ YYPOPSTACK (yylen); \
+ yystate = *yyssp; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (yyscanner, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+ while (0)
/* Error token number */
#define YYTERROR 1
@@ -915,38 +914,38 @@ do { \
} while (0)
-/*----------------------------------------.
-| Print this symbol's value on YYOUTPUT. |
-`----------------------------------------*/
+/*-----------------------------------.
+| Print this symbol's value on YYO. |
+`-----------------------------------*/
static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
- FILE *yyo = yyoutput;
- YYUSE (yyo);
+ FILE *yyoutput = yyo;
+ YYUSE (yyoutput);
YYUSE (yyscanner);
if (!yyvaluep)
return;
# ifdef YYPRINT
if (yytype < YYNTOKENS)
- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+ YYPRINT (yyo, yytoknum[yytype], *yyvaluep);
# endif
YYUSE (yytype);
}
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
+/*---------------------------.
+| Print this symbol on YYO. |
+`---------------------------*/
static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
+yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner)
{
- YYFPRINTF (yyoutput, "%s %s (",
+ YYFPRINTF (yyo, "%s %s (",
yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
- yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner);
- YYFPRINTF (yyoutput, ")");
+ yy_symbol_value_print (yyo, yytype, yyvaluep, yyscanner);
+ YYFPRINTF (yyo, ")");
}
/*------------------------------------------------------------------.
@@ -980,7 +979,7 @@ do { \
static void
yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner)
{
- unsigned long int yylno = yyrline[yyrule];
+ unsigned long yylno = yyrline[yyrule];
int yynrhs = yyr2[yyrule];
int yyi;
YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
@@ -991,7 +990,7 @@ yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yysca
YYFPRINTF (stderr, " $%d = ", yyi + 1);
yy_symbol_print (stderr,
yystos[yyssp[yyi + 1 - yynrhs]],
- &(yyvsp[(yyi + 1) - (yynrhs)])
+ &yyvsp[(yyi + 1) - (yynrhs)]
, yyscanner);
YYFPRINTF (stderr, "\n");
}
@@ -1095,7 +1094,10 @@ yytnamerr (char *yyres, const char *yystr)
case '\\':
if (*++yyp != '\\')
goto do_not_strip_quotes;
- /* Fall through. */
+ else
+ goto append;
+
+ append:
default:
if (yyres)
yyres[yyn] = *yyp;
@@ -1113,7 +1115,7 @@ yytnamerr (char *yyres, const char *yystr)
if (! yyres)
return yystrlen (yystr);
- return yystpcpy (yyres, yystr) - yyres;
+ return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres);
}
# endif
@@ -1191,10 +1193,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
yyarg[yycount++] = yytname[yyx];
{
YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
- if (! (yysize <= yysize1
- && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+ yysize = yysize1;
+ else
return 2;
- yysize = yysize1;
}
}
}
@@ -1206,6 +1208,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
case N: \
yyformat = S; \
break
+ default: /* Avoid compiler warnings. */
YYCASE_(0, YY_("syntax error"));
YYCASE_(1, YY_("syntax error, unexpected %s"));
YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
@@ -1217,9 +1220,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
{
YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
- if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)
+ yysize = yysize1;
+ else
return 2;
- yysize = yysize1;
}
if (*yymsg_alloc < yysize)
@@ -1350,23 +1354,31 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
yychar = YYEMPTY; /* Cause a token to be read. */
goto yysetstate;
+
/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate. |
+| yynewstate -- push a new state, which is found in yystate. |
`------------------------------------------------------------*/
- yynewstate:
+yynewstate:
/* In all cases, when you get here, the value and location stacks
have just been pushed. So pushing a state here evens the stacks. */
yyssp++;
- yysetstate:
- *yyssp = yystate;
+
+/*--------------------------------------------------------------------.
+| yynewstate -- set current state (the top of the stack) to yystate. |
+`--------------------------------------------------------------------*/
+yysetstate:
+ *yyssp = (yytype_int16) yystate;
if (yyss + yystacksize - 1 <= yyssp)
+#if !defined yyoverflow && !defined YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+#else
{
/* Get the current used size of the three stacks, in elements. */
- YYSIZE_T yysize = yyssp - yyss + 1;
+ YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1);
-#ifdef yyoverflow
+# if defined yyoverflow
{
/* Give user a chance to reallocate the stack. Use copies of
these so that the &'s don't force the real ones into
@@ -1382,14 +1394,10 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
&yyss1, yysize * sizeof (*yyssp),
&yyvs1, yysize * sizeof (*yyvsp),
&yystacksize);
-
yyss = yyss1;
yyvs = yyvs1;
}
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
- goto yyexhaustedlab;
-# else
+# else /* defined YYSTACK_RELOCATE */
/* Extend the stack our own way. */
if (YYMAXDEPTH <= yystacksize)
goto yyexhaustedlab;
@@ -1405,22 +1413,22 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
goto yyexhaustedlab;
YYSTACK_RELOCATE (yyss_alloc, yyss);
YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-# undef YYSTACK_RELOCATE
+# undef YYSTACK_RELOCATE
if (yyss1 != yyssa)
YYSTACK_FREE (yyss1);
}
# endif
-#endif /* no yyoverflow */
yyssp = yyss + yysize - 1;
yyvsp = yyvs + yysize - 1;
YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long int) yystacksize));
+ (unsigned long) yystacksize));
if (yyss + yystacksize - 1 <= yyssp)
YYABORT;
}
+#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
@@ -1429,11 +1437,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
goto yybackup;
+
/*-----------.
| yybackup. |
`-----------*/
yybackup:
-
/* Do appropriate processing given the current state. Read a
lookahead token if we need one and don't already have one. */
@@ -1506,7 +1514,7 @@ yydefault:
/*-----------------------------.
-| yyreduce -- Do a reduction. |
+| yyreduce -- do a reduction. |
`-----------------------------*/
yyreduce:
/* yyn is the number of a rule to reduce with. */
@@ -1527,26 +1535,26 @@ yyreduce:
switch (yyn)
{
case 4:
-#line 101 "cmFortranParser.y" /* yacc.c:1646 */
+#line 104 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_SetInInterface(parser, true);
}
-#line 1536 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1544 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 5:
-#line 105 "cmFortranParser.y" /* yacc.c:1646 */
+#line 108 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1546 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1554 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 6:
-#line 110 "cmFortranParser.y" /* yacc.c:1646 */
+#line 113 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 &&
@@ -1556,63 +1564,63 @@ yyreduce:
}
free((yyvsp[-2].string));
}
-#line 1560 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1568 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 7:
-#line 119 "cmFortranParser.y" /* yacc.c:1646 */
+#line 122 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
- cmFortranParser_RuleUse(parser, (yyvsp[-4].string));
+ cmFortranParser_RuleSubmodule(parser, (yyvsp[-4].string), (yyvsp[-2].string));
free((yyvsp[-4].string));
free((yyvsp[-2].string));
}
-#line 1571 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1579 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 8:
-#line 125 "cmFortranParser.y" /* yacc.c:1646 */
+#line 128 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
- cmFortranParser_RuleUse(parser, (yyvsp[-6].string));
+ cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string));
free((yyvsp[-6].string));
free((yyvsp[-4].string));
free((yyvsp[-2].string));
}
-#line 1583 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1591 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 9:
-#line 132 "cmFortranParser.y" /* yacc.c:1646 */
+#line 135 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_SetInInterface(parser, true);
free((yyvsp[-2].string));
}
-#line 1593 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1601 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 10:
-#line 137 "cmFortranParser.y" /* yacc.c:1646 */
+#line 140 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_SetInInterface(parser, false);
}
-#line 1602 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1610 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 11:
-#line 141 "cmFortranParser.y" /* yacc.c:1646 */
+#line 144 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1612 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1620 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 12:
-#line 146 "cmFortranParser.y" /* yacc.c:1646 */
+#line 149 "cmFortranParser.y" /* yacc.c:1652 */
{
if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
@@ -1621,139 +1629,139 @@ yyreduce:
free((yyvsp[-4].string));
free((yyvsp[-2].string));
}
-#line 1625 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1633 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 13:
-#line 154 "cmFortranParser.y" /* yacc.c:1646 */
+#line 157 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1635 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1643 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 14:
-#line 159 "cmFortranParser.y" /* yacc.c:1646 */
+#line 162 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1645 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1653 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 15:
-#line 164 "cmFortranParser.y" /* yacc.c:1646 */
+#line 167 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1655 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1663 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 16:
-#line 169 "cmFortranParser.y" /* yacc.c:1646 */
+#line 172 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1665 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1673 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 17:
-#line 174 "cmFortranParser.y" /* yacc.c:1646 */
+#line 177 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleDefine(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1675 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1683 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 18:
-#line 179 "cmFortranParser.y" /* yacc.c:1646 */
+#line 182 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUndef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1685 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1693 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 19:
-#line 184 "cmFortranParser.y" /* yacc.c:1646 */
+#line 187 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1695 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1703 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 20:
-#line 189 "cmFortranParser.y" /* yacc.c:1646 */
+#line 192 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1705 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1713 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 21:
-#line 194 "cmFortranParser.y" /* yacc.c:1646 */
+#line 197 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIf(parser);
}
-#line 1714 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1722 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 22:
-#line 198 "cmFortranParser.y" /* yacc.c:1646 */
+#line 201 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleElif(parser);
}
-#line 1723 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1731 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 23:
-#line 202 "cmFortranParser.y" /* yacc.c:1646 */
+#line 205 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleElse(parser);
}
-#line 1732 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1740 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 24:
-#line 206 "cmFortranParser.y" /* yacc.c:1646 */
+#line 209 "cmFortranParser.y" /* yacc.c:1652 */
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleEndif(parser);
}
-#line 1741 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1749 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 48:
-#line 228 "cmFortranParser.y" /* yacc.c:1646 */
+#line 231 "cmFortranParser.y" /* yacc.c:1652 */
{ free ((yyvsp[0].string)); }
-#line 1747 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1755 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
case 55:
-#line 235 "cmFortranParser.y" /* yacc.c:1646 */
+#line 238 "cmFortranParser.y" /* yacc.c:1652 */
{ free ((yyvsp[0].string)); }
-#line 1753 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1761 "cmFortranParser.cxx" /* yacc.c:1652 */
break;
-#line 1757 "cmFortranParser.cxx" /* yacc.c:1646 */
+#line 1765 "cmFortranParser.cxx" /* yacc.c:1652 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -1778,14 +1786,13 @@ yyreduce:
/* Now 'shift' the result of the reduction. Determine what state
that goes to, based on the state we popped back to and the rule
number reduced by. */
-
- yyn = yyr1[yyn];
-
- yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
- if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
- yystate = yytable[yystate];
- else
- yystate = yydefgoto[yyn - YYNTOKENS];
+ {
+ const int yylhs = yyr1[yyn] - YYNTOKENS;
+ const int yyi = yypgoto[yylhs] + *yyssp;
+ yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp
+ ? yytable[yyi]
+ : yydefgoto[yylhs]);
+ }
goto yynewstate;
@@ -1869,12 +1876,10 @@ yyerrlab:
| yyerrorlab -- error raised explicitly by YYERROR. |
`---------------------------------------------------*/
yyerrorlab:
-
- /* Pacify compilers like GCC when the user code never invokes
- YYERROR and the label yyerrorlab therefore never appears in user
- code. */
- if (/*CONSTCOND*/ 0)
- goto yyerrorlab;
+ /* Pacify compilers when the user code never invokes YYERROR and the
+ label yyerrorlab therefore never appears in user code. */
+ if (0)
+ YYERROR;
/* Do not reclaim the symbols of the rule whose action triggered
this YYERROR. */
@@ -1937,6 +1942,7 @@ yyacceptlab:
yyresult = 0;
goto yyreturn;
+
/*-----------------------------------.
| yyabortlab -- YYABORT comes here. |
`-----------------------------------*/
@@ -1944,6 +1950,7 @@ yyabortlab:
yyresult = 1;
goto yyreturn;
+
#if !defined yyoverflow || YYERROR_VERBOSE
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
@@ -1954,6 +1961,10 @@ yyexhaustedlab:
/* Fall through. */
#endif
+
+/*-----------------------------------------------------.
+| yyreturn -- parsing is finished, return the result. |
+`-----------------------------------------------------*/
yyreturn:
if (yychar != YYEMPTY)
{
@@ -1983,6 +1994,6 @@ yyreturn:
#endif
return yyresult;
}
-#line 246 "cmFortranParser.y" /* yacc.c:1906 */
+#line 249 "cmFortranParser.y" /* yacc.c:1918 */
/* End of grammar */
diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y
index acfb40ad8..87f3e0a16 100644
--- a/Source/LexerParser/cmFortranParser.y
+++ b/Source/LexerParser/cmFortranParser.y
@@ -56,6 +56,9 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message)
# pragma warning (disable: 4127) /* Conditional expression is constant. */
# pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */
#endif
+#if defined(__GNUC__) && __GNUC__ >= 8
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif
%}
/* Generate a reentrant parser object. */
@@ -118,13 +121,13 @@ stmt:
}
| SUBMODULE LPAREN WORD RPAREN WORD other EOSTMT {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
- cmFortranParser_RuleUse(parser, $3);
+ cmFortranParser_RuleSubmodule(parser, $3, $5);
free($3);
free($5);
}
| SUBMODULE LPAREN WORD COLON WORD RPAREN WORD other EOSTMT {
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
- cmFortranParser_RuleUse(parser, $3);
+ cmFortranParser_RuleSubmoduleNested(parser, $3, $5, $7);
free($3);
free($5);
free($7);
diff --git a/Source/LexerParser/cmFortranParserTokens.h b/Source/LexerParser/cmFortranParserTokens.h
index 8d6a5fe5a..0da4c1c43 100644
--- a/Source/LexerParser/cmFortranParserTokens.h
+++ b/Source/LexerParser/cmFortranParserTokens.h
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.4. */
+/* A Bison parser, made by GNU Bison 3.3.2. */
/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation,
+ Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,6 +31,9 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
+/* Undocumented macros, especially those whose name start with YY_,
+ are private implementation details. Do not rely on them. */
+
#ifndef YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
# define YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED
/* Debug traces. */
@@ -130,11 +134,11 @@ extern int cmFortran_yydebug;
union YYSTYPE
{
-#line 70 "cmFortranParser.y" /* yacc.c:1909 */
+#line 73 "cmFortranParser.y" /* yacc.c:1921 */
char* string;
-#line 138 "cmFortranParserTokens.h" /* yacc.c:1909 */
+#line 142 "cmFortranParserTokens.h" /* yacc.c:1921 */
};
typedef union YYSTYPE YYSTYPE;
diff --git a/Source/LexerParser/cmListFileLexer.c b/Source/LexerParser/cmListFileLexer.c
index 3dd3b85b9..15dcda04a 100644
--- a/Source/LexerParser/cmListFileLexer.c
+++ b/Source/LexerParser/cmListFileLexer.c
@@ -1,7 +1,4 @@
#include "cmStandardLexer.h"
-#line 2 "cmListFileLexer.c"
-
-#line 4 "cmListFileLexer.c"
#define FLEXINT_H 1
#define YY_INT_ALIGNED short int
@@ -11,11 +8,221 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6
-#define YY_FLEX_SUBMINOR_VERSION 1
+#define YY_FLEX_SUBMINOR_VERSION 4
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
+#ifdef yy_create_buffer
+#define cmListFileLexer_yy_create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer cmListFileLexer_yy_create_buffer
+#endif
+
+#ifdef yy_delete_buffer
+#define cmListFileLexer_yy_delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer cmListFileLexer_yy_delete_buffer
+#endif
+
+#ifdef yy_scan_buffer
+#define cmListFileLexer_yy_scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer cmListFileLexer_yy_scan_buffer
+#endif
+
+#ifdef yy_scan_string
+#define cmListFileLexer_yy_scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string cmListFileLexer_yy_scan_string
+#endif
+
+#ifdef yy_scan_bytes
+#define cmListFileLexer_yy_scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes cmListFileLexer_yy_scan_bytes
+#endif
+
+#ifdef yy_init_buffer
+#define cmListFileLexer_yy_init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer cmListFileLexer_yy_init_buffer
+#endif
+
+#ifdef yy_flush_buffer
+#define cmListFileLexer_yy_flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer cmListFileLexer_yy_flush_buffer
+#endif
+
+#ifdef yy_load_buffer_state
+#define cmListFileLexer_yy_load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state cmListFileLexer_yy_load_buffer_state
+#endif
+
+#ifdef yy_switch_to_buffer
+#define cmListFileLexer_yy_switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer cmListFileLexer_yy_switch_to_buffer
+#endif
+
+#ifdef yypush_buffer_state
+#define cmListFileLexer_yypush_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state cmListFileLexer_yypush_buffer_state
+#endif
+
+#ifdef yypop_buffer_state
+#define cmListFileLexer_yypop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state cmListFileLexer_yypop_buffer_state
+#endif
+
+#ifdef yyensure_buffer_stack
+#define cmListFileLexer_yyensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack cmListFileLexer_yyensure_buffer_stack
+#endif
+
+#ifdef yylex
+#define cmListFileLexer_yylex_ALREADY_DEFINED
+#else
+#define yylex cmListFileLexer_yylex
+#endif
+
+#ifdef yyrestart
+#define cmListFileLexer_yyrestart_ALREADY_DEFINED
+#else
+#define yyrestart cmListFileLexer_yyrestart
+#endif
+
+#ifdef yylex_init
+#define cmListFileLexer_yylex_init_ALREADY_DEFINED
+#else
+#define yylex_init cmListFileLexer_yylex_init
+#endif
+
+#ifdef yylex_init_extra
+#define cmListFileLexer_yylex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra cmListFileLexer_yylex_init_extra
+#endif
+
+#ifdef yylex_destroy
+#define cmListFileLexer_yylex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy cmListFileLexer_yylex_destroy
+#endif
+
+#ifdef yyget_debug
+#define cmListFileLexer_yyget_debug_ALREADY_DEFINED
+#else
+#define yyget_debug cmListFileLexer_yyget_debug
+#endif
+
+#ifdef yyset_debug
+#define cmListFileLexer_yyset_debug_ALREADY_DEFINED
+#else
+#define yyset_debug cmListFileLexer_yyset_debug
+#endif
+
+#ifdef yyget_extra
+#define cmListFileLexer_yyget_extra_ALREADY_DEFINED
+#else
+#define yyget_extra cmListFileLexer_yyget_extra
+#endif
+
+#ifdef yyset_extra
+#define cmListFileLexer_yyset_extra_ALREADY_DEFINED
+#else
+#define yyset_extra cmListFileLexer_yyset_extra
+#endif
+
+#ifdef yyget_in
+#define cmListFileLexer_yyget_in_ALREADY_DEFINED
+#else
+#define yyget_in cmListFileLexer_yyget_in
+#endif
+
+#ifdef yyset_in
+#define cmListFileLexer_yyset_in_ALREADY_DEFINED
+#else
+#define yyset_in cmListFileLexer_yyset_in
+#endif
+
+#ifdef yyget_out
+#define cmListFileLexer_yyget_out_ALREADY_DEFINED
+#else
+#define yyget_out cmListFileLexer_yyget_out
+#endif
+
+#ifdef yyset_out
+#define cmListFileLexer_yyset_out_ALREADY_DEFINED
+#else
+#define yyset_out cmListFileLexer_yyset_out
+#endif
+
+#ifdef yyget_leng
+#define cmListFileLexer_yyget_leng_ALREADY_DEFINED
+#else
+#define yyget_leng cmListFileLexer_yyget_leng
+#endif
+
+#ifdef yyget_text
+#define cmListFileLexer_yyget_text_ALREADY_DEFINED
+#else
+#define yyget_text cmListFileLexer_yyget_text
+#endif
+
+#ifdef yyget_lineno
+#define cmListFileLexer_yyget_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno cmListFileLexer_yyget_lineno
+#endif
+
+#ifdef yyset_lineno
+#define cmListFileLexer_yyset_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno cmListFileLexer_yyset_lineno
+#endif
+
+#ifdef yyget_column
+#define cmListFileLexer_yyget_column_ALREADY_DEFINED
+#else
+#define yyget_column cmListFileLexer_yyget_column
+#endif
+
+#ifdef yyset_column
+#define cmListFileLexer_yyset_column_ALREADY_DEFINED
+#else
+#define yyset_column cmListFileLexer_yyset_column
+#endif
+
+#ifdef yywrap
+#define cmListFileLexer_yywrap_ALREADY_DEFINED
+#else
+#define yywrap cmListFileLexer_yywrap
+#endif
+
+#ifdef yyalloc
+#define cmListFileLexer_yyalloc_ALREADY_DEFINED
+#else
+#define yyalloc cmListFileLexer_yyalloc
+#endif
+
+#ifdef yyrealloc
+#define cmListFileLexer_yyrealloc_ALREADY_DEFINED
+#else
+#define yyrealloc cmListFileLexer_yyrealloc
+#endif
+
+#ifdef yyfree
+#define cmListFileLexer_yyfree_ALREADY_DEFINED
+#else
+#define yyfree cmListFileLexer_yyfree
+#endif
+
/* First, we deal with platform-specific or compiler-specific issues. */
/* begin standard C headers. */
@@ -86,10 +293,16 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
+#ifndef SIZE_MAX
+#define SIZE_MAX (~(size_t)0)
+#endif
+
#endif /* ! C99 */
#endif /* ! FLEXINT_H */
+/* begin standard C++ headers. */
+
/* TODO: this is always defined, so inline it */
#define yyconst const
@@ -102,12 +315,10 @@ typedef unsigned int flex_uint32_t;
/* Returned upon end-of-file. */
#define YY_NULL 0
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index. If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
+/* Promotes a possibly negative, possibly signed char to an
+ * integer in range [0..255] for use as an array index.
*/
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+#define YY_SC_TO_UI(c) ((YY_CHAR) (c))
/* An opaque pointer. */
#ifndef YY_TYPEDEF_YY_SCANNER_T
@@ -131,20 +342,16 @@ typedef void* yyscan_t;
* definition of BEGIN.
*/
#define BEGIN yyg->yy_start = 1 + 2 *
-
/* Translate the current start state into a value that can be later handed
* to BEGIN to return to the state. The YYSTATE alias is for lex
* compatibility.
*/
#define YY_START ((yyg->yy_start - 1) / 2)
#define YYSTATE YY_START
-
/* Action number for EOF rule of a given start state. */
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE cmListFileLexer_yyrestart(yyin ,yyscanner )
-
+#define YY_NEW_FILE yyrestart( yyin , yyscanner )
#define YY_END_OF_BUFFER_CHAR 0
/* Size of default input buffer. */
@@ -180,7 +387,7 @@ typedef size_t yy_size_t;
/* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
* access to the local variable yy_act. Since yyless() is a macro, it would break
- * existing scanners that call yyless() from OUTSIDE cmListFileLexer_yylex.
+ * existing scanners that call yyless() from OUTSIDE yylex.
* One obvious solution it to make yy_act a global. I tried that, and saw
* a 5% performance hit in a non-yylineno scanner, because yy_act is
* normally declared as a register variable-- so it is not worth it.
@@ -213,7 +420,6 @@ typedef size_t yy_size_t;
YY_DO_BEFORE_ACTION; /* set up yytext again */ \
} \
while ( 0 )
-
#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
#ifndef YY_STRUCT_YY_BUFFER_STATE
@@ -273,7 +479,7 @@ struct yy_buffer_state
* possible backing-up.
*
* When we actually see the EOF, we change the status to "new"
- * (via cmListFileLexer_yyrestart()), so that the user can continue scanning by
+ * (via yyrestart()), so that the user can continue scanning by
* just pointing yyin at a new input file.
*/
#define YY_BUFFER_EOF_PENDING 2
@@ -290,73 +496,67 @@ struct yy_buffer_state
#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
: NULL)
-
/* Same as previous macro, but useful when we know that the buffer stack is not
* NULL or when we need an lvalue. For internal use only.
*/
#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
-void cmListFileLexer_yyrestart (FILE *input_file ,yyscan_t yyscanner );
-void cmListFileLexer_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmListFileLexer_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
-void cmListFileLexer_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmListFileLexer_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
-void cmListFileLexer_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
-void cmListFileLexer_yypop_buffer_state (yyscan_t yyscanner );
-
-static void cmListFileLexer_yyensure_buffer_stack (yyscan_t yyscanner );
-static void cmListFileLexer_yy_load_buffer_state (yyscan_t yyscanner );
-static void cmListFileLexer_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+void yyrestart ( FILE *input_file , yyscan_t yyscanner );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
+void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+void yypop_buffer_state ( yyscan_t yyscanner );
-#define YY_FLUSH_BUFFER cmListFileLexer_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+static void yyensure_buffer_stack ( yyscan_t yyscanner );
+static void yy_load_buffer_state ( yyscan_t yyscanner );
+static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner );
+#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner)
-YY_BUFFER_STATE cmListFileLexer_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmListFileLexer_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
-YY_BUFFER_STATE cmListFileLexer_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
-void *cmListFileLexer_yyalloc (yy_size_t ,yyscan_t yyscanner );
-void *cmListFileLexer_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
-void cmListFileLexer_yyfree (void * ,yyscan_t yyscanner );
-
-#define yy_new_buffer cmListFileLexer_yy_create_buffer
+void *yyalloc ( yy_size_t , yyscan_t yyscanner );
+void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
+void yyfree ( void * , yyscan_t yyscanner );
+#define yy_new_buffer yy_create_buffer
#define yy_set_interactive(is_interactive) \
{ \
if ( ! YY_CURRENT_BUFFER ){ \
- cmListFileLexer_yyensure_buffer_stack (yyscanner); \
+ yyensure_buffer_stack (yyscanner); \
YY_CURRENT_BUFFER_LVALUE = \
- cmListFileLexer_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
} \
YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
}
-
#define yy_set_bol(at_bol) \
{ \
if ( ! YY_CURRENT_BUFFER ){\
- cmListFileLexer_yyensure_buffer_stack (yyscanner); \
+ yyensure_buffer_stack (yyscanner); \
YY_CURRENT_BUFFER_LVALUE = \
- cmListFileLexer_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
} \
YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
}
-
#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
/* Begin user sect3 */
#define cmListFileLexer_yywrap(yyscanner) (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
-
-typedef unsigned char YY_CHAR;
+typedef flex_uint8_t YY_CHAR;
typedef int yy_state_type;
#define yytext_ptr yytext_r
-static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
-static int yy_get_next_buffer (yyscan_t yyscanner );
-static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
+static yy_state_type yy_get_previous_state ( yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans ( yy_state_type current_state , yyscan_t yyscanner);
+static int yy_get_next_buffer ( yyscan_t yyscanner );
+static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner );
/* Done after the current pattern has been matched and before the
* corresponding action - sets up yytext.
@@ -367,7 +567,6 @@ static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
yyg->yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
-
#define YY_NUM_RULES 24
#define YY_END_OF_BUFFER 25
/* This struct is not used in this scanner,
@@ -377,19 +576,19 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[77] =
+static const flex_int16_t yy_accept[79] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 4, 4,
25, 13, 22, 1, 16, 3, 13, 5, 6, 7,
- 15, 23, 17, 19, 20, 21, 10, 11, 8, 12,
- 9, 4, 13, 0, 13, 0, 22, 0, 0, 7,
- 13, 0, 13, 0, 2, 0, 13, 17, 0, 18,
- 10, 8, 4, 0, 14, 0, 0, 0, 0, 14,
- 0, 0, 14, 0, 0, 0, 2, 14, 0, 0,
- 0, 0, 0, 0, 0, 0
+ 15, 23, 23, 17, 19, 20, 21, 24, 10, 11,
+ 8, 12, 9, 4, 13, 0, 13, 0, 22, 0,
+ 0, 7, 13, 0, 13, 0, 2, 0, 13, 17,
+ 0, 18, 10, 8, 4, 0, 14, 0, 0, 0,
+ 0, 14, 0, 0, 14, 0, 0, 0, 2, 14,
+ 0, 0, 0, 0, 0, 0, 0, 0
} ;
-static yyconst YY_CHAR yy_ec[256] =
+static const YY_CHAR yy_ec[256] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
@@ -421,108 +620,122 @@ static yyconst YY_CHAR yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst YY_CHAR yy_meta[16] =
+static const YY_CHAR yy_meta[17] =
{ 0,
1, 1, 2, 3, 4, 3, 1, 3, 5, 6,
- 1, 6, 1, 1, 7
+ 1, 6, 1, 1, 7, 2
} ;
-static yyconst flex_uint16_t yy_base[95] =
+static const flex_int16_t yy_base[97] =
{ 0,
- 0, 0, 13, 25, 14, 16, 17, 18, 90, 88,
- 88, 39, 20, 237, 237, 74, 78, 237, 237, 13,
- 54, 0, 71, 237, 237, 31, 0, 237, 73, 237,
- 237, 0, 0, 65, 75, 0, 33, 30, 72, 0,
- 0, 75, 70, 0, 74, 0, 0, 62, 70, 237,
- 0, 63, 0, 85, 99, 65, 111, 62, 34, 0,
- 54, 116, 0, 54, 127, 51, 237, 50, 0, 48,
- 47, 39, 33, 29, 17, 237, 136, 143, 150, 157,
- 164, 171, 178, 184, 191, 198, 201, 207, 214, 217,
- 219, 225, 228, 230
+ 0, 0, 14, 28, 42, 56, 70, 84, 18, 19,
+ 68, 100, 16, 298, 298, 54, 58, 298, 298, 13,
+ 115, 0, 298, 51, 298, 298, 21, 298, 0, 298,
+ 53, 298, 298, 0, 0, 126, 55, 0, 25, 25,
+ 53, 0, 0, 136, 53, 0, 57, 0, 0, 42,
+ 50, 298, 0, 43, 0, 146, 160, 45, 172, 43,
+ 26, 0, 42, 177, 0, 42, 188, 40, 298, 40,
+ 0, 38, 37, 34, 32, 31, 23, 298, 197, 204,
+ 211, 218, 225, 232, 239, 245, 252, 259, 262, 268,
+ 275, 278, 280, 286, 289, 291
} ;
-static yyconst flex_int16_t yy_def[95] =
+static const flex_int16_t yy_def[97] =
{ 0,
- 76, 1, 77, 77, 78, 78, 79, 79, 80, 80,
- 76, 76, 76, 76, 76, 76, 12, 76, 76, 12,
- 76, 81, 82, 76, 76, 82, 83, 76, 76, 76,
- 76, 84, 12, 85, 12, 86, 76, 76, 87, 20,
- 12, 88, 12, 21, 76, 89, 12, 82, 82, 76,
- 83, 76, 84, 85, 76, 54, 85, 90, 76, 55,
- 87, 88, 55, 62, 88, 91, 76, 55, 92, 93,
- 90, 94, 91, 93, 94, 0, 76, 76, 76, 76,
- 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 76, 76, 76
+ 78, 1, 79, 79, 80, 80, 81, 81, 82, 82,
+ 78, 78, 78, 78, 78, 78, 12, 78, 78, 12,
+ 78, 83, 78, 84, 78, 78, 84, 78, 85, 78,
+ 78, 78, 78, 86, 12, 87, 12, 88, 78, 78,
+ 89, 20, 12, 90, 12, 21, 78, 91, 12, 84,
+ 84, 78, 85, 78, 86, 87, 78, 56, 87, 92,
+ 78, 57, 89, 90, 57, 64, 90, 93, 78, 57,
+ 94, 95, 92, 96, 93, 95, 96, 0, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78
} ;
-static yyconst flex_uint16_t yy_nxt[253] =
+static const flex_int16_t yy_nxt[315] =
{ 0,
12, 13, 14, 13, 15, 16, 17, 18, 19, 12,
- 12, 20, 21, 22, 12, 24, 28, 25, 28, 28,
- 28, 37, 40, 37, 40, 62, 26, 24, 29, 25,
- 29, 31, 31, 50, 37, 48, 37, 54, 26, 33,
- 59, 63, 45, 34, 59, 35, 45, 62, 33, 33,
- 33, 33, 36, 33, 41, 55, 54, 58, 42, 63,
- 43, 72, 60, 41, 44, 41, 45, 46, 41, 55,
- 55, 56, 70, 52, 48, 49, 67, 66, 57, 63,
- 60, 64, 58, 52, 49, 39, 38, 76, 65, 55,
- 14, 56, 14, 76, 76, 76, 76, 76, 57, 55,
-
- 76, 76, 76, 34, 76, 68, 76, 76, 55, 55,
- 55, 55, 69, 55, 54, 76, 54, 76, 54, 54,
- 63, 76, 64, 76, 76, 76, 76, 76, 76, 65,
- 62, 76, 62, 76, 62, 62, 23, 23, 23, 23,
- 23, 23, 23, 27, 27, 27, 27, 27, 27, 27,
- 30, 30, 30, 30, 30, 30, 30, 32, 32, 32,
- 32, 32, 32, 32, 47, 76, 47, 47, 47, 47,
- 47, 48, 76, 48, 76, 48, 48, 48, 51, 76,
- 51, 51, 51, 51, 53, 76, 53, 53, 53, 53,
- 53, 54, 76, 76, 54, 76, 54, 54, 33, 76,
-
- 33, 33, 33, 33, 33, 61, 61, 62, 76, 76,
- 62, 76, 62, 62, 41, 76, 41, 41, 41, 41,
- 41, 71, 71, 73, 73, 55, 76, 55, 55, 55,
- 55, 55, 74, 74, 75, 75, 11, 76, 76, 76,
- 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 76
+ 12, 20, 21, 22, 12, 23, 25, 39, 26, 39,
+ 14, 14, 42, 52, 42, 50, 39, 27, 39, 28,
+ 25, 64, 26, 28, 28, 61, 61, 47, 47, 56,
+ 65, 27, 64, 28, 30, 57, 56, 60, 65, 74,
+ 62, 57, 72, 54, 50, 51, 31, 28, 30, 69,
+ 68, 62, 60, 54, 51, 41, 40, 78, 78, 78,
+ 31, 28, 30, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 33, 28, 30, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 33, 28,
+
+ 35, 78, 78, 78, 36, 78, 37, 78, 78, 35,
+ 35, 35, 35, 38, 35, 43, 78, 78, 78, 44,
+ 78, 45, 78, 78, 43, 46, 43, 47, 48, 43,
+ 57, 78, 58, 78, 78, 78, 78, 78, 78, 59,
+ 65, 78, 66, 78, 78, 78, 78, 78, 78, 67,
+ 57, 78, 58, 78, 78, 78, 78, 78, 78, 59,
+ 57, 78, 78, 78, 36, 78, 70, 78, 78, 57,
+ 57, 57, 57, 71, 57, 56, 78, 56, 78, 56,
+ 56, 65, 78, 66, 78, 78, 78, 78, 78, 78,
+ 67, 64, 78, 64, 78, 64, 64, 24, 24, 24,
+
+ 24, 24, 24, 24, 29, 29, 29, 29, 29, 29,
+ 29, 32, 32, 32, 32, 32, 32, 32, 34, 34,
+ 34, 34, 34, 34, 34, 49, 78, 49, 49, 49,
+ 49, 49, 50, 78, 50, 78, 50, 50, 50, 53,
+ 78, 53, 53, 53, 53, 55, 78, 55, 55, 55,
+ 55, 55, 56, 78, 78, 56, 78, 56, 56, 35,
+ 78, 35, 35, 35, 35, 35, 63, 63, 64, 78,
+ 78, 64, 78, 64, 64, 43, 78, 43, 43, 43,
+ 43, 43, 73, 73, 75, 75, 57, 78, 57, 57,
+ 57, 57, 57, 76, 76, 77, 77, 11, 78, 78,
+
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78
} ;
-static yyconst flex_int16_t yy_chk[253] =
+static const flex_int16_t yy_chk[315] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 3, 5, 3, 6, 7,
- 8, 13, 20, 13, 20, 75, 3, 4, 5, 4,
- 6, 7, 8, 26, 37, 26, 37, 74, 4, 12,
- 38, 73, 38, 12, 59, 12, 59, 72, 12, 12,
- 12, 12, 12, 12, 21, 71, 70, 68, 21, 66,
- 21, 64, 61, 21, 21, 21, 21, 21, 21, 34,
- 58, 34, 56, 52, 49, 48, 45, 43, 34, 42,
- 39, 42, 35, 29, 23, 17, 16, 11, 42, 54,
- 10, 54, 9, 0, 0, 0, 0, 0, 54, 55,
-
- 0, 0, 0, 55, 0, 55, 0, 0, 55, 55,
- 55, 55, 55, 55, 57, 0, 57, 0, 57, 57,
- 62, 0, 62, 0, 0, 0, 0, 0, 0, 62,
- 65, 0, 65, 0, 65, 65, 77, 77, 77, 77,
- 77, 77, 77, 78, 78, 78, 78, 78, 78, 78,
- 79, 79, 79, 79, 79, 79, 79, 80, 80, 80,
- 80, 80, 80, 80, 81, 0, 81, 81, 81, 81,
- 81, 82, 0, 82, 0, 82, 82, 82, 83, 0,
- 83, 83, 83, 83, 84, 0, 84, 84, 84, 84,
- 84, 85, 0, 0, 85, 0, 85, 85, 86, 0,
-
- 86, 86, 86, 86, 86, 87, 87, 88, 0, 0,
- 88, 0, 88, 88, 89, 0, 89, 89, 89, 89,
- 89, 90, 90, 91, 91, 92, 0, 92, 92, 92,
- 92, 92, 93, 93, 94, 94, 76, 76, 76, 76,
- 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 76
+ 1, 1, 1, 1, 1, 1, 3, 13, 3, 13,
+ 9, 10, 20, 27, 20, 27, 39, 3, 39, 3,
+ 4, 77, 4, 9, 10, 40, 61, 40, 61, 76,
+ 75, 4, 74, 4, 5, 73, 72, 70, 68, 66,
+ 63, 60, 58, 54, 51, 50, 5, 5, 6, 47,
+ 45, 41, 37, 31, 24, 17, 16, 11, 0, 0,
+ 6, 6, 7, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 7, 7, 8, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 8, 8,
+
+ 12, 0, 0, 0, 12, 0, 12, 0, 0, 12,
+ 12, 12, 12, 12, 12, 21, 0, 0, 0, 21,
+ 0, 21, 0, 0, 21, 21, 21, 21, 21, 21,
+ 36, 0, 36, 0, 0, 0, 0, 0, 0, 36,
+ 44, 0, 44, 0, 0, 0, 0, 0, 0, 44,
+ 56, 0, 56, 0, 0, 0, 0, 0, 0, 56,
+ 57, 0, 0, 0, 57, 0, 57, 0, 0, 57,
+ 57, 57, 57, 57, 57, 59, 0, 59, 0, 59,
+ 59, 64, 0, 64, 0, 0, 0, 0, 0, 0,
+ 64, 67, 0, 67, 0, 67, 67, 79, 79, 79,
+
+ 79, 79, 79, 79, 80, 80, 80, 80, 80, 80,
+ 80, 81, 81, 81, 81, 81, 81, 81, 82, 82,
+ 82, 82, 82, 82, 82, 83, 0, 83, 83, 83,
+ 83, 83, 84, 0, 84, 0, 84, 84, 84, 85,
+ 0, 85, 85, 85, 85, 86, 0, 86, 86, 86,
+ 86, 86, 87, 0, 0, 87, 0, 87, 87, 88,
+ 0, 88, 88, 88, 88, 88, 89, 89, 90, 0,
+ 0, 90, 0, 90, 90, 91, 0, 91, 91, 91,
+ 91, 91, 92, 92, 93, 93, 94, 0, 94, 94,
+ 94, 94, 94, 95, 95, 96, 96, 78, 78, 78,
+
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78
} ;
/* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[25] =
+static const flex_int32_t yy_rule_can_match_eol[25] =
{ 0,
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1,
0, 0, 0, 0, 0, };
@@ -534,8 +747,6 @@ static yyconst flex_int32_t yy_rule_can_match_eol[25] =
#define yymore() yymore_used_but_not_detected
#define YY_MORE_ADJ 0
#define YY_RESTORE_YY_MORE_OFFSET
-#line 1 "cmListFileLexer.in.l"
-#line 2 "cmListFileLexer.in.l"
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
/*
@@ -544,20 +755,18 @@ This file must be translated to C and modified to build everywhere.
Run flex >= 2.6 like this:
- flex --nounistd -DFLEXINT_H --prefix=cmListFileLexer_yy -ocmListFileLexer.c cmListFileLexer.in.l
+ flex --nounistd -DFLEXINT_H --noline -ocmListFileLexer.c cmListFileLexer.in.l
Modify cmListFileLexer.c:
- - remove trailing whitespace: sed -i 's/\s*$//' cmListFileLexer.c
- - remove blank lines at end of file
- - #include "cmStandardLexer.h" at the top
- - add cast in cmListFileLexer_yy_scan_bytes for loop condition of _yybytes_len to size_t
- - change type of variable yyl under yy_find_action from yy_size_t to int
+ - remove trailing whitespace: sed -i 's/\s*$//' cmListFileLexer.c
+ - remove blank lines at end of file: sed -i '${/^$/d;}' cmListFileLexer.c
+ - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmListFileLexer.c
*/
/* IWYU pragma: no_forward_declare yyguts_t */
-#ifdef WIN32
+#ifdef _WIN32
#include "cmsys/Encoding.h"
#endif
@@ -596,15 +805,10 @@ static void cmListFileLexerDestroy(cmListFileLexer* lexer);
/* Replace the lexer input function. */
#undef YY_INPUT
#define YY_INPUT(buf, result, max_size) \
- { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); }
+ do { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); } while (0)
/*--------------------------------------------------------------------------*/
-
-
-
-#line 606 "cmListFileLexer.c"
-
#define INITIAL 0
#define STRING 1
#define BRACKET 2
@@ -649,44 +853,44 @@ struct yyguts_t
}; /* end struct yyguts_t */
-static int yy_init_globals (yyscan_t yyscanner );
+static int yy_init_globals ( yyscan_t yyscanner );
-int cmListFileLexer_yylex_init (yyscan_t* scanner);
+int yylex_init (yyscan_t* scanner);
-int cmListFileLexer_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
-int cmListFileLexer_yylex_destroy (yyscan_t yyscanner );
+int yylex_destroy ( yyscan_t yyscanner );
-int cmListFileLexer_yyget_debug (yyscan_t yyscanner );
+int yyget_debug ( yyscan_t yyscanner );
-void cmListFileLexer_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+void yyset_debug ( int debug_flag , yyscan_t yyscanner );
-YY_EXTRA_TYPE cmListFileLexer_yyget_extra (yyscan_t yyscanner );
+YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
-void cmListFileLexer_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
-FILE *cmListFileLexer_yyget_in (yyscan_t yyscanner );
+FILE *yyget_in ( yyscan_t yyscanner );
-void cmListFileLexer_yyset_in (FILE * _in_str ,yyscan_t yyscanner );
+void yyset_in ( FILE * _in_str , yyscan_t yyscanner );
-FILE *cmListFileLexer_yyget_out (yyscan_t yyscanner );
+FILE *yyget_out ( yyscan_t yyscanner );
-void cmListFileLexer_yyset_out (FILE * _out_str ,yyscan_t yyscanner );
+void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
- int cmListFileLexer_yyget_leng (yyscan_t yyscanner );
+ int yyget_leng ( yyscan_t yyscanner );
-char *cmListFileLexer_yyget_text (yyscan_t yyscanner );
+char *yyget_text ( yyscan_t yyscanner );
-int cmListFileLexer_yyget_lineno (yyscan_t yyscanner );
+int yyget_lineno ( yyscan_t yyscanner );
-void cmListFileLexer_yyset_lineno (int _line_number ,yyscan_t yyscanner );
+void yyset_lineno ( int _line_number , yyscan_t yyscanner );
-int cmListFileLexer_yyget_column (yyscan_t yyscanner );
+int yyget_column ( yyscan_t yyscanner );
-void cmListFileLexer_yyset_column (int _column_no ,yyscan_t yyscanner );
+void yyset_column ( int _column_no , yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -694,32 +898,31 @@ void cmListFileLexer_yyset_column (int _column_no ,yyscan_t yyscanner );
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
-extern "C" int cmListFileLexer_yywrap (yyscan_t yyscanner );
+extern "C" int yywrap ( yyscan_t yyscanner );
#else
-extern int cmListFileLexer_yywrap (yyscan_t yyscanner );
+extern int yywrap ( yyscan_t yyscanner );
#endif
#endif
#ifndef YY_NO_UNPUT
- static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner);
+ static void yyunput ( int c, char *buf_ptr , yyscan_t yyscanner);
#endif
#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
#endif
#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
#endif
#ifndef YY_NO_INPUT
-
#ifdef __cplusplus
-static int yyinput (yyscan_t yyscanner );
+static int yyinput ( yyscan_t yyscanner );
#else
-static int input (yyscan_t yyscanner );
+static int input ( yyscan_t yyscanner );
#endif
#endif
@@ -750,7 +953,7 @@ static int input (yyscan_t yyscanner );
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
- size_t n; \
+ int n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@@ -763,7 +966,7 @@ static int input (yyscan_t yyscanner );
else \
{ \
errno=0; \
- while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \
{ \
if( errno != EINTR) \
{ \
@@ -804,9 +1007,9 @@ static int input (yyscan_t yyscanner );
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
-extern int cmListFileLexer_yylex (yyscan_t yyscanner);
+extern int yylex (yyscan_t yyscanner);
-#define YY_DECL int cmListFileLexer_yylex (yyscan_t yyscanner)
+#define YY_DECL int yylex (yyscan_t yyscanner)
#endif /* !YY_DECL */
/* Code executed at the beginning of each rule, after yytext and yyleng
@@ -851,19 +1054,15 @@ YY_DECL
yyout = stdout;
if ( ! YY_CURRENT_BUFFER ) {
- cmListFileLexer_yyensure_buffer_stack (yyscanner);
+ yyensure_buffer_stack (yyscanner);
YY_CURRENT_BUFFER_LVALUE =
- cmListFileLexer_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner);
}
- cmListFileLexer_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
}
{
-#line 80 "cmListFileLexer.in.l"
-
-
-#line 866 "cmListFileLexer.c"
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
@@ -890,13 +1089,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 77 )
- yy_c = yy_meta[(unsigned int) yy_c];
+ if ( yy_current_state >= 79 )
+ yy_c = yy_meta[yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
++yy_cp;
}
- while ( yy_base[yy_current_state] != 237 );
+ while ( yy_base[yy_current_state] != 298 );
yy_find_action:
yy_act = yy_accept[yy_current_state];
@@ -935,7 +1134,6 @@ do_action: /* This label is used only to access EOF actions. */
case 1:
/* rule 1 can match eol */
YY_RULE_SETUP
-#line 82 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_Newline;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -948,7 +1146,6 @@ YY_RULE_SETUP
case 2:
/* rule 2 can match eol */
YY_RULE_SETUP
-#line 91 "cmListFileLexer.in.l"
{
const char* bracket = yytext;
lexer->comment = yytext[0] == '#';
@@ -971,7 +1168,6 @@ YY_RULE_SETUP
YY_BREAK
case 3:
YY_RULE_SETUP
-#line 111 "cmListFileLexer.in.l"
{
lexer->column += yyleng;
BEGIN(COMMENT);
@@ -979,14 +1175,12 @@ YY_RULE_SETUP
YY_BREAK
case 4:
YY_RULE_SETUP
-#line 116 "cmListFileLexer.in.l"
{
lexer->column += yyleng;
}
YY_BREAK
case 5:
YY_RULE_SETUP
-#line 120 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_ParenLeft;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -996,7 +1190,6 @@ YY_RULE_SETUP
YY_BREAK
case 6:
YY_RULE_SETUP
-#line 127 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_ParenRight;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -1006,7 +1199,6 @@ YY_RULE_SETUP
YY_BREAK
case 7:
YY_RULE_SETUP
-#line 134 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_Identifier;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -1016,7 +1208,6 @@ YY_RULE_SETUP
YY_BREAK
case 8:
YY_RULE_SETUP
-#line 141 "cmListFileLexer.in.l"
{
/* Handle ]]====]=======]*/
cmListFileLexerAppend(lexer, yytext, yyleng);
@@ -1028,7 +1219,6 @@ YY_RULE_SETUP
YY_BREAK
case 9:
YY_RULE_SETUP
-#line 150 "cmListFileLexer.in.l"
{
lexer->column += yyleng;
/* Erase the partial bracket from the token. */
@@ -1040,7 +1230,6 @@ YY_RULE_SETUP
YY_BREAK
case 10:
YY_RULE_SETUP
-#line 159 "cmListFileLexer.in.l"
{
cmListFileLexerAppend(lexer, yytext, yyleng);
lexer->column += yyleng;
@@ -1049,7 +1238,6 @@ YY_RULE_SETUP
case 11:
/* rule 11 can match eol */
YY_RULE_SETUP
-#line 164 "cmListFileLexer.in.l"
{
cmListFileLexerAppend(lexer, yytext, yyleng);
++lexer->line;
@@ -1059,7 +1247,6 @@ YY_RULE_SETUP
YY_BREAK
case 12:
YY_RULE_SETUP
-#line 171 "cmListFileLexer.in.l"
{
cmListFileLexerAppend(lexer, yytext, yyleng);
lexer->column += yyleng;
@@ -1068,7 +1255,6 @@ YY_RULE_SETUP
YY_BREAK
case YY_STATE_EOF(BRACKET):
case YY_STATE_EOF(BRACKETEND):
-#line 177 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_BadBracket;
BEGIN(INITIAL);
@@ -1077,7 +1263,6 @@ case YY_STATE_EOF(BRACKETEND):
YY_BREAK
case 13:
YY_RULE_SETUP
-#line 183 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -1087,7 +1272,6 @@ YY_RULE_SETUP
YY_BREAK
case 14:
YY_RULE_SETUP
-#line 190 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -1097,7 +1281,6 @@ YY_RULE_SETUP
YY_BREAK
case 15:
YY_RULE_SETUP
-#line 197 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -1107,7 +1290,6 @@ YY_RULE_SETUP
YY_BREAK
case 16:
YY_RULE_SETUP
-#line 204 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_ArgumentQuoted;
cmListFileLexerSetToken(lexer, "", 0);
@@ -1117,7 +1299,6 @@ YY_RULE_SETUP
YY_BREAK
case 17:
YY_RULE_SETUP
-#line 211 "cmListFileLexer.in.l"
{
cmListFileLexerAppend(lexer, yytext, yyleng);
lexer->column += yyleng;
@@ -1126,7 +1307,6 @@ YY_RULE_SETUP
case 18:
/* rule 18 can match eol */
YY_RULE_SETUP
-#line 216 "cmListFileLexer.in.l"
{
/* Continuation: text is not part of string */
++lexer->line;
@@ -1136,7 +1316,6 @@ YY_RULE_SETUP
case 19:
/* rule 19 can match eol */
YY_RULE_SETUP
-#line 222 "cmListFileLexer.in.l"
{
cmListFileLexerAppend(lexer, yytext, yyleng);
++lexer->line;
@@ -1145,7 +1324,6 @@ YY_RULE_SETUP
YY_BREAK
case 20:
YY_RULE_SETUP
-#line 228 "cmListFileLexer.in.l"
{
lexer->column += yyleng;
BEGIN(INITIAL);
@@ -1154,14 +1332,12 @@ YY_RULE_SETUP
YY_BREAK
case 21:
YY_RULE_SETUP
-#line 234 "cmListFileLexer.in.l"
{
cmListFileLexerAppend(lexer, yytext, yyleng);
lexer->column += yyleng;
}
YY_BREAK
case YY_STATE_EOF(STRING):
-#line 239 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_BadString;
BEGIN(INITIAL);
@@ -1170,7 +1346,6 @@ case YY_STATE_EOF(STRING):
YY_BREAK
case 22:
YY_RULE_SETUP
-#line 245 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_Space;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -1180,7 +1355,6 @@ YY_RULE_SETUP
YY_BREAK
case 23:
YY_RULE_SETUP
-#line 252 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_BadCharacter;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -1190,7 +1364,6 @@ YY_RULE_SETUP
YY_BREAK
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(COMMENT):
-#line 259 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_None;
cmListFileLexerSetToken(lexer, 0, 0);
@@ -1199,10 +1372,8 @@ case YY_STATE_EOF(COMMENT):
YY_BREAK
case 24:
YY_RULE_SETUP
-#line 265 "cmListFileLexer.in.l"
ECHO;
YY_BREAK
-#line 1205 "cmListFileLexer.c"
case YY_END_OF_BUFFER:
{
@@ -1218,7 +1389,7 @@ ECHO;
/* We're scanning a new file or input source. It's
* possible that this happened because the user
* just pointed yyin at a new source and called
- * cmListFileLexer_yylex(). If so, then we have to assure
+ * yylex(). If so, then we have to assure
* consistency between YY_CURRENT_BUFFER and our
* globals. Here is the right place to do so, because
* this is the first action (other than possibly a
@@ -1278,7 +1449,7 @@ ECHO;
{
yyg->yy_did_buffer_switch_on_eof = 0;
- if ( cmListFileLexer_yywrap(yyscanner ) )
+ if ( yywrap( yyscanner ) )
{
/* Note: because we've taken care in
* yy_get_next_buffer() to have set up
@@ -1332,7 +1503,7 @@ ECHO;
} /* end of action switch */
} /* end of scanning one token */
} /* end of user's declarations */
-} /* end of cmListFileLexer_yylex */
+} /* end of yylex */
/* yy_get_next_buffer - try to read in a new buffer
*
@@ -1346,7 +1517,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
char *source = yyg->yytext_ptr;
- yy_size_t number_to_move, i;
+ int number_to_move, i;
int ret_val;
if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
@@ -1375,7 +1546,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
/* Try to read more data. */
/* First move last chars to start of buffer. */
- number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1);
for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++);
@@ -1411,7 +1582,8 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
b->yy_ch_buf = (char *)
/* Include room in for 2 EOB chars. */
- cmListFileLexer_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+ yyrealloc( (void *) b->yy_ch_buf,
+ (yy_size_t) (b->yy_buf_size + 2) , yyscanner );
}
else
/* Can't grow it, we don't own it. */
@@ -1443,7 +1615,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ( number_to_move == YY_MORE_ADJ )
{
ret_val = EOB_ACT_END_OF_FILE;
- cmListFileLexer_yyrestart(yyin ,yyscanner);
+ yyrestart( yyin , yyscanner);
}
else
@@ -1457,12 +1629,15 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
ret_val = EOB_ACT_CONTINUE_SCAN;
- if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
/* Extend the array by 50%, plus the number we really need. */
int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) cmListFileLexer_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
+ (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner );
if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ /* "- 2" to take care of EOB's */
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
}
yyg->yy_n_chars += number_to_move;
@@ -1486,7 +1661,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
{
- YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 16);
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -1495,10 +1670,10 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 77 )
- yy_c = yy_meta[(unsigned int) yy_c];
+ if ( yy_current_state >= 79 )
+ yy_c = yy_meta[yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
}
return yy_current_state;
@@ -1515,7 +1690,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
char *yy_cp = yyg->yy_c_buf_p;
- YY_CHAR yy_c = 1;
+ YY_CHAR yy_c = 16;
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -1524,11 +1699,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 77 )
- yy_c = yy_meta[(unsigned int) yy_c];
+ if ( yy_current_state >= 79 )
+ yy_c = yy_meta[yy_c];
}
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
- yy_is_jam = (yy_current_state == 76);
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+ yy_is_jam = (yy_current_state == 78);
(void)yyg;
return yy_is_jam ? 0 : yy_current_state;
@@ -1605,7 +1780,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{ /* need more input */
- int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+ int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr);
++yyg->yy_c_buf_p;
switch ( yy_get_next_buffer( yyscanner ) )
@@ -1622,13 +1797,13 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
*/
/* Reset buffer status. */
- cmListFileLexer_yyrestart(yyin ,yyscanner);
+ yyrestart( yyin , yyscanner);
/*FALLTHROUGH*/
case EOB_ACT_END_OF_FILE:
{
- if ( cmListFileLexer_yywrap(yyscanner ) )
+ if ( yywrap( yyscanner ) )
return 0;
if ( ! yyg->yy_did_buffer_switch_on_eof )
@@ -1667,34 +1842,34 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @note This function does not reset the start condition to @c INITIAL .
*/
- void cmListFileLexer_yyrestart (FILE * input_file , yyscan_t yyscanner)
+ void yyrestart (FILE * input_file , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if ( ! YY_CURRENT_BUFFER ){
- cmListFileLexer_yyensure_buffer_stack (yyscanner);
+ yyensure_buffer_stack (yyscanner);
YY_CURRENT_BUFFER_LVALUE =
- cmListFileLexer_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner);
}
- cmListFileLexer_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
- cmListFileLexer_yy_load_buffer_state(yyscanner );
+ yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner);
+ yy_load_buffer_state( yyscanner );
}
/** Switch to a different input buffer.
* @param new_buffer The new input buffer.
* @param yyscanner The scanner object.
*/
- void cmListFileLexer_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* TODO. We should be able to replace this entire function body
* with
- * cmListFileLexer_yypop_buffer_state();
- * cmListFileLexer_yypush_buffer_state(new_buffer);
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
*/
- cmListFileLexer_yyensure_buffer_stack (yyscanner);
+ yyensure_buffer_stack (yyscanner);
if ( YY_CURRENT_BUFFER == new_buffer )
return;
@@ -1707,17 +1882,17 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
}
YY_CURRENT_BUFFER_LVALUE = new_buffer;
- cmListFileLexer_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
/* We don't actually know whether we did this switch during
- * EOF (cmListFileLexer_yywrap()) processing, but the only time this flag
- * is looked at is after cmListFileLexer_yywrap() is called, so it's safe
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
* to go ahead and always set it.
*/
yyg->yy_did_buffer_switch_on_eof = 1;
}
-static void cmListFileLexer_yy_load_buffer_state (yyscan_t yyscanner)
+static void yy_load_buffer_state (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
@@ -1732,35 +1907,35 @@ static void cmListFileLexer_yy_load_buffer_state (yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @return the allocated buffer state.
*/
- YY_BUFFER_STATE cmListFileLexer_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
- b = (YY_BUFFER_STATE) cmListFileLexer_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner );
if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_create_buffer()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
- b->yy_buf_size = (yy_size_t)size;
+ b->yy_buf_size = size;
/* yy_ch_buf has to be 2 characters longer than the size given because
* we need to put in 2 end-of-buffer characters.
*/
- b->yy_ch_buf = (char *) cmListFileLexer_yyalloc(b->yy_buf_size + 2 ,yyscanner );
+ b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner );
if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_create_buffer()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
b->yy_is_our_buffer = 1;
- cmListFileLexer_yy_init_buffer(b,file ,yyscanner);
+ yy_init_buffer( b, file , yyscanner);
return b;
}
/** Destroy the buffer.
- * @param b a buffer created with cmListFileLexer_yy_create_buffer()
+ * @param b a buffer created with yy_create_buffer()
* @param yyscanner The scanner object.
*/
- void cmListFileLexer_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+ void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -1771,28 +1946,28 @@ static void cmListFileLexer_yy_load_buffer_state (yyscan_t yyscanner)
YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
if ( b->yy_is_our_buffer )
- cmListFileLexer_yyfree((void *) b->yy_ch_buf ,yyscanner );
+ yyfree( (void *) b->yy_ch_buf , yyscanner );
- cmListFileLexer_yyfree((void *) b ,yyscanner );
+ yyfree( (void *) b , yyscanner );
}
/* Initializes or reinitializes a buffer.
* This function is sometimes called more than once on the same buffer,
- * such as during a cmListFileLexer_yyrestart() or at EOF.
+ * such as during a yyrestart() or at EOF.
*/
- static void cmListFileLexer_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
{
int oerrno = errno;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- cmListFileLexer_yy_flush_buffer(b ,yyscanner);
+ yy_flush_buffer( b , yyscanner);
b->yy_input_file = file;
b->yy_fill_buffer = 1;
- /* If b is the current buffer, then cmListFileLexer_yy_init_buffer was _probably_
- * called from cmListFileLexer_yyrestart() or through yy_get_next_buffer.
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
* In that case, we don't want to reset the lineno or column.
*/
if (b != YY_CURRENT_BUFFER){
@@ -1809,7 +1984,7 @@ static void cmListFileLexer_yy_load_buffer_state (yyscan_t yyscanner)
* @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
* @param yyscanner The scanner object.
*/
- void cmListFileLexer_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+ void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if ( ! b )
@@ -1830,7 +2005,7 @@ static void cmListFileLexer_yy_load_buffer_state (yyscan_t yyscanner)
b->yy_buffer_status = YY_BUFFER_NEW;
if ( b == YY_CURRENT_BUFFER )
- cmListFileLexer_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
}
/** Pushes the new state onto the stack. The new state becomes
@@ -1839,15 +2014,15 @@ static void cmListFileLexer_yy_load_buffer_state (yyscan_t yyscanner)
* @param new_buffer The new state.
* @param yyscanner The scanner object.
*/
-void cmListFileLexer_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (new_buffer == NULL)
return;
- cmListFileLexer_yyensure_buffer_stack(yyscanner);
+ yyensure_buffer_stack(yyscanner);
- /* This block is copied from cmListFileLexer_yy_switch_to_buffer. */
+ /* This block is copied from yy_switch_to_buffer. */
if ( YY_CURRENT_BUFFER )
{
/* Flush out information for old buffer. */
@@ -1861,8 +2036,8 @@ void cmListFileLexer_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t
yyg->yy_buffer_stack_top++;
YY_CURRENT_BUFFER_LVALUE = new_buffer;
- /* copied from cmListFileLexer_yy_switch_to_buffer. */
- cmListFileLexer_yy_load_buffer_state(yyscanner );
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state( yyscanner );
yyg->yy_did_buffer_switch_on_eof = 1;
}
@@ -1870,19 +2045,19 @@ void cmListFileLexer_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t
* The next element becomes the new top.
* @param yyscanner The scanner object.
*/
-void cmListFileLexer_yypop_buffer_state (yyscan_t yyscanner)
+void yypop_buffer_state (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (!YY_CURRENT_BUFFER)
return;
- cmListFileLexer_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+ yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner);
YY_CURRENT_BUFFER_LVALUE = NULL;
if (yyg->yy_buffer_stack_top > 0)
--yyg->yy_buffer_stack_top;
if (YY_CURRENT_BUFFER) {
- cmListFileLexer_yy_load_buffer_state(yyscanner );
+ yy_load_buffer_state( yyscanner );
yyg->yy_did_buffer_switch_on_eof = 1;
}
}
@@ -1890,9 +2065,9 @@ void cmListFileLexer_yypop_buffer_state (yyscan_t yyscanner)
/* Allocates the stack if it does not exist.
* Guarantees space for at least one push.
*/
-static void cmListFileLexer_yyensure_buffer_stack (yyscan_t yyscanner)
+static void yyensure_buffer_stack (yyscan_t yyscanner)
{
- int num_to_alloc;
+ yy_size_t num_to_alloc;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (!yyg->yy_buffer_stack) {
@@ -1902,11 +2077,11 @@ static void cmListFileLexer_yyensure_buffer_stack (yyscan_t yyscanner)
* immediate realloc on the next call.
*/
num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmListFileLexer_yyalloc
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
(num_to_alloc * sizeof(struct yy_buffer_state*)
, yyscanner);
if ( ! yyg->yy_buffer_stack )
- YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yyensure_buffer_stack()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
@@ -1921,12 +2096,12 @@ static void cmListFileLexer_yyensure_buffer_stack (yyscan_t yyscanner)
yy_size_t grow_size = 8 /* arbitrary grow size */;
num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
- yyg->yy_buffer_stack = (struct yy_buffer_state**)cmListFileLexer_yyrealloc
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
(yyg->yy_buffer_stack,
num_to_alloc * sizeof(struct yy_buffer_state*)
, yyscanner);
if ( ! yyg->yy_buffer_stack )
- YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yyensure_buffer_stack()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
/* zero only the new slots.*/
memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
@@ -1940,7 +2115,7 @@ static void cmListFileLexer_yyensure_buffer_stack (yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
-YY_BUFFER_STATE cmListFileLexer_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
@@ -1950,11 +2125,11 @@ YY_BUFFER_STATE cmListFileLexer_yy_scan_buffer (char * base, yy_size_t size ,
/* They forgot to leave room for the EOB's. */
return NULL;
- b = (YY_BUFFER_STATE) cmListFileLexer_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner );
if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_scan_buffer()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
- b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */
b->yy_buf_pos = b->yy_ch_buf = base;
b->yy_is_our_buffer = 0;
b->yy_input_file = NULL;
@@ -1964,53 +2139,53 @@ YY_BUFFER_STATE cmListFileLexer_yy_scan_buffer (char * base, yy_size_t size ,
b->yy_fill_buffer = 0;
b->yy_buffer_status = YY_BUFFER_NEW;
- cmListFileLexer_yy_switch_to_buffer(b ,yyscanner );
+ yy_switch_to_buffer( b , yyscanner );
return b;
}
-/** Setup the input buffer state to scan a string. The next call to cmListFileLexer_yylex() will
+/** Setup the input buffer state to scan a string. The next call to yylex() will
* scan from a @e copy of @a str.
* @param yystr a NUL-terminated string to scan
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
* @note If you want to scan bytes that may contain NUL values, then use
- * cmListFileLexer_yy_scan_bytes() instead.
+ * yy_scan_bytes() instead.
*/
-YY_BUFFER_STATE cmListFileLexer_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner)
{
- return cmListFileLexer_yy_scan_bytes(yystr,(int) strlen(yystr) ,yyscanner);
+ return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner);
}
-/** Setup the input buffer state to scan the given bytes. The next call to cmListFileLexer_yylex() will
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
* scan from a @e copy of @a bytes.
* @param yybytes the byte buffer to scan
* @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
-YY_BUFFER_STATE cmListFileLexer_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
+YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
char *buf;
yy_size_t n;
- yy_size_t i;
+ int i;
/* Get memory for full buffer, including space for trailing EOB's. */
- n = (yy_size_t) _yybytes_len + 2;
- buf = (char *) cmListFileLexer_yyalloc(n ,yyscanner );
+ n = (yy_size_t) (_yybytes_len + 2);
+ buf = (char *) yyalloc( n , yyscanner );
if ( ! buf )
- YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_scan_bytes()" );
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
- for ( i = 0; i < (size_t)_yybytes_len; ++i )
+ for ( i = 0; i < _yybytes_len; ++i )
buf[i] = yybytes[i];
buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
- b = cmListFileLexer_yy_scan_buffer(buf,n ,yyscanner);
+ b = yy_scan_buffer( buf, n , yyscanner);
if ( ! b )
- YY_FATAL_ERROR( "bad buffer in cmListFileLexer_yy_scan_bytes()" );
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
/* It's okay to grow etc. this buffer, and we should throw it
* away when we're done.
@@ -2024,11 +2199,11 @@ YY_BUFFER_STATE cmListFileLexer_yy_scan_bytes (yyconst char * yybytes, int _yy
#define YY_EXIT_FAILURE 2
#endif
-static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
- (void) fprintf( stderr, "%s\n", msg );
+ fprintf( stderr, "%s\n", msg );
exit( YY_EXIT_FAILURE );
}
@@ -2054,7 +2229,7 @@ static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
/** Get the user-defined data for this scanner.
* @param yyscanner The scanner object.
*/
-YY_EXTRA_TYPE cmListFileLexer_yyget_extra (yyscan_t yyscanner)
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyextra;
@@ -2063,7 +2238,7 @@ YY_EXTRA_TYPE cmListFileLexer_yyget_extra (yyscan_t yyscanner)
/** Get the current line number.
* @param yyscanner The scanner object.
*/
-int cmListFileLexer_yyget_lineno (yyscan_t yyscanner)
+int yyget_lineno (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -2076,7 +2251,7 @@ int cmListFileLexer_yyget_lineno (yyscan_t yyscanner)
/** Get the current column number.
* @param yyscanner The scanner object.
*/
-int cmListFileLexer_yyget_column (yyscan_t yyscanner)
+int yyget_column (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
@@ -2089,7 +2264,7 @@ int cmListFileLexer_yyget_column (yyscan_t yyscanner)
/** Get the input stream.
* @param yyscanner The scanner object.
*/
-FILE *cmListFileLexer_yyget_in (yyscan_t yyscanner)
+FILE *yyget_in (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyin;
@@ -2098,7 +2273,7 @@ FILE *cmListFileLexer_yyget_in (yyscan_t yyscanner)
/** Get the output stream.
* @param yyscanner The scanner object.
*/
-FILE *cmListFileLexer_yyget_out (yyscan_t yyscanner)
+FILE *yyget_out (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyout;
@@ -2107,7 +2282,7 @@ FILE *cmListFileLexer_yyget_out (yyscan_t yyscanner)
/** Get the length of the current token.
* @param yyscanner The scanner object.
*/
-int cmListFileLexer_yyget_leng (yyscan_t yyscanner)
+int yyget_leng (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyleng;
@@ -2117,7 +2292,7 @@ int cmListFileLexer_yyget_leng (yyscan_t yyscanner)
* @param yyscanner The scanner object.
*/
-char *cmListFileLexer_yyget_text (yyscan_t yyscanner)
+char *yyget_text (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yytext;
@@ -2127,7 +2302,7 @@ char *cmListFileLexer_yyget_text (yyscan_t yyscanner)
* @param user_defined The data to be associated with this scanner.
* @param yyscanner The scanner object.
*/
-void cmListFileLexer_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
+void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyextra = user_defined ;
@@ -2137,13 +2312,13 @@ void cmListFileLexer_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscann
* @param _line_number line number
* @param yyscanner The scanner object.
*/
-void cmListFileLexer_yyset_lineno (int _line_number , yyscan_t yyscanner)
+void yyset_lineno (int _line_number , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* lineno is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
- YY_FATAL_ERROR( "cmListFileLexer_yyset_lineno called with no buffer" );
+ YY_FATAL_ERROR( "yyset_lineno called with no buffer" );
yylineno = _line_number;
}
@@ -2152,13 +2327,13 @@ void cmListFileLexer_yyset_lineno (int _line_number , yyscan_t yyscanner)
* @param _column_no column number
* @param yyscanner The scanner object.
*/
-void cmListFileLexer_yyset_column (int _column_no , yyscan_t yyscanner)
+void yyset_column (int _column_no , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* column is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
- YY_FATAL_ERROR( "cmListFileLexer_yyset_column called with no buffer" );
+ YY_FATAL_ERROR( "yyset_column called with no buffer" );
yycolumn = _column_no;
}
@@ -2167,27 +2342,27 @@ void cmListFileLexer_yyset_column (int _column_no , yyscan_t yyscanner)
* input buffer.
* @param _in_str A readable stream.
* @param yyscanner The scanner object.
- * @see cmListFileLexer_yy_switch_to_buffer
+ * @see yy_switch_to_buffer
*/
-void cmListFileLexer_yyset_in (FILE * _in_str , yyscan_t yyscanner)
+void yyset_in (FILE * _in_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyin = _in_str ;
}
-void cmListFileLexer_yyset_out (FILE * _out_str , yyscan_t yyscanner)
+void yyset_out (FILE * _out_str , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yyout = _out_str ;
}
-int cmListFileLexer_yyget_debug (yyscan_t yyscanner)
+int yyget_debug (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yy_flex_debug;
}
-void cmListFileLexer_yyset_debug (int _bdebug , yyscan_t yyscanner)
+void yyset_debug (int _bdebug , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yy_flex_debug = _bdebug ;
@@ -2197,20 +2372,18 @@ void cmListFileLexer_yyset_debug (int _bdebug , yyscan_t yyscanner)
/* User-visible API */
-/* cmListFileLexer_yylex_init is special because it creates the scanner itself, so it is
+/* yylex_init is special because it creates the scanner itself, so it is
* the ONLY reentrant function that doesn't take the scanner as the last argument.
* That's why we explicitly handle the declaration, instead of using our macros.
*/
-
-int cmListFileLexer_yylex_init(yyscan_t* ptr_yy_globals)
-
+int yylex_init(yyscan_t* ptr_yy_globals)
{
if (ptr_yy_globals == NULL){
errno = EINVAL;
return 1;
}
- *ptr_yy_globals = (yyscan_t) cmListFileLexer_yyalloc ( sizeof( struct yyguts_t ), NULL );
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
if (*ptr_yy_globals == NULL){
errno = ENOMEM;
@@ -2223,27 +2396,25 @@ int cmListFileLexer_yylex_init(yyscan_t* ptr_yy_globals)
return yy_init_globals ( *ptr_yy_globals );
}
-/* cmListFileLexer_yylex_init_extra has the same functionality as cmListFileLexer_yylex_init, but follows the
+/* yylex_init_extra has the same functionality as yylex_init, but follows the
* convention of taking the scanner as the last argument. Note however, that
* this is a *pointer* to a scanner, as it will be allocated by this call (and
* is the reason, too, why this function also must handle its own declaration).
- * The user defined value in the first argument will be available to cmListFileLexer_yyalloc in
+ * The user defined value in the first argument will be available to yyalloc in
* the yyextra field.
*/
-
-int cmListFileLexer_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
-
+int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals )
{
struct yyguts_t dummy_yyguts;
- cmListFileLexer_yyset_extra (yy_user_defined, &dummy_yyguts);
+ yyset_extra (yy_user_defined, &dummy_yyguts);
if (ptr_yy_globals == NULL){
errno = EINVAL;
return 1;
}
- *ptr_yy_globals = (yyscan_t) cmListFileLexer_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
if (*ptr_yy_globals == NULL){
errno = ENOMEM;
@@ -2254,7 +2425,7 @@ int cmListFileLexer_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr
yy_init_globals. Leave at 0x00 for releases. */
memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
- cmListFileLexer_yyset_extra (yy_user_defined, *ptr_yy_globals);
+ yyset_extra (yy_user_defined, *ptr_yy_globals);
return yy_init_globals ( *ptr_yy_globals );
}
@@ -2263,7 +2434,7 @@ static int yy_init_globals (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* Initialization is the same as for the non-reentrant scanner.
- * This function is called from cmListFileLexer_yylex_destroy(), so don't allocate here.
+ * This function is called from yylex_destroy(), so don't allocate here.
*/
yyg->yy_buffer_stack = NULL;
@@ -2287,37 +2458,37 @@ static int yy_init_globals (yyscan_t yyscanner)
#endif
/* For future reference: Set errno on error, since we are called by
- * cmListFileLexer_yylex_init()
+ * yylex_init()
*/
return 0;
}
-/* cmListFileLexer_yylex_destroy is for both reentrant and non-reentrant scanners. */
-int cmListFileLexer_yylex_destroy (yyscan_t yyscanner)
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* Pop the buffer stack, destroying each element. */
while(YY_CURRENT_BUFFER){
- cmListFileLexer_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+ yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner );
YY_CURRENT_BUFFER_LVALUE = NULL;
- cmListFileLexer_yypop_buffer_state(yyscanner);
+ yypop_buffer_state(yyscanner);
}
/* Destroy the stack itself. */
- cmListFileLexer_yyfree(yyg->yy_buffer_stack ,yyscanner);
+ yyfree(yyg->yy_buffer_stack , yyscanner);
yyg->yy_buffer_stack = NULL;
/* Destroy the start condition stack. */
- cmListFileLexer_yyfree(yyg->yy_start_stack ,yyscanner );
+ yyfree( yyg->yy_start_stack , yyscanner );
yyg->yy_start_stack = NULL;
/* Reset the globals. This is important in a non-reentrant scanner so the next time
- * cmListFileLexer_yylex() is called, initialization will occur. */
+ * yylex() is called, initialization will occur. */
yy_init_globals( yyscanner);
/* Destroy the main struct (reentrant only). */
- cmListFileLexer_yyfree ( yyscanner , yyscanner );
+ yyfree ( yyscanner , yyscanner );
yyscanner = NULL;
return 0;
}
@@ -2327,7 +2498,7 @@ int cmListFileLexer_yylex_destroy (yyscan_t yyscanner)
*/
#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
@@ -2339,7 +2510,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca
#endif
#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+static int yy_flex_strlen (const char * s , yyscan_t yyscanner)
{
int n;
for ( n = 0; s[n]; ++n )
@@ -2349,14 +2520,14 @@ static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
}
#endif
-void *cmListFileLexer_yyalloc (yy_size_t size , yyscan_t yyscanner)
+void *yyalloc (yy_size_t size , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
return malloc(size);
}
-void *cmListFileLexer_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
+void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
@@ -2371,19 +2542,15 @@ void *cmListFileLexer_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscann
return realloc(ptr, size);
}
-void cmListFileLexer_yyfree (void * ptr , yyscan_t yyscanner)
+void yyfree (void * ptr , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg;
- free( (char *) ptr ); /* see cmListFileLexer_yyrealloc() for (char *) cast */
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
}
#define YYTABLES_NAME "yytables"
-#line 265 "cmListFileLexer.in.l"
-
-
-
/*--------------------------------------------------------------------------*/
static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text,
int length)
diff --git a/Source/LexerParser/cmListFileLexer.in.l b/Source/LexerParser/cmListFileLexer.in.l
index 5152dbf08..fdf14d2d3 100644
--- a/Source/LexerParser/cmListFileLexer.in.l
+++ b/Source/LexerParser/cmListFileLexer.in.l
@@ -7,20 +7,18 @@ This file must be translated to C and modified to build everywhere.
Run flex >= 2.6 like this:
- flex --nounistd -DFLEXINT_H --prefix=cmListFileLexer_yy -ocmListFileLexer.c cmListFileLexer.in.l
+ flex --nounistd -DFLEXINT_H --noline -ocmListFileLexer.c cmListFileLexer.in.l
Modify cmListFileLexer.c:
- - remove trailing whitespace: sed -i 's/\s*$//' cmListFileLexer.c
- - remove blank lines at end of file
- - #include "cmStandardLexer.h" at the top
- - add cast in yy_scan_bytes for loop condition of _yybytes_len to size_t
- - change type of variable yyl under yy_find_action from yy_size_t to int
+ - remove trailing whitespace: sed -i 's/\s*$//' cmListFileLexer.c
+ - remove blank lines at end of file: sed -i '${/^$/d;}' cmListFileLexer.c
+ - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmListFileLexer.c
*/
/* IWYU pragma: no_forward_declare yyguts_t */
-#ifdef WIN32
+#ifdef _WIN32
#include "cmsys/Encoding.h"
#endif
@@ -59,11 +57,13 @@ static void cmListFileLexerDestroy(cmListFileLexer* lexer);
/* Replace the lexer input function. */
#undef YY_INPUT
#define YY_INPUT(buf, result, max_size) \
- { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); }
+ do { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); } while (0)
/*--------------------------------------------------------------------------*/
%}
+%option prefix="cmListFileLexer_yy"
+
%option reentrant
%option yylineno
%option noyywrap
@@ -74,7 +74,7 @@ static void cmListFileLexerDestroy(cmListFileLexer* lexer);
%x COMMENT
MAKEVAR \$\([A-Za-z0-9_]*\)
-UNQUOTED ([^ \t\r\n\(\)#\\\"[=]|\\.)
+UNQUOTED ([^ \0\t\r\n\(\)#\\\"[=]|\\[^\0\n])
LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t[=])*\"
%%
@@ -113,7 +113,7 @@ LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t[=])*\"
BEGIN(COMMENT);
}
-<COMMENT>.* {
+<COMMENT>[^\0\n]* {
lexer->column += yyleng;
}
@@ -156,7 +156,7 @@ LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t[=])*\"
return 1;
}
-<BRACKET>([^]\n])+ {
+<BRACKET>([^]\0\n])+ {
cmListFileLexerAppend(lexer, yytext, yyleng);
lexer->column += yyleng;
}
@@ -168,7 +168,7 @@ LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t[=])*\"
BEGIN(BRACKET);
}
-<BRACKET,BRACKETEND>. {
+<BRACKET,BRACKETEND>[^\0\n] {
cmListFileLexerAppend(lexer, yytext, yyleng);
lexer->column += yyleng;
BEGIN(BRACKET);
@@ -208,7 +208,7 @@ LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t[=])*\"
BEGIN(STRING);
}
-<STRING>([^\\\n\"]|\\.)+ {
+<STRING>([^\\\0\n\"]|\\[^\0\n])+ {
cmListFileLexerAppend(lexer, yytext, yyleng);
lexer->column += yyleng;
}
@@ -231,7 +231,7 @@ LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t[=])*\"
return 1;
}
-<STRING>. {
+<STRING>[^\0\n] {
cmListFileLexerAppend(lexer, yytext, yyleng);
lexer->column += yyleng;
}
@@ -439,11 +439,15 @@ static cmListFileLexer_BOM cmListFileLexer_ReadBOM(FILE* f)
if (fread(b, 1, 2, f) == 2 && b[0] == 0 && b[1] == 0) {
return cmListFileLexer_BOM_UTF32LE;
}
- fsetpos(f, &p);
+ if (fsetpos(f, &p) != 0) {
+ return cmListFileLexer_BOM_Broken;
+ }
return cmListFileLexer_BOM_UTF16LE;
}
}
- rewind(f);
+ if (fseek(f, 0, SEEK_SET) != 0) {
+ return cmListFileLexer_BOM_Broken;
+ }
return cmListFileLexer_BOM_None;
}
diff --git a/Source/Modules/CheckCXXLinkerFlag.cmake b/Source/Modules/CheckCXXLinkerFlag.cmake
new file mode 100644
index 000000000..6cb1ba3ac
--- /dev/null
+++ b/Source/Modules/CheckCXXLinkerFlag.cmake
@@ -0,0 +1,29 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+include_guard(GLOBAL)
+include(CheckCXXSourceCompiles)
+include(CMakeCheckCompilerFlagCommonPatterns)
+
+function(check_cxx_linker_flag _flag _var)
+ if(CMAKE_VERSION VERSION_LESS "3.14")
+ set(CMAKE_REQUIRED_LIBRARIES "${_flag}")
+ else()
+ set(CMAKE_REQUIRED_LINK_OPTIONS "${_flag}")
+ endif()
+
+ # Normalize locale during test compilation.
+ set(_locale_vars LC_ALL LC_MESSAGES LANG)
+ foreach(v IN LISTS _locale_vars)
+ set(_locale_vars_saved_${v} "$ENV{${v}}")
+ set(ENV{${v}} C)
+ endforeach()
+ check_compiler_flag_common_patterns(_common_patterns)
+ check_cxx_source_compiles("int main() { return 0; }" ${_var}
+ ${_common_patterns}
+ )
+ foreach(v IN LISTS _locale_vars)
+ set(ENV{${v}} ${_locale_vars_saved_${v}})
+ endforeach()
+ set(${_var} "${${_var}}" PARENT_SCOPE)
+endfunction()
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/FindLibUV.cmake b/Source/Modules/FindLibUV.cmake
index ba13d75f8..0554d62c2 100644
--- a/Source/Modules/FindLibUV.cmake
+++ b/Source/Modules/FindLibUV.cmake
@@ -63,6 +63,8 @@ mark_as_advanced(LibUV_INCLUDE_DIR)
set(_LibUV_H_REGEX "#[ \t]*define[ \t]+UV_VERSION_(MAJOR|MINOR|PATCH)[ \t]+[0-9]+")
if(LibUV_INCLUDE_DIR AND EXISTS "${LibUV_INCLUDE_DIR}/uv-version.h")
file(STRINGS "${LibUV_INCLUDE_DIR}/uv-version.h" _LibUV_H REGEX "${_LibUV_H_REGEX}")
+elseif(LibUV_INCLUDE_DIR AND EXISTS "${LibUV_INCLUDE_DIR}/uv/version.h")
+ file(STRINGS "${LibUV_INCLUDE_DIR}/uv/version.h" _LibUV_H REGEX "${_LibUV_H_REGEX}")
elseif(LibUV_INCLUDE_DIR AND EXISTS "${LibUV_INCLUDE_DIR}/uv.h")
file(STRINGS "${LibUV_INCLUDE_DIR}/uv.h" _LibUV_H REGEX "${_LibUV_H_REGEX}")
else()
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/AddCacheEntry.cxx b/Source/QtDialog/AddCacheEntry.cxx
index 6284ac946..f5e0777bf 100644
--- a/Source/QtDialog/AddCacheEntry.cxx
+++ b/Source/QtDialog/AddCacheEntry.cxx
@@ -21,8 +21,8 @@ AddCacheEntry::AddCacheEntry(QWidget* p, const QStringList& varNames,
, VarTypes(varTypes)
{
this->setupUi(this);
- for (int i = 0; i < NumTypes; i++) {
- this->Type->addItem(TypeStrings[i]);
+ for (auto const& elem : TypeStrings) {
+ this->Type->addItem(elem);
}
QWidget* cb = new QCheckBox();
QWidget* path = new QCMakePathEditor();
@@ -32,12 +32,12 @@ AddCacheEntry::AddCacheEntry(QWidget* p, const QStringList& varNames,
this->StackedWidget->addWidget(path);
this->StackedWidget->addWidget(filepath);
this->StackedWidget->addWidget(string);
- this->setTabOrder(this->Name, this->Type);
- this->setTabOrder(this->Type, cb);
- this->setTabOrder(cb, path);
- this->setTabOrder(path, filepath);
- this->setTabOrder(filepath, string);
- this->setTabOrder(string, this->Description);
+ AddCacheEntry::setTabOrder(this->Name, this->Type);
+ AddCacheEntry::setTabOrder(this->Type, cb);
+ AddCacheEntry::setTabOrder(cb, path);
+ AddCacheEntry::setTabOrder(path, filepath);
+ AddCacheEntry::setTabOrder(filepath, string);
+ AddCacheEntry::setTabOrder(string, this->Description);
QCompleter* completer = new QCompleter(this->VarNames, this);
this->Name->setCompleter(completer);
connect(completer, SIGNAL(activated(const QString&)), this,
diff --git a/Source/QtDialog/AddCacheEntry.h b/Source/QtDialog/AddCacheEntry.h
index cc710f558..e7a60ddb3 100644
--- a/Source/QtDialog/AddCacheEntry.h
+++ b/Source/QtDialog/AddCacheEntry.h
@@ -4,14 +4,15 @@
#define AddCacheEntry_h
#include "QCMake.h"
-
#include <QCheckBox>
#include <QStringList>
#include <QWidget>
#include "ui_AddCacheEntry.h"
-class AddCacheEntry : public QWidget, public Ui::AddCacheEntry
+class AddCacheEntry
+ : public QWidget
+ , public Ui::AddCacheEntry
{
Q_OBJECT
public:
diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt
index 9e9df781e..cb89d19fd 100644
--- a/Source/QtDialog/CMakeLists.txt
+++ b/Source/QtDialog/CMakeLists.txt
@@ -2,9 +2,6 @@
# file Copyright.txt or https://cmake.org/licensing for details.
project(QtDialog)
-if(POLICY CMP0020)
- cmake_policy(SET CMP0020 NEW) # Drop when CMake >= 2.8.11 required
-endif()
CMake_OPTIONAL_COMPONENT(cmake-gui)
find_package(Qt5Widgets QUIET)
if (Qt5Widgets_FOUND)
@@ -19,9 +16,20 @@ if (Qt5Widgets_FOUND)
macro(qt4_add_resources)
qt5_add_resources(${ARGN})
endmacro()
+
set(CMake_QT_LIBRARIES ${Qt5Widgets_LIBRARIES})
set(QT_QTMAIN_LIBRARY ${Qt5Core_QTMAIN_LIBRARIES})
+ # Try to find the package WinExtras for the task bar progress
+ if(WIN32)
+ find_package(Qt5WinExtras QUIET)
+ if (Qt5WinExtras_FOUND)
+ include_directories(${Qt5WinExtras_INCLUDE_DIRS})
+ add_definitions(-DQT_WINEXTRAS)
+ list(APPEND CMake_QT_LIBRARIES ${Qt5WinExtras_LIBRARIES})
+ endif()
+ endif()
+
# Remove this when the minimum version of Qt is 4.6.
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0)
@@ -33,8 +41,14 @@ if (Qt5Widgets_FOUND)
PROPERTY COMPILE_DEFINITIONS USE_QXcbIntegrationPlugin)
endif()
+ if(CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES)
+ list(APPEND CMake_QT_LIBRARIES ${CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES})
+ set_property(SOURCE CMakeSetup.cxx
+ PROPERTY COMPILE_DEFINITIONS USE_QWindowsIntegrationPlugin)
+ 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)
@@ -65,7 +79,7 @@ if (Qt5Widgets_FOUND)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources"
${COMPONENT})
- elseif(WIN32)
+ elseif(WIN32 AND NOT CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES)
install_qt5_plugin("Qt5::QWindowsIntegrationPlugin" QT_PLUGINS)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
"[Paths]\nPlugins = ../${_qt_plugin_dir}\n")
@@ -160,6 +174,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 7fa2ac661..ee81a7d62 100644
--- a/Source/QtDialog/CMakeSetup.cxx
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -1,16 +1,8 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "QCMake.h" // include to disable MS warnings
+#include <iostream>
-#include "CMakeSetupDialog.h"
-#include "cmAlgorithms.h"
-#include "cmDocumentation.h"
-#include "cmDocumentationEntry.h"
-#include "cmVersion.h"
-#include "cmake.h"
-#include "cmsys/CommandLineArguments.hxx"
-#include "cmsys/Encoding.hxx"
-#include "cmsys/SystemTools.hxx"
+#include "QCMake.h" // include to disable MS warnings
#include <QApplication>
#include <QDir>
#include <QLocale>
@@ -18,23 +10,34 @@
#include <QTextCodec>
#include <QTranslator>
#include <QtPlugin>
-#include <iostream>
+#include "cmsys/CommandLineArguments.hxx"
+#include "cmsys/Encoding.hxx"
+#include "cmsys/SystemTools.hxx"
+
+#include "CMakeSetupDialog.h"
+#include "cmAlgorithms.h"
+#include "cmDocumentation.h"
+#include "cmDocumentationEntry.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h" // IWYU pragma: keep
+#include "cmVersion.h"
+#include "cmake.h"
-static const char* cmDocumentationName[][2] = { { CM_NULLPTR,
+static const char* cmDocumentationName[][2] = { { nullptr,
" cmake-gui - CMake GUI." },
- { CM_NULLPTR, CM_NULLPTR } };
+ { nullptr, nullptr } };
static const char* cmDocumentationUsage[][2] = {
- { CM_NULLPTR, " cmake-gui [options]\n"
- " cmake-gui [options] <path-to-source>\n"
- " cmake-gui [options] <path-to-existing-build>" },
- { CM_NULLPTR, CM_NULLPTR }
+ { nullptr,
+ " cmake-gui [options]\n"
+ " cmake-gui [options] <path-to-source>\n"
+ " cmake-gui [options] <path-to-existing-build>\n"
+ " cmake-gui [options] -S <path-to-source> -B <path-to-build>\n" },
+ { nullptr, nullptr }
};
-static const char* cmDocumentationOptions[]
- [2] = { { CM_NULLPTR, CM_NULLPTR } };
+static const char* cmDocumentationOptions[][2] = { { nullptr, nullptr } };
#if defined(Q_OS_MAC)
static int cmOSXInstall(std::string dir);
@@ -45,13 +48,22 @@ static void cmAddPluginPath();
Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
#endif
+#if defined(USE_QWindowsIntegrationPlugin)
+Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
+# if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
+Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin);
+# endif
+#endif
+
int main(int argc, char** argv)
{
+ cmSystemTools::EnsureStdPipes();
cmsys::Encoding::CommandLineArguments encoding_args =
cmsys::Encoding::CommandLineArguments::Main(argc, 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
@@ -59,13 +71,12 @@ int main(int argc, char** argv)
doc.addCMakeStandardDocSections();
if (argc2 > 1 && doc.CheckOptions(argc2, argv2)) {
// Construct and print requested documentation.
- cmake hcm(cmake::RoleInternal);
+ cmake hcm(cmake::RoleInternal, cmState::Unknown);
hcm.SetHomeDirectory("");
hcm.SetHomeOutputDirectory("");
hcm.AddCMakePaths();
- std::vector<cmDocumentationEntry> generators;
- hcm.GetGeneratorDocumentation(generators);
+ auto generators = hcm.GetGeneratorsDocumentation();
doc.SetName("cmake");
doc.SetSection("Name", cmDocumentationName);
doc.SetSection("Usage", cmDocumentationUsage);
@@ -93,6 +104,10 @@ int main(int argc, char** argv)
cmAddPluginPath();
#endif
+#if QT_VERSION >= 0x050600
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
+
QApplication app(argc, argv);
setlocale(LC_NUMERIC, "C");
@@ -121,36 +136,66 @@ int main(int argc, char** argv)
QTranslator translator;
QString transfile = QString("cmake_%1").arg(QLocale::system().name());
translator.load(transfile, translationsDir.path());
- app.installTranslator(&translator);
+ QApplication::installTranslator(&translator);
// app setup
- app.setApplicationName("CMakeSetup");
- app.setOrganizationName("Kitware");
+ QApplication::setApplicationName("CMakeSetup");
+ QApplication::setOrganizationName("Kitware");
QIcon appIcon;
appIcon.addFile(":/Icons/CMakeSetup32.png");
appIcon.addFile(":/Icons/CMakeSetup128.png");
- app.setWindowIcon(appIcon);
+ QApplication::setWindowIcon(appIcon);
CMakeSetupDialog dialog;
dialog.show();
- cmsys::CommandLineArguments arg;
- arg.Initialize(argc2, argv2);
+ QStringList args = QApplication::arguments();
std::string binaryDirectory;
std::string sourceDirectory;
- typedef cmsys::CommandLineArguments argT;
- arg.AddArgument("-B", argT::CONCAT_ARGUMENT, &binaryDirectory,
- "Binary Directory");
- arg.AddArgument("-H", argT::CONCAT_ARGUMENT, &sourceDirectory,
- "Source Directory");
- // do not complain about unknown options
- arg.StoreUnusedArguments(true);
- arg.Parse();
+ for (int i = 1; i < args.size(); ++i) {
+ const QString& arg = args[i];
+ if (arg.startsWith("-S")) {
+ QString path = arg.mid(2);
+ if (path.isEmpty()) {
+ ++i;
+ if (i >= args.size()) {
+ std::cerr << "No source directory specified for -S" << std::endl;
+ return 1;
+ }
+ path = args[i];
+ if (path[0] == '-') {
+ std::cerr << "No source directory specified for -S" << std::endl;
+ return 1;
+ }
+ }
+
+ sourceDirectory =
+ cmSystemTools::CollapseFullPath(path.toLocal8Bit().data());
+ cmSystemTools::ConvertToUnixSlashes(sourceDirectory);
+ } else if (arg.startsWith("-B")) {
+ QString path = arg.mid(2);
+ if (path.isEmpty()) {
+ ++i;
+ if (i >= args.size()) {
+ std::cerr << "No build directory specified for -B" << std::endl;
+ return 1;
+ }
+ path = args[i];
+ if (path[0] == '-') {
+ std::cerr << "No build directory specified for -B" << std::endl;
+ return 1;
+ }
+ }
+
+ binaryDirectory =
+ cmSystemTools::CollapseFullPath(path.toLocal8Bit().data());
+ cmSystemTools::ConvertToUnixSlashes(binaryDirectory);
+ }
+ }
if (!sourceDirectory.empty() && !binaryDirectory.empty()) {
dialog.setSourceDirectory(QString::fromLocal8Bit(sourceDirectory.c_str()));
dialog.setBinaryDirectory(QString::fromLocal8Bit(binaryDirectory.c_str()));
} else {
- QStringList args = app.arguments();
if (args.count() == 2) {
std::string filePath =
cmSystemTools::CollapseFullPath(args[1].toLocal8Bit().data());
@@ -180,14 +225,16 @@ int main(int argc, char** argv)
}
}
- return app.exec();
+ return QApplication::exec();
}
#if defined(Q_OS_MAC)
-#include "cm_sys_stat.h"
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
+# include <cerrno>
+# include <cstring>
+
+# include <unistd.h>
+
+# include "cm_sys_stat.h"
static bool cmOSXInstall(std::string const& dir, std::string const& tool)
{
if (tool.empty()) {
@@ -207,12 +254,11 @@ static bool cmOSXInstall(std::string const& dir, std::string const& tool)
if (symlink(tool.c_str(), link.c_str()) == 0) {
std::cerr << "Linked: '" << link << "' -> '" << tool << "'\n";
return true;
- } else {
- int err = errno;
- std::cerr << "Failed: '" << link << "' -> '" << tool
- << "': " << strerror(err) << "\n";
- return false;
}
+ int err = errno;
+ std::cerr << "Failed: '" << link << "' -> '" << tool
+ << "': " << strerror(err) << "\n";
+ return false;
}
static int cmOSXInstall(std::string dir)
{
diff --git a/Source/QtDialog/CMakeSetup.icns b/Source/QtDialog/CMakeSetup.icns
index 4a50c0416..e0bf8fdfa 100644
--- a/Source/QtDialog/CMakeSetup.icns
+++ b/Source/QtDialog/CMakeSetup.icns
Binary files differ
diff --git a/Source/QtDialog/CMakeSetup.ico b/Source/QtDialog/CMakeSetup.ico
index e13bb156f..1ac13c830 100644
--- a/Source/QtDialog/CMakeSetup.ico
+++ b/Source/QtDialog/CMakeSetup.ico
Binary files differ
diff --git a/Source/QtDialog/CMakeSetup128.png b/Source/QtDialog/CMakeSetup128.png
index 12f1d9a9a..32984e104 100644
--- a/Source/QtDialog/CMakeSetup128.png
+++ b/Source/QtDialog/CMakeSetup128.png
Binary files differ
diff --git a/Source/QtDialog/CMakeSetup32.png b/Source/QtDialog/CMakeSetup32.png
index 7bbcee413..78df82f15 100644
--- a/Source/QtDialog/CMakeSetup32.png
+++ b/Source/QtDialog/CMakeSetup32.png
Binary files differ
diff --git a/Source/QtDialog/CMakeSetup64.png b/Source/QtDialog/CMakeSetup64.png
index 43a8cc6af..5c2dbf552 100644
--- a/Source/QtDialog/CMakeSetup64.png
+++ b/Source/QtDialog/CMakeSetup64.png
Binary files differ
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
index 57f8e107e..436a90466 100644
--- a/Source/QtDialog/CMakeSetupDialog.cxx
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -21,18 +21,25 @@
#include <QToolButton>
#include <QUrl>
-#include "AddCacheEntry.h"
-#include "FirstConfigure.h"
+#ifdef QT_WINEXTRAS
+# include <QWinTaskbarButton>
+# include <QWinTaskbarProgress>
+#endif
+
#include "QCMake.h"
#include "QCMakeCacheView.h"
-#include "RegexExplorer.h"
-#include "WarningMessagesDialog.h"
+
#include "cmSystemTools.h"
#include "cmVersion.h"
+#include "AddCacheEntry.h"
+#include "FirstConfigure.h"
+#include "RegexExplorer.h"
+#include "WarningMessagesDialog.h"
+
QCMakeThread::QCMakeThread(QObject* p)
: QThread(p)
- , CMakeInstance(CM_NULLPTR)
+ , CMakeInstance(nullptr)
{
}
@@ -48,7 +55,7 @@ void QCMakeThread::run()
emit this->cmakeInitialized();
this->exec();
delete this->CMakeInstance;
- this->CMakeInstance = CM_NULLPTR;
+ this->CMakeInstance = nullptr;
}
CMakeSetupDialog::CMakeSetupDialog()
@@ -108,7 +115,7 @@ CMakeSetupDialog::CMakeSetupDialog()
QMenu* ToolsMenu = this->menuBar()->addMenu(tr("&Tools"));
this->ConfigureAction = ToolsMenu->addAction(tr("&Configure"));
- // prevent merging with Preferences menu item on Mac OS X
+ // prevent merging with Preferences menu item on macOS
this->ConfigureAction->setMenuRole(QAction::NoRole);
QObject::connect(this->ConfigureAction, SIGNAL(triggered(bool)), this,
SLOT(doConfigure()));
@@ -188,6 +195,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 +259,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,
@@ -287,6 +301,11 @@ void CMakeSetupDialog::initialize()
} else {
this->onBinaryDirectoryChanged(this->BinaryDirectory->lineEdit()->text());
}
+
+#ifdef QT_WINEXTRAS
+ this->TaskbarButton = new QWinTaskbarButton(this);
+ this->TaskbarButton->setWindow(this->windowHandle());
+#endif
}
CMakeSetupDialog::~CMakeSetupDialog()
@@ -374,6 +393,10 @@ void CMakeSetupDialog::doConfigure()
this->CacheValues->scrollToTop();
}
this->ProgressBar->reset();
+
+#ifdef QT_WINEXTRAS
+ this->TaskbarButton->progress()->reset();
+#endif
}
bool CMakeSetupDialog::doConfigureInternal()
@@ -488,28 +511,17 @@ void CMakeSetupDialog::doGenerate()
this->enterState(ReadyConfigure);
this->ProgressBar->reset();
+#ifdef QT_WINEXTRAS
+ this->TaskbarButton->progress()->reset();
+#endif
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 +642,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()
@@ -686,6 +693,12 @@ void CMakeSetupDialog::showProgress(const QString& /*msg*/, float percent)
{
percent = (percent * ProgressFactor) + ProgressOffset;
this->ProgressBar->setValue(qRound(percent * 100));
+
+#ifdef QT_WINEXTRAS
+ QWinTaskbarProgress* progress = this->TaskbarButton->progress();
+ progress->setVisible(true);
+ progress->setValue(qRound(percent * 100));
+#endif
}
void CMakeSetupDialog::error(const QString& msg)
@@ -739,6 +752,7 @@ bool CMakeSetupDialog::setupFirstConfigure()
if (dialog.exec() == QDialog::Accepted) {
dialog.saveToSettings();
this->CMakeThread->cmakeInstance()->setGenerator(dialog.getGenerator());
+ this->CMakeThread->cmakeInstance()->setPlatform(dialog.getPlatform());
this->CMakeThread->cmakeInstance()->setToolset(dialog.getToolset());
QCMakeCacheModel* m = this->CacheValues->cacheModel();
@@ -850,11 +864,11 @@ void CMakeSetupDialog::doAbout()
"built using Qt %2 (qt-project.org).\n"
#ifdef USE_LGPL
"\n"
- "The Qt Toolkit is Copyright (C) Digia Plc and/or its subsidiary(-ies).\n"
+ "The Qt Toolkit is Copyright (C) The Qt Company Ltd.\n"
"Qt is licensed under terms of the GNU LGPLv" USE_LGPL ", available at:\n"
" \"%3\""
#endif
- );
+ );
msg = msg.arg(cmVersion::GetCMakeVersion());
msg = msg.arg(qVersion());
#ifdef USE_LGPL
@@ -1001,8 +1015,9 @@ void CMakeSetupDialog::removeSelectedCacheEntries()
void CMakeSetupDialog::selectionChanged()
{
QModelIndexList idxs = this->CacheValues->selectionModel()->selectedRows();
- if (idxs.count() && (this->CurrentState == ReadyConfigure ||
- this->CurrentState == ReadyGenerate)) {
+ if (idxs.count() &&
+ (this->CurrentState == ReadyConfigure ||
+ this->CurrentState == ReadyGenerate)) {
this->RemoveEntry->setEnabled(true);
} else {
this->RemoveEntry->setEnabled(false);
@@ -1039,9 +1054,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 +1061,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"));
}
@@ -1195,7 +1204,7 @@ void CMakeSetupDialog::setSearchFilter(const QString& str)
this->CacheValues->setSearchFilter(str);
}
-void CMakeSetupDialog::doOutputContextMenu(const QPoint& pt)
+void CMakeSetupDialog::doOutputContextMenu(QPoint pt)
{
QMenu* menu = this->Output->createStandardContextMenu();
diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h
index 1abdb462d..f23aee6e8 100644
--- a/Source/QtDialog/CMakeSetupDialog.h
+++ b/Source/QtDialog/CMakeSetupDialog.h
@@ -4,19 +4,25 @@
#define CMakeSetupDialog_h
#include "QCMake.h"
-
-#include "ui_CMakeSetupDialog.h"
#include <QEventLoop>
#include <QMainWindow>
#include <QThread>
+#include "ui_CMakeSetupDialog.h"
+
class QCMakeThread;
class CMakeCacheModel;
class QProgressBar;
class QToolButton;
+#ifdef QT_WINEXTRAS
+class QWinTaskbarButton;
+#endif
+
/// Qt user interface for CMake
-class CMakeSetupDialog : public QMainWindow, public Ui::CMakeSetupDialog
+class CMakeSetupDialog
+ : public QMainWindow
+ , public Ui::CMakeSetupDialog
{
Q_OBJECT
public:
@@ -31,7 +37,6 @@ protected slots:
void initialize();
void doConfigure();
void doGenerate();
- QString getProjectFilename();
void doOpenProject();
void doInstallForCommandLine();
void doHelp();
@@ -70,7 +75,7 @@ protected slots:
bool doConfigureInternal();
bool doGenerateInternal();
void exitLoop(int);
- void doOutputContextMenu(const QPoint&);
+ void doOutputContextMenu(QPoint pt);
void doOutputFindDialog();
void doOutputFindNext(bool directionForward = true);
void doOutputFindPrev();
@@ -117,6 +122,10 @@ protected:
QEventLoop LocalLoop;
+#ifdef QT_WINEXTRAS
+ QWinTaskbarButton* TaskbarButton;
+#endif
+
float ProgressOffset;
float ProgressFactor;
};
diff --git a/Source/QtDialog/CMakeSetupDialog.ui b/Source/QtDialog/CMakeSetupDialog.ui
index 8d8e0cdc2..dc22a2989 100644
--- a/Source/QtDialog/CMakeSetupDialog.ui
+++ b/Source/QtDialog/CMakeSetupDialog.ui
@@ -57,6 +57,9 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
+ <property name="styleSheet">
+ <string notr="true">padding-left: 0</string>
+ </property>
<property name="editable">
<bool>true</bool>
</property>
diff --git a/Source/QtDialog/Compilers.h b/Source/QtDialog/Compilers.h
index 6c8c8f52a..931c93566 100644
--- a/Source/QtDialog/Compilers.h
+++ b/Source/QtDialog/Compilers.h
@@ -3,17 +3,19 @@
#ifndef COMPILERS_HPP
#define COMPILERS_HPP
-#include "cmConfigure.h"
-
-#include <QWidget>
+#include "cmConfigure.h" // IWYU pragma: keep
#include <ui_Compilers.h>
-class Compilers : public QWidget, public Ui::Compilers
+#include <QWidget>
+
+class Compilers
+ : public QWidget
+ , public Ui::Compilers
{
Q_OBJECT
public:
- Compilers(QWidget* p = CM_NULLPTR)
+ Compilers(QWidget* p = nullptr)
: QWidget(p)
{
this->setupUi(this);
diff --git a/Source/QtDialog/Delete16.png b/Source/QtDialog/Delete16.png
index 16989fee1..9d2f2b7ec 100644
--- a/Source/QtDialog/Delete16.png
+++ b/Source/QtDialog/Delete16.png
Binary files differ
diff --git a/Source/QtDialog/FirstConfigure.cxx b/Source/QtDialog/FirstConfigure.cxx
index b193a2782..ca28b1972 100644
--- a/Source/QtDialog/FirstConfigure.cxx
+++ b/Source/QtDialog/FirstConfigure.cxx
@@ -1,13 +1,15 @@
#include "FirstConfigure.h"
-#include "Compilers.h"
-
#include <QComboBox>
#include <QRadioButton>
#include <QSettings>
#include <QVBoxLayout>
+#include "cmStringAlgorithms.h"
+
+#include "Compilers.h"
+
StartCompilerSetup::StartCompilerSetup(QWidget* p)
: QWizardPage(p)
{
@@ -16,8 +18,12 @@ StartCompilerSetup::StartCompilerSetup(QWidget* p)
this->GeneratorOptions = new QComboBox(this);
l->addWidget(this->GeneratorOptions);
+ // Add the generator platform
+ this->PlatformFrame = CreatePlatformWidgets();
+ l->addWidget(PlatformFrame);
+
// Add the ability to specify toolset (-T parameter)
- ToolsetFrame = CreateToolsetWidgets();
+ this->ToolsetFrame = CreateToolsetWidgets();
l->addWidget(ToolsetFrame);
l->addSpacing(6);
@@ -45,7 +51,7 @@ StartCompilerSetup::StartCompilerSetup(QWidget* p)
SLOT(onSelectionChanged(bool)));
QObject::connect(this->CompilerSetupOptions[3], SIGNAL(toggled(bool)), this,
SLOT(onSelectionChanged(bool)));
- QObject::connect(GeneratorOptions,
+ QObject::connect(this->GeneratorOptions,
SIGNAL(currentIndexChanged(QString const&)), this,
SLOT(onGeneratorChanged(QString const&)));
}
@@ -65,10 +71,25 @@ QFrame* StartCompilerSetup::CreateToolsetWidgets()
return frame;
}
-StartCompilerSetup::~StartCompilerSetup()
+QFrame* StartCompilerSetup::CreatePlatformWidgets()
{
+ QFrame* frame = new QFrame(this);
+ QVBoxLayout* l = new QVBoxLayout(frame);
+ l->setContentsMargins(0, 0, 0, 0);
+
+ this->PlatformLabel = new QLabel(tr("Optional platform for generator"));
+ l->addWidget(this->PlatformLabel);
+
+ this->PlatformOptions = new QComboBox(frame);
+ this->PlatformOptions->setEditable(true);
+
+ l->addWidget(this->PlatformOptions);
+
+ return frame;
}
+StartCompilerSetup::~StartCompilerSetup() = default;
+
void StartCompilerSetup::setGenerators(
std::vector<cmake::GeneratorInfo> const& gens)
{
@@ -76,13 +97,31 @@ void StartCompilerSetup::setGenerators(
QStringList generator_list;
- std::vector<cmake::GeneratorInfo>::const_iterator it;
- for (it = gens.begin(); it != gens.end(); ++it) {
- generator_list.append(QString::fromLocal8Bit(it->name.c_str()));
+ for (cmake::GeneratorInfo const& gen : gens) {
+ generator_list.append(QString::fromLocal8Bit(gen.name.c_str()));
+
+ if (gen.supportsPlatform) {
+ this->GeneratorsSupportingPlatform.append(
+ QString::fromLocal8Bit(gen.name.c_str()));
+
+ this
+ ->GeneratorDefaultPlatform[QString::fromLocal8Bit(gen.name.c_str())] =
+ QString::fromLocal8Bit(gen.defaultPlatform.c_str());
+
+ auto platformIt = gen.supportedPlatforms.cbegin();
+ while (platformIt != gen.supportedPlatforms.cend()) {
+
+ this->GeneratorSupportedPlatforms.insert(
+ QString::fromLocal8Bit(gen.name.c_str()),
+ QString::fromLocal8Bit((*platformIt).c_str()));
+
+ platformIt++;
+ }
+ }
- if (it->supportsToolset) {
+ if (gen.supportsToolset) {
this->GeneratorsSupportingToolset.append(
- QString::fromLocal8Bit(it->name.c_str()));
+ QString::fromLocal8Bit(gen.name.c_str()));
}
}
@@ -102,6 +141,11 @@ QString StartCompilerSetup::getGenerator() const
return this->GeneratorOptions->currentText();
};
+QString StartCompilerSetup::getPlatform() const
+{
+ return this->PlatformOptions->currentText();
+};
+
QString StartCompilerSetup::getToolset() const
{
return this->Toolset->text();
@@ -136,6 +180,30 @@ void StartCompilerSetup::onSelectionChanged(bool on)
void StartCompilerSetup::onGeneratorChanged(QString const& name)
{
+ // Display the generator platform for the generators supporting it
+ if (GeneratorsSupportingPlatform.contains(name)) {
+
+ // Change the label title to include the default platform
+ std::string label =
+ cmStrCat("Optional platform for generator(if empty, generator uses: ",
+ this->GeneratorDefaultPlatform[name].toStdString(), ')');
+ this->PlatformLabel->setText(tr(label.c_str()));
+
+ // Regenerate the list of supported platform
+ this->PlatformOptions->clear();
+ QStringList platform_list;
+ platform_list.append("");
+
+ QList<QString> platforms = this->GeneratorSupportedPlatforms.values(name);
+ platform_list.append(platforms);
+
+ this->PlatformOptions->addItems(platform_list);
+ PlatformFrame->show();
+ } else {
+ PlatformFrame->hide();
+ }
+
+ // Display the toolset box for the generators supporting it
if (GeneratorsSupportingToolset.contains(name)) {
ToolsetFrame->show();
} else {
@@ -166,9 +234,7 @@ NativeCompilerSetup::NativeCompilerSetup(QWidget* p)
this->setupUi(c);
}
-NativeCompilerSetup::~NativeCompilerSetup()
-{
-}
+NativeCompilerSetup::~NativeCompilerSetup() = default;
QString NativeCompilerSetup::getCCompiler() const
{
@@ -230,9 +296,7 @@ CrossCompilerSetup::CrossCompilerSetup(QWidget* p)
this->registerField("systemName*", this->systemName);
}
-CrossCompilerSetup::~CrossCompilerSetup()
-{
-}
+CrossCompilerSetup::~CrossCompilerSetup() = default;
QString CrossCompilerSetup::getCCompiler() const
{
@@ -301,7 +365,7 @@ QString CrossCompilerSetup::getFindRoot() const
void CrossCompilerSetup::setFindRoot(const QString& t)
{
- return this->crossFindRoot->setText(t);
+ this->crossFindRoot->setText(t);
}
int CrossCompilerSetup::getProgramMode() const
@@ -343,9 +407,7 @@ ToolchainCompilerSetup::ToolchainCompilerSetup(QWidget* p)
l->addWidget(this->ToolchainFile);
}
-ToolchainCompilerSetup::~ToolchainCompilerSetup()
-{
-}
+ToolchainCompilerSetup::~ToolchainCompilerSetup() = default;
QString ToolchainCompilerSetup::toolchainFile() const
{
@@ -375,9 +437,7 @@ FirstConfigure::FirstConfigure()
this->setPage(ToolchainSetup, this->mToolchainCompilerSetupPage);
}
-FirstConfigure::~FirstConfigure()
-{
-}
+FirstConfigure::~FirstConfigure() = default;
void FirstConfigure::setGenerators(
std::vector<cmake::GeneratorInfo> const& gens)
@@ -390,6 +450,11 @@ QString FirstConfigure::getGenerator() const
return this->mStartCompilerSetupPage->getGenerator();
}
+QString FirstConfigure::getPlatform() const
+{
+ return this->mStartCompilerSetupPage->getPlatform();
+}
+
QString FirstConfigure::getToolset() const
{
return this->mStartCompilerSetupPage->getToolset();
diff --git a/Source/QtDialog/FirstConfigure.h b/Source/QtDialog/FirstConfigure.h
index c467ddb19..d1db5bff6 100644
--- a/Source/QtDialog/FirstConfigure.h
+++ b/Source/QtDialog/FirstConfigure.h
@@ -35,6 +35,7 @@ public:
void setCurrentGenerator(const QString& gen);
QString getGenerator() const;
QString getToolset() const;
+ QString getPlatform() const;
bool defaultSetup() const;
bool compilerSetup() const;
@@ -56,14 +57,23 @@ protected:
QFrame* ToolsetFrame;
QLineEdit* Toolset;
QLabel* ToolsetLabel;
+ QFrame* PlatformFrame;
+ QComboBox* PlatformOptions;
+ QLabel* PlatformLabel;
QStringList GeneratorsSupportingToolset;
+ QStringList GeneratorsSupportingPlatform;
+ QMultiMap<QString, QString> GeneratorSupportedPlatforms;
+ QMap<QString, QString> GeneratorDefaultPlatform;
private:
QFrame* CreateToolsetWidgets();
+ QFrame* CreatePlatformWidgets();
};
//! the page that gives basic options for native compilers
-class NativeCompilerSetup : public QWizardPage, protected Ui::Compilers
+class NativeCompilerSetup
+ : public QWizardPage
+ , protected Ui::Compilers
{
Q_OBJECT
public:
@@ -83,7 +93,9 @@ public:
};
//! the page that gives options for cross compilers
-class CrossCompilerSetup : public QWizardPage, protected Ui::CrossCompiler
+class CrossCompilerSetup
+ : public QWizardPage
+ , protected Ui::CrossCompiler
{
Q_OBJECT
public:
@@ -155,6 +167,7 @@ public:
void setGenerators(std::vector<cmake::GeneratorInfo> const& gens);
QString getGenerator() const;
+ QString getPlatform() const;
QString getToolset() const;
bool defaultSetup() const;
diff --git a/Source/QtDialog/Plus16.png b/Source/QtDialog/Plus16.png
index 552f6f004..1c33bc763 100644
--- a/Source/QtDialog/Plus16.png
+++ b/Source/QtDialog/Plus16.png
Binary files differ
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index d473d9b8f..b608fcbfc 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -7,10 +7,11 @@
#include "cmExternalMakefileProjectGenerator.h"
#include "cmState.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#ifdef Q_OS_WIN
-#include "qt_windows.h" // For SetErrorMode
+# include "qt_windows.h" // For SetErrorMode
#endif
QCMake::QCMake(QObject* p)
@@ -23,32 +24,33 @@ QCMake::QCMake(QObject* p)
cmSystemTools::DisableRunCommandOutput();
cmSystemTools::SetRunCommandHideConsole(true);
- cmSystemTools::SetMessageCallback(QCMake::messageCallback, this);
- cmSystemTools::SetStdoutCallback(QCMake::stdoutCallback, this);
- cmSystemTools::SetStderrCallback(QCMake::stderrCallback, this);
- this->CMakeInstance = new cmake(cmake::RoleProject);
+ cmSystemTools::SetMessageCallback(
+ [this](std::string const& msg, const char* title) {
+ this->messageCallback(msg, title);
+ });
+ cmSystemTools::SetStdoutCallback(
+ [this](std::string const& msg) { this->stdoutCallback(msg); });
+ cmSystemTools::SetStderrCallback(
+ [this](std::string const& msg) { this->stderrCallback(msg); });
+
+ this->CMakeInstance = new cmake(cmake::RoleProject, cmState::Project);
this->CMakeInstance->SetCMakeEditCommand(
cmSystemTools::GetCMakeGUICommand());
- this->CMakeInstance->SetProgressCallback(QCMake::progressCallback, this);
+ this->CMakeInstance->SetProgressCallback(
+ [this](const std::string& msg, float percent) {
+ this->progressCallback(msg, percent);
+ });
- cmSystemTools::SetInterruptCallback(QCMake::interruptCallback, this);
+ cmSystemTools::SetInterruptCallback(
+ [this] { return this->interruptCallback(); });
std::vector<cmake::GeneratorInfo> generators;
- this->CMakeInstance->GetRegisteredGenerators(generators);
-
- 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->CMakeInstance->GetRegisteredGenerators(
+ generators, /*includeNamesWithPlatform=*/false);
- this->AvailableGenerators.push_back(*it);
+ for (cmake::GeneratorInfo const& gen : generators) {
+ this->AvailableGenerators.push_back(gen);
}
}
@@ -83,6 +85,7 @@ void QCMake::setBinaryDirectory(const QString& _dir)
cmState* state = this->CMakeInstance->GetState();
this->setGenerator(QString());
this->setToolset(QString());
+ this->setPlatform(QString());
if (!this->CMakeInstance->LoadCache(
this->BinaryDirectory.toLocal8Bit().data())) {
QDir testDir(this->BinaryDirectory);
@@ -103,18 +106,26 @@ void QCMake::setBinaryDirectory(const QString& _dir)
}
const char* gen = state->GetCacheEntryValue("CMAKE_GENERATOR");
if (gen) {
- const char* extraGen =
+ const std::string* extraGen =
state->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR");
std::string curGen =
cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
- gen, extraGen ? extraGen : "");
+ gen, extraGen ? *extraGen : "");
this->setGenerator(QString::fromLocal8Bit(curGen.c_str()));
}
+ const char* platform =
+ state->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM");
+ if (platform) {
+ this->setPlatform(QString::fromLocal8Bit(platform));
+ }
+
const char* toolset = state->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET");
if (toolset) {
this->setToolset(QString::fromLocal8Bit(toolset));
}
+
+ checkOpenPossible();
}
}
@@ -126,6 +137,14 @@ void QCMake::setGenerator(const QString& gen)
}
}
+void QCMake::setPlatform(const QString& platform)
+{
+ if (this->Platform != platform) {
+ this->Platform = platform;
+ emit this->platformChanged(this->Platform);
+ }
+}
+
void QCMake::setToolset(const QString& toolset)
{
if (this->Toolset != toolset) {
@@ -147,7 +166,8 @@ void QCMake::configure()
this->CMakeInstance->SetGlobalGenerator(
this->CMakeInstance->CreateGlobalGenerator(
this->Generator.toLocal8Bit().data()));
- this->CMakeInstance->SetGeneratorPlatform("");
+ this->CMakeInstance->SetGeneratorPlatform(
+ this->Platform.toLocal8Bit().data());
this->CMakeInstance->SetGeneratorToolset(this->Toolset.toLocal8Bit().data());
this->CMakeInstance->LoadCache();
this->CMakeInstance->SetWarnUninitialized(this->WarnUninitializedMode);
@@ -183,6 +203,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)
@@ -194,38 +234,37 @@ void QCMake::setProperties(const QCMakePropertyList& newProps)
// set the value of properties
cmState* state = this->CMakeInstance->GetState();
std::vector<std::string> cacheKeys = state->GetCacheEntryKeys();
- for (std::vector<std::string>::const_iterator it = cacheKeys.begin();
- it != cacheKeys.end(); ++it) {
- cmStateEnums::CacheEntryType t = state->GetCacheEntryType(*it);
+ for (std::string const& key : cacheKeys) {
+ cmStateEnums::CacheEntryType t = state->GetCacheEntryType(key);
if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC) {
continue;
}
QCMakeProperty prop;
- prop.Key = QString::fromLocal8Bit(it->c_str());
+ prop.Key = QString::fromLocal8Bit(key.c_str());
int idx = props.indexOf(prop);
if (idx == -1) {
- toremove.append(QString::fromLocal8Bit(it->c_str()));
+ toremove.append(QString::fromLocal8Bit(key.c_str()));
} else {
prop = props[idx];
if (prop.Value.type() == QVariant::Bool) {
- state->SetCacheEntryValue(*it, prop.Value.toBool() ? "ON" : "OFF");
+ state->SetCacheEntryValue(key, prop.Value.toBool() ? "ON" : "OFF");
} else {
- state->SetCacheEntryValue(*it,
+ state->SetCacheEntryValue(key,
prop.Value.toString().toLocal8Bit().data());
}
props.removeAt(idx);
}
}
- // remove some properites
+ // remove some properties
foreach (QString const& s, toremove) {
this->CMakeInstance->UnwatchUnusedCli(s.toLocal8Bit().data());
state->RemoveCacheEntry(s.toLocal8Bit().data());
}
- // add some new properites
+ // add some new properties
foreach (QCMakeProperty const& s, props) {
this->CMakeInstance->WatchUnusedCli(s.Key.toLocal8Bit().data());
@@ -257,25 +296,24 @@ QCMakePropertyList QCMake::properties() const
cmState* state = this->CMakeInstance->GetState();
std::vector<std::string> cacheKeys = state->GetCacheEntryKeys();
- for (std::vector<std::string>::const_iterator i = cacheKeys.begin();
- i != cacheKeys.end(); ++i) {
- cmStateEnums::CacheEntryType t = state->GetCacheEntryType(*i);
+ for (std::string const& key : cacheKeys) {
+ cmStateEnums::CacheEntryType t = state->GetCacheEntryType(key);
if (t == cmStateEnums::INTERNAL || t == cmStateEnums::STATIC ||
t == cmStateEnums::UNINITIALIZED) {
continue;
}
- const char* cachedValue = state->GetCacheEntryValue(*i);
+ const char* cachedValue = state->GetCacheEntryValue(key);
QCMakeProperty prop;
- prop.Key = QString::fromLocal8Bit(i->c_str());
+ prop.Key = QString::fromLocal8Bit(key.c_str());
prop.Help =
- QString::fromLocal8Bit(state->GetCacheEntryProperty(*i, "HELPSTRING"));
+ QString::fromLocal8Bit(state->GetCacheEntryProperty(key, "HELPSTRING"));
prop.Value = QString::fromLocal8Bit(cachedValue);
- prop.Advanced = state->GetCacheEntryPropertyAsBool(*i, "ADVANCED");
+ prop.Advanced = state->GetCacheEntryPropertyAsBool(key, "ADVANCED");
if (t == cmStateEnums::BOOL) {
prop.Type = QCMakeProperty::BOOL;
- prop.Value = cmSystemTools::IsOn(cachedValue);
+ prop.Value = cmIsOn(cachedValue);
} else if (t == cmStateEnums::PATH) {
prop.Type = QCMakeProperty::PATH;
} else if (t == cmStateEnums::FILEPATH) {
@@ -283,7 +321,7 @@ QCMakePropertyList QCMake::properties() const
} else if (t == cmStateEnums::STRING) {
prop.Type = QCMakeProperty::STRING;
const char* stringsProperty =
- state->GetCacheEntryProperty(*i, "STRINGS");
+ state->GetCacheEntryProperty(key, "STRINGS");
if (stringsProperty) {
prop.Strings = QString::fromLocal8Bit(stringsProperty).split(";");
}
@@ -300,46 +338,40 @@ void QCMake::interrupt()
this->InterruptFlag.ref();
}
-bool QCMake::interruptCallback(void* cd)
+bool QCMake::interruptCallback()
{
- QCMake* self = reinterpret_cast<QCMake*>(cd);
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
- return self->InterruptFlag;
+ return this->InterruptFlag;
#else
- return self->InterruptFlag.load();
+ return this->InterruptFlag.load();
#endif
}
-void QCMake::progressCallback(const char* msg, float percent, void* cd)
+void QCMake::progressCallback(const std::string& msg, float percent)
{
- QCMake* self = reinterpret_cast<QCMake*>(cd);
if (percent >= 0) {
- emit self->progressChanged(QString::fromLocal8Bit(msg), percent);
+ emit this->progressChanged(QString::fromStdString(msg), percent);
} else {
- emit self->outputMessage(QString::fromLocal8Bit(msg));
+ emit this->outputMessage(QString::fromStdString(msg));
}
QCoreApplication::processEvents();
}
-void QCMake::messageCallback(const char* msg, const char* /*title*/,
- bool& /*stop*/, void* cd)
+void QCMake::messageCallback(std::string const& msg, const char* /*title*/)
{
- QCMake* self = reinterpret_cast<QCMake*>(cd);
- emit self->errorMessage(QString::fromLocal8Bit(msg));
+ emit this->errorMessage(QString::fromStdString(msg));
QCoreApplication::processEvents();
}
-void QCMake::stdoutCallback(const char* msg, size_t len, void* cd)
+void QCMake::stdoutCallback(std::string const& msg)
{
- QCMake* self = reinterpret_cast<QCMake*>(cd);
- emit self->outputMessage(QString::fromLocal8Bit(msg, int(len)));
+ emit this->outputMessage(QString::fromStdString(msg));
QCoreApplication::processEvents();
}
-void QCMake::stderrCallback(const char* msg, size_t len, void* cd)
+void QCMake::stderrCallback(std::string const& msg)
{
- QCMake* self = reinterpret_cast<QCMake*>(cd);
- emit self->outputMessage(QString::fromLocal8Bit(msg, int(len)));
+ emit this->outputMessage(QString::fromStdString(msg));
QCoreApplication::processEvents();
}
@@ -450,3 +482,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 e14cdf2c9..fa4451bc2 100644
--- a/Source/QtDialog/QCMake.h
+++ b/Source/QtDialog/QCMake.h
@@ -3,13 +3,13 @@
#ifndef QCMake_h
#define QCMake_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include "cmake.h"
#ifdef _MSC_VER
-#pragma warning(disable : 4127)
-#pragma warning(disable : 4512)
+# pragma warning(disable : 4127)
+# pragma warning(disable : 4512)
#endif
#include <vector>
@@ -50,7 +50,7 @@ struct QCMakeProperty
};
// list of properties
-typedef QList<QCMakeProperty> QCMakePropertyList;
+using QCMakePropertyList = QList<QCMakeProperty>;
// allow QVariant to be a property or list of properties
Q_DECLARE_METATYPE(QCMakeProperty)
@@ -63,7 +63,7 @@ class QCMake : public QObject
{
Q_OBJECT
public:
- QCMake(QObject* p = CM_NULLPTR);
+ QCMake(QObject* p = nullptr);
~QCMake();
public slots:
/// load the cache file in a directory
@@ -75,11 +75,15 @@ public slots:
/// set the desired generator to use
void setGenerator(const QString& generator);
/// set the desired generator to use
+ void setPlatform(const QString& platform);
+ /// set the desired generator to use
void setToolset(const QString& toolset);
/// do the configure step
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 +115,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,22 +157,29 @@ signals:
void debugOutputChanged(bool);
/// signal when the toolset changes
void toolsetChanged(const QString& toolset);
+ /// signal when the platform changes
+ void platformChanged(const QString& platform);
+ /// signal when open is done
+ void openDone(bool successful);
+ /// signal when open is done
+ void openPossible(bool possible);
protected:
cmake* CMakeInstance;
- static bool interruptCallback(void*);
- static void progressCallback(const char* msg, float percent, void* cd);
- static void messageCallback(const char* msg, const char* title, bool&,
- void* cd);
- static void stdoutCallback(const char* msg, size_t len, void* cd);
- static void stderrCallback(const char* msg, size_t len, void* cd);
+ bool interruptCallback();
+ void progressCallback(std::string const& msg, float percent);
+ void messageCallback(std::string const& msg, const char* title);
+ void stdoutCallback(std::string const& msg);
+ void stderrCallback(std::string const& msg);
+
bool WarnUninitializedMode;
bool WarnUnusedMode;
bool WarnUnusedAllMode;
QString SourceDirectory;
QString BinaryDirectory;
QString Generator;
+ QString Platform;
QString Toolset;
std::vector<cmake::GeneratorInfo> AvailableGenerators;
QString CMakeExecutable;
diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx
index 08c2d58d5..3e6a49e09 100644
--- a/Source/QtDialog/QCMakeCacheView.cxx
+++ b/Source/QtDialog/QCMakeCacheView.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "QCMakeCacheView.h"
+#include "QCMakeWidgets.h"
#include <QApplication>
#include <QEvent>
#include <QHBoxLayout>
@@ -11,8 +12,6 @@
#include <QSortFilterProxyModel>
#include <QStyle>
-#include "QCMakeWidgets.h"
-
// filter for searches
class QCMakeSearchFilter : public QSortFilterProxyModel
{
@@ -23,7 +22,7 @@ public:
}
protected:
- bool filterAcceptsRow(int row, const QModelIndex& p) const CM_OVERRIDE
+ bool filterAcceptsRow(int row, const QModelIndex& p) const override
{
QStringList strs;
const QAbstractItemModel* m = this->sourceModel();
@@ -77,7 +76,7 @@ public:
protected:
bool ShowAdvanced;
- bool filterAcceptsRow(int row, const QModelIndex& p) const CM_OVERRIDE
+ bool filterAcceptsRow(int row, const QModelIndex& p) const override
{
const QAbstractItemModel* m = this->sourceModel();
QModelIndex idx = m->index(row, 0, p);
@@ -186,9 +185,7 @@ QCMakeCacheModel::QCMakeCacheModel(QObject* p)
this->setHorizontalHeaderLabels(labels);
}
-QCMakeCacheModel::~QCMakeCacheModel()
-{
-}
+QCMakeCacheModel::~QCMakeCacheModel() = default;
static uint qHash(const QCMakeProperty& p)
{
@@ -212,7 +209,8 @@ void QCMakeCacheModel::clear()
void QCMakeCacheModel::setProperties(const QCMakePropertyList& props)
{
- QSet<QCMakeProperty> newProps, newProps2;
+ QSet<QCMakeProperty> newProps;
+ QSet<QCMakeProperty> newProps2;
if (this->ShowNewProperties) {
newProps = props.toSet();
@@ -248,9 +246,9 @@ void QCMakeCacheModel::setProperties(const QCMakePropertyList& props)
}
} else if (this->View == GroupView) {
QMap<QString, QCMakePropertyList> newPropsTree;
- this->breakProperties(newProps, newPropsTree);
+ QCMakeCacheModel::breakProperties(newProps, newPropsTree);
QMap<QString, QCMakePropertyList> newPropsTree2;
- this->breakProperties(newProps2, newPropsTree2);
+ QCMakeCacheModel::breakProperties(newProps2, newPropsTree2);
QStandardItem* root = this->invisibleRootItem();
@@ -539,7 +537,7 @@ QWidget* QCMakeCacheModelDelegate::createEditor(
QModelIndex var = idx.sibling(idx.row(), 0);
int type = var.data(QCMakeCacheModel::TypeRole).toInt();
if (type == QCMakeProperty::BOOL) {
- return CM_NULLPTR;
+ return nullptr;
}
if (type == QCMakeProperty::PATH) {
QCMakePathEditor* editor =
@@ -614,7 +612,7 @@ bool QCMakeCacheModelDelegate::editorEvent(QEvent* e,
// Can remove this function and FileDialogFlag when minimum Qt version is 4.5
bool QCMakeCacheModelDelegate::eventFilter(QObject* object, QEvent* evt)
{
- // workaround for what looks like a bug in Qt on Mac OS X
+ // workaround for what looks like a bug in Qt on macOS
// where it doesn't create a QWidget wrapper for the native file dialog
// so the Qt library ends up assuming the focus was lost to something else
@@ -642,7 +640,7 @@ QSize QCMakeCacheModelDelegate::sizeHint(const QStyleOptionViewItem& option,
QStyleOptionButton opt;
opt.QStyleOption::operator=(option);
sz = sz.expandedTo(
- style->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt, CM_NULLPTR)
+ style->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt, nullptr)
.size());
return sz;
diff --git a/Source/QtDialog/QCMakeCacheView.h b/Source/QtDialog/QCMakeCacheView.h
index c1debf590..bea196586 100644
--- a/Source/QtDialog/QCMakeCacheView.h
+++ b/Source/QtDialog/QCMakeCacheView.h
@@ -4,7 +4,6 @@
#define QCMakeCacheView_h
#include "QCMake.h"
-
#include <QItemDelegate>
#include <QSet>
#include <QStandardItemModel>
diff --git a/Source/QtDialog/QCMakeWidgets.cxx b/Source/QtDialog/QCMakeWidgets.cxx
index 7f0cafa37..332a770ef 100644
--- a/Source/QtDialog/QCMakeWidgets.cxx
+++ b/Source/QtDialog/QCMakeWidgets.cxx
@@ -2,15 +2,17 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "QCMakeWidgets.h"
+#include <utility>
+
#include <QDirModel>
#include <QFileDialog>
#include <QFileInfo>
#include <QResizeEvent>
#include <QToolButton>
-QCMakeFileEditor::QCMakeFileEditor(QWidget* p, const QString& var)
+QCMakeFileEditor::QCMakeFileEditor(QWidget* p, QString var)
: QLineEdit(p)
- , Variable(var)
+ , Variable(std::move(var))
{
this->ToolButton = new QToolButton(this);
this->ToolButton->setText("...");
@@ -57,7 +59,7 @@ void QCMakeFilePathEditor::chooseFile()
emit this->fileDialogExists(true);
path =
QFileDialog::getOpenFileName(this, title, info.absolutePath(), QString(),
- CM_NULLPTR, QFileDialog::DontResolveSymlinks);
+ nullptr, QFileDialog::DontResolveSymlinks);
emit this->fileDialogExists(false);
if (!path.isEmpty()) {
@@ -89,7 +91,7 @@ void QCMakePathEditor::chooseFile()
// use same QDirModel for all completers
static QDirModel* fileDirModel()
{
- static QDirModel* m = CM_NULLPTR;
+ static QDirModel* m = nullptr;
if (!m) {
m = new QDirModel();
}
@@ -97,7 +99,7 @@ static QDirModel* fileDirModel()
}
static QDirModel* pathDirModel()
{
- static QDirModel* m = CM_NULLPTR;
+ static QDirModel* m = nullptr;
if (!m) {
m = new QDirModel();
m->setFilter(QDir::AllDirs | QDir::Drives | QDir::NoDotAndDotDot);
diff --git a/Source/QtDialog/QCMakeWidgets.h b/Source/QtDialog/QCMakeWidgets.h
index 1ec666ff6..5d2368eab 100644
--- a/Source/QtDialog/QCMakeWidgets.h
+++ b/Source/QtDialog/QCMakeWidgets.h
@@ -3,7 +3,7 @@
#ifndef QCMakeWidgets_h
#define QCMakeWidgets_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <QComboBox>
#include <QCompleter>
@@ -18,7 +18,7 @@ class QCMakeFileEditor : public QLineEdit
{
Q_OBJECT
public:
- QCMakeFileEditor(QWidget* p, const QString& var);
+ QCMakeFileEditor(QWidget* p, QString var);
protected slots:
virtual void chooseFile() = 0;
signals:
@@ -35,7 +35,7 @@ class QCMakePathEditor : public QCMakeFileEditor
{
Q_OBJECT
public:
- QCMakePathEditor(QWidget* p = CM_NULLPTR, const QString& var = QString());
+ QCMakePathEditor(QWidget* p = nullptr, const QString& var = QString());
void chooseFile();
};
@@ -44,8 +44,7 @@ class QCMakeFilePathEditor : public QCMakeFileEditor
{
Q_OBJECT
public:
- QCMakeFilePathEditor(QWidget* p = CM_NULLPTR,
- const QString& var = QString());
+ QCMakeFilePathEditor(QWidget* p = nullptr, const QString& var = QString());
void chooseFile();
};
diff --git a/Source/QtDialog/RegexExplorer.cxx b/Source/QtDialog/RegexExplorer.cxx
index abed70e90..746fd8af2 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));
}
@@ -20,7 +20,7 @@ void RegexExplorer::setStatusColor(QWidget* widget, bool successful)
QColor color = successful ? QColor(0, 127, 0) : Qt::red;
QPalette palette = widget->palette();
- palette.setColor(QPalette::Foreground, color);
+ palette.setColor(QPalette::WindowText, color);
widget->setPalette(palette);
}
@@ -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/QtDialog/RegexExplorer.h b/Source/QtDialog/RegexExplorer.h
index 867989279..1a1d7700f 100644
--- a/Source/QtDialog/RegexExplorer.h
+++ b/Source/QtDialog/RegexExplorer.h
@@ -3,16 +3,20 @@
#ifndef RegexExplorer_h
#define RegexExplorer_h
-#include "cmsys/RegularExpression.hxx"
-#include <QDialog>
#include <string>
+#include <QDialog>
+
+#include "cmsys/RegularExpression.hxx"
+
#include "ui_RegexExplorer.h"
class QString;
class QWidget;
-class RegexExplorer : public QDialog, public Ui::RegexExplorer
+class RegexExplorer
+ : public QDialog
+ , public Ui::RegexExplorer
{
Q_OBJECT
public:
diff --git a/Source/QtDialog/WarningMessagesDialog.h b/Source/QtDialog/WarningMessagesDialog.h
index acb830d85..f209dbdb3 100644
--- a/Source/QtDialog/WarningMessagesDialog.h
+++ b/Source/QtDialog/WarningMessagesDialog.h
@@ -3,16 +3,18 @@
#ifndef WarningMessagesDialog_h
#define WarningMessagesDialog_h
+#include "QCMake.h"
#include <QDialog>
#include <QWidget>
-#include "QCMake.h"
#include "ui_WarningMessagesDialog.h"
/**
* Dialog window for setting the warning message related options.
*/
-class WarningMessagesDialog : public QDialog, public Ui_MessagesDialog
+class WarningMessagesDialog
+ : public QDialog
+ , public Ui_MessagesDialog
{
Q_OBJECT
diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx
index e96226a4b..b85cc3359 100644
--- a/Source/bindexplib.cxx
+++ b/Source/bindexplib.cxx
@@ -8,68 +8,87 @@
-------------------------------------------------------------------------*/
/*
-*----------------------------------------------------------------------
-* Program: dumpexts.exe
-* Author: Gordon Chaffee
-*
-* History: The real functionality of this file was written by
-* Matt Pietrek in 1993 in his pedump utility. I've
-* modified it to dump the externals in a bunch of object
-* files to create a .def file.
-*
-* Notes: Visual C++ puts an underscore before each exported symbol.
-* This file removes them. I don't know if this is a problem
-* this other compilers. If _MSC_VER is defined,
-* the underscore is removed. If not, it isn't. To get a
-* full dump of an object file, use the -f option. This can
-* help determine the something that may be different with a
-* compiler other than Visual C++.
-* ======================================
-* Corrections (Axel 2006-04-04):
-* Conversion to C++. Mostly.
-*
+ *----------------------------------------------------------------------
+ * Program: dumpexts.exe
+ * Author: Gordon Chaffee
+ *
+ * History: The real functionality of this file was written by
+ * Matt Pietrek in 1993 in his pedump utility. I've
+ * modified it to dump the externals in a bunch of object
+ * files to create a .def file.
+ *
+ * Notes: Visual C++ puts an underscore before each exported symbol.
+ * This file removes them. I don't know if this is a problem
+ * this other compilers. If _MSC_VER is defined,
+ * the underscore is removed. If not, it isn't. To get a
+ * full dump of an object file, use the -f option. This can
+ * help determine the something that may be different with a
+ * compiler other than Visual C++.
+ * ======================================
+ * Corrections (Axel 2006-04-04):
+ * Conversion to C++. Mostly.
+ *
* 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).
*
* ======================================
-* ======================================
-* Corrections (Valery Fine 23/02/98):
-*
-* The "(vector) deleting destructor" MUST not be exported
-* To recognize it the following test are introduced:
-* "@@UAEPAXI@Z" scalar deleting dtor
-* "@@QAEPAXI@Z" vector deleting dtor
-* "AEPAXI@Z" vector deleting dtor with thunk adjustor
-* ======================================
-* Corrections (Valery Fine 12/02/97):
-*
-* 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
-* 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
-* The DumpExternalObject function has been introduced to generate .DEF file
-*
-* Author: Valery Fine 16/09/96 (E-mail: fine@vxcern.cern.ch)
-*----------------------------------------------------------------------
-*/
+ * ======================================
+ * Corrections (Valery Fine 23/02/98):
+ *
+ * The "(vector) deleting destructor" MUST not be exported
+ * To recognize it the following test are introduced:
+ * "@@UAEPAXI@Z" scalar deleting dtor
+ * "@@QAEPAXI@Z" vector deleting dtor
+ * "AEPAXI@Z" vector deleting dtor with thunk adjustor
+ * ======================================
+ * Corrections (Valery Fine 12/02/97):
+ *
+ * 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 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 definitions
+ * The DumpExternalObject function has been introduced to generate .DEF
+ *file
+ *
+ * Author: Valery Fine 16/09/96 (E-mail: fine@vxcern.cern.ch)
+ *----------------------------------------------------------------------
+ */
#include "bindexplib.h"
-#include "cmsys/Encoding.hxx"
-#include "cmsys/FStream.hxx"
#include <iostream>
+#include <sstream>
+#include <vector>
+
#include <windows.h>
+#include "cmsys/Encoding.hxx"
+#include "cmsys/FStream.hxx"
+
+#include "cmSystemTools.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
@@ -176,7 +195,7 @@ public:
{
this->ObjectImageHeader = ih;
this->SymbolTable =
- (SymbolTableType*)((DWORD_PTR) this->ObjectImageHeader +
+ (SymbolTableType*)((DWORD_PTR)this->ObjectImageHeader +
this->ObjectImageHeader->PointerToSymbolTable);
this->SectionHeaders = GetSectionHeaderOffset(this->ObjectImageHeader);
this->SymbolCount = this->ObjectImageHeader->NumberOfSymbols;
@@ -215,10 +234,10 @@ public:
(pSymbolTable->Type == 0x20 || pSymbolTable->Type == 0x0)) {
if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
/*
- * The name of the Function entry points
- */
+ * The name of the Function entry points
+ */
if (pSymbolTable->N.Name.Short != 0) {
- symbol = "";
+ symbol.clear();
symbol.insert(0, (const char*)pSymbolTable->N.ShortName, 8);
} else {
symbol = stringTable + pSymbolTable->N.Name.Long;
@@ -270,8 +289,8 @@ public:
}
/*
- * Take into account any aux symbols
- */
+ * Take into account any aux symbols
+ */
i += pSymbolTable->NumberOfAuxSymbols;
pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
pSymbolTable++;
@@ -288,13 +307,68 @@ private:
bool IsI386;
};
-bool DumpFile(const char* filename, std::set<std::string>& symbols,
+bool DumpFileWithLlvmNm(std::string const& nmPath, const char* filename,
+ std::set<std::string>& symbols,
+ std::set<std::string>& dataSymbols)
+{
+ std::string output;
+ // break up command line into a vector
+ std::vector<std::string> command;
+ command.push_back(nmPath);
+ command.push_back("--no-weak");
+ command.push_back("--defined-only");
+ command.push_back("--format=posix");
+ command.push_back(filename);
+
+ // run the command
+ int exit_code = 0;
+ cmSystemTools::RunSingleCommand(command, &output, &output, &exit_code, "",
+ cmSystemTools::OUTPUT_NONE);
+
+ if (exit_code != 0) {
+ fprintf(stderr, "llvm-nm returned an error: %s\n", output.c_str());
+ return false;
+ }
+
+ std::istringstream ss(output);
+ std::string line;
+ while (std::getline(ss, line)) {
+ if (line.empty()) { // last line
+ continue;
+ }
+ size_t sym_end = line.find(" ");
+ if (sym_end == std::string::npos) {
+ fprintf(stderr, "Couldn't parse llvm-nm output line: %s\n",
+ line.c_str());
+ return false;
+ }
+ if (line.size() < sym_end + 1) {
+ fprintf(stderr, "Couldn't parse llvm-nm output line: %s\n",
+ line.c_str());
+ return false;
+ }
+ const std::string sym = line.substr(0, sym_end);
+ const char sym_type = line[sym_end + 1];
+ switch (sym_type) {
+ case 'D':
+ dataSymbols.insert(sym);
+ break;
+ case 'T':
+ symbols.insert(sym);
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool DumpFile(std::string const& nmPath, const char* filename,
+ std::set<std::string>& symbols,
std::set<std::string>& dataSymbols)
{
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 +394,52 @@ 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 and llvm LTO format
+ cmANON_OBJECT_HEADER_BIGOBJ* h =
+ (cmANON_OBJECT_HEADER_BIGOBJ*)lpFileBase;
+ if (h->Sig1 == 0x0 && h->Sig2 == 0xffff) {
+ // bigobj
+ 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 if (
+ // BCexCODE - llvm bitcode
+ (h->Sig1 == 0x4342 && h->Sig2 == 0xDEC0) ||
+ // 0x0B17C0DE - llvm bitcode BC wrapper
+ (h->Sig1 == 0x0B17 && h->Sig2 == 0xC0DE)) {
+
+ return DumpFileWithLlvmNm(nmPath, filename, symbols, dataSymbols);
+
+ } else {
+ printf("unrecognized file format in '%s, %u'\n", filename,
+ imageHeader->Machine);
+ return false;
+ }
}
}
UnmapViewOfFile(lpFileBase);
@@ -360,7 +450,7 @@ bool DumpFile(const char* filename, std::set<std::string>& symbols,
bool bindexplib::AddObjectFile(const char* filename)
{
- return DumpFile(filename, this->Symbols, this->DataSymbols);
+ return DumpFile(NmPath, filename, this->Symbols, this->DataSymbols);
}
bool bindexplib::AddDefinitionFile(const char* filename)
@@ -372,7 +462,7 @@ bool bindexplib::AddDefinitionFile(const char* filename)
}
std::string str;
while (std::getline(infile, str)) {
- // skip the LIBRAY and EXPORTS lines (if any)
+ // skip the LIBRARY and EXPORTS lines (if any)
if ((str.compare(0, 7, "LIBRARY") == 0) ||
(str.compare(0, 7, "EXPORTS") == 0)) {
continue;
@@ -394,12 +484,15 @@ bool bindexplib::AddDefinitionFile(const char* filename)
void bindexplib::WriteFile(FILE* file)
{
fprintf(file, "EXPORTS \n");
- for (std::set<std::string>::const_iterator i = this->DataSymbols.begin();
- i != this->DataSymbols.end(); ++i) {
- fprintf(file, "\t%s \t DATA\n", i->c_str());
+ for (std::string const& ds : this->DataSymbols) {
+ fprintf(file, "\t%s \t DATA\n", ds.c_str());
}
- for (std::set<std::string>::const_iterator i = this->Symbols.begin();
- i != this->Symbols.end(); ++i) {
- fprintf(file, "\t%s\n", i->c_str());
+ for (std::string const& s : this->Symbols) {
+ fprintf(file, "\t%s\n", s.c_str());
}
}
+
+void bindexplib::SetNmPath(std::string const& nm)
+{
+ NmPath = nm;
+}
diff --git a/Source/bindexplib.h b/Source/bindexplib.h
index bc904e9f8..538177dff 100644
--- a/Source/bindexplib.h
+++ b/Source/bindexplib.h
@@ -3,22 +3,26 @@
#ifndef bindexplib_h
#define bindexplib_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <set>
-#include <stdio.h>
#include <string>
+#include <stdio.h>
+
class bindexplib
{
public:
- bindexplib() {}
+ bindexplib() { NmPath = "nm"; }
bool AddDefinitionFile(const char* filename);
bool AddObjectFile(const char* filename);
void WriteFile(FILE* file);
+ void SetNmPath(std::string const& nm);
+
private:
std::set<std::string> Symbols;
std::set<std::string> DataSymbols;
+ std::string NmPath;
};
#endif
diff --git a/Source/cmAddCompileDefinitionsCommand.cxx b/Source/cmAddCompileDefinitionsCommand.cxx
new file mode 100644
index 000000000..b00a4a7f7
--- /dev/null
+++ b/Source/cmAddCompileDefinitionsCommand.cxx
@@ -0,0 +1,16 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmAddCompileDefinitionsCommand.h"
+
+#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+
+bool cmAddCompileDefinitionsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ cmMakefile& mf = status.GetMakefile();
+ for (std::string const& i : args) {
+ mf.AddCompileDefinition(i);
+ }
+ return true;
+}
diff --git a/Source/cmAddCompileDefinitionsCommand.h b/Source/cmAddCompileDefinitionsCommand.h
new file mode 100644
index 000000000..4bd621c4b
--- /dev/null
+++ b/Source/cmAddCompileDefinitionsCommand.h
@@ -0,0 +1,16 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmAddCompileDefinitionsCommand_h
+#define cmAddCompileDefinitionsCommand_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+class cmExecutionStatus;
+
+bool cmAddCompileDefinitionsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+
+#endif
diff --git a/Source/cmAddCompileOptionsCommand.cxx b/Source/cmAddCompileOptionsCommand.cxx
index 21a8012d8..8ccb5129a 100644
--- a/Source/cmAddCompileOptionsCommand.cxx
+++ b/Source/cmAddCompileOptionsCommand.cxx
@@ -2,20 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmAddCompileOptionsCommand.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-class cmExecutionStatus;
-
-bool cmAddCompileOptionsCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmAddCompileOptionsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- if (args.empty()) {
- return true;
- }
-
- for (std::vector<std::string>::const_iterator i = args.begin();
- i != args.end(); ++i) {
- this->Makefile->AddCompileOption(i->c_str());
+ cmMakefile& mf = status.GetMakefile();
+ for (std::string const& i : args) {
+ mf.AddCompileOption(i);
}
return true;
}
diff --git a/Source/cmAddCompileOptionsCommand.h b/Source/cmAddCompileOptionsCommand.h
index 297f901db..b172412be 100644
--- a/Source/cmAddCompileOptionsCommand.h
+++ b/Source/cmAddCompileOptionsCommand.h
@@ -3,29 +3,14 @@
#ifndef cmAddCompileOptionsCommand_h
#define cmAddCompileOptionsCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmAddCompileOptionsCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmAddCompileOptionsCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmAddCompileOptionsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index b5e7c9ea9..6e04ce582 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -3,42 +3,51 @@
#include "cmAddCustomCommandCommand.h"
#include <sstream>
+#include <unordered_set>
+#include "cmCheckCustomOutputs.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
+#include "cmCustomCommandTypes.h"
+#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmSourceFile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmTarget.h"
-#include "cmake.h"
-class cmExecutionStatus;
-
-// cmAddCustomCommandCommand
-bool cmAddCustomCommandCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
/* Let's complain at the end of this function about the lack of a particular
arg. For the moment, let's say that COMMAND, and either TARGET or SOURCE
are required.
*/
if (args.size() < 4) {
- this->SetError("called with wrong number of arguments.");
+ status.SetError("called with wrong number of arguments.");
return false;
}
- std::string source, target, main_dependency, working, depfile;
+ cmMakefile& mf = status.GetMakefile();
+ std::string source;
+ std::string target;
+ std::string main_dependency;
+ std::string working;
+ std::string depfile;
+ std::string job_pool;
std::string comment_buffer;
- const char* comment = CM_NULLPTR;
- std::vector<std::string> depends, outputs, output, byproducts;
+ const char* comment = nullptr;
+ std::vector<std::string> depends;
+ std::vector<std::string> outputs;
+ std::vector<std::string> output;
+ std::vector<std::string> byproducts;
bool verbatim = false;
bool append = false;
bool uses_terminal = false;
bool command_expand_lists = false;
std::string implicit_depends_lang;
- cmCustomCommand::ImplicitDependsList implicit_depends;
+ cmImplicitDependsList implicit_depends;
// Accumulate one command line at a time.
cmCustomCommandLine currentLine;
@@ -46,7 +55,7 @@ bool cmAddCustomCommandCommand::InitialPass(
// Save all command lines.
cmCustomCommandLines commandLines;
- cmTarget::CustomCommandType cctype = cmTarget::POST_BUILD;
+ cmCustomCommandType cctype = cmCustomCommandType::POST_BUILD;
enum tdoing
{
@@ -63,64 +72,115 @@ bool cmAddCustomCommandCommand::InitialPass(
doing_comment,
doing_working_directory,
doing_depfile,
+ doing_job_pool,
doing_nothing
};
tdoing doing = doing_nothing;
- for (unsigned int j = 0; j < args.size(); ++j) {
- std::string const& copy = args[j];
+#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(JOB_POOL);
+ 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> const keywords{
+ keyAPPEND,
+ keyARGS,
+ keyBYPRODUCTS,
+ keyCOMMAND,
+ keyCOMMAND_EXPAND_LISTS,
+ keyCOMMENT,
+ keyDEPENDS,
+ keyDEPFILE,
+ keyIMPLICIT_DEPENDS,
+ keyJOB_POOL,
+ keyMAIN_DEPENDENCY,
+ keyOUTPUT,
+ keyOUTPUTS,
+ keyPOST_BUILD,
+ keyPRE_BUILD,
+ keyPRE_LINK,
+ keySOURCE,
+ keyTARGET,
+ keyUSES_TERMINAL,
+ keyVERBATIM,
+ keyWORKING_DIRECTORY
+ };
- if (copy == "SOURCE") {
- doing = doing_source;
- } else if (copy == "COMMAND") {
- doing = doing_command;
+ for (std::string const& copy : args) {
+ 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 = cmCustomCommandType::PRE_BUILD;
+ } else if (copy == keyPRE_LINK) {
+ cctype = cmCustomCommandType::PRE_LINK;
+ } else if (copy == keyPOST_BUILD) {
+ cctype = cmCustomCommandType::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 (mf.GetGlobalGenerator()->GetName() != "Ninja") {
+ status.SetError("Option DEPFILE not supported by " +
+ mf.GetGlobalGenerator()->GetName());
+ return false;
+ }
+ } else if (copy == keyJOB_POOL) {
+ doing = doing_job_pool;
}
} else {
std::string filename;
@@ -128,7 +188,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
@@ -139,8 +199,7 @@ bool cmAddCustomCommandCommand::InitialPass(
// and later references "${CMAKE_CURRENT_SOURCE_DIR}/out.txt".
// This is fairly obscure so we can wait for someone to
// complain.
- filename = this->Makefile->GetCurrentBinaryDirectory();
- filename += "/";
+ filename = cmStrCat(mf.GetCurrentBinaryDirectory(), '/');
}
filename += copy;
cmSystemTools::ConvertToUnixSlashes(filename);
@@ -155,13 +214,16 @@ bool cmAddCustomCommandCommand::InitialPass(
break;
}
- if (cmSystemTools::FileIsFullPath(filename.c_str())) {
+ if (cmSystemTools::FileIsFullPath(filename)) {
filename = cmSystemTools::CollapseFullPath(filename);
}
switch (doing) {
case doing_depfile:
depfile = copy;
break;
+ case doing_job_pool:
+ job_pool = copy;
+ break;
case doing_working_directory:
working = copy;
break;
@@ -182,13 +244,13 @@ bool cmAddCustomCommandCommand::InitialPass(
// An implicit dependency starting point is also an
// explicit dependency.
std::string dep = copy;
+ // Upfront path conversion is correct because Genex
+ // are not supported.
cmSystemTools::ConvertToUnixSlashes(dep);
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,9 +262,7 @@ bool cmAddCustomCommandCommand::InitialPass(
target = copy;
break;
case doing_depends: {
- std::string dep = copy;
- cmSystemTools::ConvertToUnixSlashes(dep);
- depends.push_back(dep);
+ depends.push_back(copy);
} break;
case doing_outputs:
outputs.push_back(filename);
@@ -215,7 +275,7 @@ bool cmAddCustomCommandCommand::InitialPass(
comment = comment_buffer.c_str();
break;
default:
- this->SetError("Wrong syntax. Unknown type of argument.");
+ status.SetError("Wrong syntax. Unknown type of argument.");
return false;
}
}
@@ -230,51 +290,44 @@ bool cmAddCustomCommandCommand::InitialPass(
// At this point we could complain about the lack of arguments. For
// the moment, let's say that COMMAND, TARGET are always required.
if (output.empty() && target.empty()) {
- this->SetError("Wrong syntax. A TARGET or OUTPUT must be specified.");
+ status.SetError("Wrong syntax. A TARGET or OUTPUT must be specified.");
return false;
}
if (source.empty() && !target.empty() && !output.empty()) {
- this->SetError(
+ status.SetError(
"Wrong syntax. A TARGET and OUTPUT can not both be specified.");
return false;
}
if (append && output.empty()) {
- this->SetError("given APPEND option with no OUTPUT.");
+ status.SetError("given APPEND option with no OUTPUT.");
return false;
}
// Make sure the output names and locations are safe.
- if (!this->CheckOutputs(output) || !this->CheckOutputs(outputs) ||
- !this->CheckOutputs(byproducts)) {
+ if (!cmCheckCustomOutputs(output, "OUTPUT", status) ||
+ !cmCheckCustomOutputs(outputs, "OUTPUTS", status) ||
+ !cmCheckCustomOutputs(byproducts, "BYPRODUCTS", status)) {
return false;
}
// Check for an append request.
if (append) {
- // Lookup an existing command.
- if (cmSourceFile* sf =
- this->Makefile->GetSourceFileWithOutput(output[0])) {
- if (cmCustomCommand* cc = sf->GetCustomCommand()) {
- cc->AppendCommands(commandLines);
- cc->AppendDepends(depends);
- cc->AppendImplicitDepends(implicit_depends);
- return true;
- }
+ if (mf.AppendCustomCommandToOutput(output[0], depends, implicit_depends,
+ commandLines)) {
+ return true;
}
// No command for this output exists.
- std::ostringstream e;
- e << "given APPEND option with output\n\"" << output[0]
- << "\"\nwhich is not already a custom command output.";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("given APPEND option with output\n ", output[0],
+ "\nwhich is not already a custom command output."));
return false;
}
- // Convert working directory to a full path.
- if (!working.empty()) {
- const char* build_dir = this->Makefile->GetCurrentBinaryDirectory();
- working = cmSystemTools::CollapseFullPath(working, build_dir);
+ if (uses_terminal && !job_pool.empty()) {
+ status.SetError("JOB_POOL is shadowed by USES_TERMINAL.");
+ return false;
}
// Choose which mode of the command to use.
@@ -282,46 +335,27 @@ bool cmAddCustomCommandCommand::InitialPass(
if (source.empty() && output.empty()) {
// Source is empty, use the target.
std::vector<std::string> no_depends;
- this->Makefile->AddCustomCommandToTarget(
- target, byproducts, no_depends, commandLines, cctype, comment,
- working.c_str(), escapeOldStyle, uses_terminal, depfile,
- command_expand_lists);
+ mf.AddCustomCommandToTarget(target, byproducts, no_depends, commandLines,
+ cctype, comment, working.c_str(),
+ escapeOldStyle, uses_terminal, depfile,
+ job_pool, command_expand_lists);
} else if (target.empty()) {
// Target is empty, use the output.
- this->Makefile->AddCustomCommandToOutput(
- output, byproducts, depends, main_dependency, commandLines, comment,
- working.c_str(), false, escapeOldStyle, uses_terminal,
- command_expand_lists, depfile);
-
- // Add implicit dependency scanning requests if any were given.
- if (!implicit_depends.empty()) {
- bool okay = false;
- if (cmSourceFile* sf =
- this->Makefile->GetSourceFileWithOutput(output[0])) {
- if (cmCustomCommand* cc = sf->GetCustomCommand()) {
- okay = true;
- cc->SetImplicitDepends(implicit_depends);
- }
- }
- if (!okay) {
- std::ostringstream e;
- e << "could not locate source file with a custom command producing \""
- << output[0] << "\" even though this command tried to create it!";
- this->SetError(e.str());
- return false;
- }
- }
+ mf.AddCustomCommandToOutput(
+ output, byproducts, depends, main_dependency, implicit_depends,
+ commandLines, comment, working.c_str(), false, escapeOldStyle,
+ uses_terminal, command_expand_lists, depfile, job_pool);
} else if (!byproducts.empty()) {
- this->SetError("BYPRODUCTS may not be specified with SOURCE signatures");
+ status.SetError("BYPRODUCTS may not be specified with SOURCE signatures");
return false;
} else if (uses_terminal) {
- this->SetError("USES_TERMINAL may not be used with SOURCE signatures");
+ status.SetError("USES_TERMINAL may not be used with SOURCE signatures");
return false;
} else {
bool issueMessage = true;
std::ostringstream e;
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0050)) {
+ MessageType messageType = MessageType::AUTHOR_WARNING;
+ switch (mf.GetPolicyStatus(cmPolicies::CMP0050)) {
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0050) << "\n";
break;
@@ -331,51 +365,23 @@ bool cmAddCustomCommandCommand::InitialPass(
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::NEW:
- messageType = cmake::FATAL_ERROR;
+ messageType = MessageType::FATAL_ERROR;
break;
}
if (issueMessage) {
e << "The SOURCE signatures of add_custom_command are no longer "
"supported.";
- this->Makefile->IssueMessage(messageType, e.str());
- if (messageType == cmake::FATAL_ERROR) {
+ mf.IssueMessage(messageType, e.str());
+ if (messageType == MessageType::FATAL_ERROR) {
return false;
}
}
// Use the old-style mode for backward compatibility.
- this->Makefile->AddCustomCommandOldStyle(target, outputs, depends, source,
- commandLines, comment);
+ mf.AddCustomCommandOldStyle(target, outputs, depends, source, commandLines,
+ comment);
}
return true;
}
-
-bool cmAddCustomCommandCommand::CheckOutputs(
- const std::vector<std::string>& outputs)
-{
- for (std::vector<std::string>::const_iterator o = outputs.begin();
- o != outputs.end(); ++o) {
- // 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())) {
- std::string e = "attempted to have a file \"" + *o +
- "\" in a source directory as an output of custom command.";
- this->SetError(e);
- cmSystemTools::SetFatalErrorOccured();
- return false;
- }
-
- // Make sure the output file name has no invalid characters.
- std::string::size_type pos = o->find_first_of("#<>");
- if (pos != std::string::npos) {
- std::ostringstream msg;
- msg << "called with OUTPUT containing a \"" << (*o)[pos]
- << "\". This character is not allowed.";
- this->SetError(msg.str());
- return false;
- }
- }
- return true;
-}
diff --git a/Source/cmAddCustomCommandCommand.h b/Source/cmAddCustomCommandCommand.h
index c3a91b2a3..4f8c58fef 100644
--- a/Source/cmAddCustomCommandCommand.h
+++ b/Source/cmAddCustomCommandCommand.h
@@ -3,38 +3,14 @@
#ifndef cmAddCustomCommandCommand_h
#define cmAddCustomCommandCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmAddCustomCommandCommand
- * \brief cmAddCustomCommandCommand defines a new command (rule) that can
- * be executed within the build process
- *
- */
-
-class cmAddCustomCommandCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmAddCustomCommandCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-protected:
- bool CheckOutputs(const std::vector<std::string>& outputs);
-};
+bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx
index 87e114780..e27b126dd 100644
--- a/Source/cmAddCustomTargetCommand.cxx
+++ b/Source/cmAddCustomTargetCommand.cxx
@@ -2,37 +2,37 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmAddCustomTargetCommand.h"
-#include <sstream>
+#include <utility>
+#include "cmCheckCustomOutputs.h"
#include "cmCustomCommandLines.h"
+#include "cmCustomCommandTypes.h"
+#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
-#include "cmPolicies.h"
+#include "cmMessageType.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
-#include "cmake.h"
-class cmExecutionStatus;
-
-// cmAddCustomTargetCommand
-bool cmAddCustomTargetCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmAddCustomTargetCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
+ cmMakefile& mf = status.GetMakefile();
std::string const& targetName = args[0];
// Check the target name.
if (targetName.find_first_of("/\\") != std::string::npos) {
- std::ostringstream e;
- e << "called with invalid target name \"" << targetName
- << "\". Target names may not contain a slash. "
- << "Use ADD_CUSTOM_COMMAND to generate files.";
- this->SetError(e.str());
+ status.SetError(cmStrCat("called with invalid target name \"", targetName,
+ "\". Target names may not contain a slash. "
+ "Use ADD_CUSTOM_COMMAND to generate files."));
return false;
}
@@ -43,14 +43,16 @@ bool cmAddCustomTargetCommand::InitialPass(
cmCustomCommandLines commandLines;
// Accumulate dependencies.
- std::vector<std::string> depends, byproducts;
+ std::vector<std::string> depends;
+ std::vector<std::string> byproducts;
std::string working_directory;
bool verbatim = false;
bool uses_terminal = false;
bool command_expand_lists = false;
std::string comment_buffer;
- const char* comment = CM_NULLPTR;
+ const char* comment = nullptr;
std::vector<std::string> sources;
+ std::string job_pool;
// Keep track of parser state.
enum tdoing
@@ -61,6 +63,7 @@ bool cmAddCustomTargetCommand::InitialPass(
doing_working_directory,
doing_comment,
doing_source,
+ doing_job_pool,
doing_nothing
};
tdoing doing = doing_command;
@@ -96,6 +99,8 @@ bool cmAddCustomTargetCommand::InitialPass(
command_expand_lists = true;
} else if (copy == "COMMENT") {
doing = doing_comment;
+ } else if (copy == "JOB_POOL") {
+ doing = doing_job_pool;
} else if (copy == "COMMAND") {
doing = doing_command;
@@ -116,18 +121,17 @@ bool cmAddCustomTargetCommand::InitialPass(
break;
case doing_byproducts: {
std::string filename;
- if (!cmSystemTools::FileIsFullPath(copy.c_str())) {
- filename = this->Makefile->GetCurrentBinaryDirectory();
- filename += "/";
+ if (!cmSystemTools::FileIsFullPath(copy)) {
+ filename = cmStrCat(mf.GetCurrentBinaryDirectory(), '/');
}
filename += copy;
cmSystemTools::ConvertToUnixSlashes(filename);
- byproducts.push_back(filename);
+ byproducts.push_back(cmSystemTools::CollapseFullPath(filename));
} break;
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;
@@ -136,8 +140,11 @@ bool cmAddCustomTargetCommand::InitialPass(
case doing_source:
sources.push_back(copy);
break;
+ case doing_job_pool:
+ job_pool = copy;
+ break;
default:
- this->SetError("Wrong syntax. Unknown type of argument.");
+ status.SetError("Wrong syntax. Unknown type of argument.");
return false;
}
}
@@ -145,10 +152,9 @@ bool cmAddCustomTargetCommand::InitialPass(
std::string::size_type pos = targetName.find_first_of("#<>");
if (pos != std::string::npos) {
- std::ostringstream msg;
- msg << "called with target name containing a \"" << targetName[pos]
- << "\". This character is not allowed.";
- this->SetError(msg.str());
+ status.SetError(cmStrCat("called with target name containing a \"",
+ targetName[pos],
+ "\". This character is not allowed."));
return false;
}
@@ -160,35 +166,8 @@ 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 && !mf.CheckCMP0037(targetName, cmStateEnums::UTILITY)) {
+ return false;
}
// Store the last command line finished.
@@ -200,44 +179,45 @@ bool cmAddCustomTargetCommand::InitialPass(
// Enforce name uniqueness.
{
std::string msg;
- if (!this->Makefile->EnforceUniqueName(targetName, msg, true)) {
- this->SetError(msg);
+ if (!mf.EnforceUniqueName(targetName, msg, true)) {
+ status.SetError(msg);
return false;
}
}
- // Convert working directory to a full path.
- if (!working_directory.empty()) {
- const char* build_dir = this->Makefile->GetCurrentBinaryDirectory();
- working_directory =
- cmSystemTools::CollapseFullPath(working_directory, build_dir);
- }
-
if (commandLines.empty() && !byproducts.empty()) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
- "BYPRODUCTS may not be specified without any COMMAND");
+ mf.IssueMessage(MessageType::FATAL_ERROR,
+ "BYPRODUCTS may not be specified without any COMMAND");
return true;
}
if (commandLines.empty() && uses_terminal) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
- "USES_TERMINAL may not be specified without any COMMAND");
+ mf.IssueMessage(MessageType::FATAL_ERROR,
+ "USES_TERMINAL may not be specified without any COMMAND");
return true;
}
if (commandLines.empty() && command_expand_lists) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
"COMMAND_EXPAND_LISTS may not be specified without any COMMAND");
return true;
}
+ if (uses_terminal && !job_pool.empty()) {
+ status.SetError("JOB_POOL is shadowed by USES_TERMINAL.");
+ return false;
+ }
+
+ // Make sure the byproduct names and locations are safe.
+ if (!cmCheckCustomOutputs(byproducts, "BYPRODUCTS", status)) {
+ return false;
+ }
+
// 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);
+ cmTarget* target = mf.AddUtilityCommand(
+ targetName, cmCommandOrigin::Project, excludeFromAll,
+ working_directory.c_str(), byproducts, depends, commandLines,
+ escapeOldStyle, comment, uses_terminal, command_expand_lists, job_pool);
// Add additional user-specified source files to the target.
target->AddSources(sources);
diff --git a/Source/cmAddCustomTargetCommand.h b/Source/cmAddCustomTargetCommand.h
index 7229c2779..e23ef9fcc 100644
--- a/Source/cmAddCustomTargetCommand.h
+++ b/Source/cmAddCustomTargetCommand.h
@@ -3,36 +3,14 @@
#ifndef cmAddCustomTargetCommand_h
#define cmAddCustomTargetCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmAddCustomTargetCommand
- * \brief Command that adds a target to the build system.
- *
- * cmAddCustomTargetCommand adds an extra target to the build system.
- * This is useful when you would like to add special
- * targets like "install,", "clean," and so on.
- */
-class cmAddCustomTargetCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmAddCustomTargetCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmAddCustomTargetCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmAddDefinitionsCommand.cxx b/Source/cmAddDefinitionsCommand.cxx
index 9e0607c60..0b10aeef6 100644
--- a/Source/cmAddDefinitionsCommand.cxx
+++ b/Source/cmAddDefinitionsCommand.cxx
@@ -2,22 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmAddDefinitionsCommand.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-class cmExecutionStatus;
-
-// cmAddDefinitionsCommand
-bool cmAddDefinitionsCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmAddDefinitionsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- // it is OK to have no arguments
- if (args.empty()) {
- return true;
- }
-
- for (std::vector<std::string>::const_iterator i = args.begin();
- i != args.end(); ++i) {
- this->Makefile->AddDefineFlag(i->c_str());
+ cmMakefile& mf = status.GetMakefile();
+ for (std::string const& i : args) {
+ mf.AddDefineFlag(i);
}
return true;
}
diff --git a/Source/cmAddDefinitionsCommand.h b/Source/cmAddDefinitionsCommand.h
index abf5a5964..a67f09516 100644
--- a/Source/cmAddDefinitionsCommand.h
+++ b/Source/cmAddDefinitionsCommand.h
@@ -3,35 +3,14 @@
#ifndef cmAddDefinitionsCommand_h
#define cmAddDefinitionsCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmAddDefinitionsCommand
- * \brief Specify a list of compiler defines
- *
- * cmAddDefinitionsCommand specifies a list of compiler defines. These defines
- * will be added to the compile command.
- */
-class cmAddDefinitionsCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmAddDefinitionsCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmAddDefinitionsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmAddDependenciesCommand.cxx b/Source/cmAddDependenciesCommand.cxx
index a73b57e82..b1fc89341 100644
--- a/Source/cmAddDependenciesCommand.cxx
+++ b/Source/cmAddDependenciesCommand.cxx
@@ -2,45 +2,47 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmAddDependenciesCommand.h"
-#include <sstream>
-
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmRange.h"
+#include "cmStringAlgorithms.h"
#include "cmTarget.h"
-#include "cmake.h"
-
-class cmExecutionStatus;
-// cmDependenciesCommand
-bool cmAddDependenciesCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmAddDependenciesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
+ cmMakefile& mf = status.GetMakefile();
std::string const& target_name = args[0];
- if (this->Makefile->IsAlias(target_name)) {
- std::ostringstream e;
- e << "Cannot add target-level dependencies to alias target \""
- << target_name << "\".\n";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ if (mf.IsAlias(target_name)) {
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Cannot add target-level dependencies to alias target \"",
+ target_name, "\".\n"));
}
- if (cmTarget* target = this->Makefile->FindTargetToUse(target_name)) {
- std::vector<std::string>::const_iterator s = args.begin();
- ++s; // skip over target_name
- for (; s != args.end(); ++s) {
- target->AddUtility(*s, this->Makefile);
+ if (cmTarget* target = mf.FindTargetToUse(target_name)) {
+
+ // skip over target_name
+ for (std::string const& arg : cmMakeRange(args).advance(1)) {
+ target->AddUtility(arg, &mf);
}
} else {
- std::ostringstream e;
- e << "Cannot add target-level dependencies to non-existent target \""
- << target_name << "\".\n"
- << "The add_dependencies works for top-level logical targets created "
- << "by the add_executable, add_library, or add_custom_target commands. "
- << "If you want to add file-level dependencies see the DEPENDS option "
- << "of the add_custom_target and add_custom_command commands.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(
+ "Cannot add target-level dependencies to non-existent "
+ "target \"",
+ target_name,
+ "\".\nThe add_dependencies works for "
+ "top-level logical targets created by the add_executable, "
+ "add_library, or add_custom_target commands. If you want to add "
+ "file-level dependencies see the DEPENDS option of the "
+ "add_custom_target and add_custom_command commands."));
}
return true;
diff --git a/Source/cmAddDependenciesCommand.h b/Source/cmAddDependenciesCommand.h
index c7328d63e..0c60e3a2d 100644
--- a/Source/cmAddDependenciesCommand.h
+++ b/Source/cmAddDependenciesCommand.h
@@ -3,34 +3,14 @@
#ifndef cmDependenciessCommand_h
#define cmDependenciessCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmAddDependenciesCommand
- * \brief Add a dependency to a target
- *
- * cmAddDependenciesCommand adds a dependency to a target
- */
-class cmAddDependenciesCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmAddDependenciesCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmAddDependenciesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx
index 1d0376fe0..e738bc467 100644
--- a/Source/cmAddExecutableCommand.cxx
+++ b/Source/cmAddExecutableCommand.cxx
@@ -2,27 +2,24 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmAddExecutableCommand.h"
-#include <sstream>
-
+#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
-#include "cmPolicies.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmTarget.h"
-#include "cmake.h"
-
-class cmExecutionStatus;
-// cmExecutableCommand
-bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmAddExecutableCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- if (args.size() < 2) {
- this->SetError("called with incorrect number of arguments");
+ if (args.empty()) {
+ status.SetError("called with incorrect number of arguments");
return false;
}
- std::vector<std::string>::const_iterator s = args.begin();
+
+ cmMakefile& mf = status.GetMakefile();
+ auto s = args.begin();
std::string const& exename = *s;
@@ -63,143 +60,100 @@ 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 && !mf.CheckCMP0037(exename, cmStateEnums::EXECUTABLE)) {
+ return false;
}
// Special modifiers are not allowed with IMPORTED signature.
if (importTarget && (use_win32 || use_macbundle || excludeFromAll)) {
if (use_win32) {
- this->SetError("may not be given WIN32 for an IMPORTED target.");
+ status.SetError("may not be given WIN32 for an IMPORTED target.");
} else if (use_macbundle) {
- this->SetError("may not be given MACOSX_BUNDLE for an IMPORTED target.");
+ status.SetError(
+ "may not be given MACOSX_BUNDLE for an IMPORTED target.");
} else // if(excludeFromAll)
{
- this->SetError(
+ status.SetError(
"may not be given EXCLUDE_FROM_ALL for an IMPORTED target.");
}
return false;
}
if (isAlias) {
if (!cmGeneratorExpression::IsValidTargetName(exename)) {
- this->SetError("Invalid name for ALIAS: " + exename);
+ status.SetError("Invalid name for ALIAS: " + exename);
return false;
}
if (excludeFromAll) {
- this->SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense.");
+ status.SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense.");
return false;
}
if (importTarget || importGlobal) {
- this->SetError("IMPORTED with ALIAS is not allowed.");
+ status.SetError("IMPORTED with ALIAS is not allowed.");
return false;
}
if (args.size() != 3) {
- std::ostringstream e;
- e << "ALIAS requires exactly one target argument.";
- this->SetError(e.str());
+ status.SetError("ALIAS requires exactly one target argument.");
return false;
}
- const char* aliasedName = s->c_str();
- if (this->Makefile->IsAlias(aliasedName)) {
- std::ostringstream e;
- e << "cannot create ALIAS target \"" << exename << "\" because target \""
- << aliasedName << "\" is itself an ALIAS.";
- this->SetError(e.str());
+ std::string const& aliasedName = *s;
+ if (mf.IsAlias(aliasedName)) {
+ status.SetError(cmStrCat("cannot create ALIAS target \"", exename,
+ "\" because target \"", aliasedName,
+ "\" is itself an ALIAS."));
return false;
}
- cmTarget* aliasedTarget =
- this->Makefile->FindTargetToUse(aliasedName, true);
+ cmTarget* aliasedTarget = mf.FindTargetToUse(aliasedName, true);
if (!aliasedTarget) {
- std::ostringstream e;
- e << "cannot create ALIAS target \"" << exename << "\" because target \""
- << aliasedName << "\" does not already "
- "exist.";
- this->SetError(e.str());
+ status.SetError(cmStrCat("cannot create ALIAS target \"", exename,
+ "\" because target \"", aliasedName,
+ "\" does not already exist."));
return false;
}
cmStateEnums::TargetType type = aliasedTarget->GetType();
if (type != cmStateEnums::EXECUTABLE) {
- std::ostringstream e;
- e << "cannot create ALIAS target \"" << exename << "\" because target \""
- << aliasedName << "\" is not an "
- "executable.";
- this->SetError(e.str());
+ status.SetError(cmStrCat("cannot create ALIAS target \"", exename,
+ "\" because target \"", aliasedName,
+ "\" is not an executable."));
return false;
}
- if (aliasedTarget->IsImported()) {
- std::ostringstream e;
- e << "cannot create ALIAS target \"" << exename << "\" because target \""
- << aliasedName << "\" is IMPORTED.";
- this->SetError(e.str());
+ if (aliasedTarget->IsImported() &&
+ !aliasedTarget->IsImportedGloballyVisible()) {
+ status.SetError(cmStrCat("cannot create ALIAS target \"", exename,
+ "\" because target \"", aliasedName,
+ "\" is imported but not globally visible."));
return false;
}
- this->Makefile->AddAlias(exename, aliasedName);
+ mf.AddAlias(exename, aliasedName);
return true;
}
// Handle imported target creation.
if (importTarget) {
// Make sure the target does not already exist.
- if (this->Makefile->FindTargetToUse(exename)) {
- std::ostringstream e;
- e << "cannot create imported target \"" << exename
- << "\" because another target with the same name already exists.";
- this->SetError(e.str());
+ if (mf.FindTargetToUse(exename)) {
+ status.SetError(cmStrCat(
+ "cannot create imported target \"", exename,
+ "\" because another target with the same name already exists."));
return false;
}
// Create the imported target.
- this->Makefile->AddImportedTarget(exename, cmStateEnums::EXECUTABLE,
- importGlobal);
+ mf.AddImportedTarget(exename, cmStateEnums::EXECUTABLE, importGlobal);
return true;
}
// Enforce name uniqueness.
{
std::string msg;
- if (!this->Makefile->EnforceUniqueName(exename, msg)) {
- this->SetError(msg);
+ if (!mf.EnforceUniqueName(exename, msg)) {
+ status.SetError(msg);
return false;
}
}
- 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);
+ cmTarget* tgt = mf.AddExecutable(exename, srclists, excludeFromAll);
if (use_win32) {
tgt->SetProperty("WIN32_EXECUTABLE", "ON");
}
diff --git a/Source/cmAddExecutableCommand.h b/Source/cmAddExecutableCommand.h
index 8100da185..f7bc27336 100644
--- a/Source/cmAddExecutableCommand.h
+++ b/Source/cmAddExecutableCommand.h
@@ -3,35 +3,14 @@
#ifndef cmExecutablesCommand_h
#define cmExecutablesCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmExecutablesCommand
- * \brief Defines a list of executables to build.
- *
- * cmExecutablesCommand defines a list of executable (i.e., test)
- * programs to create.
- */
-class cmAddExecutableCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmAddExecutableCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmAddExecutableCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index ebf17632a..0439c518c 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -2,40 +2,37 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmAddLibraryCommand.h"
-#include <sstream>
-
+#include "cmAlgorithms.h"
+#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
-#include "cmPolicies.h"
+#include "cmMessageType.h"
#include "cmState.h"
#include "cmStateTypes.h"
-#include "cmSystemTools.h"
+#include "cmStringAlgorithms.h"
#include "cmTarget.h"
-#include "cmake.h"
-
-class cmExecutionStatus;
-// cmLibraryCommand
-bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmAddLibraryCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
+
+ cmMakefile& mf = status.GetMakefile();
// Library type defaults to value of BUILD_SHARED_LIBS, if it exists,
// otherwise it defaults to static library.
cmStateEnums::TargetType type = cmStateEnums::SHARED_LIBRARY;
- if (cmSystemTools::IsOff(
- this->Makefile->GetDefinition("BUILD_SHARED_LIBS"))) {
+ if (cmIsOff(mf.GetDefinition("BUILD_SHARED_LIBS"))) {
type = cmStateEnums::STATIC_LIBRARY;
}
bool excludeFromAll = false;
bool importTarget = false;
bool importGlobal = false;
- std::vector<std::string>::const_iterator s = args.begin();
+ auto s = args.begin();
std::string const& libName = *s;
@@ -50,9 +47,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
std::string libType = *s;
if (libType == "STATIC") {
if (type == cmStateEnums::INTERFACE_LIBRARY) {
- std::ostringstream e;
- e << "INTERFACE library specified with conflicting STATIC type.";
- this->SetError(e.str());
+ status.SetError(
+ "INTERFACE library specified with conflicting STATIC type.");
return false;
}
++s;
@@ -60,9 +56,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
haveSpecifiedType = true;
} else if (libType == "SHARED") {
if (type == cmStateEnums::INTERFACE_LIBRARY) {
- std::ostringstream e;
- e << "INTERFACE library specified with conflicting SHARED type.";
- this->SetError(e.str());
+ status.SetError(
+ "INTERFACE library specified with conflicting SHARED type.");
return false;
}
++s;
@@ -70,9 +65,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
haveSpecifiedType = true;
} else if (libType == "MODULE") {
if (type == cmStateEnums::INTERFACE_LIBRARY) {
- std::ostringstream e;
- e << "INTERFACE library specified with conflicting MODULE type.";
- this->SetError(e.str());
+ status.SetError(
+ "INTERFACE library specified with conflicting MODULE type.");
return false;
}
++s;
@@ -80,9 +74,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
haveSpecifiedType = true;
} else if (libType == "OBJECT") {
if (type == cmStateEnums::INTERFACE_LIBRARY) {
- std::ostringstream e;
- e << "INTERFACE library specified with conflicting OBJECT type.";
- this->SetError(e.str());
+ status.SetError(
+ "INTERFACE library specified with conflicting OBJECT type.");
return false;
}
++s;
@@ -90,9 +83,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
haveSpecifiedType = true;
} else if (libType == "UNKNOWN") {
if (type == cmStateEnums::INTERFACE_LIBRARY) {
- std::ostringstream e;
- e << "INTERFACE library specified with conflicting UNKNOWN type.";
- this->SetError(e.str());
+ status.SetError(
+ "INTERFACE library specified with conflicting UNKNOWN type.");
return false;
}
++s;
@@ -100,30 +92,26 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
haveSpecifiedType = true;
} else if (libType == "ALIAS") {
if (type == cmStateEnums::INTERFACE_LIBRARY) {
- std::ostringstream e;
- e << "INTERFACE library specified with conflicting ALIAS type.";
- this->SetError(e.str());
+ status.SetError(
+ "INTERFACE library specified with conflicting ALIAS type.");
return false;
}
++s;
isAlias = true;
} else if (libType == "INTERFACE") {
if (haveSpecifiedType) {
- std::ostringstream e;
- e << "INTERFACE library specified with conflicting/multiple types.";
- this->SetError(e.str());
+ status.SetError(
+ "INTERFACE library specified with conflicting/multiple types.");
return false;
}
if (isAlias) {
- std::ostringstream e;
- e << "INTERFACE library specified with conflicting ALIAS type.";
- this->SetError(e.str());
+ status.SetError(
+ "INTERFACE library specified with conflicting ALIAS type.");
return false;
}
if (excludeFromAll) {
- std::ostringstream e;
- e << "INTERFACE library may not be used with EXCLUDE_FROM_ALL.";
- this->SetError(e.str());
+ status.SetError(
+ "INTERFACE library may not be used with EXCLUDE_FROM_ALL.");
return false;
}
++s;
@@ -131,9 +119,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
haveSpecifiedType = true;
} else if (*s == "EXCLUDE_FROM_ALL") {
if (type == cmStateEnums::INTERFACE_LIBRARY) {
- std::ostringstream e;
- e << "INTERFACE library may not be used with EXCLUDE_FROM_ALL.";
- this->SetError(e.str());
+ status.SetError(
+ "INTERFACE library may not be used with EXCLUDE_FROM_ALL.");
return false;
}
++s;
@@ -145,9 +132,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
++s;
importGlobal = true;
} else if (type == cmStateEnums::INTERFACE_LIBRARY && *s == "GLOBAL") {
- std::ostringstream e;
- e << "GLOBAL option may only be used with IMPORTED libraries.";
- this->SetError(e.str());
+ status.SetError(
+ "GLOBAL option may only be used with IMPORTED libraries.");
return false;
} else {
break;
@@ -156,15 +142,12 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
if (type == cmStateEnums::INTERFACE_LIBRARY) {
if (s != args.end()) {
- std::ostringstream e;
- e << "INTERFACE library requires no source arguments.";
- this->SetError(e.str());
+ status.SetError("INTERFACE library requires no source arguments.");
return false;
}
if (importGlobal && !importTarget) {
- std::ostringstream e;
- e << "INTERFACE library specified as GLOBAL, but not as IMPORTED.";
- this->SetError(e.str());
+ status.SetError(
+ "INTERFACE library specified as GLOBAL, but not as IMPORTED.");
return false;
}
}
@@ -175,73 +158,40 @@ 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 && !mf.CheckCMP0037(libName, type)) {
+ return false;
}
if (isAlias) {
if (!cmGeneratorExpression::IsValidTargetName(libName)) {
- this->SetError("Invalid name for ALIAS: " + libName);
+ status.SetError("Invalid name for ALIAS: " + libName);
return false;
}
if (excludeFromAll) {
- this->SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense.");
+ status.SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense.");
return false;
}
if (importTarget || importGlobal) {
- this->SetError("IMPORTED with ALIAS is not allowed.");
+ status.SetError("IMPORTED with ALIAS is not allowed.");
return false;
}
if (args.size() != 3) {
- std::ostringstream e;
- e << "ALIAS requires exactly one target argument.";
- this->SetError(e.str());
+ status.SetError("ALIAS requires exactly one target argument.");
return false;
}
- const char* aliasedName = s->c_str();
- if (this->Makefile->IsAlias(aliasedName)) {
- std::ostringstream e;
- e << "cannot create ALIAS target \"" << libName << "\" because target \""
- << aliasedName << "\" is itself an ALIAS.";
- this->SetError(e.str());
+ std::string const& aliasedName = *s;
+ if (mf.IsAlias(aliasedName)) {
+ status.SetError(cmStrCat("cannot create ALIAS target \"", libName,
+ "\" because target \"", aliasedName,
+ "\" is itself an ALIAS."));
return false;
}
- cmTarget* aliasedTarget =
- this->Makefile->FindTargetToUse(aliasedName, true);
+ cmTarget* aliasedTarget = mf.FindTargetToUse(aliasedName, true);
if (!aliasedTarget) {
- std::ostringstream e;
- e << "cannot create ALIAS target \"" << libName << "\" because target \""
- << aliasedName << "\" does not already "
- "exist.";
- this->SetError(e.str());
+ status.SetError(cmStrCat("cannot create ALIAS target \"", libName,
+ "\" because target \"", aliasedName,
+ "\" does not already exist."));
return false;
}
cmStateEnums::TargetType aliasedType = aliasedTarget->GetType();
@@ -249,26 +199,27 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
aliasedType != cmStateEnums::STATIC_LIBRARY &&
aliasedType != cmStateEnums::MODULE_LIBRARY &&
aliasedType != cmStateEnums::OBJECT_LIBRARY &&
- aliasedType != cmStateEnums::INTERFACE_LIBRARY) {
- std::ostringstream e;
- e << "cannot create ALIAS target \"" << libName << "\" because target \""
- << aliasedName << "\" is not a library.";
- this->SetError(e.str());
+ aliasedType != cmStateEnums::INTERFACE_LIBRARY &&
+ !(aliasedType == cmStateEnums::UNKNOWN_LIBRARY &&
+ aliasedTarget->IsImported())) {
+ status.SetError(cmStrCat("cannot create ALIAS target \"", libName,
+ "\" because target \"", aliasedName,
+ "\" is not a library."));
return false;
}
- if (aliasedTarget->IsImported()) {
- std::ostringstream e;
- e << "cannot create ALIAS target \"" << libName << "\" because target \""
- << aliasedName << "\" is IMPORTED.";
- this->SetError(e.str());
+ if (aliasedTarget->IsImported() &&
+ !aliasedTarget->IsImportedGloballyVisible()) {
+ status.SetError(cmStrCat("cannot create ALIAS target \"", libName,
+ "\" because target \"", aliasedName,
+ "\" is imported but not globally visible."));
return false;
}
- this->Makefile->AddAlias(libName, aliasedName);
+ mf.AddAlias(libName, aliasedName);
return true;
}
if (importTarget && excludeFromAll) {
- this->SetError("excludeFromAll with IMPORTED target makes no sense.");
+ status.SetError("excludeFromAll with IMPORTED target makes no sense.");
return false;
}
@@ -278,14 +229,14 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
yet its linker language. */
if ((type == cmStateEnums::SHARED_LIBRARY ||
type == cmStateEnums::MODULE_LIBRARY) &&
- !this->Makefile->GetState()->GetGlobalPropertyAsBool(
- "TARGET_SUPPORTS_SHARED_LIBS")) {
- std::ostringstream w;
- w << "ADD_LIBRARY called with "
- << (type == cmStateEnums::SHARED_LIBRARY ? "SHARED" : "MODULE")
- << " option but the target platform does not support dynamic linking. "
- "Building a STATIC library instead. This may lead to problems.";
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ !mf.GetState()->GetGlobalPropertyAsBool("TARGET_SUPPORTS_SHARED_LIBS")) {
+ mf.IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(
+ "ADD_LIBRARY called with ",
+ (type == cmStateEnums::SHARED_LIBRARY ? "SHARED" : "MODULE"),
+ " option but the target platform does not support dynamic linking. ",
+ "Building a STATIC library instead. This may lead to problems."));
type = cmStateEnums::STATIC_LIBRARY;
}
@@ -293,15 +244,14 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
if (importTarget) {
// The IMPORTED signature requires a type to be specified explicitly.
if (!haveSpecifiedType) {
- this->SetError("called with IMPORTED argument but no library type.");
+ status.SetError("called with IMPORTED argument but no library type.");
return false;
}
if (type == cmStateEnums::OBJECT_LIBRARY) {
std::string reason;
- if (!this->Makefile->GetGlobalGenerator()->HasKnownObjectFileLocation(
- &reason)) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ if (!mf.GetGlobalGenerator()->HasKnownObjectFileLocation(&reason)) {
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
"The OBJECT library type may not be used for IMPORTED libraries" +
reason + ".");
return true;
@@ -309,31 +259,29 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
}
if (type == cmStateEnums::INTERFACE_LIBRARY) {
if (!cmGeneratorExpression::IsValidTargetName(libName)) {
- std::ostringstream e;
- e << "Invalid name for IMPORTED INTERFACE library target: " << libName;
- this->SetError(e.str());
+ status.SetError(cmStrCat(
+ "Invalid name for IMPORTED INTERFACE library target: ", libName));
return false;
}
}
// Make sure the target does not already exist.
- if (this->Makefile->FindTargetToUse(libName)) {
- std::ostringstream e;
- e << "cannot create imported target \"" << libName
- << "\" because another target with the same name already exists.";
- this->SetError(e.str());
+ if (mf.FindTargetToUse(libName)) {
+ status.SetError(cmStrCat(
+ "cannot create imported target \"", libName,
+ "\" because another target with the same name already exists."));
return false;
}
// Create the imported target.
- this->Makefile->AddImportedTarget(libName, type, importGlobal);
+ mf.AddImportedTarget(libName, type, importGlobal);
return true;
}
// A non-imported target may not have UNKNOWN type.
if (type == cmStateEnums::UNKNOWN_LIBRARY) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
"The UNKNOWN library type may be used only for IMPORTED libraries.");
return true;
}
@@ -341,8 +289,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
// Enforce name uniqueness.
{
std::string msg;
- if (!this->Makefile->EnforceUniqueName(libName, msg)) {
- this->SetError(msg);
+ if (!mf.EnforceUniqueName(libName, msg)) {
+ status.SetError(msg);
return false;
}
}
@@ -352,27 +300,18 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
if (type == cmStateEnums::INTERFACE_LIBRARY) {
if (!cmGeneratorExpression::IsValidTargetName(libName) ||
libName.find("::") != std::string::npos) {
- std::ostringstream e;
- e << "Invalid name for INTERFACE library target: " << libName;
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("Invalid name for INTERFACE library target: ", libName));
return false;
}
- this->Makefile->AddLibrary(libName, type, srclists, excludeFromAll);
+ mf.AddLibrary(libName, type, srclists, excludeFromAll);
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());
+ cmAppend(srclists, s, args.end());
- this->Makefile->AddLibrary(libName, type, srclists, excludeFromAll);
+ mf.AddLibrary(libName, type, srclists, excludeFromAll);
return true;
}
diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h
index df49fae93..609449c87 100644
--- a/Source/cmAddLibraryCommand.h
+++ b/Source/cmAddLibraryCommand.h
@@ -3,35 +3,14 @@
#ifndef cmLibrarysCommand_h
#define cmLibrarysCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmLibrarysCommand
- * \brief Defines a list of executables to build.
- *
- * cmLibrarysCommand defines a list of executable (i.e., test)
- * programs to create.
- */
-class cmAddLibraryCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmAddLibraryCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmAddLibraryCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmAddLinkOptionsCommand.cxx b/Source/cmAddLinkOptionsCommand.cxx
new file mode 100644
index 000000000..7ed31bdbc
--- /dev/null
+++ b/Source/cmAddLinkOptionsCommand.cxx
@@ -0,0 +1,16 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmAddLinkOptionsCommand.h"
+
+#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+
+bool cmAddLinkOptionsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ cmMakefile& mf = status.GetMakefile();
+ for (std::string const& i : args) {
+ mf.AddLinkOption(i);
+ }
+ return true;
+}
diff --git a/Source/cmAddLinkOptionsCommand.h b/Source/cmAddLinkOptionsCommand.h
new file mode 100644
index 000000000..466fc3215
--- /dev/null
+++ b/Source/cmAddLinkOptionsCommand.h
@@ -0,0 +1,16 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmAddLinkOptionsCommand_h
+#define cmAddLinkOptionsCommand_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+class cmExecutionStatus;
+
+bool cmAddLinkOptionsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+
+#endif
diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx
index 1727ca56f..6a1a514f7 100644
--- a/Source/cmAddSubDirectoryCommand.cxx
+++ b/Source/cmAddSubDirectoryCommand.cxx
@@ -2,41 +2,39 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmAddSubDirectoryCommand.h"
-#include <sstream>
-#include <string.h>
+#include <cstring>
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmRange.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
-
-// cmAddSubDirectoryCommand
-bool cmAddSubDirectoryCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmAddSubDirectoryCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
+ cmMakefile& mf = status.GetMakefile();
// store the binpath
- std::string const& srcArg = args[0];
+ std::string const& srcArg = args.front();
std::string binArg;
bool excludeFromAll = false;
// process the rest of the arguments looking for optional args
- std::vector<std::string>::const_iterator i = args.begin();
- ++i;
- for (; i != args.end(); ++i) {
- if (*i == "EXCLUDE_FROM_ALL") {
+ for (std::string const& arg : cmMakeRange(args).advance(1)) {
+ if (arg == "EXCLUDE_FROM_ALL") {
excludeFromAll = true;
continue;
}
if (binArg.empty()) {
- binArg = *i;
+ binArg = arg;
} else {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
}
@@ -44,18 +42,15 @@ 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();
- srcPath += "/";
- srcPath += srcArg;
+ srcPath = cmStrCat(mf.GetCurrentSourceDirectory(), '/', srcArg);
}
if (!cmSystemTools::FileIsDirectory(srcPath)) {
- std::string error = "given source \"";
- error += srcArg;
- error += "\" which is not an existing directory.";
- this->SetError(error);
+ std::string error = cmStrCat("given source \"", srcArg,
+ "\" which is not an existing directory.");
+ status.SetError(error);
return false;
}
srcPath = cmSystemTools::CollapseFullPath(srcPath);
@@ -66,46 +61,44 @@ bool cmAddSubDirectoryCommand::InitialPass(
// No binary directory was specified. If the source directory is
// not a subdirectory of the current directory then it is an
// error.
- if (!cmSystemTools::IsSubDirectory(
- srcPath, this->Makefile->GetCurrentSourceDirectory())) {
- std::ostringstream e;
- e << "not given a binary directory but the given source directory "
- << "\"" << srcPath << "\" is not a subdirectory of \""
- << this->Makefile->GetCurrentSourceDirectory() << "\". "
- << "When specifying an out-of-tree source a binary directory "
- << "must be explicitly specified.";
- this->SetError(e.str());
+ if (!cmSystemTools::IsSubDirectory(srcPath,
+ mf.GetCurrentSourceDirectory())) {
+ status.SetError(
+ cmStrCat("not given a binary directory but the given source ",
+ "directory \"", srcPath, "\" is not a subdirectory of \"",
+ mf.GetCurrentSourceDirectory(),
+ "\". When specifying an "
+ "out-of-tree source a binary directory must be explicitly "
+ "specified."));
return false;
}
// Remove the CurrentDirectory from the srcPath and replace it
// with the CurrentOutputDirectory.
- const char* src = this->Makefile->GetCurrentSourceDirectory();
- const char* bin = this->Makefile->GetCurrentBinaryDirectory();
- size_t srcLen = strlen(src);
- size_t binLen = strlen(bin);
- if (srcLen > 0 && src[srcLen - 1] == '/') {
+ const std::string& src = mf.GetCurrentSourceDirectory();
+ const std::string& bin = mf.GetCurrentBinaryDirectory();
+ size_t srcLen = src.length();
+ size_t binLen = bin.length();
+ if (srcLen > 0 && src.back() == '/') {
--srcLen;
}
- if (binLen > 0 && bin[binLen - 1] == '/') {
+ if (binLen > 0 && bin.back() == '/') {
--binLen;
}
- binPath = std::string(bin, binLen) + srcPath.substr(srcLen);
+ binPath = bin.substr(0, binLen) + srcPath.substr(srcLen);
} 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();
- binPath += "/";
- binPath += binArg;
+ binPath = cmStrCat(mf.GetCurrentBinaryDirectory(), '/', binArg);
}
}
binPath = cmSystemTools::CollapseFullPath(binPath);
// Add the subdirectory using the computed full paths.
- this->Makefile->AddSubDirectory(srcPath, binPath, excludeFromAll, true);
+ mf.AddSubDirectory(srcPath, binPath, excludeFromAll, true);
return true;
}
diff --git a/Source/cmAddSubDirectoryCommand.h b/Source/cmAddSubDirectoryCommand.h
index 0e71ffd85..87da8402b 100644
--- a/Source/cmAddSubDirectoryCommand.h
+++ b/Source/cmAddSubDirectoryCommand.h
@@ -3,36 +3,14 @@
#ifndef cmAddSubDirectoryCommand_h
#define cmAddSubDirectoryCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmAddSubDirectoryCommand
- * \brief Specify a subdirectory to build
- *
- * cmAddSubDirectoryCommand specifies a subdirectory to process
- * by CMake. CMake will descend
- * into the specified source directory and process any CMakeLists.txt found.
- */
-class cmAddSubDirectoryCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmAddSubDirectoryCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmAddSubDirectoryCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmAddTestCommand.cxx b/Source/cmAddTestCommand.cxx
index 3a3afdb05..89421131a 100644
--- a/Source/cmAddTestCommand.cxx
+++ b/Source/cmAddTestCommand.cxx
@@ -2,63 +2,63 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmAddTestCommand.h"
-#include <sstream>
-
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
#include "cmTest.h"
#include "cmTestGenerator.h"
-class cmExecutionStatus;
+static bool cmAddTestCommandHandleNameMode(
+ std::vector<std::string> const& args, cmExecutionStatus& status);
-// cmExecutableCommand
-bool cmAddTestCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmAddTestCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (!args.empty() && args[0] == "NAME") {
- return this->HandleNameMode(args);
+ return cmAddTestCommandHandleNameMode(args, status);
}
// First argument is the name of the test Second argument is the name of
// the executable to run (a target or external program) Remaining arguments
// are the arguments to pass to the executable
if (args.size() < 2) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
+ cmMakefile& mf = status.GetMakefile();
// Collect the command with arguments.
- std::vector<std::string> command;
- command.insert(command.end(), args.begin() + 1, args.end());
+ std::vector<std::string> command(args.begin() + 1, args.end());
// Create the test but add a generator only the first time it is
// seen. This preserves behavior from before test generators.
- cmTest* test = this->Makefile->GetTest(args[0]);
+ cmTest* test = mf.GetTest(args[0]);
if (test) {
// If the test was already added by a new-style signature do not
// allow it to be duplicated.
if (!test->GetOldStyle()) {
- std::ostringstream e;
- e << " given test name \"" << args[0]
- << "\" which already exists in this directory.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(" given test name \"", args[0],
+ "\" which already exists in this directory."));
return false;
}
} else {
- test = this->Makefile->CreateTest(args[0]);
+ test = mf.CreateTest(args[0]);
test->SetOldStyle(true);
- this->Makefile->AddTestGenerator(new cmTestGenerator(test));
+ mf.AddTestGenerator(new cmTestGenerator(test));
}
test->SetCommand(command);
return true;
}
-bool cmAddTestCommand::HandleNameMode(std::vector<std::string> const& args)
+bool cmAddTestCommandHandleNameMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
std::string name;
std::vector<std::string> configurations;
std::string working_directory;
std::vector<std::string> command;
+ bool command_expand_lists = false;
// Read the arguments.
enum Doing
@@ -73,22 +73,29 @@ bool cmAddTestCommand::HandleNameMode(std::vector<std::string> const& args)
for (unsigned int i = 1; i < args.size(); ++i) {
if (args[i] == "COMMAND") {
if (!command.empty()) {
- this->SetError(" may be given at most one COMMAND.");
+ status.SetError(" may be given at most one COMMAND.");
return false;
}
doing = DoingCommand;
} else if (args[i] == "CONFIGURATIONS") {
if (!configurations.empty()) {
- this->SetError(" may be given at most one set of CONFIGURATIONS.");
+ status.SetError(" may be given at most one set of CONFIGURATIONS.");
return false;
}
doing = DoingConfigs;
} else if (args[i] == "WORKING_DIRECTORY") {
if (!working_directory.empty()) {
- this->SetError(" may be given at most one WORKING_DIRECTORY.");
+ status.SetError(" may be given at most one WORKING_DIRECTORY.");
return false;
}
doing = DoingWorkingDirectory;
+ } else if (args[i] == "COMMAND_EXPAND_LISTS") {
+ if (command_expand_lists) {
+ status.SetError(" may be given at most one COMMAND_EXPAND_LISTS.");
+ return false;
+ }
+ command_expand_lists = true;
+ doing = DoingNone;
} else if (doing == DoingName) {
name = args[i];
doing = DoingNone;
@@ -100,42 +107,41 @@ bool cmAddTestCommand::HandleNameMode(std::vector<std::string> const& args)
working_directory = args[i];
doing = DoingNone;
} else {
- std::ostringstream e;
- e << " given unknown argument:\n " << args[i] << "\n";
- this->SetError(e.str());
+ status.SetError(cmStrCat(" given unknown argument:\n ", args[i], "\n"));
return false;
}
}
// Require a test name.
if (name.empty()) {
- this->SetError(" must be given non-empty NAME.");
+ status.SetError(" must be given non-empty NAME.");
return false;
}
// Require a command.
if (command.empty()) {
- this->SetError(" must be given non-empty COMMAND.");
+ status.SetError(" must be given non-empty COMMAND.");
return false;
}
+ cmMakefile& mf = status.GetMakefile();
+
// Require a unique test name within the directory.
- if (this->Makefile->GetTest(name)) {
- std::ostringstream e;
- e << " given test NAME \"" << name
- << "\" which already exists in this directory.";
- this->SetError(e.str());
+ if (mf.GetTest(name)) {
+ status.SetError(cmStrCat(" given test NAME \"", name,
+ "\" which already exists in this directory."));
return false;
}
// Add the test.
- cmTest* test = this->Makefile->CreateTest(name);
+ cmTest* test = mf.CreateTest(name);
test->SetOldStyle(false);
test->SetCommand(command);
if (!working_directory.empty()) {
test->SetProperty("WORKING_DIRECTORY", working_directory.c_str());
}
- this->Makefile->AddTestGenerator(new cmTestGenerator(test, configurations));
+ test->SetCommandExpandLists(command_expand_lists);
+ mf.AddTestGenerator(new cmTestGenerator(test, configurations));
return true;
}
diff --git a/Source/cmAddTestCommand.h b/Source/cmAddTestCommand.h
index a098a03f1..5877547e8 100644
--- a/Source/cmAddTestCommand.h
+++ b/Source/cmAddTestCommand.h
@@ -3,37 +3,14 @@
#ifndef cmAddTestCommand_h
#define cmAddTestCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmAddTestCommand
- * \brief Add a test to the lists of tests to run.
- *
- * cmAddTestCommand adds a test to the list of tests to run .
- */
-class cmAddTestCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmAddTestCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- bool HandleNameMode(std::vector<std::string> const& args);
-};
+bool cmAddTestCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmAffinity.cxx b/Source/cmAffinity.cxx
new file mode 100644
index 000000000..8f9fe2ad8
--- /dev/null
+++ b/Source/cmAffinity.cxx
@@ -0,0 +1,65 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmAffinity.h"
+
+#include "cm_uv.h"
+
+#ifndef CMAKE_USE_SYSTEM_LIBUV
+# ifdef _WIN32
+# define CM_HAVE_CPU_AFFINITY
+# include <windows.h>
+# elif defined(__linux__) || defined(__FreeBSD__)
+# define CM_HAVE_CPU_AFFINITY
+# include <pthread.h>
+# include <sched.h>
+// On some platforms CPU_ZERO needs memset but sched.h forgets string.h
+# include <cstring> // IWYU pragma: keep
+# if defined(__FreeBSD__)
+# include <pthread_np.h>
+
+# include <sys/cpuset.h>
+# include <sys/param.h>
+# endif
+# if defined(__linux__)
+using cm_cpuset_t = cpu_set_t;
+# else
+using cm_cpuset_t = cpuset_t;
+# endif
+# endif
+#endif
+
+namespace cmAffinity {
+
+std::set<size_t> GetProcessorsAvailable()
+{
+ std::set<size_t> processorsAvailable;
+#ifdef CM_HAVE_CPU_AFFINITY
+ int cpumask_size = uv_cpumask_size();
+ if (cpumask_size > 0) {
+# ifdef _WIN32
+ DWORD_PTR procmask;
+ DWORD_PTR sysmask;
+ if (GetProcessAffinityMask(GetCurrentProcess(), &procmask, &sysmask) !=
+ 0) {
+ for (int i = 0; i < cpumask_size; ++i) {
+ if (procmask & (((DWORD_PTR)1) << i)) {
+ processorsAvailable.insert(i);
+ }
+ }
+ }
+# else
+ cm_cpuset_t cpuset;
+ CPU_ZERO(&cpuset); // NOLINT(clang-tidy)
+ if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset), &cpuset) == 0) {
+ for (int i = 0; i < cpumask_size; ++i) {
+ if (CPU_ISSET(i, &cpuset)) {
+ processorsAvailable.insert(i);
+ }
+ }
+ }
+# endif
+ }
+#endif
+ return processorsAvailable;
+}
+}
diff --git a/Source/cmAffinity.h b/Source/cmAffinity.h
new file mode 100644
index 000000000..3775bae40
--- /dev/null
+++ b/Source/cmAffinity.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. */
+#pragma once
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cstddef>
+#include <set>
+
+namespace cmAffinity {
+
+std::set<size_t> GetProcessorsAvailable();
+}
diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h
index 4adfe2328..e0d27eedf 100644
--- a/Source/cmAlgorithms.h
+++ b/Source/cmAlgorithms.h
@@ -5,90 +5,25 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cm_kwiml.h"
#include <algorithm>
#include <functional>
#include <iterator>
-#include <sstream>
-#include <string.h>
-#include <string>
+#include <unordered_set>
#include <utility>
#include <vector>
-inline bool cmHasLiteralPrefixImpl(const std::string& str1, const char* str2,
- size_t N)
-{
- return strncmp(str1.c_str(), str2, N) == 0;
-}
-
-inline bool cmHasLiteralPrefixImpl(const char* str1, const char* str2,
- size_t N)
-{
- return strncmp(str1, str2, N) == 0;
-}
-
-inline bool cmHasLiteralSuffixImpl(const std::string& str1, const char* str2,
- size_t N)
-{
- size_t len = str1.size();
- return len >= N && strcmp(str1.c_str() + len - N, str2) == 0;
-}
-
-inline bool cmHasLiteralSuffixImpl(const char* str1, const char* str2,
- size_t N)
-{
- size_t len = strlen(str1);
- return len >= N && strcmp(str1 + len - N, str2) == 0;
-}
-
-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;
-}
+#include "cm_kwiml.h"
-template <typename T, size_t N>
-bool cmHasLiteralPrefix(const T& str1, const char (&str2)[N])
-{
- return cmHasLiteralPrefixImpl(str1, str2, N - 1);
-}
+#include "cmRange.h"
-template <typename T, size_t N>
-bool cmHasLiteralSuffix(const T& str1, const char (&str2)[N])
+template <std::size_t N>
+struct cmOverloadPriority : cmOverloadPriority<N - 1>
{
- return cmHasLiteralSuffixImpl(str1, str2, N - 1);
-}
+};
-struct cmStrCmp
+template <>
+struct cmOverloadPriority<0>
{
- cmStrCmp(const char* test)
- : m_test(test)
- {
- }
- cmStrCmp(const std::string& test)
- : m_test(test)
- {
- }
-
- bool operator()(const std::string& input) const { return m_test == input; }
-
- bool operator()(const char* input) const
- {
- return strcmp(input, m_test.c_str()) == 0;
- }
-
-private:
- const std::string m_test;
};
template <typename FwdIt>
@@ -107,6 +42,34 @@ void cmEraseIf(Container& cont, Predicate pred)
cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end());
}
+template <typename Range, typename Key>
+auto cmContainsImpl(Range const& range, Key const& key, cmOverloadPriority<2>)
+ -> decltype(range.exists(key))
+{
+ return range.exists(key);
+}
+
+template <typename Range, typename Key>
+auto cmContainsImpl(Range const& range, Key const& key, cmOverloadPriority<1>)
+ -> decltype(range.find(key) != range.end())
+{
+ return range.find(key) != range.end();
+}
+
+template <typename Range, typename Key>
+bool cmContainsImpl(Range const& range, Key const& key, cmOverloadPriority<0>)
+{
+ using std::begin;
+ using std::end;
+ return std::find(begin(range), end(range), key) != end(range);
+}
+
+template <typename Range, typename Key>
+bool cmContains(Range const& range, Key const& key)
+{
+ return cmContainsImpl(range, key, cmOverloadPriority<2>{});
+}
+
namespace ContainerAlgorithms {
template <typename T>
@@ -119,7 +82,7 @@ struct cmIsPair
};
template <typename K, typename V>
-struct cmIsPair<std::pair<K, V> >
+struct cmIsPair<std::pair<K, V>>
{
enum
{
@@ -154,7 +117,7 @@ FwdIt RemoveN(FwdIt i1, FwdIt i2, size_t n)
template <typename Range>
struct BinarySearcher
{
- typedef typename Range::value_type argument_type;
+ using argument_type = typename Range::value_type;
BinarySearcher(Range const& r)
: m_range(r)
{
@@ -170,56 +133,9 @@ private:
};
}
-template <typename const_iterator_>
-struct cmRange
-{
- typedef const_iterator_ const_iterator;
- typedef typename std::iterator_traits<const_iterator>::value_type value_type;
- typedef typename std::iterator_traits<const_iterator>::difference_type
- difference_type;
- cmRange(const_iterator begin_, const_iterator end_)
- : Begin(begin_)
- , End(end_)
- {
- }
- const_iterator begin() const { return Begin; }
- const_iterator end() const { return End; }
- bool empty() const { return std::distance(Begin, End) == 0; }
- difference_type size() const { return std::distance(Begin, End); }
- cmRange& advance(KWIML_INT_intptr_t amount)
- {
- std::advance(Begin, amount);
- return *this;
- }
-
- cmRange& retreat(KWIML_INT_intptr_t amount)
- {
- std::advance(End, -amount);
- return *this;
- }
-
-private:
- const_iterator Begin;
- const_iterator End;
-};
-
-typedef cmRange<std::vector<std::string>::const_iterator> cmStringRange;
-
class cmListFileBacktrace;
-typedef cmRange<std::vector<cmListFileBacktrace>::const_iterator>
- cmBacktraceRange;
-
-template <typename Iter1, typename Iter2>
-cmRange<Iter1> cmMakeRange(Iter1 begin, Iter2 end)
-{
- return cmRange<Iter1>(begin, end);
-}
-
-template <typename Range>
-cmRange<typename Range::const_iterator> cmMakeRange(Range const& range)
-{
- return cmRange<typename Range::const_iterator>(range.begin(), range.end());
-}
+using cmBacktraceRange =
+ cmRange<std::vector<cmListFileBacktrace>::const_iterator>;
template <typename Range>
void cmDeleteAll(Range const& r)
@@ -228,29 +144,16 @@ void cmDeleteAll(Range const& r)
ContainerAlgorithms::DefaultDeleter<Range>());
}
-template <typename Range>
-std::string cmJoin(Range const& r, const char* delimiter)
+template <typename T, typename Range>
+void cmAppend(std::vector<T>& v, Range const& r)
{
- if (r.empty()) {
- return std::string();
- }
- std::ostringstream os;
- typedef typename Range::value_type ValueType;
- typedef typename Range::const_iterator InputIt;
- const InputIt first = r.begin();
- InputIt last = r.end();
- --last;
- std::copy(first, last, std::ostream_iterator<ValueType>(os, delimiter));
-
- os << *last;
-
- return os.str();
+ v.insert(v.end(), r.begin(), r.end());
}
-template <typename Range>
-std::string cmJoin(Range const& r, std::string const& delimiter)
+template <typename T, typename InputIt>
+void cmAppend(std::vector<T>& v, InputIt first, InputIt last)
{
- return cmJoin(r, delimiter.c_str());
+ v.insert(v.end(), first, last);
}
template <typename Range>
@@ -264,14 +167,14 @@ typename Range::const_iterator cmRemoveIndices(Range& r, InputRange const& rem)
{
typename InputRange::const_iterator remIt = rem.begin();
typename InputRange::const_iterator remEnd = rem.end();
- const typename Range::iterator rangeEnd = r.end();
+ const auto rangeEnd = r.end();
if (remIt == remEnd) {
return rangeEnd;
}
- typename Range::iterator writer = r.begin();
+ auto writer = r.begin();
std::advance(writer, *remIt);
- typename Range::iterator pivot = writer;
+ auto pivot = writer;
typename InputRange::value_type prevRem = *remIt;
++remIt;
size_t count = 1;
@@ -290,116 +193,51 @@ typename Range::const_iterator cmRemoveMatching(Range& r, MatchRange const& m)
ContainerAlgorithms::BinarySearcher<MatchRange>(m));
}
-namespace ContainerAlgorithms {
-
-template <typename Range, typename T = typename Range::value_type>
-struct RemoveDuplicatesAPI
+template <typename ForwardIterator>
+ForwardIterator cmRemoveDuplicates(ForwardIterator first, ForwardIterator last)
{
- typedef typename Range::const_iterator const_iterator;
- typedef typename Range::const_iterator value_type;
-
- static bool lessThan(value_type a, value_type b) { return *a < *b; }
- static value_type uniqueValue(const_iterator a) { return a; }
- template <typename It>
- static bool valueCompare(It it, const_iterator it2)
+ using Value = typename std::iterator_traits<ForwardIterator>::value_type;
+ using Hash = struct
{
- return **it != *it2;
- }
-};
-
-template <typename Range, typename T>
-struct RemoveDuplicatesAPI<Range, T*>
-{
- typedef typename Range::const_iterator const_iterator;
- typedef T* value_type;
+ std::size_t operator()(ForwardIterator it) const
+ {
+ return std::hash<Value>{}(*it);
+ }
+ };
- static bool lessThan(value_type a, value_type b) { return a < b; }
- static value_type uniqueValue(const_iterator a) { return *a; }
- template <typename It>
- static bool valueCompare(It it, const_iterator it2)
+ using Equal = struct
{
- return *it != *it2;
- }
-};
-}
-
-template <typename Range>
-typename Range::const_iterator cmRemoveDuplicates(Range& r)
-{
- typedef typename ContainerAlgorithms::RemoveDuplicatesAPI<Range> API;
- typedef typename API::value_type T;
- std::vector<T> unique;
- unique.reserve(r.size());
- std::vector<size_t> indices;
- size_t count = 0;
- const typename Range::const_iterator end = r.end();
- for (typename Range::const_iterator it = r.begin(); it != end;
- ++it, ++count) {
- const typename std::vector<T>::iterator low = std::lower_bound(
- unique.begin(), unique.end(), API::uniqueValue(it), API::lessThan);
- if (low == unique.end() || API::valueCompare(low, it)) {
- unique.insert(low, API::uniqueValue(it));
- } else {
- indices.push_back(count);
+ bool operator()(ForwardIterator it1, ForwardIterator it2) const
+ {
+ return *it1 == *it2;
}
+ };
+ std::unordered_set<ForwardIterator, Hash, Equal> uniq;
+
+ ForwardIterator result = first;
+ while (first != last) {
+ if (!cmContains(uniq, first)) {
+ if (result != first) {
+ *result = std::move(*first);
+ }
+ uniq.insert(result);
+ ++result;
+ }
+ ++first;
}
- if (indices.empty()) {
- return end;
- }
- return cmRemoveIndices(r, indices);
-}
-
-template <typename Range>
-std::string cmWrap(std::string const& prefix, Range const& r,
- std::string const& suffix, std::string const& sep)
-{
- if (r.empty()) {
- return std::string();
- }
- return prefix + cmJoin(r, suffix + sep + prefix) + suffix;
+ return result;
}
template <typename Range>
-std::string cmWrap(char prefix, Range const& r, char suffix,
- std::string const& sep)
+typename Range::const_iterator cmRemoveDuplicates(Range& r)
{
- return cmWrap(std::string(1, prefix), r, std::string(1, suffix), sep);
+ return cmRemoveDuplicates(r.begin(), r.end());
}
template <typename Range, typename T>
typename Range::const_iterator cmFindNot(Range const& r, T const& t)
{
- return std::find_if(r.begin(), r.end(),
- std::bind1st(std::not_equal_to<T>(), t));
-}
-
-template <typename Range>
-cmRange<typename Range::const_reverse_iterator> cmReverseRange(
- Range const& range)
-{
- return cmRange<typename Range::const_reverse_iterator>(range.rbegin(),
- range.rend());
-}
-
-template <class Iter>
-std::reverse_iterator<Iter> cmMakeReverseIterator(Iter it)
-{
- return std::reverse_iterator<Iter>(it);
-}
-
-inline bool cmHasSuffix(const std::string& str, const std::string& suffix)
-{
- if (str.size() < suffix.size()) {
- return false;
- }
- return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
-}
-
-inline void cmStripSuffixIfExists(std::string& str, const std::string& suffix)
-{
- if (cmHasSuffix(str, suffix)) {
- str.resize(str.size() - suffix.size());
- }
+ return std::find_if(r.begin(), r.end(), [&t](T const& i) { return i != t; });
}
#endif
diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx
index 0f13b114f..e5eea795d 100644
--- a/Source/cmArchiveWrite.cxx
+++ b/Source/cmArchiveWrite.cxx
@@ -2,19 +2,24 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmArchiveWrite.h"
-#include "cmLocale.h"
-#include "cmSystemTools.h"
-#include "cm_get_date.h"
-#include "cm_libarchive.h"
+#include <cstring>
+#include <ctime>
+#include <iostream>
+#include <sstream>
+
#include "cmsys/Directory.hxx"
#include "cmsys/Encoding.hxx"
#include "cmsys/FStream.hxx"
-#include <iostream>
-#include <string.h>
-#include <time.h>
+
+#include "cm_get_date.h"
+#include "cm_libarchive.h"
+
+#include "cmLocale.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
#ifndef __LA_SSIZE_T
-#define __LA_SSIZE_T la_ssize_t
+# define __LA_SSIZE_T la_ssize_t
#endif
static std::string cm_archive_error_string(struct archive* a)
@@ -53,6 +58,8 @@ public:
{
}
~Entry() { archive_entry_free(this->Object); }
+ Entry(const Entry&) = delete;
+ Entry& operator=(const Entry&) = delete;
operator struct archive_entry*() { return this->Object; }
};
@@ -82,75 +89,94 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c,
switch (c) {
case CompressNone:
if (archive_write_add_filter_none(this->Archive) != ARCHIVE_OK) {
- this->Error = "archive_write_add_filter_none: ";
- this->Error += cm_archive_error_string(this->Archive);
+ this->Error = cmStrCat("archive_write_add_filter_none: ",
+ cm_archive_error_string(this->Archive));
return;
}
break;
case CompressCompress:
if (archive_write_add_filter_compress(this->Archive) != ARCHIVE_OK) {
- this->Error = "archive_write_add_filter_compress: ";
- this->Error += cm_archive_error_string(this->Archive);
+ this->Error = cmStrCat("archive_write_add_filter_compress: ",
+ cm_archive_error_string(this->Archive));
return;
}
break;
- case CompressGZip:
+ case CompressGZip: {
if (archive_write_add_filter_gzip(this->Archive) != ARCHIVE_OK) {
- this->Error = "archive_write_add_filter_gzip: ";
- this->Error += cm_archive_error_string(this->Archive);
+ this->Error = cmStrCat("archive_write_add_filter_gzip: ",
+ cm_archive_error_string(this->Archive));
return;
}
- break;
+ std::string source_date_epoch;
+ cmSystemTools::GetEnv("SOURCE_DATE_EPOCH", source_date_epoch);
+ if (!source_date_epoch.empty()) {
+ // We're not able to specify an arbitrary timestamp for gzip.
+ // The next best thing is to omit the timestamp entirely.
+ if (archive_write_set_filter_option(this->Archive, "gzip", "timestamp",
+ nullptr) != ARCHIVE_OK) {
+ this->Error = cmStrCat("archive_write_set_filter_option: ",
+ cm_archive_error_string(this->Archive));
+ return;
+ }
+ }
+ } break;
case CompressBZip2:
if (archive_write_add_filter_bzip2(this->Archive) != ARCHIVE_OK) {
- this->Error = "archive_write_add_filter_bzip2: ";
- this->Error += cm_archive_error_string(this->Archive);
+ this->Error = cmStrCat("archive_write_add_filter_bzip2: ",
+ cm_archive_error_string(this->Archive));
return;
}
break;
case CompressLZMA:
if (archive_write_add_filter_lzma(this->Archive) != ARCHIVE_OK) {
- this->Error = "archive_write_add_filter_lzma: ";
- this->Error += cm_archive_error_string(this->Archive);
+ this->Error = cmStrCat("archive_write_add_filter_lzma: ",
+ cm_archive_error_string(this->Archive));
return;
}
break;
case CompressXZ:
if (archive_write_add_filter_xz(this->Archive) != ARCHIVE_OK) {
- this->Error = "archive_write_add_filter_xz: ";
- this->Error += cm_archive_error_string(this->Archive);
+ this->Error = cmStrCat("archive_write_add_filter_xz: ",
+ cm_archive_error_string(this->Archive));
return;
}
break;
- };
+ case CompressZstd:
+ if (archive_write_add_filter_zstd(this->Archive) != ARCHIVE_OK) {
+ this->Error = cmStrCat("archive_write_add_filter_zstd: ",
+ cm_archive_error_string(this->Archive));
+ return;
+ }
+ break;
+ }
#if !defined(_WIN32) || defined(__CYGWIN__)
if (archive_read_disk_set_standard_lookup(this->Disk) != ARCHIVE_OK) {
- this->Error = "archive_read_disk_set_standard_lookup: ";
- this->Error += cm_archive_error_string(this->Archive);
+ this->Error = cmStrCat("archive_read_disk_set_standard_lookup: ",
+ cm_archive_error_string(this->Archive));
return;
}
#endif
if (archive_write_set_format_by_name(this->Archive, format.c_str()) !=
ARCHIVE_OK) {
- this->Error = "archive_write_set_format_by_name: ";
- this->Error += cm_archive_error_string(this->Archive);
+ this->Error = cmStrCat("archive_write_set_format_by_name: ",
+ cm_archive_error_string(this->Archive));
return;
}
// do not pad the last block!!
if (archive_write_set_bytes_in_last_block(this->Archive, 1)) {
- this->Error = "archive_write_set_bytes_in_last_block: ";
- this->Error += cm_archive_error_string(this->Archive);
+ this->Error = cmStrCat("archive_write_set_bytes_in_last_block: ",
+ cm_archive_error_string(this->Archive));
return;
}
if (archive_write_open(
- this->Archive, this, CM_NULLPTR,
+ this->Archive, this, nullptr,
reinterpret_cast<archive_write_callback*>(&Callback::Write),
- CM_NULLPTR) != ARCHIVE_OK) {
- this->Error = "archive_write_open: ";
- this->Error += cm_archive_error_string(this->Archive);
+ nullptr) != ARCHIVE_OK) {
+ this->Error =
+ cmStrCat("archive_write_open: ", cm_archive_error_string(this->Archive));
return;
}
}
@@ -164,12 +190,10 @@ cmArchiveWrite::~cmArchiveWrite()
bool cmArchiveWrite::Add(std::string path, size_t skip, const char* prefix,
bool recursive)
{
- if (this->Okay()) {
- if (!path.empty() && path[path.size() - 1] == '/') {
- path.erase(path.size() - 1);
- }
- this->AddPath(path.c_str(), skip, prefix, recursive);
+ if (!path.empty() && path.back() == '/') {
+ path.erase(path.size() - 1);
}
+ this->AddPath(path.c_str(), skip, prefix, recursive);
return this->Okay();
}
@@ -185,8 +209,7 @@ bool cmArchiveWrite::AddPath(const char* path, size_t skip, const char* prefix,
}
cmsys::Directory d;
if (d.Load(path)) {
- std::string next = path;
- next += "/";
+ std::string next = cmStrCat(path, '/');
std::string::size_type end = next.size();
unsigned long n = d.GetNumberOfFiles();
for (unsigned long i = 0; i < n; ++i) {
@@ -205,6 +228,7 @@ bool cmArchiveWrite::AddPath(const char* path, size_t skip, const char* prefix,
bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix)
{
+ this->Error = "";
// Skip the file if we have no name for it. This may happen on a
// top-level directory, which does not need to be included anyway.
if (skip >= strlen(file)) {
@@ -216,20 +240,17 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix)
static_cast<void>(localeRAII);
// Meta-data.
- std::string dest = prefix ? prefix : "";
- dest += out;
+ std::string dest = cmStrCat(prefix ? prefix : "", out);
if (this->Verbose) {
std::cout << dest << "\n";
}
Entry e;
cm_archive_entry_copy_sourcepath(e, file);
cm_archive_entry_copy_pathname(e, dest);
- if (archive_read_disk_entry_from_file(this->Disk, e, -1, CM_NULLPTR) !=
+ if (archive_read_disk_entry_from_file(this->Disk, e, -1, nullptr) !=
ARCHIVE_OK) {
- this->Error = "archive_read_disk_entry_from_file '";
- this->Error += file;
- this->Error += "': ";
- this->Error += cm_archive_error_string(this->Disk);
+ this->Error = cmStrCat("Unable to read from file '", file,
+ "': ", cm_archive_error_string(this->Disk));
return false;
}
if (!this->MTime.empty()) {
@@ -237,12 +258,21 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix)
time(&now);
time_t t = cm_get_date(now, this->MTime.c_str());
if (t == -1) {
- this->Error = "unable to parse mtime '";
- this->Error += this->MTime;
- this->Error += "'";
+ this->Error = cmStrCat("unable to parse mtime '", this->MTime, '\'');
return false;
}
archive_entry_set_mtime(e, t, 0);
+ } else {
+ std::string source_date_epoch;
+ cmSystemTools::GetEnv("SOURCE_DATE_EPOCH", source_date_epoch);
+ if (!source_date_epoch.empty()) {
+ std::istringstream iss(source_date_epoch);
+ time_t epochTime;
+ iss >> epochTime;
+ if (iss.eof() && !iss.fail()) {
+ archive_entry_set_mtime(e, epochTime, 0);
+ }
+ }
}
// manages the uid/guid of the entry (if any)
@@ -278,8 +308,8 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix)
}
if (archive_write_header(this->Archive, e) != ARCHIVE_OK) {
- this->Error = "archive_write_header: ";
- this->Error += cm_archive_error_string(this->Archive);
+ this->Error = cmStrCat("archive_write_header: ",
+ cm_archive_error_string(this->Archive));
return false;
}
@@ -297,17 +327,15 @@ bool cmArchiveWrite::AddData(const char* file, size_t size)
{
cmsys::ifstream fin(file, std::ios::in | std::ios::binary);
if (!fin) {
- this->Error = "Error opening \"";
- this->Error += file;
- this->Error += "\": ";
- this->Error += cmSystemTools::GetLastSystemError();
+ this->Error = cmStrCat("Error opening \"", file,
+ "\": ", cmSystemTools::GetLastSystemError());
return false;
}
char buffer[16384];
size_t nleft = size;
while (nleft > 0) {
- typedef std::streamsize ssize_type;
+ using ssize_type = std::streamsize;
size_t const nnext = nleft > sizeof(buffer) ? sizeof(buffer) : nleft;
ssize_type const nnext_s = static_cast<ssize_type>(nnext);
fin.read(buffer, nnext_s);
@@ -318,17 +346,15 @@ bool cmArchiveWrite::AddData(const char* file, size_t size)
break;
}
if (archive_write_data(this->Archive, buffer, nnext) != nnext_s) {
- this->Error = "archive_write_data: ";
- this->Error += cm_archive_error_string(this->Archive);
+ this->Error = cmStrCat("archive_write_data: ",
+ cm_archive_error_string(this->Archive));
return false;
}
nleft -= nnext;
}
if (nleft > 0) {
- this->Error = "Error reading \"";
- this->Error += file;
- this->Error += "\": ";
- this->Error += cmSystemTools::GetLastSystemError();
+ this->Error = cmStrCat("Error reading \"", file,
+ "\": ", cmSystemTools::GetLastSystemError());
return false;
}
return true;
diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h
index 4c85c0d16..e791761cb 100644
--- a/Source/cmArchiveWrite.h
+++ b/Source/cmArchiveWrite.h
@@ -5,12 +5,12 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <iosfwd>
-#include <stddef.h>
#include <string>
-#if !defined(CMAKE_BUILD_WITH_CMAKE)
-#error "cmArchiveWrite not allowed during bootstrap build!"
+#if defined(CMAKE_BOOTSTRAP)
+# error "cmArchiveWrite not allowed during bootstrap build!"
#endif
template <typename T>
@@ -28,6 +28,7 @@ public:
void Clear() { this->IsValueSet = false; }
bool IsSet() const { return this->IsValueSet; }
T Get() const { return Value; }
+
private:
T Value;
bool IsValueSet;
@@ -39,8 +40,6 @@ private:
*/
class cmArchiveWrite
{
- typedef void (cmArchiveWrite::*safe_bool)();
- void safe_bool_true() {}
public:
/** Compression type. */
enum Compress
@@ -50,7 +49,8 @@ public:
CompressGZip,
CompressBZip2,
CompressLZMA,
- CompressXZ
+ CompressXZ,
+ CompressZstd
};
/** Construct with output stream to which to write archive. */
@@ -59,6 +59,9 @@ public:
~cmArchiveWrite();
+ cmArchiveWrite(const cmArchiveWrite&) = delete;
+ cmArchiveWrite& operator=(const cmArchiveWrite&) = delete;
+
/**
* Add a path (file or directory) to the archive. Directories are
* added recursively. The "path" must be readable on disk, either
@@ -67,14 +70,11 @@ public:
* skip. The remaining part of the input path is appended to the
* "prefix" value to construct the final name in the archive.
*/
- bool Add(std::string path, size_t skip = 0, const char* prefix = CM_NULLPTR,
+ bool Add(std::string path, size_t skip = 0, const char* prefix = nullptr,
bool recursive = true);
/** Returns true if there has been no error. */
- operator safe_bool() const
- {
- return this->Okay() ? &cmArchiveWrite::safe_bool_true : CM_NULLPTR;
- }
+ explicit operator bool() const { return this->Okay(); }
/** Returns true if there has been an error. */
bool operator!() const { return !this->Okay(); }
diff --git a/Source/cmArgumentParser.cxx b/Source/cmArgumentParser.cxx
new file mode 100644
index 000000000..4c8717749
--- /dev/null
+++ b/Source/cmArgumentParser.cxx
@@ -0,0 +1,97 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmArgumentParser.h"
+
+#include <algorithm>
+#include <type_traits>
+
+namespace ArgumentParser {
+
+auto ActionMap::Emplace(cm::string_view name, Action action)
+ -> std::pair<iterator, bool>
+{
+ auto const it =
+ std::lower_bound(this->begin(), this->end(), name,
+ [](value_type const& elem, cm::string_view const& k) {
+ return elem.first < k;
+ });
+ return (it != this->end() && it->first == name)
+ ? std::make_pair(it, false)
+ : std::make_pair(this->emplace(it, name, std::move(action)), true);
+}
+
+auto ActionMap::Find(cm::string_view name) const -> const_iterator
+{
+ auto const it =
+ std::lower_bound(this->begin(), this->end(), name,
+ [](value_type const& elem, cm::string_view const& k) {
+ return elem.first < k;
+ });
+ return (it != this->end() && it->first == name) ? it : this->end();
+}
+
+void Instance::Bind(bool& val)
+{
+ val = true;
+ this->CurrentString = nullptr;
+ this->CurrentList = nullptr;
+ this->ExpectValue = false;
+}
+
+void Instance::Bind(std::string& val)
+{
+ this->CurrentString = &val;
+ this->CurrentList = nullptr;
+ this->ExpectValue = true;
+}
+
+void Instance::Bind(StringList& val)
+{
+ this->CurrentString = nullptr;
+ this->CurrentList = &val;
+ this->ExpectValue = true;
+}
+
+void Instance::Bind(MultiStringList& val)
+{
+ this->CurrentString = nullptr;
+ this->CurrentList = (static_cast<void>(val.emplace_back()), &val.back());
+ this->ExpectValue = false;
+}
+
+void Instance::Consume(cm::string_view arg, void* result,
+ std::vector<std::string>* unparsedArguments,
+ std::vector<std::string>* keywordsMissingValue,
+ std::vector<std::string>* parsedKeywords)
+{
+ auto const it = this->Bindings.Find(arg);
+ if (it != this->Bindings.end()) {
+ if (parsedKeywords != nullptr) {
+ parsedKeywords->emplace_back(arg);
+ }
+ it->second(*this, result);
+ if (this->ExpectValue && keywordsMissingValue != nullptr) {
+ keywordsMissingValue->emplace_back(arg);
+ }
+ return;
+ }
+
+ if (this->CurrentString != nullptr) {
+ this->CurrentString->assign(std::string(arg));
+ this->CurrentString = nullptr;
+ this->CurrentList = nullptr;
+ } else if (this->CurrentList != nullptr) {
+ this->CurrentList->emplace_back(arg);
+ } else if (unparsedArguments != nullptr) {
+ unparsedArguments->emplace_back(arg);
+ }
+
+ if (this->ExpectValue) {
+ if (keywordsMissingValue != nullptr) {
+ keywordsMissingValue->pop_back();
+ }
+ this->ExpectValue = false;
+ }
+}
+
+} // namespace ArgumentParser
diff --git a/Source/cmArgumentParser.h b/Source/cmArgumentParser.h
new file mode 100644
index 000000000..94265372a
--- /dev/null
+++ b/Source/cmArgumentParser.h
@@ -0,0 +1,151 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmArgumentParser_h
+#define cmArgumentParser_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cassert>
+#include <functional>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm/string_view>
+
+#include "cm_static_string_view.hxx"
+
+namespace ArgumentParser {
+
+using StringList = std::vector<std::string>;
+using MultiStringList = std::vector<StringList>;
+
+class Instance;
+using Action = std::function<void(Instance&, void*)>;
+
+// using ActionMap = cm::flat_map<cm::string_view, Action>;
+class ActionMap : public std::vector<std::pair<cm::string_view, Action>>
+{
+public:
+ std::pair<iterator, bool> Emplace(cm::string_view name, Action action);
+ const_iterator Find(cm::string_view name) const;
+};
+
+class Instance
+{
+public:
+ Instance(ActionMap const& bindings)
+ : Bindings(bindings)
+ {
+ }
+
+ void Bind(bool& val);
+ void Bind(std::string& val);
+ void Bind(StringList& val);
+ void Bind(MultiStringList& val);
+
+ void Consume(cm::string_view arg, void* result,
+ std::vector<std::string>* unparsedArguments,
+ std::vector<std::string>* keywordsMissingValue,
+ std::vector<std::string>* parsedKeywords);
+
+private:
+ ActionMap const& Bindings;
+ std::string* CurrentString = nullptr;
+ StringList* CurrentList = nullptr;
+ bool ExpectValue = false;
+};
+
+} // namespace ArgumentParser
+
+template <typename Result>
+class cmArgumentParser
+{
+public:
+ // I *think* this function could be made `constexpr` when the code is
+ // compiled as C++20. This would allow building a parser at compile time.
+ template <typename T>
+ cmArgumentParser& Bind(cm::static_string_view name, T Result::*member)
+ {
+ bool const inserted =
+ this->Bindings
+ .Emplace(name,
+ [member](ArgumentParser::Instance& instance, void* result) {
+ instance.Bind(static_cast<Result*>(result)->*member);
+ })
+ .second;
+ assert(inserted), (void)inserted;
+ return *this;
+ }
+
+ template <typename Range>
+ void Parse(Result& result, Range const& args,
+ std::vector<std::string>* unparsedArguments = nullptr,
+ std::vector<std::string>* keywordsMissingValue = nullptr,
+ std::vector<std::string>* parsedKeywords = nullptr) const
+ {
+ ArgumentParser::Instance instance(this->Bindings);
+ for (cm::string_view arg : args) {
+ instance.Consume(arg, &result, unparsedArguments, keywordsMissingValue,
+ parsedKeywords);
+ }
+ }
+
+ template <typename Range>
+ Result Parse(Range const& args,
+ std::vector<std::string>* unparsedArguments = nullptr,
+ std::vector<std::string>* keywordsMissingValue = nullptr,
+ std::vector<std::string>* parsedKeywords = nullptr) const
+ {
+ Result result;
+ this->Parse(result, args, unparsedArguments, keywordsMissingValue,
+ parsedKeywords);
+ return result;
+ }
+
+private:
+ ArgumentParser::ActionMap Bindings;
+};
+
+template <>
+class cmArgumentParser<void>
+{
+public:
+ template <typename T>
+ cmArgumentParser& Bind(cm::static_string_view name, T& ref)
+ {
+ bool const inserted = this->Bind(cm::string_view(name), ref);
+ assert(inserted), (void)inserted;
+ return *this;
+ }
+
+ template <typename Range>
+ void Parse(Range const& args,
+ std::vector<std::string>* unparsedArguments = nullptr,
+ std::vector<std::string>* keywordsMissingValue = nullptr,
+ std::vector<std::string>* parsedKeywords = nullptr) const
+ {
+ ArgumentParser::Instance instance(this->Bindings);
+ for (cm::string_view arg : args) {
+ instance.Consume(arg, nullptr, unparsedArguments, keywordsMissingValue,
+ parsedKeywords);
+ }
+ }
+
+protected:
+ template <typename T>
+ bool Bind(cm::string_view name, T& ref)
+ {
+ return this->Bindings
+ .Emplace(name,
+ [&ref](ArgumentParser::Instance& instance, void*) {
+ instance.Bind(ref);
+ })
+ .second;
+ }
+
+private:
+ ArgumentParser::ActionMap Bindings;
+};
+
+#endif
diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx
index 847a41660..289bb7217 100644
--- a/Source/cmAuxSourceDirectoryCommand.cxx
+++ b/Source/cmAuxSourceDirectoryCommand.cxx
@@ -2,40 +2,39 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmAuxSourceDirectoryCommand.h"
-#include "cmsys/Directory.hxx"
#include <algorithm>
-#include <stddef.h>
+#include <cstddef>
+#include <utility>
+
+#include "cmsys/Directory.hxx"
-#include "cmAlgorithms.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
-class cmExecutionStatus;
-
-// cmAuxSourceDirectoryCommand
-bool cmAuxSourceDirectoryCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmAuxSourceDirectoryCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() != 2) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
+ cmMakefile& mf = status.GetMakefile();
std::string sourceListValue;
std::string const& templateDirectory = args[0];
std::string tdir;
- if (!cmSystemTools::FileIsFullPath(templateDirectory.c_str())) {
- tdir = this->Makefile->GetCurrentSourceDirectory();
- tdir += "/";
- tdir += templateDirectory;
+ if (!cmSystemTools::FileIsFullPath(templateDirectory)) {
+ tdir = cmStrCat(mf.GetCurrentSourceDirectory(), '/', templateDirectory);
} else {
tdir = templateDirectory;
}
// was the list already populated
- const char* def = this->Makefile->GetDefinition(args[1]);
+ const char* def = mf.GetDefinition(args[1]);
if (def) {
sourceListValue = def;
}
@@ -54,18 +53,14 @@ 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()) {
- std::string fullname = templateDirectory;
- fullname += "/";
- fullname += file;
+ auto cm = mf.GetCMakeInstance();
+ if (!base.empty() && cm->IsSourceExtension(ext)) {
+ std::string fullname = cmStrCat(templateDirectory, '/', file);
// add the file as a class file so
// depends can be done
- cmSourceFile* sf = this->Makefile->GetOrCreateSource(fullname);
+ cmSourceFile* sf = mf.GetOrCreateSource(fullname);
sf->SetProperty("ABSTRACT", "0");
- files.push_back(fullname);
+ files.push_back(std::move(fullname));
}
}
}
@@ -75,6 +70,6 @@ bool cmAuxSourceDirectoryCommand::InitialPass(
sourceListValue += ";";
}
sourceListValue += cmJoin(files, ";");
- this->Makefile->AddDefinition(args[1], sourceListValue.c_str());
+ mf.AddDefinition(args[1], sourceListValue);
return true;
}
diff --git a/Source/cmAuxSourceDirectoryCommand.h b/Source/cmAuxSourceDirectoryCommand.h
index e49e86117..ae2609205 100644
--- a/Source/cmAuxSourceDirectoryCommand.h
+++ b/Source/cmAuxSourceDirectoryCommand.h
@@ -3,38 +3,14 @@
#ifndef cmAuxSourceDirectoryCommand_h
#define cmAuxSourceDirectoryCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmAuxSourceDirectoryCommand
- * \brief Specify auxiliary source code directories.
- *
- * cmAuxSourceDirectoryCommand specifies source code directories
- * that must be built as part of this build process. This directories
- * are not recursively processed like the SUBDIR command (cmSubdirCommand).
- * A side effect of this command is to create a subdirectory in the build
- * directory structure.
- */
-class cmAuxSourceDirectoryCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmAuxSourceDirectoryCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmAuxSourceDirectoryCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmBase32.cxx b/Source/cmBase32.cxx
index 1dac212c2..80ada4766 100644
--- a/Source/cmBase32.cxx
+++ b/Source/cmBase32.cxx
@@ -34,13 +34,9 @@ void Base32Encode5(const unsigned char src[5], char dst[8])
// -- Class methods
-cmBase32Encoder::cmBase32Encoder()
-{
-}
+cmBase32Encoder::cmBase32Encoder() = default;
-cmBase32Encoder::~cmBase32Encoder()
-{
-}
+cmBase32Encoder::~cmBase32Encoder() = default;
std::string cmBase32Encoder::encodeString(const unsigned char* input,
size_t len, bool padding)
diff --git a/Source/cmBase32.h b/Source/cmBase32.h
index c6758d4f3..d85198dd5 100644
--- a/Source/cmBase32.h
+++ b/Source/cmBase32.h
@@ -5,7 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include <stddef.h>
+#include <cstddef>
#include <string>
/** \class cmBase32Encoder
diff --git a/Source/cmBinUtilsLinker.cxx b/Source/cmBinUtilsLinker.cxx
new file mode 100644
index 000000000..a9f4d91fc
--- /dev/null
+++ b/Source/cmBinUtilsLinker.cxx
@@ -0,0 +1,16 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmBinUtilsLinker.h"
+
+#include "cmRuntimeDependencyArchive.h"
+
+cmBinUtilsLinker::cmBinUtilsLinker(cmRuntimeDependencyArchive* archive)
+ : Archive(archive)
+{
+}
+
+void cmBinUtilsLinker::SetError(const std::string& e)
+{
+ this->Archive->SetError(e);
+}
diff --git a/Source/cmBinUtilsLinker.h b/Source/cmBinUtilsLinker.h
new file mode 100644
index 000000000..78d517b61
--- /dev/null
+++ b/Source/cmBinUtilsLinker.h
@@ -0,0 +1,30 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmBinUtilsLinker_h
+#define cmBinUtilsLinker_h
+
+#include <string>
+
+#include "cmStateTypes.h"
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsLinker
+{
+public:
+ cmBinUtilsLinker(cmRuntimeDependencyArchive* archive);
+ virtual ~cmBinUtilsLinker() = default;
+
+ virtual bool Prepare() { return true; }
+
+ virtual bool ScanDependencies(std::string const& file,
+ cmStateEnums::TargetType type) = 0;
+
+protected:
+ cmRuntimeDependencyArchive* Archive;
+
+ void SetError(const std::string& e);
+};
+
+#endif // cmBinUtilsLinker_h
diff --git a/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.cxx
new file mode 100644
index 000000000..abd12092c
--- /dev/null
+++ b/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.cxx
@@ -0,0 +1,19 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h"
+
+#include "cmRuntimeDependencyArchive.h"
+
+cmBinUtilsLinuxELFGetRuntimeDependenciesTool::
+ cmBinUtilsLinuxELFGetRuntimeDependenciesTool(
+ cmRuntimeDependencyArchive* archive)
+ : Archive(archive)
+{
+}
+
+void cmBinUtilsLinuxELFGetRuntimeDependenciesTool::SetError(
+ const std::string& error)
+{
+ this->Archive->SetError(error);
+}
diff --git a/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h b/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h
new file mode 100644
index 000000000..d514e7f91
--- /dev/null
+++ b/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h
@@ -0,0 +1,30 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmBinUtilsLinuxELFGetRuntimeDependenciesTool_h
+#define cmBinUtilsLinuxELFGetRuntimeDependenciesTool_h
+
+#include <string>
+#include <vector>
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsLinuxELFGetRuntimeDependenciesTool
+{
+public:
+ cmBinUtilsLinuxELFGetRuntimeDependenciesTool(
+ cmRuntimeDependencyArchive* archive);
+ virtual ~cmBinUtilsLinuxELFGetRuntimeDependenciesTool() = default;
+
+ virtual bool GetFileInfo(std::string const& file,
+ std::vector<std::string>& needed,
+ std::vector<std::string>& rpaths,
+ std::vector<std::string>& runpaths) = 0;
+
+protected:
+ cmRuntimeDependencyArchive* Archive;
+
+ void SetError(const std::string& e);
+};
+
+#endif // cmBinUtilsLinuxELFGetRuntimeDependenciesTool_h
diff --git a/Source/cmBinUtilsLinuxELFLinker.cxx b/Source/cmBinUtilsLinuxELFLinker.cxx
new file mode 100644
index 000000000..0dea8256c
--- /dev/null
+++ b/Source/cmBinUtilsLinuxELFLinker.cxx
@@ -0,0 +1,179 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmBinUtilsLinuxELFLinker.h"
+
+#include <sstream>
+
+#include <cm/memory>
+
+#include <cmsys/RegularExpression.hxx>
+
+#include "cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h"
+#include "cmLDConfigLDConfigTool.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmRuntimeDependencyArchive.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+static std::string ReplaceOrigin(const std::string& rpath,
+ const std::string& origin)
+{
+ static const cmsys::RegularExpression originRegex(
+ "(\\$ORIGIN)([^a-zA-Z0-9_]|$)");
+ static const cmsys::RegularExpression originCurlyRegex("\\${ORIGIN}");
+
+ cmsys::RegularExpressionMatch match;
+ if (originRegex.find(rpath.c_str(), match)) {
+ std::string begin = rpath.substr(0, match.start(1));
+ std::string end = rpath.substr(match.end(1));
+ return begin + origin + end;
+ }
+ if (originCurlyRegex.find(rpath.c_str(), match)) {
+ std::string begin = rpath.substr(0, match.start());
+ std::string end = rpath.substr(match.end());
+ return begin + origin + end;
+ }
+ return rpath;
+}
+
+cmBinUtilsLinuxELFLinker::cmBinUtilsLinuxELFLinker(
+ cmRuntimeDependencyArchive* archive)
+ : cmBinUtilsLinker(archive)
+{
+}
+
+bool cmBinUtilsLinuxELFLinker::Prepare()
+{
+ std::string tool = this->Archive->GetGetRuntimeDependenciesTool();
+ if (tool.empty()) {
+ tool = "objdump";
+ }
+ if (tool == "objdump") {
+ this->Tool =
+ cm::make_unique<cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool>(
+ this->Archive);
+ } else {
+ std::ostringstream e;
+ e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL: " << tool;
+ this->SetError(e.str());
+ return false;
+ }
+
+ std::string ldConfigTool =
+ this->Archive->GetMakefile()->GetSafeDefinition("CMAKE_LDCONFIG_TOOL");
+ if (ldConfigTool.empty()) {
+ ldConfigTool = "ldconfig";
+ }
+ if (ldConfigTool == "ldconfig") {
+ this->LDConfigTool =
+ cm::make_unique<cmLDConfigLDConfigTool>(this->Archive);
+ } else {
+ std::ostringstream e;
+ e << "Invalid value for CMAKE_LDCONFIG_TOOL: " << ldConfigTool;
+ this->SetError(e.str());
+ return false;
+ }
+
+ return true;
+}
+
+bool cmBinUtilsLinuxELFLinker::ScanDependencies(
+ std::string const& file, cmStateEnums::TargetType /* unused */)
+{
+ std::vector<std::string> parentRpaths;
+ return this->ScanDependencies(file, parentRpaths);
+}
+
+bool cmBinUtilsLinuxELFLinker::ScanDependencies(
+ std::string const& file, std::vector<std::string> const& parentRpaths)
+{
+ std::string origin = cmSystemTools::GetFilenamePath(file);
+ std::vector<std::string> needed;
+ std::vector<std::string> rpaths;
+ std::vector<std::string> runpaths;
+ if (!this->Tool->GetFileInfo(file, needed, rpaths, runpaths)) {
+ return false;
+ }
+ for (auto& runpath : runpaths) {
+ runpath = ReplaceOrigin(runpath, origin);
+ }
+ for (auto& rpath : rpaths) {
+ rpath = ReplaceOrigin(rpath, origin);
+ }
+
+ std::vector<std::string> searchPaths;
+ if (!runpaths.empty()) {
+ searchPaths = runpaths;
+ } else {
+ searchPaths = rpaths;
+ searchPaths.insert(searchPaths.end(), parentRpaths.begin(),
+ parentRpaths.end());
+ }
+
+ std::vector<std::string> ldConfigPaths;
+ if (!this->LDConfigTool->GetLDConfigPaths(ldConfigPaths)) {
+ return false;
+ }
+ searchPaths.insert(searchPaths.end(), ldConfigPaths.begin(),
+ ldConfigPaths.end());
+
+ for (auto const& dep : needed) {
+ if (!this->Archive->IsPreExcluded(dep)) {
+ std::string path;
+ bool resolved = false;
+ if (dep.find('/') != std::string::npos) {
+ this->SetError("Paths to dependencies are not supported");
+ return false;
+ }
+ if (!this->ResolveDependency(dep, searchPaths, path, resolved)) {
+ return false;
+ }
+ if (resolved) {
+ if (!this->Archive->IsPostExcluded(path)) {
+ bool unique;
+ this->Archive->AddResolvedPath(dep, path, unique);
+ if (unique && !this->ScanDependencies(path, rpaths)) {
+ return false;
+ }
+ }
+ } else {
+ this->Archive->AddUnresolvedPath(dep);
+ }
+ }
+ }
+
+ return true;
+}
+
+bool cmBinUtilsLinuxELFLinker::ResolveDependency(
+ std::string const& name, std::vector<std::string> const& searchPaths,
+ std::string& path, bool& resolved)
+{
+ for (auto const& searchPath : searchPaths) {
+ path = cmStrCat(searchPath, '/', name);
+ if (cmSystemTools::PathExists(path)) {
+ resolved = true;
+ return true;
+ }
+ }
+
+ for (auto const& searchPath : this->Archive->GetSearchDirectories()) {
+ path = cmStrCat(searchPath, '/', name);
+ if (cmSystemTools::PathExists(path)) {
+ std::ostringstream warning;
+ warning << "Dependency " << name << " found in search directory:\n "
+ << searchPath
+ << "\nSee file(GET_RUNTIME_DEPENDENCIES) documentation for "
+ << "more information.";
+ this->Archive->GetMakefile()->IssueMessage(MessageType::WARNING,
+ warning.str());
+ resolved = true;
+ return true;
+ }
+ }
+
+ resolved = false;
+ return true;
+}
diff --git a/Source/cmBinUtilsLinuxELFLinker.h b/Source/cmBinUtilsLinuxELFLinker.h
new file mode 100644
index 000000000..b17df11ee
--- /dev/null
+++ b/Source/cmBinUtilsLinuxELFLinker.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. */
+
+#ifndef cmBinUtilsLinuxELFLinker_h
+#define cmBinUtilsLinuxELFLinker_h
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "cmBinUtilsLinker.h"
+#include "cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h"
+#include "cmLDConfigTool.h"
+#include "cmStateTypes.h"
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsLinuxELFLinker : public cmBinUtilsLinker
+{
+public:
+ cmBinUtilsLinuxELFLinker(cmRuntimeDependencyArchive* archive);
+
+ bool Prepare() override;
+
+ bool ScanDependencies(std::string const& file,
+ cmStateEnums::TargetType type) override;
+
+private:
+ std::unique_ptr<cmBinUtilsLinuxELFGetRuntimeDependenciesTool> Tool;
+ std::unique_ptr<cmLDConfigTool> LDConfigTool;
+ bool HaveLDConfigPaths = false;
+ std::vector<std::string> LDConfigPaths;
+
+ bool ScanDependencies(std::string const& file,
+ std::vector<std::string> const& parentRpaths);
+
+ bool ResolveDependency(std::string const& name,
+ std::vector<std::string> const& searchPaths,
+ std::string& path, bool& resolved);
+
+ bool GetLDConfigPaths();
+};
+
+#endif // cmBinUtilsLinuxELFLinker_h
diff --git a/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx
new file mode 100644
index 000000000..566e4a488
--- /dev/null
+++ b/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx
@@ -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. */
+
+#include "cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h"
+
+#include <sstream>
+
+#include <cmsys/RegularExpression.hxx>
+
+#include "cmRuntimeDependencyArchive.h"
+#include "cmSystemTools.h"
+#include "cmUVProcessChain.h"
+
+cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool::
+ cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool(
+ cmRuntimeDependencyArchive* archive)
+ : cmBinUtilsLinuxELFGetRuntimeDependenciesTool(archive)
+{
+}
+
+bool cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool::GetFileInfo(
+ std::string const& file, std::vector<std::string>& needed,
+ std::vector<std::string>& rpaths, std::vector<std::string>& runpaths)
+{
+ cmUVProcessChainBuilder builder;
+ builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT);
+
+ std::vector<std::string> command;
+ if (!this->Archive->GetGetRuntimeDependenciesCommand("objdump", command)) {
+ this->SetError("Could not find objdump");
+ return false;
+ }
+ command.emplace_back("-p");
+ command.push_back(file);
+ builder.AddCommand(command);
+
+ auto process = builder.Start();
+ if (!process.Valid()) {
+ std::ostringstream e;
+ e << "Failed to start objdump process for:\n " << file;
+ this->SetError(e.str());
+ return false;
+ }
+
+ std::string line;
+ static const cmsys::RegularExpression neededRegex("^ *NEEDED *([^\n]*)$");
+ static const cmsys::RegularExpression rpathRegex("^ *RPATH *([^\n]*)$");
+ static const cmsys::RegularExpression runpathRegex("^ *RUNPATH *([^\n]*)$");
+ while (std::getline(*process.OutputStream(), line)) {
+ cmsys::RegularExpressionMatch match;
+ if (neededRegex.find(line.c_str(), match)) {
+ needed.push_back(match.match(1));
+ } else if (rpathRegex.find(line.c_str(), match)) {
+ std::vector<std::string> rpathSplit =
+ cmSystemTools::SplitString(match.match(1), ':');
+ rpaths.reserve(rpaths.size() + rpathSplit.size());
+ for (auto const& rpath : rpathSplit) {
+ rpaths.push_back(rpath);
+ }
+ } else if (runpathRegex.find(line.c_str(), match)) {
+ std::vector<std::string> runpathSplit =
+ cmSystemTools::SplitString(match.match(1), ':');
+ runpaths.reserve(runpaths.size() + runpathSplit.size());
+ for (auto const& runpath : runpathSplit) {
+ runpaths.push_back(runpath);
+ }
+ }
+ }
+
+ if (!process.Wait()) {
+ std::ostringstream e;
+ e << "Failed to wait on objdump process for:\n " << file;
+ this->SetError(e.str());
+ return false;
+ }
+ auto status = process.GetStatus();
+ if (!status[0] || status[0]->ExitStatus != 0) {
+ std::ostringstream e;
+ e << "Failed to run objdump on:\n " << file;
+ this->SetError(e.str());
+ return false;
+ }
+
+ return true;
+}
diff --git a/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h b/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h
new file mode 100644
index 000000000..969e4d4dc
--- /dev/null
+++ b/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h
@@ -0,0 +1,26 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmBinUtilsLinuxELFGetRuntimeCollectDependenciesTool_h
+#define cmBinUtilsLinuxELFGetRuntimeCollectDependenciesTool_h
+
+#include <string>
+#include <vector>
+
+#include "cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h"
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool
+ : public cmBinUtilsLinuxELFGetRuntimeDependenciesTool
+{
+public:
+ cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool(
+ cmRuntimeDependencyArchive* archive);
+
+ bool GetFileInfo(std::string const& file, std::vector<std::string>& needed,
+ std::vector<std::string>& rpaths,
+ std::vector<std::string>& runpaths) override;
+};
+
+#endif // cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool_h
diff --git a/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.cxx
new file mode 100644
index 000000000..a296a474c
--- /dev/null
+++ b/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.cxx
@@ -0,0 +1,19 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h"
+
+#include "cmRuntimeDependencyArchive.h"
+
+cmBinUtilsMacOSMachOGetRuntimeDependenciesTool::
+ cmBinUtilsMacOSMachOGetRuntimeDependenciesTool(
+ cmRuntimeDependencyArchive* archive)
+ : Archive(archive)
+{
+}
+
+void cmBinUtilsMacOSMachOGetRuntimeDependenciesTool::SetError(
+ const std::string& error)
+{
+ this->Archive->SetError(error);
+}
diff --git a/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h b/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h
new file mode 100644
index 000000000..dbb288255
--- /dev/null
+++ b/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h
@@ -0,0 +1,29 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmBinUtilsMacOSMachOGetRuntimeDependenciesTool_h
+#define cmBinUtilsMacOSMachOGetRuntimeDependenciesTool_h
+
+#include <string>
+#include <vector>
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsMacOSMachOGetRuntimeDependenciesTool
+{
+public:
+ cmBinUtilsMacOSMachOGetRuntimeDependenciesTool(
+ cmRuntimeDependencyArchive* archive);
+ virtual ~cmBinUtilsMacOSMachOGetRuntimeDependenciesTool() = default;
+
+ virtual bool GetFileInfo(std::string const& file,
+ std::vector<std::string>& libs,
+ std::vector<std::string>& rpaths) = 0;
+
+protected:
+ cmRuntimeDependencyArchive* Archive;
+
+ void SetError(const std::string& error);
+};
+
+#endif // cmBinUtilsMacOSMachOGetRuntimeDependenciesTool_h
diff --git a/Source/cmBinUtilsMacOSMachOLinker.cxx b/Source/cmBinUtilsMacOSMachOLinker.cxx
new file mode 100644
index 000000000..98250b1c0
--- /dev/null
+++ b/Source/cmBinUtilsMacOSMachOLinker.cxx
@@ -0,0 +1,231 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmBinUtilsMacOSMachOLinker.h"
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <cm/memory>
+
+#include "cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h"
+#include "cmRuntimeDependencyArchive.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+cmBinUtilsMacOSMachOLinker::cmBinUtilsMacOSMachOLinker(
+ cmRuntimeDependencyArchive* archive)
+ : cmBinUtilsLinker(archive)
+{
+}
+
+bool cmBinUtilsMacOSMachOLinker::Prepare()
+{
+ std::string tool = this->Archive->GetGetRuntimeDependenciesTool();
+ if (tool.empty()) {
+ tool = "otool";
+ }
+ if (tool == "otool") {
+ this->Tool =
+ cm::make_unique<cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool>(
+ this->Archive);
+ } else {
+ std::ostringstream e;
+ e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL: " << tool;
+ this->SetError(e.str());
+ return false;
+ }
+
+ return true;
+}
+
+bool cmBinUtilsMacOSMachOLinker::ScanDependencies(
+ std::string const& file, cmStateEnums::TargetType type)
+{
+ std::string executableFile;
+ if (type == cmStateEnums::EXECUTABLE) {
+ executableFile = file;
+ } else {
+ executableFile = this->Archive->GetBundleExecutable();
+ }
+ std::string executablePath;
+ if (!executableFile.empty()) {
+ executablePath = cmSystemTools::GetFilenamePath(executableFile);
+ }
+ return this->ScanDependencies(file, executablePath);
+}
+
+bool cmBinUtilsMacOSMachOLinker::ScanDependencies(
+ std::string const& file, std::string const& executablePath)
+{
+ std::vector<std::string> libs;
+ std::vector<std::string> rpaths;
+ if (!this->Tool->GetFileInfo(file, libs, rpaths)) {
+ return false;
+ }
+
+ std::string loaderPath = cmSystemTools::GetFilenamePath(file);
+ return this->GetFileDependencies(libs, executablePath, loaderPath, rpaths);
+}
+
+bool cmBinUtilsMacOSMachOLinker::GetFileDependencies(
+ std::vector<std::string> const& names, std::string const& executablePath,
+ std::string const& loaderPath, std::vector<std::string> const& rpaths)
+{
+ for (std::string const& name : names) {
+ if (!this->Archive->IsPreExcluded(name)) {
+ std::string path;
+ bool resolved;
+ if (!this->ResolveDependency(name, executablePath, loaderPath, rpaths,
+ path, resolved)) {
+ return false;
+ }
+ if (resolved) {
+ if (!this->Archive->IsPostExcluded(path)) {
+ auto filename = cmSystemTools::GetFilenameName(path);
+ bool unique;
+ this->Archive->AddResolvedPath(filename, path, unique);
+ if (unique && !this->ScanDependencies(path, executablePath)) {
+ return false;
+ }
+ }
+ } else {
+ this->Archive->AddUnresolvedPath(name);
+ }
+ }
+ }
+
+ return true;
+}
+
+bool cmBinUtilsMacOSMachOLinker::ResolveDependency(
+ std::string const& name, std::string const& executablePath,
+ std::string const& loaderPath, std::vector<std::string> const& rpaths,
+ std::string& path, bool& resolved)
+{
+ resolved = false;
+ if (cmHasLiteralPrefix(name, "@rpath/")) {
+ if (!this->ResolveRPathDependency(name, executablePath, loaderPath, rpaths,
+ path, resolved)) {
+ return false;
+ }
+ } else if (cmHasLiteralPrefix(name, "@loader_path/")) {
+ if (!this->ResolveLoaderPathDependency(name, loaderPath, path, resolved)) {
+ return false;
+ }
+ } else if (cmHasLiteralPrefix(name, "@executable_path/")) {
+ if (!this->ResolveExecutablePathDependency(name, executablePath, path,
+ resolved)) {
+ return false;
+ }
+ } else {
+ resolved = true;
+ path = name;
+ }
+
+ if (resolved && !cmSystemTools::FileIsFullPath(path)) {
+ this->SetError("Resolved path is not absolute");
+ return false;
+ }
+
+ return true;
+}
+
+bool cmBinUtilsMacOSMachOLinker::ResolveExecutablePathDependency(
+ std::string const& name, std::string const& executablePath,
+ std::string& path, bool& resolved)
+{
+ if (executablePath.empty()) {
+ resolved = false;
+ return true;
+ }
+
+ // 16 is == "@executable_path".length()
+ path = name;
+ path.replace(0, 16, executablePath);
+
+ if (!cmSystemTools::PathExists(path)) {
+ resolved = false;
+ return true;
+ }
+
+ resolved = true;
+ return true;
+}
+
+bool cmBinUtilsMacOSMachOLinker::ResolveLoaderPathDependency(
+ std::string const& name, std::string const& loaderPath, std::string& path,
+ bool& resolved)
+{
+ if (loaderPath.empty()) {
+ resolved = false;
+ return true;
+ }
+
+ // 12 is "@loader_path".length();
+ path = name;
+ path.replace(0, 12, loaderPath);
+
+ if (!cmSystemTools::PathExists(path)) {
+ resolved = false;
+ return true;
+ }
+
+ resolved = true;
+ return true;
+}
+
+bool cmBinUtilsMacOSMachOLinker::ResolveRPathDependency(
+ std::string const& name, std::string const& executablePath,
+ std::string const& loaderPath, std::vector<std::string> const& rpaths,
+ std::string& path, bool& resolved)
+{
+ for (std::string const& rpath : rpaths) {
+ std::string searchFile = name;
+ searchFile.replace(0, 6, rpath);
+ if (cmHasLiteralPrefix(searchFile, "@loader_path/")) {
+ if (!this->ResolveLoaderPathDependency(searchFile, loaderPath, path,
+ resolved)) {
+ return false;
+ }
+ if (resolved) {
+ return true;
+ }
+ } else if (cmHasLiteralPrefix(searchFile, "@executable_path/")) {
+ if (!this->ResolveExecutablePathDependency(searchFile, executablePath,
+ path, resolved)) {
+ return false;
+ }
+ if (resolved) {
+ return true;
+ }
+ } else if (cmSystemTools::PathExists(searchFile)) {
+ /*
+ * paraphrasing @ben.boeckel:
+ * if /b/libB.dylib is supposed to be used,
+ * /a/libbB.dylib will be found first if it exists. CMake tries to
+ * sort rpath directories to avoid this, but sometimes there is no
+ * right answer.
+ *
+ * I believe it is possible to resolve this using otools -l
+ * then checking the LC_LOAD_DYLIB command whose name is
+ * equal to the value of search_file, UNLESS the build
+ * specifically sets the RPath to paths that will match
+ * duplicate libs; at this point can we just point to
+ * user error, or is there a reason why the advantages
+ * to this scenario outweigh its disadvantages?
+ *
+ * Also priority seems to be the order as passed in when compiled
+ * so as long as this method's resolution guarantees priority
+ * in that manner further checking should not be necessary?
+ */
+ path = searchFile;
+ resolved = true;
+ return true;
+ }
+ }
+
+ resolved = false;
+ return true;
+}
diff --git a/Source/cmBinUtilsMacOSMachOLinker.h b/Source/cmBinUtilsMacOSMachOLinker.h
new file mode 100644
index 000000000..4a24ea35e
--- /dev/null
+++ b/Source/cmBinUtilsMacOSMachOLinker.h
@@ -0,0 +1,59 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmBinUtilsMacOSMachOLinker_h
+#define cmBinUtilsMacOSMachOLinker_h
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "cmBinUtilsLinker.h"
+#include "cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h"
+#include "cmStateTypes.h"
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsMacOSMachOLinker : public cmBinUtilsLinker
+{
+public:
+ cmBinUtilsMacOSMachOLinker(cmRuntimeDependencyArchive* archive);
+
+ bool Prepare() override;
+
+ bool ScanDependencies(std::string const& file,
+ cmStateEnums::TargetType type) override;
+
+private:
+ std::unique_ptr<cmBinUtilsMacOSMachOGetRuntimeDependenciesTool> Tool;
+
+ bool ScanDependencies(std::string const& file,
+ std::string const& executablePath);
+
+ bool GetFileDependencies(std::vector<std::string> const& names,
+ std::string const& executablePath,
+ std::string const& loaderPath,
+ std::vector<std::string> const& rpaths);
+
+ bool ResolveDependency(std::string const& name,
+ std::string const& executablePath,
+ std::string const& loaderPath,
+ std::vector<std::string> const& rpaths,
+ std::string& path, bool& resolved);
+
+ bool ResolveExecutablePathDependency(std::string const& name,
+ std::string const& executablePath,
+ std::string& path, bool& resolved);
+
+ bool ResolveLoaderPathDependency(std::string const& name,
+ std::string const& loaderPath,
+ std::string& path, bool& resolved);
+
+ bool ResolveRPathDependency(std::string const& name,
+ std::string const& executablePath,
+ std::string const& loaderPath,
+ std::vector<std::string> const& rpaths,
+ std::string& path, bool& resolved);
+};
+
+#endif // cmBinUtilsMacOSMachOLinker_h
diff --git a/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx
new file mode 100644
index 000000000..351d92aa8
--- /dev/null
+++ b/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx
@@ -0,0 +1,100 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h"
+
+#include <sstream>
+
+#include <cmsys/RegularExpression.hxx>
+
+#include "cmRuntimeDependencyArchive.h"
+#include "cmUVProcessChain.h"
+
+cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool::
+ cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool(
+ cmRuntimeDependencyArchive* archive)
+ : cmBinUtilsMacOSMachOGetRuntimeDependenciesTool(archive)
+{
+}
+
+bool cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool::GetFileInfo(
+ std::string const& file, std::vector<std::string>& libs,
+ std::vector<std::string>& rpaths)
+{
+ std::vector<std::string> command;
+ if (!this->Archive->GetGetRuntimeDependenciesCommand("otool", command)) {
+ this->SetError("Could not find otool");
+ return false;
+ }
+ command.emplace_back("-l");
+ command.emplace_back(file);
+
+ cmUVProcessChainBuilder builder;
+ builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
+ .AddCommand(command);
+
+ auto process = builder.Start();
+ if (!process.Valid()) {
+ std::ostringstream e;
+ e << "Failed to start otool process for:\n " << file;
+ this->SetError(e.str());
+ return false;
+ }
+
+ std::string line;
+ static const cmsys::RegularExpression rpathRegex("^ *cmd LC_RPATH$");
+ static const cmsys::RegularExpression loadDylibRegex(
+ "^ *cmd LC_LOAD_DYLIB$");
+ static const cmsys::RegularExpression pathRegex(
+ "^ *path (.*) \\(offset [0-9]+\\)$");
+ static const cmsys::RegularExpression nameRegex(
+ "^ *name (.*) \\(offset [0-9]+\\)$");
+ while (std::getline(*process.OutputStream(), line)) {
+ cmsys::RegularExpressionMatch cmdMatch;
+ if (rpathRegex.find(line.c_str(), cmdMatch)) {
+ if (!std::getline(*process.OutputStream(), line) ||
+ !std::getline(*process.OutputStream(), line)) {
+ this->SetError("Invalid output from otool");
+ return false;
+ }
+
+ cmsys::RegularExpressionMatch pathMatch;
+ if (pathRegex.find(line.c_str(), pathMatch)) {
+ rpaths.push_back(pathMatch.match(1));
+ } else {
+ this->SetError("Invalid output from otool");
+ return false;
+ }
+ } else if (loadDylibRegex.find(line.c_str(), cmdMatch)) {
+ if (!std::getline(*process.OutputStream(), line) ||
+ !std::getline(*process.OutputStream(), line)) {
+ this->SetError("Invalid output from otool");
+ return false;
+ }
+
+ cmsys::RegularExpressionMatch nameMatch;
+ if (nameRegex.find(line.c_str(), nameMatch)) {
+ libs.push_back(nameMatch.match(1));
+ } else {
+ this->SetError("Invalid output from otool");
+ return false;
+ }
+ }
+ }
+
+ if (!process.Wait()) {
+ std::ostringstream e;
+ e << "Failed to wait on otool process for:\n " << file;
+ this->SetError(e.str());
+ return false;
+ }
+ auto status = process.GetStatus();
+ if (!status[0] || status[0]->ExitStatus != 0) {
+ std::ostringstream e;
+ e << "Failed to run otool on:\n " << file;
+ this->SetError(e.str());
+ return false;
+ }
+
+ return true;
+}
diff --git a/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h b/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h
new file mode 100644
index 000000000..8ac7e188e
--- /dev/null
+++ b/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h
@@ -0,0 +1,25 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool_h
+#define cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool_h
+
+#include <string>
+#include <vector>
+
+#include "cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h"
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool
+ : public cmBinUtilsMacOSMachOGetRuntimeDependenciesTool
+{
+public:
+ cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool(
+ cmRuntimeDependencyArchive* archive);
+
+ bool GetFileInfo(std::string const& file, std::vector<std::string>& libs,
+ std::vector<std::string>& rpaths) override;
+};
+
+#endif // cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool_h
diff --git a/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx
new file mode 100644
index 000000000..f342884dc
--- /dev/null
+++ b/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx
@@ -0,0 +1,68 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h"
+
+#include <sstream>
+
+#include <cmsys/RegularExpression.hxx>
+
+#include "cmRuntimeDependencyArchive.h"
+#include "cmUVProcessChain.h"
+
+cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool::
+ cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool(
+ cmRuntimeDependencyArchive* archive)
+ : cmBinUtilsWindowsPEGetRuntimeDependenciesTool(archive)
+{
+}
+
+bool cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool::GetFileInfo(
+ const std::string& file, std::vector<std::string>& needed)
+{
+ cmUVProcessChainBuilder builder;
+ builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT);
+
+ std::vector<std::string> command;
+ if (!this->Archive->GetGetRuntimeDependenciesCommand("dumpbin", command)) {
+ this->SetError("Could not find dumpbin");
+ return false;
+ }
+ command.emplace_back("/dependents");
+ command.push_back(file);
+ builder.AddCommand(command);
+
+ auto process = builder.Start();
+ if (!process.Valid()) {
+ std::ostringstream e;
+ e << "Failed to start dumpbin process for:\n " << file;
+ this->SetError(e.str());
+ return false;
+ }
+
+ std::string line;
+ static const cmsys::RegularExpression regex(
+ "^ ([^\n]*\\.[Dd][Ll][Ll])\r$");
+ while (std::getline(*process.OutputStream(), line)) {
+ cmsys::RegularExpressionMatch match;
+ if (regex.find(line.c_str(), match)) {
+ needed.push_back(match.match(1));
+ }
+ }
+
+ if (!process.Wait()) {
+ std::ostringstream e;
+ e << "Failed to wait on dumpbin process for:\n " << file;
+ this->SetError(e.str());
+ return false;
+ }
+ auto status = process.GetStatus();
+ if (!status[0] || status[0]->ExitStatus != 0) {
+ std::ostringstream e;
+ e << "Failed to run dumpbin on:\n " << file;
+ this->SetError(e.str());
+ return false;
+ }
+
+ return true;
+}
diff --git a/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h b/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h
new file mode 100644
index 000000000..eae22eae8
--- /dev/null
+++ b/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h
@@ -0,0 +1,25 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool_h
+#define cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool_h
+
+#include <string>
+#include <vector>
+
+#include "cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h"
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool
+ : public cmBinUtilsWindowsPEGetRuntimeDependenciesTool
+{
+public:
+ cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool(
+ cmRuntimeDependencyArchive* archive);
+
+ bool GetFileInfo(const std::string& file,
+ std::vector<std::string>& needed) override;
+};
+
+#endif // cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool_h
diff --git a/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.cxx
new file mode 100644
index 000000000..468a40c7a
--- /dev/null
+++ b/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.cxx
@@ -0,0 +1,19 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h"
+
+#include "cmRuntimeDependencyArchive.h"
+
+cmBinUtilsWindowsPEGetRuntimeDependenciesTool::
+ cmBinUtilsWindowsPEGetRuntimeDependenciesTool(
+ cmRuntimeDependencyArchive* archive)
+ : Archive(archive)
+{
+}
+
+void cmBinUtilsWindowsPEGetRuntimeDependenciesTool::SetError(
+ const std::string& error)
+{
+ this->Archive->SetError(error);
+}
diff --git a/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h b/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h
new file mode 100644
index 000000000..e9e402b0f
--- /dev/null
+++ b/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h
@@ -0,0 +1,28 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmBinUtilsWindowsPEGetRuntimeDependenciesTool_h
+#define cmBinUtilsWindowsPEGetRuntimeDependenciesTool_h
+
+#include <string>
+#include <vector>
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsWindowsPEGetRuntimeDependenciesTool
+{
+public:
+ cmBinUtilsWindowsPEGetRuntimeDependenciesTool(
+ cmRuntimeDependencyArchive* archive);
+ virtual ~cmBinUtilsWindowsPEGetRuntimeDependenciesTool() = default;
+
+ virtual bool GetFileInfo(const std::string& file,
+ std::vector<std::string>& needed) = 0;
+
+protected:
+ cmRuntimeDependencyArchive* Archive;
+
+ void SetError(const std::string& error);
+};
+
+#endif // cmBinUtilsWindowsPEGetRuntimeDependenciesTool_h
diff --git a/Source/cmBinUtilsWindowsPELinker.cxx b/Source/cmBinUtilsWindowsPELinker.cxx
new file mode 100644
index 000000000..79e39e9c5
--- /dev/null
+++ b/Source/cmBinUtilsWindowsPELinker.cxx
@@ -0,0 +1,123 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmBinUtilsWindowsPELinker.h"
+
+#include <sstream>
+#include <vector>
+
+#include <cm/memory>
+
+#include "cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h"
+#include "cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h"
+#include "cmRuntimeDependencyArchive.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+#ifdef _WIN32
+# include <windows.h>
+#endif
+
+cmBinUtilsWindowsPELinker::cmBinUtilsWindowsPELinker(
+ cmRuntimeDependencyArchive* archive)
+ : cmBinUtilsLinker(archive)
+{
+}
+
+bool cmBinUtilsWindowsPELinker::Prepare()
+{
+ std::string tool = this->Archive->GetGetRuntimeDependenciesTool();
+ if (tool.empty()) {
+ std::vector<std::string> command;
+ if (this->Archive->GetGetRuntimeDependenciesCommand("dumpbin", command)) {
+ tool = "dumpbin";
+ } else {
+ tool = "objdump";
+ }
+ }
+ if (tool == "dumpbin") {
+ this->Tool =
+ cm::make_unique<cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool>(
+ this->Archive);
+ } else if (tool == "objdump") {
+ this->Tool =
+ cm::make_unique<cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool>(
+ this->Archive);
+ } else {
+ std::ostringstream e;
+ e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL: " << tool;
+ this->SetError(e.str());
+ return false;
+ }
+
+ return true;
+}
+
+bool cmBinUtilsWindowsPELinker::ScanDependencies(
+ std::string const& file, cmStateEnums::TargetType /* unused */)
+{
+ std::vector<std::string> needed;
+ if (!this->Tool->GetFileInfo(file, needed)) {
+ return false;
+ }
+ for (auto& n : needed) {
+ n = cmSystemTools::LowerCase(n);
+ }
+ std::string origin = cmSystemTools::GetFilenamePath(file);
+
+ for (auto const& lib : needed) {
+ if (!this->Archive->IsPreExcluded(lib)) {
+ std::string path;
+ bool resolved = false;
+ if (!this->ResolveDependency(lib, origin, path, resolved)) {
+ return false;
+ }
+ if (resolved) {
+ if (!this->Archive->IsPostExcluded(path)) {
+ bool unique;
+ this->Archive->AddResolvedPath(lib, path, unique);
+ if (unique &&
+ !this->ScanDependencies(path, cmStateEnums::SHARED_LIBRARY)) {
+ return false;
+ }
+ }
+ } else {
+ this->Archive->AddUnresolvedPath(lib);
+ }
+ }
+ }
+
+ return true;
+}
+
+bool cmBinUtilsWindowsPELinker::ResolveDependency(std::string const& name,
+ std::string const& origin,
+ std::string& path,
+ bool& resolved)
+{
+ auto dirs = this->Archive->GetSearchDirectories();
+
+#ifdef _WIN32
+ char buf[MAX_PATH];
+ unsigned int len;
+ if ((len = GetWindowsDirectoryA(buf, MAX_PATH)) > 0) {
+ dirs.insert(dirs.begin(), std::string(buf, len));
+ }
+ if ((len = GetSystemDirectoryA(buf, MAX_PATH)) > 0) {
+ dirs.insert(dirs.begin(), std::string(buf, len));
+ }
+#endif
+
+ dirs.insert(dirs.begin(), origin);
+
+ for (auto const& searchPath : dirs) {
+ path = cmStrCat(searchPath, '/', name);
+ if (cmSystemTools::PathExists(path)) {
+ resolved = true;
+ return true;
+ }
+ }
+
+ resolved = false;
+ return true;
+}
diff --git a/Source/cmBinUtilsWindowsPELinker.h b/Source/cmBinUtilsWindowsPELinker.h
new file mode 100644
index 000000000..a8bb59629
--- /dev/null
+++ b/Source/cmBinUtilsWindowsPELinker.h
@@ -0,0 +1,33 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmBinUtilsWindowsPELinker_h
+#define cmBinUtilsWindowsPELinker_h
+
+#include <memory>
+#include <string>
+
+#include "cmBinUtilsLinker.h"
+#include "cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h"
+#include "cmStateTypes.h"
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsWindowsPELinker : public cmBinUtilsLinker
+{
+public:
+ cmBinUtilsWindowsPELinker(cmRuntimeDependencyArchive* archive);
+
+ bool Prepare() override;
+
+ bool ScanDependencies(std::string const& file,
+ cmStateEnums::TargetType type) override;
+
+private:
+ std::unique_ptr<cmBinUtilsWindowsPEGetRuntimeDependenciesTool> Tool;
+
+ bool ResolveDependency(std::string const& name, std::string const& origin,
+ std::string& path, bool& resolved);
+};
+
+#endif // cmBinUtilsWindowsPELinker_h
diff --git a/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx
new file mode 100644
index 000000000..1effda053
--- /dev/null
+++ b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx
@@ -0,0 +1,68 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h"
+
+#include <sstream>
+
+#include <cmsys/RegularExpression.hxx>
+
+#include "cmRuntimeDependencyArchive.h"
+#include "cmUVProcessChain.h"
+
+cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool::
+ cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool(
+ cmRuntimeDependencyArchive* archive)
+ : cmBinUtilsWindowsPEGetRuntimeDependenciesTool(archive)
+{
+}
+
+bool cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool::GetFileInfo(
+ const std::string& file, std::vector<std::string>& needed)
+{
+ cmUVProcessChainBuilder builder;
+ builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT);
+
+ std::vector<std::string> command;
+ if (!this->Archive->GetGetRuntimeDependenciesCommand("objdump", command)) {
+ this->SetError("Could not find objdump");
+ return false;
+ }
+ command.emplace_back("-p");
+ command.push_back(file);
+ builder.AddCommand(command);
+
+ auto process = builder.Start();
+ if (!process.Valid()) {
+ std::ostringstream e;
+ e << "Failed to start objdump process for:\n " << file;
+ this->SetError(e.str());
+ return false;
+ }
+
+ std::string line;
+ static const cmsys::RegularExpression regex(
+ "^\t*DLL Name: ([^\n]*\\.[Dd][Ll][Ll])\r$");
+ while (std::getline(*process.OutputStream(), line)) {
+ cmsys::RegularExpressionMatch match;
+ if (regex.find(line.c_str(), match)) {
+ needed.push_back(match.match(1));
+ }
+ }
+
+ if (!process.Wait()) {
+ std::ostringstream e;
+ e << "Failed to wait on objdump process for:\n " << file;
+ this->SetError(e.str());
+ return false;
+ }
+ auto status = process.GetStatus();
+ if (!status[0] || status[0]->ExitStatus != 0) {
+ std::ostringstream e;
+ e << "Failed to run objdump on:\n " << file;
+ this->SetError(e.str());
+ return false;
+ }
+
+ return true;
+}
diff --git a/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h
new file mode 100644
index 000000000..a67cb0cf1
--- /dev/null
+++ b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h
@@ -0,0 +1,25 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool_h
+#define cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool_h
+
+#include <string>
+#include <vector>
+
+#include "cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h"
+
+class cmRuntimeDependencyArchive;
+
+class cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool
+ : public cmBinUtilsWindowsPEGetRuntimeDependenciesTool
+{
+public:
+ cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool(
+ cmRuntimeDependencyArchive* archive);
+
+ bool GetFileInfo(const std::string& file,
+ std::vector<std::string>& needed) override;
+};
+
+#endif // cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool_h
diff --git a/Source/cmBreakCommand.cxx b/Source/cmBreakCommand.cxx
index 3772c6fb6..95db689cd 100644
--- a/Source/cmBreakCommand.cxx
+++ b/Source/cmBreakCommand.cxx
@@ -6,18 +6,18 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmake.h"
// cmBreakCommand
-bool cmBreakCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status)
+bool cmBreakCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- if (!this->Makefile->IsLoopBlock()) {
+ if (!status.GetMakefile().IsLoopBlock()) {
bool issueMessage = true;
std::ostringstream e;
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0055)) {
+ MessageType messageType = MessageType::AUTHOR_WARNING;
+ switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0055)) {
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0055) << "\n";
break;
@@ -27,15 +27,15 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const& args,
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::NEW:
- messageType = cmake::FATAL_ERROR;
+ messageType = MessageType::FATAL_ERROR;
break;
}
if (issueMessage) {
e << "A BREAK command was found outside of a proper "
"FOREACH or WHILE loop scope.";
- this->Makefile->IssueMessage(messageType, e.str());
- if (messageType == cmake::FATAL_ERROR) {
+ status.GetMakefile().IssueMessage(messageType, e.str());
+ if (messageType == MessageType::FATAL_ERROR) {
return false;
}
}
@@ -46,8 +46,8 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const& args,
if (!args.empty()) {
bool issueMessage = true;
std::ostringstream e;
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0055)) {
+ MessageType messageType = MessageType::AUTHOR_WARNING;
+ switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0055)) {
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0055) << "\n";
break;
@@ -57,14 +57,14 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const& args,
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::NEW:
- messageType = cmake::FATAL_ERROR;
+ messageType = MessageType::FATAL_ERROR;
break;
}
if (issueMessage) {
e << "The BREAK command does not accept any arguments.";
- this->Makefile->IssueMessage(messageType, e.str());
- if (messageType == cmake::FATAL_ERROR) {
+ status.GetMakefile().IssueMessage(messageType, e.str());
+ if (messageType == MessageType::FATAL_ERROR) {
return false;
}
}
diff --git a/Source/cmBreakCommand.h b/Source/cmBreakCommand.h
index fcca45c31..e6ce6fe74 100644
--- a/Source/cmBreakCommand.h
+++ b/Source/cmBreakCommand.h
@@ -3,34 +3,19 @@
#ifndef cmBreakCommand_h
#define cmBreakCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmBreakCommand
+/**
* \brief Break from an enclosing foreach or while loop
*
* cmBreakCommand returns from an enclosing foreach or while loop
*/
-class cmBreakCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmBreakCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmBreakCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx
index fd876004b..49c943975 100644
--- a/Source/cmBuildCommand.cxx
+++ b/Source/cmBuildCommand.cxx
@@ -2,32 +2,21 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmBuildCommand.h"
-#include <sstream>
-
+#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmake.h"
-
-class cmExecutionStatus;
-
-bool cmBuildCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
-{
- // Support the legacy signature of the command:
- //
- if (2 == args.size()) {
- return this->TwoArgsSignature(args);
- }
- return this->MainSignature(args);
-}
+namespace {
-bool cmBuildCommand::MainSignature(std::vector<std::string> const& args)
+bool MainSignature(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("requires at least one argument naming a CMake variable");
+ status.SetError("requires at least one argument naming a CMake variable");
return false;
}
@@ -63,9 +52,7 @@ bool cmBuildCommand::MainSignature(std::vector<std::string> const& args)
doing = DoingNone;
target = args[i];
} else {
- std::ostringstream e;
- e << "unknown argument \"" << args[i] << "\"";
- this->SetError(e.str());
+ status.SetError(cmStrCat("unknown argument \"", args[i], "\""));
return false;
}
}
@@ -82,30 +69,32 @@ bool cmBuildCommand::MainSignature(std::vector<std::string> const& args)
configuration = "Release";
}
+ cmMakefile& mf = status.GetMakefile();
if (!project_name.empty()) {
- this->Makefile->IssueMessage(
- cmake::AUTHOR_WARNING,
- "Ignoring PROJECT_NAME option because it has no effect.");
+ mf.IssueMessage(MessageType::AUTHOR_WARNING,
+ "Ignoring PROJECT_NAME option because it has no effect.");
}
- std::string makecommand =
- this->Makefile->GetGlobalGenerator()->GenerateCMakeBuildCommand(
- target, configuration, "", this->Makefile->IgnoreErrorsCMP0061());
+ std::string makecommand = mf.GetGlobalGenerator()->GenerateCMakeBuildCommand(
+ target, configuration, "", mf.IgnoreErrorsCMP0061());
- this->Makefile->AddDefinition(variable, makecommand.c_str());
+ mf.AddDefinition(variable, makecommand);
return true;
}
-bool cmBuildCommand::TwoArgsSignature(std::vector<std::string> const& args)
+bool TwoArgsSignature(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("called with less than two arguments");
+ status.SetError("called with less than two arguments");
return false;
}
+ cmMakefile& mf = status.GetMakefile();
+
std::string const& define = args[0];
- const char* cacheValue = this->Makefile->GetDefinition(define);
+ const char* cacheValue = mf.GetDefinition(define);
std::string configType;
if (!cmSystemTools::GetEnv("CMAKE_CONFIG_TYPE", configType) ||
@@ -113,16 +102,28 @@ bool cmBuildCommand::TwoArgsSignature(std::vector<std::string> const& args)
configType = "Release";
}
- std::string makecommand =
- this->Makefile->GetGlobalGenerator()->GenerateCMakeBuildCommand(
- "", configType, "", this->Makefile->IgnoreErrorsCMP0061());
+ std::string makecommand = mf.GetGlobalGenerator()->GenerateCMakeBuildCommand(
+ "", configType, "", mf.IgnoreErrorsCMP0061());
if (cacheValue) {
return true;
}
- this->Makefile->AddCacheDefinition(define, makecommand.c_str(),
- "Command used to build entire project "
- "from the command line.",
- cmStateEnums::STRING);
+ mf.AddCacheDefinition(define, makecommand.c_str(),
+ "Command used to build entire project "
+ "from the command line.",
+ cmStateEnums::STRING);
return true;
}
+
+} // namespace
+
+bool cmBuildCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ // Support the legacy signature of the command:
+ if (args.size() == 2) {
+ return TwoArgsSignature(args, status);
+ }
+
+ return MainSignature(args, status);
+}
diff --git a/Source/cmBuildCommand.h b/Source/cmBuildCommand.h
index 1f357a980..45aa71da2 100644
--- a/Source/cmBuildCommand.h
+++ b/Source/cmBuildCommand.h
@@ -3,47 +3,14 @@
#ifndef cmBuildCommand_h
#define cmBuildCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmBuildCommand
- * \brief build_command command
- *
- * cmBuildCommand implements the build_command CMake command
- */
-class cmBuildCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmBuildCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
- /**
- * The primary command signature with optional, KEYWORD-based args.
- */
- virtual bool MainSignature(std::vector<std::string> const& args);
-
- /**
- * Legacy "exactly 2 args required" signature.
- */
- virtual bool TwoArgsSignature(std::vector<std::string> const& args);
-
-private:
- bool IgnoreErrors() const;
-};
+bool cmBuildCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmBuildNameCommand.cxx b/Source/cmBuildNameCommand.cxx
index 9d2c0c642..3e517dca4 100644
--- a/Source/cmBuildNameCommand.cxx
+++ b/Source/cmBuildNameCommand.cxx
@@ -2,24 +2,24 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmBuildNameCommand.h"
-#include "cmsys/RegularExpression.hxx"
#include <algorithm>
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
-
-// cmBuildNameCommand
-bool cmBuildNameCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmBuildNameCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
- const char* cacheValue = this->Makefile->GetDefinition(args[0]);
+ cmMakefile& mf = status.GetMakefile();
+ const char* cacheValue = mf.GetDefinition(args[0]);
if (cacheValue) {
// do we need to correct the value?
cmsys::RegularExpression reg("[()/]");
@@ -28,33 +28,33 @@ bool cmBuildNameCommand::InitialPass(std::vector<std::string> const& args,
std::replace(cv.begin(), cv.end(), '/', '_');
std::replace(cv.begin(), cv.end(), '(', '_');
std::replace(cv.begin(), cv.end(), ')', '_');
- this->Makefile->AddCacheDefinition(args[0], cv.c_str(), "Name of build.",
- cmStateEnums::STRING);
+ mf.AddCacheDefinition(args[0], cv.c_str(), "Name of build.",
+ cmStateEnums::STRING);
}
return true;
}
std::string buildname = "WinNT";
- if (this->Makefile->GetDefinition("UNIX")) {
- buildname = "";
+ if (mf.GetDefinition("UNIX")) {
+ buildname.clear();
cmSystemTools::RunSingleCommand("uname -a", &buildname, &buildname);
if (!buildname.empty()) {
std::string RegExp = "([^ ]*) [^ ]* ([^ ]*) ";
- cmsys::RegularExpression reg(RegExp.c_str());
- if (reg.find(buildname.c_str())) {
+ cmsys::RegularExpression reg(RegExp);
+ if (reg.find(buildname)) {
buildname = reg.match(1) + "-" + reg.match(2);
}
}
}
std::string compiler = "${CMAKE_CXX_COMPILER}";
- this->Makefile->ExpandVariablesInString(compiler);
+ mf.ExpandVariablesInString(compiler);
buildname += "-";
buildname += cmSystemTools::GetFilenameName(compiler);
std::replace(buildname.begin(), buildname.end(), '/', '_');
std::replace(buildname.begin(), buildname.end(), '(', '_');
std::replace(buildname.begin(), buildname.end(), ')', '_');
- this->Makefile->AddCacheDefinition(args[0], buildname.c_str(),
- "Name of build.", cmStateEnums::STRING);
+ mf.AddCacheDefinition(args[0], buildname.c_str(), "Name of build.",
+ cmStateEnums::STRING);
return true;
}
diff --git a/Source/cmBuildNameCommand.h b/Source/cmBuildNameCommand.h
index ff26c559c..37a72689c 100644
--- a/Source/cmBuildNameCommand.h
+++ b/Source/cmBuildNameCommand.h
@@ -3,21 +3,14 @@
#ifndef cmBuildNameCommand_h
#define cmBuildNameCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmBuildNameCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE { return new cmBuildNameCommand; }
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmBuildNameCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmCLocaleEnvironmentScope.cxx b/Source/cmCLocaleEnvironmentScope.cxx
index 28e8f2efc..c6c38f83c 100644
--- a/Source/cmCLocaleEnvironmentScope.cxx
+++ b/Source/cmCLocaleEnvironmentScope.cxx
@@ -2,11 +2,11 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCLocaleEnvironmentScope.h"
-#include "cmSystemTools.h"
-
#include <sstream>
#include <utility>
+#include "cmSystemTools.h"
+
cmCLocaleEnvironmentScope::cmCLocaleEnvironmentScope()
{
this->SetEnv("LANGUAGE", "");
@@ -45,10 +45,9 @@ void cmCLocaleEnvironmentScope::SetEnv(std::string const& key,
cmCLocaleEnvironmentScope::~cmCLocaleEnvironmentScope()
{
- for (backup_map_t::const_iterator i = this->EnvironmentBackup.begin();
- i != this->EnvironmentBackup.end(); ++i) {
+ for (auto const& envb : this->EnvironmentBackup) {
std::ostringstream tmp;
- tmp << i->first << "=" << i->second;
+ tmp << envb.first << "=" << envb.second;
cmSystemTools::PutEnv(tmp.str());
}
}
diff --git a/Source/cmCLocaleEnvironmentScope.h b/Source/cmCLocaleEnvironmentScope.h
index e956cb24d..aa2827e74 100644
--- a/Source/cmCLocaleEnvironmentScope.h
+++ b/Source/cmCLocaleEnvironmentScope.h
@@ -3,24 +3,26 @@
#ifndef cmCLocaleEnvironmentScope_h
#define cmCLocaleEnvironmentScope_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
#include <string>
class cmCLocaleEnvironmentScope
{
- CM_DISABLE_COPY(cmCLocaleEnvironmentScope)
-
public:
cmCLocaleEnvironmentScope();
~cmCLocaleEnvironmentScope();
+ cmCLocaleEnvironmentScope(cmCLocaleEnvironmentScope const&) = delete;
+ cmCLocaleEnvironmentScope& operator=(cmCLocaleEnvironmentScope const&) =
+ delete;
+
private:
std::string GetEnv(std::string const& key);
void SetEnv(std::string const& key, std::string const& value);
- typedef std::map<std::string, std::string> backup_map_t;
+ using backup_map_t = std::map<std::string, std::string>;
backup_map_t EnvironmentBackup;
};
diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx
index 4475c5a52..26e9af027 100644
--- a/Source/cmCMakeHostSystemInformationCommand.cxx
+++ b/Source/cmCMakeHostSystemInformationCommand.cxx
@@ -2,27 +2,38 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCMakeHostSystemInformationCommand.h"
-#include <sstream>
+#include <cstddef>
-#include "cmMakefile.h"
#include "cmsys/SystemInformation.hxx"
+#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+
#if defined(_WIN32)
-#include "cmSystemTools.h"
-#include "cmVSSetupHelper.h"
-#define HAVE_VS_SETUP_HELPER
+# include "cmAlgorithms.h"
+# include "cmGlobalGenerator.h"
+# include "cmGlobalVisualStudioVersionedGenerator.h"
+# include "cmSystemTools.h"
+# include "cmVSSetupHelper.h"
+# define HAVE_VS_SETUP_HELPER
#endif
-class cmExecutionStatus;
+namespace {
+bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info,
+ std::string const& key, std::string& value);
+std::string ValueToString(size_t value);
+std::string ValueToString(const char* value);
+std::string ValueToString(std::string const& value);
+}
// cmCMakeHostSystemInformation
-bool cmCMakeHostSystemInformationCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
size_t current_index = 0;
if (args.size() < (current_index + 2) || args[current_index] != "RESULT") {
- this->SetError("missing RESULT specification.");
+ status.SetError("missing RESULT specification.");
return false;
}
@@ -30,7 +41,7 @@ bool cmCMakeHostSystemInformationCommand::InitialPass(
current_index += 2;
if (args.size() < (current_index + 2) || args[current_index] != "QUERY") {
- this->SetError("missing QUERY specification");
+ status.SetError("missing QUERY specification");
return false;
}
@@ -46,69 +57,143 @@ bool cmCMakeHostSystemInformationCommand::InitialPass(
result_list += ";";
}
std::string value;
- if (!this->GetValue(info, key, value)) {
+ if (!GetValue(status, info, key, value)) {
return false;
}
result_list += value;
}
- this->Makefile->AddDefinition(variable, result_list.c_str());
+ status.GetMakefile().AddDefinition(variable, result_list);
return true;
}
-bool cmCMakeHostSystemInformationCommand::GetValue(
- cmsys::SystemInformation& info, std::string const& key, std::string& value)
+namespace {
+
+bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info,
+ std::string const& key, std::string& value)
{
if (key == "NUMBER_OF_LOGICAL_CORES") {
- value = this->ValueToString(info.GetNumberOfLogicalCPU());
+ value = ValueToString(info.GetNumberOfLogicalCPU());
} else if (key == "NUMBER_OF_PHYSICAL_CORES") {
- value = this->ValueToString(info.GetNumberOfPhysicalCPU());
+ value = ValueToString(info.GetNumberOfPhysicalCPU());
} else if (key == "HOSTNAME") {
- value = this->ValueToString(info.GetHostname());
+ value = ValueToString(info.GetHostname());
} else if (key == "FQDN") {
- value = this->ValueToString(info.GetFullyQualifiedDomainName());
+ value = ValueToString(info.GetFullyQualifiedDomainName());
} else if (key == "TOTAL_VIRTUAL_MEMORY") {
- value = this->ValueToString(info.GetTotalVirtualMemory());
+ value = ValueToString(info.GetTotalVirtualMemory());
} else if (key == "AVAILABLE_VIRTUAL_MEMORY") {
- value = this->ValueToString(info.GetAvailableVirtualMemory());
+ value = ValueToString(info.GetAvailableVirtualMemory());
} else if (key == "TOTAL_PHYSICAL_MEMORY") {
- value = this->ValueToString(info.GetTotalPhysicalMemory());
+ value = ValueToString(info.GetTotalPhysicalMemory());
} else if (key == "AVAILABLE_PHYSICAL_MEMORY") {
- value = this->ValueToString(info.GetAvailablePhysicalMemory());
+ value = ValueToString(info.GetAvailablePhysicalMemory());
+ } else if (key == "IS_64BIT") {
+ value = ValueToString(info.Is64Bits());
+ } else if (key == "HAS_FPU") {
+ value = ValueToString(
+ info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_FPU));
+ } else if (key == "HAS_MMX") {
+ value = ValueToString(
+ info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_MMX));
+ } else if (key == "HAS_MMX_PLUS") {
+ value = ValueToString(info.DoesCPUSupportFeature(
+ cmsys::SystemInformation::CPU_FEATURE_MMX_PLUS));
+ } else if (key == "HAS_SSE") {
+ value = ValueToString(
+ info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE));
+ } else if (key == "HAS_SSE2") {
+ value = ValueToString(
+ info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE2));
+ } else if (key == "HAS_SSE_FP") {
+ value = ValueToString(info.DoesCPUSupportFeature(
+ cmsys::SystemInformation::CPU_FEATURE_SSE_FP));
+ } else if (key == "HAS_SSE_MMX") {
+ value = ValueToString(info.DoesCPUSupportFeature(
+ cmsys::SystemInformation::CPU_FEATURE_SSE_MMX));
+ } else if (key == "HAS_AMD_3DNOW") {
+ value = ValueToString(info.DoesCPUSupportFeature(
+ cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW));
+ } else if (key == "HAS_AMD_3DNOW_PLUS") {
+ value = ValueToString(info.DoesCPUSupportFeature(
+ cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW_PLUS));
+ } else if (key == "HAS_IA64") {
+ value = ValueToString(
+ info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_IA64));
+ } else if (key == "HAS_SERIAL_NUMBER") {
+ value = ValueToString(info.DoesCPUSupportFeature(
+ cmsys::SystemInformation::CPU_FEATURE_SERIALNUMBER));
+ } else if (key == "PROCESSOR_NAME") {
+ value = ValueToString(info.GetExtendedProcessorName());
+ } else if (key == "PROCESSOR_DESCRIPTION") {
+ value = info.GetCPUDescription();
+ } else if (key == "PROCESSOR_SERIAL_NUMBER") {
+ value = ValueToString(info.GetProcessorSerialNumber());
+ } else if (key == "OS_NAME") {
+ value = ValueToString(info.GetOSName());
+ } else if (key == "OS_RELEASE") {
+ value = ValueToString(info.GetOSRelease());
+ } else if (key == "OS_VERSION") {
+ value = ValueToString(info.GetOSVersion());
+ } else if (key == "OS_PLATFORM") {
+ value = ValueToString(info.GetOSPlatform());
#ifdef HAVE_VS_SETUP_HELPER
} else if (key == "VS_15_DIR") {
- cmVSSetupAPIHelper vsSetupAPIHelper;
+ // If generating for the VS 15 IDE, use the same instance.
+ cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator();
+ if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 15 ")) {
+ cmGlobalVisualStudioVersionedGenerator* vs15gen =
+ static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg);
+ if (vs15gen->GetVSInstance(value)) {
+ return true;
+ }
+ }
+
+ // Otherwise, find a VS 15 instance ourselves.
+ cmVSSetupAPIHelper vsSetupAPIHelper(15);
+ if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
+ cmSystemTools::ConvertToUnixSlashes(value);
+ }
+ } else if (key == "VS_16_DIR") {
+ // If generating for the VS 16 IDE, use the same instance.
+ cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator();
+ if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 16 ")) {
+ cmGlobalVisualStudioVersionedGenerator* vs16gen =
+ static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg);
+ if (vs16gen->GetVSInstance(value)) {
+ return true;
+ }
+ }
+
+ // Otherwise, find a VS 16 instance ourselves.
+ cmVSSetupAPIHelper vsSetupAPIHelper(16);
if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
cmSystemTools::ConvertToUnixSlashes(value);
}
#endif
} else {
std::string e = "does not recognize <key> " + key;
- this->SetError(e);
+ status.SetError(e);
return false;
}
return true;
}
-std::string cmCMakeHostSystemInformationCommand::ValueToString(
- size_t value) const
+std::string ValueToString(size_t value)
{
- std::ostringstream tmp;
- tmp << value;
- return tmp.str();
+ return std::to_string(value);
}
-std::string cmCMakeHostSystemInformationCommand::ValueToString(
- const char* value) const
+std::string ValueToString(const char* value)
{
std::string safe_string = value ? value : "";
return safe_string;
}
-std::string cmCMakeHostSystemInformationCommand::ValueToString(
- std::string const& value) const
+std::string ValueToString(std::string const& value)
{
return value;
}
+}
diff --git a/Source/cmCMakeHostSystemInformationCommand.h b/Source/cmCMakeHostSystemInformationCommand.h
index ef6ca3730..79e3f2702 100644
--- a/Source/cmCMakeHostSystemInformationCommand.h
+++ b/Source/cmCMakeHostSystemInformationCommand.h
@@ -3,50 +3,20 @@
#ifndef cmCMakeHostSystemInformationCommand_h
#define cmCMakeHostSystemInformationCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include <stddef.h>
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-namespace cmsys {
-class SystemInformation;
-} // namespace cmsys
-/** \class cmCMakeHostSystemInformationCommand
+/**
* \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
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE
- {
- return new cmCMakeHostSystemInformationCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- bool GetValue(cmsys::SystemInformation& info, std::string const& key,
- std::string& value);
-
- std::string ValueToString(size_t value) const;
- std::string ValueToString(const char* value) const;
- std::string ValueToString(std::string const& value) const;
-};
+bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmCMakeMinimumRequired.cxx b/Source/cmCMakeMinimumRequired.cxx
index 942688cee..1b03873d0 100644
--- a/Source/cmCMakeMinimumRequired.cxx
+++ b/Source/cmCMakeMinimumRequired.cxx
@@ -2,52 +2,73 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCMakeMinimumRequired.h"
+#include <cstdio>
#include <sstream>
-#include <stdio.h>
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
-#include "cmake.h"
-class cmExecutionStatus;
+namespace {
+bool EnforceUnknownArguments(std::string const& version_max,
+ std::vector<std::string> const& unknown_arguments,
+ cmExecutionStatus& status);
+}
// cmCMakeMinimumRequired
-bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmCMakeMinimumRequired(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
// Process arguments.
std::string version_string;
bool doing_version = false;
- for (unsigned int i = 0; i < args.size(); ++i) {
- if (args[i] == "VERSION") {
+ std::vector<std::string> unknown_arguments;
+ for (std::string const& arg : args) {
+ if (arg == "VERSION") {
doing_version = true;
- } else if (args[i] == "FATAL_ERROR") {
+ } else if (arg == "FATAL_ERROR") {
if (doing_version) {
- this->SetError("called with no value for VERSION.");
+ status.SetError("called with no value for VERSION.");
return false;
}
doing_version = false;
} else if (doing_version) {
doing_version = false;
- version_string = args[i];
+ version_string = arg;
} else {
- this->UnknownArguments.push_back(args[i]);
+ unknown_arguments.push_back(arg);
}
}
if (doing_version) {
- this->SetError("called with no value for VERSION.");
+ status.SetError("called with no value for VERSION.");
return false;
}
// Make sure there was a version to check.
if (version_string.empty()) {
- return this->EnforceUnknownArguments();
+ return EnforceUnknownArguments(std::string(), unknown_arguments, status);
+ }
+
+ // Separate the <min> version and any trailing ...<max> component.
+ std::string::size_type const dd = version_string.find("...");
+ std::string const version_min = version_string.substr(0, dd);
+ std::string const version_max = dd != std::string::npos
+ ? version_string.substr(dd + 3, std::string::npos)
+ : std::string();
+ if (dd != std::string::npos &&
+ (version_min.empty() || version_max.empty())) {
+ std::ostringstream e;
+ e << "VERSION \"" << version_string
+ << R"(" does not have a version on both sides of "...".)";
+ status.SetError(e.str());
+ return false;
}
// Save the required version string.
- this->Makefile->AddDefinition("CMAKE_MINIMUM_REQUIRED_VERSION",
- version_string.c_str());
+ status.GetMakefile().AddDefinition("CMAKE_MINIMUM_REQUIRED_VERSION",
+ version_min);
// Get the current version number.
unsigned int current_major = cmVersion::GetMajorVersion();
@@ -61,11 +82,11 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
unsigned int required_minor = 0;
unsigned int required_patch = 0;
unsigned int required_tweak = 0;
- if (sscanf(version_string.c_str(), "%u.%u.%u.%u", &required_major,
+ if (sscanf(version_min.c_str(), "%u.%u.%u.%u", &required_major,
&required_minor, &required_patch, &required_tweak) < 2) {
std::ostringstream e;
- e << "could not parse VERSION \"" << version_string << "\".";
- this->SetError(e.str());
+ e << "could not parse VERSION \"" << version_min << "\".";
+ status.SetError(e.str());
return false;
}
@@ -78,39 +99,67 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args,
current_patch == required_patch && current_tweak < required_tweak)) {
// The current version is too low.
std::ostringstream e;
- e << "CMake " << version_string
+ e << "CMake " << version_min
<< " or higher is required. You are running version "
<< cmVersion::GetCMakeVersion();
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str());
cmSystemTools::SetFatalErrorOccured();
return true;
}
// The version is not from the future, so enforce unknown arguments.
- if (!this->EnforceUnknownArguments()) {
+ if (!EnforceUnknownArguments(version_max, unknown_arguments, status)) {
return false;
}
if (required_major < 2 || (required_major == 2 && required_minor < 4)) {
- this->Makefile->IssueMessage(
- cmake::AUTHOR_WARNING,
+ status.GetMakefile().IssueMessage(
+ MessageType::AUTHOR_WARNING,
"Compatibility with CMake < 2.4 is not supported by CMake >= 3.0.");
- this->Makefile->SetPolicyVersion("2.4");
+ status.GetMakefile().SetPolicyVersion("2.4", version_max);
} else {
- this->Makefile->SetPolicyVersion(version_string.c_str());
+ status.GetMakefile().SetPolicyVersion(version_min, version_max);
}
return true;
}
-bool cmCMakeMinimumRequired::EnforceUnknownArguments()
+namespace {
+bool EnforceUnknownArguments(std::string const& version_max,
+ std::vector<std::string> const& unknown_arguments,
+ cmExecutionStatus& status)
{
- if (!this->UnknownArguments.empty()) {
- std::ostringstream e;
- e << "called with unknown argument \"" << this->UnknownArguments[0]
- << "\".";
- this->SetError(e.str());
- return false;
+ if (unknown_arguments.empty()) {
+ return true;
}
- return true;
+
+ // Consider the max version if at least two components were given.
+ unsigned int max_major = 0;
+ unsigned int max_minor = 0;
+ unsigned int max_patch = 0;
+ unsigned int max_tweak = 0;
+ if (sscanf(version_max.c_str(), "%u.%u.%u.%u", &max_major, &max_minor,
+ &max_patch, &max_tweak) >= 2) {
+ unsigned int current_major = cmVersion::GetMajorVersion();
+ unsigned int current_minor = cmVersion::GetMinorVersion();
+ unsigned int current_patch = cmVersion::GetPatchVersion();
+ unsigned int current_tweak = cmVersion::GetTweakVersion();
+
+ if ((current_major < max_major) ||
+ (current_major == max_major && current_minor < max_minor) ||
+ (current_major == max_major && current_minor == max_minor &&
+ current_patch < max_patch) ||
+ (current_major == max_major && current_minor == max_minor &&
+ current_patch == max_patch && current_tweak < max_tweak)) {
+ // A ...<max> version was given that is larger than the current
+ // version of CMake, so tolerate unknown arguments.
+ return true;
+ }
+ }
+
+ std::ostringstream e;
+ e << "called with unknown argument \"" << unknown_arguments[0] << "\".";
+ status.SetError(e.str());
+ return false;
+}
}
diff --git a/Source/cmCMakeMinimumRequired.h b/Source/cmCMakeMinimumRequired.h
index 45b6b7885..53f78f690 100644
--- a/Source/cmCMakeMinimumRequired.h
+++ b/Source/cmCMakeMinimumRequired.h
@@ -3,38 +3,19 @@
#ifndef cmCMakeMinimumRequired_h
#define cmCMakeMinimumRequired_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmCMakeMinimumRequired
+/**
* \brief cmake_minimum_required command
*
* cmCMakeMinimumRequired implements the cmake_minimum_required CMake command
*/
-class cmCMakeMinimumRequired : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmCMakeMinimumRequired; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- std::vector<std::string> UnknownArguments;
- bool EnforceUnknownArguments();
-};
+bool cmCMakeMinimumRequired(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx
index 3ccc815e6..b7f08d2dd 100644
--- a/Source/cmCMakePolicyCommand.cxx
+++ b/Source/cmCMakePolicyCommand.cxx
@@ -2,87 +2,99 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCMakePolicyCommand.h"
-#include <sstream>
-
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmState.h"
#include "cmStateTypes.h"
-#include "cmake.h"
+#include "cmStringAlgorithms.h"
-class cmExecutionStatus;
+namespace {
+bool HandleSetMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+bool HandleGetMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+bool HandleVersionMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+bool HandleGetWarningMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+}
// cmCMakePolicyCommand
-bool cmCMakePolicyCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmCMakePolicyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("requires at least one argument.");
+ status.SetError("requires at least one argument.");
return false;
}
if (args[0] == "SET") {
- return this->HandleSetMode(args);
+ return HandleSetMode(args, status);
}
if (args[0] == "GET") {
- return this->HandleGetMode(args);
+ return HandleGetMode(args, status);
}
if (args[0] == "PUSH") {
if (args.size() > 1) {
- this->SetError("PUSH may not be given additional arguments.");
+ status.SetError("PUSH may not be given additional arguments.");
return false;
}
- this->Makefile->PushPolicy();
+ status.GetMakefile().PushPolicy();
return true;
}
if (args[0] == "POP") {
if (args.size() > 1) {
- this->SetError("POP may not be given additional arguments.");
+ status.SetError("POP may not be given additional arguments.");
return false;
}
- this->Makefile->PopPolicy();
+ status.GetMakefile().PopPolicy();
return true;
}
if (args[0] == "VERSION") {
- return this->HandleVersionMode(args);
+ return HandleVersionMode(args, status);
+ }
+ if (args[0] == "GET_WARNING") {
+ return HandleGetWarningMode(args, status);
}
- std::ostringstream e;
- e << "given unknown first argument \"" << args[0] << "\"";
- this->SetError(e.str());
+ status.SetError(cmStrCat("given unknown first argument \"", args[0], "\""));
return false;
}
-bool cmCMakePolicyCommand::HandleSetMode(std::vector<std::string> const& args)
+namespace {
+
+bool HandleSetMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() != 3) {
- this->SetError("SET must be given exactly 2 additional arguments.");
+ status.SetError("SET must be given exactly 2 additional arguments.");
return false;
}
- cmPolicies::PolicyStatus status;
+ cmPolicies::PolicyStatus policyStatus;
if (args[2] == "OLD") {
- status = cmPolicies::OLD;
+ policyStatus = cmPolicies::OLD;
} else if (args[2] == "NEW") {
- status = cmPolicies::NEW;
+ policyStatus = cmPolicies::NEW;
} else {
- std::ostringstream e;
- e << "SET given unrecognized policy status \"" << args[2] << "\"";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("SET given unrecognized policy status \"", args[2], "\""));
return false;
}
- if (!this->Makefile->SetPolicy(args[1].c_str(), status)) {
- this->SetError("SET failed to set policy.");
+ if (!status.GetMakefile().SetPolicy(args[1].c_str(), policyStatus)) {
+ status.SetError("SET failed to set policy.");
return false;
}
if (args[1] == "CMP0001" &&
- (status == cmPolicies::WARN || status == cmPolicies::OLD)) {
- if (!(this->Makefile->GetState()->GetInitializedCacheValue(
+ (policyStatus == cmPolicies::WARN || policyStatus == cmPolicies::OLD)) {
+ if (!(status.GetMakefile().GetState()->GetInitializedCacheValue(
"CMAKE_BACKWARDS_COMPATIBILITY"))) {
// Set it to 2.4 because that is the last version where the
// variable had meaning.
- this->Makefile->AddCacheDefinition(
+ status.GetMakefile().AddCacheDefinition(
"CMAKE_BACKWARDS_COMPATIBILITY", "2.4",
"For backwards compatibility, what version of CMake "
"commands and "
@@ -93,10 +105,15 @@ bool cmCMakePolicyCommand::HandleSetMode(std::vector<std::string> const& args)
return true;
}
-bool cmCMakePolicyCommand::HandleGetMode(std::vector<std::string> const& args)
+bool HandleGetMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- if (args.size() != 3) {
- this->SetError("GET must be given exactly 2 additional arguments.");
+ bool parent_scope = false;
+ if (args.size() == 4 && args[3] == "PARENT_SCOPE") {
+ // Undocumented PARENT_SCOPE option for use within CMake.
+ parent_scope = true;
+ } else if (args.size() != 3) {
+ status.SetError("GET must be given exactly 2 additional arguments.");
return false;
}
@@ -107,55 +124,102 @@ bool cmCMakePolicyCommand::HandleGetMode(std::vector<std::string> const& args)
// Lookup the policy number.
cmPolicies::PolicyID pid;
if (!cmPolicies::GetPolicyID(id.c_str(), pid)) {
- std::ostringstream e;
- e << "GET given policy \"" << id << "\" which is not known to this "
- << "version of CMake.";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("GET given policy \"", id,
+ "\" which is not known to this version of CMake."));
return false;
}
// Lookup the policy setting.
- cmPolicies::PolicyStatus status = this->Makefile->GetPolicyStatus(pid);
- switch (status) {
+ cmPolicies::PolicyStatus policyStatus =
+ status.GetMakefile().GetPolicyStatus(pid, parent_scope);
+ switch (policyStatus) {
case cmPolicies::OLD:
// Report that the policy is set to OLD.
- this->Makefile->AddDefinition(var, "OLD");
+ status.GetMakefile().AddDefinition(var, "OLD");
break;
case cmPolicies::WARN:
// Report that the policy is not set.
- this->Makefile->AddDefinition(var, "");
+ status.GetMakefile().AddDefinition(var, "");
break;
case cmPolicies::NEW:
// Report that the policy is set to NEW.
- this->Makefile->AddDefinition(var, "NEW");
+ status.GetMakefile().AddDefinition(var, "NEW");
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
// The policy is required to be set before anything needs it.
{
- std::ostringstream e;
- e << cmPolicies::GetRequiredPolicyError(pid) << "\n"
- << "The call to cmake_policy(GET " << id << " ...) at which this "
- << "error appears requests the policy, and this version of CMake "
- << "requires that the policy be set to NEW before it is checked.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ status.GetMakefile().IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(
+ cmPolicies::GetRequiredPolicyError(pid), "\n",
+ "The call to cmake_policy(GET ", id,
+ " ...) at which this "
+ "error appears requests the policy, and this version of CMake ",
+ "requires that the policy be set to NEW before it is checked."));
}
}
return true;
}
-bool cmCMakePolicyCommand::HandleVersionMode(
- std::vector<std::string> const& args)
+bool HandleVersionMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() <= 1) {
- this->SetError("VERSION not given an argument");
+ status.SetError("VERSION not given an argument");
return false;
}
if (args.size() >= 3) {
- this->SetError("VERSION given too many arguments");
+ status.SetError("VERSION given too many arguments");
+ return false;
+ }
+ std::string const& version_string = args[1];
+
+ // Separate the <min> version and any trailing ...<max> component.
+ std::string::size_type const dd = version_string.find("...");
+ std::string const version_min = version_string.substr(0, dd);
+ std::string const version_max = dd != std::string::npos
+ ? version_string.substr(dd + 3, std::string::npos)
+ : std::string();
+ if (dd != std::string::npos &&
+ (version_min.empty() || version_max.empty())) {
+ status.SetError(
+ cmStrCat("VERSION \"", version_string,
+ R"(" does not have a version on both sides of "...".)"));
return false;
}
- this->Makefile->SetPolicyVersion(args[1].c_str());
+
+ status.GetMakefile().SetPolicyVersion(version_min, version_max);
return true;
}
+
+bool HandleGetWarningMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.size() != 3) {
+ status.SetError(
+ "GET_WARNING must be given exactly 2 additional arguments.");
+ return false;
+ }
+
+ // Get arguments.
+ std::string const& id = args[1];
+ std::string const& var = args[2];
+
+ // Lookup the policy number.
+ cmPolicies::PolicyID pid;
+ if (!cmPolicies::GetPolicyID(id.c_str(), pid)) {
+ status.SetError(
+ cmStrCat("GET_WARNING given policy \"", id,
+ "\" which is not known to this version of CMake."));
+ return false;
+ }
+
+ // Lookup the policy warning.
+ status.GetMakefile().AddDefinition(var, cmPolicies::GetPolicyWarning(pid));
+
+ return true;
+}
+}
diff --git a/Source/cmCMakePolicyCommand.h b/Source/cmCMakePolicyCommand.h
index 0e88243f5..ba9397d76 100644
--- a/Source/cmCMakePolicyCommand.h
+++ b/Source/cmCMakePolicyCommand.h
@@ -3,40 +3,20 @@
#ifndef cmCMakePolicyCommand_h
#define cmCMakePolicyCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmCMakePolicyCommand
+/**
* \brief Set how CMake should handle policies
*
* cmCMakePolicyCommand sets how CMake should deal with backwards
* compatibility policies.
*/
-class cmCMakePolicyCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmCMakePolicyCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- bool HandleSetMode(std::vector<std::string> const& args);
- bool HandleGetMode(std::vector<std::string> const& args);
- bool HandleVersionMode(std::vector<std::string> const& args);
-};
+bool cmCMakePolicyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmCPackPropertiesGenerator.cxx b/Source/cmCPackPropertiesGenerator.cxx
index 57a8b383c..cc9ad0103 100644
--- a/Source/cmCPackPropertiesGenerator.cxx
+++ b/Source/cmCPackPropertiesGenerator.cxx
@@ -1,13 +1,12 @@
#include "cmCPackPropertiesGenerator.h"
+#include <map>
+#include <ostream>
+
#include "cmGeneratorExpression.h"
#include "cmInstalledFile.h"
#include "cmOutputConverter.h"
-#include <map>
-#include <ostream>
-#include <utility>
-
cmCPackPropertiesGenerator::cmCPackPropertiesGenerator(
cmLocalGenerator* lg, cmInstalledFile const& installedFile,
std::vector<std::string> const& configurations)
@@ -27,19 +26,17 @@ void cmCPackPropertiesGenerator::GenerateScriptForConfig(
cmInstalledFile::PropertyMapType const& properties =
this->InstalledFile.GetProperties();
- for (cmInstalledFile::PropertyMapType::const_iterator i = properties.begin();
- i != properties.end(); ++i) {
- std::string const& name = i->first;
- cmInstalledFile::Property const& property = i->second;
+ for (cmInstalledFile::PropertyMapType::value_type const& i : properties) {
+ std::string const& name = i.first;
+ cmInstalledFile::Property const& property = i.second;
os << indent << "set_property(INSTALL "
<< cmOutputConverter::EscapeForCMake(expandedFileName) << " PROPERTY "
<< cmOutputConverter::EscapeForCMake(name);
- for (cmInstalledFile::ExpressionVectorType::const_iterator j =
- property.ValueExpressions.begin();
- j != property.ValueExpressions.end(); ++j) {
- std::string value = (*j)->Evaluate(this->LG, config);
+ for (cmInstalledFile::ExpressionVectorType::value_type const& j :
+ property.ValueExpressions) {
+ std::string value = j->Evaluate(this->LG, config);
os << " " << cmOutputConverter::EscapeForCMake(value);
}
diff --git a/Source/cmCPackPropertiesGenerator.h b/Source/cmCPackPropertiesGenerator.h
index 48f4c10f4..83392383a 100644
--- a/Source/cmCPackPropertiesGenerator.h
+++ b/Source/cmCPackPropertiesGenerator.h
@@ -3,14 +3,14 @@
#ifndef cmCPackPropertiesGenerator_h
#define cmCPackPropertiesGenerator_h
-#include "cmConfigure.h"
-
-#include "cmScriptGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
#include <vector>
+#include "cmScriptGenerator.h"
+
class cmInstalledFile;
class cmLocalGenerator;
@@ -20,16 +20,18 @@ class cmLocalGenerator;
*/
class cmCPackPropertiesGenerator : public cmScriptGenerator
{
- CM_DISABLE_COPY(cmCPackPropertiesGenerator)
-
public:
cmCPackPropertiesGenerator(cmLocalGenerator* lg,
cmInstalledFile const& installedFile,
std::vector<std::string> const& configurations);
+ cmCPackPropertiesGenerator(cmCPackPropertiesGenerator const&) = delete;
+ cmCPackPropertiesGenerator& operator=(cmCPackPropertiesGenerator const&) =
+ delete;
+
protected:
void GenerateScriptForConfig(std::ostream& os, const std::string& config,
- Indent indent) CM_OVERRIDE;
+ Indent indent) override;
cmLocalGenerator* LG;
cmInstalledFile const& InstalledFile;
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index e78f5fe04..177bca889 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -7,6 +7,8 @@
#include "cmCPluginAPI.h"
+#include <cstdlib>
+
#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
@@ -14,10 +16,8 @@
#include "cmState.h"
#include "cmVersion.h"
-#include <stdlib.h>
-
#ifdef __QNX__
-#include <malloc.h> /* for malloc/free on QNX */
+# include <malloc.h> /* for malloc/free on QNX */
#endif
extern "C" {
@@ -65,8 +65,10 @@ unsigned int CCONV cmGetMinorVersion(void*)
void CCONV cmAddDefinition(void* arg, const char* name, const char* value)
{
- cmMakefile* mf = static_cast<cmMakefile*>(arg);
- mf->AddDefinition(name, value);
+ if (value) {
+ cmMakefile* mf = static_cast<cmMakefile*>(arg);
+ mf->AddDefinition(name, value);
+ }
}
/* Add a definition to this makefile and the global cmake cache. */
@@ -108,32 +110,32 @@ 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)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
- return mf->GetCurrentSourceDirectory();
+ return mf->GetCurrentSourceDirectory().c_str();
}
const char* CCONV cmGetStartOutputDirectory(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
- return mf->GetCurrentBinaryDirectory();
+ return mf->GetCurrentBinaryDirectory().c_str();
}
const char* CCONV cmGetCurrentDirectory(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
- return mf->GetCurrentSourceDirectory();
+ return mf->GetCurrentSourceDirectory().c_str();
}
const char* CCONV cmGetCurrentOutputDirectory(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
- return mf->GetCurrentBinaryDirectory();
+ return mf->GetCurrentBinaryDirectory().c_str();
}
const char* CCONV cmGetDefinition(void* arg, const char* def)
{
@@ -167,11 +169,11 @@ void CCONV cmAddLinkDirectoryForTarget(void* arg, const char* tgt,
cmTarget* t = mf->FindLocalNonAliasTarget(tgt);
if (!t) {
cmSystemTools::Error(
- "Attempt to add link directories to non-existent target: ", tgt,
- " for directory ", d);
+ "Attempt to add link directories to non-existent target: " +
+ std::string(tgt) + " for directory " + std::string(d));
return;
}
- t->AddLinkDirectory(d);
+ t->InsertLinkDirectory(d, mf->GetBacktrace());
}
void CCONV cmAddExecutable(void* arg, const char* exename, int numSrcs,
@@ -181,7 +183,7 @@ void CCONV cmAddExecutable(void* arg, const char* exename, int numSrcs,
std::vector<std::string> srcs2;
int i;
for (i = 0; i < numSrcs; ++i) {
- srcs2.push_back(srcs[i]);
+ srcs2.emplace_back(srcs[i]);
}
cmTarget* tg = mf->AddExecutable(exename, srcs2);
if (win32) {
@@ -218,8 +220,10 @@ void CCONV cmAddUtilityCommand(void* arg, const char* utilityName,
}
// Pass the call to the makefile instance.
- mf->AddUtilityCommand(utilityName, (all ? false : true), CM_NULLPTR,
- depends2, commandLines);
+ std::vector<std::string> no_byproducts;
+ mf->AddUtilityCommand(utilityName, cmCommandOrigin::Project,
+ (all ? false : true), nullptr, no_byproducts, depends2,
+ commandLines);
}
void CCONV cmAddCustomCommand(void* arg, const char* source,
const char* command, int numArgs,
@@ -257,7 +261,7 @@ void CCONV cmAddCustomCommand(void* arg, const char* source,
}
// Pass the call to the makefile instance.
- const char* no_comment = CM_NULLPTR;
+ const char* no_comment = nullptr;
mf->AddCustomCommandOldStyle(target, outputs2, depends2, source,
commandLines, no_comment);
}
@@ -291,8 +295,8 @@ void CCONV cmAddCustomCommandToOutput(void* arg, const char* output,
}
// Pass the call to the makefile instance.
- const char* no_comment = CM_NULLPTR;
- const char* no_working_dir = CM_NULLPTR;
+ const char* no_comment = nullptr;
+ const char* no_working_dir = nullptr;
mf->AddCustomCommandToOutput(output, depends2, main_dependency, commandLines,
no_comment, no_working_dir);
}
@@ -317,24 +321,24 @@ void CCONV cmAddCustomCommandToTarget(void* arg, const char* target,
commandLines.push_back(commandLine);
// Select the command type.
- cmTarget::CustomCommandType cctype = cmTarget::POST_BUILD;
+ cmCustomCommandType cctype = cmCustomCommandType::POST_BUILD;
switch (commandType) {
case CM_PRE_BUILD:
- cctype = cmTarget::PRE_BUILD;
+ cctype = cmCustomCommandType::PRE_BUILD;
break;
case CM_PRE_LINK:
- cctype = cmTarget::PRE_LINK;
+ cctype = cmCustomCommandType::PRE_LINK;
break;
case CM_POST_BUILD:
- cctype = cmTarget::POST_BUILD;
+ cctype = cmCustomCommandType::POST_BUILD;
break;
}
// Pass the call to the makefile instance.
std::vector<std::string> no_byproducts;
std::vector<std::string> no_depends;
- const char* no_comment = CM_NULLPTR;
- const char* no_working_dir = CM_NULLPTR;
+ const char* no_comment = nullptr;
+ const char* no_working_dir = nullptr;
mf->AddCustomCommandToTarget(target, no_byproducts, no_depends, commandLines,
cctype, no_comment, no_working_dir);
}
@@ -347,7 +351,7 @@ static void addLinkLibrary(cmMakefile* mf, std::string const& target,
std::ostringstream e;
e << "Attempt to add link library \"" << lib << "\" to target \"" << target
<< "\" which is not built in this directory.";
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
@@ -362,7 +366,7 @@ static void addLinkLibrary(cmMakefile* mf, std::string const& target,
<< " 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.";
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
}
t->AddLinkLibrary(*mf, lib, llt);
@@ -393,11 +397,12 @@ void CCONV cmAddLibrary(void* arg, const char* libname, int shared,
std::vector<std::string> srcs2;
int i;
for (i = 0; i < numSrcs; ++i) {
- srcs2.push_back(srcs[i]);
+ srcs2.emplace_back(srcs[i]);
}
- mf->AddLibrary(libname, (shared ? cmStateEnums::SHARED_LIBRARY
- : cmStateEnums::STATIC_LIBRARY),
- srcs2);
+ mf->AddLibrary(
+ libname,
+ (shared ? cmStateEnums::SHARED_LIBRARY : cmStateEnums::STATIC_LIBRARY),
+ srcs2);
}
char CCONV* cmExpandVariablesInString(void* arg, const char* source,
@@ -405,14 +410,9 @@ char CCONV* cmExpandVariablesInString(void* arg, const char* source,
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
std::string barf = source;
- std::string result = mf->ExpandVariablesInString(
- barf, (escapeQuotes ? true : false), (atOnly ? true : false));
- char* res = static_cast<char*>(malloc(result.size() + 1));
- if (!result.empty()) {
- strcpy(res, result.c_str());
- }
- res[result.size()] = '\0';
- return res;
+ std::string const& result =
+ mf->ExpandVariablesInString(barf, escapeQuotes != 0, atOnly != 0);
+ return strdup(result.c_str());
}
int CCONV cmExecuteCommand(void* arg, const char* name, int numArgs,
@@ -423,10 +423,9 @@ int CCONV cmExecuteCommand(void* arg, const char* name, int numArgs,
lff.Name = name;
for (int i = 0; i < numArgs; ++i) {
// Assume all arguments are quoted.
- lff.Arguments.push_back(
- cmListFileArgument(args[i], cmListFileArgument::Quoted, 0));
+ lff.Arguments.emplace_back(args[i], cmListFileArgument::Quoted, 0);
}
- cmExecutionStatus status;
+ cmExecutionStatus status(*mf);
return mf->ExecuteCommand(lff, status);
}
@@ -440,10 +439,10 @@ void CCONV cmExpandSourceListArguments(void* arg, int numArgs,
std::vector<std::string> result;
int i;
for (i = 0; i < numArgs; ++i) {
- result.push_back(args[i]);
+ result.emplace_back(args[i]);
}
int resargc = static_cast<int>(result.size());
- char** resargv = CM_NULLPTR;
+ char** resargv = nullptr;
if (resargc) {
resargv = (char**)malloc(resargc * sizeof(char*));
}
@@ -460,9 +459,7 @@ void CCONV cmFreeArguments(int argc, char** argv)
for (i = 0; i < argc; ++i) {
free(argv[i]);
}
- if (argv) {
- free(argv);
- }
+ free(argv);
}
int CCONV cmGetTotalArgumentSize(int argc, char** argv)
@@ -481,11 +478,7 @@ int CCONV cmGetTotalArgumentSize(int argc, char** argv)
// API for source files.
struct cmCPluginAPISourceFile
{
- cmCPluginAPISourceFile()
- : RealSourceFile(CM_NULLPTR)
- {
- }
- cmSourceFile* RealSourceFile;
+ cmSourceFile* RealSourceFile = nullptr;
std::string SourceName;
std::string SourceExtension;
std::string FullPath;
@@ -499,27 +492,30 @@ class cmCPluginAPISourceFileMap
: public std::map<cmSourceFile*, cmCPluginAPISourceFile*>
{
public:
- typedef std::map<cmSourceFile*, cmCPluginAPISourceFile*> derived;
- typedef derived::iterator iterator;
- typedef derived::value_type value_type;
+ using derived = std::map<cmSourceFile*, cmCPluginAPISourceFile*>;
+ using iterator = derived::iterator;
+ using value_type = derived::value_type;
+ cmCPluginAPISourceFileMap() = default;
~cmCPluginAPISourceFileMap()
{
- for (iterator i = this->begin(); i != this->end(); ++i) {
- delete i->second;
+ for (auto const& i : *this) {
+ delete i.second;
}
}
+ cmCPluginAPISourceFileMap(const cmCPluginAPISourceFileMap&) = delete;
+ cmCPluginAPISourceFileMap& operator=(const cmCPluginAPISourceFileMap&) =
+ delete;
};
cmCPluginAPISourceFileMap cmCPluginAPISourceFiles;
void* CCONV cmCreateSourceFile(void)
{
- return (void*)new cmCPluginAPISourceFile;
+ return new cmCPluginAPISourceFile;
}
void* CCONV cmCreateNewSourceFile(void*)
{
- cmCPluginAPISourceFile* sf = new cmCPluginAPISourceFile;
- return (void*)sf;
+ return new cmCPluginAPISourceFile;
}
void CCONV cmDestroySourceFile(void* arg)
@@ -537,12 +533,12 @@ void CCONV* cmGetSource(void* arg, const char* name)
cmMakefile* mf = static_cast<cmMakefile*>(arg);
if (cmSourceFile* rsf = mf->GetSource(name)) {
// Lookup the proxy source file object for this source.
- cmCPluginAPISourceFileMap::iterator i = cmCPluginAPISourceFiles.find(rsf);
+ auto i = cmCPluginAPISourceFiles.find(rsf);
if (i == cmCPluginAPISourceFiles.end()) {
// Create a proxy source file object for this source.
cmCPluginAPISourceFile* sf = new cmCPluginAPISourceFile;
sf->RealSourceFile = rsf;
- sf->FullPath = rsf->GetFullPath();
+ sf->FullPath = rsf->ResolveFullPath();
sf->SourceName =
cmSystemTools::GetFilenameWithoutLastExtension(sf->FullPath);
sf->SourceExtension =
@@ -552,9 +548,9 @@ void CCONV* cmGetSource(void* arg, const char* name)
cmCPluginAPISourceFileMap::value_type entry(rsf, sf);
i = cmCPluginAPISourceFiles.insert(entry).first;
}
- return (void*)i->second;
+ return i->second;
}
- return CM_NULLPTR;
+ return nullptr;
}
void* CCONV cmAddSource(void* arg, void* arg2)
@@ -562,15 +558,14 @@ void* CCONV cmAddSource(void* arg, void* arg2)
cmMakefile* mf = static_cast<cmMakefile*>(arg);
cmCPluginAPISourceFile* osf = static_cast<cmCPluginAPISourceFile*>(arg2);
if (osf->FullPath.empty()) {
- return CM_NULLPTR;
+ return nullptr;
}
// Create the real cmSourceFile instance and copy over saved information.
cmSourceFile* rsf = mf->GetOrCreateSource(osf->FullPath);
- rsf->GetProperties() = osf->Properties;
- for (std::vector<std::string>::iterator i = osf->Depends.begin();
- i != osf->Depends.end(); ++i) {
- rsf->AddDepend(*i);
+ rsf->SetProperties(osf->Properties);
+ for (std::string const& d : osf->Depends) {
+ rsf->AddDepend(d);
}
// Create the proxy for the real source file.
@@ -582,7 +577,7 @@ void* CCONV cmAddSource(void* arg, void* arg2)
// Store the proxy in the map so it can be re-used and deleted later.
cmCPluginAPISourceFiles[rsf] = sf;
- return (void*)sf;
+ return sf;
}
const char* CCONV cmSourceFileGetSourceName(void* arg)
@@ -615,7 +610,7 @@ int CCONV cmSourceFileGetPropertyAsBool(void* arg, const char* prop)
if (cmSourceFile* rsf = sf->RealSourceFile) {
return rsf->GetPropertyAsBool(prop) ? 1 : 0;
}
- return cmSystemTools::IsOn(cmSourceFileGetProperty(arg, prop)) ? 1 : 0;
+ return cmIsOn(cmSourceFileGetProperty(arg, prop)) ? 1 : 0;
}
void CCONV cmSourceFileSetProperty(void* arg, const char* prop,
@@ -638,7 +633,7 @@ void CCONV cmSourceFileAddDepend(void* arg, const char* depend)
if (cmSourceFile* rsf = sf->RealSourceFile) {
rsf->AddDepend(depend);
} else {
- sf->Depends.push_back(depend);
+ sf->Depends.emplace_back(depend);
}
}
@@ -658,10 +653,10 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir,
std::vector<std::string> headerExts;
int i;
for (i = 0; i < numSourceExtensions; ++i) {
- sourceExts.push_back(sourceExtensions[i]);
+ sourceExts.emplace_back(sourceExtensions[i]);
}
for (i = 0; i < numHeaderExtensions; ++i) {
- headerExts.push_back(headerExtensions[i]);
+ headerExts.emplace_back(headerExtensions[i]);
}
// Save the original name given.
@@ -674,7 +669,7 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir,
// First try and see whether the listed file can be found
// as is without extensions added on.
std::string hname = pathname;
- if (cmSystemTools::FileExists(hname.c_str())) {
+ if (cmSystemTools::FileExists(hname)) {
sf->SourceName = cmSystemTools::GetFilenamePath(name);
if (!sf->SourceName.empty()) {
sf->SourceName += "/";
@@ -696,26 +691,20 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir,
}
// Next, try the various source extensions
- for (std::vector<std::string>::const_iterator ext = sourceExts.begin();
- ext != sourceExts.end(); ++ext) {
- hname = pathname;
- hname += ".";
- hname += *ext;
- if (cmSystemTools::FileExists(hname.c_str())) {
- sf->SourceExtension = *ext;
+ for (std::string const& ext : sourceExts) {
+ hname = cmStrCat(pathname, '.', ext);
+ if (cmSystemTools::FileExists(hname)) {
+ sf->SourceExtension = ext;
sf->FullPath = hname;
return;
}
}
// Finally, try the various header extensions
- for (std::vector<std::string>::const_iterator ext = headerExts.begin();
- ext != headerExts.end(); ++ext) {
- hname = pathname;
- hname += ".";
- hname += *ext;
- if (cmSystemTools::FileExists(hname.c_str())) {
- sf->SourceExtension = *ext;
+ for (std::string const& ext : headerExts) {
+ hname = cmStrCat(pathname, '.', ext);
+ if (cmSystemTools::FileExists(hname)) {
+ sf->SourceExtension = ext;
sf->FullPath = hname;
return;
}
@@ -724,15 +713,13 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir,
std::ostringstream e;
e << "Cannot find source file \"" << pathname << "\"";
e << "\n\nTried extensions";
- for (std::vector<std::string>::const_iterator ext = sourceExts.begin();
- ext != sourceExts.end(); ++ext) {
- e << " ." << *ext;
+ for (std::string const& ext : sourceExts) {
+ e << " ." << ext;
}
- for (std::vector<std::string>::const_iterator ext = headerExts.begin();
- ext != headerExts.end(); ++ext) {
- e << " ." << *ext;
+ for (std::string const& ext : headerExts) {
+ e << " ." << ext;
}
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
}
void CCONV cmSourceFileSetName2(void* arg, const char* name, const char* dir,
@@ -763,25 +750,19 @@ void CCONV cmSourceFileSetName2(void* arg, const char* name, const char* dir,
char* CCONV cmGetFilenameWithoutExtension(const char* name)
{
std::string sres = cmSystemTools::GetFilenameWithoutExtension(name);
- char* result = (char*)malloc(sres.size() + 1);
- strcpy(result, sres.c_str());
- return result;
+ return strdup(sres.c_str());
}
char* CCONV cmGetFilenamePath(const char* name)
{
std::string sres = cmSystemTools::GetFilenamePath(name);
- char* result = (char*)malloc(sres.size() + 1);
- strcpy(result, sres.c_str());
- return result;
+ return strdup(sres.c_str());
}
char* CCONV cmCapitalized(const char* name)
{
std::string sres = cmSystemTools::Capitalized(name);
- char* result = (char*)malloc(sres.size() + 1);
- strcpy(result, sres.c_str());
- return result;
+ return strdup(sres.c_str());
}
void CCONV cmCopyFileIfDifferent(const char* name1, const char* name2)
diff --git a/Source/cmCPluginAPI.h b/Source/cmCPluginAPI.h
index 88b81c6c1..6a9514869 100644
--- a/Source/cmCPluginAPI.h
+++ b/Source/cmCPluginAPI.h
@@ -19,15 +19,16 @@ extern "C" {
#endif
#ifdef __WATCOMC__
-#define CCONV __cdecl
+# define CCONV __cdecl
#else
-#define CCONV
+# define CCONV
#endif
/*=========================================================================
this is the structure of function entry points that a plugin may call. This
structure must be kept in sync with the static decaled at the bottom of
cmCPLuginAPI.cxx
=========================================================================*/
+/* NOLINTNEXTLINE(modernize-use-using) */
typedef struct
{
/*=========================================================================
@@ -161,9 +162,9 @@ typedef struct
CM_PLUGIN_EXPORT should be used by plugins
=========================================================================*/
#ifdef _WIN32
-#define CM_PLUGIN_EXPORT __declspec(dllexport)
+# define CM_PLUGIN_EXPORT __declspec(dllexport)
#else
-#define CM_PLUGIN_EXPORT
+# define CM_PLUGIN_EXPORT
#endif
/*=========================================================================
@@ -194,12 +195,21 @@ define the different types of custom commands for a target
/*=========================================================================
Finally we define the key data structures and function prototypes
=========================================================================*/
+
+/* NOLINTNEXTLINE(modernize-use-using) */
typedef const char*(CCONV* CM_DOC_FUNCTION)();
+
+/* NOLINTNEXTLINE(modernize-use-using) */
typedef int(CCONV* CM_INITIAL_PASS_FUNCTION)(void* info, void* mf, int argc,
char* []);
+
+/* NOLINTNEXTLINE(modernize-use-using) */
typedef void(CCONV* CM_FINAL_PASS_FUNCTION)(void* info, void* mf);
+
+/* NOLINTNEXTLINE(modernize-use-using) */
typedef void(CCONV* CM_DESTRUCTOR_FUNCTION)(void* info);
+/* NOLINTNEXTLINE(modernize-use-using) */
typedef struct
{
unsigned long reserved1; /* Reserved for future use. DO NOT USE. */
@@ -216,6 +226,7 @@ typedef struct
void* ClientData;
} cmLoadedCommandInfo;
+/* NOLINTNEXTLINE(modernize-use-using) */
typedef void(CCONV* CM_INIT_FUNCTION)(cmLoadedCommandInfo*);
#ifdef __cplusplus
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index e2605561a..6eae26e4c 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -2,27 +2,37 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTest.h"
-#include "cm_curl.h"
-#include "cm_zlib.h"
-#include "cmsys/Base64.h"
-#include "cmsys/Directory.hxx"
-#include "cmsys/FStream.hxx"
-#include "cmsys/Glob.hxx"
-#include "cmsys/Process.h"
-#include "cmsys/String.hxx"
-#include "cmsys/SystemInformation.hxx"
-#include <ctype.h>
+#include <algorithm>
+#include <cctype>
+#include <chrono>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
#include <iostream>
#include <map>
#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <string>
-#include <time.h>
#include <utility>
#include <vector>
+#include "cmsys/Base64.h"
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/Process.h"
+#include "cmsys/SystemInformation.hxx"
+
+#include "cm_curl.h"
+#include "cm_zlib.h"
+#if defined(_WIN32)
+# include <windows.h> // IWYU pragma: keep
+#else
+# include <unistd.h> // IWYU pragma: keep
+#endif
+
+#include <cm/memory>
+
#include "cmAlgorithms.h"
#include "cmCTestBuildAndTestHandler.h"
#include "cmCTestBuildHandler.h"
@@ -36,7 +46,6 @@
#include "cmCTestTestHandler.h"
#include "cmCTestUpdateHandler.h"
#include "cmCTestUploadHandler.h"
-#include "cmCurl.h"
#include "cmDynamicLoader.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
@@ -45,37 +54,175 @@
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
#include "cmVersionConfig.h"
#include "cmXMLWriter.h"
-#include "cm_auto_ptr.hxx"
#include "cmake.h"
#if defined(__BEOS__) || defined(__HAIKU__)
-#include <be/kernel/OS.h> /* disable_debugger() API. */
+# include <be/kernel/OS.h> /* disable_debugger() API. */
#endif
-#define DEBUGOUT \
- std::cout << __LINE__ << " "; \
- std::cout
-#define DEBUGERR \
- std::cerr << __LINE__ << " "; \
- std::cerr
+struct cmCTest::Private
+{
+ /** Representation of one part. */
+ struct PartInfo
+ {
+ void SetName(const std::string& name) { this->Name = name; }
+ const std::string& GetName() const { return this->Name; }
+
+ void Enable() { this->Enabled = true; }
+ explicit operator bool() const { return this->Enabled; }
+
+ std::vector<std::string> SubmitFiles;
+
+ private:
+ bool Enabled = false;
+ std::string Name;
+ };
+
+ int RepeatTests = 1; // default to run each test once
+ bool RepeatUntilFail = false;
+ std::string ConfigType;
+ std::string ScheduleType;
+ std::chrono::system_clock::time_point StopTime;
+ bool TestProgressOutput = false;
+ bool Verbose = false;
+ bool ExtraVerbose = false;
+ bool ProduceXML = false;
+ bool LabelSummary = true;
+ bool SubprojectSummary = true;
+ bool UseHTTP10 = false;
+ bool PrintLabels = false;
+ bool Failover = false;
+
+ bool FlushTestProgressLine = false;
+
+ bool ForceNewCTestProcess = false;
+
+ bool RunConfigurationScript = false;
+
+ // these are helper classes
+ cmCTestBuildHandler BuildHandler;
+ cmCTestBuildAndTestHandler BuildAndTestHandler;
+ cmCTestCoverageHandler CoverageHandler;
+ cmCTestScriptHandler ScriptHandler;
+ cmCTestTestHandler TestHandler;
+ cmCTestUpdateHandler UpdateHandler;
+ cmCTestConfigureHandler ConfigureHandler;
+ cmCTestMemCheckHandler MemCheckHandler;
+ cmCTestSubmitHandler SubmitHandler;
+ cmCTestUploadHandler UploadHandler;
+
+ std::vector<cmCTestGenericHandler*> GetTestingHandlers()
+ {
+ return { &this->BuildHandler, &this->BuildAndTestHandler,
+ &this->CoverageHandler, &this->ScriptHandler,
+ &this->TestHandler, &this->UpdateHandler,
+ &this->ConfigureHandler, &this->MemCheckHandler,
+ &this->SubmitHandler, &this->UploadHandler };
+ }
+
+ std::map<std::string, cmCTestGenericHandler*> GetNamedTestingHandlers()
+ {
+ return { { "build", &this->BuildHandler },
+ { "buildtest", &this->BuildAndTestHandler },
+ { "coverage", &this->CoverageHandler },
+ { "script", &this->ScriptHandler },
+ { "test", &this->TestHandler },
+ { "update", &this->UpdateHandler },
+ { "configure", &this->ConfigureHandler },
+ { "memcheck", &this->MemCheckHandler },
+ { "submit", &this->SubmitHandler },
+ { "upload", &this->UploadHandler } };
+ }
+
+ bool ShowOnly = false;
+ bool OutputAsJson = false;
+ int OutputAsJsonVersion = 1;
+
+ // 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
+ // affecting any higher-precedence settings.
+ std::map<std::string, std::string> CTestConfiguration;
+ std::map<std::string, std::string> CTestConfigurationOverwrites;
+
+ PartInfo Parts[PartCount];
+ std::map<std::string, Part> PartMap;
+
+ std::string CurrentTag;
+ bool TomorrowTag = false;
+
+ int TestModel = cmCTest::EXPERIMENTAL;
+ std::string SpecificGroup;
+
+ cmDuration TimeOut = cmDuration::zero();
+
+ cmDuration GlobalTimeout = cmDuration::zero();
+
+ int MaxTestNameWidth = 30;
+
+ int ParallelLevel = 1;
+ bool ParallelLevelSetInCli = false;
+
+ unsigned long TestLoad = 0;
+
+ int CompatibilityMode;
+
+ // information for the --build-and-test options
+ std::string BinaryDir;
+
+ std::string NotesFiles;
+
+ bool InteractiveDebugMode = true;
+
+ bool ShortDateFormat = true;
+
+ bool CompressXMLFiles = false;
+ bool CompressTestOutput = true;
+
+ // By default we write output to the process output streams.
+ std::ostream* StreamOut = &std::cout;
+ std::ostream* StreamErr = &std::cerr;
+
+ bool SuppressUpdatingCTestConfiguration = false;
+
+ bool Debug = false;
+ bool ShowLineNumbers = false;
+ bool Quiet = false;
+
+ std::string BuildID;
+
+ std::vector<std::string> InitialCommandLineArguments;
+
+ int SubmitIndex = 0;
+
+ cmGeneratedFileStream* OutputLogFile = nullptr;
+ int OutputLogFileLastTag = -1;
+
+ bool OutputTestOutputOnTestFailure = false;
+ bool OutputColorCode = cmCTest::ColoredOutputSupportedByConsole();
+
+ std::map<std::string, std::string> Definitions;
+};
struct tm* cmCTest::GetNightlyTime(std::string const& str, bool tomorrowtag)
{
struct tm* lctime;
- time_t tctime = time(CM_NULLPTR);
+ time_t tctime = time(nullptr);
lctime = gmtime(&tctime);
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", lctime->tm_year + 1900, lctime->tm_mon + 1,
lctime->tm_mday, str.c_str());
- cmCTestLog(this, OUTPUT, "Determine Nightly Start Time"
- << std::endl
- << " Specified time: " << str << std::endl);
+ cmCTestLog(this, OUTPUT,
+ "Determine Nightly Start Time" << std::endl
+ << " Specified time: " << str
+ << std::endl);
// Convert the nightly start time to seconds. Since we are
// providing only a time and a timezone, the current date of
// the local machine is assumed. Consequently, nightlySeconds
@@ -84,7 +231,7 @@ struct tm* cmCTest::GetNightlyTime(std::string const& str, bool tomorrowtag)
// As such, this time may be in the past or in the future.
time_t ntime = curl_getdate(buf, &tctime);
cmCTestLog(this, DEBUG, " Get curl time: " << ntime << std::endl);
- tctime = time(CM_NULLPTR);
+ tctime = time(nullptr);
cmCTestLog(this, DEBUG, " Get the current time: " << tctime << std::endl);
const int dayLength = 24 * 60 * 60;
@@ -97,16 +244,17 @@ struct tm* cmCTest::GetNightlyTime(std::string const& str, bool tomorrowtag)
// time of the current open dashboard
ntime -= dayLength;
cmCTestLog(this, DEBUG, "Pick yesterday" << std::endl);
- cmCTestLog(this, DEBUG, " Future time, subtract day: " << ntime
- << std::endl);
+ cmCTestLog(this, DEBUG,
+ " Future time, subtract day: " << ntime << std::endl);
}
while (tctime > (ntime + dayLength)) {
ntime += dayLength;
cmCTestLog(this, DEBUG, " Past time, add day: " << ntime << std::endl);
}
cmCTestLog(this, DEBUG, "nightlySeconds: " << ntime << std::endl);
- cmCTestLog(this, DEBUG, " Current time: " << tctime << " Nightly time: "
- << ntime << std::endl);
+ cmCTestLog(this, DEBUG,
+ " Current time: " << tctime << " Nightly time: " << ntime
+ << std::endl);
if (tomorrowtag) {
cmCTestLog(this, OUTPUT, " Use future tag, Add a day" << std::endl);
ntime += dayLength;
@@ -115,6 +263,11 @@ struct tm* cmCTest::GetNightlyTime(std::string const& str, bool tomorrowtag)
return lctime;
}
+bool cmCTest::GetTomorrowTag() const
+{
+ return this->Impl->TomorrowTag;
+}
+
std::string cmCTest::CleanString(const std::string& str)
{
std::string::size_type spos = str.find_first_not_of(" \n\t\r\f\v");
@@ -130,11 +283,11 @@ std::string cmCTest::CleanString(const std::string& str)
std::string cmCTest::CurrentTime()
{
- time_t currenttime = time(CM_NULLPTR);
+ time_t currenttime = time(nullptr);
struct tm* t = localtime(&currenttime);
// return ::CleanString(ctime(&currenttime));
char current_time[1024];
- if (this->ShortDateFormat) {
+ if (this->Impl->ShortDateFormat) {
strftime(current_time, 1000, "%b %d %H:%M %Z", t);
} else {
strftime(current_time, 1000, "%a %b %d %H:%M:%S %Z %Y", t);
@@ -146,101 +299,19 @@ std::string cmCTest::CurrentTime()
std::string cmCTest::GetCostDataFile()
{
std::string fname = this->GetCTestConfiguration("CostDataFile");
- if (fname == "") {
+ if (fname.empty()) {
fname = this->GetBinaryDir() + "/Testing/Temporary/CTestCostData.txt";
}
return fname;
}
-#ifdef CMAKE_BUILD_WITH_CMAKE
-static size_t HTTPResponseCallback(void* ptr, size_t size, size_t nmemb,
- void* data)
-{
- int realsize = (int)(size * nmemb);
-
- std::string* response = static_cast<std::string*>(data);
- const char* chPtr = static_cast<char*>(ptr);
- *response += chPtr;
-
- return realsize;
-}
-
-int cmCTest::HTTPRequest(std::string url, HTTPMethod method,
- std::string& response, std::string const& fields,
- std::string const& putFile, int timeout)
-{
- CURL* curl;
- FILE* file;
- ::curl_global_init(CURL_GLOBAL_ALL);
- curl = ::curl_easy_init();
- cmCurlSetCAInfo(curl);
-
- // set request options based on method
- switch (method) {
- case cmCTest::HTTP_POST:
- ::curl_easy_setopt(curl, CURLOPT_POST, 1);
- ::curl_easy_setopt(curl, CURLOPT_POSTFIELDS, fields.c_str());
- break;
- case cmCTest::HTTP_PUT:
- if (!cmSystemTools::FileExists(putFile.c_str())) {
- response = "Error: File ";
- response += putFile + " does not exist.\n";
- return -1;
- }
- ::curl_easy_setopt(curl, CURLOPT_PUT, 1);
- file = cmsys::SystemTools::Fopen(putFile, "rb");
- ::curl_easy_setopt(curl, CURLOPT_INFILE, file);
- // fall through to append GET fields
- case cmCTest::HTTP_GET:
- if (!fields.empty()) {
- url += "?" + fields;
- }
- break;
- }
-
- ::curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
- ::curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
- ::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
-
- // set response options
- ::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPResponseCallback);
- ::curl_easy_setopt(curl, CURLOPT_FILE, (void*)&response);
- ::curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
-
- CURLcode res = ::curl_easy_perform(curl);
-
- ::curl_easy_cleanup(curl);
- ::curl_global_cleanup();
-
- return static_cast<int>(res);
-}
-#endif
-
-std::string cmCTest::MakeURLSafe(const std::string& str)
-{
- std::ostringstream ost;
- char buffer[10];
- for (std::string::size_type pos = 0; pos < str.size(); pos++) {
- unsigned char ch = str[pos];
- if ((ch > 126 || ch < 32 || ch == '&' || ch == '%' || ch == '+' ||
- ch == '=' || ch == '@') &&
- ch != 9) {
- sprintf(buffer, "%02x;", (unsigned int)ch);
- ost << buffer;
- } else {
- ost << ch;
- }
- }
- return ost.str();
-}
-
std::string cmCTest::DecodeURL(const std::string& in)
{
std::string out;
for (const char* c = in.c_str(); *c; ++c) {
if (*c == '%' && isxdigit(*(c + 1)) && isxdigit(*(c + 2))) {
char buf[3] = { *(c + 1), *(c + 2), 0 };
- out.append(1, char(strtoul(buf, CM_NULLPTR, 16)));
+ out.append(1, char(strtoul(buf, nullptr, 16)));
c += 2;
} else {
out.append(1, *c);
@@ -250,88 +321,38 @@ std::string cmCTest::DecodeURL(const std::string& in)
}
cmCTest::cmCTest()
-{
- this->LabelSummary = true;
- this->ParallelLevel = 1;
- this->ParallelLevelSetInCli = false;
- this->TestLoad = 0;
- this->SubmitIndex = 0;
- this->Failover = false;
- this->BatchJobs = false;
- this->ForceNewCTestProcess = false;
- this->TomorrowTag = false;
- this->Verbose = false;
-
- this->Debug = false;
- this->ShowLineNumbers = false;
- this->Quiet = false;
- this->ExtraVerbose = false;
- this->ProduceXML = false;
- this->ShowOnly = false;
- this->RunConfigurationScript = false;
- this->UseHTTP10 = false;
- this->PrintLabels = false;
- this->CompressTestOutput = true;
- this->TestModel = cmCTest::EXPERIMENTAL;
- this->MaxTestNameWidth = 30;
- this->InteractiveDebugMode = true;
- this->TimeOut = 0;
- this->GlobalTimeout = 0;
- this->LastStopTimeout = 24 * 60 * 60;
- this->CompressXMLFiles = false;
- this->CTestConfigFile = "";
- this->ScheduleType = "";
- this->StopTime = "";
- this->NextDayStopTime = false;
- this->OutputLogFile = CM_NULLPTR;
- this->OutputLogFileLastTag = -1;
- this->SuppressUpdatingCTestConfiguration = false;
- this->DartVersion = 1;
- this->DropSiteCDash = false;
- this->OutputTestOutputOnTestFailure = false;
- this->RepeatTests = 1; // default to run each test once
- this->RepeatUntilFail = false;
- std::string outOnFail;
- if (cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE", outOnFail)) {
- this->OutputTestOutputOnTestFailure =
- !cmSystemTools::IsOff(outOnFail.c_str());
- }
- this->InitStreams();
-
- this->Parts[PartStart].SetName("Start");
- this->Parts[PartUpdate].SetName("Update");
- this->Parts[PartConfigure].SetName("Configure");
- this->Parts[PartBuild].SetName("Build");
- this->Parts[PartTest].SetName("Test");
- this->Parts[PartCoverage].SetName("Coverage");
- this->Parts[PartMemCheck].SetName("MemCheck");
- this->Parts[PartSubmit].SetName("Submit");
- this->Parts[PartNotes].SetName("Notes");
- this->Parts[PartExtraFiles].SetName("ExtraFiles");
- this->Parts[PartUpload].SetName("Upload");
+ : Impl(new Private)
+{
+ std::string envValue;
+ if (cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE", envValue)) {
+ this->Impl->OutputTestOutputOnTestFailure = !cmIsOff(envValue);
+ }
+ envValue.clear();
+ if (cmSystemTools::GetEnv("CTEST_PROGRESS_OUTPUT", envValue)) {
+ this->Impl->TestProgressOutput = !cmIsOff(envValue);
+ }
+
+ this->Impl->Parts[PartStart].SetName("Start");
+ this->Impl->Parts[PartUpdate].SetName("Update");
+ this->Impl->Parts[PartConfigure].SetName("Configure");
+ this->Impl->Parts[PartBuild].SetName("Build");
+ this->Impl->Parts[PartTest].SetName("Test");
+ this->Impl->Parts[PartCoverage].SetName("Coverage");
+ this->Impl->Parts[PartMemCheck].SetName("MemCheck");
+ this->Impl->Parts[PartSubmit].SetName("Submit");
+ this->Impl->Parts[PartNotes].SetName("Notes");
+ this->Impl->Parts[PartExtraFiles].SetName("ExtraFiles");
+ this->Impl->Parts[PartUpload].SetName("Upload");
+ this->Impl->Parts[PartDone].SetName("Done");
// Fill the part name-to-id map.
for (Part p = PartStart; p != PartCount; p = Part(p + 1)) {
- this->PartMap[cmSystemTools::LowerCase(this->Parts[p].GetName())] = p;
+ this->Impl
+ ->PartMap[cmSystemTools::LowerCase(this->Impl->Parts[p].GetName())] = p;
}
- this->ShortDateFormat = true;
-
- this->TestingHandlers["build"] = new cmCTestBuildHandler;
- this->TestingHandlers["buildtest"] = new cmCTestBuildAndTestHandler;
- this->TestingHandlers["coverage"] = new cmCTestCoverageHandler;
- this->TestingHandlers["script"] = new cmCTestScriptHandler;
- this->TestingHandlers["test"] = new cmCTestTestHandler;
- this->TestingHandlers["update"] = new cmCTestUpdateHandler;
- this->TestingHandlers["configure"] = new cmCTestConfigureHandler;
- this->TestingHandlers["memcheck"] = new cmCTestMemCheckHandler;
- this->TestingHandlers["submit"] = new cmCTestSubmitHandler;
- this->TestingHandlers["upload"] = new cmCTestUploadHandler;
-
- cmCTest::t_TestingHandlers::iterator it;
- for (it = this->TestingHandlers.begin(); it != this->TestingHandlers.end();
- ++it) {
- it->second->SetCTestInstance(this);
+ for (auto& handler : this->Impl->GetTestingHandlers()) {
+ handler->SetCTestInstance(this);
}
// Make sure we can capture the build tool output.
@@ -340,31 +361,40 @@ cmCTest::cmCTest()
cmCTest::~cmCTest()
{
- cmDeleteAll(this->TestingHandlers);
- this->SetOutputLogFileName(CM_NULLPTR);
+ delete this->Impl->OutputLogFile;
+}
+
+int cmCTest::GetParallelLevel() const
+{
+ return this->Impl->ParallelLevel;
}
void cmCTest::SetParallelLevel(int level)
{
- this->ParallelLevel = level < 1 ? 1 : level;
+ this->Impl->ParallelLevel = level < 1 ? 1 : level;
+}
+
+unsigned long cmCTest::GetTestLoad() const
+{
+ return this->Impl->TestLoad;
}
void cmCTest::SetTestLoad(unsigned long load)
{
- this->TestLoad = load;
+ this->Impl->TestLoad = load;
}
bool cmCTest::ShouldCompressTestOutput()
{
- return this->CompressTestOutput;
+ return this->Impl->CompressTestOutput;
}
cmCTest::Part cmCTest::GetPartFromName(const char* name)
{
// Look up by lower-case to make names case-insensitive.
std::string lower_name = cmSystemTools::LowerCase(name);
- PartMapType::const_iterator i = this->PartMap.find(lower_name);
- if (i != this->PartMap.end()) {
+ auto const i = this->Impl->PartMap.find(lower_name);
+ if (i != this->Impl->PartMap.end()) {
return i->second;
}
@@ -380,29 +410,30 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
}
cmCTestOptionalLog(this, DEBUG, "Here: " << __LINE__ << std::endl, quiet);
- if (!this->InteractiveDebugMode) {
+ if (!this->Impl->InteractiveDebugMode) {
this->BlockTestErrorDiagnostics();
} else {
cmSystemTools::PutEnv("CTEST_INTERACTIVE_DEBUG_MODE=1");
}
- this->BinaryDir = binary_dir;
- cmSystemTools::ConvertToUnixSlashes(this->BinaryDir);
+ this->Impl->BinaryDir = binary_dir;
+ cmSystemTools::ConvertToUnixSlashes(this->Impl->BinaryDir);
this->UpdateCTestConfiguration();
cmCTestOptionalLog(this, DEBUG, "Here: " << __LINE__ << std::endl, quiet);
- if (this->ProduceXML) {
+ if (this->Impl->ProduceXML) {
cmCTestOptionalLog(this, DEBUG, "Here: " << __LINE__ << std::endl, quiet);
- cmCTestOptionalLog(
- this, OUTPUT, " Site: "
- << this->GetCTestConfiguration("Site") << std::endl
- << " Build name: "
- << cmCTest::SafeBuildIdField(this->GetCTestConfiguration("BuildName"))
- << std::endl,
- quiet);
+ cmCTestOptionalLog(this, OUTPUT,
+ " Site: "
+ << this->GetCTestConfiguration("Site") << std::endl
+ << " Build name: "
+ << cmCTest::SafeBuildIdField(
+ this->GetCTestConfiguration("BuildName"))
+ << std::endl,
+ quiet);
cmCTestOptionalLog(this, DEBUG, "Produce XML is on" << std::endl, quiet);
- if (this->TestModel == cmCTest::NIGHTLY &&
+ if (this->Impl->TestModel == cmCTest::NIGHTLY &&
this->GetCTestConfiguration("NightlyStartTime").empty()) {
cmCTestOptionalLog(
this, WARNING,
@@ -416,36 +447,36 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
}
}
- cmake cm(cmake::RoleScript);
+ cmake cm(cmake::RoleScript, cmState::CTest);
cm.SetHomeDirectory("");
cm.SetHomeOutputDirectory("");
cm.GetCurrentSnapshot().SetDefaultDefinitions();
cmGlobalGenerator gg(&cm);
- CM_AUTO_PTR<cmMakefile> mf(new cmMakefile(&gg, cm.GetCurrentSnapshot()));
- if (!this->ReadCustomConfigurationFileTree(this->BinaryDir.c_str(),
- mf.get())) {
+ cmMakefile mf(&gg, cm.GetCurrentSnapshot());
+ if (!this->ReadCustomConfigurationFileTree(this->Impl->BinaryDir.c_str(),
+ &mf)) {
cmCTestOptionalLog(
this, DEBUG, "Cannot find custom configuration file tree" << std::endl,
quiet);
return 0;
}
- if (this->ProduceXML) {
+ if (this->Impl->ProduceXML) {
// Verify "Testing" directory exists:
//
- std::string testingDir = this->BinaryDir + "/Testing";
- if (cmSystemTools::FileExists(testingDir.c_str())) {
+ std::string testingDir = this->Impl->BinaryDir + "/Testing";
+ if (cmSystemTools::FileExists(testingDir)) {
if (!cmSystemTools::FileIsDirectory(testingDir)) {
- cmCTestLog(this, ERROR_MESSAGE, "File "
- << testingDir
- << " is in the place of the testing directory"
- << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "File " << testingDir
+ << " is in the place of the testing directory"
+ << std::endl);
return 0;
}
} else {
- if (!cmSystemTools::MakeDirectory(testingDir.c_str())) {
- cmCTestLog(this, ERROR_MESSAGE, "Cannot create directory "
- << testingDir << std::endl);
+ if (!cmSystemTools::MakeDirectory(testingDir)) {
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Cannot create directory " << testingDir << std::endl);
return 0;
}
}
@@ -462,8 +493,8 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
std::string tag;
if (createNewTag) {
- time_t tctime = time(CM_NULLPTR);
- if (this->TomorrowTag) {
+ time_t tctime = time(nullptr);
+ if (this->Impl->TomorrowTag) {
tctime += (24 * 60 * 60);
}
struct tm* lctime = gmtime(&tctime);
@@ -477,26 +508,32 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
&min);
if (year != lctime->tm_year + 1900 || mon != lctime->tm_mon + 1 ||
day != lctime->tm_mday) {
- tag = "";
+ tag.clear();
}
- std::string tagmode;
- if (cmSystemTools::GetLineFromStream(tfin, tagmode)) {
- if (tagmode.size() > 4 && !this->Parts[PartStart]) {
- this->TestModel = cmCTest::GetTestModelFromString(tagmode.c_str());
- }
+ std::string group;
+ if (cmSystemTools::GetLineFromStream(tfin, group) &&
+ !this->Impl->Parts[PartStart] && !command) {
+ this->Impl->SpecificGroup = group;
+ }
+ std::string model;
+ if (cmSystemTools::GetLineFromStream(tfin, model) &&
+ !this->Impl->Parts[PartStart] && !command) {
+ this->Impl->TestModel = GetTestModelFromString(model.c_str());
}
tfin.close();
}
- if (tag.empty() || (CM_NULLPTR != command) || this->Parts[PartStart]) {
+ if (tag.empty() || (nullptr != command) ||
+ this->Impl->Parts[PartStart]) {
cmCTestOptionalLog(
this, DEBUG,
"TestModel: " << this->GetTestModelString() << std::endl, quiet);
- cmCTestOptionalLog(
- this, DEBUG, "TestModel: " << this->TestModel << std::endl, quiet);
- if (this->TestModel == cmCTest::NIGHTLY) {
+ cmCTestOptionalLog(this, DEBUG,
+ "TestModel: " << this->Impl->TestModel << std::endl,
+ quiet);
+ if (this->Impl->TestModel == cmCTest::NIGHTLY) {
lctime = this->GetNightlyTime(
this->GetCTestConfiguration("NightlyStartTime"),
- this->TomorrowTag);
+ this->Impl->TomorrowTag);
}
char datestring[100];
sprintf(datestring, "%04d%02d%02d-%02d%02d", lctime->tm_year + 1900,
@@ -507,34 +544,88 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
if (ofs) {
ofs << tag << std::endl;
ofs << this->GetTestModelString() << std::endl;
+ switch (this->Impl->TestModel) {
+ case cmCTest::EXPERIMENTAL:
+ ofs << "Experimental" << std::endl;
+ break;
+ case cmCTest::NIGHTLY:
+ ofs << "Nightly" << std::endl;
+ break;
+ case cmCTest::CONTINUOUS:
+ ofs << "Continuous" << std::endl;
+ break;
+ }
}
ofs.close();
- if (CM_NULLPTR == command) {
- cmCTestOptionalLog(this, OUTPUT, "Create new tag: "
- << tag << " - " << this->GetTestModelString()
- << std::endl,
+ if (nullptr == command) {
+ cmCTestOptionalLog(this, OUTPUT,
+ "Create new tag: " << tag << " - "
+ << this->GetTestModelString()
+ << std::endl,
quiet);
}
}
} else {
+ std::string group;
+ std::string modelStr;
+ int model = cmCTest::UNKNOWN;
+
if (tfin) {
cmSystemTools::GetLineFromStream(tfin, tag);
+ cmSystemTools::GetLineFromStream(tfin, group);
+ if (cmSystemTools::GetLineFromStream(tfin, modelStr)) {
+ model = GetTestModelFromString(modelStr.c_str());
+ }
tfin.close();
}
if (tag.empty()) {
- cmCTestLog(this, ERROR_MESSAGE, "Cannot read existing TAG file in "
- << testingDir << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Cannot read existing TAG file in " << testingDir
+ << std::endl);
return 0;
}
- cmCTestOptionalLog(this, OUTPUT, " Use existing tag: "
- << tag << " - " << this->GetTestModelString()
- << std::endl,
+ if (this->Impl->TestModel == cmCTest::UNKNOWN) {
+ if (model == cmCTest::UNKNOWN) {
+ cmCTestLog(this, ERROR_MESSAGE,
+ "TAG file does not contain model and "
+ "no model specified in start command"
+ << std::endl);
+ return 0;
+ }
+
+ this->SetTestModel(model);
+ }
+
+ if (model != this->Impl->TestModel && model != cmCTest::UNKNOWN &&
+ this->Impl->TestModel != cmCTest::UNKNOWN) {
+ cmCTestOptionalLog(this, WARNING,
+ "Model given in TAG does not match "
+ "model given in ctest_start()"
+ << std::endl,
+ quiet);
+ }
+
+ if (!this->Impl->SpecificGroup.empty() &&
+ group != this->Impl->SpecificGroup) {
+ cmCTestOptionalLog(this, WARNING,
+ "Group given in TAG does not match "
+ "group given in ctest_start()"
+ << std::endl,
+ quiet);
+ } else {
+ this->Impl->SpecificGroup = group;
+ }
+
+ cmCTestOptionalLog(this, OUTPUT,
+ " Use existing tag: " << tag << " - "
+ << this->GetTestModelString()
+ << std::endl,
quiet);
}
- this->CurrentTag = tag;
+ this->Impl->CurrentTag = tag;
}
return 1;
@@ -544,49 +635,37 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command)
{
std::string src_dir = this->GetCTestConfiguration("SourceDirectory");
std::string bld_dir = this->GetCTestConfiguration("BuildDirectory");
- this->DartVersion = 1;
- this->DropSiteCDash = false;
+ this->Impl->BuildID = "";
for (Part p = PartStart; p != PartCount; p = Part(p + 1)) {
- this->Parts[p].SubmitFiles.clear();
+ this->Impl->Parts[p].SubmitFiles.clear();
}
cmMakefile* mf = command->GetMakefile();
std::string fname;
- std::string src_dir_fname = src_dir;
- src_dir_fname += "/CTestConfig.cmake";
+ std::string src_dir_fname = cmStrCat(src_dir, "/CTestConfig.cmake");
cmSystemTools::ConvertToUnixSlashes(src_dir_fname);
- std::string bld_dir_fname = bld_dir;
- bld_dir_fname += "/CTestConfig.cmake";
+ std::string bld_dir_fname = cmStrCat(bld_dir, "/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;
}
if (!fname.empty()) {
- cmCTestOptionalLog(this, OUTPUT, " Reading ctest configuration file: "
- << fname << std::endl,
+ cmCTestOptionalLog(this, OUTPUT,
+ " Reading ctest configuration file: " << fname
+ << std::endl,
command->ShouldBeQuiet());
- bool readit = mf->ReadDependentFile(fname.c_str());
+ bool readit = mf->ReadDependentFile(fname);
if (!readit) {
- std::string m = "Could not find include file: ";
- m += fname;
+ std::string m = cmStrCat("Could not find include file: ", fname);
command->SetError(m);
return false;
}
- } else {
- cmCTestOptionalLog(this, WARNING,
- "Cannot locate CTest configuration: in BuildDirectory: "
- << bld_dir_fname << std::endl,
- command->ShouldBeQuiet());
- cmCTestOptionalLog(
- this, WARNING, "Cannot locate CTest configuration: in SourceDirectory: "
- << src_dir_fname << std::endl,
- command->ShouldBeQuiet());
}
this->SetCTestConfigurationFromCMakeVariable(mf, "NightlyStartTime",
@@ -596,52 +675,38 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command)
command->ShouldBeQuiet());
this->SetCTestConfigurationFromCMakeVariable(
mf, "BuildName", "CTEST_BUILD_NAME", command->ShouldBeQuiet());
- const char* dartVersion = mf->GetDefinition("CTEST_DART_SERVER_VERSION");
- if (dartVersion) {
- this->DartVersion = atoi(dartVersion);
- if (this->DartVersion < 0) {
- cmCTestLog(this, ERROR_MESSAGE, "Invalid Dart server version: "
- << dartVersion << ". Please specify the version number."
- << std::endl);
- return false;
- }
- }
- this->DropSiteCDash = mf->IsOn("CTEST_DROP_SITE_CDASH");
if (!this->Initialize(bld_dir.c_str(), command)) {
return false;
}
- cmCTestOptionalLog(this, OUTPUT, " Use "
- << this->GetTestModelString()
- << " tag: " << this->GetCurrentTag() << std::endl,
+ cmCTestOptionalLog(this, OUTPUT,
+ " Use " << this->GetTestModelString() << " tag: "
+ << this->GetCurrentTag() << std::endl,
command->ShouldBeQuiet());
return true;
}
bool cmCTest::UpdateCTestConfiguration()
{
- if (this->SuppressUpdatingCTestConfiguration) {
+ if (this->Impl->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->Impl->BinaryDir + "/CTestConfiguration.ini";
+ if (!cmSystemTools::FileExists(fileName)) {
+ fileName = this->Impl->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
- << std::endl);
+ if (this->Impl->ProduceXML) {
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Cannot find file: " << fileName << std::endl);
return false;
}
} else {
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Parse Config file:" << fileName
- << "\n");
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ "Parse Config file:" << fileName << "\n");
// parse the dart test file
cmsys::ifstream fin(fileName.c_str());
@@ -658,7 +723,7 @@ bool cmCTest::UpdateCTestConfiguration()
if (line.empty()) {
continue;
}
- while (fin && (line[line.size() - 1] == '\\')) {
+ while (fin && (line.back() == '\\')) {
line = line.substr(0, line.size() - 1);
buffer[0] = 0;
fin.getline(buffer, 1023);
@@ -674,28 +739,29 @@ bool cmCTest::UpdateCTestConfiguration()
}
std::string key = line.substr(0, cpos);
std::string value = cmCTest::CleanString(line.substr(cpos + 1));
- this->CTestConfiguration[key] = value;
+ this->Impl->CTestConfiguration[key] = value;
}
fin.close();
}
if (!this->GetCTestConfiguration("BuildDirectory").empty()) {
- this->BinaryDir = this->GetCTestConfiguration("BuildDirectory");
- cmSystemTools::ChangeDirectory(this->BinaryDir);
+ this->Impl->BinaryDir = this->GetCTestConfiguration("BuildDirectory");
+ cmSystemTools::ChangeDirectory(this->Impl->BinaryDir);
}
- this->TimeOut = atoi(this->GetCTestConfiguration("TimeOut").c_str());
+ this->Impl->TimeOut =
+ std::chrono::seconds(atoi(this->GetCTestConfiguration("TimeOut").c_str()));
std::string const& testLoad = this->GetCTestConfiguration("TestLoad");
if (!testLoad.empty()) {
unsigned long load;
- if (cmSystemTools::StringToULong(testLoad.c_str(), &load)) {
+ if (cmStrToULong(testLoad, &load)) {
this->SetTestLoad(load);
} else {
cmCTestLog(this, WARNING,
"Invalid value for 'Test Load' : " << testLoad << std::endl);
}
}
- if (this->ProduceXML) {
- this->CompressXMLFiles = cmSystemTools::IsOn(
- this->GetCTestConfiguration("CompressSubmission").c_str());
+ if (this->Impl->ProduceXML) {
+ this->Impl->CompressXMLFiles =
+ cmIsOn(this->GetCTestConfiguration("CompressSubmission"));
}
return true;
}
@@ -713,26 +779,32 @@ void cmCTest::BlockTestErrorDiagnostics()
void cmCTest::SetTestModel(int mode)
{
- this->InteractiveDebugMode = false;
- this->TestModel = mode;
+ this->Impl->InteractiveDebugMode = false;
+ this->Impl->TestModel = mode;
+}
+
+int cmCTest::GetTestModel() const
+{
+ return this->Impl->TestModel;
}
bool cmCTest::SetTest(const char* ttype, bool report)
{
if (cmSystemTools::LowerCase(ttype) == "all") {
for (Part p = PartStart; p != PartCount; p = Part(p + 1)) {
- this->Parts[p].Enable();
+ this->Impl->Parts[p].Enable();
}
return true;
}
Part p = this->GetPartFromName(ttype);
if (p != PartCount) {
- this->Parts[p].Enable();
+ this->Impl->Parts[p].Enable();
return true;
}
if (report) {
- cmCTestLog(this, ERROR_MESSAGE, "Don't know about test \""
- << ttype << "\" yet..." << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Don't know about test \"" << ttype << "\" yet..."
+ << std::endl);
}
return false;
}
@@ -744,33 +816,34 @@ void cmCTest::Finalize()
bool cmCTest::OpenOutputFile(const std::string& path, const std::string& name,
cmGeneratedFileStream& stream, bool compress)
{
- std::string testingDir = this->BinaryDir + "/Testing";
+ std::string testingDir = this->Impl->BinaryDir + "/Testing";
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"
- << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "File " << testingDir
+ << " is in the place of the testing directory"
+ << std::endl);
return false;
}
} else {
- if (!cmSystemTools::MakeDirectory(testingDir.c_str())) {
- cmCTestLog(this, ERROR_MESSAGE, "Cannot create directory " << testingDir
- << std::endl);
+ if (!cmSystemTools::MakeDirectory(testingDir)) {
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Cannot create directory " << testingDir << std::endl);
return false;
}
}
std::string filename = testingDir + "/" + name;
- stream.Open(filename.c_str());
+ stream.Open(filename);
if (!stream) {
- cmCTestLog(this, ERROR_MESSAGE, "Problem opening file: " << filename
- << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Problem opening file: " << filename << std::endl);
return false;
}
if (compress) {
- if (this->CompressXMLFiles) {
+ if (this->Impl->CompressXMLFiles) {
stream.SetCompression(true);
}
}
@@ -782,8 +855,7 @@ bool cmCTest::AddIfExists(Part part, const char* file)
if (this->CTestFileExists(file)) {
this->AddSubmitFile(part, file);
} else {
- std::string name = file;
- name += ".gz";
+ std::string name = cmStrCat(file, ".gz");
if (this->CTestFileExists(name)) {
this->AddSubmitFile(part, file);
} else {
@@ -795,40 +867,59 @@ bool cmCTest::AddIfExists(Part part, const char* file)
bool cmCTest::CTestFileExists(const std::string& filename)
{
- std::string testingDir =
- this->BinaryDir + "/Testing/" + this->CurrentTag + "/" + filename;
- return cmSystemTools::FileExists(testingDir.c_str());
+ std::string testingDir = this->Impl->BinaryDir + "/Testing/" +
+ this->Impl->CurrentTag + "/" + filename;
+ return cmSystemTools::FileExists(testingDir);
}
-cmCTestGenericHandler* cmCTest::GetInitializedHandler(const char* handler)
+cmCTestBuildHandler* cmCTest::GetBuildHandler()
{
- cmCTest::t_TestingHandlers::iterator it =
- this->TestingHandlers.find(handler);
- if (it == this->TestingHandlers.end()) {
- return CM_NULLPTR;
- }
- it->second->Initialize();
- return it->second;
+ return &this->Impl->BuildHandler;
}
-cmCTestGenericHandler* cmCTest::GetHandler(const char* handler)
+cmCTestBuildAndTestHandler* cmCTest::GetBuildAndTestHandler()
{
- cmCTest::t_TestingHandlers::iterator it =
- this->TestingHandlers.find(handler);
- if (it == this->TestingHandlers.end()) {
- return CM_NULLPTR;
- }
- return it->second;
+ return &this->Impl->BuildAndTestHandler;
}
-int cmCTest::ExecuteHandler(const char* shandler)
+cmCTestCoverageHandler* cmCTest::GetCoverageHandler()
{
- cmCTestGenericHandler* handler = this->GetHandler(shandler);
- if (!handler) {
- return -1;
- }
- handler->Initialize();
- return handler->ProcessHandler();
+ return &this->Impl->CoverageHandler;
+}
+
+cmCTestScriptHandler* cmCTest::GetScriptHandler()
+{
+ return &this->Impl->ScriptHandler;
+}
+
+cmCTestTestHandler* cmCTest::GetTestHandler()
+{
+ return &this->Impl->TestHandler;
+}
+
+cmCTestUpdateHandler* cmCTest::GetUpdateHandler()
+{
+ return &this->Impl->UpdateHandler;
+}
+
+cmCTestConfigureHandler* cmCTest::GetConfigureHandler()
+{
+ return &this->Impl->ConfigureHandler;
+}
+
+cmCTestMemCheckHandler* cmCTest::GetMemCheckHandler()
+{
+ return &this->Impl->MemCheckHandler;
+}
+
+cmCTestSubmitHandler* cmCTest::GetSubmitHandler()
+{
+ return &this->Impl->SubmitHandler;
+}
+
+cmCTestUploadHandler* cmCTest::GetUploadHandler()
+{
+ return &this->Impl->UploadHandler;
}
int cmCTest::ProcessSteps()
@@ -838,10 +929,11 @@ int cmCTest::ProcessSteps()
int update_count = 0;
for (Part p = PartStart; notest && p != PartCount; p = Part(p + 1)) {
- notest = !this->Parts[p];
+ notest = !this->Impl->Parts[p];
}
- if (this->Parts[PartUpdate] && (this->GetRemainingTimeAllowed() - 120 > 0)) {
- cmCTestGenericHandler* uphandler = this->GetHandler("update");
+ if (this->Impl->Parts[PartUpdate] &&
+ (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) {
+ cmCTestUpdateHandler* uphandler = this->GetUpdateHandler();
uphandler->SetPersistentOption(
"SourceDirectory",
this->GetCTestConfiguration("SourceDirectory").c_str());
@@ -850,44 +942,45 @@ int cmCTest::ProcessSteps()
res |= cmCTest::UPDATE_ERRORS;
}
}
- if (this->TestModel == cmCTest::CONTINUOUS && !update_count) {
+ if (this->Impl->TestModel == cmCTest::CONTINUOUS && !update_count) {
return 0;
}
- if (this->Parts[PartConfigure] &&
- (this->GetRemainingTimeAllowed() - 120 > 0)) {
- if (this->GetHandler("configure")->ProcessHandler() < 0) {
+ if (this->Impl->Parts[PartConfigure] &&
+ (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) {
+ if (this->GetConfigureHandler()->ProcessHandler() < 0) {
res |= cmCTest::CONFIGURE_ERRORS;
}
}
- if (this->Parts[PartBuild] && (this->GetRemainingTimeAllowed() - 120 > 0)) {
+ if (this->Impl->Parts[PartBuild] &&
+ (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) {
this->UpdateCTestConfiguration();
- if (this->GetHandler("build")->ProcessHandler() < 0) {
+ if (this->GetBuildHandler()->ProcessHandler() < 0) {
res |= cmCTest::BUILD_ERRORS;
}
}
- if ((this->Parts[PartTest] || notest) &&
- (this->GetRemainingTimeAllowed() - 120 > 0)) {
+ if ((this->Impl->Parts[PartTest] || notest) &&
+ (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) {
this->UpdateCTestConfiguration();
- if (this->GetHandler("test")->ProcessHandler() < 0) {
+ if (this->GetTestHandler()->ProcessHandler() < 0) {
res |= cmCTest::TEST_ERRORS;
}
}
- if (this->Parts[PartCoverage] &&
- (this->GetRemainingTimeAllowed() - 120 > 0)) {
+ if (this->Impl->Parts[PartCoverage] &&
+ (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) {
this->UpdateCTestConfiguration();
- if (this->GetHandler("coverage")->ProcessHandler() < 0) {
+ if (this->GetCoverageHandler()->ProcessHandler() < 0) {
res |= cmCTest::COVERAGE_ERRORS;
}
}
- if (this->Parts[PartMemCheck] &&
- (this->GetRemainingTimeAllowed() - 120 > 0)) {
+ if (this->Impl->Parts[PartMemCheck] &&
+ (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) {
this->UpdateCTestConfiguration();
- if (this->GetHandler("memcheck")->ProcessHandler() < 0) {
+ if (this->GetMemCheckHandler()->ProcessHandler() < 0) {
res |= cmCTest::MEMORY_ERRORS;
}
}
if (!notest) {
- std::string notes_dir = this->BinaryDir + "/Testing/Notes";
+ std::string notes_dir = this->Impl->BinaryDir + "/Testing/Notes";
if (cmSystemTools::FileIsDirectory(notes_dir)) {
cmsys::Directory d;
d.Load(notes_dir);
@@ -895,26 +988,26 @@ 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 += ";";
+ if (!this->Impl->NotesFiles.empty()) {
+ this->Impl->NotesFiles += ";";
}
- this->NotesFiles += fullname;
- this->Parts[PartNotes].Enable();
+ this->Impl->NotesFiles += fullname;
+ this->Impl->Parts[PartNotes].Enable();
}
}
}
}
- if (this->Parts[PartNotes]) {
+ if (this->Impl->Parts[PartNotes]) {
this->UpdateCTestConfiguration();
- if (!this->NotesFiles.empty()) {
- this->GenerateNotesFile(this->NotesFiles.c_str());
+ if (!this->Impl->NotesFiles.empty()) {
+ this->GenerateNotesFile(this->Impl->NotesFiles.c_str());
}
}
- if (this->Parts[PartSubmit]) {
+ if (this->Impl->Parts[PartSubmit]) {
this->UpdateCTestConfiguration();
- if (this->GetHandler("submit")->ProcessHandler() < 0) {
+ if (this->GetSubmitHandler()->ProcessHandler() < 0) {
res |= cmCTest::SUBMIT_ERRORS;
}
}
@@ -926,10 +1019,10 @@ int cmCTest::ProcessSteps()
std::string cmCTest::GetTestModelString()
{
- if (!this->SpecificTrack.empty()) {
- return this->SpecificTrack;
+ if (!this->Impl->SpecificGroup.empty()) {
+ return this->Impl->SpecificGroup;
}
- switch (this->TestModel) {
+ switch (this->Impl->TestModel) {
case cmCTest::NIGHTLY:
return "Nightly";
case cmCTest::CONTINUOUS:
@@ -944,10 +1037,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,8 +1051,8 @@ int cmCTest::GetTestModelFromString(const char* str)
//######################################################################
//######################################################################
-int cmCTest::RunMakeCommand(const char* command, std::string& output,
- int* retVal, const char* dir, int timeout,
+int cmCTest::RunMakeCommand(const std::string& command, std::string& output,
+ int* retVal, const char* dir, cmDuration timeout,
std::ostream& ofs, Encoding encoding)
{
// First generate the command and arguments
@@ -970,26 +1063,28 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output,
}
std::vector<const char*> argv;
- for (std::vector<std::string>::const_iterator a = args.begin();
- a != args.end(); ++a) {
- argv.push_back(a->c_str());
+ argv.reserve(args.size() + 1);
+ for (std::string const& a : args) {
+ argv.push_back(a.c_str());
}
- argv.push_back(CM_NULLPTR);
+ argv.push_back(nullptr);
- output = "";
+ output.clear();
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Run command:");
- std::vector<const char*>::iterator ait;
- for (ait = argv.begin(); ait != argv.end() && *ait; ++ait) {
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, " \"" << *ait << "\"");
+ for (char const* arg : argv) {
+ if (!arg) {
+ break;
+ }
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, " \"" << arg << "\"");
}
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, std::endl);
// Now create process object
cmsysProcess* cp = cmsysProcess_New();
- cmsysProcess_SetCommand(cp, &*argv.begin());
+ cmsysProcess_SetCommand(cp, argv.data());
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
@@ -1001,14 +1096,16 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output,
int length;
cmProcessOutput processOutput(encoding);
std::string strdata;
- cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, " Each . represents "
- << tick_len << " bytes of output" << std::endl
- << " " << std::flush);
- while (cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) {
+ cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
+ " Each . represents " << tick_len
+ << " bytes of output\n"
+ " "
+ << std::flush);
+ while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) {
processOutput.DecodeText(data, length, strdata);
- for (size_t cc = 0; cc < strdata.size(); ++cc) {
- if (strdata[cc] == 0) {
- strdata[cc] = '\n';
+ for (char& cc : strdata) {
+ if (cc == 0) {
+ cc = '\n';
}
}
output.append(strdata);
@@ -1018,8 +1115,7 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output,
if (tick % tick_line_len == 0 && tick > 0) {
cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
" Size: " << int((double(output.size()) / 1024.0) + 1)
- << "K" << std::endl
- << " " << std::flush);
+ << "K\n " << std::flush);
}
}
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
@@ -1037,10 +1133,11 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output,
ofs << cmCTestLogWrite(strdata.c_str(), strdata.size());
}
}
- cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, " Size of output: "
- << int(double(output.size()) / 1024.0) << "K" << std::endl);
+ cmCTestLog(this, HANDLER_PROGRESS_OUTPUT,
+ " Size of output: " << int(double(output.size()) / 1024.0) << "K"
+ << std::endl);
- cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+ cmsysProcess_WaitForExit(cp, nullptr);
int result = cmsysProcess_GetState(cp);
@@ -1050,16 +1147,17 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output,
"Command exited with the value: " << *retVal << std::endl);
} else if (result == cmsysProcess_State_Exception) {
*retVal = cmsysProcess_GetExitException(cp);
- cmCTestLog(this, WARNING, "There was an exception: " << *retVal
- << std::endl);
+ cmCTestLog(this, WARNING,
+ "There was an exception: " << *retVal << std::endl);
} else if (result == cmsysProcess_State_Expired) {
cmCTestLog(this, WARNING, "There was a timeout" << std::endl);
} else if (result == cmsysProcess_State_Error) {
output += "\n*** ERROR executing: ";
output += cmsysProcess_GetErrorString(cp);
output += "\n***The build process failed.";
- cmCTestLog(this, ERROR_MESSAGE, "There was an error: "
- << cmsysProcess_GetErrorString(cp) << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "There was an error: " << cmsysProcess_GetErrorString(cp)
+ << std::endl);
}
cmsysProcess_Delete(cp);
@@ -1073,58 +1171,67 @@ 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) {
- timeout = this->TimeOut;
+ cmDuration timeout = this->GetRemainingTimeAllowed();
+ if (timeout != cmCTest::MaxDuration()) {
+ timeout -= std::chrono::minutes(2);
+ }
+ if (this->Impl->TimeOut > cmDuration::zero() &&
+ this->Impl->TimeOut < timeout) {
+ timeout = this->Impl->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;
+ if (timeout <= cmDuration::zero()) {
+ timeout = std::chrono::seconds(1);
}
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
- "Test timeout computed to be: " << timeout << "\n");
+ "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) {
+ !this->Impl->ForceNewCTestProcess) {
cmCTest inst;
- inst.ConfigType = this->ConfigType;
- inst.TimeOut = timeout;
+ inst.Impl->ConfigType = this->Impl->ConfigType;
+ inst.Impl->TimeOut = timeout;
// Capture output of the child ctest.
std::ostringstream oss;
inst.SetStreams(&oss, &oss);
std::vector<std::string> args;
- for (unsigned int i = 0; i < argv.size(); ++i) {
- if (argv[i]) {
+ for (char const* i : argv) {
+ if (i) {
// 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(argv[i], "--build-generator") == 0 && timeout > 0) {
- args.push_back("--test-timeout");
- std::ostringstream msg;
- msg << timeout;
- args.push_back(msg.str());
+ if (strcmp(i, "--build-generator") == 0 &&
+ timeout != cmCTest::MaxDuration() &&
+ timeout > cmDuration::zero()) {
+ args.emplace_back("--test-timeout");
+ args.push_back(std::to_string(cmDurationTo<unsigned int>(timeout)));
}
- args.push_back(argv[i]);
+ args.emplace_back(i);
}
}
if (log) {
*log << "* Run internal CTest" << std::endl;
}
- CM_AUTO_PTR<cmSystemTools::SaveRestoreEnvironment> saveEnv;
+ std::unique_ptr<cmSystemTools::SaveRestoreEnvironment> saveEnv;
if (modifyEnv) {
- saveEnv.reset(new cmSystemTools::SaveRestoreEnvironment);
+ saveEnv = cm::make_unique<cmSystemTools::SaveRestoreEnvironment>();
cmSystemTools::AppendEnv(*environment);
}
@@ -1146,33 +1253,33 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
}
std::vector<char> tempOutput;
if (output) {
- *output = "";
+ output->clear();
}
- CM_AUTO_PTR<cmSystemTools::SaveRestoreEnvironment> saveEnv;
+ std::unique_ptr<cmSystemTools::SaveRestoreEnvironment> saveEnv;
if (modifyEnv) {
- saveEnv.reset(new cmSystemTools::SaveRestoreEnvironment);
+ saveEnv = cm::make_unique<cmSystemTools::SaveRestoreEnvironment>();
cmSystemTools::AppendEnv(*environment);
}
cmsysProcess* cp = cmsysProcess_New();
- cmsysProcess_SetCommand(cp, &*argv.begin());
+ cmsysProcess_SetCommand(cp, argv.data());
cmCTestLog(this, DEBUG, "Command is: " << argv[0] << std::endl);
if (cmSystemTools::GetRunCommandHideConsole()) {
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
}
- cmsysProcess_SetTimeout(cp, timeout);
+ cmsysProcess_SetTimeout(cp, timeout.count());
cmsysProcess_Execute(cp);
char* data;
int length;
cmProcessOutput processOutput(encoding);
std::string strdata;
- while (cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) {
+ while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) {
processOutput.DecodeText(data, length, strdata);
if (output) {
- tempOutput.insert(tempOutput.end(), data, data + length);
+ cmAppend(tempOutput, data, data + length);
}
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
cmCTestLogWrite(strdata.c_str(), strdata.size()));
@@ -1189,41 +1296,39 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
}
}
- cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+ cmsysProcess_WaitForExit(cp, nullptr);
processOutput.DecodeText(tempOutput, tempOutput);
if (output && tempOutput.begin() != tempOutput.end()) {
- output->append(&*tempOutput.begin(), tempOutput.size());
+ output->append(tempOutput.data(), tempOutput.size());
}
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "-- Process completed"
- << std::endl);
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
+ "-- Process completed" << std::endl);
int result = cmsysProcess_GetState(cp);
if (result == cmsysProcess_State_Exited) {
*retVal = cmsysProcess_GetExitValue(cp);
- if (*retVal != 0 && this->OutputTestOutputOnTestFailure) {
+ if (*retVal != 0 && this->Impl->OutputTestOutputOnTestFailure) {
OutputTestErrors(tempOutput);
}
} else if (result == cmsysProcess_State_Exception) {
- if (this->OutputTestOutputOnTestFailure) {
+ if (this->Impl->OutputTestOutputOnTestFailure) {
OutputTestErrors(tempOutput);
}
*retVal = cmsysProcess_GetExitException(cp);
- std::string outerr = "\n*** Exception executing: ";
- outerr += cmsysProcess_GetExceptionString(cp);
+ std::string outerr = cmStrCat("\n*** Exception executing: ",
+ cmsysProcess_GetExceptionString(cp));
if (output) {
*output += outerr;
}
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl
- << std::flush);
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl);
} else if (result == cmsysProcess_State_Error) {
- std::string outerr = "\n*** ERROR executing: ";
- outerr += cmsysProcess_GetErrorString(cp);
+ std::string outerr =
+ cmStrCat("\n*** ERROR executing: ", cmsysProcess_GetErrorString(cp));
if (output) {
*output += outerr;
}
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl
- << std::flush);
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl);
}
cmsysProcess_Delete(cp);
@@ -1234,7 +1339,7 @@ std::string cmCTest::SafeBuildIdField(const std::string& value)
{
std::string safevalue(value);
- if (safevalue != "") {
+ if (!safevalue.empty()) {
// Disallow non-filename and non-space whitespace characters.
// If they occur, replace them with ""
//
@@ -1253,7 +1358,7 @@ std::string cmCTest::SafeBuildIdField(const std::string& value)
}
}
- if (safevalue == "") {
+ if (safevalue.empty()) {
safevalue = "(empty)";
}
@@ -1262,9 +1367,10 @@ std::string cmCTest::SafeBuildIdField(const std::string& value)
void cmCTest::StartXML(cmXMLWriter& xml, bool append)
{
- if (this->CurrentTag.empty()) {
- cmCTestLog(this, ERROR_MESSAGE, "Current Tag empty, this may mean"
- " NightlStartTime was not set correctly."
+ if (this->Impl->CurrentTag.empty()) {
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Current Tag empty, this may mean"
+ " NightlStartTime was not set correctly."
<< std::endl);
cmSystemTools::SetFatalErrorOccured();
}
@@ -1277,7 +1383,7 @@ void cmCTest::StartXML(cmXMLWriter& xml, bool append)
std::string buildname =
cmCTest::SafeBuildIdField(this->GetCTestConfiguration("BuildName"));
- std::string stamp = cmCTest::SafeBuildIdField(this->CurrentTag + "-" +
+ std::string stamp = cmCTest::SafeBuildIdField(this->Impl->CurrentTag + "-" +
this->GetTestModelString());
std::string site =
cmCTest::SafeBuildIdField(this->GetCTestConfiguration("Site"));
@@ -1325,8 +1431,7 @@ void cmCTest::StartXML(cmXMLWriter& xml, bool append)
void cmCTest::AddSiteProperties(cmXMLWriter& xml)
{
- cmCTestScriptHandler* ch =
- static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
+ cmCTestScriptHandler* ch = this->GetScriptHandler();
cmake* cm = ch->GetCMake();
// if no CMake then this is the old style script and props like
// this will not work anyway.
@@ -1343,11 +1448,9 @@ void cmCTest::AddSiteProperties(cmXMLWriter& xml)
if (labels) {
xml.StartElement("Labels");
std::string l = labels;
- std::vector<std::string> args;
- cmSystemTools::ExpandListArgument(l, args);
- for (std::vector<std::string>::iterator i = args.begin();
- i != args.end(); ++i) {
- xml.Element("Label", *i);
+ std::vector<std::string> args = cmExpandedList(l);
+ for (std::string const& i : args) {
+ xml.Element("Label", i);
}
xml.EndElement();
}
@@ -1363,6 +1466,31 @@ void cmCTest::AddSiteProperties(cmXMLWriter& xml)
}
}
+void cmCTest::GenerateSubprojectsOutput(cmXMLWriter& xml)
+{
+ for (std::string const& subproj : this->GetLabelsForSubprojects()) {
+ xml.StartElement("Subproject");
+ xml.Attribute("name", subproj);
+ xml.Element("Label", subproj);
+ xml.EndElement(); // Subproject
+ }
+}
+
+std::vector<std::string> cmCTest::GetLabelsForSubprojects()
+{
+ std::string labelsForSubprojects =
+ this->GetCTestConfiguration("LabelsForSubprojects");
+ std::vector<std::string> subprojects = cmExpandedList(labelsForSubprojects);
+
+ // sort the array
+ std::sort(subprojects.begin(), subprojects.end());
+ // remove duplicates
+ auto new_end = std::unique(subprojects.begin(), subprojects.end());
+ subprojects.erase(new_end, subprojects.end());
+
+ return subprojects;
+}
+
void cmCTest::EndXML(cmXMLWriter& xml)
{
xml.EndElement(); // Site
@@ -1370,11 +1498,10 @@ void cmCTest::EndXML(cmXMLWriter& xml)
}
int cmCTest::GenerateCTestNotesOutput(cmXMLWriter& xml,
- const cmCTest::VectorOfStrings& files)
+ std::vector<std::string> const& files)
{
std::string buildname =
cmCTest::SafeBuildIdField(this->GetCTestConfiguration("BuildName"));
- cmCTest::VectorOfStrings::const_iterator it;
xml.StartDocument();
xml.ProcessingInstruction("xml-stylesheet",
"type=\"text/xsl\" "
@@ -1383,22 +1510,22 @@ int cmCTest::GenerateCTestNotesOutput(cmXMLWriter& xml,
xml.StartElement("Site");
xml.Attribute("BuildName", buildname);
xml.Attribute("BuildStamp",
- this->CurrentTag + "-" + this->GetTestModelString());
+ this->Impl->CurrentTag + "-" + this->GetTestModelString());
xml.Attribute("Name", this->GetCTestConfiguration("Site"));
xml.Attribute("Generator",
- std::string("ctest") + cmVersion::GetCMakeVersion());
+ std::string("ctest-") + cmVersion::GetCMakeVersion());
this->AddSiteProperties(xml);
xml.StartElement("Notes");
- for (it = files.begin(); it != files.end(); it++) {
- cmCTestLog(this, OUTPUT, "\tAdd file: " << *it << std::endl);
+ for (std::string const& file : files) {
+ cmCTestLog(this, OUTPUT, "\tAdd file: " << file << std::endl);
std::string note_time = this->CurrentTime();
xml.StartElement("Note");
- xml.Attribute("Name", *it);
- xml.Element("Time", cmSystemTools::GetTime());
+ xml.Attribute("Name", file);
+ xml.Element("Time", std::chrono::system_clock::now());
xml.Element("DateTime", note_time);
xml.StartElement("Text");
- cmsys::ifstream ifs(it->c_str());
+ cmsys::ifstream ifs(file.c_str());
if (ifs) {
std::string line;
while (cmSystemTools::GetLineFromStream(ifs, line)) {
@@ -1407,9 +1534,10 @@ int cmCTest::GenerateCTestNotesOutput(cmXMLWriter& xml,
}
ifs.close();
} else {
- xml.Content("Problem reading file: " + *it + "\n");
- cmCTestLog(this, ERROR_MESSAGE, "Problem reading file: "
- << *it << " while creating notes" << std::endl);
+ xml.Content("Problem reading file: " + file + "\n");
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Problem reading file: " << file << " while creating notes"
+ << std::endl);
}
xml.EndElement(); // Text
xml.EndElement(); // Note
@@ -1420,10 +1548,10 @@ int cmCTest::GenerateCTestNotesOutput(cmXMLWriter& xml,
return 1;
}
-int cmCTest::GenerateNotesFile(const VectorOfStrings& files)
+int cmCTest::GenerateNotesFile(std::vector<std::string> const& files)
{
cmGeneratedFileStream ofs;
- if (!this->OpenOutputFile(this->CurrentTag, "Notes.xml", ofs)) {
+ if (!this->OpenOutputFile(this->Impl->CurrentTag, "Notes.xml", ofs)) {
cmCTestLog(this, ERROR_MESSAGE, "Cannot open notes file" << std::endl);
return 1;
}
@@ -1438,11 +1566,10 @@ int cmCTest::GenerateNotesFile(const char* cfiles)
return 1;
}
- VectorOfStrings files;
-
cmCTestLog(this, OUTPUT, "Create notes file" << std::endl);
- files = cmSystemTools::SplitString(cfiles, ';');
+ std::vector<std::string> const files =
+ cmSystemTools::SplitString(cfiles, ';');
if (files.empty()) {
return 1;
}
@@ -1450,16 +1577,35 @@ int cmCTest::GenerateNotesFile(const char* cfiles)
return this->GenerateNotesFile(files);
}
+int cmCTest::GenerateDoneFile()
+{
+ cmGeneratedFileStream ofs;
+ if (!this->OpenOutputFile(this->Impl->CurrentTag, "Done.xml", ofs)) {
+ cmCTestLog(this, ERROR_MESSAGE, "Cannot open done file" << std::endl);
+ return 1;
+ }
+ cmXMLWriter xml(ofs);
+ xml.StartDocument();
+ xml.StartElement("Done");
+ xml.Element("buildId", this->Impl->BuildID);
+ xml.Element("time", std::chrono::system_clock::now());
+ xml.EndElement(); // Done
+ xml.EndDocument();
+
+ return 0;
+}
+
std::string cmCTest::Base64GzipEncodeFile(std::string const& file)
{
std::string tarFile = file + "_temp.tar.gz";
std::vector<std::string> files;
files.push_back(file);
- if (!cmSystemTools::CreateTar(tarFile.c_str(), files,
- cmSystemTools::TarCompressGZip, false)) {
- cmCTestLog(this, ERROR_MESSAGE, "Error creating tar while "
- "encoding file: "
+ if (!cmSystemTools::CreateTar(tarFile, files, cmSystemTools::TarCompressGZip,
+ false)) {
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Error creating tar while "
+ "encoding file: "
<< file << std::endl);
return "";
}
@@ -1471,11 +1617,12 @@ std::string cmCTest::Base64GzipEncodeFile(std::string const& file)
std::string cmCTest::Base64EncodeFile(std::string const& file)
{
size_t const len = cmSystemTools::FileLength(file);
- cmsys::ifstream ifs(file.c_str(), std::ios::in
+ cmsys::ifstream ifs(file.c_str(),
+ std::ios::in
#ifdef _WIN32
| std::ios::binary
#endif
- );
+ );
std::vector<char> file_buffer(len + 1);
ifs.read(&file_buffer[0], len);
ifs.close();
@@ -1489,16 +1636,16 @@ std::string cmCTest::Base64EncodeFile(std::string const& file)
return std::string(&encoded_buffer[0], rlen);
}
-bool cmCTest::SubmitExtraFiles(const VectorOfStrings& files)
+bool cmCTest::SubmitExtraFiles(std::vector<std::string> const& files)
{
- VectorOfStrings::const_iterator it;
- for (it = files.begin(); it != files.end(); ++it) {
- if (!cmSystemTools::FileExists(it->c_str())) {
- cmCTestLog(this, ERROR_MESSAGE, "Cannot find extra file: "
- << *it << " to submit." << std::endl;);
+ for (std::string const& file : files) {
+ if (!cmSystemTools::FileExists(file)) {
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Cannot find extra file: " << file << " to submit."
+ << std::endl;);
return false;
}
- this->AddSubmitFile(PartExtraFiles, it->c_str());
+ this->AddSubmitFile(PartExtraFiles, file.c_str());
}
return true;
}
@@ -1509,11 +1656,10 @@ bool cmCTest::SubmitExtraFiles(const char* cfiles)
return true;
}
- VectorOfStrings files;
-
cmCTestLog(this, OUTPUT, "Submit extra files" << std::endl);
- files = cmSystemTools::SplitString(cfiles, ';');
+ std::vector<std::string> const files =
+ cmSystemTools::SplitString(cfiles, ';');
if (files.empty()) {
return true;
}
@@ -1652,7 +1798,8 @@ void cmCTest::ErrorMessageUnknownDashDValue(std::string& val)
"CTest -D called with incorrect option: " << val << std::endl);
cmCTestLog(
- this, ERROR_MESSAGE, "Available options are:"
+ this, ERROR_MESSAGE,
+ "Available options are:"
<< std::endl
<< " ctest -D Continuous" << std::endl
<< " ctest -D Continuous(Start|Update|Configure|Build)" << std::endl
@@ -1680,17 +1827,17 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
{
std::string arg = args[i];
if (this->CheckArgument(arg, "-F")) {
- this->Failover = true;
+ this->Impl->Failover = true;
}
if (this->CheckArgument(arg, "-j", "--parallel") && i < args.size() - 1) {
i++;
int plevel = atoi(args[i].c_str());
this->SetParallelLevel(plevel);
- this->ParallelLevelSetInCli = true;
+ this->Impl->ParallelLevelSetInCli = true;
} else if (arg.find("-j") == 0) {
int plevel = atoi(arg.substr(2).c_str());
this->SetParallelLevel(plevel);
- this->ParallelLevelSetInCli = true;
+ this->Impl->ParallelLevelSetInCli = true;
}
if (this->CheckArgument(arg, "--repeat-until-fail")) {
if (i >= args.size() - 1) {
@@ -1699,21 +1846,21 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
}
i++;
long repeat = 1;
- if (!cmSystemTools::StringToLong(args[i].c_str(), &repeat)) {
+ if (!cmStrToLong(args[i], &repeat)) {
errormsg =
"'--repeat-until-fail' given non-integer value '" + args[i] + "'";
return false;
}
- this->RepeatTests = static_cast<int>(repeat);
+ this->Impl->RepeatTests = static_cast<int>(repeat);
if (repeat > 1) {
- this->RepeatUntilFail = true;
+ this->Impl->RepeatUntilFail = true;
}
}
if (this->CheckArgument(arg, "--test-load") && i < args.size() - 1) {
i++;
unsigned long load;
- if (cmSystemTools::StringToULong(args[i].c_str(), &load)) {
+ if (cmStrToULong(args[i], &load)) {
this->SetTestLoad(load);
} else {
cmCTestLog(this, WARNING,
@@ -1722,21 +1869,21 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
}
if (this->CheckArgument(arg, "--no-compress-output")) {
- this->CompressTestOutput = false;
+ this->Impl->CompressTestOutput = false;
}
if (this->CheckArgument(arg, "--print-labels")) {
- this->PrintLabels = true;
+ this->Impl->PrintLabels = true;
}
if (this->CheckArgument(arg, "--http1.0")) {
- this->UseHTTP10 = true;
+ this->Impl->UseHTTP10 = true;
}
if (this->CheckArgument(arg, "--timeout") && i < args.size() - 1) {
i++;
- double timeout = (double)atof(args[i].c_str());
- this->GlobalTimeout = timeout;
+ auto timeout = cmDuration(atof(args[i].c_str()));
+ this->Impl->GlobalTimeout = timeout;
}
if (this->CheckArgument(arg, "--stop-time") && i < args.size() - 1) {
@@ -1751,44 +1898,50 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
}
if (this->CheckArgument(arg, "--debug")) {
- this->Debug = true;
- this->ShowLineNumbers = true;
+ this->Impl->Debug = true;
+ this->Impl->ShowLineNumbers = true;
}
+ if (this->CheckArgument(arg, "--group") && i < args.size() - 1) {
+ i++;
+ this->Impl->SpecificGroup = args[i];
+ }
+ // This is an undocumented / deprecated option.
+ // "Track" has been renamed to "Group".
if (this->CheckArgument(arg, "--track") && i < args.size() - 1) {
i++;
- this->SpecificTrack = args[i];
+ this->Impl->SpecificGroup = args[i];
}
if (this->CheckArgument(arg, "--show-line-numbers")) {
- this->ShowLineNumbers = true;
+ this->Impl->ShowLineNumbers = true;
}
if (this->CheckArgument(arg, "--no-label-summary")) {
- this->LabelSummary = false;
+ this->Impl->LabelSummary = false;
+ }
+ if (this->CheckArgument(arg, "--no-subproject-summary")) {
+ this->Impl->SubprojectSummary = false;
}
if (this->CheckArgument(arg, "-Q", "--quiet")) {
- this->Quiet = true;
+ this->Impl->Quiet = true;
}
- if (this->CheckArgument(arg, "-V", "--verbose")) {
- this->Verbose = true;
+ if (this->CheckArgument(arg, "--progress")) {
+ this->Impl->TestProgressOutput = true;
}
- if (this->CheckArgument(arg, "-B")) {
- this->BatchJobs = true;
+ if (this->CheckArgument(arg, "-V", "--verbose")) {
+ this->Impl->Verbose = true;
}
if (this->CheckArgument(arg, "-VV", "--extra-verbose")) {
- this->ExtraVerbose = true;
- this->Verbose = true;
+ this->Impl->ExtraVerbose = true;
+ this->Impl->Verbose = true;
}
if (this->CheckArgument(arg, "--output-on-failure")) {
- this->OutputTestOutputOnTestFailure = true;
+ this->Impl->OutputTestOutputOnTestFailure = true;
}
if (this->CheckArgument(arg, "--test-output-size-passed") &&
i < args.size() - 1) {
i++;
long outputSize;
- if (cmSystemTools::StringToLong(args[i].c_str(), &outputSize)) {
- if (cmCTestTestHandler* pCTestTestHandler =
- static_cast<cmCTestTestHandler*>(this->TestingHandlers["test"])) {
- pCTestTestHandler->SetTestOutputSizePassed(int(outputSize));
- }
+ if (cmStrToLong(args[i], &outputSize)) {
+ this->Impl->TestHandler.SetTestOutputSizePassed(int(outputSize));
} else {
cmCTestLog(this, WARNING,
"Invalid value for '--test-output-size-passed': " << args[i]
@@ -1799,11 +1952,8 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
i < args.size() - 1) {
i++;
long outputSize;
- if (cmSystemTools::StringToLong(args[i].c_str(), &outputSize)) {
- if (cmCTestTestHandler* pCTestTestHandler =
- static_cast<cmCTestTestHandler*>(this->TestingHandlers["test"])) {
- pCTestTestHandler->SetTestOutputSizeFailed(int(outputSize));
- }
+ if (cmStrToLong(args[i], &outputSize)) {
+ this->Impl->TestHandler.SetTestOutputSizeFailed(int(outputSize));
} else {
cmCTestLog(this, WARNING,
"Invalid value for '--test-output-size-failed': " << args[i]
@@ -1811,7 +1961,24 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
}
}
if (this->CheckArgument(arg, "-N", "--show-only")) {
- this->ShowOnly = true;
+ this->Impl->ShowOnly = true;
+ }
+ if (cmHasLiteralPrefix(arg, "--show-only=")) {
+ this->Impl->ShowOnly = true;
+
+ // Check if a specific format is requested. Defaults to human readable
+ // text.
+ std::string argWithFormat = "--show-only=";
+ std::string format = arg.substr(argWithFormat.length());
+ if (format == "json-v1") {
+ // Force quiet mode so the only output is the json object model.
+ this->Impl->Quiet = true;
+ this->Impl->OutputAsJson = true;
+ this->Impl->OutputAsJsonVersion = 1;
+ } else if (format != "human") {
+ errormsg = "'--show-only=' given unknown value '" + format + "'";
+ return false;
+ }
}
if (this->CheckArgument(arg, "-O", "--output-log") && i < args.size() - 1) {
@@ -1820,25 +1987,25 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
}
if (this->CheckArgument(arg, "--tomorrow-tag")) {
- this->TomorrowTag = true;
+ this->Impl->TomorrowTag = true;
}
if (this->CheckArgument(arg, "--force-new-ctest-process")) {
- this->ForceNewCTestProcess = true;
+ this->Impl->ForceNewCTestProcess = true;
}
if (this->CheckArgument(arg, "-W", "--max-width") && i < args.size() - 1) {
i++;
- this->MaxTestNameWidth = atoi(args[i].c_str());
+ this->Impl->MaxTestNameWidth = atoi(args[i].c_str());
}
if (this->CheckArgument(arg, "--interactive-debug-mode") &&
i < args.size() - 1) {
i++;
- this->InteractiveDebugMode = cmSystemTools::IsOn(args[i].c_str());
+ this->Impl->InteractiveDebugMode = cmIsOn(args[i]);
}
if (this->CheckArgument(arg, "--submit-index") && i < args.size() - 1) {
i++;
- this->SubmitIndex = atoi(args[i].c_str());
- if (this->SubmitIndex < 0) {
- this->SubmitIndex = 0;
+ this->Impl->SubmitIndex = atoi(args[i].c_str());
+ if (this->Impl->SubmitIndex < 0) {
+ this->Impl->SubmitIndex = 0;
}
}
@@ -1847,7 +2014,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
this->AddCTestConfigurationOverwrite(args[i]);
}
if (this->CheckArgument(arg, "-A", "--add-notes") && i < args.size() - 1) {
- this->ProduceXML = true;
+ this->Impl->ProduceXML = true;
this->SetTest("Notes");
i++;
this->SetNotesFiles(args[i].c_str());
@@ -1857,82 +2024,128 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
if (this->CheckArgument(arg, "-I", "--tests-information") &&
i < args.size() - 1) {
i++;
- this->GetHandler("test")->SetPersistentOption("TestsToRunInformation",
- args[i].c_str());
- this->GetHandler("memcheck")
- ->SetPersistentOption("TestsToRunInformation", args[i].c_str());
+ this->GetTestHandler()->SetPersistentOption("TestsToRunInformation",
+ args[i].c_str());
+ this->GetMemCheckHandler()->SetPersistentOption("TestsToRunInformation",
+ args[i].c_str());
}
if (this->CheckArgument(arg, "-U", "--union")) {
- this->GetHandler("test")->SetPersistentOption("UseUnion", "true");
- this->GetHandler("memcheck")->SetPersistentOption("UseUnion", "true");
+ this->GetTestHandler()->SetPersistentOption("UseUnion", "true");
+ this->GetMemCheckHandler()->SetPersistentOption("UseUnion", "true");
}
if (this->CheckArgument(arg, "-R", "--tests-regex") && i < args.size() - 1) {
i++;
- this->GetHandler("test")->SetPersistentOption("IncludeRegularExpression",
- args[i].c_str());
- this->GetHandler("memcheck")
- ->SetPersistentOption("IncludeRegularExpression", args[i].c_str());
+ this->GetTestHandler()->SetPersistentOption("IncludeRegularExpression",
+ args[i].c_str());
+ this->GetMemCheckHandler()->SetPersistentOption("IncludeRegularExpression",
+ args[i].c_str());
}
if (this->CheckArgument(arg, "-L", "--label-regex") && i < args.size() - 1) {
i++;
- this->GetHandler("test")->SetPersistentOption("LabelRegularExpression",
- args[i].c_str());
- this->GetHandler("memcheck")
- ->SetPersistentOption("LabelRegularExpression", args[i].c_str());
+ this->GetTestHandler()->SetPersistentOption("LabelRegularExpression",
+ args[i].c_str());
+ this->GetMemCheckHandler()->SetPersistentOption("LabelRegularExpression",
+ args[i].c_str());
}
if (this->CheckArgument(arg, "-LE", "--label-exclude") &&
i < args.size() - 1) {
i++;
- this->GetHandler("test")->SetPersistentOption(
+ this->GetTestHandler()->SetPersistentOption(
+ "ExcludeLabelRegularExpression", args[i].c_str());
+ this->GetMemCheckHandler()->SetPersistentOption(
"ExcludeLabelRegularExpression", args[i].c_str());
- this->GetHandler("memcheck")
- ->SetPersistentOption("ExcludeLabelRegularExpression", args[i].c_str());
}
if (this->CheckArgument(arg, "-E", "--exclude-regex") &&
i < args.size() - 1) {
i++;
- this->GetHandler("test")->SetPersistentOption("ExcludeRegularExpression",
- args[i].c_str());
- this->GetHandler("memcheck")
- ->SetPersistentOption("ExcludeRegularExpression", args[i].c_str());
+ this->GetTestHandler()->SetPersistentOption("ExcludeRegularExpression",
+ args[i].c_str());
+ this->GetMemCheckHandler()->SetPersistentOption("ExcludeRegularExpression",
+ args[i].c_str());
}
if (this->CheckArgument(arg, "-FA", "--fixture-exclude-any") &&
i < args.size() - 1) {
i++;
- this->GetHandler("test")->SetPersistentOption(
+ this->GetTestHandler()->SetPersistentOption(
+ "ExcludeFixtureRegularExpression", args[i].c_str());
+ this->GetMemCheckHandler()->SetPersistentOption(
"ExcludeFixtureRegularExpression", args[i].c_str());
- this->GetHandler("memcheck")
- ->SetPersistentOption("ExcludeFixtureRegularExpression",
- args[i].c_str());
}
if (this->CheckArgument(arg, "-FS", "--fixture-exclude-setup") &&
i < args.size() - 1) {
i++;
- this->GetHandler("test")->SetPersistentOption(
+ this->GetTestHandler()->SetPersistentOption(
+ "ExcludeFixtureSetupRegularExpression", args[i].c_str());
+ this->GetMemCheckHandler()->SetPersistentOption(
"ExcludeFixtureSetupRegularExpression", args[i].c_str());
- this->GetHandler("memcheck")
- ->SetPersistentOption("ExcludeFixtureSetupRegularExpression",
- args[i].c_str());
}
if (this->CheckArgument(arg, "-FC", "--fixture-exclude-cleanup") &&
i < args.size() - 1) {
i++;
- this->GetHandler("test")->SetPersistentOption(
+ this->GetTestHandler()->SetPersistentOption(
"ExcludeFixtureCleanupRegularExpression", args[i].c_str());
- this->GetHandler("memcheck")
- ->SetPersistentOption("ExcludeFixtureCleanupRegularExpression",
- args[i].c_str());
+ this->GetMemCheckHandler()->SetPersistentOption(
+ "ExcludeFixtureCleanupRegularExpression", args[i].c_str());
+ }
+
+ if (this->CheckArgument(arg, "--resource-spec-file") &&
+ i < args.size() - 1) {
+ i++;
+ this->GetTestHandler()->SetPersistentOption("ResourceSpecFile",
+ args[i].c_str());
+ this->GetMemCheckHandler()->SetPersistentOption("ResourceSpecFile",
+ args[i].c_str());
}
if (this->CheckArgument(arg, "--rerun-failed")) {
- this->GetHandler("test")->SetPersistentOption("RerunFailed", "true");
- this->GetHandler("memcheck")->SetPersistentOption("RerunFailed", "true");
+ this->GetTestHandler()->SetPersistentOption("RerunFailed", "true");
+ this->GetMemCheckHandler()->SetPersistentOption("RerunFailed", "true");
}
return true;
}
+#if !defined(_WIN32)
+bool cmCTest::ConsoleIsNotDumb()
+{
+ std::string term_env_variable;
+ if (cmSystemTools::GetEnv("TERM", term_env_variable)) {
+ return isatty(1) && term_env_variable != "dumb";
+ }
+ return false;
+}
+#endif
+
+bool cmCTest::ProgressOutputSupportedByConsole()
+{
+#if defined(_WIN32)
+ // On Windows we need a console buffer.
+ void* console = GetStdHandle(STD_OUTPUT_HANDLE);
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ return GetConsoleScreenBufferInfo(console, &csbi);
+#else
+ // On UNIX we need a non-dumb tty.
+ return ConsoleIsNotDumb();
+#endif
+}
+
+bool cmCTest::ColoredOutputSupportedByConsole()
+{
+#if defined(_WIN32)
+ // Not supported on Windows
+ return false;
+#else
+ // On UNIX we need a non-dumb tty.
+ std::string clicolor_force;
+ if (cmSystemTools::GetEnv("CLICOLOR_FORCE", clicolor_force) &&
+ !clicolor_force.empty() && clicolor_force != "0") {
+ return true;
+ }
+ return ConsoleIsNotDumb();
+#endif
+}
+
// handle the -S -SR and -SP arguments
void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args,
bool& SRArgumentSpecified)
@@ -1940,10 +2153,9 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args,
std::string arg = args[i];
if (this->CheckArgument(arg, "-SP", "--script-new-process") &&
i < args.size() - 1) {
- this->RunConfigurationScript = true;
+ this->Impl->RunConfigurationScript = true;
i++;
- cmCTestScriptHandler* ch =
- static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
+ cmCTestScriptHandler* ch = this->GetScriptHandler();
// -SR is an internal argument, -SP should be ignored when it is passed
if (!SRArgumentSpecified) {
ch->AddConfigurationScript(args[i].c_str(), false);
@@ -1952,18 +2164,16 @@ void cmCTest::HandleScriptArguments(size_t& i, std::vector<std::string>& args,
if (this->CheckArgument(arg, "-SR", "--script-run") && i < args.size() - 1) {
SRArgumentSpecified = true;
- this->RunConfigurationScript = true;
+ this->Impl->RunConfigurationScript = true;
i++;
- cmCTestScriptHandler* ch =
- static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
+ cmCTestScriptHandler* ch = this->GetScriptHandler();
ch->AddConfigurationScript(args[i].c_str(), true);
}
if (this->CheckArgument(arg, "-S", "--script") && i < args.size() - 1) {
- this->RunConfigurationScript = true;
+ this->Impl->RunConfigurationScript = true;
i++;
- cmCTestScriptHandler* ch =
- static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
+ cmCTestScriptHandler* ch = this->GetScriptHandler();
// -SR is an internal argument, -S should be ignored when it is passed
if (!SRArgumentSpecified) {
ch->AddConfigurationScript(args[i].c_str(), true);
@@ -1978,7 +2188,7 @@ bool cmCTest::AddVariableDefinition(const std::string& arg)
cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED;
if (cmake::ParseCacheEntry(arg, name, value, type)) {
- this->Definitions[name] = value;
+ this->Impl->Definitions[name] = value;
return true;
}
@@ -1994,15 +2204,14 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output)
bool SRArgumentSpecified = false;
// copy the command line
- this->InitialCommandLineArguments.insert(
- this->InitialCommandLineArguments.end(), args.begin(), args.end());
+ cmAppend(this->Impl->InitialCommandLineArguments, args);
// process the command line arguments
for (size_t i = 1; i < args.size(); ++i) {
// handle the simple commandline arguments
std::string errormsg;
if (!this->HandleCommandLineArguments(i, args, errormsg)) {
- cmSystemTools::Error(errormsg.c_str());
+ cmSystemTools::Error(errormsg);
return 1;
}
@@ -2012,7 +2221,7 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output)
// --dashboard: handle a request for a dashboard
std::string arg = args[i];
if (this->CheckArgument(arg, "-D", "--dashboard") && i < args.size() - 1) {
- this->ProduceXML = true;
+ this->Impl->ProduceXML = true;
i++;
std::string targ = args[i];
// AddTestsForDashboard parses the dashboard type and converts it
@@ -2030,7 +2239,7 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output)
// attempts are simply ignored since previous ctest versions ignore
// this too. (As well as many other unknown command line args.)
//
- if (arg != "-D" && cmSystemTools::StringStartsWith(arg.c_str(), "-D")) {
+ if (arg != "-D" && cmHasLiteralPrefix(arg, "-D")) {
std::string input = arg.substr(2);
this->AddVariableDefinition(input);
}
@@ -2048,7 +2257,7 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output)
// --extra-submit
if (this->CheckArgument(arg, "--extra-submit") && i < args.size() - 1) {
- this->ProduceXML = true;
+ this->Impl->ProduceXML = true;
this->SetTest("Submit");
i++;
if (!this->SubmitExtraFiles(args[i].c_str())) {
@@ -2063,16 +2272,14 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output)
// --schedule-random
if (this->CheckArgument(arg, "--schedule-random")) {
- this->ScheduleType = "Random";
+ this->Impl->ScheduleType = "Random";
}
// pass the argument to all the handlers as well, but i may no longer be
// set to what it was originally so I'm not sure this is working as
// intended
- cmCTest::t_TestingHandlers::iterator it;
- for (it = this->TestingHandlers.begin(); it != this->TestingHandlers.end();
- ++it) {
- if (!it->second->ProcessCommandLineArguments(arg, i, args)) {
+ for (auto& handler : this->Impl->GetTestingHandlers()) {
+ if (!handler->ProcessCommandLineArguments(arg, i, args)) {
cmCTestLog(this, ERROR_MESSAGE,
"Problem parsing command line arguments within a handler");
return 0;
@@ -2081,7 +2288,7 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output)
} // the close of the for argument loop
// handle CTEST_PARALLEL_LEVEL environment variable
- if (!this->ParallelLevelSetInCli) {
+ if (!this->Impl->ParallelLevelSetInCli) {
std::string parallel;
if (cmSystemTools::GetEnv("CTEST_PARALLEL_LEVEL", parallel)) {
int plevel = atoi(parallel.c_str());
@@ -2089,6 +2296,18 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output)
}
}
+ // TestProgressOutput only supported if console supports it and not logging
+ // to a file
+ this->Impl->TestProgressOutput = this->Impl->TestProgressOutput &&
+ !this->Impl->OutputLogFile && this->ProgressOutputSupportedByConsole();
+#ifdef _WIN32
+ if (this->Impl->TestProgressOutput) {
+ // Disable output line buffering so we can print content without
+ // a newline.
+ std::setvbuf(stdout, nullptr, _IONBF, 0);
+ }
+#endif
+
// now what should cmake do? if --build-and-test was specified then
// we run the build and test handler and return
if (cmakeAndTest) {
@@ -2109,13 +2328,15 @@ bool cmCTest::HandleTestActionArgument(const char* ctestExec, size_t& i,
std::string arg = args[i];
if (this->CheckArgument(arg, "-T", "--test-action") &&
(i < args.size() - 1)) {
- this->ProduceXML = true;
+ this->Impl->ProduceXML = true;
i++;
if (!this->SetTest(args[i].c_str(), false)) {
success = false;
- cmCTestLog(this, ERROR_MESSAGE, "CTest -T called with incorrect option: "
- << args[i] << std::endl);
- cmCTestLog(this, ERROR_MESSAGE, "Available options are:"
+ cmCTestLog(this, ERROR_MESSAGE,
+ "CTest -T called with incorrect option: " << args[i]
+ << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Available options are:"
<< std::endl
<< " " << ctestExec << " -T all" << std::endl
<< " " << ctestExec << " -T start" << std::endl
@@ -2149,9 +2370,11 @@ bool cmCTest::HandleTestModelArgument(const char* ctestExec, size_t& i,
this->SetTestModel(cmCTest::EXPERIMENTAL);
} else {
success = false;
- cmCTestLog(this, ERROR_MESSAGE, "CTest -M called with incorrect option: "
- << str << std::endl);
- cmCTestLog(this, ERROR_MESSAGE, "Available options are:"
+ cmCTestLog(this, ERROR_MESSAGE,
+ "CTest -M called with incorrect option: " << str
+ << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Available options are:"
<< std::endl
<< " " << ctestExec << " -M Continuous" << std::endl
<< " " << ctestExec << " -M Experimental" << std::endl
@@ -2165,18 +2388,16 @@ int cmCTest::ExecuteTests()
{
int res;
// call process directory
- if (this->RunConfigurationScript) {
- if (this->ExtraVerbose) {
+ if (this->Impl->RunConfigurationScript) {
+ if (this->Impl->ExtraVerbose) {
cmCTestLog(this, OUTPUT, "* Extra verbosity turned on" << std::endl);
}
- cmCTest::t_TestingHandlers::iterator it;
- for (it = this->TestingHandlers.begin(); it != this->TestingHandlers.end();
- ++it) {
- it->second->SetVerbose(this->ExtraVerbose);
- it->second->SetSubmitIndex(this->SubmitIndex);
+ for (auto& handler : this->Impl->GetTestingHandlers()) {
+ handler->SetVerbose(this->Impl->ExtraVerbose);
+ handler->SetSubmitIndex(this->Impl->SubmitIndex);
}
- this->GetHandler("script")->SetVerbose(this->Verbose);
- res = this->GetHandler("script")->ProcessHandler();
+ this->GetScriptHandler()->SetVerbose(this->Impl->Verbose);
+ res = this->GetScriptHandler()->ProcessHandler();
if (res != 0) {
cmCTestLog(this, DEBUG,
"running script failing returning: " << res << std::endl);
@@ -2185,19 +2406,17 @@ int cmCTest::ExecuteTests()
} else {
// What is this? -V seems to be the same as -VV,
// and Verbose is always on in this case
- this->ExtraVerbose = this->Verbose;
- this->Verbose = true;
- cmCTest::t_TestingHandlers::iterator it;
- for (it = this->TestingHandlers.begin(); it != this->TestingHandlers.end();
- ++it) {
- it->second->SetVerbose(this->Verbose);
- it->second->SetSubmitIndex(this->SubmitIndex);
+ this->Impl->ExtraVerbose = this->Impl->Verbose;
+ this->Impl->Verbose = true;
+ for (auto& handler : this->Impl->GetTestingHandlers()) {
+ handler->SetVerbose(this->Impl->Verbose);
+ handler->SetSubmitIndex(this->Impl->SubmitIndex);
}
std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
- if (!this->Initialize(cwd.c_str(), CM_NULLPTR)) {
+ if (!this->Initialize(cwd.c_str(), nullptr)) {
res = 12;
- cmCTestLog(this, ERROR_MESSAGE, "Problem initializing the dashboard."
- << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Problem initializing the dashboard." << std::endl);
} else {
res = this->ProcessSteps();
}
@@ -2212,17 +2431,16 @@ int cmCTest::ExecuteTests()
int cmCTest::RunCMakeAndTest(std::string* output)
{
- this->Verbose = true;
- cmCTestBuildAndTestHandler* handler =
- static_cast<cmCTestBuildAndTestHandler*>(this->GetHandler("buildtest"));
+ this->Impl->Verbose = true;
+ cmCTestBuildAndTestHandler* handler = this->GetBuildAndTestHandler();
int retv = handler->ProcessHandler();
*output = handler->GetOutput();
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
cmDynamicLoader::FlushCache();
#endif
if (retv != 0) {
- cmCTestLog(this, DEBUG, "build and test failing returning: " << retv
- << std::endl);
+ cmCTestLog(this, DEBUG,
+ "build and test failing returning: " << retv << std::endl);
}
return retv;
}
@@ -2232,36 +2450,81 @@ void cmCTest::SetNotesFiles(const char* notes)
if (!notes) {
return;
}
- this->NotesFiles = notes;
+ this->Impl->NotesFiles = notes;
}
-void cmCTest::SetStopTime(std::string const& time)
+std::chrono::system_clock::time_point cmCTest::GetStopTime() const
{
- this->StopTime = time;
- this->DetermineNextDayStop();
+ return this->Impl->StopTime;
+}
+
+void cmCTest::SetStopTime(std::string const& time_str)
+{
+
+ 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->Impl->StopTime = std::chrono::system_clock::time_point();
+ return;
+ }
+ this->Impl->StopTime = std::chrono::system_clock::from_time_t(stop_time);
+
+ if (stop_time < current_time) {
+ this->Impl->StopTime += std::chrono::hours(24);
+ }
+}
+
+std::string cmCTest::GetScheduleType() const
+{
+ return this->Impl->ScheduleType;
+}
+
+void cmCTest::SetScheduleType(std::string const& type)
+{
+ this->Impl->ScheduleType = type;
}
int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf)
{
bool found = false;
- VectorOfStrings dirs;
- VectorOfStrings ndirs;
- cmCTestLog(this, DEBUG, "* Read custom CTest configuration directory: "
- << dir << std::endl);
+ cmCTestLog(this, DEBUG,
+ "* Read custom CTest configuration directory: " << dir
+ << std::endl);
- std::string fname = dir;
- fname += "/CTestCustom.cmake";
+ std::string fname = cmStrCat(dir, "/CTestCustom.cmake");
cmCTestLog(this, DEBUG, "* Check for file: " << fname << std::endl);
- if (cmSystemTools::FileExists(fname.c_str())) {
- cmCTestLog(this, DEBUG, "* Read custom CTest configuration file: "
- << fname << std::endl);
+ if (cmSystemTools::FileExists(fname)) {
+ cmCTestLog(this, DEBUG,
+ "* Read custom CTest configuration file: " << fname
+ << std::endl);
bool erroroc = cmSystemTools::GetErrorOccuredFlag();
cmSystemTools::ResetErrorOccuredFlag();
- if (!mf->ReadListFile(fname.c_str()) ||
- cmSystemTools::GetErrorOccuredFlag()) {
- cmCTestLog(this, ERROR_MESSAGE, "Problem reading custom configuration: "
- << fname << std::endl);
+ if (!mf->ReadListFile(fname) || cmSystemTools::GetErrorOccuredFlag()) {
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Problem reading custom configuration: " << fname
+ << std::endl);
}
found = true;
if (erroroc) {
@@ -2269,22 +2532,20 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf)
}
}
- std::string rexpr = dir;
- rexpr += "/CTestCustom.ctest";
+ std::string rexpr = cmStrCat(dir, "/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);
std::vector<std::string>& files = gl.GetFiles();
- std::vector<std::string>::iterator fileIt;
- for (fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
- cmCTestLog(this, DEBUG, "* Read custom CTest configuration file: "
- << *fileIt << std::endl);
- if (!mf->ReadListFile(fileIt->c_str()) ||
- cmSystemTools::GetErrorOccuredFlag()) {
+ for (const std::string& file : files) {
+ cmCTestLog(this, DEBUG,
+ "* Read custom CTest configuration file: " << file
+ << std::endl);
+ if (!mf->ReadListFile(file) || cmSystemTools::GetErrorOccuredFlag()) {
cmCTestLog(this, ERROR_MESSAGE,
- "Problem reading custom configuration: " << *fileIt
+ "Problem reading custom configuration: " << file
<< std::endl);
}
}
@@ -2292,13 +2553,12 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf)
}
if (found) {
- cmCTest::t_TestingHandlers::iterator it;
- for (it = this->TestingHandlers.begin(); it != this->TestingHandlers.end();
- ++it) {
+ for (auto& handler : this->Impl->GetNamedTestingHandlers()) {
cmCTestLog(this, DEBUG,
"* Read custom CTest configuration vectors for handler: "
- << it->first << " (" << it->second << ")" << std::endl);
- it->second->PopulateCustomVectors(mf);
+ << handler.first << " (" << handler.second << ")"
+ << std::endl);
+ handler.second->PopulateCustomVectors(mf);
}
}
@@ -2315,11 +2575,10 @@ void cmCTest::PopulateCustomVector(cmMakefile* mf, const std::string& def,
cmCTestLog(this, DEBUG, "PopulateCustomVector: " << def << std::endl);
vec.clear();
- cmSystemTools::ExpandListArgument(dval, vec);
+ cmExpandList(dval, vec);
- for (std::vector<std::string>::const_iterator it = vec.begin();
- it != vec.end(); ++it) {
- cmCTestLog(this, DEBUG, " -- " << *it << std::endl);
+ for (std::string const& it : vec) {
+ cmCTestLog(this, DEBUG, " -- " << it << std::endl);
}
}
@@ -2342,17 +2601,15 @@ 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;
bool inBld = bldRelpath.find("..") == std::string::npos;
// TODO: Handle files with .. in their name
- std::string* res = CM_NULLPTR;
+ std::string* res = nullptr;
if (inSrc && inBld) {
// If both have relative path with no dots, pick the shorter one
@@ -2375,7 +2632,7 @@ std::string cmCTest::GetShortPathToFile(const char* cfname)
cmSystemTools::ConvertToUnixSlashes(*res);
path = "./" + *res;
- if (path[path.size() - 1] == '/') {
+ if (path.back() == '/') {
path = path.substr(0, path.size() - 1);
}
}
@@ -2387,54 +2644,23 @@ std::string cmCTest::GetShortPathToFile(const char* cfname)
std::string cmCTest::GetCTestConfiguration(const std::string& name)
{
- if (this->CTestConfigurationOverwrites.find(name) !=
- this->CTestConfigurationOverwrites.end()) {
- return this->CTestConfigurationOverwrites[name];
+ if (this->Impl->CTestConfigurationOverwrites.find(name) !=
+ this->Impl->CTestConfigurationOverwrites.end()) {
+ return this->Impl->CTestConfigurationOverwrites[name];
}
- return this->CTestConfiguration[name];
+ return this->Impl->CTestConfiguration[name];
}
void cmCTest::EmptyCTestConfiguration()
{
- this->CTestConfiguration.clear();
-}
-
-void cmCTest::DetermineNextDayStop()
-{
- struct tm* lctime;
- time_t current_time = time(CM_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;
- }
+ this->Impl->CTestConfiguration.clear();
}
void cmCTest::SetCTestConfiguration(const char* name, const char* value,
bool suppress)
{
- cmCTestOptionalLog(this, HANDLER_VERBOSE_OUTPUT, "SetCTestConfiguration:"
+ cmCTestOptionalLog(this, HANDLER_VERBOSE_OUTPUT,
+ "SetCTestConfiguration:"
<< name << ":" << (value ? value : "(null)") << "\n",
suppress);
@@ -2442,67 +2668,223 @@ void cmCTest::SetCTestConfiguration(const char* name, const char* value,
return;
}
if (!value) {
- this->CTestConfiguration.erase(name);
+ this->Impl->CTestConfiguration.erase(name);
return;
}
- this->CTestConfiguration[name] = value;
+ this->Impl->CTestConfiguration[name] = value;
+}
+
+std::string cmCTest::GetSubmitURL()
+{
+ std::string url = this->GetCTestConfiguration("SubmitURL");
+ if (url.empty()) {
+ std::string method = this->GetCTestConfiguration("DropMethod");
+ std::string user = this->GetCTestConfiguration("DropSiteUser");
+ std::string password = this->GetCTestConfiguration("DropSitePassword");
+ std::string site = this->GetCTestConfiguration("DropSite");
+ std::string location = this->GetCTestConfiguration("DropLocation");
+
+ url = cmStrCat(method.empty() ? "http" : method, "://");
+ if (!user.empty()) {
+ url += user;
+ if (!password.empty()) {
+ url += ':';
+ url += password;
+ }
+ url += '@';
+ }
+ url += site;
+ url += location;
+ }
+ return url;
}
std::string cmCTest::GetCurrentTag()
{
- return this->CurrentTag;
+ return this->Impl->CurrentTag;
}
std::string cmCTest::GetBinaryDir()
{
- return this->BinaryDir;
+ return this->Impl->BinaryDir;
}
std::string const& cmCTest::GetConfigType()
{
- return this->ConfigType;
+ return this->Impl->ConfigType;
+}
+
+cmDuration cmCTest::GetTimeOut() const
+{
+ return this->Impl->TimeOut;
+}
+
+void cmCTest::SetTimeOut(cmDuration t)
+{
+ this->Impl->TimeOut = t;
+}
+
+cmDuration cmCTest::GetGlobalTimeout() const
+{
+ return this->Impl->GlobalTimeout;
}
bool cmCTest::GetShowOnly()
{
- return this->ShowOnly;
+ return this->Impl->ShowOnly;
+}
+
+bool cmCTest::GetOutputAsJson()
+{
+ return this->Impl->OutputAsJson;
+}
+
+int cmCTest::GetOutputAsJsonVersion()
+{
+ return this->Impl->OutputAsJsonVersion;
+}
+
+bool cmCTest::ShouldUseHTTP10() const
+{
+ return this->Impl->UseHTTP10;
+}
+
+bool cmCTest::ShouldPrintLabels() const
+{
+ return this->Impl->PrintLabels;
}
int cmCTest::GetMaxTestNameWidth() const
{
- return this->MaxTestNameWidth;
+ return this->Impl->MaxTestNameWidth;
+}
+
+void cmCTest::SetMaxTestNameWidth(int w)
+{
+ this->Impl->MaxTestNameWidth = w;
}
void cmCTest::SetProduceXML(bool v)
{
- this->ProduceXML = v;
+ this->Impl->ProduceXML = v;
}
bool cmCTest::GetProduceXML()
{
- return this->ProduceXML;
+ return this->Impl->ProduceXML;
}
-const char* cmCTest::GetSpecificTrack()
+std::vector<std::string>& cmCTest::GetInitialCommandLineArguments()
{
- if (this->SpecificTrack.empty()) {
- return CM_NULLPTR;
+ return this->Impl->InitialCommandLineArguments;
+}
+
+const char* cmCTest::GetSpecificGroup()
+{
+ if (this->Impl->SpecificGroup.empty()) {
+ return nullptr;
}
- return this->SpecificTrack.c_str();
+ return this->Impl->SpecificGroup.c_str();
}
-void cmCTest::SetSpecificTrack(const char* track)
+void cmCTest::SetSpecificGroup(const char* group)
{
- if (!track) {
- this->SpecificTrack = "";
+ if (!group) {
+ this->Impl->SpecificGroup.clear();
return;
}
- this->SpecificTrack = track;
+ this->Impl->SpecificGroup = group;
+}
+
+void cmCTest::SetFailover(bool failover)
+{
+ this->Impl->Failover = failover;
+}
+
+bool cmCTest::GetFailover() const
+{
+ return this->Impl->Failover;
+}
+
+bool cmCTest::GetTestProgressOutput() const
+{
+ return this->Impl->TestProgressOutput;
+}
+
+bool cmCTest::GetVerbose() const
+{
+ return this->Impl->Verbose;
+}
+
+bool cmCTest::GetExtraVerbose() const
+{
+ return this->Impl->ExtraVerbose;
+}
+
+void cmCTest::SetStreams(std::ostream* out, std::ostream* err)
+{
+ this->Impl->StreamOut = out;
+ this->Impl->StreamErr = err;
+}
+
+bool cmCTest::GetLabelSummary() const
+{
+ return this->Impl->LabelSummary;
+}
+
+bool cmCTest::GetSubprojectSummary() const
+{
+ return this->Impl->SubprojectSummary;
+}
+
+bool cmCTest::GetOutputTestOutputOnTestFailure() const
+{
+ return this->Impl->OutputTestOutputOnTestFailure;
+}
+
+const std::map<std::string, std::string>& cmCTest::GetDefinitions() const
+{
+ return this->Impl->Definitions;
+}
+
+int cmCTest::GetTestRepeat() const
+{
+ return this->Impl->RepeatTests;
+}
+
+bool cmCTest::GetRepeatUntilFail() const
+{
+ return this->Impl->RepeatUntilFail;
+}
+
+void cmCTest::SetBuildID(const std::string& id)
+{
+ this->Impl->BuildID = id;
+}
+
+std::string cmCTest::GetBuildID() const
+{
+ return this->Impl->BuildID;
}
void cmCTest::AddSubmitFile(Part part, const char* name)
{
- this->Parts[part].SubmitFiles.push_back(name);
+ this->Impl->Parts[part].SubmitFiles.emplace_back(name);
+}
+
+std::vector<std::string> const& cmCTest::GetSubmitFiles(Part part) const
+{
+ return this->Impl->Parts[part].SubmitFiles;
+}
+
+void cmCTest::ClearSubmitFiles(Part part)
+{
+ this->Impl->Parts[part].SubmitFiles.clear();
+}
+
+void cmCTest::SetSuppressUpdatingCTestConfiguration(bool val)
+{
+ this->Impl->SuppressUpdatingCTestConfiguration = val;
}
void cmCTest::AddCTestConfigurationOverwrite(const std::string& overStr)
@@ -2518,14 +2900,14 @@ void cmCTest::AddCTestConfigurationOverwrite(const std::string& overStr)
}
std::string key = overStr.substr(0, epos);
std::string value = overStr.substr(epos + 1);
- this->CTestConfigurationOverwrites[key] = value;
+ this->Impl->CTestConfigurationOverwrites[key] = value;
}
void cmCTest::SetConfigType(const char* ct)
{
- this->ConfigType = ct ? ct : "";
- cmSystemTools::ReplaceString(this->ConfigType, ".\\", "");
- std::string confTypeEnv = "CMAKE_CONFIG_TYPE=" + this->ConfigType;
+ this->Impl->ConfigType = ct ? ct : "";
+ cmSystemTools::ReplaceString(this->Impl->ConfigType, ".\\", "");
+ std::string confTypeEnv = "CMAKE_CONFIG_TYPE=" + this->Impl->ConfigType;
cmSystemTools::PutEnv(confTypeEnv);
}
@@ -2546,33 +2928,28 @@ bool cmCTest::SetCTestConfigurationFromCMakeVariable(
return true;
}
-bool cmCTest::RunCommand(const char* command, std::string* stdOut,
- std::string* stdErr, int* retVal, const char* dir,
- double timeout, Encoding encoding)
+bool cmCTest::RunCommand(std::vector<std::string> const& args,
+ std::string* stdOut, std::string* stdErr, int* retVal,
+ const char* dir, cmDuration timeout,
+ Encoding encoding)
{
- std::vector<std::string> args = cmSystemTools::ParseArguments(command);
-
- if (args.empty()) {
- return false;
- }
-
std::vector<const char*> argv;
- for (std::vector<std::string>::const_iterator a = args.begin();
- a != args.end(); ++a) {
- argv.push_back(a->c_str());
+ argv.reserve(args.size() + 1);
+ for (std::string const& a : args) {
+ argv.push_back(a.c_str());
}
- argv.push_back(CM_NULLPTR);
+ argv.push_back(nullptr);
- *stdOut = "";
- *stdErr = "";
+ stdOut->clear();
+ stdErr->clear();
cmsysProcess* cp = cmsysProcess_New();
- cmsysProcess_SetCommand(cp, &*argv.begin());
+ cmsysProcess_SetCommand(cp, argv.data());
cmsysProcess_SetWorkingDirectory(cp, dir);
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;
@@ -2584,38 +2961,38 @@ bool cmCTest::RunCommand(const char* command, std::string* stdOut,
int res;
bool done = false;
while (!done) {
- res = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR);
+ res = cmsysProcess_WaitForData(cp, &data, &length, nullptr);
switch (res) {
case cmsysProcess_Pipe_STDOUT:
- tempOutput.insert(tempOutput.end(), data, data + length);
+ cmAppend(tempOutput, data, data + length);
break;
case cmsysProcess_Pipe_STDERR:
- tempError.insert(tempError.end(), data, data + length);
+ cmAppend(tempError, data, data + length);
break;
default:
done = true;
}
if ((res == cmsysProcess_Pipe_STDOUT || res == cmsysProcess_Pipe_STDERR) &&
- this->ExtraVerbose) {
+ this->Impl->ExtraVerbose) {
processOutput.DecodeText(data, length, strdata);
- cmSystemTools::Stdout(strdata.c_str(), strdata.size());
+ cmSystemTools::Stdout(strdata);
}
}
- if (this->ExtraVerbose) {
+ if (this->Impl->ExtraVerbose) {
processOutput.DecodeText(std::string(), strdata);
if (!strdata.empty()) {
- cmSystemTools::Stdout(strdata.c_str(), strdata.size());
+ cmSystemTools::Stdout(strdata);
}
}
- cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+ cmsysProcess_WaitForExit(cp, nullptr);
if (!tempOutput.empty()) {
processOutput.DecodeText(tempOutput, tempOutput);
- stdOut->append(&*tempOutput.begin(), tempOutput.size());
+ stdOut->append(tempOutput.data(), tempOutput.size());
}
if (!tempError.empty()) {
processOutput.DecodeText(tempError, tempError);
- stdErr->append(&*tempError.begin(), tempError.size());
+ stdErr->append(tempError.data(), tempError.size());
}
bool result = true;
@@ -2650,12 +3027,12 @@ bool cmCTest::RunCommand(const char* command, std::string* stdOut,
void cmCTest::SetOutputLogFileName(const char* name)
{
- if (this->OutputLogFile) {
- delete this->OutputLogFile;
- this->OutputLogFile = CM_NULLPTR;
+ if (this->Impl->OutputLogFile) {
+ delete this->Impl->OutputLogFile;
+ this->Impl->OutputLogFile = nullptr;
}
if (name) {
- this->OutputLogFile = new cmGeneratedFileStream(name);
+ this->Impl->OutputLogFile = new cmGeneratedFileStream(name);
}
}
@@ -2663,22 +3040,18 @@ static const char* cmCTestStringLogType[] = { "DEBUG",
"OUTPUT",
"HANDLER_OUTPUT",
"HANDLER_PROGRESS_OUTPUT",
+ "HANDLER_TEST_PROGRESS_OUTPUT",
"HANDLER_VERBOSE_OUTPUT",
"WARNING",
"ERROR_MESSAGE",
- CM_NULLPTR };
+ nullptr };
#define cmCTestLogOutputFileLine(stream) \
- if (this->ShowLineNumbers) { \
- (stream) << std::endl << file << ":" << line << " "; \
- }
-
-void cmCTest::InitStreams()
-{
- // By default we write output to the process output streams.
- this->StreamOut = &std::cout;
- this->StreamErr = &std::cerr;
-}
+ do { \
+ if (this->Impl->ShowLineNumbers) { \
+ (stream) << std::endl << file << ":" << line << " "; \
+ } \
+ } while (false)
void cmCTest::Log(int logType, const char* file, int line, const char* msg,
bool suppress)
@@ -2690,42 +3063,70 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg,
return;
}
if (logType == cmCTest::HANDLER_PROGRESS_OUTPUT &&
- (this->Debug || this->ExtraVerbose)) {
+ (this->Impl->Debug || this->Impl->ExtraVerbose)) {
return;
}
- if (this->OutputLogFile) {
+ if (this->Impl->OutputLogFile) {
bool display = true;
- if (logType == cmCTest::DEBUG && !this->Debug) {
+ if (logType == cmCTest::DEBUG && !this->Impl->Debug) {
display = false;
}
- if (logType == cmCTest::HANDLER_VERBOSE_OUTPUT && !this->Debug &&
- !this->ExtraVerbose) {
+ if (logType == cmCTest::HANDLER_VERBOSE_OUTPUT && !this->Impl->Debug &&
+ !this->Impl->ExtraVerbose) {
display = false;
}
if (display) {
- cmCTestLogOutputFileLine(*this->OutputLogFile);
- if (logType != this->OutputLogFileLastTag) {
- *this->OutputLogFile << "[";
+ cmCTestLogOutputFileLine(*this->Impl->OutputLogFile);
+ if (logType != this->Impl->OutputLogFileLastTag) {
+ *this->Impl->OutputLogFile << "[";
if (logType >= OTHER || logType < 0) {
- *this->OutputLogFile << "OTHER";
+ *this->Impl->OutputLogFile << "OTHER";
} else {
- *this->OutputLogFile << cmCTestStringLogType[logType];
+ *this->Impl->OutputLogFile << cmCTestStringLogType[logType];
}
- *this->OutputLogFile << "] " << std::endl << std::flush;
+ *this->Impl->OutputLogFile << "] " << std::endl;
}
- *this->OutputLogFile << msg << std::flush;
- if (logType != this->OutputLogFileLastTag) {
- *this->OutputLogFile << std::endl << std::flush;
- this->OutputLogFileLastTag = logType;
+ *this->Impl->OutputLogFile << msg << std::flush;
+ if (logType != this->Impl->OutputLogFileLastTag) {
+ *this->Impl->OutputLogFile << std::endl;
+ this->Impl->OutputLogFileLastTag = logType;
}
}
}
- if (!this->Quiet) {
- std::ostream& out = *this->StreamOut;
- std::ostream& err = *this->StreamErr;
+ if (!this->Impl->Quiet) {
+ std::ostream& out = *this->Impl->StreamOut;
+ std::ostream& err = *this->Impl->StreamErr;
+
+ if (logType == HANDLER_TEST_PROGRESS_OUTPUT) {
+ if (this->Impl->TestProgressOutput) {
+ cmCTestLogOutputFileLine(out);
+ if (this->Impl->FlushTestProgressLine) {
+ printf("\r");
+ this->Impl->FlushTestProgressLine = false;
+ out.flush();
+ }
+
+ std::string msg_str{ msg };
+ auto const lineBreakIt = msg_str.find('\n');
+ if (lineBreakIt != std::string::npos) {
+ this->Impl->FlushTestProgressLine = true;
+ msg_str.erase(std::remove(msg_str.begin(), msg_str.end(), '\n'),
+ msg_str.end());
+ }
+
+ out << msg_str;
+#ifndef _WIN32
+ printf("\x1B[K"); // move caret to end
+#endif
+ out.flush();
+ return;
+ }
+ logType = HANDLER_OUTPUT;
+ }
+
switch (logType) {
case DEBUG:
- if (this->Debug) {
+ if (this->Impl->Debug) {
cmCTestLogOutputFileLine(out);
out << msg;
out.flush();
@@ -2733,14 +3134,14 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg,
break;
case OUTPUT:
case HANDLER_OUTPUT:
- if (this->Debug || this->Verbose) {
+ if (this->Impl->Debug || this->Impl->Verbose) {
cmCTestLogOutputFileLine(out);
out << msg;
out.flush();
}
break;
case HANDLER_VERBOSE_OUTPUT:
- if (this->Debug || this->ExtraVerbose) {
+ if (this->Impl->Debug || this->Impl->ExtraVerbose) {
cmCTestLogOutputFileLine(out);
out << msg;
out.flush();
@@ -2765,25 +3166,42 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg,
}
}
-double cmCTest::GetRemainingTimeAllowed()
+std::string cmCTest::GetColorCode(Color color) const
{
- if (!this->GetHandler("script")) {
- return 1.0e7;
+ if (this->Impl->OutputColorCode) {
+#if defined(_WIN32)
+ // Not supported on Windows
+ static_cast<void>(color);
+#else
+ return "\033[0;" + std::to_string(static_cast<int>(color)) + "m";
+#endif
}
- cmCTestScriptHandler* ch =
- static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
+ return "";
+}
- return ch->GetRemainingTimeAllowed();
+cmDuration cmCTest::GetRemainingTimeAllowed()
+{
+ return this->GetScriptHandler()->GetRemainingTimeAllowed();
+}
+
+cmDuration cmCTest::MaxDuration()
+{
+ return cmDuration(1.0e7);
+}
+
+void cmCTest::SetRunCurrentScript(bool value)
+{
+ this->GetScriptHandler()->SetRunCurrentScript(value);
}
void cmCTest::OutputTestErrors(std::vector<char> const& process_output)
{
std::string test_outputs("\n*** Test Failed:\n");
if (!process_output.empty()) {
- test_outputs.append(&*process_output.begin(), process_output.size());
+ test_outputs.append(process_output.data(), process_output.size());
}
- cmCTestLog(this, HANDLER_OUTPUT, test_outputs << std::endl << std::flush);
+ cmCTestLog(this, HANDLER_OUTPUT, test_outputs << std::endl);
}
bool cmCTest::CompressString(std::string& str)
@@ -2813,8 +3231,8 @@ bool cmCTest::CompressString(std::string& str)
ret = deflate(&strm, Z_FINISH);
if (ret != Z_STREAM_END) {
- cmCTestLog(this, ERROR_MESSAGE, "Error during gzip compression."
- << std::endl);
+ cmCTestLog(this, ERROR_MESSAGE,
+ "Error during gzip compression." << std::endl);
return false;
}
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index 60f3295e7..82a6f4cbd 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -3,18 +3,29 @@
#ifndef cmCTest_h
#define cmCTest_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmProcessOutput.h"
-#include "cmsys/String.hxx"
+#include <chrono>
+#include <ctime>
#include <map>
-#include <set>
+#include <memory>
#include <sstream>
#include <string>
-#include <time.h>
#include <vector>
-class cmCTestGenericHandler;
+#include "cmDuration.h"
+#include "cmProcessOutput.h"
+
+class cmCTestBuildHandler;
+class cmCTestBuildAndTestHandler;
+class cmCTestCoverageHandler;
+class cmCTestScriptHandler;
+class cmCTestTestHandler;
+class cmCTestUpdateHandler;
+class cmCTestConfigureHandler;
+class cmCTestMemCheckHandler;
+class cmCTestSubmitHandler;
+class cmCTestUploadHandler;
class cmCTestStartCommand;
class cmGeneratedFileStream;
class cmMakefile;
@@ -29,11 +40,8 @@ class cmXMLWriter;
*/
class cmCTest
{
- friend class cmCTestRunTest;
- friend class cmCTestMultiProcessHandler;
-
public:
- typedef cmProcessOutput::Encoding Encoding;
+ using Encoding = cmProcessOutput::Encoding;
/** Enumerate parts of the testing and submission process. */
enum Part
{
@@ -48,54 +56,16 @@ public:
PartNotes,
PartExtraFiles,
PartUpload,
+ PartDone,
PartCount // Update names in constructor when adding a part
};
- /** Representation of one part. */
- struct PartInfo
- {
- PartInfo()
- : Enabled(false)
- {
- }
-
- void SetName(const std::string& name) { this->Name = name; }
- const std::string& GetName() const { return this->Name; }
-
- void Enable() { this->Enabled = true; }
- operator bool() const { return this->Enabled; }
-
- std::vector<std::string> SubmitFiles;
-
- private:
- bool Enabled;
- std::string Name;
- };
-#ifdef CMAKE_BUILD_WITH_CMAKE
- enum HTTPMethod
- {
- HTTP_GET,
- HTTP_POST,
- HTTP_PUT
- };
-
- /**
- * Perform an HTTP request.
- */
- static int HTTPRequest(std::string url, HTTPMethod method,
- std::string& response, std::string const& fields = "",
- std::string const& putFile = "", int timeout = 0);
-#endif
-
/** Get a testing part id from its string name. Returns PartCount
if the string does not name a valid part. */
Part GetPartFromName(const char* name);
- typedef std::vector<cmsys::String> VectorOfStrings;
- typedef std::set<std::string> SetOfStrings;
-
/** Process Command line arguments */
- int Run(std::vector<std::string>&, std::string* output = CM_NULLPTR);
+ int Run(std::vector<std::string>&, std::string* output = nullptr);
/**
* Initialize and finalize testing
@@ -130,25 +100,25 @@ public:
/**
* Is the tomorrow tag set?
*/
- bool GetTomorrowTag() { return this->TomorrowTag; }
+ bool GetTomorrowTag() const;
/**
* Try to run tests of the project
*/
int TestDirectory(bool memcheck);
- /** what is the configuraiton type, e.g. Debug, Release etc. */
+ /** what is the configuration type, e.g. Debug, Release etc. */
std::string const& GetConfigType();
- double GetTimeOut() { return this->TimeOut; }
- void SetTimeOut(double t) { this->TimeOut = t; }
+ cmDuration GetTimeOut() const;
+ void SetTimeOut(cmDuration t);
- double GetGlobalTimeout() { return this->GlobalTimeout; }
+ cmDuration GetGlobalTimeout() const;
/** how many test to run at the same time */
- int GetParallelLevel() { return this->ParallelLevel; }
+ int GetParallelLevel() const;
void SetParallelLevel(int);
- unsigned long GetTestLoad() { return this->TestLoad; }
+ unsigned long GetTestLoad() const;
void SetTestLoad(unsigned long);
/**
@@ -166,7 +136,7 @@ public:
* Set the cmake test mode (experimental, nightly, continuous).
*/
void SetTestModel(int mode);
- int GetTestModel() { return this->TestModel; }
+ int GetTestModel() const;
std::string GetTestModelString();
static int GetTestModelFromString(const char* str);
@@ -176,12 +146,17 @@ public:
bool suppress = false);
void EmptyCTestConfiguration();
+ std::string GetSubmitURL();
+
/**
* constructor and destructor
*/
cmCTest();
~cmCTest();
+ cmCTest(const cmCTest&) = delete;
+ cmCTest& operator=(const cmCTest&) = delete;
+
/** Set the notes files to be created. */
void SetNotesFiles(const char* notes);
@@ -200,9 +175,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
@@ -213,23 +190,27 @@ public:
/** Should we only show what we would do? */
bool GetShowOnly();
- bool ShouldUseHTTP10() { return this->UseHTTP10; }
+ bool GetOutputAsJson();
+
+ int GetOutputAsJsonVersion();
+
+ bool ShouldUseHTTP10() const;
- bool ShouldPrintLabels() { return this->PrintLabels; }
+ bool ShouldPrintLabels() const;
bool ShouldCompressTestOutput();
bool CompressString(std::string& str);
- std::string GetStopTime() { return this->StopTime; }
+ std::chrono::system_clock::time_point GetStopTime() const;
void SetStopTime(std::string const& time);
/** Used for parallel ctest job scheduling */
- std::string GetScheduleType() { return this->ScheduleType; }
- void SetScheduleType(std::string const& type) { this->ScheduleType = type; }
+ std::string GetScheduleType() const;
+ void SetScheduleType(std::string const& type);
/** The max output width */
int GetMaxTestNameWidth() const;
- void SetMaxTestNameWidth(int w) { this->MaxTestNameWidth = w; }
+ void SetMaxTestNameWidth(int w);
/**
* Run a single executable command and put the stdout and stderr
@@ -245,15 +226,11 @@ public:
* exit code will be stored. If the retVal is not specified and
* the program exits with a code other than 0, then the this
* function will return false.
- *
- * If the command has spaces in the path the caller MUST call
- * cmSystemTools::ConvertToRunCommandPath on the command before passing
- * it into this function or it will not work. The command must be correctly
- * escaped for this to with spaces.
*/
- bool RunCommand(const char* command, std::string* stdOut,
- std::string* stdErr, int* retVal = CM_NULLPTR,
- const char* dir = CM_NULLPTR, double timeout = 0.0,
+ bool RunCommand(std::vector<std::string> const& args, std::string* stdOut,
+ std::string* stdErr, int* retVal = nullptr,
+ const char* dir = nullptr,
+ cmDuration timeout = cmDuration::zero(),
Encoding encoding = cmProcessOutput::Auto);
/**
@@ -272,8 +249,9 @@ public:
* Run command specialized for make and configure. Returns process status
* 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,
+ int RunMakeCommand(const std::string& command, std::string& output,
+ int* retVal, const char* dir, cmDuration timeout,
+ std::ostream& ofs,
Encoding encoding = cmProcessOutput::Auto);
/** Return the current tag */
@@ -292,9 +270,10 @@ public:
enum
{
- EXPERIMENTAL,
- NIGHTLY,
- CONTINUOUS
+ UNKNOWN = -1,
+ EXPERIMENTAL = 0,
+ NIGHTLY = 1,
+ CONTINUOUS = 2,
};
/** provide some more detailed info on the return code for ctest */
@@ -320,21 +299,23 @@ 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);
/**
- * Execute handler and return its result. If the handler fails, it returns
- * negative value.
- */
- int ExecuteHandler(const char* handler);
-
- /**
* Get the handler object
*/
- cmCTestGenericHandler* GetHandler(const char* handler);
- cmCTestGenericHandler* GetInitializedHandler(const char* handler);
+ cmCTestBuildHandler* GetBuildHandler();
+ cmCTestBuildAndTestHandler* GetBuildAndTestHandler();
+ cmCTestCoverageHandler* GetCoverageHandler();
+ cmCTestScriptHandler* GetScriptHandler();
+ cmCTestTestHandler* GetTestHandler();
+ cmCTestUpdateHandler* GetUpdateHandler();
+ cmCTestConfigureHandler* GetConfigureHandler();
+ cmCTestMemCheckHandler* GetMemCheckHandler();
+ cmCTestSubmitHandler* GetSubmitHandler();
+ cmCTestUploadHandler* GetUploadHandler();
/**
* Set the CTest variable from CMake variable
@@ -344,9 +325,6 @@ public:
const std::string& cmake_var,
bool suppress = false);
- /** Make string safe to be send as an URL */
- static std::string MakeURLSafe(const std::string&);
-
/** Decode a URL to the original string. */
static std::string DecodeURL(const std::string&);
@@ -354,10 +332,7 @@ public:
* Should ctect configuration be updated. When using new style ctest
* script, this should be true.
*/
- void SetSuppressUpdatingCTestConfiguration(bool val)
- {
- this->SuppressUpdatingCTestConfiguration = val;
- }
+ void SetSuppressUpdatingCTestConfiguration(bool val);
/**
* Add overwrite to ctest configuration.
@@ -367,11 +342,14 @@ public:
void AddCTestConfigurationOverwrite(const std::string& encstr);
/** Create XML file that contains all the notes specified */
- int GenerateNotesFile(const VectorOfStrings& files);
+ int GenerateNotesFile(std::vector<std::string> const& files);
+
+ /** Create XML file to indicate that build is complete */
+ int GenerateDoneFile();
/** Submit extra files to the server */
bool SubmitExtraFiles(const char* files);
- bool SubmitExtraFiles(const VectorOfStrings& files);
+ bool SubmitExtraFiles(std::vector<std::string> const& files);
/** Set the output log file name */
void SetOutputLogFileName(const char* name);
@@ -386,6 +364,7 @@ public:
OUTPUT,
HANDLER_OUTPUT,
HANDLER_PROGRESS_OUTPUT,
+ HANDLER_TEST_PROGRESS_OUTPUT,
HANDLER_VERBOSE_OUTPUT,
WARNING,
ERROR_MESSAGE,
@@ -396,143 +375,74 @@ public:
void Log(int logType, const char* file, int line, const char* msg,
bool suppress = false);
- /** Get the version of dart server */
- int GetDartVersion() { return this->DartVersion; }
- int GetDropSiteCDash() { return this->DropSiteCDash; }
+ /** Color values */
+ enum class Color
+ {
+ CLEAR_COLOR = 0,
+ RED = 31,
+ GREEN = 32,
+ YELLOW = 33,
+ BLUE = 34
+ };
+
+ /** Get color code characters for a specific color */
+ std::string GetColorCode(Color color) const;
+
+ /** The Build ID is assigned by CDash */
+ void SetBuildID(const std::string& id);
+ std::string GetBuildID() const;
/** Add file to be submitted */
void AddSubmitFile(Part part, const char* name);
- std::vector<std::string> const& GetSubmitFiles(Part part)
- {
- return this->Parts[part].SubmitFiles;
- }
- void ClearSubmitFiles(Part part) { this->Parts[part].SubmitFiles.clear(); }
+ std::vector<std::string> const& GetSubmitFiles(Part part) const;
+ void ClearSubmitFiles(Part part);
/**
* Read the custom configuration files and apply them to the current ctest
*/
int ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf);
- std::vector<std::string>& GetInitialCommandLineArguments()
- {
- return this->InitialCommandLineArguments;
- }
+ std::vector<std::string>& GetInitialCommandLineArguments();
- /** Set the track to submit to */
- void SetSpecificTrack(const char* track);
- const char* GetSpecificTrack();
+ /** Set the group to submit to */
+ void SetSpecificGroup(const char* group);
+ const char* GetSpecificGroup();
- void SetFailover(bool failover) { this->Failover = failover; }
- bool GetFailover() { return this->Failover; }
+ void SetFailover(bool failover);
+ bool GetFailover() const;
- void SetBatchJobs(bool batch = true) { this->BatchJobs = batch; }
- bool GetBatchJobs() { return this->BatchJobs; }
+ bool GetTestProgressOutput() const;
- bool GetVerbose() { return this->Verbose; }
- bool GetExtraVerbose() { return this->ExtraVerbose; }
+ bool GetVerbose() const;
+ bool GetExtraVerbose() const;
/** Direct process output to given streams. */
- void SetStreams(std::ostream* out, std::ostream* err)
- {
- this->StreamOut = out;
- this->StreamErr = err;
- }
+ void SetStreams(std::ostream* out, std::ostream* err);
+
void AddSiteProperties(cmXMLWriter& xml);
- bool GetLabelSummary() { return this->LabelSummary; }
+
+ bool GetLabelSummary() const;
+ bool GetSubprojectSummary() const;
std::string GetCostDataFile();
- const std::map<std::string, std::string>& GetDefinitions()
- {
- return this->Definitions;
- }
+ bool GetOutputTestOutputOnTestFailure() const;
+
+ const std::map<std::string, std::string>& GetDefinitions() const;
/** Return the number of times a test should be run */
- int GetTestRepeat() { return this->RepeatTests; }
+ int GetTestRepeat() const;
/** Return true if test should run until fail */
- bool GetRepeatUntilFail() { return this->RepeatUntilFail; }
-
-private:
- int RepeatTests;
- bool RepeatUntilFail;
- std::string ConfigType;
- std::string ScheduleType;
- std::string StopTime;
- bool NextDayStopTime;
- bool Verbose;
- bool ExtraVerbose;
- bool ProduceXML;
- bool LabelSummary;
- bool UseHTTP10;
- bool PrintLabels;
- bool Failover;
- bool BatchJobs;
-
- bool ForceNewCTestProcess;
-
- bool RunConfigurationScript;
-
- int GenerateNotesFile(const char* files);
-
- void DetermineNextDayStop();
-
- // these are helper classes
- typedef std::map<std::string, cmCTestGenericHandler*> t_TestingHandlers;
- t_TestingHandlers TestingHandlers;
-
- bool ShowOnly;
-
- /** 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
- // affecting any higher-precedence settings.
- CTestConfigurationMap CTestConfiguration;
- CTestConfigurationMap CTestConfigurationOverwrites;
- PartInfo Parts[PartCount];
- typedef std::map<std::string, Part> PartMapType;
- PartMapType PartMap;
-
- std::string CurrentTag;
- bool TomorrowTag;
-
- int TestModel;
- std::string SpecificTrack;
-
- double TimeOut;
-
- double GlobalTimeout;
-
- int LastStopTimeout;
+ bool GetRepeatUntilFail() const;
- int MaxTestNameWidth;
+ void GenerateSubprojectsOutput(cmXMLWriter& xml);
+ std::vector<std::string> GetLabelsForSubprojects();
- int ParallelLevel;
- bool ParallelLevelSetInCli;
+ void SetRunCurrentScript(bool value);
- unsigned long TestLoad;
-
- int CompatibilityMode;
-
- // information for the --build-and-test options
- std::string BinaryDir;
-
- std::string NotesFiles;
-
- bool InteractiveDebugMode;
-
- bool ShortDateFormat;
-
- bool CompressXMLFiles;
- bool CompressTestOutput;
-
- void InitStreams();
- std::ostream* StreamOut;
- std::ostream* StreamErr;
+private:
+ int GenerateNotesFile(const char* files);
void BlockTestErrorDiagnostics();
@@ -559,7 +469,18 @@ private:
bool HandleCommandLineArguments(size_t& i, std::vector<std::string>& args,
std::string& errormsg);
- /** hande the -S -SP and -SR arguments */
+#if !defined(_WIN32)
+ /** returns true iff the console supports progress output */
+ static bool ConsoleIsNotDumb();
+#endif
+
+ /** returns true iff the console supports progress output */
+ static bool ProgressOutputSupportedByConsole();
+
+ /** returns true iff the console supports colored output */
+ static bool ColoredOutputSupportedByConsole();
+
+ /** handle the -S -SP and -SR arguments */
void HandleScriptArguments(size_t& i, std::vector<std::string>& args,
bool& SRArgumentSpecified);
@@ -567,11 +488,12 @@ private:
bool UpdateCTestConfiguration();
/** Create note from files. */
- int GenerateCTestNotesOutput(cmXMLWriter& xml, const VectorOfStrings& files);
+ int GenerateCTestNotesOutput(cmXMLWriter& xml,
+ std::vector<std::string> const& files);
/** Check if the argument is the one specified */
bool CheckArgument(const std::string& arg, const char* varg1,
- const char* varg2 = CM_NULLPTR);
+ const char* varg2 = nullptr);
/** Output errors from a test */
void OutputTestErrors(std::vector<char> const& process_output);
@@ -587,25 +509,8 @@ private:
int RunCMakeAndTest(std::string* output);
int ExecuteTests();
- bool SuppressUpdatingCTestConfiguration;
-
- bool Debug;
- bool ShowLineNumbers;
- bool Quiet;
-
- int DartVersion;
- bool DropSiteCDash;
-
- std::vector<std::string> InitialCommandLineArguments;
-
- int SubmitIndex;
-
- cmGeneratedFileStream* OutputLogFile;
- int OutputLogFileLastTag;
-
- bool OutputTestOutputOnTestFailure;
-
- std::map<std::string, std::string> Definitions;
+ struct Private;
+ std::unique_ptr<Private> Impl;
};
class cmCTestLogWrite
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index 0b025ab6f..d627465c7 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -2,18 +2,22 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCacheManager.h"
-#include "cmsys/FStream.hxx"
-#include "cmsys/Glob.hxx"
#include <algorithm>
+#include <cstdio>
+#include <cstring>
#include <sstream>
-#include <stdio.h>
-#include <string.h>
+#include <string>
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
#include "cmGeneratedFileStream.h"
+#include "cmMessageType.h"
+#include "cmMessenger.h"
#include "cmState.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
-#include "cmake.h"
cmCacheManager::cmCacheManager()
{
@@ -23,9 +27,7 @@ cmCacheManager::cmCacheManager()
void cmCacheManager::CleanCMakeFiles(const std::string& path)
{
- std::string glob = path;
- glob += cmake::GetCMakeFilesDirectory();
- glob += "/*.cmake";
+ std::string glob = cmStrCat(path, "/CMakeFiles/*.cmake");
cmsys::Glob globIt;
globIt.FindFiles(glob);
std::vector<std::string> files = globIt.GetFiles();
@@ -36,13 +38,12 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
std::set<std::string>& excludes,
std::set<std::string>& includes)
{
- std::string cacheFile = path;
- cacheFile += "/CMakeCache.txt";
+ std::string cacheFile = cmStrCat(path, "/CMakeCache.txt");
// clear the old cache, if we are reading in internal values
if (internal) {
this->Cache.clear();
}
- if (!cmSystemTools::FileExists(cacheFile.c_str())) {
+ if (!cmSystemTools::FileExists(cacheFile)) {
this->CleanCMakeFiles(path);
return false;
}
@@ -102,12 +103,10 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
// not visible in the gui
if (!internal) {
e.Type = cmStateEnums::INTERNAL;
- helpString = "DO NOT EDIT, ";
- helpString += entryKey;
- helpString += " loaded from external file. "
- "To change this value edit this file: ";
- helpString += path;
- helpString += "/CMakeCache.txt";
+ helpString = cmStrCat("DO NOT EDIT, ", entryKey,
+ " loaded from external file. "
+ "To change this value edit this file: ",
+ path, "/CMakeCache.txt");
e.SetProperty("HELPSTRING", helpString.c_str());
}
if (!this->ReadPropertyEntry(entryKey, e)) {
@@ -120,20 +119,20 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
std::ostringstream error;
error << "Parse error in cache file " << cacheFile;
error << " on line " << lineno << ". Offending entry: " << realbuffer;
- cmSystemTools::Error(error.str().c_str());
+ cmSystemTools::Error(error.str());
}
}
this->CacheMajorVersion = 0;
this->CacheMinorVersion = 0;
- if (const char* cmajor =
+ if (const std::string* cmajor =
this->GetInitializedCacheValue("CMAKE_CACHE_MAJOR_VERSION")) {
unsigned int v = 0;
- if (sscanf(cmajor, "%u", &v) == 1) {
+ if (sscanf(cmajor->c_str(), "%u", &v) == 1) {
this->CacheMajorVersion = v;
}
- if (const char* cminor =
+ if (const std::string* cminor =
this->GetInitializedCacheValue("CMAKE_CACHE_MINOR_VERSION")) {
- if (sscanf(cminor, "%u", &v) == 1) {
+ if (sscanf(cminor->c_str(), "%u", &v) == 1) {
this->CacheMinorVersion = v;
}
}
@@ -151,29 +150,31 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
}
// check to make sure the cache directory has not
// been moved
- const char* oldDir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
+ const std::string* oldDir =
+ this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
if (internal && oldDir) {
std::string currentcwd = path;
- std::string oldcwd = oldDir;
+ std::string oldcwd = *oldDir;
cmSystemTools::ConvertToUnixSlashes(currentcwd);
currentcwd += "/CMakeCache.txt";
oldcwd += "/CMakeCache.txt";
if (!cmSystemTools::SameFile(oldcwd, currentcwd)) {
- std::string message =
- std::string("The current CMakeCache.txt directory ") + currentcwd +
- std::string(" is different than the directory ") +
- std::string(this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR")) +
- std::string(" where CMakeCache.txt was created. This may result "
- "in binaries being created in the wrong place. If you "
- "are not sure, reedit the CMakeCache.txt");
- cmSystemTools::Error(message.c_str());
+ const std::string* dir =
+ this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
+ std::ostringstream message;
+ message << "The current CMakeCache.txt directory " << currentcwd
+ << " is different than the directory " << (dir ? *dir : "")
+ << " where CMakeCache.txt was created. This may result "
+ "in binaries being created in the wrong place. If you "
+ "are not sure, reedit the CMakeCache.txt";
+ cmSystemTools::Error(message.str());
}
}
return true;
}
const char* cmCacheManager::PersistentProperties[] = { "ADVANCED", "MODIFIED",
- "STRINGS", CM_NULLPTR };
+ "STRINGS", nullptr };
bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey,
CacheEntry& e)
@@ -184,7 +185,7 @@ bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey,
}
const char* end = entryKey.c_str() + entryKey.size();
- for (const char** p = this->PersistentProperties; *p; ++p) {
+ for (const char** p = cmCacheManager::PersistentProperties; *p; ++p) {
std::string::size_type plen = strlen(*p) + 1;
if (entryKey.size() > plen && *(end - plen) == '-' &&
strcmp(end - plen + 1, *p) == 0) {
@@ -205,53 +206,50 @@ 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) {
+ for (const char** p = cmCacheManager::PersistentProperties; *p; ++p) {
if (const char* value = i.GetProperty(*p)) {
- std::string helpstring = *p;
- helpstring += " property for variable: ";
- helpstring += i.GetName();
+ std::string helpstring =
+ cmStrCat(*p, " property for variable: ", i.GetName());
cmCacheManager::OutputHelpString(os, helpstring);
- std::string key = i.GetName();
- key += "-";
- key += *p;
- this->OutputKey(os, key);
+ std::string key = cmStrCat(i.GetName(), '-', *p);
+ cmCacheManager::OutputKey(os, key);
os << ":INTERNAL=";
- this->OutputValue(os, value);
+ cmCacheManager::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";
- cmGeneratedFileStream fout(cacheFile.c_str());
+ std::string cacheFile = cmStrCat(path, "/CMakeCache.txt");
+ cmGeneratedFileStream fout(cacheFile);
fout.SetCopyIfDifferent(true);
if (!fout) {
- cmSystemTools::Error("Unable to open cache file for save. ",
- cacheFile.c_str());
+ cmSystemTools::Error("Unable to open cache file for save. " + cacheFile);
cmSystemTools::ReportLastSystemError("");
return false;
}
// before writing the cache, update the version numbers
// to the
- char temp[1024];
- sprintf(temp, "%d", cmVersion::GetMinorVersion());
- this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", temp,
- "Minor version of cmake used to create the "
+ this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION",
+ std::to_string(cmVersion::GetMajorVersion()).c_str(),
+ "Major version of cmake used to create the "
"current loaded cache",
cmStateEnums::INTERNAL);
- sprintf(temp, "%d", cmVersion::GetMajorVersion());
- this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", temp,
- "Major version of cmake used to create the "
+ this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION",
+ std::to_string(cmVersion::GetMinorVersion()).c_str(),
+ "Minor version of cmake used to create the "
"current loaded cache",
cmStateEnums::INTERNAL);
- sprintf(temp, "%d", cmVersion::GetPatchVersion());
- this->AddCacheEntry("CMAKE_CACHE_PATCH_VERSION", temp,
+ this->AddCacheEntry("CMAKE_CACHE_PATCH_VERSION",
+ std::to_string(cmVersion::GetPatchVersion()).c_str(),
"Patch version of cmake used to create the "
"current loaded cache",
cmStateEnums::INTERNAL);
@@ -297,16 +295,13 @@ bool cmCacheManager::SaveCache(const std::string& path)
fout << "########################\n";
fout << "\n";
- for (std::map<std::string, CacheEntry>::const_iterator i =
- this->Cache.begin();
- i != this->Cache.end(); ++i) {
- const CacheEntry& ce = (*i).second;
+ for (auto const& i : this->Cache) {
+ CacheEntry const& ce = i.second;
cmStateEnums::CacheEntryType t = ce.Type;
if (!ce.Initialized) {
/*
// This should be added in, but is not for now.
- cmSystemTools::Error("Cache entry \"", (*i).first.c_str(),
- "\" is uninitialized");
+ cmSystemTools::Error("Cache entry \"" + i.first + "\" is uninitialized");
*/
} else if (t != cmStateEnums::INTERNAL) {
// Format is key:type=value
@@ -315,10 +310,13 @@ bool cmCacheManager::SaveCache(const std::string& path)
} else {
cmCacheManager::OutputHelpString(fout, "Missing description");
}
- this->OutputKey(fout, i->first);
+ cmCacheManager::OutputKey(fout, i.first);
fout << ":" << cmState::CacheEntryTypeToString(t) << "=";
- this->OutputValue(fout, ce.Value);
- fout << "\n\n";
+ cmCacheManager::OutputValue(fout, ce.Value);
+ fout << "\n";
+ cmCacheManager::OutputNewlineTruncationWarning(fout, i.first, ce.Value,
+ messenger);
+ fout << "\n";
}
}
@@ -335,28 +333,29 @@ 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")) {
- this->OutputHelpString(fout, help);
+ cmCacheManager::OutputHelpString(fout, help);
}
- this->OutputKey(fout, i.GetName());
+ cmCacheManager::OutputKey(fout, i.GetName());
fout << ":" << cmState::CacheEntryTypeToString(t) << "=";
- this->OutputValue(fout, i.GetValue());
+ cmCacheManager::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());
+ std::string checkCacheFile = cmStrCat(path, "/CMakeFiles");
+ cmSystemTools::MakeDirectory(checkCacheFile);
checkCacheFile += "/cmake.check_cache";
cmsys::ofstream checkCache(checkCacheFile.c_str());
if (!checkCache) {
- cmSystemTools::Error("Unable to open check cache file for write. ",
- checkCacheFile.c_str());
+ cmSystemTools::Error("Unable to open check cache file for write. " +
+ checkCacheFile);
return false;
}
checkCache << "# This file is generated by cmake for dependency checking "
@@ -370,11 +369,11 @@ 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
- cmakeFiles += cmake::GetCMakeFilesDirectory();
+ cmakeFiles += "/CMakeFiles";
if (cmSystemTools::FileIsDirectory(cmakeFiles)) {
cmSystemTools::RemoveADirectory(cmakeFiles);
}
@@ -392,9 +391,21 @@ 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')) {
+ if (!value.empty() && (value.back() == ' ' || value.back() == '\t')) {
fout << '\'' << value << '\'';
} else {
fout << value;
@@ -425,9 +436,52 @@ 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 =
+ cmStrCat("Value of ", key, " contained a newline; truncating");
+ messenger->IssueMessage(MessageType::WARNING, message);
+ }
+
+ std::string comment =
+ cmStrCat("WARNING: Value of ", key,
+ " 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);
+ auto i = this->Cache.find(key);
if (i != this->Cache.end()) {
this->Cache.erase(i);
}
@@ -436,37 +490,35 @@ void cmCacheManager::RemoveCacheEntry(const std::string& key)
cmCacheManager::CacheEntry* cmCacheManager::GetCacheEntry(
const std::string& key)
{
- CacheEntryMap::iterator i = this->Cache.find(key);
+ auto i = this->Cache.find(key);
if (i != this->Cache.end()) {
return &i->second;
}
- return CM_NULLPTR;
+ return nullptr;
}
cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator(const char* key)
{
- return CacheIterator(*this, key);
+ return { *this, key };
}
-const char* cmCacheManager::GetInitializedCacheValue(
+const std::string* cmCacheManager::GetInitializedCacheValue(
const std::string& key) const
{
- CacheEntryMap::const_iterator i = this->Cache.find(key);
+ auto i = this->Cache.find(key);
if (i != this->Cache.end() && i->second.Initialized) {
- return i->second.Value.c_str();
+ return &i->second.Value;
}
- return CM_NULLPTR;
+ return nullptr;
}
void cmCacheManager::PrintCache(std::ostream& out) const
{
out << "=================================================" << std::endl;
out << "CMakeCache Contents:" << std::endl;
- for (std::map<std::string, CacheEntry>::const_iterator i =
- this->Cache.begin();
- i != this->Cache.end(); ++i) {
- if ((*i).second.Type != cmStateEnums::INTERNAL) {
- out << (*i).first << " = " << (*i).second.Value << std::endl;
+ for (auto const& i : this->Cache) {
+ if (i.second.Type != cmStateEnums::INTERNAL) {
+ out << i.first << " = " << i.second.Value << std::endl;
}
}
out << "\n\n";
@@ -484,28 +536,27 @@ void cmCacheManager::AddCacheEntry(const std::string& key, const char* value,
e.Value = value;
e.Initialized = true;
} else {
- e.Value = "";
+ e.Value.clear();
}
e.Type = type;
// make sure we only use unix style paths
if (type == cmStateEnums::FILEPATH || type == cmStateEnums::PATH) {
if (e.Value.find(';') != std::string::npos) {
- std::vector<std::string> paths;
- cmSystemTools::ExpandListArgument(e.Value, paths);
+ std::vector<std::string> paths = cmExpandedList(e.Value);
const char* sep = "";
e.Value = "";
- for (std::vector<std::string>::iterator i = paths.begin();
- i != paths.end(); ++i) {
- cmSystemTools::ConvertToUnixSlashes(*i);
+ for (std::string& i : paths) {
+ cmSystemTools::ConvertToUnixSlashes(i);
e.Value += sep;
- e.Value += *i;
+ e.Value += i;
sep = ";";
}
} else {
cmSystemTools::ConvertToUnixSlashes(e.Value);
}
}
- e.SetProperty("HELPSTRING", helpString
+ e.SetProperty("HELPSTRING",
+ helpString
? helpString
: "(This variable does not exist and should not be used)");
}
@@ -548,18 +599,18 @@ void cmCacheManager::CacheIterator::SetValue(const char* value)
entry->Value = value;
entry->Initialized = true;
} else {
- entry->Value = "";
+ entry->Value.clear();
}
}
bool cmCacheManager::CacheIterator::GetValueAsBool() const
{
- return cmSystemTools::IsOn(this->GetEntry().Value.c_str());
+ return cmIsOn(this->GetEntry().Value);
}
std::vector<std::string> cmCacheManager::CacheEntry::GetPropertyList() const
{
- return this->Properties.GetPropertyList();
+ return this->Properties.GetKeys();
}
const char* cmCacheManager::CacheEntry::GetProperty(
@@ -610,7 +661,7 @@ const char* cmCacheManager::CacheIterator::GetProperty(
if (!this->IsAtEnd()) {
return this->GetEntry().GetProperty(prop);
}
- return CM_NULLPTR;
+ return nullptr;
}
void cmCacheManager::CacheIterator::SetProperty(const std::string& p,
@@ -634,7 +685,7 @@ bool cmCacheManager::CacheIterator::GetPropertyAsBool(
const std::string& prop) const
{
if (const char* value = this->GetProperty(prop)) {
- return cmSystemTools::IsOn(value);
+ return cmIsOn(value);
}
return false;
}
@@ -647,5 +698,5 @@ void cmCacheManager::CacheIterator::SetProperty(const std::string& p, bool v)
bool cmCacheManager::CacheIterator::PropertyExists(
const std::string& prop) const
{
- return this->GetProperty(prop) != CM_NULLPTR;
+ return this->GetProperty(prop) != nullptr;
}
diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h
index c464311c6..faa60c528 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
@@ -34,20 +34,14 @@ private:
struct CacheEntry
{
std::string Value;
- cmStateEnums::CacheEntryType Type;
+ cmStateEnums::CacheEntryType Type = cmStateEnums::UNINITIALIZED;
cmPropertyMap Properties;
std::vector<std::string> GetPropertyList() const;
const char* GetProperty(const std::string&) const;
void SetProperty(const std::string& property, const char* value);
void AppendProperty(const std::string& property, const char* value,
bool asString = false);
- bool Initialized;
- CacheEntry()
- : Value("")
- , Type(cmStateEnums::UNINITIALIZED)
- , Initialized(false)
- {
- }
+ bool Initialized = false;
};
public:
@@ -99,40 +93,40 @@ public:
CacheEntry& GetEntry() { return this->Position->second; }
};
- ///! return an iterator to iterate through the cache map
- cmCacheManager::CacheIterator NewIterator() { return CacheIterator(*this); }
+ //! return an iterator to iterate through the cache map
+ cmCacheManager::CacheIterator NewIterator() { return { *this }; }
- ///! Load a cache for given makefile. Loads from path/CMakeCache.txt.
+ //! Load a cache for given makefile. Loads from path/CMakeCache.txt.
bool LoadCache(const std::string& path, bool internal,
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
+ //! Delete the cache given
bool DeleteCache(const std::string& path);
- ///! Print the cache to a stream
+ //! Print the cache to a stream
void PrintCache(std::ostream&) const;
- ///! Get the iterator for an entry with a given key.
- cmCacheManager::CacheIterator GetCacheIterator(const char* key = CM_NULLPTR);
+ //! Get the iterator for an entry with a given key.
+ cmCacheManager::CacheIterator GetCacheIterator(const char* key = nullptr);
- ///! Remove an entry from the cache
+ //! Remove an entry from the cache
void RemoveCacheEntry(const std::string& key);
- ///! Get the number of entries in the cache
+ //! Get the number of entries in the cache
int GetSize() { return static_cast<int>(this->Cache.size()); }
- ///! Get a value from the cache given a key
- const char* GetInitializedCacheValue(const std::string& key) const;
+ //! Get a value from the cache given a key
+ const std::string* GetInitializedCacheValue(const std::string& key) const;
const char* GetCacheEntryValue(const std::string& key)
{
cmCacheManager::CacheIterator it = this->GetCacheIterator(key.c_str());
if (it.IsAtEnd()) {
- return CM_NULLPTR;
+ return nullptr;
}
return it.GetValue();
}
@@ -175,8 +169,7 @@ public:
void RemoveCacheEntryProperty(std::string const& key,
std::string const& propName)
{
- this->GetCacheIterator(key.c_str())
- .SetProperty(propName, (void*)CM_NULLPTR);
+ this->GetCacheIterator(key.c_str()).SetProperty(propName, nullptr);
}
void AppendCacheEntryProperty(std::string const& key,
@@ -204,14 +197,14 @@ public:
unsigned int GetCacheMinorVersion() const { return this->CacheMinorVersion; }
protected:
- ///! Add an entry into the cache
+ //! Add an entry into the cache
void AddCacheEntry(const std::string& key, const char* value,
const char* helpString,
cmStateEnums::CacheEntryType type);
- ///! Get a cache entry object for a key
+ //! Get a cache entry object for a key
CacheEntry* GetCacheEntry(const std::string& key);
- ///! Clean out the CMakeFiles directory if no CMakeCache.txt
+ //! Clean out the CMakeFiles directory if no CMakeCache.txt
void CleanCMakeFiles(const std::string& path);
// Cache version info
@@ -219,16 +212,25 @@ protected:
unsigned int CacheMinorVersion;
private:
- cmake* CMakeInstance;
- typedef std::map<std::string, CacheEntry> CacheEntryMap;
+ using CacheEntryMap = std::map<std::string, CacheEntry>;
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/cmCallVisualStudioMacro.cxx b/Source/cmCallVisualStudioMacro.cxx
index 99fe5877e..9e152ff80 100644
--- a/Source/cmCallVisualStudioMacro.cxx
+++ b/Source/cmCallVisualStudioMacro.cxx
@@ -4,10 +4,11 @@
#include <sstream>
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#if defined(_MSC_VER)
-#define HAVE_COMDEF_H
+# define HAVE_COMDEF_H
#endif
// Just for this file:
@@ -16,41 +17,41 @@ static bool LogErrorsAsMessages;
#if defined(HAVE_COMDEF_H)
-#include <comdef.h>
+# include <comdef.h>
// Copied from a correct comdef.h to avoid problems with deficient versions
// of comdef.h that exist in the wild... Fixes issue #7533.
//
-#ifdef _NATIVE_WCHAR_T_DEFINED
-#ifdef _DEBUG
-#pragma comment(lib, "comsuppwd.lib")
-#else
-#pragma comment(lib, "comsuppw.lib")
-#endif
-#else
-#ifdef _DEBUG
-#pragma comment(lib, "comsuppd.lib")
-#else
-#pragma comment(lib, "comsupp.lib")
-#endif
-#endif
-
-///! Use ReportHRESULT to make a cmSystemTools::Message after calling
-///! a COM method that may have failed.
-#define ReportHRESULT(hr, context) \
- if (FAILED(hr)) { \
- if (LogErrorsAsMessages) { \
- std::ostringstream _hresult_oss; \
- _hresult_oss.flags(std::ios::hex); \
- _hresult_oss << context << " failed HRESULT, hr = 0x" << hr \
- << std::endl; \
- _hresult_oss.flags(std::ios::dec); \
- _hresult_oss << __FILE__ << "(" << __LINE__ << ")"; \
- cmSystemTools::Message(_hresult_oss.str().c_str()); \
- } \
- }
+# ifdef _NATIVE_WCHAR_T_DEFINED
+# ifdef _DEBUG
+# pragma comment(lib, "comsuppwd.lib")
+# else
+# pragma comment(lib, "comsuppw.lib")
+# endif
+# else
+# ifdef _DEBUG
+# pragma comment(lib, "comsuppd.lib")
+# else
+# pragma comment(lib, "comsupp.lib")
+# endif
+# endif
+
+//! Use ReportHRESULT to make a cmSystemTools::Message after calling
+//! a COM method that may have failed.
+# define ReportHRESULT(hr, context) \
+ if (FAILED(hr)) { \
+ if (LogErrorsAsMessages) { \
+ std::ostringstream _hresult_oss; \
+ _hresult_oss.flags(std::ios::hex); \
+ _hresult_oss << context << " failed HRESULT, hr = 0x" << hr \
+ << std::endl; \
+ _hresult_oss.flags(std::ios::dec); \
+ _hresult_oss << __FILE__ << "(" << __LINE__ << ")"; \
+ cmSystemTools::Message(_hresult_oss.str()); \
+ } \
+ }
-///! Using the given instance of Visual Studio, call the named macro
+//! Using the given instance of Visual Studio, call the named macro
HRESULT InstanceCallMacro(IDispatch* vsIDE, const std::string& macro,
const std::string& args)
{
@@ -61,7 +62,8 @@ HRESULT InstanceCallMacro(IDispatch* vsIDE, const std::string& macro,
if (0 != vsIDE) {
DISPID dispid = (DISPID)-1;
- OLECHAR* name = L"ExecuteCommand";
+ wchar_t execute_command[] = L"ExecuteCommand";
+ OLECHAR* name = execute_command;
hr =
vsIDE->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispid);
@@ -119,7 +121,8 @@ HRESULT InstanceCallMacro(IDispatch* vsIDE, const std::string& macro,
}
oss << " dwHelpContext: " << excep.dwHelpContext << std::endl;
oss << " pvReserved: " << excep.pvReserved << std::endl;
- oss << " pfnDeferredFillIn: " << excep.pfnDeferredFillIn << std::endl;
+ oss << " pfnDeferredFillIn: "
+ << reinterpret_cast<void*>(excep.pfnDeferredFillIn) << std::endl;
oss << " scode: " << excep.scode << std::endl;
}
@@ -133,14 +136,15 @@ HRESULT InstanceCallMacro(IDispatch* vsIDE, const std::string& macro,
return hr;
}
-///! Get the Solution object from the IDE object
+//! Get the Solution object from the IDE object
HRESULT GetSolutionObject(IDispatch* vsIDE, IDispatchPtr& vsSolution)
{
HRESULT hr = E_POINTER;
if (0 != vsIDE) {
DISPID dispid = (DISPID)-1;
- OLECHAR* name = L"Solution";
+ wchar_t solution[] = L"Solution";
+ OLECHAR* name = solution;
hr =
vsIDE->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispid);
@@ -176,14 +180,15 @@ HRESULT GetSolutionObject(IDispatch* vsIDE, IDispatchPtr& vsSolution)
return hr;
}
-///! Get the FullName property from the Solution object
+//! Get the FullName property from the Solution object
HRESULT GetSolutionFullName(IDispatch* vsSolution, std::string& fullName)
{
HRESULT hr = E_POINTER;
if (0 != vsSolution) {
DISPID dispid = (DISPID)-1;
- OLECHAR* name = L"FullName";
+ wchar_t full_name[] = L"FullName";
+ OLECHAR* name = full_name;
hr = vsSolution->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT,
&dispid);
@@ -220,7 +225,7 @@ HRESULT GetSolutionFullName(IDispatch* vsSolution, std::string& fullName)
return hr;
}
-///! Get the FullName property from the Solution object, given the IDE object
+//! Get the FullName property from the Solution object, given the IDE object
HRESULT GetIDESolutionFullName(IDispatch* vsIDE, std::string& fullName)
{
IDispatchPtr vsSolution;
@@ -235,8 +240,8 @@ HRESULT GetIDESolutionFullName(IDispatch* vsIDE, std::string& fullName)
return hr;
}
-///! Get all running objects from the Windows running object table.
-///! Save them in a map by their display names.
+//! Get all running objects from the Windows running object table.
+//! Save them in a map by their display names.
HRESULT GetRunningInstances(std::map<std::string, IUnknownPtr>& mrot)
{
// mrot == Map of the Running Object Table
@@ -292,8 +297,8 @@ HRESULT GetRunningInstances(std::map<std::string, IUnknownPtr>& mrot)
return hr;
}
-///! Do the two file names refer to the same Visual Studio solution? Or are
-///! we perhaps looking for any and all solutions?
+//! Do the two file names refer to the same Visual Studio solution? Or are
+//! we perhaps looking for any and all solutions?
bool FilesSameSolution(const std::string& slnFile, const std::string& slnName)
{
if (slnFile == "ALL" || slnName == "ALL") {
@@ -310,9 +315,9 @@ bool FilesSameSolution(const std::string& slnFile, const std::string& slnName)
return s1 == s2;
}
-///! Find instances of Visual Studio with the given solution file
-///! open. Pass "ALL" for slnFile to gather all running instances
-///! of Visual Studio.
+//! Find instances of Visual Studio with the given solution file
+//! open. Pass "ALL" for slnFile to gather all running instances
+//! of Visual Studio.
HRESULT FindVisualStudioInstances(const std::string& slnFile,
std::vector<IDispatchPtr>& instances)
{
@@ -324,8 +329,7 @@ HRESULT FindVisualStudioInstances(const std::string& slnFile,
if (SUCCEEDED(hr)) {
std::map<std::string, IUnknownPtr>::iterator it;
for (it = mrot.begin(); it != mrot.end(); ++it) {
- if (cmSystemTools::StringStartsWith(it->first.c_str(),
- "!VisualStudio.DTE.")) {
+ if (cmHasLiteralPrefix(it->first, "!VisualStudio.DTE.")) {
IDispatchPtr disp(it->second);
if (disp != (IDispatch*)0) {
std::string slnName;
@@ -384,8 +388,8 @@ int cmCallVisualStudioMacro::GetNumberOfRunningVisualStudioInstances(
return count;
}
-///! Get all running objects from the Windows running object table.
-///! Save them in a map by their display names.
+//! Get all running objects from the Windows running object table.
+//! Save them in a map by their display names.
int cmCallVisualStudioMacro::CallMacro(const std::string& slnFile,
const std::string& macro,
const std::string& args,
@@ -446,7 +450,7 @@ int cmCallVisualStudioMacro::CallMacro(const std::string& slnFile,
if (err && LogErrorsAsMessages) {
std::ostringstream oss;
oss << "cmCallVisualStudioMacro::CallMacro failed, err = " << err;
- cmSystemTools::Message(oss.str().c_str());
+ cmSystemTools::Message(oss.str());
}
return 0;
diff --git a/Source/cmCallVisualStudioMacro.h b/Source/cmCallVisualStudioMacro.h
index ad35d306a..9b5b3a843 100644
--- a/Source/cmCallVisualStudioMacro.h
+++ b/Source/cmCallVisualStudioMacro.h
@@ -3,7 +3,7 @@
#ifndef cmCallVisualStudioMacro_h
#define cmCallVisualStudioMacro_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
@@ -16,16 +16,16 @@
class cmCallVisualStudioMacro
{
public:
- ///! Call the named macro in instances of Visual Studio with the
- ///! given solution file open. Pass "ALL" for slnFile to call the
- ///! macro in each Visual Studio instance.
+ //! Call the named macro in instances of Visual Studio with the
+ //! given solution file open. Pass "ALL" for slnFile to call the
+ //! macro in each Visual Studio instance.
static int CallMacro(const std::string& slnFile, const std::string& macro,
const std::string& args,
const bool logErrorsAsMessages);
- ///! Count the number of running instances of Visual Studio with the
- ///! given solution file open. Pass "ALL" for slnFile to count all
- ///! running Visual Studio instances.
+ //! Count the number of running instances of Visual Studio with the
+ //! given solution file open. Pass "ALL" for slnFile to count all
+ //! running Visual Studio instances.
static int GetNumberOfRunningVisualStudioInstances(
const std::string& slnFile);
diff --git a/Source/cmCheckCustomOutputs.cxx b/Source/cmCheckCustomOutputs.cxx
new file mode 100644
index 000000000..7645c8808
--- /dev/null
+++ b/Source/cmCheckCustomOutputs.cxx
@@ -0,0 +1,36 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCheckCustomOutputs.h"
+
+#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+bool cmCheckCustomOutputs(const std::vector<std::string>& outputs,
+ cm::string_view keyword, cmExecutionStatus& status)
+{
+ cmMakefile& mf = status.GetMakefile();
+
+ 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 (!mf.CanIWriteThisFile(o)) {
+ status.SetError(
+ cmStrCat("attempted to have a file\n ", o,
+ "\nin a source directory as an output of custom command."));
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+
+ // Make sure the output file name has no invalid characters.
+ std::string::size_type pos = o.find_first_of("#<>");
+ if (pos != std::string::npos) {
+ status.SetError(cmStrCat("called with ", keyword, " containing a \"",
+ o[pos], "\". This character is not allowed."));
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/Source/cmCheckCustomOutputs.h b/Source/cmCheckCustomOutputs.h
new file mode 100644
index 000000000..9f33d1665
--- /dev/null
+++ b/Source/cmCheckCustomOutputs.h
@@ -0,0 +1,18 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCheckCustomOutputs_h
+#define cmCheckCustomOutputs_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+#include <cm/string_view>
+
+class cmExecutionStatus;
+
+bool cmCheckCustomOutputs(const std::vector<std::string>& outputs,
+ cm::string_view keyword, cmExecutionStatus& status);
+
+#endif
diff --git a/Source/cmCommand.cxx b/Source/cmCommand.cxx
index d349c9167..0c2734e0f 100644
--- a/Source/cmCommand.cxx
+++ b/Source/cmCommand.cxx
@@ -2,11 +2,19 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCommand.h"
+#include <utility>
+
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-class cmExecutionStatus;
struct cmListFileArgument;
+void cmCommand::SetExecutionStatus(cmExecutionStatus* status)
+{
+ this->Status = status;
+ this->Makefile = &status->GetMakefile();
+}
+
bool cmCommand::InvokeInitialPass(const std::vector<cmListFileArgument>& args,
cmExecutionStatus& status)
{
@@ -19,15 +27,33 @@ bool cmCommand::InvokeInitialPass(const std::vector<cmListFileArgument>& args,
return this->InitialPass(expandedArguments, status);
}
-const char* cmCommand::GetError()
+void cmCommand::SetError(const std::string& e)
{
- if (this->Error.empty()) {
- return "unknown error.";
- }
- return this->Error.c_str();
+ this->Status->SetError(e);
}
-void cmCommand::SetError(const std::string& e)
+cmLegacyCommandWrapper::cmLegacyCommandWrapper(std::unique_ptr<cmCommand> cmd)
+ : Command(std::move(cmd))
+{
+}
+
+cmLegacyCommandWrapper::cmLegacyCommandWrapper(
+ cmLegacyCommandWrapper const& other)
+ : Command(other.Command->Clone())
+{
+}
+
+cmLegacyCommandWrapper& cmLegacyCommandWrapper::operator=(
+ cmLegacyCommandWrapper const& other)
+{
+ this->Command = other.Command->Clone();
+ return *this;
+}
+
+bool cmLegacyCommandWrapper::operator()(
+ std::vector<cmListFileArgument> const& args, cmExecutionStatus& status) const
{
- this->Error = e;
+ auto cmd = this->Command->Clone();
+ cmd->SetExecutionStatus(&status);
+ return cmd->InvokeInitialPass(args, status);
}
diff --git a/Source/cmCommand.h b/Source/cmCommand.h
index ad72fe208..bcb178d38 100644
--- a/Source/cmCommand.h
+++ b/Source/cmCommand.h
@@ -3,8 +3,9 @@
#ifndef cmCommand_h
#define cmCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+#include <memory>
#include <string>
#include <vector>
@@ -24,35 +25,35 @@ struct cmListFileArgument;
*/
class cmCommand
{
- CM_DISABLE_COPY(cmCommand)
-
public:
/**
* Construct the command. By default it has no makefile.
*/
- cmCommand()
- : Makefile(CM_NULLPTR)
- {
- }
+ cmCommand() = default;
/**
* Need virtual destructor to destroy real command type.
*/
- virtual ~cmCommand() {}
+ virtual ~cmCommand() = default;
+
+ cmCommand(cmCommand const&) = delete;
+ cmCommand& operator=(cmCommand const&) = delete;
/**
* Specify the makefile.
*/
- void SetMakefile(cmMakefile* m) { this->Makefile = m; }
cmMakefile* GetMakefile() { return this->Makefile; }
+ void SetExecutionStatus(cmExecutionStatus* s);
+ cmExecutionStatus* GetExecutionStatus() { return this->Status; };
+
/**
* This is called by the cmMakefile when the command is first
* encountered in the CMakeLists.txt file. It expands the command's
* arguments and then invokes the InitialPass.
*/
- virtual bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
- cmExecutionStatus& status);
+ bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
+ cmExecutionStatus& status);
/**
* This is called when the command is first encountered in
@@ -62,27 +63,9 @@ public:
cmExecutionStatus&) = 0;
/**
- * This is called at the end after all the information
- * specified by the command is accumulated. Most commands do
- * not implement this method. At this point, reading and
- * writing to the cache can be done.
- */
- virtual void FinalPass() {}
-
- /**
- * Does this command have a final pass? Query after InitialPass.
- */
- virtual bool HasFinalPass() const { return false; }
-
- /**
* This is a virtual constructor for the command.
*/
- virtual cmCommand* Clone() = 0;
-
- /**
- * Return the last error string.
- */
- const char* GetError();
+ virtual std::unique_ptr<cmCommand> Clone() = 0;
/**
* Set the error message
@@ -90,10 +73,28 @@ public:
void SetError(const std::string& e);
protected:
- cmMakefile* Makefile;
+ cmMakefile* Makefile = nullptr;
+
+private:
+ cmExecutionStatus* Status = nullptr;
+};
+
+class cmLegacyCommandWrapper
+{
+public:
+ explicit cmLegacyCommandWrapper(std::unique_ptr<cmCommand> cmd);
+
+ cmLegacyCommandWrapper(cmLegacyCommandWrapper const& other);
+ cmLegacyCommandWrapper& operator=(cmLegacyCommandWrapper const& other);
+
+ cmLegacyCommandWrapper(cmLegacyCommandWrapper&&) = default;
+ cmLegacyCommandWrapper& operator=(cmLegacyCommandWrapper&&) = default;
+
+ bool operator()(std::vector<cmListFileArgument> const& args,
+ cmExecutionStatus& status) const;
private:
- std::string Error;
+ std::unique_ptr<cmCommand> Command;
};
#endif
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index 4eb4531f6..613ae06d1 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -2,32 +2,23 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCommandArgumentParserHelper.h"
+#include <cstring>
+#include <iostream>
+#include <sstream>
+
#include "cmCommandArgumentLexer.h"
#include "cmMakefile.h"
#include "cmState.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmake.h"
-
-#include <iostream>
-#include <sstream>
-#include <string.h>
int cmCommandArgument_yyparse(yyscan_t yyscanner);
//
cmCommandArgumentParserHelper::cmCommandArgumentParserHelper()
{
- this->WarnUninitialized = false;
- this->CheckSystemVars = false;
this->FileLine = -1;
- this->FileName = CM_NULLPTR;
+ 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 +35,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,81 +46,68 @@ 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;
if (cmSystemTools::GetEnv(var, str)) {
if (this->EscapeQuotes) {
- return this->AddString(cmSystemTools::EscapeQuotes(str));
+ return this->AddString(cmEscapeQuotes(str));
}
return this->AddString(str);
}
- return this->EmptyVariable;
+ return "";
}
if (strcmp(key, "CACHE") == 0) {
- if (const char* c =
+ if (const std::string* c =
this->Makefile->GetState()->GetInitializedCacheValue(var)) {
if (this->EscapeQuotes) {
- return this->AddString(cmSystemTools::EscapeQuotes(c));
+ return this->AddString(cmEscapeQuotes(*c));
}
- return this->AddString(c);
+ return this->AddString(*c);
}
- return this->EmptyVariable;
+ return "";
}
std::ostringstream e;
e << "Syntax $" << key << "{} is not supported. "
<< "Only ${}, $ENV{}, and $CACHE{} are allowed.";
this->SetError(e.str());
- return CM_NULLPTR;
+ return nullptr;
}
-char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
+const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
{
if (!var) {
- return CM_NULLPTR;
+ return nullptr;
}
if (this->FileLine >= 0 && strcmp(var, "CMAKE_CURRENT_LIST_LINE") == 0) {
- std::ostringstream ostr;
- ostr << this->FileLine;
- return this->AddString(ostr.str());
+ return this->AddString(std::to_string(this->FileLine));
}
const char* value = this->Makefile->GetDefinition(var);
- if (!value && !this->RemoveEmpty) {
- // check to see if we need to print a warning
- // if strict mode is on and the variable has
- // not been "cleared"/initialized with a set(foo ) call
- if (this->WarnUninitialized && !this->Makefile->VariableInitialized(var)) {
- if (this->CheckSystemVars ||
- cmSystemTools::IsSubDirectory(this->FileName,
- this->Makefile->GetHomeDirectory()) ||
- cmSystemTools::IsSubDirectory(
- this->FileName, this->Makefile->GetHomeOutputDirectory())) {
- std::ostringstream msg;
- msg << "uninitialized variable \'" << var << "\'";
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, msg.str());
- }
+ if (!value) {
+ this->Makefile->MaybeWarnUninitialized(var, this->FileName);
+ if (!this->RemoveEmpty) {
+ return nullptr;
}
- return CM_NULLPTR;
}
if (this->EscapeQuotes && value) {
- return this->AddString(cmSystemTools::EscapeQuotes(value));
+ return this->AddString(cmEscapeQuotes(value));
}
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) {
@@ -144,13 +122,12 @@ char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var)
// - this->ReplaceAtSyntax is false
// - this->ReplaceAtSyntax is true, but this->RemoveEmpty is false,
// and the variable was not defined
- std::string ref = "@";
- ref += var;
- ref += "@";
+ std::string ref = cmStrCat('@', 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;
@@ -169,17 +146,18 @@ char* cmCommandArgumentParserHelper::CombineUnions(char* in1, char* in2)
void cmCommandArgumentParserHelper::AllocateParserType(
cmCommandArgumentParserHelper::ParserType* pt, const char* str, int len)
{
- pt->str = CM_NULLPTR;
+ pt->str = nullptr;
if (len == 0) {
len = static_cast<int>(strlen(str));
}
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];
+ memcpy(out, str, len);
+ out[len] = 0;
+ pt->str = out;
+ this->Variables.push_back(out);
}
bool cmCommandArgumentParserHelper::HandleEscapeSymbol(
@@ -234,7 +212,7 @@ int cmCommandArgumentParserHelper::ParseString(const char* str, int verb)
this->InputBufferPos = 0;
this->CurrentLine = 0;
- this->Result = "";
+ this->Result.clear();
yyscan_t yyscanner;
cmCommandArgument_yylex_init(&yyscanner);
@@ -257,9 +235,8 @@ int cmCommandArgumentParserHelper::ParseString(const char* str, int verb)
void cmCommandArgumentParserHelper::CleanupParser()
{
- std::vector<char*>::iterator sit;
- for (sit = this->Variables.begin(); sit != this->Variables.end(); ++sit) {
- delete[] * sit;
+ for (char* var : this->Variables) {
+ delete[] var;
}
this->Variables.erase(this->Variables.begin(), this->Variables.end());
}
@@ -291,14 +268,12 @@ void cmCommandArgumentParserHelper::Error(const char* str)
void cmCommandArgumentParserHelper::SetMakefile(const cmMakefile* mf)
{
this->Makefile = mf;
- this->WarnUninitialized = mf->GetCMakeInstance()->GetWarnUninitialized();
- this->CheckSystemVars = mf->GetCMakeInstance()->GetCheckSystemVars();
}
void cmCommandArgumentParserHelper::SetResult(const char* value)
{
if (!value) {
- this->Result = "";
+ this->Result.clear();
return;
}
this->Result = value;
diff --git a/Source/cmCommandArgumentParserHelper.h b/Source/cmCommandArgumentParserHelper.h
index 465ca9e28..25e689224 100644
--- a/Source/cmCommandArgumentParserHelper.h
+++ b/Source/cmCommandArgumentParserHelper.h
@@ -3,7 +3,7 @@
#ifndef cmCommandArgumentParserHelper_h
#define cmCommandArgumentParserHelper_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
@@ -12,17 +12,19 @@ class cmMakefile;
class cmCommandArgumentParserHelper
{
- CM_DISABLE_COPY(cmCommandArgumentParserHelper)
-
public:
struct ParserType
{
- char* str;
+ const char* str;
};
cmCommandArgumentParserHelper();
~cmCommandArgumentParserHelper();
+ cmCommandArgumentParserHelper(cmCommandArgumentParserHelper const&) = delete;
+ cmCommandArgumentParserHelper& operator=(
+ cmCommandArgumentParserHelper const&) = delete;
+
int ParseString(const char* str, int verb);
// For the lexer:
@@ -35,11 +37,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 +55,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 +64,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);
@@ -82,8 +77,6 @@ private:
long FileLine;
int CurrentLine;
int Verbose;
- bool WarnUninitialized;
- bool CheckSystemVars;
bool EscapeQuotes;
bool NoEscapeMode;
bool ReplaceAtSyntax;
diff --git a/Source/cmCommandArgumentsHelper.cxx b/Source/cmCommandArgumentsHelper.cxx
deleted file mode 100644
index babddbe94..000000000
--- a/Source/cmCommandArgumentsHelper.cxx
+++ /dev/null
@@ -1,245 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmCommandArgumentsHelper.h"
-
-cmCommandArgument::cmCommandArgument(cmCommandArgumentsHelper* args,
- const char* key,
- cmCommandArgumentGroup* group)
- : Key(key)
- , Group(group)
- , WasActive(false)
- , ArgumentsBeforeEmpty(true)
- , CurrentIndex(0)
-{
- if (args != CM_NULLPTR) {
- args->AddArgument(this);
- }
-
- if (this->Group != CM_NULLPTR) {
- this->Group->ContainedArguments.push_back(this);
- }
-}
-
-void cmCommandArgument::Reset()
-{
- this->WasActive = false;
- this->CurrentIndex = 0;
- this->DoReset();
-}
-
-void cmCommandArgument::Follows(const cmCommandArgument* arg)
-{
- this->ArgumentsBeforeEmpty = false;
- this->ArgumentsBefore.insert(arg);
-}
-
-void cmCommandArgument::FollowsGroup(const cmCommandArgumentGroup* group)
-{
- if (group != CM_NULLPTR) {
- this->ArgumentsBeforeEmpty = false;
- this->ArgumentsBefore.insert(group->ContainedArguments.begin(),
- group->ContainedArguments.end());
- }
-}
-
-bool cmCommandArgument::MayFollow(const cmCommandArgument* current) const
-{
- if (this->ArgumentsBeforeEmpty) {
- return true;
- }
- return this->ArgumentsBefore.find(current) != this->ArgumentsBefore.end();
-}
-
-bool cmCommandArgument::KeyMatches(const std::string& key) const
-{
- if ((this->Key == CM_NULLPTR) || (this->Key[0] == '\0')) {
- return true;
- }
- return (key == this->Key);
-}
-
-void cmCommandArgument::ApplyOwnGroup()
-{
- if (this->Group != CM_NULLPTR) {
- for (std::vector<cmCommandArgument*>::const_iterator it =
- this->Group->ContainedArguments.begin();
- it != this->Group->ContainedArguments.end(); ++it) {
- if (*it != this) {
- this->ArgumentsBefore.insert(*it);
- }
- }
- }
-}
-
-void cmCommandArgument::Activate()
-{
- this->WasActive = true;
- this->CurrentIndex = 0;
-}
-
-bool cmCommandArgument::Consume(const std::string& arg)
-{
- bool res = this->DoConsume(arg, this->CurrentIndex);
- this->CurrentIndex++;
- return res;
-}
-
-cmCAStringVector::cmCAStringVector(cmCommandArgumentsHelper* args,
- const char* key,
- cmCommandArgumentGroup* group)
- : cmCommandArgument(args, key, group)
- , Ignore(CM_NULLPTR)
-{
- if ((key == CM_NULLPTR) || (*key == 0)) {
- this->DataStart = 0;
- } else {
- this->DataStart = 1;
- }
-}
-
-bool cmCAStringVector::DoConsume(const std::string& arg, unsigned int index)
-{
- if (index >= this->DataStart) {
- if ((this->Ignore == CM_NULLPTR) || (arg != this->Ignore)) {
- this->Vector.push_back(arg);
- }
- }
-
- return false;
-}
-
-void cmCAStringVector::DoReset()
-{
- this->Vector.clear();
-}
-
-cmCAString::cmCAString(cmCommandArgumentsHelper* args, const char* key,
- cmCommandArgumentGroup* group)
- : cmCommandArgument(args, key, group)
-{
- if ((key == CM_NULLPTR) || (*key == 0)) {
- this->DataStart = 0;
- } else {
- this->DataStart = 1;
- }
-}
-
-bool cmCAString::DoConsume(const std::string& arg, unsigned int index)
-{
- if (index == this->DataStart) {
- this->String = arg;
- }
-
- return index >= this->DataStart;
-}
-
-void cmCAString::DoReset()
-{
- this->String = "";
-}
-
-cmCAEnabler::cmCAEnabler(cmCommandArgumentsHelper* args, const char* key,
- cmCommandArgumentGroup* group)
- : cmCommandArgument(args, key, group)
- , Enabled(false)
-{
-}
-
-bool cmCAEnabler::DoConsume(const std::string&, unsigned int index)
-{
- if (index == 0) {
- this->Enabled = true;
- }
- return true;
-}
-
-void cmCAEnabler::DoReset()
-{
- this->Enabled = false;
-}
-
-cmCADisabler::cmCADisabler(cmCommandArgumentsHelper* args, const char* key,
- cmCommandArgumentGroup* group)
- : cmCommandArgument(args, key, group)
- , Enabled(true)
-{
-}
-
-bool cmCADisabler::DoConsume(const std::string&, unsigned int index)
-{
- if (index == 0) {
- this->Enabled = false;
- }
- return true;
-}
-
-void cmCADisabler::DoReset()
-{
- this->Enabled = true;
-}
-
-void cmCommandArgumentGroup::Follows(const cmCommandArgument* arg)
-{
- for (std::vector<cmCommandArgument*>::iterator it =
- this->ContainedArguments.begin();
- it != this->ContainedArguments.end(); ++it) {
- (*it)->Follows(arg);
- }
-}
-
-void cmCommandArgumentGroup::FollowsGroup(const cmCommandArgumentGroup* group)
-{
- for (std::vector<cmCommandArgument*>::iterator it =
- this->ContainedArguments.begin();
- it != this->ContainedArguments.end(); ++it) {
- (*it)->FollowsGroup(group);
- }
-}
-
-void cmCommandArgumentsHelper::Parse(const std::vector<std::string>* args,
- std::vector<std::string>* unconsumedArgs)
-{
- if (args == CM_NULLPTR) {
- return;
- }
-
- for (std::vector<cmCommandArgument*>::iterator argIt =
- this->Arguments.begin();
- argIt != this->Arguments.end(); ++argIt) {
- (*argIt)->ApplyOwnGroup();
- (*argIt)->Reset();
- }
-
- cmCommandArgument* activeArgument = CM_NULLPTR;
- const cmCommandArgument* previousArgument = CM_NULLPTR;
- for (std::vector<std::string>::const_iterator it = args->begin();
- it != args->end(); ++it) {
- for (std::vector<cmCommandArgument*>::iterator argIt =
- this->Arguments.begin();
- argIt != this->Arguments.end(); ++argIt) {
- if ((*argIt)->KeyMatches(*it) &&
- ((*argIt)->MayFollow(previousArgument))) {
- activeArgument = *argIt;
- activeArgument->Activate();
- break;
- }
- }
-
- if (activeArgument) {
- bool argDone = activeArgument->Consume(*it);
- previousArgument = activeArgument;
- if (argDone) {
- activeArgument = CM_NULLPTR;
- }
- } else {
- if (unconsumedArgs != CM_NULLPTR) {
- unconsumedArgs->push_back(*it);
- }
- }
- }
-}
-
-void cmCommandArgumentsHelper::AddArgument(cmCommandArgument* arg)
-{
- this->Arguments.push_back(arg);
-}
diff --git a/Source/cmCommandArgumentsHelper.h b/Source/cmCommandArgumentsHelper.h
deleted file mode 100644
index 44db374d6..000000000
--- a/Source/cmCommandArgumentsHelper.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmCommandArgumentsHelper_h
-#define cmCommandArgumentsHelper_h
-
-#include "cmConfigure.h"
-
-#include <set>
-#include <string>
-#include <vector>
-
-class cmCommandArgumentGroup;
-class cmCommandArgumentsHelper;
-
-/* cmCommandArgumentsHelper, cmCommandArgumentGroup and cmCommandArgument (i.e.
-its derived classes cmCAXXX can be used to simplify the processing of
-arguments to cmake commands. Maybe they can also be used to generate
-documentation.
-
-For every argument supported by a command one cmCommandArgument is created
-and added to cmCommandArgumentsHelper. cmCommand has a cmCommandArgumentsHelper
-as member variable so this should be used.
-
-The order of the arguments is defined using the Follows(arg) method. It says
-that this argument follows immediateley the given argument. It can be used
-with multiple arguments if the argument can follow after different arguments.
-
-Arguments can be arranged in groups using cmCommandArgumentGroup. Every
-member of a group can follow any other member of the group. These groups
-can also be used to define the order.
-
-Once all arguments and groups are set up, cmCommandArgumentsHelper::Parse()
-is called and afterwards the values of the arguments can be evaluated.
-
-For an example see cmExportCommand.cxx.
-*/
-class cmCommandArgument
-{
-public:
- cmCommandArgument(cmCommandArgumentsHelper* args, const char* key,
- cmCommandArgumentGroup* group = CM_NULLPTR);
- virtual ~cmCommandArgument() {}
-
- /// this argument may follow after arg. 0 means it comes first.
- void Follows(const cmCommandArgument* arg);
-
- /// this argument may follow after any of the arguments in the given group
- void FollowsGroup(const cmCommandArgumentGroup* group);
-
- /// Returns true if the argument was found in the argument list
- bool WasFound() const { return this->WasActive; }
-
- // The following methods are only called from
- // cmCommandArgumentsHelper::Parse(), but making this a friend would
- // give it access to everything
-
- /// Make the current argument the currently active argument
- void Activate();
- /// Consume the current string
- bool Consume(const std::string& arg);
-
- /// Return true if this argument may follow after the given argument.
- bool MayFollow(const cmCommandArgument* current) const;
-
- /** Returns true if the given key matches the key for this argument.
- If this argument has an empty key everything matches. */
- bool KeyMatches(const std::string& key) const;
-
- /// Make this argument follow all members of the own group
- void ApplyOwnGroup();
-
- /// Reset argument, so it's back to its initial state
- void Reset();
-
-private:
- const char* Key;
- std::set<const cmCommandArgument*> ArgumentsBefore;
- cmCommandArgumentGroup* Group;
- bool WasActive;
- bool ArgumentsBeforeEmpty;
- unsigned int CurrentIndex;
-
- virtual bool DoConsume(const std::string& arg, unsigned int index) = 0;
- virtual void DoReset() = 0;
-};
-
-/** cmCAStringVector is to be used for arguments which can consist of more
-than one string, e.g. the FILES argument in INSTALL(FILES f1 f2 f3 ...). */
-class cmCAStringVector : public cmCommandArgument
-{
-public:
- cmCAStringVector(cmCommandArgumentsHelper* args, const char* key,
- cmCommandArgumentGroup* group = CM_NULLPTR);
-
- /// Return the vector of strings
- const std::vector<std::string>& GetVector() const { return this->Vector; }
-
- /** Is there a keyword which should be skipped in
- the arguments (e.g. ARGS for ADD_CUSTOM_COMMAND) ? */
- void SetIgnore(const char* ignore) { this->Ignore = ignore; }
-private:
- std::vector<std::string> Vector;
- unsigned int DataStart;
- const char* Ignore;
- cmCAStringVector();
- bool DoConsume(const std::string& arg, unsigned int index) CM_OVERRIDE;
- void DoReset() CM_OVERRIDE;
-};
-
-/** cmCAString is to be used for arguments which consist of one value,
-e.g. the executable name in ADD_EXECUTABLE(). */
-class cmCAString : public cmCommandArgument
-{
-public:
- cmCAString(cmCommandArgumentsHelper* args, const char* key,
- cmCommandArgumentGroup* group = CM_NULLPTR);
-
- /// Return the string
- const std::string& GetString() const { return this->String; }
- const char* GetCString() const { return this->String.c_str(); }
-private:
- std::string String;
- unsigned int DataStart;
- bool DoConsume(const std::string& arg, unsigned int index) CM_OVERRIDE;
- void DoReset() CM_OVERRIDE;
- cmCAString();
-};
-
-/** cmCAEnabler is to be used for options which are off by default and can be
-enabled using a special argument, e.g. EXCLUDE_FROM_ALL in ADD_EXECUTABLE(). */
-class cmCAEnabler : public cmCommandArgument
-{
-public:
- cmCAEnabler(cmCommandArgumentsHelper* args, const char* key,
- cmCommandArgumentGroup* group = CM_NULLPTR);
-
- /// Has it been enabled ?
- bool IsEnabled() const { return this->Enabled; }
-private:
- bool Enabled;
- bool DoConsume(const std::string& arg, unsigned int index) CM_OVERRIDE;
- void DoReset() CM_OVERRIDE;
- cmCAEnabler();
-};
-
-/** cmCADisable is to be used for options which are on by default and can be
-disabled using a special argument.*/
-class cmCADisabler : public cmCommandArgument
-{
-public:
- cmCADisabler(cmCommandArgumentsHelper* args, const char* key,
- cmCommandArgumentGroup* group = CM_NULLPTR);
-
- /// Is it still enabled ?
- bool IsEnabled() const { return this->Enabled; }
-private:
- bool Enabled;
- bool DoConsume(const std::string& arg, unsigned int index) CM_OVERRIDE;
- void DoReset() CM_OVERRIDE;
- cmCADisabler();
-};
-
-/** Group of arguments, needed for ordering. E.g. WIN32, EXCLUDE_FROM_ALL and
-MACSOX_BUNDLE from ADD_EXECUTABLE() are a group.
-*/
-class cmCommandArgumentGroup
-{
- friend class cmCommandArgument;
-
-public:
- cmCommandArgumentGroup() {}
-
- /// All members of this group may follow the given argument
- void Follows(const cmCommandArgument* arg);
-
- /// All members of this group may follow all members of the given group
- void FollowsGroup(const cmCommandArgumentGroup* group);
-
-private:
- std::vector<cmCommandArgument*> ContainedArguments;
-};
-
-class cmCommandArgumentsHelper
-{
-public:
- /// Parse the argument list
- void Parse(const std::vector<std::string>* args,
- std::vector<std::string>* unconsumedArgs);
- /// Add an argument.
- void AddArgument(cmCommandArgument* arg);
-
-private:
- std::vector<cmCommandArgument*> Arguments;
-};
-
-#endif
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index e1d8ef143..6f19697bc 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -1,9 +1,11 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+
#include "cmCommands.h"
-#include "cmPolicies.h"
-#include "cmState.h"
+#include <cm/memory>
+
+#include "cmAddCompileDefinitionsCommand.h"
#include "cmAddCustomCommandCommand.h"
#include "cmAddCustomTargetCommand.h"
#include "cmAddDefinitionsCommand.h"
@@ -16,6 +18,7 @@
#include "cmBuildCommand.h"
#include "cmCMakeMinimumRequired.h"
#include "cmCMakePolicyCommand.h"
+#include "cmCommand.h"
#include "cmConfigureFileCommand.h"
#include "cmContinueCommand.h"
#include "cmCreateTestSourceList.h"
@@ -42,6 +45,7 @@
#include "cmIfCommand.h"
#include "cmIncludeCommand.h"
#include "cmIncludeDirectoryCommand.h"
+#include "cmIncludeGuardCommand.h"
#include "cmIncludeRegularExpressionCommand.h"
#include "cmInstallCommand.h"
#include "cmInstallFilesCommand.h"
@@ -55,6 +59,7 @@
#include "cmMessageCommand.h"
#include "cmOptionCommand.h"
#include "cmParseArgumentsCommand.h"
+#include "cmPolicies.h"
#include "cmProjectCommand.h"
#include "cmReturnCommand.h"
#include "cmSeparateArgumentsCommand.h"
@@ -65,134 +70,143 @@
#include "cmSetTargetPropertiesCommand.h"
#include "cmSetTestsPropertiesCommand.h"
#include "cmSiteNameCommand.h"
+#include "cmState.h"
#include "cmStringCommand.h"
#include "cmSubdirCommand.h"
+#include "cmTargetCompileDefinitionsCommand.h"
+#include "cmTargetCompileFeaturesCommand.h"
+#include "cmTargetCompileOptionsCommand.h"
+#include "cmTargetIncludeDirectoriesCommand.h"
#include "cmTargetLinkLibrariesCommand.h"
+#include "cmTargetLinkOptionsCommand.h"
+#include "cmTargetPrecompileHeadersCommand.h"
+#include "cmTargetSourcesCommand.h"
#include "cmTryCompileCommand.h"
#include "cmTryRunCommand.h"
#include "cmUnsetCommand.h"
#include "cmWhileCommand.h"
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmAddCompileOptionsCommand.h"
-#include "cmAuxSourceDirectoryCommand.h"
-#include "cmBuildNameCommand.h"
-#include "cmCMakeHostSystemInformationCommand.h"
-#include "cmExportCommand.h"
-#include "cmExportLibraryDependenciesCommand.h"
-#include "cmFLTKWrapUICommand.h"
-#include "cmIncludeExternalMSProjectCommand.h"
-#include "cmInstallProgramsCommand.h"
-#include "cmLinkLibrariesCommand.h"
-#include "cmLoadCacheCommand.h"
-#include "cmLoadCommandCommand.h"
-#include "cmOutputRequiredFilesCommand.h"
-#include "cmQTWrapCPPCommand.h"
-#include "cmQTWrapUICommand.h"
-#include "cmRemoveCommand.h"
-#include "cmRemoveDefinitionsCommand.h"
-#include "cmSourceGroupCommand.h"
-#include "cmSubdirDependsCommand.h"
-#include "cmTargetCompileDefinitionsCommand.h"
-#include "cmTargetCompileFeaturesCommand.h"
-#include "cmTargetCompileOptionsCommand.h"
-#include "cmTargetIncludeDirectoriesCommand.h"
-#include "cmTargetSourcesCommand.h"
-#include "cmUseMangledMesaCommand.h"
-#include "cmUtilitySourceCommand.h"
-#include "cmVariableRequiresCommand.h"
-#include "cmVariableWatchCommand.h"
-#include "cmWriteFileCommand.h"
+#if !defined(CMAKE_BOOTSTRAP)
+# include "cmAddCompileOptionsCommand.h"
+# include "cmAddLinkOptionsCommand.h"
+# include "cmAuxSourceDirectoryCommand.h"
+# include "cmBuildNameCommand.h"
+# include "cmCMakeHostSystemInformationCommand.h"
+# include "cmExportCommand.h"
+# include "cmExportLibraryDependenciesCommand.h"
+# include "cmFLTKWrapUICommand.h"
+# include "cmIncludeExternalMSProjectCommand.h"
+# include "cmInstallProgramsCommand.h"
+# include "cmLinkLibrariesCommand.h"
+# include "cmLoadCacheCommand.h"
+# include "cmLoadCommandCommand.h"
+# include "cmOutputRequiredFilesCommand.h"
+# include "cmQTWrapCPPCommand.h"
+# include "cmQTWrapUICommand.h"
+# include "cmRemoveCommand.h"
+# include "cmRemoveDefinitionsCommand.h"
+# include "cmSourceGroupCommand.h"
+# include "cmSubdirDependsCommand.h"
+# include "cmTargetLinkDirectoriesCommand.h"
+# include "cmUseMangledMesaCommand.h"
+# include "cmUtilitySourceCommand.h"
+# include "cmVariableRequiresCommand.h"
+# include "cmVariableWatchCommand.h"
+# include "cmWriteFileCommand.h"
#endif
void GetScriptingCommands(cmState* state)
{
- state->AddBuiltinCommand("break", new cmBreakCommand);
- state->AddBuiltinCommand("cmake_minimum_required",
- new cmCMakeMinimumRequired);
- state->AddBuiltinCommand("cmake_policy", new cmCMakePolicyCommand);
- state->AddBuiltinCommand("configure_file", new cmConfigureFileCommand);
- state->AddBuiltinCommand("continue", new cmContinueCommand);
- state->AddBuiltinCommand("exec_program", new cmExecProgramCommand);
- state->AddBuiltinCommand("execute_process", new cmExecuteProcessCommand);
- state->AddBuiltinCommand("file", new cmFileCommand);
- state->AddBuiltinCommand("find_file", new cmFindFileCommand);
- state->AddBuiltinCommand("find_library", new cmFindLibraryCommand);
- state->AddBuiltinCommand("find_package", new cmFindPackageCommand);
- state->AddBuiltinCommand("find_path", new cmFindPathCommand);
- state->AddBuiltinCommand("find_program", new cmFindProgramCommand);
- state->AddBuiltinCommand("foreach", new cmForEachCommand);
- state->AddBuiltinCommand("function", new cmFunctionCommand);
- state->AddBuiltinCommand("get_cmake_property",
- new cmGetCMakePropertyCommand);
+ state->AddBuiltinCommand("break", cmBreakCommand);
+ state->AddBuiltinCommand("cmake_minimum_required", cmCMakeMinimumRequired);
+ state->AddBuiltinCommand("cmake_policy", cmCMakePolicyCommand);
+ state->AddBuiltinCommand("configure_file", cmConfigureFileCommand);
+ state->AddBuiltinCommand("continue", cmContinueCommand);
+ state->AddBuiltinCommand("exec_program", cmExecProgramCommand);
+ state->AddBuiltinCommand("execute_process", cmExecuteProcessCommand);
+ state->AddBuiltinCommand("file", cmFileCommand);
+ state->AddBuiltinCommand("find_file", cmFindFile);
+ state->AddBuiltinCommand("find_library", cmFindLibrary);
+ state->AddBuiltinCommand("find_package", cmFindPackage);
+ state->AddBuiltinCommand("find_path", cmFindPath);
+ state->AddBuiltinCommand("find_program", cmFindProgram);
+ state->AddBuiltinCommand("foreach", cmForEachCommand);
+ state->AddBuiltinCommand("function", cmFunctionCommand);
+ state->AddBuiltinCommand("get_cmake_property", cmGetCMakePropertyCommand);
state->AddBuiltinCommand("get_directory_property",
- new cmGetDirectoryPropertyCommand);
+ cmGetDirectoryPropertyCommand);
state->AddBuiltinCommand("get_filename_component",
- new cmGetFilenameComponentCommand);
- state->AddBuiltinCommand("get_property", new cmGetPropertyCommand);
- state->AddBuiltinCommand("if", new cmIfCommand);
- state->AddBuiltinCommand("include", new cmIncludeCommand);
- state->AddBuiltinCommand("list", new cmListCommand);
- state->AddBuiltinCommand("macro", new cmMacroCommand);
- state->AddBuiltinCommand("make_directory", new cmMakeDirectoryCommand);
- state->AddBuiltinCommand("mark_as_advanced", new cmMarkAsAdvancedCommand);
- state->AddBuiltinCommand("math", new cmMathCommand);
- state->AddBuiltinCommand("message", new cmMessageCommand);
- state->AddBuiltinCommand("option", new cmOptionCommand);
- state->AddBuiltinCommand("cmake_parse_arguments",
- new cmParseArgumentsCommand);
- state->AddBuiltinCommand("return", new cmReturnCommand);
- state->AddBuiltinCommand("separate_arguments",
- new cmSeparateArgumentsCommand);
- state->AddBuiltinCommand("set", new cmSetCommand);
+ cmGetFilenameComponentCommand);
+ state->AddBuiltinCommand("get_property", cmGetPropertyCommand);
+ state->AddBuiltinCommand("if", cmIfCommand);
+ state->AddBuiltinCommand("include", cmIncludeCommand);
+ state->AddBuiltinCommand("include_guard", cmIncludeGuardCommand);
+ state->AddBuiltinCommand("list", cmListCommand);
+ state->AddBuiltinCommand("macro", cmMacroCommand);
+ state->AddBuiltinCommand("make_directory", cmMakeDirectoryCommand);
+ state->AddBuiltinCommand("mark_as_advanced", cmMarkAsAdvancedCommand);
+ state->AddBuiltinCommand("math", cmMathCommand);
+ state->AddBuiltinCommand("message", cmMessageCommand);
+ state->AddBuiltinCommand("option", cmOptionCommand);
+ state->AddBuiltinCommand("cmake_parse_arguments", cmParseArgumentsCommand);
+ state->AddBuiltinCommand("return", cmReturnCommand);
+ state->AddBuiltinCommand("separate_arguments", cmSeparateArgumentsCommand);
+ state->AddBuiltinCommand("set", cmSetCommand);
state->AddBuiltinCommand("set_directory_properties",
- new cmSetDirectoryPropertiesCommand);
- state->AddBuiltinCommand("set_property", new cmSetPropertyCommand);
- state->AddBuiltinCommand("site_name", new cmSiteNameCommand);
- state->AddBuiltinCommand("string", new cmStringCommand);
- state->AddBuiltinCommand("unset", new cmUnsetCommand);
- state->AddBuiltinCommand("while", new cmWhileCommand);
+ cmSetDirectoryPropertiesCommand);
+ state->AddBuiltinCommand("set_property", cmSetPropertyCommand);
+ state->AddBuiltinCommand("site_name", cmSiteNameCommand);
+ state->AddBuiltinCommand("string", cmStringCommand);
+ state->AddBuiltinCommand("unset", cmUnsetCommand);
+ state->AddBuiltinCommand("while", cmWhileCommand);
state->AddUnexpectedCommand(
- "else", "An ELSE command was found outside of a proper "
- "IF ENDIF structure. Or its arguments did not match "
- "the opening IF command.");
+ "else",
+ "An ELSE command was found outside of a proper "
+ "IF ENDIF structure. Or its arguments did not match "
+ "the opening IF command.");
state->AddUnexpectedCommand(
- "elseif", "An ELSEIF command was found outside of a proper "
- "IF ENDIF structure.");
+ "elseif",
+ "An ELSEIF command was found outside of a proper "
+ "IF ENDIF structure.");
state->AddUnexpectedCommand(
- "endforeach", "An ENDFOREACH command was found outside of a proper "
- "FOREACH ENDFOREACH structure. Or its arguments did "
- "not match the opening FOREACH command.");
+ "endforeach",
+ "An ENDFOREACH command was found outside of a proper "
+ "FOREACH ENDFOREACH structure. Or its arguments did "
+ "not match the opening FOREACH command.");
state->AddUnexpectedCommand(
- "endfunction", "An ENDFUNCTION command was found outside of a proper "
- "FUNCTION ENDFUNCTION structure. Or its arguments did not "
- "match the opening FUNCTION command.");
+ "endfunction",
+ "An ENDFUNCTION command was found outside of a proper "
+ "FUNCTION ENDFUNCTION structure. Or its arguments did not "
+ "match the opening FUNCTION command.");
state->AddUnexpectedCommand(
- "endif", "An ENDIF command was found outside of a proper "
- "IF ENDIF structure. Or its arguments did not match "
- "the opening IF command.");
+ "endif",
+ "An ENDIF command was found outside of a proper "
+ "IF ENDIF structure. Or its arguments did not match "
+ "the opening IF command.");
state->AddUnexpectedCommand(
- "endmacro", "An ENDMACRO command was found outside of a proper "
- "MACRO ENDMACRO structure. Or its arguments did not "
- "match the opening MACRO command.");
+ "endmacro",
+ "An ENDMACRO command was found outside of a proper "
+ "MACRO ENDMACRO structure. Or its arguments did not "
+ "match the opening MACRO command.");
state->AddUnexpectedCommand(
- "endwhile", "An ENDWHILE command was found outside of a proper "
- "WHILE ENDWHILE structure. Or its arguments did not "
- "match the opening WHILE command.");
+ "endwhile",
+ "An ENDWHILE command was found outside of a proper "
+ "WHILE ENDWHILE structure. Or its arguments did not "
+ "match the opening WHILE command.");
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
state->AddBuiltinCommand("cmake_host_system_information",
- new cmCMakeHostSystemInformationCommand);
- state->AddBuiltinCommand("remove", new cmRemoveCommand);
- state->AddBuiltinCommand("variable_watch", new cmVariableWatchCommand);
- state->AddBuiltinCommand("write_file", new cmWriteFileCommand);
+ cmCMakeHostSystemInformationCommand);
+ state->AddBuiltinCommand("remove", cmRemoveCommand);
+ state->AddBuiltinCommand("variable_watch", cmVariableWatchCommand);
+ state->AddBuiltinCommand("write_file", cmWriteFileCommand);
state->AddDisallowedCommand(
- "build_name", new cmBuildNameCommand, cmPolicies::CMP0036,
+ "build_name", cmBuildNameCommand, cmPolicies::CMP0036,
"The build_name command should not be called; see CMP0036.");
state->AddDisallowedCommand(
- "use_mangled_mesa", new cmUseMangledMesaCommand, cmPolicies::CMP0030,
+ "use_mangled_mesa", cmUseMangledMesaCommand, cmPolicies::CMP0030,
"The use_mangled_mesa command should not be called; see CMP0030.");
#endif
@@ -200,94 +214,96 @@ void GetScriptingCommands(cmState* state)
void GetProjectCommands(cmState* state)
{
- state->AddBuiltinCommand("add_custom_command",
- new cmAddCustomCommandCommand);
- state->AddBuiltinCommand("add_custom_target", new cmAddCustomTargetCommand);
- state->AddBuiltinCommand("add_definitions", new cmAddDefinitionsCommand);
- state->AddBuiltinCommand("add_dependencies", new cmAddDependenciesCommand);
- state->AddBuiltinCommand("add_executable", new cmAddExecutableCommand);
- state->AddBuiltinCommand("add_library", new cmAddLibraryCommand);
- state->AddBuiltinCommand("add_subdirectory", new cmAddSubDirectoryCommand);
- state->AddBuiltinCommand("add_test", new cmAddTestCommand);
- state->AddBuiltinCommand("build_command", new cmBuildCommand);
- state->AddBuiltinCommand("create_test_sourcelist",
- new cmCreateTestSourceList);
- state->AddBuiltinCommand("define_property", new cmDefinePropertyCommand);
- state->AddBuiltinCommand("enable_language", new cmEnableLanguageCommand);
- state->AddBuiltinCommand("enable_testing", new cmEnableTestingCommand);
+ state->AddBuiltinCommand("add_custom_command", cmAddCustomCommandCommand);
+ state->AddBuiltinCommand("add_custom_target", cmAddCustomTargetCommand);
+ state->AddBuiltinCommand("add_definitions", cmAddDefinitionsCommand);
+ state->AddBuiltinCommand("add_dependencies", cmAddDependenciesCommand);
+ state->AddBuiltinCommand("add_executable", cmAddExecutableCommand);
+ state->AddBuiltinCommand("add_library", cmAddLibraryCommand);
+ state->AddBuiltinCommand("add_subdirectory", cmAddSubDirectoryCommand);
+ state->AddBuiltinCommand("add_test", cmAddTestCommand);
+ state->AddBuiltinCommand("build_command", cmBuildCommand);
+ state->AddBuiltinCommand("create_test_sourcelist", cmCreateTestSourceList);
+ state->AddBuiltinCommand("define_property", cmDefinePropertyCommand);
+ state->AddBuiltinCommand("enable_language", cmEnableLanguageCommand);
+ state->AddBuiltinCommand("enable_testing", cmEnableTestingCommand);
state->AddBuiltinCommand("get_source_file_property",
- new cmGetSourceFilePropertyCommand);
- state->AddBuiltinCommand("get_target_property",
- new cmGetTargetPropertyCommand);
- state->AddBuiltinCommand("get_test_property", new cmGetTestPropertyCommand);
- state->AddBuiltinCommand("include_directories",
- new cmIncludeDirectoryCommand);
+ cmGetSourceFilePropertyCommand);
+ state->AddBuiltinCommand("get_target_property", cmGetTargetPropertyCommand);
+ state->AddBuiltinCommand("get_test_property", cmGetTestPropertyCommand);
+ state->AddBuiltinCommand("include_directories", cmIncludeDirectoryCommand);
state->AddBuiltinCommand("include_regular_expression",
- new cmIncludeRegularExpressionCommand);
- state->AddBuiltinCommand("install", new cmInstallCommand);
- state->AddBuiltinCommand("install_files", new cmInstallFilesCommand);
- state->AddBuiltinCommand("install_targets", new cmInstallTargetsCommand);
- state->AddBuiltinCommand("link_directories", new cmLinkDirectoriesCommand);
- state->AddBuiltinCommand("project", new cmProjectCommand);
+ cmIncludeRegularExpressionCommand);
+ state->AddBuiltinCommand("install", cmInstallCommand);
+ state->AddBuiltinCommand("install_files", cmInstallFilesCommand);
+ state->AddBuiltinCommand("install_targets", cmInstallTargetsCommand);
+ state->AddBuiltinCommand("link_directories", cmLinkDirectoriesCommand);
+ state->AddBuiltinCommand("project", cmProjectCommand);
state->AddBuiltinCommand("set_source_files_properties",
- new cmSetSourceFilesPropertiesCommand);
+ cmSetSourceFilesPropertiesCommand);
state->AddBuiltinCommand("set_target_properties",
- new cmSetTargetPropertiesCommand);
+ cmSetTargetPropertiesCommand);
state->AddBuiltinCommand("set_tests_properties",
- new cmSetTestsPropertiesCommand);
- state->AddBuiltinCommand("subdirs", new cmSubdirCommand);
- state->AddBuiltinCommand("target_link_libraries",
- new cmTargetLinkLibrariesCommand);
- state->AddBuiltinCommand("try_compile", new cmTryCompileCommand);
- state->AddBuiltinCommand("try_run", new cmTryRunCommand);
-
-#if defined(CMAKE_BUILD_WITH_CMAKE)
- state->AddBuiltinCommand("add_compile_options",
- new cmAddCompileOptionsCommand);
- state->AddBuiltinCommand("aux_source_directory",
- new cmAuxSourceDirectoryCommand);
- state->AddBuiltinCommand("export", new cmExportCommand);
- state->AddBuiltinCommand("fltk_wrap_ui", new cmFLTKWrapUICommand);
- state->AddBuiltinCommand("include_external_msproject",
- new cmIncludeExternalMSProjectCommand);
- state->AddBuiltinCommand("install_programs", new cmInstallProgramsCommand);
- state->AddBuiltinCommand("link_libraries", new cmLinkLibrariesCommand);
- state->AddBuiltinCommand("load_cache", new cmLoadCacheCommand);
- state->AddBuiltinCommand("qt_wrap_cpp", new cmQTWrapCPPCommand);
- state->AddBuiltinCommand("qt_wrap_ui", new cmQTWrapUICommand);
- state->AddBuiltinCommand("remove_definitions",
- new cmRemoveDefinitionsCommand);
- state->AddBuiltinCommand("source_group", new cmSourceGroupCommand);
+ cmSetTestsPropertiesCommand);
+ state->AddBuiltinCommand("subdirs", cmSubdirCommand);
state->AddBuiltinCommand("target_compile_definitions",
- new cmTargetCompileDefinitionsCommand);
+ cmTargetCompileDefinitionsCommand);
state->AddBuiltinCommand("target_compile_features",
- new cmTargetCompileFeaturesCommand);
+ cmTargetCompileFeaturesCommand);
state->AddBuiltinCommand("target_compile_options",
- new cmTargetCompileOptionsCommand);
+ cmTargetCompileOptionsCommand);
state->AddBuiltinCommand("target_include_directories",
- new cmTargetIncludeDirectoriesCommand);
- state->AddBuiltinCommand("target_sources", new cmTargetSourcesCommand);
+ cmTargetIncludeDirectoriesCommand);
+ state->AddBuiltinCommand("target_link_libraries",
+ cmTargetLinkLibrariesCommand);
+ state->AddBuiltinCommand("target_link_options", cmTargetLinkOptionsCommand);
+ state->AddBuiltinCommand("target_sources", cmTargetSourcesCommand);
+ state->AddBuiltinCommand("try_compile",
+ cm::make_unique<cmTryCompileCommand>());
+ state->AddBuiltinCommand("try_run", cm::make_unique<cmTryRunCommand>());
+ state->AddBuiltinCommand("target_precompile_headers",
+ cmTargetPrecompileHeadersCommand);
+
+#if !defined(CMAKE_BOOTSTRAP)
+ state->AddBuiltinCommand("add_compile_definitions",
+ cmAddCompileDefinitionsCommand);
+ state->AddBuiltinCommand("add_compile_options", cmAddCompileOptionsCommand);
+ state->AddBuiltinCommand("aux_source_directory",
+ cmAuxSourceDirectoryCommand);
+ state->AddBuiltinCommand("export", cmExportCommand);
+ state->AddBuiltinCommand("fltk_wrap_ui", cmFLTKWrapUICommand);
+ state->AddBuiltinCommand("include_external_msproject",
+ cmIncludeExternalMSProjectCommand);
+ state->AddBuiltinCommand("install_programs", cmInstallProgramsCommand);
+ state->AddBuiltinCommand("add_link_options", cmAddLinkOptionsCommand);
+ state->AddBuiltinCommand("link_libraries", cmLinkLibrariesCommand);
+ state->AddBuiltinCommand("target_link_directories",
+ cmTargetLinkDirectoriesCommand);
+ state->AddBuiltinCommand("load_cache", cmLoadCacheCommand);
+ state->AddBuiltinCommand("qt_wrap_cpp", cmQTWrapCPPCommand);
+ state->AddBuiltinCommand("qt_wrap_ui", cmQTWrapUICommand);
+ state->AddBuiltinCommand("remove_definitions", cmRemoveDefinitionsCommand);
+ state->AddBuiltinCommand("source_group", cmSourceGroupCommand);
state->AddDisallowedCommand(
- "export_library_dependencies", new cmExportLibraryDependenciesCommand,
+ "export_library_dependencies", cmExportLibraryDependenciesCommand,
cmPolicies::CMP0033,
"The export_library_dependencies command should not be called; "
"see CMP0033.");
state->AddDisallowedCommand(
- "load_command", new cmLoadCommandCommand, cmPolicies::CMP0031,
+ "load_command", cmLoadCommandCommand, cmPolicies::CMP0031,
"The load_command command should not be called; see CMP0031.");
state->AddDisallowedCommand(
- "output_required_files", new cmOutputRequiredFilesCommand,
- cmPolicies::CMP0032,
+ "output_required_files", cmOutputRequiredFilesCommand, cmPolicies::CMP0032,
"The output_required_files command should not be called; see CMP0032.");
state->AddDisallowedCommand(
- "subdir_depends", new cmSubdirDependsCommand, cmPolicies::CMP0029,
+ "subdir_depends", cmSubdirDependsCommand, cmPolicies::CMP0029,
"The subdir_depends command should not be called; see CMP0029.");
state->AddDisallowedCommand(
- "utility_source", new cmUtilitySourceCommand, cmPolicies::CMP0034,
+ "utility_source", cmUtilitySourceCommand, cmPolicies::CMP0034,
"The utility_source command should not be called; see CMP0034.");
state->AddDisallowedCommand(
- "variable_requires", new cmVariableRequiresCommand, cmPolicies::CMP0035,
+ "variable_requires", cmVariableRequiresCommand, cmPolicies::CMP0035,
"The variable_requires command should not be called; see CMP0035.");
#endif
}
@@ -341,7 +357,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 391d65c40..19a096bdf 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -2,12 +2,10 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCommonTargetGenerator.h"
-#include "cmConfigure.h"
#include <set>
#include <sstream>
#include <utility>
-#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
@@ -18,20 +16,20 @@
#include "cmOutputConverter.h"
#include "cmSourceFile.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt)
: GeneratorTarget(gt)
, Makefile(gt->Makefile)
- , LocalGenerator(static_cast<cmLocalCommonGenerator*>(gt->LocalGenerator))
- , GlobalGenerator(static_cast<cmGlobalCommonGenerator*>(
+ , LocalCommonGenerator(
+ static_cast<cmLocalCommonGenerator*>(gt->LocalGenerator))
+ , GlobalCommonGenerator(static_cast<cmGlobalCommonGenerator*>(
gt->LocalGenerator->GetGlobalGenerator()))
- , ConfigName(LocalGenerator->GetConfigName())
+ , ConfigName(LocalCommonGenerator->GetConfigName())
{
}
-cmCommonTargetGenerator::~cmCommonTargetGenerator()
-{
-}
+cmCommonTargetGenerator::~cmCommonTargetGenerator() = default;
std::string const& cmCommonTargetGenerator::GetConfigName() const
{
@@ -61,11 +59,12 @@ void cmCommonTargetGenerator::AddModuleDefinitionFlag(
// Append the flag and value. Use ConvertToLinkReference to help
// vs6's "cl -link" pass it to the linker.
- std::string flag = defFileFlag;
- flag += this->LocalGenerator->ConvertToOutputFormat(
- linkLineComputer->ConvertToLinkReference(mdi->DefFile),
- cmOutputConverter::SHELL);
- this->LocalGenerator->AppendFlags(flags, flag);
+ std::string flag =
+ cmStrCat(defFileFlag,
+ this->LocalCommonGenerator->ConvertToOutputFormat(
+ linkLineComputer->ConvertToLinkReference(mdi->DefFile),
+ cmOutputConverter::SHELL));
+ this->LocalCommonGenerator->AppendFlags(flags, flag);
}
void cmCommonTargetGenerator::AppendFortranFormatFlags(
@@ -78,7 +77,7 @@ void cmCommonTargetGenerator::AppendFortranFormatFlags(
const char* tgtfmt = this->GeneratorTarget->GetProperty("Fortran_FORMAT");
format = cmOutputConverter::GetFortranFormat(tgtfmt);
}
- const char* var = CM_NULLPTR;
+ const char* var = nullptr;
switch (format) {
case cmOutputConverter::FortranFormatFixed:
var = "CMAKE_Fortran_FORMAT_FIXED_FLAG";
@@ -90,19 +89,19 @@ void cmCommonTargetGenerator::AppendFortranFormatFlags(
break;
}
if (var) {
- this->LocalGenerator->AppendFlags(flags,
- this->Makefile->GetDefinition(var));
+ this->LocalCommonGenerator->AppendFlags(
+ flags, this->Makefile->GetSafeDefinition(var));
}
}
std::string cmCommonTargetGenerator::GetFlags(const std::string& l)
{
- ByLanguageMap::iterator i = this->FlagsByLanguage.find(l);
+ auto i = this->FlagsByLanguage.find(l);
if (i == this->FlagsByLanguage.end()) {
std::string flags;
- this->LocalGenerator->GetTargetCompileFlags(this->GeneratorTarget,
- this->ConfigName, l, flags);
+ this->LocalCommonGenerator->GetTargetCompileFlags(
+ this->GeneratorTarget, this->ConfigName, l, flags);
ByLanguageMap::value_type entry(l, flags);
i = this->FlagsByLanguage.insert(entry).first;
@@ -112,14 +111,14 @@ std::string cmCommonTargetGenerator::GetFlags(const std::string& l)
std::string cmCommonTargetGenerator::GetDefines(const std::string& l)
{
- ByLanguageMap::iterator i = this->DefinesByLanguage.find(l);
+ auto i = this->DefinesByLanguage.find(l);
if (i == this->DefinesByLanguage.end()) {
std::set<std::string> defines;
- this->LocalGenerator->GetTargetDefines(this->GeneratorTarget,
- this->ConfigName, l, defines);
+ this->LocalCommonGenerator->GetTargetDefines(this->GeneratorTarget,
+ this->ConfigName, l, defines);
std::string definesString;
- this->LocalGenerator->JoinDefines(defines, definesString, l);
+ this->LocalCommonGenerator->JoinDefines(defines, definesString, l);
ByLanguageMap::value_type entry(l, definesString);
i = this->DefinesByLanguage.insert(entry).first;
@@ -129,7 +128,7 @@ std::string cmCommonTargetGenerator::GetDefines(const std::string& l)
std::string cmCommonTargetGenerator::GetIncludes(std::string const& l)
{
- ByLanguageMap::iterator i = this->IncludesByLanguage.find(l);
+ auto i = this->IncludesByLanguage.find(l);
if (i == this->IncludesByLanguage.end()) {
std::string includes;
this->AddIncludeFlags(includes, l);
@@ -147,21 +146,19 @@ std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories()
if (cmComputeLinkInformation* cli =
this->GeneratorTarget->GetLinkInformation(this->ConfigName)) {
cmComputeLinkInformation::ItemVector const& items = cli->GetItems();
- for (cmComputeLinkInformation::ItemVector::const_iterator i =
- items.begin();
- i != items.end(); ++i) {
- cmGeneratorTarget const* linkee = i->Target;
- if (linkee && !linkee->IsImported()
+ for (auto const& item : items) {
+ cmGeneratorTarget const* linkee = item.Target;
+ if (linkee &&
+ !linkee->IsImported()
// We can ignore the INTERFACE_LIBRARY items because
// Target->GetLinkInformation already processed their
// link interface and they don't have any output themselves.
&& linkee->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
emitted.insert(linkee).second) {
cmLocalGenerator* lg = linkee->GetLocalGenerator();
- std::string di = lg->GetCurrentBinaryDirectory();
- di += "/";
- di += lg->GetTargetDirectory(linkee);
- dirs.push_back(di);
+ std::string di = cmStrCat(lg->GetCurrentBinaryDirectory(), '/',
+ lg->GetTargetDirectory(linkee));
+ dirs.push_back(std::move(di));
}
}
}
@@ -174,6 +171,7 @@ std::string cmCommonTargetGenerator::ComputeTargetCompilePDB() const
if (this->GeneratorTarget->GetType() > cmStateEnums::OBJECT_LIBRARY) {
return compilePdbPath;
}
+
compilePdbPath =
this->GeneratorTarget->GetCompilePDBPath(this->GetConfigName());
if (compilePdbPath.empty()) {
@@ -196,11 +194,12 @@ std::string cmCommonTargetGenerator::GetManifests()
this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName);
std::vector<std::string> manifests;
- for (std::vector<cmSourceFile const*>::iterator mi = manifest_srcs.begin();
- mi != manifest_srcs.end(); ++mi) {
- manifests.push_back(this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->ConvertToRelativePath(
- this->LocalGenerator->GetWorkingDirectory(), (*mi)->GetFullPath()),
+ manifests.reserve(manifest_srcs.size());
+ for (cmSourceFile const* manifest_src : manifest_srcs) {
+ manifests.push_back(this->LocalCommonGenerator->ConvertToOutputFormat(
+ this->LocalCommonGenerator->MaybeConvertToRelativePath(
+ this->LocalCommonGenerator->GetWorkingDirectory(),
+ manifest_src->GetFullPath()),
cmOutputConverter::SHELL));
}
@@ -212,11 +211,7 @@ void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags,
const char* name, bool so)
{
// Lookup the flag to specify the version.
- std::string fvar = "CMAKE_";
- fvar += lang;
- fvar += "_OSX_";
- fvar += name;
- fvar += "_VERSION_FLAG";
+ std::string fvar = cmStrCat("CMAKE_", lang, "_OSX_", name, "_VERSION_FLAG");
const char* flag = this->Makefile->GetDefinition(fvar);
// Skip if no such flag.
@@ -233,6 +228,6 @@ void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags,
// Append the flag since a non-zero version is specified.
std::ostringstream vflag;
vflag << flag << major << "." << minor << "." << patch;
- this->LocalGenerator->AppendFlags(flags, vflag.str());
+ this->LocalCommonGenerator->AppendFlags(flags, vflag.str());
}
}
diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h
index c36145fe2..17792d6ac 100644
--- a/Source/cmCommonTargetGenerator.h
+++ b/Source/cmCommonTargetGenerator.h
@@ -37,8 +37,8 @@ protected:
cmGeneratorTarget* GeneratorTarget;
cmMakefile* Makefile;
- cmLocalCommonGenerator* LocalGenerator;
- cmGlobalCommonGenerator* GlobalGenerator;
+ cmLocalCommonGenerator* LocalCommonGenerator;
+ cmGlobalCommonGenerator* GlobalCommonGenerator;
std::string ConfigName;
void AppendFortranFormatFlags(std::string& flags,
@@ -50,7 +50,7 @@ protected:
void AppendOSXVerFlag(std::string& flags, const std::string& lang,
const char* name, bool so);
- typedef std::map<std::string, std::string> ByLanguageMap;
+ using ByLanguageMap = std::map<std::string, std::string>;
std::string GetFlags(const std::string& l);
ByLanguageMap FlagsByLanguage;
std::string GetDefines(const std::string& l);
diff --git a/Source/cmComputeComponentGraph.cxx b/Source/cmComputeComponentGraph.cxx
index a02d8854b..af257ee03 100644
--- a/Source/cmComputeComponentGraph.cxx
+++ b/Source/cmComputeComponentGraph.cxx
@@ -3,8 +3,7 @@
#include "cmComputeComponentGraph.h"
#include <algorithm>
-
-#include <assert.h>
+#include <cassert>
cmComputeComponentGraph::cmComputeComponentGraph(Graph const& input)
: InputGraph(input)
@@ -18,9 +17,7 @@ cmComputeComponentGraph::cmComputeComponentGraph(Graph const& input)
this->TransferEdges();
}
-cmComputeComponentGraph::~cmComputeComponentGraph()
-{
-}
+cmComputeComponentGraph::~cmComputeComponentGraph() = default;
void cmComputeComponentGraph::Tarjan()
{
@@ -57,8 +54,8 @@ void cmComputeComponentGraph::TarjanVisit(int i)
// Follow outgoing edges.
EdgeList const& nl = this->InputGraph[i];
- for (EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
- int j = *ni;
+ for (cmGraphEdge const& ni : nl) {
+ int j = ni;
// Ignore edges to nodes that have been reached by a previous DFS
// walk. Since we did not reach the current node from that walk
@@ -88,7 +85,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.
@@ -119,14 +116,14 @@ void cmComputeComponentGraph::TransferEdges()
for (int i = 0; i < n; ++i) {
int i_component = this->TarjanComponents[i];
EdgeList const& nl = this->InputGraph[i];
- for (EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
- int j = *ni;
+ for (cmGraphEdge const& ni : nl) {
+ int j = ni;
int j_component = this->TarjanComponents[j];
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(), ni.GetBacktrace());
}
}
}
diff --git a/Source/cmComputeComponentGraph.h b/Source/cmComputeComponentGraph.h
index 8cd4fe73a..202888cf9 100644
--- a/Source/cmComputeComponentGraph.h
+++ b/Source/cmComputeComponentGraph.h
@@ -5,11 +5,11 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmGraphAdjacencyList.h"
-
#include <stack>
#include <vector>
+#include "cmGraphAdjacencyList.h"
+
/** \class cmComputeComponentGraph
* \brief Analyze a graph to determine strongly connected components.
*
@@ -24,9 +24,9 @@ class cmComputeComponentGraph
{
public:
// Represent the graph with an adjacency list.
- typedef cmGraphNodeList NodeList;
- typedef cmGraphEdgeList EdgeList;
- typedef cmGraphAdjacencyList Graph;
+ using NodeList = cmGraphNodeList;
+ using EdgeList = cmGraphEdgeList;
+ using Graph = cmGraphAdjacencyList;
cmComputeComponentGraph(Graph const& input);
~cmComputeComponentGraph();
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index 9c516ee8d..7a9e2b7f6 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -2,25 +2,28 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmComputeLinkDepends.h"
-#include "cmAlgorithms.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+#include <iterator>
+#include <sstream>
+#include <utility>
+
+#include <cm/memory>
+
#include "cmComputeComponentGraph.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmRange.h"
#include "cmStateTypes.h"
-#include "cmSystemTools.h"
+#include "cmStringAlgorithms.h"
#include "cmTarget.h"
#include "cmake.h"
-#include <algorithm>
-#include <assert.h>
-#include <iterator>
-#include <sstream>
-#include <stdio.h>
-#include <string.h>
-#include <utility>
-
/*
This file computes an ordered list of link items to use when linking a
@@ -194,14 +197,10 @@ cmComputeLinkDepends::cmComputeLinkDepends(const cmGeneratorTarget* target,
this->OldLinkDirMode = false;
// No computation has been done.
- this->CCG = CM_NULLPTR;
+ this->CCG = nullptr;
}
-cmComputeLinkDepends::~cmComputeLinkDepends()
-{
- cmDeleteAll(this->InferredDependSets);
- delete this->CCG;
-}
+cmComputeLinkDepends::~cmComputeLinkDepends() = default;
void cmComputeLinkDepends::SetOldLinkDirMode(bool b)
{
@@ -239,8 +238,9 @@ cmComputeLinkDepends::Compute()
// Display the constraint graph.
if (this->DebugMode) {
- fprintf(stderr, "---------------------------------------"
- "---------------------------------------\n");
+ fprintf(stderr,
+ "---------------------------------------"
+ "---------------------------------------\n");
fprintf(stderr, "Link dependency analysis for target %s, config %s\n",
this->Target->GetName().c_str(),
this->HasConfig ? this->Config.c_str() : "noconfig");
@@ -254,11 +254,7 @@ cmComputeLinkDepends::Compute()
// Iterate in reverse order so we can keep only the last occurrence
// of a shared library.
std::set<int> emmitted;
- for (std::vector<int>::const_reverse_iterator
- li = this->FinalLinkOrder.rbegin(),
- le = this->FinalLinkOrder.rend();
- li != le; ++li) {
- int i = *li;
+ for (int i : cmReverseRange(this->FinalLinkOrder)) {
LinkEntry const& e = this->EntryList[i];
cmGeneratorTarget const* t = e.Target;
// Entries that we know the linker will re-use do not need to be repeated.
@@ -278,23 +274,22 @@ cmComputeLinkDepends::Compute()
return this->FinalLinkEntries;
}
-std::map<std::string, int>::iterator cmComputeLinkDepends::AllocateLinkEntry(
- std::string const& item)
+std::map<cmLinkItem, int>::iterator cmComputeLinkDepends::AllocateLinkEntry(
+ cmLinkItem const& item)
{
- std::map<std::string, int>::value_type index_entry(
+ std::map<cmLinkItem, int>::value_type index_entry(
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->InferredDependSets.push_back(CM_NULLPTR);
- this->EntryConstraintGraph.push_back(EdgeList());
+ auto lei = this->LinkEntryIndex.insert(index_entry).first;
+ this->EntryList.emplace_back();
+ this->InferredDependSets.emplace_back();
+ this->EntryConstraintGraph.emplace_back();
return lei;
}
int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item)
{
// Check if the item entry has already been added.
- std::map<std::string, int>::iterator lei = this->LinkEntryIndex.find(item);
+ auto lei = this->LinkEntryIndex.find(item);
if (lei != this->LinkEntryIndex.end()) {
// Yes. We do not need to follow the item's dependencies again.
return lei->second;
@@ -306,27 +301,27 @@ int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item)
// Initialize the item entry.
int index = lei->second;
LinkEntry& entry = this->EntryList[index];
- entry.Item = item;
+ entry.Item = item.AsStr();
entry.Target = item.Target;
- entry.IsFlag = (!entry.Target && item[0] == '-' && item[1] != 'l' &&
- item.substr(0, 10) != "-framework");
+ entry.IsFlag =
+ (!entry.Target && entry.Item[0] == '-' && entry.Item[1] != 'l' &&
+ entry.Item.substr(0, 10) != "-framework");
// If the item has dependencies queue it to follow them.
if (entry.Target) {
// Target dependencies are always known. Follow them.
- BFSEntry qe = { index, CM_NULLPTR };
+ BFSEntry qe = { index, nullptr };
this->BFSQueue.push(qe);
} else {
// Look for an old-style <item>_LIB_DEPENDS variable.
- std::string var = entry.Item;
- var += "_LIB_DEPENDS";
+ std::string var = cmStrCat(entry.Item, "_LIB_DEPENDS");
if (const char* val = this->Makefile->GetDefinition(var)) {
// The item dependencies are known. Follow them.
BFSEntry qe = { index, val };
this->BFSQueue.push(qe);
} else if (!entry.IsFlag) {
// The item dependencies are not known. We need to infer them.
- this->InferredDependSets[index] = new DependSetList;
+ this->InferredDependSets[index].Initialized = true;
}
}
@@ -357,10 +352,8 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry qe)
this->FollowSharedDeps(depender_index, iface);
// Support for CMP0003.
- for (std::vector<cmLinkItem>::const_iterator oi =
- iface->WrongConfigLibraries.begin();
- oi != iface->WrongConfigLibraries.end(); ++oi) {
- this->CheckWrongConfigItem(*oi);
+ for (cmLinkItem const& oi : iface->WrongConfigLibraries) {
+ this->CheckWrongConfigItem(oi);
}
}
} else {
@@ -385,10 +378,9 @@ void cmComputeLinkDepends::FollowSharedDeps(int depender_index,
void cmComputeLinkDepends::QueueSharedDependencies(
int depender_index, std::vector<cmLinkItem> const& deps)
{
- for (std::vector<cmLinkItem>::const_iterator li = deps.begin();
- li != deps.end(); ++li) {
+ for (cmLinkItem const& li : deps) {
SharedDepEntry qe;
- qe.Item = *li;
+ qe.Item = li;
qe.DependerIndex = depender_index;
this->SharedDepQueue.push(qe);
}
@@ -397,15 +389,14 @@ void cmComputeLinkDepends::QueueSharedDependencies(
void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
{
// Check if the target already has an entry.
- std::map<std::string, int>::iterator lei =
- this->LinkEntryIndex.find(dep.Item);
+ auto lei = this->LinkEntryIndex.find(dep.Item);
if (lei == this->LinkEntryIndex.end()) {
// Allocate a spot for the item entry.
lei = this->AllocateLinkEntry(dep.Item);
// Initialize the item entry.
LinkEntry& entry = this->EntryList[lei->second];
- entry.Item = dep.Item;
+ entry.Item = dep.Item.AsStr();
entry.Target = dep.Item.Target;
// This item was added specifically because it is a dependent
@@ -420,7 +411,8 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
// This shared library dependency must follow the item that listed
// it.
- this->EntryConstraintGraph[dep.DependerIndex].push_back(index);
+ this->EntryConstraintGraph[dep.DependerIndex].emplace_back(
+ index, true, cmListFileBacktrace());
// Target items may have their own dependencies.
if (entry.Target) {
@@ -438,33 +430,30 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
// This is called to add the dependencies named by
// <item>_LIB_DEPENDS. The variable contains a semicolon-separated
// list. The list contains link-type;item pairs and just items.
- std::vector<std::string> deplist;
- cmSystemTools::ExpandListArgument(value, deplist);
+ std::vector<std::string> deplist = cmExpandedList(value);
// Look for entries meant for this configuration.
std::vector<cmLinkItem> actual_libs;
cmTargetLinkLibraryType llt = GENERAL_LibraryType;
bool haveLLT = false;
- for (std::vector<std::string>::const_iterator di = deplist.begin();
- di != deplist.end(); ++di) {
- if (*di == "debug") {
+ for (std::string const& d : deplist) {
+ if (d == "debug") {
llt = DEBUG_LibraryType;
haveLLT = true;
- } else if (*di == "optimized") {
+ } else if (d == "optimized") {
llt = OPTIMIZED_LibraryType;
haveLLT = true;
- } else if (*di == "general") {
+ } else if (d == "general") {
llt = GENERAL_LibraryType;
haveLLT = true;
- } else if (!di->empty()) {
+ } else if (!d.empty()) {
// If no explicit link type was given prior to this entry then
// check if the entry has its own link type variable. This is
// needed for compatibility with dependency files generated by
// the export_library_dependencies command from CMake 2.4 and
// lower.
if (!haveLLT) {
- std::string var = *di;
- var += "_LINK_TYPE";
+ std::string var = cmStrCat(d, "_LINK_TYPE");
if (const char* val = this->Makefile->GetDefinition(var)) {
if (strcmp(val, "debug") == 0) {
llt = DEBUG_LibraryType;
@@ -476,10 +465,9 @@ 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(*di, this->FindTargetToLink(depender_index, *di));
- actual_libs.push_back(item);
+ actual_libs.emplace_back(this->ResolveLinkItem(depender_index, d));
} else if (this->OldLinkDirMode) {
- cmLinkItem item(*di, this->FindTargetToLink(depender_index, *di));
+ cmLinkItem item = this->ResolveLinkItem(depender_index, d);
this->CheckWrongConfigItem(item);
}
@@ -499,10 +487,8 @@ void cmComputeLinkDepends::AddDirectLinkEntries()
cmLinkImplementation const* impl =
this->Target->GetLinkImplementation(this->Config);
this->AddLinkEntries(-1, impl->Libraries);
- for (std::vector<cmLinkItem>::const_iterator wi =
- impl->WrongConfigLibraries.begin();
- wi != impl->WrongConfigLibraries.end(); ++wi) {
- this->CheckWrongConfigItem(*wi);
+ for (cmLinkItem const& wi : impl->WrongConfigLibraries) {
+ this->CheckWrongConfigItem(wi);
}
}
@@ -514,56 +500,54 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index,
std::map<int, DependSet> dependSets;
// Loop over the libraries linked directly by the depender.
- for (typename std::vector<T>::const_iterator li = libs.begin();
- li != libs.end(); ++li) {
+ for (T const& l : libs) {
// Skip entries that will resolve to the target getting linked or
// are empty.
- cmLinkItem const& item = *li;
- if (item == this->Target->GetName() || item.empty()) {
+ cmLinkItem const& item = l;
+ if (item.AsStr() == this->Target->GetName() || item.AsStr().empty()) {
continue;
}
// Add a link entry for this item.
- int dependee_index = this->AddLinkEntry(*li);
+ int dependee_index = this->AddLinkEntry(l);
// The dependee must come after the depender.
if (depender_index >= 0) {
- this->EntryConstraintGraph[depender_index].push_back(dependee_index);
+ this->EntryConstraintGraph[depender_index].emplace_back(
+ dependee_index, false, cmListFileBacktrace());
} else {
// This is a direct dependency of the target being linked.
this->OriginalEntries.push_back(dependee_index);
}
// Update the inferred dependencies for earlier items.
- for (std::map<int, DependSet>::iterator dsi = dependSets.begin();
- dsi != dependSets.end(); ++dsi) {
+ for (auto& dependSet : dependSets) {
// Add this item to the inferred dependencies of other items.
// Target items are never inferred dependees because unknown
// items are outside libraries that should not be depending on
// targets.
if (!this->EntryList[dependee_index].Target &&
!this->EntryList[dependee_index].IsFlag &&
- dependee_index != dsi->first) {
- dsi->second.insert(dependee_index);
+ dependee_index != dependSet.first) {
+ dependSet.second.insert(dependee_index);
}
}
// If this item needs to have dependencies inferred, do so.
- if (this->InferredDependSets[dependee_index]) {
+ if (this->InferredDependSets[dependee_index].Initialized) {
// Make sure an entry exists to hold the set for the item.
dependSets[dependee_index];
}
}
// Store the inferred dependency sets discovered for this list.
- for (std::map<int, DependSet>::iterator dsi = dependSets.begin();
- dsi != dependSets.end(); ++dsi) {
- this->InferredDependSets[dsi->first]->push_back(dsi->second);
+ for (auto const& dependSet : dependSets) {
+ this->InferredDependSets[dependSet.first].push_back(dependSet.second);
}
}
-cmGeneratorTarget const* cmComputeLinkDepends::FindTargetToLink(
- int depender_index, const std::string& name)
+cmLinkItem cmComputeLinkDepends::ResolveLinkItem(int depender_index,
+ const std::string& name)
{
// Look for a target in the scope of the depender.
cmGeneratorTarget const* from = this->Target;
@@ -573,7 +557,7 @@ cmGeneratorTarget const* cmComputeLinkDepends::FindTargetToLink(
from = depender;
}
}
- return from->FindTargetToLink(name);
+ return from->ResolveLinkItem(name, cmListFileBacktrace());
}
void cmComputeLinkDepends::InferDependencies()
@@ -585,37 +569,39 @@ void cmComputeLinkDepends::InferDependencies()
depender_index < this->InferredDependSets.size(); ++depender_index) {
// Skip items for which dependencies do not need to be inferred or
// for which the inferred dependency sets are empty.
- DependSetList* sets = this->InferredDependSets[depender_index];
- if (!sets || sets->empty()) {
+ DependSetList& sets = this->InferredDependSets[depender_index];
+ if (!sets.Initialized || sets.empty()) {
continue;
}
// Intersect the sets for this item.
- DependSetList::const_iterator i = sets->begin();
- DependSet common = *i;
- for (++i; i != sets->end(); ++i) {
+ DependSet common = sets.front();
+ for (DependSet const& i : cmMakeRange(sets).advance(1)) {
DependSet intersection;
- std::set_intersection(common.begin(), common.end(), i->begin(), i->end(),
+ std::set_intersection(common.begin(), common.end(), i.begin(), i.end(),
std::inserter(intersection, intersection.begin()));
common = intersection;
}
// Add the inferred dependencies to the graph.
cmGraphEdgeList& edges = this->EntryConstraintGraph[depender_index];
- edges.insert(edges.end(), common.begin(), common.end());
+ edges.reserve(edges.size() + common.size());
+ for (auto const& c : common) {
+ edges.emplace_back(c, true, cmListFileBacktrace());
+ }
}
}
void cmComputeLinkDepends::CleanConstraintGraph()
{
- for (Graph::iterator i = this->EntryConstraintGraph.begin();
- i != this->EntryConstraintGraph.end(); ++i) {
+ for (cmGraphEdgeList& edgeList : this->EntryConstraintGraph) {
// Sort the outgoing edges for each graph node so that the
// original order will be preserved as much as possible.
- std::sort(i->begin(), i->end());
+ std::sort(edgeList.begin(), edgeList.end());
// Make the edge list unique.
- i->erase(std::unique(i->begin(), i->end()), i->end());
+ edgeList.erase(std::unique(edgeList.begin(), edgeList.end()),
+ edgeList.end());
}
}
@@ -638,7 +624,8 @@ void cmComputeLinkDepends::OrderLinkEntires()
// the same order in which the items were originally discovered in
// the BFS. This should preserve the original order when no
// constraints disallow it.
- this->CCG = new cmComputeComponentGraph(this->EntryConstraintGraph);
+ this->CCG =
+ cm::make_unique<cmComputeComponentGraph>(this->EntryConstraintGraph);
// The component graph is guaranteed to be acyclic. Start a DFS
// from every entry to compute a topological order for the
@@ -660,9 +647,8 @@ void cmComputeLinkDepends::OrderLinkEntires()
}
// Start with the original link line.
- for (std::vector<int>::const_iterator i = this->OriginalEntries.begin();
- i != this->OriginalEntries.end(); ++i) {
- this->VisitEntry(*i);
+ for (int originalEntry : this->OriginalEntries) {
+ this->VisitEntry(originalEntry);
}
// Now explore anything left pending. Since the component graph is
@@ -684,13 +670,12 @@ void cmComputeLinkDepends::DisplayComponents()
for (unsigned int c = 0; c < components.size(); ++c) {
fprintf(stderr, "Component (%u):\n", c);
NodeList const& nl = components[c];
- for (NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
- int i = *ni;
+ for (int i : nl) {
fprintf(stderr, " item %d [%s]\n", i, this->EntryList[i].Item.c_str());
}
EdgeList const& ol = this->CCG->GetComponentGraphEdges(c);
- for (EdgeList::const_iterator oi = ol.begin(); oi != ol.end(); ++oi) {
- int i = *oi;
+ for (cmGraphEdge const& oi : ol) {
+ int i = oi;
fprintf(stderr, " followed by Component (%d)\n", i);
}
fprintf(stderr, " topo order index %d\n", this->ComponentOrder[c]);
@@ -712,9 +697,8 @@ void cmComputeLinkDepends::VisitComponent(unsigned int c)
// Run in reverse order so the topological order will preserve the
// original order where there are no constraints.
EdgeList const& nl = this->CCG->GetComponentGraphEdges(c);
- for (EdgeList::const_reverse_iterator ni = nl.rbegin(); ni != nl.rend();
- ++ni) {
- this->VisitComponent(*ni);
+ for (cmGraphEdge const& edge : cmReverseRange(nl)) {
+ this->VisitComponent(edge);
}
// Assign an ordering id to this component.
@@ -729,8 +713,7 @@ void cmComputeLinkDepends::VisitEntry(int index)
// This entry has now been seen. Update its component.
bool completed = false;
int component = this->CCG->GetComponentMap()[index];
- std::map<int, PendingComponent>::iterator mi =
- this->PendingComponents.find(this->ComponentOrder[component]);
+ auto mi = this->PendingComponents.find(this->ComponentOrder[component]);
if (mi != this->PendingComponents.end()) {
// The entry is in an already pending component.
PendingComponent& pc = mi->second;
@@ -771,10 +754,10 @@ void cmComputeLinkDepends::VisitEntry(int index)
// are now pending.
if (completed) {
EdgeList const& ol = this->CCG->GetComponentGraphEdges(component);
- for (EdgeList::const_iterator oi = ol.begin(); oi != ol.end(); ++oi) {
+ for (cmGraphEdge const& oi : ol) {
// This entire component is now pending no matter whether it has
// been partially seen already.
- this->MakePendingComponent(*oi);
+ this->MakePendingComponent(oi);
}
}
}
@@ -816,8 +799,8 @@ cmComputeLinkDepends::MakePendingComponent(unsigned int component)
int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl)
{
unsigned int count = 2;
- for (NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
- if (cmGeneratorTarget const* target = this->EntryList[*ni].Target) {
+ for (int ni : nl) {
+ if (cmGeneratorTarget const* target = this->EntryList[ni].Target) {
if (cmLinkInterface const* iface =
target->GetLinkInterface(this->Config, this->Target)) {
if (iface->Multiplicity > count) {
@@ -832,13 +815,11 @@ int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl)
void cmComputeLinkDepends::DisplayFinalEntries()
{
fprintf(stderr, "target [%s] links to:\n", this->Target->GetName().c_str());
- for (std::vector<LinkEntry>::const_iterator lei =
- this->FinalLinkEntries.begin();
- lei != this->FinalLinkEntries.end(); ++lei) {
- if (lei->Target) {
- fprintf(stderr, " target [%s]\n", lei->Target->GetName().c_str());
+ for (LinkEntry const& lei : this->FinalLinkEntries) {
+ if (lei.Target) {
+ fprintf(stderr, " target [%s]\n", lei.Target->GetName().c_str());
} else {
- fprintf(stderr, " item [%s]\n", lei->Item.c_str());
+ fprintf(stderr, " item [%s]\n", lei.Item.c_str());
}
}
fprintf(stderr, "\n");
diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h
index 84ee9161f..645189ad5 100644
--- a/Source/cmComputeLinkDepends.h
+++ b/Source/cmComputeLinkDepends.h
@@ -5,16 +5,18 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmGraphAdjacencyList.h"
-#include "cmLinkItem.h"
-#include "cmTargetLinkLibraryType.h"
-
#include <map>
-#include <queue>
+#include <memory>
#include <set>
#include <string>
#include <vector>
+#include <queue>
+
+#include "cmGraphAdjacencyList.h"
+#include "cmLinkItem.h"
+#include "cmTargetLinkLibraryType.h"
+
class cmComputeComponentGraph;
class cmGeneratorTarget;
class cmGlobalGenerator;
@@ -31,30 +33,19 @@ public:
const std::string& config);
~cmComputeLinkDepends();
+ cmComputeLinkDepends(const cmComputeLinkDepends&) = delete;
+ cmComputeLinkDepends& operator=(const cmComputeLinkDepends&) = delete;
+
// Basic information about each link item.
struct LinkEntry
{
std::string Item;
- cmGeneratorTarget const* Target;
- bool IsSharedDep;
- bool IsFlag;
- LinkEntry()
- : Item()
- , Target(CM_NULLPTR)
- , IsSharedDep(false)
- , IsFlag(false)
- {
- }
- LinkEntry(LinkEntry const& r)
- : Item(r.Item)
- , Target(r.Target)
- , IsSharedDep(r.IsSharedDep)
- , IsFlag(r.IsFlag)
- {
- }
+ cmGeneratorTarget const* Target = nullptr;
+ bool IsSharedDep = false;
+ bool IsFlag = false;
};
- typedef std::vector<LinkEntry> EntryVector;
+ using EntryVector = std::vector<LinkEntry>;
EntryVector const& Compute();
void SetOldLinkDirMode(bool b);
@@ -72,19 +63,18 @@ private:
std::string Config;
EntryVector FinalLinkEntries;
- std::map<std::string, int>::iterator AllocateLinkEntry(
- std::string const& item);
+ std::map<cmLinkItem, int>::iterator AllocateLinkEntry(
+ cmLinkItem const& item);
int AddLinkEntry(cmLinkItem const& item);
void AddVarLinkEntries(int depender_index, const char* value);
void AddDirectLinkEntries();
template <typename T>
void AddLinkEntries(int depender_index, std::vector<T> const& libs);
- cmGeneratorTarget const* FindTargetToLink(int depender_index,
- const std::string& name);
+ cmLinkItem ResolveLinkItem(int depender_index, const std::string& name);
// One entry for each unique item.
std::vector<LinkEntry> EntryList;
- std::map<std::string, int> LinkEntryIndex;
+ std::map<cmLinkItem, int> LinkEntryIndex;
// BFS of initial dependencies.
struct BFSEntry
@@ -117,14 +107,15 @@ private:
};
struct DependSetList : public std::vector<DependSet>
{
+ bool Initialized = false;
};
- std::vector<DependSetList*> InferredDependSets;
+ std::vector<DependSetList> InferredDependSets;
void InferDependencies();
// Ordering constraint graph adjacency list.
- typedef cmGraphNodeList NodeList;
- typedef cmGraphEdgeList EdgeList;
- typedef cmGraphAdjacencyList Graph;
+ using NodeList = cmGraphNodeList;
+ using EdgeList = cmGraphEdgeList;
+ using Graph = cmGraphAdjacencyList;
Graph EntryConstraintGraph;
void CleanConstraintGraph();
void DisplayConstraintGraph();
@@ -149,7 +140,7 @@ private:
std::set<int> Entries;
};
std::map<int, PendingComponent> PendingComponents;
- cmComputeComponentGraph* CCG;
+ std::unique_ptr<cmComputeComponentGraph> CCG;
std::vector<int> FinalLinkOrder;
void DisplayComponents();
void VisitComponent(unsigned int c);
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index b2deaaa85..8773d1036 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -2,27 +2,30 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmComputeLinkInformation.h"
+#include <algorithm>
+#include <cctype>
+#include <cstring>
+#include <sstream>
+#include <utility>
+
#include "cmAlgorithms.h"
#include "cmComputeLinkDepends.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmOrderDirectories.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmState.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmake.h"
-#include <algorithm>
-#include <ctype.h>
-#include <sstream>
-#include <string.h>
-#include <utility>
-
//#define CM_COMPUTE_LINK_INFO_DEBUG
/*
@@ -30,7 +33,7 @@ Notes about linking on various platforms:
------------------------------------------------------------------------------
-Linux, FreeBSD, Mac OS X, IRIX, Sun, Windows:
+Linux, FreeBSD, macOS, Sun, Windows:
Linking to libraries using the full path works fine.
@@ -240,27 +243,24 @@ because this need be done only for shared libraries without soname-s.
cmComputeLinkInformation::cmComputeLinkInformation(
const cmGeneratorTarget* target, const std::string& config)
-{
// Store context information.
- this->Target = target;
- this->Makefile = this->Target->Target->GetMakefile();
- this->GlobalGenerator =
- this->Target->GetLocalGenerator()->GetGlobalGenerator();
- this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance();
-
+ : Target(target)
+ , Makefile(target->Target->GetMakefile())
+ , GlobalGenerator(target->GetLocalGenerator()->GetGlobalGenerator())
+ , CMakeInstance(this->GlobalGenerator->GetCMakeInstance())
+ // The configuration being linked.
+ , Config(config)
+{
// Check whether to recognize OpenBSD-style library versioned names.
this->OpenBSD = this->Makefile->GetState()->GetGlobalPropertyAsBool(
"FIND_LIBRARY_USE_OPENBSD_VERSIONING");
- // The configuration being linked.
- this->Config = config;
-
// Allocate internals.
this->OrderLinkerSearchPath = new cmOrderDirectories(
this->GlobalGenerator, target, "linker search path");
this->OrderRuntimeSearchPath = new cmOrderDirectories(
this->GlobalGenerator, target, "runtime search path");
- this->OrderDependentRPath = CM_NULLPTR;
+ this->OrderDependentRPath = nullptr;
// Get the language used for linking this target.
this->LinkLanguage = this->Target->GetLinkerLanguage(config);
@@ -270,10 +270,6 @@ cmComputeLinkInformation::cmComputeLinkInformation(
return;
}
- // Check whether we should use an import library for linking a target.
- this->UseImportLibrary =
- this->Makefile->IsDefinitionSet("CMAKE_IMPORT_LIBRARY_SUFFIX");
-
// Check whether we should skip dependencies on shared library files.
this->LinkDependsNoShared =
this->Target->GetPropertyAsBool("LINK_DEPENDS_NO_SHARED");
@@ -281,22 +277,36 @@ cmComputeLinkInformation::cmComputeLinkInformation(
// On platforms without import libraries there may be a special flag
// to use when creating a plugin (module) that obtains symbols from
// the program that will load it.
- this->LoaderFlag = CM_NULLPTR;
- if (!this->UseImportLibrary &&
+ this->LoaderFlag = nullptr;
+ if (!this->Target->IsDLLPlatform() &&
this->Target->GetType() == cmStateEnums::MODULE_LIBRARY) {
- std::string loader_flag_var = "CMAKE_SHARED_MODULE_LOADER_";
- loader_flag_var += this->LinkLanguage;
- loader_flag_var += "_FLAG";
+ std::string loader_flag_var =
+ cmStrCat("CMAKE_SHARED_MODULE_LOADER_", this->LinkLanguage, "_FLAG");
this->LoaderFlag = this->Makefile->GetDefinition(loader_flag_var);
}
// Get options needed to link libraries.
- this->LibLinkFlag =
- this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FLAG");
- this->LibLinkFileFlag =
- this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FILE_FLAG");
- this->LibLinkSuffix =
- this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX");
+ if (const char* flag = this->Makefile->GetDefinition(
+ "CMAKE_" + this->LinkLanguage + "_LINK_LIBRARY_FLAG")) {
+ this->LibLinkFlag = flag;
+ } else {
+ this->LibLinkFlag =
+ this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FLAG");
+ }
+ if (const char* flag = this->Makefile->GetDefinition(
+ "CMAKE_" + this->LinkLanguage + "_LINK_LIBRARY_FILE_FLAG")) {
+ this->LibLinkFileFlag = flag;
+ } else {
+ this->LibLinkFileFlag =
+ this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FILE_FLAG");
+ }
+ if (const char* suffix = this->Makefile->GetDefinition(
+ "CMAKE_" + this->LinkLanguage + "_LINK_LIBRARY_SUFFIX")) {
+ this->LibLinkSuffix = suffix;
+ } else {
+ this->LibLinkSuffix =
+ this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX");
+ }
// Get options needed to specify RPATHs.
this->RuntimeUseChrpath = false;
@@ -304,11 +314,8 @@ cmComputeLinkInformation::cmComputeLinkInformation(
const char* tType = ((this->Target->GetType() == cmStateEnums::EXECUTABLE)
? "EXECUTABLE"
: "SHARED_LIBRARY");
- std::string rtVar = "CMAKE_";
- rtVar += tType;
- rtVar += "_RUNTIME_";
- rtVar += this->LinkLanguage;
- rtVar += "_FLAG";
+ std::string rtVar =
+ cmStrCat("CMAKE_", tType, "_RUNTIME_", this->LinkLanguage, "_FLAG");
std::string rtSepVar = rtVar + "_SEP";
this->RuntimeFlag = this->Makefile->GetSafeDefinition(rtVar);
this->RuntimeSep = this->Makefile->GetSafeDefinition(rtSepVar);
@@ -318,19 +325,15 @@ cmComputeLinkInformation::cmComputeLinkInformation(
this->RuntimeUseChrpath = this->Target->IsChrpathUsed(config);
// Get options needed to help find dependent libraries.
- std::string rlVar = "CMAKE_";
- rlVar += tType;
- rlVar += "_RPATH_LINK_";
- rlVar += this->LinkLanguage;
- rlVar += "_FLAG";
+ std::string rlVar =
+ cmStrCat("CMAKE_", tType, "_RPATH_LINK_", this->LinkLanguage, "_FLAG");
this->RPathLinkFlag = this->Makefile->GetSafeDefinition(rlVar);
}
// Check if we need to include the runtime search path at link time.
{
- std::string var = "CMAKE_SHARED_LIBRARY_LINK_";
- var += this->LinkLanguage;
- var += "_WITH_RUNTIME_PATH";
+ std::string var = cmStrCat("CMAKE_SHARED_LIBRARY_LINK_",
+ this->LinkLanguage, "_WITH_RUNTIME_PATH");
this->LinkWithRuntimePath = this->Makefile->IsOn(var);
}
@@ -360,10 +363,10 @@ cmComputeLinkInformation::cmComputeLinkInformation(
}
// Add the search path entries requested by the user to path ordering.
- this->OrderLinkerSearchPath->AddUserDirectories(
- this->Target->GetLinkDirectories());
- this->OrderRuntimeSearchPath->AddUserDirectories(
- this->Target->GetLinkDirectories());
+ std::vector<std::string> directories;
+ this->Target->GetLinkDirectories(directories, config, this->LinkLanguage);
+ this->OrderLinkerSearchPath->AddUserDirectories(directories);
+ this->OrderRuntimeSearchPath->AddUserDirectories(directories);
// Set up the implicit link directories.
this->LoadImplicitLinkInfo();
@@ -390,8 +393,7 @@ cmComputeLinkInformation::cmComputeLinkInformation(
if (this->OldLinkDirMode) {
// Construct a mask to not bother with this behavior for link
// directories already specified by the user.
- std::vector<std::string> const& dirs = this->Target->GetLinkDirectories();
- this->OldLinkDirMask.insert(dirs.begin(), dirs.end());
+ this->OldLinkDirMask.insert(directories.begin(), directories.end());
}
this->CMP0060Warn = this->Makefile->PolicyOptionalWarningEnabled(
@@ -405,18 +407,53 @@ cmComputeLinkInformation::~cmComputeLinkInformation()
delete this->OrderDependentRPath;
}
+void cmComputeLinkInformation::AppendValues(
+ std::string& result, std::vector<BT<std::string>>& values)
+{
+ for (BT<std::string>& p : values) {
+ if (result.empty()) {
+ result.append(" ");
+ }
+
+ result.append(p.Value);
+ }
+}
+
cmComputeLinkInformation::ItemVector const&
-cmComputeLinkInformation::GetItems()
+cmComputeLinkInformation::GetItems() const
{
return this->Items;
}
std::vector<std::string> const& cmComputeLinkInformation::GetDirectories()
+ const
{
return this->OrderLinkerSearchPath->GetOrderedDirectories();
}
-std::string cmComputeLinkInformation::GetRPathLinkString()
+std::vector<BT<std::string>>
+cmComputeLinkInformation::GetDirectoriesWithBacktraces()
+{
+ std::vector<BT<std::string>> directoriesWithBacktraces;
+
+ std::vector<BT<std::string>> targetLinkDirectores =
+ this->Target->GetLinkDirectories(this->Config, this->LinkLanguage);
+
+ const std::vector<std::string>& orderedDirectories = this->GetDirectories();
+ for (const std::string& dir : orderedDirectories) {
+ auto result =
+ std::find(targetLinkDirectores.begin(), targetLinkDirectores.end(), dir);
+ if (result != targetLinkDirectores.end()) {
+ directoriesWithBacktraces.emplace_back(std::move(*result));
+ } else {
+ directoriesWithBacktraces.emplace_back(dir);
+ }
+ }
+
+ return directoriesWithBacktraces;
+}
+
+std::string cmComputeLinkInformation::GetRPathLinkString() const
{
// If there is no separate linker runtime search flag (-rpath-link)
// there is no reason to compute a string.
@@ -424,22 +461,24 @@ std::string cmComputeLinkInformation::GetRPathLinkString()
return "";
}
- // Construct the linker runtime search path.
+ // Construct the linker runtime search path. These MUST NOT contain tokens
+ // such as $ORIGIN, see https://sourceware.org/bugzilla/show_bug.cgi?id=16936
return cmJoin(this->OrderDependentRPath->GetOrderedDirectories(), ":");
}
-std::vector<std::string> const& cmComputeLinkInformation::GetDepends()
+std::vector<std::string> const& cmComputeLinkInformation::GetDepends() const
{
return this->Depends;
}
std::vector<std::string> const& cmComputeLinkInformation::GetFrameworkPaths()
+ const
{
return this->FrameworkPaths;
}
const std::set<const cmGeneratorTarget*>&
-cmComputeLinkInformation::GetSharedLibrariesLinked()
+cmComputeLinkInformation::GetSharedLibrariesLinked() const
{
return this->SharedLibrariesLinked;
}
@@ -457,8 +496,8 @@ bool cmComputeLinkInformation::Compute()
// We require a link language for the target.
if (this->LinkLanguage.empty()) {
cmSystemTools::Error(
- "CMake can not determine linker language for target: ",
- this->Target->GetName().c_str());
+ "CMake can not determine linker language for target: " +
+ this->Target->GetName());
return false;
}
@@ -468,20 +507,18 @@ bool cmComputeLinkInformation::Compute()
cmComputeLinkDepends::EntryVector const& linkEntries = cld.Compute();
// Add the link line items.
- for (cmComputeLinkDepends::EntryVector::const_iterator lei =
- linkEntries.begin();
- lei != linkEntries.end(); ++lei) {
- if (lei->IsSharedDep) {
- this->AddSharedDepItem(lei->Item, lei->Target);
+ for (cmComputeLinkDepends::LinkEntry const& linkEntry : linkEntries) {
+ if (linkEntry.IsSharedDep) {
+ this->AddSharedDepItem(linkEntry.Item, linkEntry.Target);
} else {
- this->AddItem(lei->Item, lei->Target);
+ this->AddItem(linkEntry.Item, linkEntry.Target);
}
}
// Restore the target link type so the correct system runtime
// libraries are found.
const char* lss = this->Target->GetProperty("LINK_SEARCH_END_STATIC");
- if (cmSystemTools::IsOn(lss)) {
+ if (cmIsOn(lss)) {
this->SetCurrentLinkType(LinkStatic);
} else {
this->SetCurrentLinkType(this->StartLinkType);
@@ -494,17 +531,12 @@ bool cmComputeLinkInformation::Compute()
// directories.
std::set<cmGeneratorTarget const*> const& wrongItems =
cld.GetOldWrongConfigItems();
- for (std::set<cmGeneratorTarget const*>::const_iterator i =
- wrongItems.begin();
- i != wrongItems.end(); ++i) {
- cmGeneratorTarget const* tgt = *i;
- bool implib = (this->UseImportLibrary &&
- (tgt->GetType() == cmStateEnums::SHARED_LIBRARY));
- cmStateEnums::ArtifactType artifact = implib
+ for (cmGeneratorTarget const* tgt : wrongItems) {
+ cmStateEnums::ArtifactType artifact = tgt->HasImportLibrary(this->Config)
? 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));
}
}
@@ -528,7 +560,7 @@ bool cmComputeLinkInformation::Compute()
"name."
;
/* clang-format on */
- this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(),
+ this->CMakeInstance->IssueMessage(MessageType::AUTHOR_WARNING, w.str(),
this->Target->GetBacktrace());
}
@@ -540,11 +572,10 @@ void cmComputeLinkInformation::AddImplicitLinkInfo()
// The link closure lists all languages whose implicit info is needed.
cmGeneratorTarget::LinkClosure const* lc =
this->Target->GetLinkClosure(this->Config);
- for (std::vector<std::string>::const_iterator li = lc->Languages.begin();
- li != lc->Languages.end(); ++li) {
+ for (std::string const& li : lc->Languages) {
// Skip those of the linker language. They are implicit.
- if (*li != this->LinkLanguage) {
- this->AddImplicitLinkInfo(*li);
+ if (li != this->LinkLanguage) {
+ this->AddImplicitLinkInfo(li);
}
}
}
@@ -553,28 +584,21 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang)
{
// Add libraries for this language that are not implied by the
// linker language.
- std::string libVar = "CMAKE_";
- libVar += lang;
- libVar += "_IMPLICIT_LINK_LIBRARIES";
+ std::string libVar = cmStrCat("CMAKE_", lang, "_IMPLICIT_LINK_LIBRARIES");
if (const char* libs = this->Makefile->GetDefinition(libVar)) {
- std::vector<std::string> libsVec;
- cmSystemTools::ExpandListArgument(libs, libsVec);
- for (std::vector<std::string>::const_iterator i = libsVec.begin();
- i != libsVec.end(); ++i) {
- if (this->ImplicitLinkLibs.find(*i) == this->ImplicitLinkLibs.end()) {
- this->AddItem(*i, CM_NULLPTR);
+ std::vector<std::string> libsVec = cmExpandedList(libs);
+ for (std::string const& i : libsVec) {
+ if (!cmContains(this->ImplicitLinkLibs, i)) {
+ this->AddItem(i, nullptr);
}
}
}
// Add linker search paths for this language that are not
// implied by the linker language.
- std::string dirVar = "CMAKE_";
- dirVar += lang;
- dirVar += "_IMPLICIT_LINK_DIRECTORIES";
+ std::string dirVar = cmStrCat("CMAKE_", lang, "_IMPLICIT_LINK_DIRECTORIES");
if (const char* dirs = this->Makefile->GetDefinition(dirVar)) {
- std::vector<std::string> dirsVec;
- cmSystemTools::ExpandListArgument(dirs, dirsVec);
+ std::vector<std::string> dirsVec = cmExpandedList(dirs);
this->OrderLinkerSearchPath->AddLanguageDirectories(dirsVec);
}
}
@@ -585,7 +609,7 @@ void cmComputeLinkInformation::AddItem(std::string const& item,
// Compute the proper name to use to link this library.
const std::string& config = this->Config;
bool impexe = (tgt && tgt->IsExecutableWithExports());
- if (impexe && !this->UseImportLibrary && !this->LoaderFlag) {
+ if (impexe && !tgt->HasImportLibrary(config) && !this->LoaderFlag) {
// Skip linking to executables on platforms with no import
// libraries or loader flags.
return;
@@ -599,36 +623,45 @@ void cmComputeLinkInformation::AddItem(std::string const& item,
// platform. Add it now.
std::string linkItem;
linkItem = this->LoaderFlag;
- cmStateEnums::ArtifactType artifact = this->UseImportLibrary
+ cmStateEnums::ArtifactType artifact = tgt->HasImportLibrary(config)
? cmStateEnums::ImportLibraryArtifact
: cmStateEnums::RuntimeBinaryArtifact;
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);
if (!libName.empty()) {
- this->AddItem(libName, CM_NULLPTR);
+ this->AddItem(libName, nullptr);
}
+ } else if (tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ // Ignore object library!
+ // Its object-files should already have been extracted for linking.
} else {
// Decide whether to use an import library.
- bool implib =
- (this->UseImportLibrary &&
- (impexe || tgt->GetType() == cmStateEnums::SHARED_LIBRARY));
- cmStateEnums::ArtifactType artifact = implib
+ cmStateEnums::ArtifactType artifact = tgt->HasImportLibrary(config)
? cmStateEnums::ImportLibraryArtifact
: cmStateEnums::RuntimeBinaryArtifact;
// Pass the full path to the target file.
std::string lib = tgt->GetFullPath(config, artifact, true);
+ if (tgt->Target->IsAIX() && cmHasLiteralSuffix(lib, "-NOTFOUND") &&
+ artifact == cmStateEnums::ImportLibraryArtifact) {
+ // This is an imported executable on AIX that has ENABLE_EXPORTS
+ // but not IMPORTED_IMPLIB. CMake used to produce and accept such
+ // imported executables on AIX before we taught it to use linker
+ // import files. For compatibility, simply skip linking to this
+ // executable as we did before. It works with runtime linking.
+ return;
+ }
if (!this->LinkDependsNoShared ||
tgt->GetType() != cmStateEnums::SHARED_LIBRARY) {
this->Depends.push_back(lib);
@@ -639,7 +672,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);
@@ -675,13 +708,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;
}
@@ -698,7 +731,7 @@ void cmComputeLinkInformation::AddSharedDepItem(std::string const& item,
// linked will be able to find it.
std::string lib;
if (tgt) {
- cmStateEnums::ArtifactType artifact = this->UseImportLibrary
+ cmStateEnums::ArtifactType artifact = tgt->HasImportLibrary(this->Config)
? cmStateEnums::ImportLibraryArtifact
: cmStateEnums::RuntimeBinaryArtifact;
lib = tgt->GetFullPath(this->Config, artifact);
@@ -710,7 +743,7 @@ void cmComputeLinkInformation::AddSharedDepItem(std::string const& item,
// Check if we need to include the dependent shared library in other
// path ordering.
- cmOrderDirectories* order = CM_NULLPTR;
+ cmOrderDirectories* order = nullptr;
if (this->SharedDependencyMode == SharedDepModeLibDir &&
!this->LinkWithRuntimePath /* AddLibraryRuntimeInfo adds it */) {
// Add the item to the linker search path.
@@ -722,7 +755,7 @@ void cmComputeLinkInformation::AddSharedDepItem(std::string const& item,
if (order) {
if (tgt) {
std::string soName = tgt->GetSOName(this->Config);
- const char* soname = soName.empty() ? CM_NULLPTR : soName.c_str();
+ const char* soname = soName.empty() ? nullptr : soName.c_str();
order->AddRuntimeLibrary(lib, soname);
} else {
order->AddRuntimeLibrary(lib);
@@ -741,9 +774,9 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo()
this->LinkTypeEnabled = false;
// Lookup link type selection flags.
- const char* static_link_type_flag = CM_NULLPTR;
- const char* shared_link_type_flag = CM_NULLPTR;
- const char* target_type_str = CM_NULLPTR;
+ const char* static_link_type_flag = nullptr;
+ const char* shared_link_type_flag = nullptr;
+ const char* target_type_str = nullptr;
switch (this->Target->GetType()) {
case cmStateEnums::EXECUTABLE:
target_type_str = "EXE";
@@ -758,19 +791,15 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo()
break;
}
if (target_type_str) {
- std::string static_link_type_flag_var = "CMAKE_";
- static_link_type_flag_var += target_type_str;
- static_link_type_flag_var += "_LINK_STATIC_";
- static_link_type_flag_var += this->LinkLanguage;
- static_link_type_flag_var += "_FLAGS";
+ std::string static_link_type_flag_var =
+ cmStrCat("CMAKE_", target_type_str, "_LINK_STATIC_", this->LinkLanguage,
+ "_FLAGS");
static_link_type_flag =
this->Makefile->GetDefinition(static_link_type_flag_var);
- std::string shared_link_type_flag_var = "CMAKE_";
- shared_link_type_flag_var += target_type_str;
- shared_link_type_flag_var += "_LINK_DYNAMIC_";
- shared_link_type_flag_var += this->LinkLanguage;
- shared_link_type_flag_var += "_FLAGS";
+ std::string shared_link_type_flag_var =
+ cmStrCat("CMAKE_", target_type_str, "_LINK_DYNAMIC_", this->LinkLanguage,
+ "_FLAGS");
shared_link_type_flag =
this->Makefile->GetDefinition(shared_link_type_flag_var);
}
@@ -786,7 +815,7 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo()
// Lookup the starting link type from the target (linked statically?).
const char* lss = this->Target->GetProperty("LINK_SEARCH_START_STATIC");
- this->StartLinkType = cmSystemTools::IsOn(lss) ? LinkStatic : LinkShared;
+ this->StartLinkType = cmIsOn(lss) ? LinkStatic : LinkShared;
this->CurrentLinkType = this->StartLinkType;
}
@@ -809,20 +838,16 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
LinkUnknown);
if (const char* linkSuffixes =
mf->GetDefinition("CMAKE_EXTRA_LINK_EXTENSIONS")) {
- std::vector<std::string> linkSuffixVec;
- cmSystemTools::ExpandListArgument(linkSuffixes, linkSuffixVec);
- for (std::vector<std::string>::iterator i = linkSuffixVec.begin();
- i != linkSuffixVec.end(); ++i) {
- this->AddLinkExtension(i->c_str(), LinkUnknown);
+ std::vector<std::string> linkSuffixVec = cmExpandedList(linkSuffixes);
+ for (std::string const& i : linkSuffixVec) {
+ this->AddLinkExtension(i.c_str(), LinkUnknown);
}
}
if (const char* sharedSuffixes =
mf->GetDefinition("CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES")) {
- std::vector<std::string> sharedSuffixVec;
- cmSystemTools::ExpandListArgument(sharedSuffixes, sharedSuffixVec);
- for (std::vector<std::string>::iterator i = sharedSuffixVec.begin();
- i != sharedSuffixVec.end(); ++i) {
- this->AddLinkExtension(i->c_str(), LinkShared);
+ std::vector<std::string> sharedSuffixVec = cmExpandedList(sharedSuffixes);
+ for (std::string const& i : sharedSuffixVec) {
+ this->AddLinkExtension(i.c_str(), LinkShared);
}
}
@@ -840,17 +865,15 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
// be the library name. Match index 3 will be the library
// extension.
reg = "^(";
- for (std::set<std::string>::iterator p = this->LinkPrefixes.begin();
- p != this->LinkPrefixes.end(); ++p) {
- reg += *p;
+ for (std::string const& p : this->LinkPrefixes) {
+ reg += p;
reg += "|";
}
reg += ")";
reg += "([^/:]*)";
// Create a regex to match any library name.
- std::string reg_any = reg;
- reg_any += libext;
+ std::string reg_any = cmStrCat(reg, libext);
#ifdef CM_COMPUTE_LINK_INFO_DEBUG
fprintf(stderr, "any regex [%s]\n", reg_any.c_str());
#endif
@@ -858,9 +881,8 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
// Create a regex to match static library names.
if (!this->StaticLinkExtensions.empty()) {
- std::string reg_static = reg;
- reg_static +=
- this->CreateExtensionRegex(this->StaticLinkExtensions, LinkStatic);
+ std::string reg_static = cmStrCat(
+ reg, this->CreateExtensionRegex(this->StaticLinkExtensions, LinkStatic));
#ifdef CM_COMPUTE_LINK_INFO_DEBUG
fprintf(stderr, "static regex [%s]\n", reg_static.c_str());
#endif
@@ -891,12 +913,12 @@ void cmComputeLinkInformation::AddLinkExtension(const char* e, LinkType type)
{
if (e && *e) {
if (type == LinkStatic) {
- this->StaticLinkExtensions.push_back(e);
+ this->StaticLinkExtensions.emplace_back(e);
}
if (type == LinkShared) {
- this->SharedLinkExtensions.push_back(e);
+ this->SharedLinkExtensions.emplace_back(e);
}
- this->LinkExtensions.push_back(e);
+ this->LinkExtensions.emplace_back(e);
}
}
@@ -906,8 +928,7 @@ std::string cmComputeLinkInformation::CreateExtensionRegex(
// Build a list of extension choices.
std::string libext = "(";
const char* sep = "";
- for (std::vector<std::string>::const_iterator i = exts.begin();
- i != exts.end(); ++i) {
+ for (std::string const& i : exts) {
// Separate this choice from the previous one.
libext += sep;
sep = "|";
@@ -915,20 +936,18 @@ std::string cmComputeLinkInformation::CreateExtensionRegex(
// Store this extension choice with the "." escaped.
libext += "\\";
#if defined(_WIN32) && !defined(__CYGWIN__)
- libext += this->NoCaseExpression(i->c_str());
+ libext += this->NoCaseExpression(i.c_str());
#else
- libext += *i;
+ libext += i;
#endif
}
// 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 += "$";
@@ -963,10 +982,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;
@@ -1000,21 +1019,16 @@ void cmComputeLinkInformation::AddTargetItem(std::string const& item,
return;
}
- // If this platform wants a flag before the full path, add it.
- if (!this->LibLinkFileFlag.empty()) {
- this->Items.push_back(Item(this->LibLinkFileFlag, false));
- }
-
// For compatibility with CMake 2.4 include the item's directory in
// the linker search path.
if (this->OldLinkDirMode && !target->IsFrameworkOnApple() &&
- this->OldLinkDirMask.find(cmSystemTools::GetFilenamePath(item)) ==
- this->OldLinkDirMask.end()) {
+ !cmContains(this->OldLinkDirMask,
+ cmSystemTools::GetFilenamePath(item))) {
this->OldLinkDirItems.push_back(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)
@@ -1036,7 +1050,7 @@ void cmComputeLinkInformation::AddFullItem(std::string const& item)
(generator.find("Visual Studio") != std::string::npos ||
generator.find("Xcode") != std::string::npos)) {
std::string file = cmSystemTools::GetFilenameName(item);
- if (!this->ExtractAnyLibraryName.find(file.c_str())) {
+ if (!this->ExtractAnyLibraryName.find(file)) {
this->HandleBadFullItem(item, file);
return;
}
@@ -1062,18 +1076,13 @@ void cmComputeLinkInformation::AddFullItem(std::string const& item)
// For compatibility with CMake 2.4 include the item's directory in
// the linker search path.
if (this->OldLinkDirMode &&
- this->OldLinkDirMask.find(cmSystemTools::GetFilenamePath(item)) ==
- this->OldLinkDirMask.end()) {
+ !cmContains(this->OldLinkDirMask,
+ cmSystemTools::GetFilenamePath(item))) {
this->OldLinkDirItems.push_back(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));
- }
-
// 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)
@@ -1087,7 +1096,7 @@ bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item)
// Check if this item is in an implicit link directory.
std::string dir = cmSystemTools::GetFilenamePath(item);
- if (this->ImplicitLinkDirs.find(dir) == this->ImplicitLinkDirs.end()) {
+ if (!cmContains(this->ImplicitLinkDirs, dir)) {
// Only libraries in implicit link directories are converted to
// pathless items.
return false;
@@ -1160,7 +1169,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;
}
@@ -1229,10 +1238,8 @@ void cmComputeLinkInformation::AddUserItem(std::string const& item,
}
// Create an option to ask the linker to search for the library.
- std::string out = this->LibLinkFlag;
- out += lib;
- out += this->LibLinkSuffix;
- this->Items.push_back(Item(out, false));
+ std::string out = cmStrCat(this->LibLinkFlag, lib, this->LibLinkSuffix);
+ 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
@@ -1243,22 +1250,17 @@ void cmComputeLinkInformation::AddUserItem(std::string const& item,
void cmComputeLinkInformation::AddFrameworkItem(std::string const& item)
{
// Try to separate the framework name and path.
- if (!this->SplitFramework.find(item.c_str())) {
+ if (!this->SplitFramework.find(item)) {
std::ostringstream e;
e << "Could not parse framework path \"" << item << "\" "
<< "linked by target " << this->Target->GetName() << ".";
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
return;
}
std::string fw_path = this->SplitFramework.match(1);
std::string fw = this->SplitFramework.match(2);
- std::string full_fw = fw_path;
- full_fw += "/";
- full_fw += fw;
- full_fw += ".framework";
- full_fw += "/";
- full_fw += fw;
+ std::string full_fw = cmStrCat(fw_path, '/', fw, ".framework/", fw);
// Add the directory portion to the framework search path.
this->AddFrameworkPath(fw_path);
@@ -1267,16 +1269,16 @@ 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)
{
if (this->Makefile->IsOn("APPLE") &&
- cmSystemTools::IsPathToFramework(item.c_str())) {
+ cmSystemTools::IsPathToFramework(item)) {
this->AddFrameworkItem(item);
} else {
this->DropDirectoryItem(item);
@@ -1292,7 +1294,7 @@ void cmComputeLinkInformation::DropDirectoryItem(std::string const& item)
<< "\" requests linking to directory \"" << item << "\". "
<< "Targets may link only to libraries. "
<< "CMake is dropping the item.";
- cmSystemTools::Message(e.str().c_str());
+ cmSystemTools::Message(e.str());
}
void cmComputeLinkInformation::ComputeFrameworkInfo()
@@ -1303,16 +1305,15 @@ void cmComputeLinkInformation::ComputeFrameworkInfo()
// Get platform-wide implicit directories.
if (const char* implicitLinks = this->Makefile->GetDefinition(
"CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES")) {
- cmSystemTools::ExpandListArgument(implicitLinks, implicitDirVec);
+ cmExpandList(implicitLinks, implicitDirVec);
}
// Get language-specific implicit directories.
- std::string implicitDirVar = "CMAKE_";
- implicitDirVar += this->LinkLanguage;
- implicitDirVar += "_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES";
+ std::string implicitDirVar = cmStrCat(
+ "CMAKE_", this->LinkLanguage, "_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES");
if (const char* implicitDirs =
this->Makefile->GetDefinition(implicitDirVar)) {
- cmSystemTools::ExpandListArgument(implicitDirs, implicitDirVec);
+ cmExpandList(implicitDirs, implicitDirVec);
}
this->FrameworkPathsEmmitted.insert(implicitDirVec.begin(),
@@ -1366,8 +1367,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item,
std::string const& file)
{
// Do not depend on things that do not exist.
- std::vector<std::string>::iterator i =
- std::find(this->Depends.begin(), this->Depends.end(), item);
+ auto i = std::find(this->Depends.begin(), this->Depends.end(), item);
if (i != this->Depends.end()) {
this->Depends.erase(i);
}
@@ -1382,8 +1382,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item,
switch (this->Target->GetPolicyStatusCMP0008()) {
case cmPolicies::WARN: {
// Print the warning at most once for this item.
- std::string wid = "CMP0008-WARNING-GIVEN-";
- wid += item;
+ std::string wid = cmStrCat("CMP0008-WARNING-GIVEN-", item);
if (!this->CMakeInstance->GetState()->GetGlobalPropertyAsBool(wid)) {
this->CMakeInstance->GetState()->SetGlobalProperty(wid, "1");
std::ostringstream w;
@@ -1393,7 +1392,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item,
<< " " << item << "\n"
<< "which is a full-path but not a valid library file name.";
/* clang-format on */
- this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(),
+ this->CMakeInstance->IssueMessage(MessageType::AUTHOR_WARNING, w.str(),
this->Target->GetBacktrace());
}
}
@@ -1412,7 +1411,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item,
<< " " << item << "\n"
<< "which is a full-path but not a valid library file name.";
/* clang-format on */
- this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->CMakeInstance->IssueMessage(MessageType::FATAL_ERROR, e.str(),
this->Target->GetBacktrace());
} break;
}
@@ -1435,7 +1434,7 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories()
"CMP0003-WARNING-GIVEN", "1");
std::ostringstream w;
this->PrintLinkPolicyDiagnosis(w);
- this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(),
+ this->CMakeInstance->IssueMessage(MessageType::AUTHOR_WARNING, w.str(),
this->Target->GetBacktrace());
}
case cmPolicies::OLD:
@@ -1450,17 +1449,15 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories()
std::ostringstream e;
e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0003) << "\n";
this->PrintLinkPolicyDiagnosis(e);
- this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->CMakeInstance->IssueMessage(MessageType::FATAL_ERROR, e.str(),
this->Target->GetBacktrace());
return false;
}
}
// Add the link directories for full path items.
- for (std::vector<std::string>::const_iterator i =
- this->OldLinkDirItems.begin();
- i != this->OldLinkDirItems.end(); ++i) {
- this->OrderLinkerSearchPath->AddLinkLibrary(*i);
+ for (std::string const& i : this->OldLinkDirItems) {
+ this->OrderLinkerSearchPath->AddLinkLibrary(i);
}
return true;
}
@@ -1489,19 +1486,17 @@ void cmComputeLinkInformation::PrintLinkPolicyDiagnosis(std::ostream& os)
std::string::size_type max_size = 76;
std::string line;
const char* sep = " ";
- for (std::vector<std::string>::const_iterator i =
- this->OldUserFlagItems.begin();
- i != this->OldUserFlagItems.end(); ++i) {
+ for (std::string const& i : this->OldUserFlagItems) {
// If the addition of another item will exceed the limit then
// output the current line and reset it. Note that the separator
// is either " " or ", " which is always 2 characters.
- if (!line.empty() && (line.size() + i->size() + 2) > max_size) {
+ if (!line.empty() && (line.size() + i.size() + 2) > max_size) {
os << line << "\n";
sep = " ";
- line = "";
+ line.clear();
}
line += sep;
- line += *i;
+ line += i;
// Convert to the other separator.
sep = ", ";
}
@@ -1513,11 +1508,9 @@ void cmComputeLinkInformation::PrintLinkPolicyDiagnosis(std::ostream& os)
// List the paths old behavior is adding.
os << "and other libraries with known full path:\n";
std::set<std::string> emitted;
- for (std::vector<std::string>::const_iterator i =
- this->OldLinkDirItems.begin();
- i != this->OldLinkDirItems.end(); ++i) {
- if (emitted.insert(cmSystemTools::GetFilenamePath(*i)).second) {
- os << " " << *i << "\n";
+ for (std::string const& i : this->OldLinkDirItems) {
+ if (emitted.insert(cmSystemTools::GetFilenamePath(i)).second) {
+ os << " " << i << "\n";
}
}
@@ -1537,26 +1530,24 @@ void cmComputeLinkInformation::LoadImplicitLinkInfo()
// Get platform-wide implicit directories.
if (const char* implicitLinks = (this->Makefile->GetDefinition(
"CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES"))) {
- cmSystemTools::ExpandListArgument(implicitLinks, implicitDirVec);
+ cmExpandList(implicitLinks, implicitDirVec);
}
// Append library architecture to all implicit platform directories
// and add them to the set
if (const char* libraryArch =
this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE")) {
- for (std::vector<std::string>::const_iterator i = implicitDirVec.begin();
- i != implicitDirVec.end(); ++i) {
- this->ImplicitLinkDirs.insert(*i + "/" + libraryArch);
+ for (std::string const& i : implicitDirVec) {
+ this->ImplicitLinkDirs.insert(i + "/" + libraryArch);
}
}
// Get language-specific implicit directories.
- std::string implicitDirVar = "CMAKE_";
- implicitDirVar += this->LinkLanguage;
- implicitDirVar += "_IMPLICIT_LINK_DIRECTORIES";
+ std::string implicitDirVar =
+ cmStrCat("CMAKE_", this->LinkLanguage, "_IMPLICIT_LINK_DIRECTORIES");
if (const char* implicitDirs =
this->Makefile->GetDefinition(implicitDirVar)) {
- cmSystemTools::ExpandListArgument(implicitDirs, implicitDirVec);
+ cmExpandList(implicitDirs, implicitDirVec);
}
// Store implicit link directories.
@@ -1564,20 +1555,17 @@ void cmComputeLinkInformation::LoadImplicitLinkInfo()
// Get language-specific implicit libraries.
std::vector<std::string> implicitLibVec;
- std::string implicitLibVar = "CMAKE_";
- implicitLibVar += this->LinkLanguage;
- implicitLibVar += "_IMPLICIT_LINK_LIBRARIES";
+ std::string implicitLibVar =
+ cmStrCat("CMAKE_", this->LinkLanguage, "_IMPLICIT_LINK_LIBRARIES");
if (const char* implicitLibs =
this->Makefile->GetDefinition(implicitLibVar)) {
- cmSystemTools::ExpandListArgument(implicitLibs, implicitLibVec);
+ cmExpandList(implicitLibs, implicitLibVec);
}
// Store implicit link libraries.
- for (std::vector<std::string>::const_iterator i = implicitLibVec.begin();
- i != implicitLibVec.end(); ++i) {
+ for (std::string const& item : implicitLibVec) {
// Items starting in '-' but not '-l' are flags, not libraries,
// and should not be filtered by this implicit list.
- std::string const& item = *i;
if (item[0] != '-' || item[1] == 'l') {
this->ImplicitLinkLibs.insert(item);
}
@@ -1586,12 +1574,12 @@ void cmComputeLinkInformation::LoadImplicitLinkInfo()
// Get platform specific rpath link directories
if (const char* rpathDirs =
(this->Makefile->GetDefinition("CMAKE_PLATFORM_RUNTIME_PATH"))) {
- cmSystemTools::ExpandListArgument(rpathDirs, this->RuntimeLinkDirs);
+ cmExpandList(rpathDirs, this->RuntimeLinkDirs);
}
}
std::vector<std::string> const&
-cmComputeLinkInformation::GetRuntimeSearchPath()
+cmComputeLinkInformation::GetRuntimeSearchPath() const
{
return this->OrderRuntimeSearchPath->GetOrderedDirectories();
}
@@ -1623,7 +1611,7 @@ void cmComputeLinkInformation::AddLibraryRuntimeInfo(
// Try to get the soname of the library. Only files with this name
// could possibly conflict.
std::string soName = target->GetSOName(this->Config);
- const char* soname = soName.empty() ? CM_NULLPTR : soName.c_str();
+ const char* soname = soName.empty() ? nullptr : soName.c_str();
// Include this library in the runtime path ordering.
this->OrderRuntimeSearchPath->AddRuntimeLibrary(fullPath, soname);
@@ -1657,7 +1645,7 @@ void cmComputeLinkInformation::AddLibraryRuntimeInfo(
if (!is_shared_library) {
// On some platforms (AIX) a shared library may look static.
if (this->ArchivesMayBeShared) {
- if (this->ExtractStaticLibraryName.find(file.c_str())) {
+ if (this->ExtractStaticLibraryName.find(file)) {
// This is the name of a shared library or archive.
is_shared_library = true;
}
@@ -1692,18 +1680,16 @@ static void cmCLI_ExpandListUnique(const char* str,
std::vector<std::string>& out,
std::set<std::string>& emitted)
{
- std::vector<std::string> tmp;
- cmSystemTools::ExpandListArgument(str, tmp);
- for (std::vector<std::string>::iterator i = tmp.begin(); i != tmp.end();
- ++i) {
- if (emitted.insert(*i).second) {
- out.push_back(*i);
+ std::vector<std::string> tmp = cmExpandedList(str);
+ for (std::string const& i : tmp) {
+ if (emitted.insert(i).second) {
+ out.push_back(i);
}
}
}
void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
- bool for_install)
+ bool for_install) const
{
// Select whether to generate runtime search directories.
bool outputRuntime =
@@ -1715,7 +1701,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
(for_install ||
this->Target->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"));
bool use_install_rpath =
- (outputRuntime && this->Target->HaveInstallTreeRPATH() &&
+ (outputRuntime && this->Target->HaveInstallTreeRPATH(this->Config) &&
linking_for_install);
bool use_build_rpath =
(outputRuntime && this->Target->HaveBuildTreeRPATH(this->Config) &&
@@ -1724,16 +1710,28 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
!this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH") &&
this->Target->GetPropertyAsBool("INSTALL_RPATH_USE_LINK_PATH");
+ // Select whether to use $ORIGIN in RPATHs for artifacts in the build tree.
+ std::string const& originToken = this->Makefile->GetSafeDefinition(
+ "CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN");
+ std::string targetOutputDir = this->Target->GetDirectory(this->Config);
+ bool use_relative_build_rpath =
+ this->Target->GetPropertyAsBool("BUILD_RPATH_USE_ORIGIN") &&
+ !originToken.empty() && !targetOutputDir.empty();
+
// Construct the RPATH.
std::set<std::string> emitted;
if (use_install_rpath) {
- const char* install_rpath = this->Target->GetProperty("INSTALL_RPATH");
- cmCLI_ExpandListUnique(install_rpath, runtimeDirs, emitted);
+ std::string install_rpath;
+ this->Target->GetInstallRPATH(this->Config, install_rpath);
+ cmCLI_ExpandListUnique(install_rpath.c_str(), runtimeDirs, emitted);
}
if (use_build_rpath) {
// Add directories explicitly specified by user
- if (const char* build_rpath = this->Target->GetProperty("BUILD_RPATH")) {
- cmCLI_ExpandListUnique(build_rpath, runtimeDirs, emitted);
+ std::string build_rpath;
+ if (this->Target->GetBuildRPATH(this->Config, build_rpath)) {
+ // This will not resolve entries to use $ORIGIN, the user is expected to
+ // do that if necessary.
+ cmCLI_ExpandListUnique(build_rpath.c_str(), runtimeDirs, emitted);
}
}
if (use_build_rpath || use_link_rpath) {
@@ -1746,49 +1744,57 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
}
const char* stagePath =
this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX");
- const char* installPrefix =
+ std::string const& installPrefix =
this->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
cmSystemTools::ConvertToUnixSlashes(rootPath);
std::vector<std::string> const& rdirs = this->GetRuntimeSearchPath();
- for (std::vector<std::string>::const_iterator ri = rdirs.begin();
- ri != rdirs.end(); ++ri) {
+ std::string const& topBinaryDir =
+ this->CMakeInstance->GetHomeOutputDirectory();
+ for (std::string const& ri : rdirs) {
// Put this directory in the rpath if using build-tree rpath
// support or if using the link path as an rpath.
if (use_build_rpath) {
- std::string d = *ri;
+ std::string d = ri;
if (!rootPath.empty() && d.find(rootPath) == 0) {
d = d.substr(rootPath.size());
} else if (stagePath && *stagePath && d.find(stagePath) == 0) {
std::string suffix = d.substr(strlen(stagePath));
- d = installPrefix;
- d += "/";
- d += suffix;
+ d = cmStrCat(installPrefix, '/', suffix);
cmSystemTools::ConvertToUnixSlashes(d);
+ } else if (use_relative_build_rpath) {
+ // If expansion of the $ORIGIN token is supported and permitted per
+ // policy, use relative paths in the RPATH.
+ if (cmSystemTools::ComparePath(d, topBinaryDir) ||
+ cmSystemTools::IsSubDirectory(d, topBinaryDir)) {
+ d = cmSystemTools::RelativePath(targetOutputDir, d);
+ if (!d.empty()) {
+ d = cmStrCat(originToken, "/", d);
+ } else {
+ d = originToken;
+ }
+ }
}
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 =
- this->CMakeInstance->GetHomeOutputDirectory();
- if (!cmSystemTools::ComparePath(*ri, topSourceDir) &&
- !cmSystemTools::ComparePath(*ri, topBinaryDir) &&
- !cmSystemTools::IsSubDirectory(*ri, topSourceDir) &&
- !cmSystemTools::IsSubDirectory(*ri, topBinaryDir)) {
- std::string d = *ri;
+ std::string const& topSourceDir =
+ this->CMakeInstance->GetHomeDirectory();
+ if (!cmSystemTools::ComparePath(ri, topSourceDir) &&
+ !cmSystemTools::ComparePath(ri, topBinaryDir) &&
+ !cmSystemTools::IsSubDirectory(ri, topSourceDir) &&
+ !cmSystemTools::IsSubDirectory(ri, topBinaryDir)) {
+ std::string d = ri;
if (!rootPath.empty() && d.find(rootPath) == 0) {
d = d.substr(rootPath.size());
} else if (stagePath && *stagePath && d.find(stagePath) == 0) {
std::string suffix = d.substr(strlen(stagePath));
- d = installPrefix;
- d += "/";
- d += suffix;
+ d = cmStrCat(installPrefix, '/', suffix);
cmSystemTools::ConvertToUnixSlashes(d);
}
if (emitted.insert(d).second) {
- runtimeDirs.push_back(d);
+ runtimeDirs.push_back(std::move(d));
}
}
}
@@ -1800,12 +1806,11 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
{
cmGeneratorTarget::LinkClosure const* lc =
this->Target->GetLinkClosure(this->Config);
- for (std::vector<std::string>::const_iterator li = lc->Languages.begin();
- li != lc->Languages.end(); ++li) {
+ for (std::string const& li : lc->Languages) {
std::string useVar =
- "CMAKE_" + *li + "_USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH";
+ "CMAKE_" + li + "_USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH";
if (this->Makefile->IsOn(useVar)) {
- std::string dirVar = "CMAKE_" + *li + "_IMPLICIT_LINK_DIRECTORIES";
+ std::string dirVar = "CMAKE_" + li + "_IMPLICIT_LINK_DIRECTORIES";
if (const char* dirs = this->Makefile->GetDefinition(dirVar)) {
cmCLI_ExpandListUnique(dirs, runtimeDirs, emitted);
}
@@ -1818,7 +1823,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
cmCLI_ExpandListUnique(this->RuntimeAlways.c_str(), runtimeDirs, emitted);
}
-std::string cmComputeLinkInformation::GetRPathString(bool for_install)
+std::string cmComputeLinkInformation::GetRPathString(bool for_install) const
{
// Get the directories to use.
std::vector<std::string> runtimeDirs;
@@ -1846,7 +1851,7 @@ std::string cmComputeLinkInformation::GetRPathString(bool for_install)
return rpath;
}
-std::string cmComputeLinkInformation::GetChrpathString()
+std::string cmComputeLinkInformation::GetChrpathString() const
{
if (!this->RuntimeUseChrpath) {
return "";
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index 00e3ad265..92ab83b3b 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -5,17 +5,21 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmsys/RegularExpression.hxx"
#include <iosfwd>
#include <set>
#include <string>
+#include <utility>
#include <vector>
+#include "cmsys/RegularExpression.hxx"
+
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmMakefile;
class cmOrderDirectories;
class cmake;
+template <typename T>
+class BT;
/** \class cmComputeLinkInformation
* \brief Compute link information for a target in one configuration.
@@ -30,41 +34,45 @@ public:
struct Item
{
- Item()
- : Value()
- , IsPath(true)
- , Target(CM_NULLPTR)
- {
- }
- Item(std::string const& v, bool p,
- cmGeneratorTarget const* target = CM_NULLPTR)
- : Value(v)
+ Item() = default;
+ Item(std::string v, bool p, cmGeneratorTarget const* target = nullptr)
+ : Value(std::move(v))
, IsPath(p)
, Target(target)
{
}
std::string Value;
- bool IsPath;
- cmGeneratorTarget const* Target;
+ bool IsPath = true;
+ cmGeneratorTarget const* Target = nullptr;
};
- typedef std::vector<Item> ItemVector;
- ItemVector const& GetItems();
- std::vector<std::string> const& GetDirectories();
- std::vector<std::string> const& GetDepends();
- std::vector<std::string> const& GetFrameworkPaths();
+ using ItemVector = std::vector<Item>;
+ void AppendValues(std::string& result, std::vector<BT<std::string>>& values);
+ ItemVector const& GetItems() const;
+ std::vector<std::string> const& GetDirectories() const;
+ std::vector<BT<std::string>> GetDirectoriesWithBacktraces();
+ std::vector<std::string> const& GetDepends() const;
+ std::vector<std::string> const& GetFrameworkPaths() const;
std::string GetLinkLanguage() const { return this->LinkLanguage; }
- std::vector<std::string> const& GetRuntimeSearchPath();
+ std::vector<std::string> const& GetRuntimeSearchPath() const;
std::string const& GetRuntimeFlag() const { return this->RuntimeFlag; }
std::string const& GetRuntimeSep() const { return this->RuntimeSep; }
- void GetRPath(std::vector<std::string>& runtimeDirs, bool for_install);
- std::string GetRPathString(bool for_install);
- std::string GetChrpathString();
- std::set<cmGeneratorTarget const*> const& GetSharedLibrariesLinked();
+ void GetRPath(std::vector<std::string>& runtimeDirs, bool for_install) const;
+ std::string GetRPathString(bool for_install) const;
+ std::string GetChrpathString() const;
+ std::set<cmGeneratorTarget const*> const& GetSharedLibrariesLinked() const;
+
+ std::string const& GetLibLinkFileFlag() const
+ {
+ return this->LibLinkFileFlag;
+ }
std::string const& GetRPathLinkFlag() const { return this->RPathLinkFlag; }
- std::string GetRPathLinkString();
+ std::string GetRPathLinkString() const;
std::string GetConfig() const { return this->Config; }
+
+ const cmGeneratorTarget* GetTarget() { return this->Target; }
+
private:
void AddItem(std::string const& item, const cmGeneratorTarget* tgt);
void AddSharedDepItem(std::string const& item, cmGeneratorTarget const* tgt);
@@ -78,13 +86,13 @@ private:
std::set<cmGeneratorTarget const*> SharedLibrariesLinked;
// Context information.
- cmGeneratorTarget const* Target;
- cmMakefile* Makefile;
- cmGlobalGenerator* GlobalGenerator;
- cmake* CMakeInstance;
+ cmGeneratorTarget const* const Target;
+ cmMakefile* const Makefile;
+ cmGlobalGenerator* const GlobalGenerator;
+ cmake* const CMakeInstance;
// Configuration information.
- std::string Config;
+ std::string const Config;
std::string LinkLanguage;
// Modes for dealing with dependent shared libraries.
@@ -183,7 +191,6 @@ private:
bool OldLinkDirMode;
bool OpenBSD;
bool LinkDependsNoShared;
- bool UseImportLibrary;
bool RuntimeUseChrpath;
bool NoSONameUsesPath;
bool LinkWithRuntimePath;
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index ff19eac63..162bab298 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -2,13 +2,21 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmComputeTargetDepends.h"
+#include <cassert>
+#include <cstdio>
+#include <sstream>
+#include <utility>
+
#include "cmComputeComponentGraph.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLinkItem.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateTypes.h"
@@ -17,13 +25,6 @@
#include "cmTargetDepend.h"
#include "cmake.h"
-#include <assert.h>
-#include <sstream>
-#include <stdio.h>
-#include <utility>
-
-class cmListFileBacktrace;
-
/*
This class is meant to analyze inter-target dependencies globally
@@ -103,9 +104,7 @@ cmComputeTargetDepends::cmComputeTargetDepends(cmGlobalGenerator* gg)
cm->GetState()->GetGlobalPropertyAsBool("GLOBAL_DEPENDS_NO_CYCLES");
}
-cmComputeTargetDepends::~cmComputeTargetDepends()
-{
-}
+cmComputeTargetDepends::~cmComputeTargetDepends() = default;
bool cmComputeTargetDepends::Compute()
{
@@ -141,17 +140,17 @@ void cmComputeTargetDepends::GetTargetDirectDepends(cmGeneratorTarget const* t,
{
// Lookup the index for this target. All targets should be known by
// this point.
- std::map<cmGeneratorTarget const*, int>::const_iterator tii =
- this->TargetIndex.find(t);
+ auto tii = this->TargetIndex.find(t);
assert(tii != this->TargetIndex.end());
int i = tii->second;
// Get its final dependencies.
EdgeList const& nl = this->FinalGraph[i];
- for (EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
- cmGeneratorTarget const* dep = this->Targets[*ni];
- cmTargetDependSet::iterator di = deps.insert(dep).first;
- di->SetType(ni->IsStrong());
+ for (cmGraphEdge const& ni : nl) {
+ cmGeneratorTarget const* dep = this->Targets[ni];
+ auto di = deps.insert(dep).first;
+ di->SetType(ni.IsStrong());
+ di->SetBacktrace(ni.GetBacktrace());
}
}
@@ -160,15 +159,13 @@ void cmComputeTargetDepends::CollectTargets()
// Collect all targets from all generators.
std::vector<cmLocalGenerator*> const& lgens =
this->GlobalGenerator->GetLocalGenerators();
- for (unsigned int i = 0; i < lgens.size(); ++i) {
- const std::vector<cmGeneratorTarget*> targets =
- lgens[i]->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::const_iterator ti = targets.begin();
- ti != targets.end(); ++ti) {
- cmGeneratorTarget* gt = *ti;
+ for (cmLocalGenerator* lgen : lgens) {
+ const std::vector<cmGeneratorTarget*>& targets =
+ lgen->GetGeneratorTargets();
+ for (cmGeneratorTarget const* ti : targets) {
int index = static_cast<int>(this->Targets.size());
- this->TargetIndex[gt] = index;
- this->Targets.push_back(gt);
+ this->TargetIndex[ti] = index;
+ this->Targets.push_back(ti);
}
}
}
@@ -197,48 +194,45 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
// dependencies in all targets, because the generated build-systems can't
// deal with config-specific dependencies.
{
- std::set<std::string> emitted;
+ std::set<cmLinkItem> emitted;
- std::vector<std::string> configs;
- depender->Makefile->GetConfigurations(configs);
- if (configs.empty()) {
- configs.push_back("");
- }
- for (std::vector<std::string>::const_iterator it = configs.begin();
- it != configs.end(); ++it) {
+ std::vector<std::string> const& configs =
+ depender->Makefile->GetGeneratorConfigs();
+ for (std::string const& it : configs) {
std::vector<cmSourceFile const*> objectFiles;
- depender->GetExternalObjects(objectFiles, *it);
- for (std::vector<cmSourceFile const*>::const_iterator oi =
- objectFiles.begin();
- oi != objectFiles.end(); ++oi) {
- std::string objLib = (*oi)->GetObjectLibrary();
- if (!objLib.empty() && emitted.insert(objLib).second) {
- if (depender->GetType() != cmStateEnums::EXECUTABLE &&
- depender->GetType() != cmStateEnums::STATIC_LIBRARY &&
- depender->GetType() != cmStateEnums::SHARED_LIBRARY &&
- depender->GetType() != cmStateEnums::MODULE_LIBRARY) {
- this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
- cmake::FATAL_ERROR,
- "Only executables and non-OBJECT libraries may "
- "reference target objects.",
- depender->GetBacktrace());
- return;
+ depender->GetExternalObjects(objectFiles, it);
+ for (cmSourceFile const* o : objectFiles) {
+ std::string const& objLib = o->GetObjectLibrary();
+ if (!objLib.empty()) {
+ cmLinkItem const& objItem =
+ depender->ResolveLinkItem(objLib, cmListFileBacktrace());
+ if (emitted.insert(objItem).second) {
+ if (depender->GetType() != cmStateEnums::EXECUTABLE &&
+ depender->GetType() != cmStateEnums::STATIC_LIBRARY &&
+ depender->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ depender->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ depender->GetType() != cmStateEnums::OBJECT_LIBRARY) {
+ this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "Only executables and libraries may reference target objects.",
+ depender->GetBacktrace());
+ return;
+ }
+ const_cast<cmGeneratorTarget*>(depender)->Target->AddUtility(
+ objLib);
}
- const_cast<cmGeneratorTarget*>(depender)->Target->AddUtility(objLib);
}
}
- cmLinkImplementation const* impl = depender->GetLinkImplementation(*it);
+ cmLinkImplementation const* impl = depender->GetLinkImplementation(it);
// A target should not depend on itself.
- emitted.insert(depender->GetName());
- for (std::vector<cmLinkImplItem>::const_iterator lib =
- impl->Libraries.begin();
- lib != impl->Libraries.end(); ++lib) {
+ emitted.insert(cmLinkItem(depender, cmListFileBacktrace()));
+ for (cmLinkImplItem const& lib : impl->Libraries) {
// Don't emit the same library twice for this target.
- if (emitted.insert(*lib).second) {
- this->AddTargetDepend(depender_index, *lib, true);
- this->AddInterfaceDepends(depender_index, *lib, *it, emitted);
+ if (emitted.insert(lib).second) {
+ this->AddTargetDepend(depender_index, lib, true);
+ this->AddInterfaceDepends(depender_index, lib, it, emitted);
}
}
}
@@ -247,14 +241,13 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
// Loop over all utility dependencies.
{
std::set<cmLinkItem> const& tutils = depender->GetUtilityItems();
- std::set<std::string> emitted;
+ std::set<cmLinkItem> emitted;
// A target should not depend on itself.
- emitted.insert(depender->GetName());
- for (std::set<cmLinkItem>::const_iterator util = tutils.begin();
- util != tutils.end(); ++util) {
+ emitted.insert(cmLinkItem(depender, cmListFileBacktrace()));
+ for (cmLinkItem const& litem : tutils) {
// Don't emit the same utility twice for this target.
- if (emitted.insert(*util).second) {
- this->AddTargetDepend(depender_index, *util, false);
+ if (emitted.insert(litem).second) {
+ this->AddTargetDepend(depender_index, litem, false);
}
}
}
@@ -262,18 +255,22 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
void cmComputeTargetDepends::AddInterfaceDepends(
int depender_index, const cmGeneratorTarget* dependee,
- const std::string& config, std::set<std::string>& emitted)
+ cmListFileBacktrace const& dependee_backtrace, const std::string& config,
+ std::set<cmLinkItem>& emitted)
{
cmGeneratorTarget const* depender = this->Targets[depender_index];
if (cmLinkInterface const* iface =
dependee->GetLinkInterface(config, depender)) {
- for (std::vector<cmLinkItem>::const_iterator lib =
- iface->Libraries.begin();
- lib != iface->Libraries.end(); ++lib) {
+ for (cmLinkItem const& lib : iface->Libraries) {
// Don't emit the same library twice for this target.
- if (emitted.insert(*lib).second) {
- this->AddTargetDepend(depender_index, *lib, true);
- this->AddInterfaceDepends(depender_index, *lib, config, emitted);
+ if (emitted.insert(lib).second) {
+ // Inject the backtrace of the original link dependency whose
+ // link interface we are adding. This indicates the line of
+ // code in the project that caused this dependency to be added.
+ cmLinkItem libBT = lib;
+ libBT.Backtrace = dependee_backtrace;
+ this->AddTargetDepend(depender_index, libBT, true);
+ this->AddInterfaceDepends(depender_index, libBT, config, emitted);
}
}
}
@@ -281,7 +278,7 @@ void cmComputeTargetDepends::AddInterfaceDepends(
void cmComputeTargetDepends::AddInterfaceDepends(
int depender_index, cmLinkItem const& dependee_name,
- const std::string& config, std::set<std::string>& emitted)
+ const std::string& config, std::set<cmLinkItem>& emitted)
{
cmGeneratorTarget const* depender = this->Targets[depender_index];
cmGeneratorTarget const* dependee = dependee_name.Target;
@@ -290,13 +287,14 @@ void cmComputeTargetDepends::AddInterfaceDepends(
// within the project.
if (dependee && dependee->GetType() == cmStateEnums::EXECUTABLE &&
!dependee->IsExecutableWithExports()) {
- dependee = CM_NULLPTR;
+ dependee = nullptr;
}
if (dependee) {
// A target should not depend on itself.
- emitted.insert(depender->GetName());
- this->AddInterfaceDepends(depender_index, dependee, config, emitted);
+ emitted.insert(cmLinkItem(depender, cmListFileBacktrace()));
+ this->AddInterfaceDepends(depender_index, dependee,
+ dependee_name.Backtrace, config, emitted);
}
}
@@ -312,7 +310,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index,
if (!dependee && !linking &&
(depender->GetType() != cmStateEnums::GLOBAL_TARGET)) {
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ MessageType messageType = MessageType::AUTHOR_WARNING;
bool issueMessage = false;
std::ostringstream e;
switch (depender->GetPolicyStatusCMP0046()) {
@@ -325,7 +323,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index,
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
issueMessage = true;
- messageType = cmake::FATAL_ERROR;
+ messageType = MessageType::FATAL_ERROR;
}
if (issueMessage) {
cmake* cm = this->GlobalGenerator->GetCMakeInstance();
@@ -333,13 +331,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index,
e << "The dependency target \"" << dependee_name << "\" of target \""
<< depender->GetName() << "\" does not exist.";
- cmListFileBacktrace const* backtrace =
- depender->GetUtilityBacktrace(dependee_name);
- if (backtrace) {
- cm->IssueMessage(messageType, e.str(), *backtrace);
- } else {
- cm->IssueMessage(messageType, e.str());
- }
+ cm->IssueMessage(messageType, e.str(), dependee_name.Backtrace);
}
}
@@ -348,40 +340,40 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index,
// within the project.
if (linking && dependee && dependee->GetType() == cmStateEnums::EXECUTABLE &&
!dependee->IsExecutableWithExports()) {
- dependee = CM_NULLPTR;
+ dependee = nullptr;
}
if (dependee) {
- this->AddTargetDepend(depender_index, dependee, linking);
+ this->AddTargetDepend(depender_index, dependee, dependee_name.Backtrace,
+ linking);
}
}
-void cmComputeTargetDepends::AddTargetDepend(int depender_index,
- const cmGeneratorTarget* dependee,
- bool linking)
+void cmComputeTargetDepends::AddTargetDepend(
+ int depender_index, cmGeneratorTarget const* dependee,
+ cmListFileBacktrace const& dependee_backtrace, bool linking)
{
if (dependee->IsImported() ||
dependee->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
// Skip IMPORTED and INTERFACE targets but follow their utility
// dependencies.
std::set<cmLinkItem> const& utils = dependee->GetUtilityItems();
- for (std::set<cmLinkItem>::const_iterator i = utils.begin();
- i != utils.end(); ++i) {
- if (cmGeneratorTarget const* transitive_dependee = i->Target) {
- this->AddTargetDepend(depender_index, transitive_dependee, false);
+ for (cmLinkItem const& i : utils) {
+ if (cmGeneratorTarget const* transitive_dependee = i.Target) {
+ this->AddTargetDepend(depender_index, transitive_dependee, i.Backtrace,
+ false);
}
}
} else {
// Lookup the index for this target. All targets should be known by
// this point.
- std::map<cmGeneratorTarget const*, int>::const_iterator tii =
- this->TargetIndex.find(dependee);
+ auto tii = this->TargetIndex.find(dependee);
assert(tii != this->TargetIndex.end());
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,
+ dependee_backtrace);
}
}
@@ -395,11 +387,11 @@ void cmComputeTargetDepends::DisplayGraph(Graph const& graph,
cmGeneratorTarget const* depender = this->Targets[depender_index];
fprintf(stderr, "target %d is [%s]\n", depender_index,
depender->GetName().c_str());
- for (EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
- int dependee_index = *ni;
+ for (cmGraphEdge const& ni : nl) {
+ int dependee_index = ni;
cmGeneratorTarget const* dependee = this->Targets[dependee_index];
fprintf(stderr, " depends on target %d [%s] (%s)\n", dependee_index,
- dependee->GetName().c_str(), ni->IsStrong() ? "strong" : "weak");
+ dependee->GetName().c_str(), ni.IsStrong() ? "strong" : "weak");
}
}
fprintf(stderr, "\n");
@@ -414,8 +406,7 @@ void cmComputeTargetDepends::DisplayComponents(
for (int c = 0; c < n; ++c) {
NodeList const& nl = components[c];
fprintf(stderr, "Component (%d):\n", c);
- for (NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
- int i = *ni;
+ for (int i : nl) {
fprintf(stderr, " contains target %d [%s]\n", i,
this->Targets[i]->GetName().c_str());
}
@@ -446,8 +437,8 @@ bool cmComputeTargetDepends::CheckComponents(
}
// Make sure the component is all STATIC_LIBRARY targets.
- for (NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
- if (this->Targets[*ni]->GetType() != cmStateEnums::STATIC_LIBRARY) {
+ for (int ni : nl) {
+ if (this->Targets[ni]->GetType() != cmStateEnums::STATIC_LIBRARY) {
this->ComplainAboutBadComponent(ccg, c);
return false;
}
@@ -466,9 +457,8 @@ void cmComputeTargetDepends::ComplainAboutBadComponent(
std::vector<NodeList> const& components = ccg.GetComponents();
std::vector<int> const& cmap = ccg.GetComponentMap();
NodeList const& cl = components[c];
- for (NodeList::const_iterator ci = cl.begin(); ci != cl.end(); ++ci) {
+ for (int i : cl) {
// Get the depender.
- int i = *ci;
cmGeneratorTarget const* depender = this->Targets[i];
// Describe the depender.
@@ -477,12 +467,12 @@ void cmComputeTargetDepends::ComplainAboutBadComponent(
// List its dependencies that are inside the component.
EdgeList const& nl = this->InitialGraph[i];
- for (EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
- int j = *ni;
+ for (cmGraphEdge const& ni : nl) {
+ int j = ni;
if (cmap[j] == c) {
cmGeneratorTarget const* dependee = this->Targets[j];
e << " depends on \"" << dependee->GetName() << "\""
- << " (" << (ni->IsStrong() ? "strong" : "weak") << ")\n";
+ << " (" << (ni.IsStrong() ? "strong" : "weak") << ")\n";
}
}
}
@@ -499,7 +489,7 @@ void cmComputeTargetDepends::ComplainAboutBadComponent(
e << "At least one of these targets is not a STATIC_LIBRARY. "
<< "Cyclic dependencies are allowed only among static libraries.";
}
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
}
bool cmComputeTargetDepends::IntraComponent(std::vector<int> const& cmap,
@@ -514,10 +504,10 @@ bool cmComputeTargetDepends::IntraComponent(std::vector<int> const& cmap,
if (emitted.insert(i).second) {
// Honor strong intra-component edges in the final order.
EdgeList const& el = this->InitialGraph[i];
- for (EdgeList::const_iterator ei = el.begin(); ei != el.end(); ++ei) {
- int j = *ei;
- if (cmap[j] == c && ei->IsStrong()) {
- this->FinalGraph[i].push_back(cmGraphEdge(j, true));
+ for (cmGraphEdge const& edge : el) {
+ int j = edge;
+ if (cmap[j] == c && edge.IsStrong()) {
+ this->FinalGraph[i].emplace_back(j, true, edge.GetBacktrace());
if (!this->IntraComponent(cmap, c, j, head, emitted, visited)) {
return false;
}
@@ -526,7 +516,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, cmListFileBacktrace());
} else {
this->ComponentTail[c] = i;
}
@@ -555,10 +545,9 @@ bool cmComputeTargetDepends::ComputeFinalDepends(
int head = -1;
std::set<int> emitted;
NodeList const& nl = components[c];
- for (NodeList::const_reverse_iterator ni = nl.rbegin(); ni != nl.rend();
- ++ni) {
+ for (int ni : cmReverseRange(nl)) {
std::set<int> visited;
- if (!this->IntraComponent(cmap, c, *ni, &head, emitted, visited)) {
+ if (!this->IntraComponent(cmap, c, ni, &head, emitted, visited)) {
// Cycle in add_dependencies within component!
this->ComplainAboutBadComponent(ccg, c, true);
return false;
@@ -573,11 +562,11 @@ bool cmComputeTargetDepends::ComputeFinalDepends(
++depender_component) {
int depender_component_tail = this->ComponentTail[depender_component];
EdgeList const& nl = cgraph[depender_component];
- for (EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) {
- int dependee_component = *ni;
+ 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(), ni.GetBacktrace());
}
}
return true;
diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h
index e93e376ce..d8060aede 100644
--- a/Source/cmComputeTargetDepends.h
+++ b/Source/cmComputeTargetDepends.h
@@ -5,13 +5,14 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmGraphAdjacencyList.h"
-
#include <map>
#include <set>
#include <string>
#include <vector>
+#include "cmGraphAdjacencyList.h"
+#include "cmListFileCache.h"
+
class cmComputeComponentGraph;
class cmGeneratorTarget;
class cmGlobalGenerator;
@@ -47,15 +48,17 @@ private:
void AddTargetDepend(int depender_index, cmLinkItem const& dependee_name,
bool linking);
void AddTargetDepend(int depender_index, cmGeneratorTarget const* dependee,
+ cmListFileBacktrace const& dependee_backtrace,
bool linking);
bool ComputeFinalDepends(cmComputeComponentGraph const& ccg);
void AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name,
const std::string& config,
- std::set<std::string>& emitted);
+ std::set<cmLinkItem>& emitted);
void AddInterfaceDepends(int depender_index,
cmGeneratorTarget const* dependee,
+ cmListFileBacktrace const& dependee_backtrace,
const std::string& config,
- std::set<std::string>& emitted);
+ std::set<cmLinkItem>& emitted);
cmGlobalGenerator* GlobalGenerator;
bool DebugMode;
bool NoCycles;
@@ -67,9 +70,9 @@ private:
// Represent the target dependency graph. The entry at each
// top-level index corresponds to a depender whose dependencies are
// listed.
- typedef cmGraphNodeList NodeList;
- typedef cmGraphEdgeList EdgeList;
- typedef cmGraphAdjacencyList Graph;
+ using NodeList = cmGraphNodeList;
+ using EdgeList = cmGraphEdgeList;
+ using Graph = cmGraphAdjacencyList;
Graph InitialGraph;
Graph FinalGraph;
void DisplayGraph(Graph const& graph, const std::string& name);
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
index 2bacf7321..003e60d57 100644
--- a/Source/cmConditionEvaluator.cxx
+++ b/Source/cmConditionEvaluator.cxx
@@ -2,20 +2,23 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmConditionEvaluator.h"
-#include "cmConfigure.h"
-#include "cmsys/RegularExpression.hxx"
-#include <algorithm>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <functional>
#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <utility>
+
+#include "cmsys/RegularExpression.hxx"
#include "cmAlgorithms.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmState.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmake.h"
-class cmCommand;
class cmTest;
static std::string const keyAND = "AND";
@@ -52,11 +55,11 @@ static std::string const keyVERSION_LESS = "VERSION_LESS";
static std::string const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL";
cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile,
- const cmListFileContext& context,
- const cmListFileBacktrace& bt)
+ cmListFileContext context,
+ cmListFileBacktrace bt)
: Makefile(makefile)
- , ExecutionContext(context)
- , Backtrace(bt)
+ , ExecutionContext(std::move(context))
+ , Backtrace(std::move(bt))
, Policy12Status(makefile.GetPolicyStatus(cmPolicies::CMP0012))
, Policy54Status(makefile.GetPolicyStatus(cmPolicies::CMP0054))
, Policy57Status(makefile.GetPolicyStatus(cmPolicies::CMP0057))
@@ -82,9 +85,9 @@ cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile,
bool cmConditionEvaluator::IsTrue(
const std::vector<cmExpandedCommandArgument>& args, std::string& errorString,
- cmake::MessageType& status)
+ MessageType& status)
{
- errorString = "";
+ errorString.clear();
// handle empty invocation
if (args.empty()) {
@@ -92,10 +95,7 @@ bool cmConditionEvaluator::IsTrue(
}
// store the reduced args in this vector
- cmArgumentList newArgs;
-
- // copy to the list structure
- newArgs.insert(newArgs.end(), args.begin(), args.end());
+ cmArgumentList newArgs(args.begin(), args.end());
// now loop through the arguments and see if we can reduce any of them
// we do this multiple times. Once for each level of precedence
@@ -124,12 +124,12 @@ bool cmConditionEvaluator::IsTrue(
// now at the end there should only be one argument left
if (newArgs.size() != 1) {
errorString = "Unknown arguments specified";
- status = cmake::FATAL_ERROR;
+ status = MessageType::FATAL_ERROR;
return false;
}
- return this->GetBooleanValueWithAutoDereference(*(newArgs.begin()),
- errorString, status, true);
+ return this->GetBooleanValueWithAutoDereference(newArgs.front(), errorString,
+ status, true);
}
//=========================================================================
@@ -139,7 +139,7 @@ const char* cmConditionEvaluator::GetDefinitionIfUnquoted(
if ((this->Policy54Status != cmPolicies::WARN &&
this->Policy54Status != cmPolicies::OLD) &&
argument.WasQuoted()) {
- return CM_NULLPTR;
+ return nullptr;
}
const char* def = this->Makefile.GetDefinition(argument.GetValue());
@@ -156,7 +156,7 @@ const char* cmConditionEvaluator::GetDefinitionIfUnquoted(
"Since the policy is not set the OLD behavior will be used.";
this->Makefile.GetCMakeInstance()->IssueMessage(
- cmake::AUTHOR_WARNING, e.str(), this->Backtrace);
+ MessageType::AUTHOR_WARNING, e.str(), this->Backtrace);
}
}
@@ -200,7 +200,7 @@ bool cmConditionEvaluator::IsKeyword(std::string const& keyword,
"Since the policy is not set the OLD behavior will be used.";
this->Makefile.GetCMakeInstance()->IssueMessage(
- cmake::AUTHOR_WARNING, e.str(), this->Backtrace);
+ MessageType::AUTHOR_WARNING, e.str(), this->Backtrace);
}
}
@@ -220,10 +220,10 @@ bool cmConditionEvaluator::GetBooleanValue(
}
// Check named constants.
- if (cmSystemTools::IsOn(arg.c_str())) {
+ if (cmIsOn(arg.GetValue())) {
return true;
}
- if (cmSystemTools::IsOff(arg.c_str())) {
+ if (cmIsOff(arg.GetValue())) {
return false;
}
@@ -239,7 +239,7 @@ bool cmConditionEvaluator::GetBooleanValue(
// Check definition.
const char* def = this->GetDefinitionIfUnquoted(arg);
- return !cmSystemTools::IsOff(def);
+ return !cmIsOff(def);
}
//=========================================================================
@@ -256,21 +256,21 @@ bool cmConditionEvaluator::GetBooleanValueOld(
return true;
}
const char* def = this->GetDefinitionIfUnquoted(arg);
- return !cmSystemTools::IsOff(def);
+ return !cmIsOff(def);
}
// Old GetVariableOrNumber behavior.
const char* def = this->GetDefinitionIfUnquoted(arg);
if (!def && atoi(arg.c_str())) {
def = arg.c_str();
}
- return !cmSystemTools::IsOff(def);
+ return !cmIsOff(def);
}
//=========================================================================
// returns the resulting boolean value
bool cmConditionEvaluator::GetBooleanValueWithAutoDereference(
cmExpandedCommandArgument& newArg, std::string& errorString,
- cmake::MessageType& status, bool oneArg) const
+ MessageType& status, bool oneArg) const
{
// Use the policy if it is set.
if (this->Policy12Status == cmPolicies::NEW) {
@@ -289,7 +289,7 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference(
errorString = "An argument named \"" + newArg.GetValue() +
"\" appears in a conditional statement. " +
cmPolicies::GetPolicyWarning(cmPolicies::CMP0012);
- status = cmake::AUTHOR_WARNING;
+ status = MessageType::AUTHOR_WARNING;
CM_FALLTHROUGH;
case cmPolicies::OLD:
return oldResult;
@@ -298,7 +298,7 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference(
errorString = "An argument named \"" + newArg.GetValue() +
"\" appears in a conditional statement. " +
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0012);
- status = cmake::FATAL_ERROR;
+ status = MessageType::FATAL_ERROR;
}
case cmPolicies::NEW:
break;
@@ -363,12 +363,12 @@ void cmConditionEvaluator::HandleBinaryOp(bool value, int& reducible,
// level 0 processes parenthetical expressions
bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs,
std::string& errorString,
- cmake::MessageType& status)
+ MessageType& status)
{
int reducible;
do {
reducible = 0;
- cmArgumentList::iterator arg = newArgs.begin();
+ auto arg = newArgs.begin();
while (arg != newArgs.end()) {
if (IsKeyword(keyParenL, *arg)) {
// search for the closing paren for this opening one
@@ -387,16 +387,16 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs,
}
if (depth) {
errorString = "mismatched parenthesis in condition";
- status = cmake::FATAL_ERROR;
+ status = MessageType::FATAL_ERROR;
return false;
}
// store the reduced args in this vector
std::vector<cmExpandedCommandArgument> newArgs2;
// copy to the list structure
- cmArgumentList::iterator argP1 = arg;
+ auto argP1 = arg;
argP1++;
- newArgs2.insert(newArgs2.end(), argP1, argClose);
+ cmAppend(newArgs2, argP1, argClose);
newArgs2.pop_back();
// now recursively invoke IsTrue to handle the values inside the
// parenthetical expression
@@ -420,12 +420,12 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs,
//=========================================================================
// level one handles most predicates except for NOT
bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,
- cmake::MessageType&)
+ MessageType&)
{
int reducible;
do {
reducible = 0;
- cmArgumentList::iterator arg = newArgs.begin();
+ auto arg = newArgs.begin();
cmArgumentList::iterator argP1;
cmArgumentList::iterator argP2;
while (arg != newArgs.end()) {
@@ -453,9 +453,9 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,
}
// does a command exist
if (this->IsKeyword(keyCOMMAND, *arg) && argP1 != newArgs.end()) {
- cmCommand* command =
+ cmState::Command command =
this->Makefile.GetState()->GetCommand(argP1->c_str());
- this->HandlePredicate(command != CM_NULLPTR, reducible, arg, newArgs,
+ this->HandlePredicate(command != nullptr, reducible, arg, newArgs,
argP1, argP2);
}
// does a policy exist
@@ -467,7 +467,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,
// does a target exist
if (this->IsKeyword(keyTARGET, *arg) && argP1 != newArgs.end()) {
this->HandlePredicate(
- this->Makefile.FindTargetToUse(argP1->GetValue()) != CM_NULLPTR,
+ this->Makefile.FindTargetToUse(argP1->GetValue()) != nullptr,
reducible, arg, newArgs, argP1, argP2);
}
// does a test exist
@@ -475,8 +475,8 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,
this->Policy64Status != cmPolicies::WARN) {
if (this->IsKeyword(keyTEST, *arg) && argP1 != newArgs.end()) {
const cmTest* haveTest = this->Makefile.GetTest(argP1->c_str());
- this->HandlePredicate(haveTest != CM_NULLPTR, reducible, arg,
- newArgs, argP1, argP2);
+ this->HandlePredicate(haveTest != nullptr, reducible, arg, newArgs,
+ argP1, argP2);
}
} else if (this->Policy64Status == cmPolicies::WARN &&
this->IsKeyword(keyTEST, *arg)) {
@@ -486,7 +486,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,
"when the policy is set to NEW. "
"Since the policy is not set the OLD behavior will be used.";
- this->Makefile.IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
}
// is a variable defined
if (this->IsKeyword(keyDEFINED, *arg) && argP1 != newArgs.end()) {
@@ -495,7 +495,13 @@ 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 if (argP1len > 6 &&
+ argP1->GetValue().substr(0, 6) == "CACHE{" &&
+ argP1->GetValue().operator[](argP1len - 1) == '}') {
+ std::string cache = argP1->GetValue().substr(6, argP1len - 7);
+ bdef =
+ this->Makefile.GetState()->GetCacheEntryValue(cache) != nullptr;
} else {
bdef = this->Makefile.IsDefinitionSet(argP1->GetValue());
}
@@ -511,7 +517,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,
// level two handles most binary operations except for AND OR
bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
std::string& errorString,
- cmake::MessageType& status)
+ MessageType& status)
{
int reducible;
std::string def_buf;
@@ -519,7 +525,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
const char* def2;
do {
reducible = 0;
- cmArgumentList::iterator arg = newArgs.begin();
+ auto arg = newArgs.begin();
cmArgumentList::iterator argP1;
cmArgumentList::iterator argP2;
while (arg != newArgs.end()) {
@@ -542,7 +548,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
std::ostringstream error;
error << "Regular expression \"" << rex << "\" cannot compile";
errorString = error.str();
- status = cmake::FATAL_ERROR;
+ status = MessageType::FATAL_ERROR;
return false;
}
if (regEntry.find(def)) {
@@ -663,10 +669,9 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
def2 = this->Makefile.GetDefinition(argP2->GetValue());
if (def2) {
- std::vector<std::string> list;
- cmSystemTools::ExpandListArgument(def2, list, true);
+ std::vector<std::string> list = cmExpandedList(def2, true);
- result = std::find(list.begin(), list.end(), def) != list.end();
+ result = cmContains(list, def);
}
this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2);
@@ -677,7 +682,7 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
"when the policy is set to NEW. "
"Since the policy is not set the OLD behavior will be used.";
- this->Makefile.IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
}
}
@@ -691,12 +696,12 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
// level 3 handles NOT
bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs,
std::string& errorString,
- cmake::MessageType& status)
+ MessageType& status)
{
int reducible;
do {
reducible = 0;
- cmArgumentList::iterator arg = newArgs.begin();
+ auto arg = newArgs.begin();
cmArgumentList::iterator argP1;
cmArgumentList::iterator argP2;
while (arg != newArgs.end()) {
@@ -717,14 +722,14 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs,
// level 4 handles AND OR
bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs,
std::string& errorString,
- cmake::MessageType& status)
+ MessageType& status)
{
int reducible;
bool lhs;
bool rhs;
do {
reducible = 0;
- cmArgumentList::iterator arg = newArgs.begin();
+ auto arg = newArgs.begin();
cmArgumentList::iterator argP1;
cmArgumentList::iterator argP2;
while (arg != newArgs.end()) {
diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h
index 50f4edc4f..082534ce8 100644
--- a/Source/cmConditionEvaluator.h
+++ b/Source/cmConditionEvaluator.h
@@ -11,24 +11,24 @@
#include "cmExpandedCommandArgument.h"
#include "cmListFileCache.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmake.h"
class cmMakefile;
class cmConditionEvaluator
{
public:
- typedef std::list<cmExpandedCommandArgument> cmArgumentList;
+ using cmArgumentList = std::list<cmExpandedCommandArgument>;
- cmConditionEvaluator(cmMakefile& makefile, cmListFileContext const& context,
- cmListFileBacktrace const& bt);
+ cmConditionEvaluator(cmMakefile& makefile, cmListFileContext context,
+ cmListFileBacktrace bt);
// this is a shared function for both If and Else to determine if the
// arguments were valid, and if so, was the response true. If there is
// an error, the errorString will be set.
bool IsTrue(const std::vector<cmExpandedCommandArgument>& args,
- std::string& errorString, cmake::MessageType& status);
+ std::string& errorString, MessageType& status);
private:
// Filter the given variable definition based on policy CMP0054.
@@ -48,7 +48,7 @@ private:
bool GetBooleanValueWithAutoDereference(cmExpandedCommandArgument& newArg,
std::string& errorString,
- cmake::MessageType& status,
+ MessageType& status,
bool oneArg = false) const;
void IncrementArguments(cmArgumentList& newArgs,
@@ -66,19 +66,18 @@ private:
cmArgumentList::iterator& argP2);
bool HandleLevel0(cmArgumentList& newArgs, std::string& errorString,
- cmake::MessageType& status);
+ MessageType& status);
- bool HandleLevel1(cmArgumentList& newArgs, std::string&,
- cmake::MessageType&);
+ bool HandleLevel1(cmArgumentList& newArgs, std::string&, MessageType&);
bool HandleLevel2(cmArgumentList& newArgs, std::string& errorString,
- cmake::MessageType& status);
+ MessageType& status);
bool HandleLevel3(cmArgumentList& newArgs, std::string& errorString,
- cmake::MessageType& status);
+ MessageType& status);
bool HandleLevel4(cmArgumentList& newArgs, std::string& errorString,
- cmake::MessageType& status);
+ MessageType& status);
cmMakefile& Makefile;
cmListFileContext ExecutionContext;
diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in
index 524fdf808..4de1c5d6f 100644
--- a/Source/cmConfigure.cmake.h.in
+++ b/Source/cmConfigure.cmake.h.in
@@ -19,51 +19,15 @@
#cmakedefine HAVE_UNSETENV
#cmakedefine CMAKE_USE_ELF_PARSER
#cmakedefine CMAKE_USE_MACH_PARSER
-#cmakedefine CMAKE_USE_LIBUV
-#cmakedefine CMake_HAVE_CXX_AUTO_PTR
-#cmakedefine CMake_HAVE_CXX_EQ_DELETE
-#cmakedefine CMake_HAVE_CXX_FALLTHROUGH
-#cmakedefine CMake_HAVE_CXX_GNU_FALLTHROUGH
-#cmakedefine CMake_HAVE_CXX_ATTRIBUTE_FALLTHROUGH
#cmakedefine CMake_HAVE_CXX_MAKE_UNIQUE
-#cmakedefine CMake_HAVE_CXX_NULLPTR
-#cmakedefine CMake_HAVE_CXX_OVERRIDE
-#cmakedefine CMake_HAVE_CXX_UNIQUE_PTR
-#cmakedefine CMake_HAVE_CXX_UNORDERED_MAP
-#cmakedefine CMake_HAVE_CXX_UNORDERED_SET
+#define CMake_DEFAULT_RECURSION_LIMIT @CMake_DEFAULT_RECURSION_LIMIT@
#define CMAKE_BIN_DIR "/@CMAKE_BIN_DIR@"
#define CMAKE_DATA_DIR "/@CMAKE_DATA_DIR@"
-#ifdef CMake_HAVE_CXX_EQ_DELETE
-#define CM_EQ_DELETE = delete
-#else
-#define CM_EQ_DELETE
-#endif
-
-#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
-#ifdef CMake_HAVE_CXX_NULLPTR
-#define CM_NULLPTR nullptr
-#else
-#define CM_NULLPTR 0
+#if defined(_WIN32) && !defined(NOMINMAX)
+# define NOMINMAX
#endif
-#ifdef CMake_HAVE_CXX_OVERRIDE
-#define CM_OVERRIDE override
-#else
-#define CM_OVERRIDE
-#endif
-
-#define CM_DISABLE_COPY(Class) \
- Class(Class const&) CM_EQ_DELETE; \
- Class& operator=(Class const&) CM_EQ_DELETE;
-
#endif
diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx
index 18005f27c..8767386cf 100644
--- a/Source/cmConfigureFileCommand.cxx
+++ b/Source/cmConfigureFileCommand.cxx
@@ -2,84 +2,74 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmConfigureFileCommand.h"
-#include <sstream>
-
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmNewLineStyle.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmake.h"
-
-class cmExecutionStatus;
// cmConfigureFileCommand
-bool cmConfigureFileCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmConfigureFileCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("called with incorrect number of arguments, expected 2");
+ status.SetError("called with incorrect number of arguments, expected 2");
return false;
}
std::string const& inFile = args[0];
- if (!cmSystemTools::FileIsFullPath(inFile)) {
- this->InputFile = this->Makefile->GetCurrentSourceDirectory();
- this->InputFile += "/";
- }
- this->InputFile += inFile;
+ const std::string inputFile = cmSystemTools::CollapseFullPath(
+ inFile, status.GetMakefile().GetCurrentSourceDirectory());
// If the input location is a directory, error out.
- if (cmSystemTools::FileIsDirectory(this->InputFile)) {
- std::ostringstream e;
- /* clang-format off */
- e << "input location\n"
- << " " << this->InputFile << "\n"
- << "is a directory but a file was expected.";
- /* clang-format on */
- this->SetError(e.str());
+ if (cmSystemTools::FileIsDirectory(inputFile)) {
+ status.SetError(cmStrCat("input location\n ", inputFile,
+ "\n"
+ "is a directory but a file was expected."));
return false;
}
std::string const& outFile = args[1];
- if (!cmSystemTools::FileIsFullPath(outFile)) {
- this->OutputFile = this->Makefile->GetCurrentBinaryDirectory();
- this->OutputFile += "/";
- }
- this->OutputFile += outFile;
+ std::string outputFile = cmSystemTools::CollapseFullPath(
+ outFile, status.GetMakefile().GetCurrentBinaryDirectory());
// If the output location is already a directory put the file in it.
- if (cmSystemTools::FileIsDirectory(this->OutputFile)) {
- this->OutputFile += "/";
- this->OutputFile += cmSystemTools::GetFilenameName(inFile);
+ if (cmSystemTools::FileIsDirectory(outputFile)) {
+ outputFile += "/";
+ outputFile += cmSystemTools::GetFilenameName(inFile);
}
- if (!this->Makefile->CanIWriteThisFile(this->OutputFile.c_str())) {
- std::string e = "attempted to configure a file: " + this->OutputFile +
+ if (!status.GetMakefile().CanIWriteThisFile(outputFile)) {
+ std::string e = "attempted to configure a file: " + outputFile +
" into a source directory.";
- this->SetError(e);
+ status.SetError(e);
cmSystemTools::SetFatalErrorOccured();
return false;
}
std::string errorMessage;
- if (!this->NewLineStyle.ReadFromArguments(args, errorMessage)) {
- this->SetError(errorMessage);
+ cmNewLineStyle newLineStyle;
+ if (!newLineStyle.ReadFromArguments(args, errorMessage)) {
+ status.SetError(errorMessage);
return false;
}
- this->CopyOnly = false;
- this->EscapeQuotes = false;
+ bool copyOnly = false;
+ bool escapeQuotes = false;
std::string unknown_args;
- this->AtOnly = false;
+ bool atOnly = false;
for (unsigned int i = 2; i < args.size(); ++i) {
if (args[i] == "COPYONLY") {
- this->CopyOnly = true;
- if (this->NewLineStyle.IsValid()) {
- this->SetError("COPYONLY could not be used in combination "
- "with NEWLINE_STYLE");
+ copyOnly = true;
+ if (newLineStyle.IsValid()) {
+ status.SetError("COPYONLY could not be used in combination "
+ "with NEWLINE_STYLE");
return false;
}
} else if (args[i] == "ESCAPE_QUOTES") {
- this->EscapeQuotes = true;
+ escapeQuotes = true;
} else if (args[i] == "@ONLY") {
- this->AtOnly = true;
+ atOnly = true;
} else if (args[i] == "IMMEDIATE") {
/* Ignore legacy option. */
} else if (args[i] == "NEWLINE_STYLE" || args[i] == "LF" ||
@@ -93,22 +83,16 @@ bool cmConfigureFileCommand::InitialPass(std::vector<std::string> const& args,
}
}
if (!unknown_args.empty()) {
- std::string msg = "configure_file called with unknown argument(s):\n";
- msg += unknown_args;
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, msg);
+ std::string msg = cmStrCat(
+ "configure_file called with unknown argument(s):\n", unknown_args);
+ status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, msg);
}
- if (!this->ConfigureFile()) {
- this->SetError("Problem configuring file");
+ if (!status.GetMakefile().ConfigureFile(
+ inputFile, outputFile, copyOnly, atOnly, escapeQuotes, newLineStyle)) {
+ status.SetError("Problem configuring file");
return false;
}
return true;
}
-
-int cmConfigureFileCommand::ConfigureFile()
-{
- return this->Makefile->ConfigureFile(
- this->InputFile.c_str(), this->OutputFile.c_str(), this->CopyOnly,
- this->AtOnly, this->EscapeQuotes, this->NewLineStyle);
-}
diff --git a/Source/cmConfigureFileCommand.h b/Source/cmConfigureFileCommand.h
index 6cebbd258..c7f95b852 100644
--- a/Source/cmConfigureFileCommand.h
+++ b/Source/cmConfigureFileCommand.h
@@ -3,38 +3,13 @@
#ifndef cmConfigureFileCommand_h
#define cmConfigureFileCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-#include "cmNewLineStyle.h"
-
class cmExecutionStatus;
-class cmConfigureFileCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE { return new cmConfigureFileCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the input file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- int ConfigureFile();
-
- cmNewLineStyle NewLineStyle;
-
- std::string InputFile;
- std::string OutputFile;
- bool CopyOnly;
- bool EscapeQuotes;
- bool AtOnly;
-};
-
+bool cmConfigureFileCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmConnection.cxx b/Source/cmConnection.cxx
new file mode 100644
index 000000000..884e31432
--- /dev/null
+++ b/Source/cmConnection.cxx
@@ -0,0 +1,164 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmConnection.h"
+
+#include <cassert>
+#include <cstring>
+
+#include "cm_uv.h"
+
+#include "cmServer.h"
+
+struct write_req_t
+{
+ uv_write_t req;
+ uv_buf_t buf;
+};
+
+void cmEventBasedConnection::on_alloc_buffer(uv_handle_t* handle,
+ size_t suggested_size,
+ uv_buf_t* buf)
+{
+ (void)(handle);
+ char* rawBuffer = new char[suggested_size];
+ *buf = uv_buf_init(rawBuffer, static_cast<unsigned int>(suggested_size));
+}
+
+void cmEventBasedConnection::on_read(uv_stream_t* stream, ssize_t nread,
+ const uv_buf_t* buf)
+{
+ auto conn = static_cast<cmEventBasedConnection*>(stream->data);
+ if (conn) {
+ if (nread >= 0) {
+ conn->ReadData(std::string(buf->base, buf->base + nread));
+ } else {
+ conn->OnDisconnect(static_cast<int>(nread));
+ }
+ }
+
+ delete[](buf->base);
+}
+
+void cmEventBasedConnection::on_close(uv_handle_t* /*handle*/)
+{
+}
+
+void cmEventBasedConnection::on_write(uv_write_t* req, int status)
+{
+ (void)(status);
+
+ // Free req and buffer
+ write_req_t* wr = reinterpret_cast<write_req_t*>(req);
+ delete[](wr->buf.base);
+ delete wr;
+}
+
+void cmEventBasedConnection::on_new_connection(uv_stream_t* stream, int status)
+{
+ (void)(status);
+ auto conn = static_cast<cmEventBasedConnection*>(stream->data);
+
+ if (conn) {
+ conn->Connect(stream);
+ }
+}
+
+bool cmEventBasedConnection::IsOpen() const
+{
+ return this->WriteStream != nullptr;
+}
+
+void cmEventBasedConnection::WriteData(const std::string& _data)
+{
+#ifndef NDEBUG
+ auto curr_thread_id = uv_thread_self();
+ assert(this->Server);
+ assert(uv_thread_equal(&curr_thread_id, &this->Server->ServeThreadId));
+#endif
+
+ auto data = _data;
+ assert(this->WriteStream.get());
+ if (BufferStrategy) {
+ data = BufferStrategy->BufferOutMessage(data);
+ }
+
+ auto ds = data.size();
+
+ write_req_t* req = new write_req_t;
+ 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), this->WriteStream, &req->buf, 1,
+ on_write);
+}
+
+void cmEventBasedConnection::ReadData(const std::string& data)
+{
+ this->RawReadBuffer += data;
+ if (BufferStrategy) {
+ std::string packet = BufferStrategy->BufferMessage(this->RawReadBuffer);
+ while (!packet.empty()) {
+ ProcessRequest(packet);
+ packet = BufferStrategy->BufferMessage(this->RawReadBuffer);
+ }
+ } else {
+ ProcessRequest(this->RawReadBuffer);
+ this->RawReadBuffer.clear();
+ }
+}
+
+cmEventBasedConnection::cmEventBasedConnection(
+ cmConnectionBufferStrategy* bufferStrategy)
+ : BufferStrategy(bufferStrategy)
+{
+}
+
+void cmEventBasedConnection::Connect(uv_stream_t* server)
+{
+ (void)server;
+ Server->OnConnected(nullptr);
+}
+
+void cmEventBasedConnection::OnDisconnect(int onerror)
+{
+ (void)onerror;
+ this->OnConnectionShuttingDown();
+ if (this->Server) {
+ this->Server->OnDisconnect(this);
+ }
+}
+
+cmConnection::~cmConnection() = default;
+
+bool cmConnection::OnConnectionShuttingDown()
+{
+ this->Server = nullptr;
+ return true;
+}
+
+void cmConnection::SetServer(cmServerBase* s)
+{
+ Server = s;
+}
+
+void cmConnection::ProcessRequest(const std::string& request)
+{
+ Server->ProcessRequest(this, request);
+}
+
+bool cmConnection::OnServeStart(std::string* errString)
+{
+ (void)errString;
+ return true;
+}
+
+bool cmEventBasedConnection::OnConnectionShuttingDown()
+{
+ if (this->WriteStream.get()) {
+ this->WriteStream->data = nullptr;
+ }
+
+ WriteStream.reset();
+
+ return true;
+}
diff --git a/Source/cmConnection.h b/Source/cmConnection.h
new file mode 100644
index 000000000..7bb249404
--- /dev/null
+++ b/Source/cmConnection.h
@@ -0,0 +1,137 @@
+/* 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 <cstddef>
+#include <memory>
+#include <string>
+
+#include "cm_uv.h"
+
+#include "cmUVHandlePtr.h"
+
+class cmServerBase;
+
+/***
+ * Given a sequence of bytes with any kind of buffering, instances of this
+ * class arrange logical chunks according to whatever the use case is for
+ * the connection.
+ */
+class cmConnectionBufferStrategy
+{
+public:
+ virtual ~cmConnectionBufferStrategy();
+
+ /***
+ * Called whenever with an active raw buffer. If a logical chunk
+ * becomes available, that chunk is returned and that portion is
+ * removed from the rawBuffer
+ *
+ * @param rawBuffer in/out parameter. Receive buffer; the buffer strategy is
+ * free to manipulate this buffer anyway it needs to.
+ *
+ * @return Next chunk from the stream. Returns the empty string if a chunk
+ * isn't ready yet. Users of this interface should repeatedly call this
+ * function until an empty string is returned since its entirely possible
+ * multiple chunks come in a single raw buffer.
+ */
+ virtual std::string BufferMessage(std::string& rawBuffer) = 0;
+
+ /***
+ * Called to properly buffer an outgoing message.
+ *
+ * @param rawBuffer Message to format in the correct way
+ *
+ * @return Formatted message
+ */
+ virtual std::string BufferOutMessage(const std::string& rawBuffer) const
+ {
+ return rawBuffer;
+ };
+ /***
+ * Resets the internal state of the buffering
+ */
+ virtual void clear();
+
+ // TODO: There should be a callback / flag set for errors
+};
+
+class cmConnection
+{
+public:
+ cmConnection() = default;
+
+ cmConnection(cmConnection const&) = delete;
+ cmConnection& operator=(cmConnection const&) = delete;
+
+ virtual void WriteData(const std::string& data) = 0;
+
+ virtual ~cmConnection();
+
+ virtual bool OnConnectionShuttingDown();
+
+ virtual bool IsOpen() const = 0;
+
+ virtual void SetServer(cmServerBase* s);
+
+ virtual void ProcessRequest(const std::string& request);
+
+ virtual bool OnServeStart(std::string* pString);
+
+protected:
+ cmServerBase* Server = nullptr;
+};
+
+/***
+ * Abstraction of a connection; ties in event callbacks from libuv and notifies
+ * the server when appropriate
+ */
+class cmEventBasedConnection : public cmConnection
+{
+
+public:
+ /***
+ * @param bufferStrategy If no strategy is given, it will process the raw
+ * chunks as they come in. The connection
+ * owns the pointer given.
+ */
+ cmEventBasedConnection(cmConnectionBufferStrategy* bufferStrategy = nullptr);
+
+ virtual void Connect(uv_stream_t* server);
+
+ virtual void ReadData(const std::string& data);
+
+ bool IsOpen() const override;
+
+ void WriteData(const std::string& data) override;
+ bool OnConnectionShuttingDown() override;
+
+ virtual void OnDisconnect(int errorCode);
+
+ static void on_close(uv_handle_t* handle);
+
+ template <typename T>
+ static void on_close_delete(uv_handle_t* handle)
+ {
+ delete reinterpret_cast<T*>(handle);
+ }
+
+protected:
+ cm::uv_stream_ptr WriteStream;
+
+ std::string RawReadBuffer;
+
+ std::unique_ptr<cmConnectionBufferStrategy> BufferStrategy;
+
+ static void on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
+
+ static void on_write(uv_write_t* req, int status);
+
+ static void on_new_connection(uv_stream_t* stream, int status);
+
+ static void on_alloc_buffer(uv_handle_t* handle, size_t suggested_size,
+ uv_buf_t* buf);
+};
diff --git a/Source/cmContinueCommand.cxx b/Source/cmContinueCommand.cxx
index 2298a05c5..bb63dffd6 100644
--- a/Source/cmContinueCommand.cxx
+++ b/Source/cmContinueCommand.cxx
@@ -4,17 +4,18 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmSystemTools.h"
-#include "cmake.h"
// cmContinueCommand
-bool cmContinueCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status)
+bool cmContinueCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- if (!this->Makefile->IsLoopBlock()) {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
- "A CONTINUE command was found outside of a "
- "proper FOREACH or WHILE loop scope.");
+ if (!status.GetMakefile().IsLoopBlock()) {
+ status.GetMakefile().IssueMessage(
+ MessageType::FATAL_ERROR,
+ "A CONTINUE command was found outside of a "
+ "proper FOREACH or WHILE loop scope.");
cmSystemTools::SetFatalErrorOccured();
return true;
}
@@ -22,9 +23,10 @@ bool cmContinueCommand::InitialPass(std::vector<std::string> const& args,
status.SetContinueInvoked();
if (!args.empty()) {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
- "The CONTINUE command does not accept any "
- "arguments.");
+ status.GetMakefile().IssueMessage(
+ MessageType::FATAL_ERROR,
+ "The CONTINUE command does not accept any "
+ "arguments.");
cmSystemTools::SetFatalErrorOccured();
return true;
}
diff --git a/Source/cmContinueCommand.h b/Source/cmContinueCommand.h
index 92bc68e85..ff903aaf6 100644
--- a/Source/cmContinueCommand.h
+++ b/Source/cmContinueCommand.h
@@ -3,34 +3,19 @@
#ifndef cmContinueCommand_h
#define cmContinueCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmContinueCommand
+/**
* \brief Continue from an enclosing foreach or while loop
*
* cmContinueCommand returns from an enclosing foreach or while loop
*/
-class cmContinueCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmContinueCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmContinueCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmConvertMSBuildXMLToJSON.py b/Source/cmConvertMSBuildXMLToJSON.py
index 93ab8a82f..02074ba65 100644
--- a/Source/cmConvertMSBuildXMLToJSON.py
+++ b/Source/cmConvertMSBuildXMLToJSON.py
@@ -96,7 +96,6 @@ def read_msbuild_json(path, values=[]):
return values
-
def main():
"""Script entrypoint."""
# Parse the arguments
@@ -213,6 +212,14 @@ def __find_and_remove_value(list, compare):
return found
+def __normalize_switch(switch, separator):
+ new = switch
+ if switch.startswith("/") or switch.startswith("-"):
+ new = switch[1:]
+ if new and separator:
+ new = new + separator
+ return new
+
###########################################################################################
# private xml functions
def __convert(root, tag, values, func):
@@ -257,6 +264,8 @@ def __convert_bool(node):
reverse_switch = __get_attribute(node, 'ReverseSwitch')
if reverse_switch:
+ __with_argument(node, converted)
+
converted_reverse = copy.deepcopy(converted)
converted_reverse['switch'] = reverse_switch
@@ -303,7 +312,11 @@ def __convert_node(node, default_value='', default_flags=vsflags()):
converted = {}
converted['name'] = name
- converted['switch'] = __get_attribute(node, 'Switch')
+
+ switch = __get_attribute(node, 'Switch')
+ separator = __get_attribute(node, 'Separator')
+ converted['switch'] = __normalize_switch(switch, separator)
+
converted['comment'] = __get_attribute(node, 'DisplayName')
converted['value'] = default_value
@@ -343,7 +356,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
@@ -435,7 +448,7 @@ def __write_json_file(path, values):
with open(path, 'w') as f:
json.dump(sorted_values, f, indent=2, separators=(',', ': '))
-
+ f.write("\n")
###########################################################################################
# private list helpers
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 9a4abf3ca..5711cae49 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -2,21 +2,24 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCoreTryCompile.h"
-#include "cmConfigure.h"
-#include "cmsys/Directory.hxx"
+#include <cstdio>
+#include <cstring>
#include <set>
#include <sstream>
-#include <stdio.h>
-#include <string.h>
#include <utility>
-#include "cmAlgorithms.h"
+#include "cmsys/Directory.hxx"
+
+#include "cm_static_string_view.hxx"
+
#include "cmExportTryCompileFileGenerator.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmState.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmVersion.h"
@@ -25,15 +28,25 @@
static std::string const kCMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN =
"CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN";
static std::string const kCMAKE_C_COMPILER_TARGET = "CMAKE_C_COMPILER_TARGET";
+static std::string const kCMAKE_C_LINK_NO_PIE_SUPPORTED =
+ "CMAKE_C_LINK_NO_PIE_SUPPORTED";
+static std::string const kCMAKE_C_LINK_PIE_SUPPORTED =
+ "CMAKE_C_LINK_PIE_SUPPORTED";
static std::string const kCMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN =
"CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN";
static std::string const kCMAKE_CXX_COMPILER_TARGET =
"CMAKE_CXX_COMPILER_TARGET";
+static std::string const kCMAKE_CXX_LINK_NO_PIE_SUPPORTED =
+ "CMAKE_CXX_LINK_NO_PIE_SUPPORTED";
+static std::string const kCMAKE_CXX_LINK_PIE_SUPPORTED =
+ "CMAKE_CXX_LINK_PIE_SUPPORTED";
static std::string const kCMAKE_ENABLE_EXPORTS = "CMAKE_ENABLE_EXPORTS";
static std::string const kCMAKE_LINK_SEARCH_END_STATIC =
"CMAKE_LINK_SEARCH_END_STATIC";
static std::string const kCMAKE_LINK_SEARCH_START_STATIC =
"CMAKE_LINK_SEARCH_START_STATIC";
+static std::string const kCMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT =
+ "CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT";
static std::string const kCMAKE_OSX_ARCHITECTURES = "CMAKE_OSX_ARCHITECTURES";
static std::string const kCMAKE_OSX_DEPLOYMENT_TARGET =
"CMAKE_OSX_DEPLOYMENT_TARGET";
@@ -43,12 +56,21 @@ static std::string const kCMAKE_POSITION_INDEPENDENT_CODE =
static std::string const kCMAKE_SYSROOT = "CMAKE_SYSROOT";
static std::string const kCMAKE_SYSROOT_COMPILE = "CMAKE_SYSROOT_COMPILE";
static std::string const kCMAKE_SYSROOT_LINK = "CMAKE_SYSROOT_LINK";
+static std::string const kCMAKE_Swift_COMPILER_TARGET =
+ "CMAKE_Swift_COMPILER_TARGET";
static std::string const kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES =
"CMAKE_TRY_COMPILE_OSX_ARCHITECTURES";
static std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES =
"CMAKE_TRY_COMPILE_PLATFORM_VARIABLES";
static std::string const kCMAKE_WARN_DEPRECATED = "CMAKE_WARN_DEPRECATED";
+/* GHS Multi platform variables */
+static std::set<std::string> ghs_platform_vars{
+ "GHS_TARGET_PLATFORM", "GHS_PRIMARY_TARGET", "GHS_TOOLSET_ROOT",
+ "GHS_OS_ROOT", "GHS_OS_DIR", "GHS_BSP_NAME",
+ "GHS_OS_DIR_OPTION"
+};
+
static void writeProperty(FILE* fout, std::string const& targetName,
std::string const& prop, std::string const& value)
{
@@ -72,7 +94,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
bool isTryRun)
{
this->BinaryDirectory = argv[1];
- this->OutputFile = "";
+ this->OutputFile.clear();
// which signature were we called with ?
this->SrcFileSignature = true;
@@ -83,17 +105,20 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
if (strcmp(tt, cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE)) ==
0) {
targetType = cmStateEnums::EXECUTABLE;
- } else if (strcmp(tt, cmState::GetTargetTypeName(
- cmStateEnums::STATIC_LIBRARY)) == 0) {
+ } else if (strcmp(tt,
+ cmState::GetTargetTypeName(
+ cmStateEnums::STATIC_LIBRARY)) == 0) {
targetType = cmStateEnums::STATIC_LIBRARY;
} else {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR, std::string("Invalid value '") + tt +
+ MessageType::FATAL_ERROR,
+ std::string("Invalid value '") + tt +
"' for "
"CMAKE_TRY_COMPILE_TARGET_TYPE. Only "
"'" +
- cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE) + "' and "
- "'" +
+ cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE) +
+ "' and "
+ "'" +
cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY) +
"' "
"are allowed.");
@@ -101,24 +126,32 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
}
- const char* sourceDirectory = argv[2].c_str();
- const char* projectName = CM_NULLPTR;
+ std::string sourceDirectory = argv[2];
+ std::string projectName;
std::string targetName;
std::vector<std::string> cmakeFlags(1, "CMAKE_FLAGS"); // fake argv[0]
std::vector<std::string> compileDefs;
+ std::string cmakeInternal;
std::string outputVariable;
std::string copyFile;
std::string copyFileError;
std::string cStandard;
+ std::string objcStandard;
std::string cxxStandard;
+ std::string objcxxStandard;
std::string cudaStandard;
std::string cStandardRequired;
std::string cxxStandardRequired;
+ std::string objcStandardRequired;
+ std::string objcxxStandardRequired;
std::string cudaStandardRequired;
std::string cExtensions;
std::string cxxExtensions;
+ std::string objcExtensions;
+ std::string objcxxExtensions;
std::string cudaExtensions;
std::vector<std::string> targets;
+ std::vector<std::string> linkOptions;
std::string libsToLink = " ";
bool useOldLinkLibs = true;
char targetNameBuf[64];
@@ -127,12 +160,18 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
bool didCopyFileError = false;
bool didCStandard = false;
bool didCxxStandard = false;
+ bool didObjCStandard = false;
+ bool didObjCxxStandard = false;
bool didCudaStandard = false;
bool didCStandardRequired = false;
bool didCxxStandardRequired = false;
+ bool didObjCStandardRequired = false;
+ bool didObjCxxStandardRequired = false;
bool didCudaStandardRequired = false;
bool didCExtensions = false;
bool didCxxExtensions = false;
+ bool didObjCExtensions = false;
+ bool didObjCxxExtensions = false;
bool didCudaExtensions = false;
bool useSources = argv[2] == "SOURCES";
std::vector<std::string> sources;
@@ -142,20 +181,28 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
DoingNone,
DoingCMakeFlags,
DoingCompileDefinitions,
+ DoingLinkOptions,
DoingLinkLibraries,
DoingOutputVariable,
DoingCopyFile,
DoingCopyFileError,
DoingCStandard,
DoingCxxStandard,
+ DoingObjCStandard,
+ DoingObjCxxStandard,
DoingCudaStandard,
DoingCStandardRequired,
DoingCxxStandardRequired,
+ DoingObjCStandardRequired,
+ DoingObjCxxStandardRequired,
DoingCudaStandardRequired,
DoingCExtensions,
DoingCxxExtensions,
+ DoingObjCExtensions,
+ DoingObjCxxExtensions,
DoingCudaExtensions,
- DoingSources
+ DoingSources,
+ DoingCMakeInternal
};
Doing doing = useSources ? DoingSources : DoingNone;
for (size_t i = 3; i < argv.size(); ++i) {
@@ -163,6 +210,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
doing = DoingCMakeFlags;
} else if (argv[i] == "COMPILE_DEFINITIONS") {
doing = DoingCompileDefinitions;
+ } else if (argv[i] == "LINK_OPTIONS") {
+ doing = DoingLinkOptions;
} else if (argv[i] == "LINK_LIBRARIES") {
doing = DoingLinkLibraries;
useOldLinkLibs = false;
@@ -181,6 +230,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} else if (argv[i] == "CXX_STANDARD") {
doing = DoingCxxStandard;
didCxxStandard = true;
+ } else if (argv[i] == "OBJC_STANDARD") {
+ doing = DoingObjCStandard;
+ didObjCStandard = true;
+ } else if (argv[i] == "OBJCXX_STANDARD") {
+ doing = DoingObjCxxStandard;
+ didObjCxxStandard = true;
} else if (argv[i] == "CUDA_STANDARD") {
doing = DoingCudaStandard;
didCudaStandard = true;
@@ -190,6 +245,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} else if (argv[i] == "CXX_STANDARD_REQUIRED") {
doing = DoingCxxStandardRequired;
didCxxStandardRequired = true;
+ } else if (argv[i] == "OBJC_STANDARD_REQUIRED") {
+ doing = DoingObjCStandardRequired;
+ didObjCStandardRequired = true;
+ } else if (argv[i] == "OBJCXX_STANDARD_REQUIRED") {
+ doing = DoingObjCxxStandardRequired;
+ didObjCxxStandardRequired = true;
} else if (argv[i] == "CUDA_STANDARD_REQUIRED") {
doing = DoingCudaStandardRequired;
didCudaStandardRequired = true;
@@ -199,15 +260,25 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} else if (argv[i] == "CXX_EXTENSIONS") {
doing = DoingCxxExtensions;
didCxxExtensions = true;
+ } else if (argv[i] == "OBJC_EXTENSIONS") {
+ doing = DoingObjCExtensions;
+ didObjCExtensions = true;
+ } else if (argv[i] == "OBJCXX_EXTENSIONS") {
+ doing = DoingObjCxxExtensions;
+ didObjCxxExtensions = true;
} else if (argv[i] == "CUDA_EXTENSIONS") {
doing = DoingCudaExtensions;
didCudaExtensions = true;
+ } else if (argv[i] == "__CMAKE_INTERNAL") {
+ doing = DoingCMakeInternal;
} else if (doing == DoingCMakeFlags) {
cmakeFlags.push_back(argv[i]);
} else if (doing == DoingCompileDefinitions) {
- compileDefs.push_back(argv[i]);
+ cmExpandList(argv[i], compileDefs);
+ } else if (doing == DoingLinkOptions) {
+ linkOptions.push_back(argv[i]);
} else if (doing == DoingLinkLibraries) {
- libsToLink += "\"" + cmSystemTools::TrimWhitespace(argv[i]) + "\" ";
+ libsToLink += "\"" + cmTrimWhitespace(argv[i]) + "\" ";
if (cmTarget* tgt = this->Makefile->FindTargetToUse(argv[i])) {
switch (tgt->GetType()) {
case cmStateEnums::SHARED_LIBRARY:
@@ -222,11 +293,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
CM_FALLTHROUGH;
default:
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"Only libraries may be used as try_compile or try_run IMPORTED "
"LINK_LIBRARIES. Got " +
- std::string(tgt->GetName()) + " of "
- "type " +
+ std::string(tgt->GetName()) +
+ " of "
+ "type " +
cmState::GetTargetTypeName(tgt->GetType()) + ".");
return -1;
}
@@ -249,6 +321,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} else if (doing == DoingCxxStandard) {
cxxStandard = argv[i];
doing = DoingNone;
+ } else if (doing == DoingObjCStandard) {
+ objcStandard = argv[i];
+ doing = DoingNone;
+ } else if (doing == DoingObjCxxStandard) {
+ objcxxStandard = argv[i];
+ doing = DoingNone;
} else if (doing == DoingCudaStandard) {
cudaStandard = argv[i];
doing = DoingNone;
@@ -258,6 +336,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} else if (doing == DoingCxxStandardRequired) {
cxxStandardRequired = argv[i];
doing = DoingNone;
+ } else if (doing == DoingObjCStandardRequired) {
+ objcStandardRequired = argv[i];
+ doing = DoingNone;
+ } else if (doing == DoingObjCxxStandardRequired) {
+ objcxxStandardRequired = argv[i];
+ doing = DoingNone;
} else if (doing == DoingCudaStandardRequired) {
cudaStandardRequired = argv[i];
doing = DoingNone;
@@ -267,106 +351,117 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
} else if (doing == DoingCxxExtensions) {
cxxExtensions = argv[i];
doing = DoingNone;
+ } else if (doing == DoingObjCExtensions) {
+ objcExtensions = argv[i];
+ doing = DoingNone;
+ } else if (doing == DoingObjCxxExtensions) {
+ objcxxExtensions = argv[i];
+ doing = DoingNone;
} else if (doing == DoingCudaExtensions) {
cudaExtensions = argv[i];
doing = DoingNone;
} else if (doing == DoingSources) {
sources.push_back(argv[i]);
+ } else if (doing == DoingCMakeInternal) {
+ cmakeInternal = argv[i];
+ doing = DoingNone;
} else if (i == 3) {
this->SrcFileSignature = false;
- projectName = argv[i].c_str();
+ projectName = argv[i];
} else if (i == 4 && !this->SrcFileSignature) {
targetName = argv[i];
} else {
std::ostringstream m;
m << "try_compile given unknown argument \"" << argv[i] << "\".";
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, m.str());
+ this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, m.str());
}
}
if (didCopyFile && copyFile.empty()) {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
"COPY_FILE must be followed by a file path");
return -1;
}
if (didCopyFileError && copyFileError.empty()) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"COPY_FILE_ERROR must be followed by a variable name");
return -1;
}
if (didCopyFileError && !didCopyFile) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR, "COPY_FILE_ERROR may be used only with COPY_FILE");
+ MessageType::FATAL_ERROR,
+ "COPY_FILE_ERROR may be used only with COPY_FILE");
return -1;
}
if (didOutputVariable && outputVariable.empty()) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"OUTPUT_VARIABLE must be followed by a variable name");
return -1;
}
if (useSources && sources.empty()) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"SOURCES must be followed by at least one source file");
return -1;
}
if (didCStandard && !this->SrcFileSignature) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR, "C_STANDARD allowed only in source file signature.");
+ MessageType::FATAL_ERROR,
+ "C_STANDARD allowed only in source file signature.");
return -1;
}
if (didCxxStandard && !this->SrcFileSignature) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"CXX_STANDARD allowed only in source file signature.");
return -1;
}
if (didCudaStandard && !this->SrcFileSignature) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"CUDA_STANDARD allowed only in source file signature.");
return -1;
}
if (didCStandardRequired && !this->SrcFileSignature) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"C_STANDARD_REQUIRED allowed only in source file signature.");
return -1;
}
if (didCxxStandardRequired && !this->SrcFileSignature) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"CXX_STANDARD_REQUIRED allowed only in source file signature.");
return -1;
}
if (didCudaStandardRequired && !this->SrcFileSignature) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"CUDA_STANDARD_REQUIRED allowed only in source file signature.");
return -1;
}
if (didCExtensions && !this->SrcFileSignature) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"C_EXTENSIONS allowed only in source file signature.");
return -1;
}
if (didCxxExtensions && !this->SrcFileSignature) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"CXX_EXTENSIONS allowed only in source file signature.");
return -1;
}
if (didCudaExtensions && !this->SrcFileSignature) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"CUDA_EXTENSIONS allowed only in source file signature.");
return -1;
}
@@ -374,32 +469,31 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
// compute the binary dir when TRY_COMPILE is called with a src file
// signature
if (this->SrcFileSignature) {
- this->BinaryDirectory += cmake::GetCMakeFilesDirectory();
- this->BinaryDirectory += "/CMakeTmp";
+ this->BinaryDirectory += "/CMakeFiles/CMakeTmp";
} else {
// only valid for srcfile signatures
if (!compileDefs.empty()) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"COMPILE_DEFINITIONS specified on a srcdir type TRY_COMPILE");
return -1;
}
if (!copyFile.empty()) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"COPY_FILE specified on a srcdir type TRY_COMPILE");
return -1;
}
}
// 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()) {
std::ostringstream e;
e << "Attempt at a recursive or nested TRY_COMPILE in directory\n"
<< " " << this->BinaryDirectory << "\n";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return -1;
}
@@ -418,23 +512,22 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
// Detect languages to enable.
cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
std::set<std::string> testLangs;
- for (std::vector<std::string>::iterator si = sources.begin();
- si != sources.end(); ++si) {
- std::string ext = cmSystemTools::GetFilenameLastExtension(*si);
+ for (std::string const& si : sources) {
+ std::string ext = cmSystemTools::GetFilenameLastExtension(si);
std::string lang = gg->GetLanguageFromExtension(ext.c_str());
if (!lang.empty()) {
testLangs.insert(lang);
} else {
std::ostringstream err;
err << "Unknown extension \"" << ext << "\" for file\n"
- << " " << *si << "\n"
+ << " " << si << "\n"
<< "try_compile() works only for enabled languages. "
<< "Currently these are:\n ";
std::vector<std::string> langs;
gg->GetEnabledLanguages(langs);
err << cmJoin(langs, " ");
err << "\nSee project() command to enable other languages.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, err.str());
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, err.str());
return -1;
}
}
@@ -444,7 +537,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
// we need to create a directory and CMakeLists file etc...
// first create the directories
- sourceDirectory = this->BinaryDirectory.c_str();
+ sourceDirectory = this->BinaryDirectory;
// now create a CMakeLists.txt file in that directory
FILE* fout = cmsys::SystemTools::Fopen(outFileName, "w");
@@ -455,7 +548,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
<< " " << outFileName << "\n"
<< cmSystemTools::GetLastSystemError();
/* clang-format on */
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return -1;
}
@@ -467,12 +560,18 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
fprintf(fout, "set(CMAKE_MODULE_PATH \"%s\")\n", def);
}
+ /* Set MSVC runtime library policy to match our selection. */
+ if (const char* msvcRuntimeLibraryDefault =
+ this->Makefile->GetDefinition(kCMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT)) {
+ fprintf(fout, "cmake_policy(SET CMP0091 %s)\n",
+ *msvcRuntimeLibraryDefault ? "NEW" : "OLD");
+ }
+
std::string projectLangs;
- for (std::set<std::string>::iterator li = testLangs.begin();
- li != testLangs.end(); ++li) {
- projectLangs += " " + *li;
+ for (std::string const& li : testLangs) {
+ projectLangs += " " + li;
std::string rulesOverrideBase = "CMAKE_USER_MAKE_RULES_OVERRIDE";
- std::string rulesOverrideLang = rulesOverrideBase + "_" + *li;
+ std::string rulesOverrideLang = cmStrCat(rulesOverrideBase, "_", li);
if (const char* rulesOverridePath =
this->Makefile->GetDefinition(rulesOverrideLang)) {
fprintf(fout, "set(%s \"%s\")\n", rulesOverrideLang.c_str(),
@@ -484,16 +583,24 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
}
fprintf(fout, "project(CMAKE_TRY_COMPILE%s)\n", projectLangs.c_str());
+ if (cmakeInternal == "ABI") {
+ // This is the ABI detection step, also used for implicit includes.
+ // Erase any include_directories() calls from the toolchain file so
+ // that we do not see them as implicit. Our ABI detection source
+ // does not include any system headers anyway.
+ fprintf(fout,
+ "set_property(DIRECTORY PROPERTY INCLUDE_DIRECTORIES \"\")\n");
+ }
fprintf(fout, "set(CMAKE_VERBOSE_MAKEFILE 1)\n");
- for (std::set<std::string>::iterator li = testLangs.begin();
- li != testLangs.end(); ++li) {
- std::string langFlags = "CMAKE_" + *li + "_FLAGS";
+ for (std::string const& li : testLangs) {
+ std::string langFlags = "CMAKE_" + li + "_FLAGS";
const char* flags = this->Makefile->GetDefinition(langFlags);
- fprintf(fout, "set(CMAKE_%s_FLAGS %s)\n", li->c_str(),
+ fprintf(fout, "set(CMAKE_%s_FLAGS %s)\n", li.c_str(),
cmOutputConverter::EscapeForCMake(flags ? flags : "").c_str());
- fprintf(fout, "set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}"
- " ${COMPILE_DEFINITIONS}\")\n",
- li->c_str(), li->c_str());
+ fprintf(fout,
+ "set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}"
+ " ${COMPILE_DEFINITIONS}\")\n",
+ li.c_str(), li.c_str());
}
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0066)) {
case cmPolicies::WARN:
@@ -507,7 +614,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
"(e.g. CMAKE_C_FLAGS_DEBUG) in the test project."
;
/* clang-format on */
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
}
case cmPolicies::OLD:
// OLD behavior is to do nothing.
@@ -515,7 +622,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0066));
CM_FALLTHROUGH;
case cmPolicies::NEW: {
@@ -523,9 +630,9 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
static std::string const cfgDefault = "DEBUG";
std::string const cfg =
!tcConfig.empty() ? cmSystemTools::UpperCase(tcConfig) : cfgDefault;
- for (std::set<std::string>::iterator li = testLangs.begin();
- li != testLangs.end(); ++li) {
- std::string const langFlagsCfg = "CMAKE_" + *li + "_FLAGS_" + cfg;
+ for (std::string const& li : testLangs) {
+ std::string const langFlagsCfg =
+ cmStrCat("CMAKE_", li, "_FLAGS_", cfg);
const char* flagsCfg = this->Makefile->GetDefinition(langFlagsCfg);
fprintf(fout, "set(%s %s)\n", langFlagsCfg.c_str(),
cmOutputConverter::EscapeForCMake(flagsCfg ? flagsCfg : "")
@@ -545,7 +652,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
"in the test project."
;
/* clang-format on */
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
}
case cmPolicies::OLD:
// OLD behavior is to do nothing.
@@ -553,7 +660,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0056));
CM_FALLTHROUGH;
case cmPolicies::NEW:
@@ -568,14 +675,17 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
break;
}
- fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS}"
- " ${EXE_LINKER_FLAGS}\")\n");
+ fprintf(fout,
+ "set(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS}"
+ " ${EXE_LINKER_FLAGS}\")\n");
fprintf(fout, "include_directories(${INCLUDE_DIRECTORIES})\n");
fprintf(fout, "set(CMAKE_SUPPRESS_REGENERATION 1)\n");
fprintf(fout, "link_directories(${LINK_DIRECTORIES})\n");
// handle any compile flags we need to pass on
if (!compileDefs.empty()) {
- fprintf(fout, "add_definitions(%s)\n", cmJoin(compileDefs, " ").c_str());
+ // Pass using bracket arguments to preserve content.
+ fprintf(fout, "add_definitions([==[%s]==])\n",
+ cmJoin(compileDefs, "]==] [==[").c_str());
}
/* Use a random file name to avoid rapid creation and deletion
@@ -585,12 +695,13 @@ 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);
if (!tcfg.GenerateImportFile()) {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
"could not write export file.");
fclose(fout);
return -1;
@@ -616,15 +727,26 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
vars.insert(kCMAKE_SYSROOT);
vars.insert(kCMAKE_SYSROOT_COMPILE);
vars.insert(kCMAKE_SYSROOT_LINK);
+ vars.insert(kCMAKE_Swift_COMPILER_TARGET);
vars.insert(kCMAKE_WARN_DEPRECATED);
+ vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s);
if (const char* varListStr = this->Makefile->GetDefinition(
kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES)) {
- std::vector<std::string> varList;
- cmSystemTools::ExpandListArgument(varListStr, varList);
+ std::vector<std::string> varList = cmExpandedList(varListStr);
vars.insert(varList.begin(), varList.end());
}
+ if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0083) ==
+ cmPolicies::NEW) {
+ // To ensure full support of PIE, propagate cache variables
+ // driving the link options
+ vars.insert(kCMAKE_C_LINK_PIE_SUPPORTED);
+ vars.insert(kCMAKE_C_LINK_NO_PIE_SUPPORTED);
+ vars.insert(kCMAKE_CXX_LINK_PIE_SUPPORTED);
+ vars.insert(kCMAKE_CXX_LINK_NO_PIE_SUPPORTED);
+ }
+
/* for the TRY_COMPILEs we want to be able to specify the architecture.
So the user can set CMAKE_OSX_ARCHITECTURES to i386;ppc and then set
CMAKE_TRY_COMPILE_OSX_ARCHITECTURES first to i386 and then to ppc to
@@ -636,15 +758,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::set<std::string>::iterator vi = vars.begin(); vi != vars.end();
- ++vi) {
- std::string const& var = *vi;
+ 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));
}
}
}
@@ -656,6 +776,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
? "NEW"
: "OLD");
+ /* Set the appropriate policy information for PIE link flags */
+ fprintf(fout, "cmake_policy(SET CMP0083 %s)\n",
+ this->Makefile->GetPolicyStatus(cmPolicies::CMP0083) ==
+ cmPolicies::NEW
+ ? "NEW"
+ : "OLD");
+
if (targetType == cmStateEnums::EXECUTABLE) {
/* Put the executable at a known location (for COPY_FILE). */
fprintf(fout, "set(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"%s\")\n",
@@ -670,28 +797,31 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
/* Create the actual static library. */
fprintf(fout, "add_library(%s STATIC", targetName.c_str());
}
- for (std::vector<std::string>::iterator si = sources.begin();
- si != sources.end(); ++si) {
- fprintf(fout, " \"%s\"", si->c_str());
+ for (std::string const& si : sources) {
+ fprintf(fout, " \"%s\"", si.c_str());
// Add dependencies on any non-temporary sources.
- if (si->find("CMakeTmp") == std::string::npos) {
- this->Makefile->AddCMakeDependFile(*si);
+ if (si.find("CMakeTmp") == std::string::npos) {
+ this->Makefile->AddCMakeDependFile(si);
}
}
fprintf(fout, ")\n");
bool const testC = testLangs.find("C") != testLangs.end();
+ bool const testObjC = testLangs.find("OBJC") != testLangs.end();
bool const testCxx = testLangs.find("CXX") != testLangs.end();
+ bool const testObjCxx = testLangs.find("OBJCXX") != testLangs.end();
bool const testCuda = testLangs.find("CUDA") != testLangs.end();
bool warnCMP0067 = false;
bool honorStandard = true;
- if (!didCStandard && !didCxxStandard && !didCudaStandard &&
- !didCStandardRequired && !didCxxStandardRequired &&
- !didCudaStandardRequired && !didCExtensions && !didCxxExtensions &&
- !didCudaExtensions) {
+ if (!didCStandard && !didCxxStandard && !didObjCStandard &&
+ !didObjCxxStandard && !didCudaStandard && !didCStandardRequired &&
+ !didCxxStandardRequired && !didObjCStandardRequired &&
+ !didObjCxxStandardRequired && !didCudaStandardRequired &&
+ !didCExtensions && !didCxxExtensions && !didObjCExtensions &&
+ !didObjCxxExtensions && !didCudaExtensions) {
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0067)) {
case cmPolicies::WARN:
warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled(
@@ -704,7 +834,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0067));
case cmPolicies::NEW:
// NEW behavior is to honor the language standard variables.
@@ -714,45 +844,42 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
if (honorStandard || warnCMP0067) {
- if (testC) {
- if (!didCStandard) {
- cStandard = this->LookupStdVar("CMAKE_C_STANDARD", warnCMP0067);
- }
- if (!didCStandardRequired) {
- cStandardRequired =
- this->LookupStdVar("CMAKE_C_STANDARD_REQUIRED", warnCMP0067);
- }
- if (!didCExtensions) {
- cExtensions = this->LookupStdVar("CMAKE_C_EXTENSIONS", warnCMP0067);
- }
- }
- if (testCxx) {
- if (!didCxxStandard) {
- cxxStandard = this->LookupStdVar("CMAKE_CXX_STANDARD", warnCMP0067);
- }
- if (!didCxxStandardRequired) {
- cxxStandardRequired =
- this->LookupStdVar("CMAKE_CXX_STANDARD_REQUIRED", warnCMP0067);
- }
- if (!didCxxExtensions) {
- cxxExtensions =
- this->LookupStdVar("CMAKE_CXX_EXTENSIONS", warnCMP0067);
- }
- }
- if (testCuda) {
- if (!didCudaStandard) {
- cudaStandard =
- this->LookupStdVar("CMAKE_CUDA_STANDARD", warnCMP0067);
- }
- if (!didCudaStandardRequired) {
- cudaStandardRequired =
- this->LookupStdVar("CMAKE_CUDA_STANDARD_REQUIRED", warnCMP0067);
- }
- if (!didCudaExtensions) {
- cudaExtensions =
- this->LookupStdVar("CMAKE_CUDA_EXTENSIONS", warnCMP0067);
- }
- }
+
+ auto testLanguage =
+ [&](bool testLang, bool didLangStandard, bool didLangStandardRequired,
+ bool didLangExtensions, std::string& langStandard,
+ std::string& langStandardRequired, std::string& langExtensions,
+ const std::string& lang) {
+ if (testLang) {
+ if (!didLangStandard) {
+ langStandard = this->LookupStdVar(
+ cmStrCat("CMAKE_", lang, "_STANDARD"), warnCMP0067);
+ }
+ if (!didLangStandardRequired) {
+ langStandardRequired = this->LookupStdVar(
+ cmStrCat("CMAKE_", lang, "_STANDARD_REQUIRED"), warnCMP0067);
+ }
+ if (!didLangExtensions) {
+ langExtensions = this->LookupStdVar(
+ cmStrCat("CMAKE_", lang, "_EXTENSIONS"), warnCMP0067);
+ }
+ }
+ };
+
+ testLanguage(testC, didCStandard, didCStandardRequired, didCExtensions,
+ cStandard, cStandardRequired, cExtensions, "C");
+ testLanguage(testObjC, didObjCStandard, didObjCStandardRequired,
+ didObjCExtensions, objcStandard, objcStandardRequired,
+ objcExtensions, "OBJC");
+ testLanguage(testCxx, didCxxStandard, didCxxStandardRequired,
+ didCxxExtensions, cxxStandard, cxxStandardRequired,
+ cxxExtensions, "CXX");
+ testLanguage(testObjCxx, didObjCxxStandard, didObjCxxStandardRequired,
+ didObjCxxExtensions, objcxxStandard, objcxxStandardRequired,
+ objcxxExtensions, "OBJCXX");
+ testLanguage(testCuda, didCudaStandard, didCudaStandardRequired,
+ didCudaExtensions, cudaStandard, cudaStandardRequired,
+ cudaExtensions, "CUDA");
}
if (!this->WarnCMP0067.empty()) {
@@ -763,49 +890,58 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
"is not honoring language standard variables in the test project:\n"
;
/* clang-format on */
- for (std::vector<std::string>::iterator vi = this->WarnCMP0067.begin();
- vi != this->WarnCMP0067.end(); ++vi) {
- w << " " << *vi << "\n";
+ for (std::string const& vi : this->WarnCMP0067) {
+ w << " " << vi << "\n";
}
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
}
- if (testC) {
- if (!cStandard.empty()) {
- writeProperty(fout, targetName, "C_STANDARD", cStandard);
- }
- if (!cStandardRequired.empty()) {
- writeProperty(fout, targetName, "C_STANDARD_REQUIRED",
- cStandardRequired);
- }
- if (!cExtensions.empty()) {
- writeProperty(fout, targetName, "C_EXTENSIONS", cExtensions);
+ auto writeLanguageProperties = [&](bool testLang,
+ const std::string& langStandard,
+ const std::string& langStandardRequired,
+ const std::string& langExtensions,
+ const std::string& lang) {
+ if (testLang) {
+ if (!langStandard.empty()) {
+ writeProperty(fout, targetName, cmStrCat(lang, "_STANDARD"),
+ langStandard);
+ }
+ if (!langStandardRequired.empty()) {
+ writeProperty(fout, targetName, cmStrCat(lang, "_STANDARD_REQUIRED"),
+ langStandardRequired);
+ }
+ if (!langExtensions.empty()) {
+ writeProperty(fout, targetName, cmStrCat(lang, "_EXTENSIONS"),
+ langExtensions);
+ }
}
- }
+ };
- if (testCxx) {
- if (!cxxStandard.empty()) {
- writeProperty(fout, targetName, "CXX_STANDARD", cxxStandard);
- }
- if (!cxxStandardRequired.empty()) {
- writeProperty(fout, targetName, "CXX_STANDARD_REQUIRED",
- cxxStandardRequired);
- }
- if (!cxxExtensions.empty()) {
- writeProperty(fout, targetName, "CXX_EXTENSIONS", cxxExtensions);
- }
- }
+ writeLanguageProperties(testC, cStandard, cStandardRequired, cExtensions,
+ "C");
+ writeLanguageProperties(testObjC, objcStandard, objcStandardRequired,
+ objcExtensions, "OBJC");
+ writeLanguageProperties(testCxx, cxxStandard, cxxStandardRequired,
+ cxxExtensions, "CXX");
+ writeLanguageProperties(testObjCxx, objcxxStandard, objcxxStandardRequired,
+ objcxxExtensions, "OBJCXX");
+ writeLanguageProperties(testCuda, cudaStandard, cudaStandardRequired,
+ cudaExtensions, "CUDA");
- if (testCuda) {
- if (!cudaStandard.empty()) {
- writeProperty(fout, targetName, "CUDA_STANDARD", cudaStandard);
- }
- if (!cudaStandardRequired.empty()) {
- writeProperty(fout, targetName, "CUDA_STANDARD_REQUIRED",
- cudaStandardRequired);
+ if (!linkOptions.empty()) {
+ std::vector<std::string> options;
+ options.reserve(linkOptions.size());
+ for (const auto& option : linkOptions) {
+ options.emplace_back(cmOutputConverter::EscapeForCMake(option));
}
- if (!cudaExtensions.empty()) {
- writeProperty(fout, targetName, "CUDA_EXTENSIONS", cudaExtensions);
+
+ if (targetType == cmStateEnums::STATIC_LIBRARY) {
+ fprintf(fout,
+ "set_property(TARGET %s PROPERTY STATIC_LIBRARY_OPTIONS %s)\n",
+ targetName.c_str(), cmJoin(options, " ").c_str());
+ } else {
+ fprintf(fout, "target_link_options(%s PRIVATE %s)\n",
+ targetName.c_str(), cmJoin(options, " ").c_str());
}
}
@@ -820,13 +956,24 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
projectName = "CMAKE_TRY_COMPILE";
}
+ if (this->Makefile->GetState()->UseGhsMultiIDE()) {
+ // Forward the GHS variables to the inner project cache.
+ for (std::string const& var : ghs_platform_vars) {
+ if (const char* val = this->Makefile->GetDefinition(var)) {
+ std::string flag = "-D" + var + "=" + "'" + val + "'";
+ cmakeFlags.push_back(std::move(flag));
+ }
+ }
+ }
+
bool erroroc = cmSystemTools::GetErrorOccuredFlag();
cmSystemTools::ResetErrorOccuredFlag();
std::string output;
// actually do the try compile now that everything is setup
int res = this->Makefile->TryCompile(
sourceDirectory, this->BinaryDirectory, projectName, targetName,
- this->SrcFileSignature, &cmakeFlags, output);
+ this->SrcFileSignature, cmake::NO_BUILD_PARALLEL_LEVEL, &cmakeFlags,
+ output);
if (erroroc) {
cmSystemTools::SetErrorOccured();
}
@@ -837,7 +984,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
cmStateEnums::INTERNAL);
if (!outputVariable.empty()) {
- this->Makefile->AddDefinition(outputVariable, output.c_str());
+ this->Makefile->AddDefinition(outputVariable, output);
}
if (this->SrcFileSignature) {
@@ -855,10 +1002,10 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
<< " '" << copyFile << "'\n";
/* clang-format on */
if (!this->FindErrorMessage.empty()) {
- emsg << this->FindErrorMessage.c_str();
+ emsg << this->FindErrorMessage;
}
if (copyFileError.empty()) {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, emsg.str());
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, emsg.str());
return -1;
}
copyFileErrorMessage = emsg.str();
@@ -866,24 +1013,22 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
if (!copyFileError.empty()) {
- this->Makefile->AddDefinition(copyFileError,
- copyFileErrorMessage.c_str());
+ this->Makefile->AddDefinition(copyFileError, copyFileErrorMessage);
}
}
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:",
+ "CMakeTmp:" +
binDir);
return;
}
@@ -898,7 +1043,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
@@ -906,9 +1051,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)
@@ -928,8 +1072,8 @@ void cmCoreTryCompile::CleanupFiles(const char* binDir)
void cmCoreTryCompile::FindOutputFile(const std::string& targetName,
cmStateEnums::TargetType targetType)
{
- this->FindErrorMessage = "";
- this->OutputFile = "";
+ this->FindErrorMessage.clear();
+ this->OutputFile.clear();
std::string tmpOutputFile = "/";
if (targetType == cmStateEnums::EXECUTABLE) {
tmpOutputFile += targetName;
@@ -947,29 +1091,31 @@ 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");
// if a config was specified try that first
if (config && config[0]) {
- std::string tmp = "/";
- tmp += config;
- searchDirs.push_back(tmp);
+ std::string tmp = cmStrCat('/', config);
+ searchDirs.push_back(std::move(tmp));
}
- searchDirs.push_back("/Debug");
+ searchDirs.emplace_back("/Debug");
#if defined(__APPLE__)
- std::string app = "/Debug/" + targetName + ".app";
- searchDirs.push_back(app);
+ std::string app = "/" + targetName + ".app";
+ if (config && config[0]) {
+ std::string tmp = cmStrCat('/', config, app);
+ searchDirs.push_back(std::move(tmp));
+ }
+ std::string tmp = "/Debug" + app;
+ searchDirs.emplace_back(std::move(tmp));
+ searchDirs.push_back(std::move(app));
#endif
- searchDirs.push_back("/Development");
-
- for (std::vector<std::string>::const_iterator it = searchDirs.begin();
- it != searchDirs.end(); ++it) {
- std::string command = this->BinaryDirectory;
- command += *it;
- command += tmpOutputFile;
- if (cmSystemTools::FileExists(command.c_str())) {
+ searchDirs.emplace_back("/Development");
+
+ for (std::string const& sdir : searchDirs) {
+ std::string command = cmStrCat(this->BinaryDirectory, sdir, tmpOutputFile);
+ if (cmSystemTools::FileExists(command)) {
this->OutputFile = cmSystemTools::CollapseFullPath(command);
return;
}
diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h
index 365154dfb..ae714a63a 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
@@ -46,7 +46,7 @@ protected:
std::string BinaryDirectory;
std::string OutputFile;
std::string FindErrorMessage;
- bool SrcFileSignature;
+ bool SrcFileSignature = false;
private:
std::vector<std::string> WarnCMP0067;
diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx
index 69532e61b..9d492ba84 100644
--- a/Source/cmCreateTestSourceList.cxx
+++ b/Source/cmCreateTestSourceList.cxx
@@ -4,22 +4,21 @@
#include <algorithm>
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
-
-// cmCreateTestSourceList
-bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmCreateTestSourceList(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 3) {
- this->SetError("called with wrong number of arguments.");
+ status.SetError("called with wrong number of arguments.");
return false;
}
- std::vector<std::string>::const_iterator i = args.begin();
+ auto i = args.begin();
std::string extraInclude;
std::string function;
std::vector<std::string> tests;
@@ -28,20 +27,17 @@ bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args,
if (*i == "EXTRA_INCLUDE") {
++i;
if (i == args.end()) {
- this->SetError("incorrect arguments to EXTRA_INCLUDE");
+ status.SetError("incorrect arguments to EXTRA_INCLUDE");
return false;
}
- extraInclude = "#include \"";
- extraInclude += *i;
- extraInclude += "\"\n";
+ extraInclude = cmStrCat("#include \"", *i, "\"\n");
} else if (*i == "FUNCTION") {
++i;
if (i == args.end()) {
- this->SetError("incorrect arguments to FUNCTION");
+ status.SetError("incorrect arguments to FUNCTION");
return false;
}
- function = *i;
- function += "(&ac, &av);\n";
+ function = cmStrCat(*i, "(&ac, &av);\n");
} else {
tests.push_back(*i);
}
@@ -56,13 +52,12 @@ bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args,
// Name of the test driver
// make sure they specified an extension
if (cmSystemTools::GetFilenameExtension(*i).size() < 2) {
- this->SetError(
+ status.SetError(
"You must specify a file extension for the test driver file.");
return false;
}
- std::string driver = this->Makefile->GetCurrentBinaryDirectory();
- driver += "/";
- driver += *i;
+ cmMakefile& mf = status.GetMakefile();
+ std::string driver = cmStrCat(mf.GetCurrentBinaryDirectory(), '/', *i);
++i;
std::string configFile = cmSystemTools::GetCMakeRoot();
@@ -70,7 +65,7 @@ bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args,
configFile += "/Templates/TestDriver.cxx.in";
// Create the test driver file
- std::vector<std::string>::const_iterator testsBegin = i;
+ auto testsBegin = i;
std::vector<std::string> tests_func_name;
// The rest of the arguments consist of a list of test source files.
@@ -124,37 +119,32 @@ bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args,
numTests++;
}
if (!extraInclude.empty()) {
- this->Makefile->AddDefinition("CMAKE_TESTDRIVER_EXTRA_INCLUDES",
- extraInclude.c_str());
+ mf.AddDefinition("CMAKE_TESTDRIVER_EXTRA_INCLUDES", extraInclude);
}
if (!function.empty()) {
- this->Makefile->AddDefinition("CMAKE_TESTDRIVER_ARGVC_FUNCTION",
- function.c_str());
+ mf.AddDefinition("CMAKE_TESTDRIVER_ARGVC_FUNCTION", function);
}
- this->Makefile->AddDefinition("CMAKE_FORWARD_DECLARE_TESTS",
- forwardDeclareCode.c_str());
- this->Makefile->AddDefinition("CMAKE_FUNCTION_TABLE_ENTIRES",
- functionMapCode.c_str());
+ mf.AddDefinition("CMAKE_FORWARD_DECLARE_TESTS", forwardDeclareCode);
+ mf.AddDefinition("CMAKE_FUNCTION_TABLE_ENTIRES", functionMapCode);
bool res = true;
- if (!this->Makefile->ConfigureFile(configFile.c_str(), driver.c_str(), false,
- true, false)) {
+ if (!mf.ConfigureFile(configFile, driver, false, true, false)) {
res = false;
}
// Construct the source list.
std::string sourceListValue;
{
- cmSourceFile* sf = this->Makefile->GetOrCreateSource(driver);
+ cmSourceFile* sf = mf.GetOrCreateSource(driver);
sf->SetProperty("ABSTRACT", "0");
sourceListValue = args[1];
}
for (i = testsBegin; i != tests.end(); ++i) {
- cmSourceFile* sf = this->Makefile->GetOrCreateSource(*i);
+ cmSourceFile* sf = mf.GetOrCreateSource(*i);
sf->SetProperty("ABSTRACT", "0");
sourceListValue += ";";
sourceListValue += *i;
}
- this->Makefile->AddDefinition(sourceList, sourceListValue.c_str());
+ mf.AddDefinition(sourceList, sourceListValue);
return res;
}
diff --git a/Source/cmCreateTestSourceList.h b/Source/cmCreateTestSourceList.h
index f1f1e4b8a..19503f43d 100644
--- a/Source/cmCreateTestSourceList.h
+++ b/Source/cmCreateTestSourceList.h
@@ -3,34 +3,14 @@
#ifndef cmCreateTestSourceList_h
#define cmCreateTestSourceList_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmCreateTestSourceList
- * \brief Test driver generation command
- *
- */
-
-class cmCreateTestSourceList : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmCreateTestSourceList; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmCreateTestSourceList(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmCryptoHash.cxx b/Source/cmCryptoHash.cxx
index 7995b2cb3..dc7d939c9 100644
--- a/Source/cmCryptoHash.cxx
+++ b/Source/cmCryptoHash.cxx
@@ -2,10 +2,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCryptoHash.h"
+#include <cm/memory>
+
+#include "cmsys/FStream.hxx"
+
#include "cm_kwiml.h"
#include "cm_rhash.h"
-#include "cmsys/FStream.hxx"
-#include <string.h>
static unsigned int const cmCryptoHashAlgoToId[] = {
/* clang-format needs this comment to break after the opening brace */
@@ -43,39 +45,39 @@ cmCryptoHash::~cmCryptoHash()
rhash_free(this->CTX);
}
-CM_AUTO_PTR<cmCryptoHash> cmCryptoHash::New(const char* algo)
+std::unique_ptr<cmCryptoHash> cmCryptoHash::New(cm::string_view algo)
{
- if (strcmp(algo, "MD5") == 0) {
- return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoMD5));
+ if (algo == "MD5") {
+ return cm::make_unique<cmCryptoHash>(AlgoMD5);
}
- if (strcmp(algo, "SHA1") == 0) {
- return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA1));
+ if (algo == "SHA1") {
+ return cm::make_unique<cmCryptoHash>(AlgoSHA1);
}
- if (strcmp(algo, "SHA224") == 0) {
- return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA224));
+ if (algo == "SHA224") {
+ return cm::make_unique<cmCryptoHash>(AlgoSHA224);
}
- if (strcmp(algo, "SHA256") == 0) {
- return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA256));
+ if (algo == "SHA256") {
+ return cm::make_unique<cmCryptoHash>(AlgoSHA256);
}
- if (strcmp(algo, "SHA384") == 0) {
- return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA384));
+ if (algo == "SHA384") {
+ return cm::make_unique<cmCryptoHash>(AlgoSHA384);
}
- if (strcmp(algo, "SHA512") == 0) {
- return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA512));
+ if (algo == "SHA512") {
+ return cm::make_unique<cmCryptoHash>(AlgoSHA512);
}
- if (strcmp(algo, "SHA3_224") == 0) {
- return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA3_224));
+ if (algo == "SHA3_224") {
+ return cm::make_unique<cmCryptoHash>(AlgoSHA3_224);
}
- if (strcmp(algo, "SHA3_256") == 0) {
- return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA3_256));
+ if (algo == "SHA3_256") {
+ return cm::make_unique<cmCryptoHash>(AlgoSHA3_256);
}
- if (strcmp(algo, "SHA3_384") == 0) {
- return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA3_384));
+ if (algo == "SHA3_384") {
+ return cm::make_unique<cmCryptoHash>(AlgoSHA3_384);
}
- if (strcmp(algo, "SHA3_512") == 0) {
- return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA3_512));
+ if (algo == "SHA3_512") {
+ return cm::make_unique<cmCryptoHash>(AlgoSHA3_512);
}
- return CM_AUTO_PTR<cmCryptoHash>(CM_NULLPTR);
+ return std::unique_ptr<cmCryptoHash>(nullptr);
}
bool cmCryptoHash::IntFromHexDigit(char input, char& output)
@@ -103,20 +105,18 @@ std::string cmCryptoHash::ByteHashToString(
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
std::string res;
- for (std::vector<unsigned char>::const_iterator vit = hash.begin();
- vit != hash.end(); ++vit) {
- res.push_back(hex[(*vit) >> 4]);
- res.push_back(hex[(*vit) & 0xF]);
+ res.reserve(hash.size() * 2);
+ for (unsigned char v : hash) {
+ res.push_back(hex[v >> 4]);
+ res.push_back(hex[v & 0xF]);
}
return res;
}
-std::vector<unsigned char> cmCryptoHash::ByteHashString(
- const std::string& input)
+std::vector<unsigned char> cmCryptoHash::ByteHashString(cm::string_view input)
{
this->Initialize();
- this->Append(reinterpret_cast<unsigned char const*>(input.c_str()),
- static_cast<int>(input.size()));
+ this->Append(input);
return this->Finalize();
}
@@ -154,7 +154,7 @@ std::vector<unsigned char> cmCryptoHash::ByteHashFile(const std::string& file)
return std::vector<unsigned char>();
}
-std::string cmCryptoHash::HashString(const std::string& input)
+std::string cmCryptoHash::HashString(cm::string_view input)
{
return ByteHashToString(this->ByteHashString(input));
}
@@ -174,9 +174,9 @@ void cmCryptoHash::Append(void const* buf, size_t sz)
rhash_update(this->CTX, buf, sz);
}
-void cmCryptoHash::Append(std::string const& str)
+void cmCryptoHash::Append(cm::string_view input)
{
- this->Append(str.c_str(), str.size());
+ rhash_update(this->CTX, input.data(), input.size());
}
std::vector<unsigned char> cmCryptoHash::Finalize()
diff --git a/Source/cmCryptoHash.h b/Source/cmCryptoHash.h
index c380d85ff..f27bb5db4 100644
--- a/Source/cmCryptoHash.h
+++ b/Source/cmCryptoHash.h
@@ -3,21 +3,20 @@
#ifndef cmCryptoHash_h
#define cmCryptoHash_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include <stddef.h>
+#include <cstddef>
+#include <memory>
#include <string>
#include <vector>
-#include "cm_auto_ptr.hxx"
+#include <cm/string_view>
/**
* @brief Abstract base class for cryptographic hash generators
*/
class cmCryptoHash
{
- CM_DISABLE_COPY(cmCryptoHash)
-
public:
enum Algo
{
@@ -36,13 +35,16 @@ public:
cmCryptoHash(Algo algo);
~cmCryptoHash();
+ cmCryptoHash(cmCryptoHash const&) = delete;
+ cmCryptoHash& operator=(cmCryptoHash const&) = delete;
+
/// @brief Returns a new hash generator of the requested type
/// @arg algo Hash type name. Supported hash types are
/// MD5, SHA1, SHA224, SHA256, SHA384, SHA512,
/// SHA3_224, SHA3_256, SHA3_384, SHA3_512
/// @return A valid auto pointer if algo is supported or
/// an invalid/NULL pointer otherwise
- static CM_AUTO_PTR<cmCryptoHash> New(const char* algo);
+ static std::unique_ptr<cmCryptoHash> New(cm::string_view algo);
/// @brief Converts a hex character to its binary value (4 bits)
/// @arg input Hex character [0-9a-fA-F].
@@ -55,7 +57,7 @@ public:
/// @brief Calculates a binary hash from string input data
/// @return Binary hash vector
- std::vector<unsigned char> ByteHashString(const std::string& input);
+ std::vector<unsigned char> ByteHashString(cm::string_view input);
/// @brief Calculates a binary hash from file content
/// @see ByteHashString()
@@ -65,7 +67,7 @@ public:
/// @brief Calculates a hash string from string input data
/// @return Sequence of hex characters pairs for each byte of the binary hash
- std::string HashString(const std::string& input);
+ std::string HashString(cm::string_view input);
/// @brief Calculates a hash string from file content
/// @see HashString()
@@ -75,7 +77,7 @@ public:
void Initialize();
void Append(void const*, size_t);
- void Append(std::string const& str);
+ void Append(cm::string_view input);
std::vector<unsigned char> Finalize();
std::string FinalizeHex();
diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx
index 341b8c077..233790e54 100644
--- a/Source/cmCurl.cxx
+++ b/Source/cmCurl.cxx
@@ -2,25 +2,26 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCurl.h"
-#include "cmThirdParty.h"
-
#if !defined(CMAKE_USE_SYSTEM_CURL) && !defined(_WIN32) && \
!defined(__APPLE__) && !defined(CURL_CA_BUNDLE) && !defined(CURL_CA_PATH)
-#define CMAKE_FIND_CAFILE
-#include "cmSystemTools.h"
+# define CMAKE_FIND_CAFILE
+# include "cmSystemTools.h"
#endif
+#include "cmStringAlgorithms.h"
// curl versions before 7.21.5 did not provide this error code
#if defined(LIBCURL_VERSION_NUM) && LIBCURL_VERSION_NUM < 0x071505
-#define CURLE_NOT_BUILT_IN 4
+# define CURLE_NOT_BUILT_IN 4
#endif
#define check_curl_result(result, errstr) \
- if ((result) != CURLE_OK && (result) != CURLE_NOT_BUILT_IN) { \
- e += e.empty() ? "" : "\n"; \
- e += (errstr); \
- e += ::curl_easy_strerror(result); \
- }
+ do { \
+ if ((result) != CURLE_OK && (result) != CURLE_NOT_BUILT_IN) { \
+ e += e.empty() ? "" : "\n"; \
+ e += (errstr); \
+ e += ::curl_easy_strerror(result); \
+ } \
+ } while (false)
std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile)
{
@@ -30,29 +31,67 @@ std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile)
check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: ");
}
#ifdef CMAKE_FIND_CAFILE
-#define CMAKE_CAFILE_FEDORA "/etc/pki/tls/certs/ca-bundle.crt"
+# define CMAKE_CAFILE_FEDORA "/etc/pki/tls/certs/ca-bundle.crt"
else if (cmSystemTools::FileExists(CMAKE_CAFILE_FEDORA, true)) {
::CURLcode res =
::curl_easy_setopt(curl, CURLOPT_CAINFO, CMAKE_CAFILE_FEDORA);
check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: ");
}
-#undef CMAKE_CAFILE_FEDORA
+# undef CMAKE_CAFILE_FEDORA
else {
-#define CMAKE_CAFILE_COMMON "/etc/ssl/certs/ca-certificates.crt"
+# define CMAKE_CAFILE_COMMON "/etc/ssl/certs/ca-certificates.crt"
if (cmSystemTools::FileExists(CMAKE_CAFILE_COMMON, true)) {
::CURLcode res =
::curl_easy_setopt(curl, CURLOPT_CAINFO, CMAKE_CAFILE_COMMON);
check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: ");
}
-#undef CMAKE_CAFILE_COMMON
-#define CMAKE_CAPATH_COMMON "/etc/ssl/certs"
+# undef CMAKE_CAFILE_COMMON
+# define CMAKE_CAPATH_COMMON "/etc/ssl/certs"
if (cmSystemTools::FileIsDirectory(CMAKE_CAPATH_COMMON)) {
::CURLcode res =
::curl_easy_setopt(curl, CURLOPT_CAPATH, CMAKE_CAPATH_COMMON);
check_curl_result(res, "Unable to set TLS/SSL Verify CAPATH: ");
}
-#undef CMAKE_CAPATH_COMMON
+# undef CMAKE_CAPATH_COMMON
}
#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 = cmStrCat("NETRC accepts OPTIONAL, IGNORED or REQUIRED but got: ",
+ 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 a2fa4b1c0..cb73ce631 100644
--- a/Source/cmCurl.h
+++ b/Source/cmCurl.h
@@ -3,11 +3,14 @@
#ifndef cmCurl_h
#define cmCurl_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cm_curl.h"
#include <string>
-std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile = CM_NULLPTR);
+#include "cm_curl.h"
+
+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/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index 5e377b574..09d269b20 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -2,38 +2,25 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCustomCommand.h"
-#include "cmMakefile.h"
-
-#include "cmConfigure.h"
+#include <utility>
-cmCustomCommand::cmCustomCommand()
- : Backtrace()
-{
- this->HaveComment = false;
- this->EscapeOldStyle = true;
- this->EscapeAllowMakeVars = false;
- this->UsesTerminal = false;
- this->CommandExpandLists = false;
-}
+#include "cmAlgorithms.h"
+#include "cmMakefile.h"
cmCustomCommand::cmCustomCommand(cmMakefile const* mf,
- const std::vector<std::string>& outputs,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines,
+ std::vector<std::string> outputs,
+ std::vector<std::string> byproducts,
+ std::vector<std::string> depends,
+ cmCustomCommandLines commandLines,
const char* comment,
const char* workingDirectory)
- : Outputs(outputs)
- , Byproducts(byproducts)
- , Depends(depends)
- , CommandLines(commandLines)
- , Backtrace()
+ : Outputs(std::move(outputs))
+ , Byproducts(std::move(byproducts))
+ , Depends(std::move(depends))
+ , CommandLines(std::move(commandLines))
, Comment(comment ? comment : "")
, WorkingDirectory(workingDirectory ? workingDirectory : "")
- , HaveComment(comment != CM_NULLPTR)
- , EscapeAllowMakeVars(false)
- , EscapeOldStyle(true)
- , CommandExpandLists(false)
+ , HaveComment(comment != nullptr)
{
if (mf) {
this->Backtrace = mf->GetBacktrace();
@@ -62,19 +49,18 @@ const cmCustomCommandLines& cmCustomCommand::GetCommandLines() const
const char* cmCustomCommand::GetComment() const
{
- const char* no_comment = CM_NULLPTR;
+ const char* no_comment = nullptr;
return this->HaveComment ? this->Comment.c_str() : no_comment;
}
void cmCustomCommand::AppendCommands(const cmCustomCommandLines& commandLines)
{
- this->CommandLines.insert(this->CommandLines.end(), commandLines.begin(),
- commandLines.end());
+ cmAppend(this->CommandLines, commandLines);
}
void cmCustomCommand::AppendDepends(const std::vector<std::string>& depends)
{
- this->Depends.insert(this->Depends.end(), depends.begin(), depends.end());
+ cmAppend(this->Depends, depends);
}
bool cmCustomCommand::GetEscapeOldStyle() const
@@ -102,21 +88,19 @@ cmListFileBacktrace const& cmCustomCommand::GetBacktrace() const
return this->Backtrace;
}
-cmCustomCommand::ImplicitDependsList const&
-cmCustomCommand::GetImplicitDepends() const
+cmImplicitDependsList const& cmCustomCommand::GetImplicitDepends() const
{
return this->ImplicitDepends;
}
-void cmCustomCommand::SetImplicitDepends(ImplicitDependsList const& l)
+void cmCustomCommand::SetImplicitDepends(cmImplicitDependsList const& l)
{
this->ImplicitDepends = l;
}
-void cmCustomCommand::AppendImplicitDepends(ImplicitDependsList const& l)
+void cmCustomCommand::AppendImplicitDepends(cmImplicitDependsList const& l)
{
- this->ImplicitDepends.insert(this->ImplicitDepends.end(), l.begin(),
- l.end());
+ cmAppend(this->ImplicitDepends, l);
}
bool cmCustomCommand::GetUsesTerminal() const
@@ -148,3 +132,13 @@ void cmCustomCommand::SetDepfile(const std::string& depfile)
{
this->Depfile = depfile;
}
+
+const std::string& cmCustomCommand::GetJobPool() const
+{
+ return this->JobPool;
+}
+
+void cmCustomCommand::SetJobPool(const std::string& job_pool)
+{
+ this->JobPool = job_pool;
+}
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index 9e82f2505..4689aceea 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -5,15 +5,20 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmCustomCommandLines.h"
-#include "cmListFileCache.h"
-
#include <string>
#include <utility>
#include <vector>
+#include "cmCustomCommandLines.h"
+#include "cmListFileCache.h"
+
class cmMakefile;
+class cmImplicitDependsList
+ : public std::vector<std::pair<std::string, std::string>>
+{
+};
+
/** \class cmCustomCommand
* \brief A class to encapsulate a custom command
*
@@ -22,16 +27,12 @@ class cmMakefile;
class cmCustomCommand
{
public:
- /** Default and copy constructors for STL containers. */
- cmCustomCommand();
-
/** Main constructor specifies all information for the command. */
- cmCustomCommand(cmMakefile const* mf,
- const std::vector<std::string>& outputs,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines,
- const char* comment, const char* workingDirectory);
+ cmCustomCommand(cmMakefile const* mf, std::vector<std::string> outputs,
+ std::vector<std::string> byproducts,
+ std::vector<std::string> depends,
+ cmCustomCommandLines commandLines, const char* comment,
+ const char* workingDirectory);
/** Get the output file produced by the command. */
const std::vector<std::string>& GetOutputs() const;
@@ -72,13 +73,9 @@ public:
/** Backtrace of the command that created this custom command. */
cmListFileBacktrace const& GetBacktrace() const;
- typedef std::pair<std::string, std::string> ImplicitDependsPair;
- class ImplicitDependsList : public std::vector<ImplicitDependsPair>
- {
- };
- void SetImplicitDepends(ImplicitDependsList const&);
- void AppendImplicitDepends(ImplicitDependsList const&);
- ImplicitDependsList const& GetImplicitDepends() const;
+ void SetImplicitDepends(cmImplicitDependsList const&);
+ void AppendImplicitDepends(cmImplicitDependsList const&);
+ cmImplicitDependsList const& GetImplicitDepends() const;
/** Set/Get whether this custom command should be given access to the
real console (if possible). */
@@ -93,21 +90,26 @@ public:
const std::string& GetDepfile() const;
void SetDepfile(const std::string& depfile);
+ /** Set/Get the job_pool (used by the Ninja generator) */
+ const std::string& GetJobPool() const;
+ void SetJobPool(const std::string& job_pool);
+
private:
std::vector<std::string> Outputs;
std::vector<std::string> Byproducts;
std::vector<std::string> Depends;
cmCustomCommandLines CommandLines;
cmListFileBacktrace Backtrace;
- ImplicitDependsList ImplicitDepends;
+ cmImplicitDependsList ImplicitDepends;
std::string Comment;
std::string WorkingDirectory;
std::string Depfile;
- bool HaveComment;
- bool EscapeAllowMakeVars;
- bool EscapeOldStyle;
- bool UsesTerminal;
- bool CommandExpandLists;
+ std::string JobPool;
+ bool HaveComment = false;
+ bool EscapeAllowMakeVars = false;
+ bool EscapeOldStyle = true;
+ bool UsesTerminal = false;
+ bool CommandExpandLists = false;
};
#endif
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 67213ecaa..c1f412df8 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -2,53 +2,94 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCustomCommandGenerator.h"
+#include <cstddef>
+#include <memory>
+#include <utility>
+
+#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmOutputConverter.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cm_auto_ptr.hxx"
-#include "cmConfigure.h"
+namespace {
+void AppendPaths(const std::vector<std::string>& inputs,
+ cmGeneratorExpression const& ge, cmLocalGenerator* lg,
+ std::string const& config, std::vector<std::string>& output)
+{
+ for (std::string const& in : inputs) {
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(in);
+ std::vector<std::string> result =
+ cmExpandedList(cge->Evaluate(lg, config));
+ for (std::string& it : result) {
+ cmSystemTools::ConvertToUnixSlashes(it);
+ if (cmSystemTools::FileIsFullPath(it)) {
+ it = cmSystemTools::CollapseFullPath(it);
+ }
+ }
+ cmAppend(output, result);
+ }
+}
+}
cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
- const std::string& config,
+ std::string config,
cmLocalGenerator* lg)
: CC(cc)
- , Config(config)
+ , Config(std::move(config))
, LG(lg)
, OldStyle(cc.GetEscapeOldStyle())
, MakeVars(cc.GetEscapeAllowMakeVars())
- , GE(new cmGeneratorExpression(cc.GetBacktrace()))
- , DependsDone(false)
+ , EmulatorsWithArguments(cc.GetCommandLines().size())
{
+ cmGeneratorExpression ge(cc.GetBacktrace());
+
const cmCustomCommandLines& cmdlines = this->CC.GetCommandLines();
- for (cmCustomCommandLines::const_iterator cmdline = cmdlines.begin();
- cmdline != cmdlines.end(); ++cmdline) {
+ for (cmCustomCommandLine const& cmdline : cmdlines) {
cmCustomCommandLine argv;
- for (cmCustomCommandLine::const_iterator clarg = cmdline->begin();
- clarg != cmdline->end(); ++clarg) {
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = this->GE->Parse(*clarg);
+ for (std::string const& clarg : cmdline) {
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(clarg);
std::string parsed_arg = cge->Evaluate(this->LG, this->Config);
if (this->CC.GetCommandExpandLists()) {
- std::vector<std::string> ExpandedArg;
- cmSystemTools::ExpandListArgument(parsed_arg, ExpandedArg);
- argv.insert(argv.end(), ExpandedArg.begin(), ExpandedArg.end());
+ cmAppend(argv, cmExpandedList(parsed_arg));
} else {
- argv.push_back(parsed_arg);
+ argv.push_back(std::move(parsed_arg));
}
}
- this->CommandLines.push_back(argv);
+
+ // Later code assumes at least one entry exists, but expanding
+ // lists on an empty command may have left this empty.
+ // FIXME: Should we define behavior for removing empty commands?
+ if (argv.empty()) {
+ argv.emplace_back();
+ }
+
+ this->CommandLines.push_back(std::move(argv));
+ }
+
+ AppendPaths(cc.GetByproducts(), ge, this->LG, this->Config,
+ this->Byproducts);
+ AppendPaths(cc.GetDepends(), ge, this->LG, this->Config, this->Depends);
+
+ const std::string& workingdirectory = this->CC.GetWorkingDirectory();
+ if (!workingdirectory.empty()) {
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(workingdirectory);
+ this->WorkingDirectory = cge->Evaluate(this->LG, this->Config);
+ // Convert working directory to a full path.
+ if (!this->WorkingDirectory.empty()) {
+ std::string const& build_dir = this->LG->GetCurrentBinaryDirectory();
+ this->WorkingDirectory =
+ cmSystemTools::CollapseFullPath(this->WorkingDirectory, build_dir);
+ }
}
-}
-cmCustomCommandGenerator::~cmCustomCommandGenerator()
-{
- delete this->GE;
+ this->FillEmulatorsWithArguments();
}
unsigned int cmCustomCommandGenerator::GetNumberOfCommands() const
@@ -56,19 +97,36 @@ unsigned int cmCustomCommandGenerator::GetNumberOfCommands() const
return static_cast<unsigned int>(this->CC.GetCommandLines().size());
}
-const char* cmCustomCommandGenerator::GetCrossCompilingEmulator(
- unsigned int c) const
+void cmCustomCommandGenerator::FillEmulatorsWithArguments()
{
if (!this->LG->GetMakefile()->IsOn("CMAKE_CROSSCOMPILING")) {
- return CM_NULLPTR;
+ return;
}
- std::string const& argv0 = this->CommandLines[c][0];
- cmGeneratorTarget* target = this->LG->FindGeneratorTargetToUse(argv0);
- if (target && target->GetType() == cmStateEnums::EXECUTABLE &&
- !target->IsImported()) {
- return target->GetProperty("CROSSCOMPILING_EMULATOR");
+
+ for (unsigned int c = 0; c < this->GetNumberOfCommands(); ++c) {
+ std::string const& argv0 = this->CommandLines[c][0];
+ cmGeneratorTarget* target = this->LG->FindGeneratorTargetToUse(argv0);
+ if (target && target->GetType() == cmStateEnums::EXECUTABLE &&
+ !target->IsImported()) {
+
+ const char* emulator_property =
+ target->GetProperty("CROSSCOMPILING_EMULATOR");
+ if (!emulator_property) {
+ continue;
+ }
+
+ cmExpandList(emulator_property, this->EmulatorsWithArguments[c]);
+ }
}
- return CM_NULLPTR;
+}
+
+std::vector<std::string> cmCustomCommandGenerator::GetCrossCompilingEmulator(
+ unsigned int c) const
+{
+ if (c >= this->EmulatorsWithArguments.size()) {
+ return std::vector<std::string>();
+ }
+ return this->EmulatorsWithArguments[c];
}
const char* cmCustomCommandGenerator::GetArgv0Location(unsigned int c) const
@@ -81,13 +139,26 @@ const char* cmCustomCommandGenerator::GetArgv0Location(unsigned int c) const
!this->LG->GetMakefile()->IsOn("CMAKE_CROSSCOMPILING"))) {
return target->GetLocation(this->Config);
}
- return CM_NULLPTR;
+ return nullptr;
+}
+
+bool cmCustomCommandGenerator::HasOnlyEmptyCommandLines() const
+{
+ for (size_t i = 0; i < this->CommandLines.size(); ++i) {
+ for (size_t j = 0; j < this->CommandLines[i].size(); ++j) {
+ if (!this->CommandLines[i][j].empty()) {
+ return false;
+ }
+ }
+ }
+ return true;
}
std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const
{
- if (const char* emulator = this->GetCrossCompilingEmulator(c)) {
- return std::string(emulator);
+ std::vector<std::string> emulator = this->GetCrossCompilingEmulator(c);
+ if (!emulator.empty()) {
+ return emulator[0];
}
if (const char* location = this->GetArgv0Location(c)) {
return std::string(location);
@@ -104,9 +175,7 @@ std::string escapeForShellOldStyle(const std::string& str)
std::string temp = str;
if (temp.find(" ") != std::string::npos &&
temp.find("\"") == std::string::npos) {
- result = "\"";
- result += str;
- result += "\"";
+ result = cmStrCat('"', str, '"');
return result;
}
return str;
@@ -125,14 +194,24 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c,
std::string& cmd) const
{
unsigned int offset = 1;
- if (this->GetCrossCompilingEmulator(c) != CM_NULLPTR) {
+ std::vector<std::string> emulator = this->GetCrossCompilingEmulator(c);
+ if (!emulator.empty()) {
+ for (unsigned j = 1; j < emulator.size(); ++j) {
+ cmd += " ";
+ if (this->OldStyle) {
+ cmd += escapeForShellOldStyle(emulator[j]);
+ } else {
+ cmd += this->LG->EscapeForShell(emulator[j], this->MakeVars);
+ }
+ }
+
offset = 0;
}
+
cmCustomCommandLine const& commandLine = this->CommandLines[c];
for (unsigned int j = offset; j < commandLine.size(); ++j) {
std::string arg;
- if (const char* location =
- j == 0 ? this->GetArgv0Location(c) : CM_NULLPTR) {
+ if (const char* location = j == 0 ? this->GetArgv0Location(c) : nullptr) {
// GetCommand returned the emulator instead of the argv0 location,
// so transform the latter now.
arg = location;
@@ -143,8 +222,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);
}
}
}
@@ -156,7 +234,7 @@ const char* cmCustomCommandGenerator::GetComment() const
std::string cmCustomCommandGenerator::GetWorkingDirectory() const
{
- return this->CC.GetWorkingDirectory();
+ return this->WorkingDirectory;
}
std::vector<std::string> const& cmCustomCommandGenerator::GetOutputs() const
@@ -166,28 +244,10 @@ std::vector<std::string> const& cmCustomCommandGenerator::GetOutputs() const
std::vector<std::string> const& cmCustomCommandGenerator::GetByproducts() const
{
- return this->CC.GetByproducts();
+ return this->Byproducts;
}
std::vector<std::string> const& cmCustomCommandGenerator::GetDepends() const
{
- if (!this->DependsDone) {
- this->DependsDone = true;
- std::vector<std::string> depends = this->CC.GetDepends();
- for (std::vector<std::string>::const_iterator i = depends.begin();
- i != depends.end(); ++i) {
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = this->GE->Parse(*i);
- std::vector<std::string> result;
- cmSystemTools::ExpandListArgument(cge->Evaluate(this->LG, this->Config),
- result);
- for (std::vector<std::string>::iterator it = result.begin();
- it != result.end(); ++it) {
- if (cmSystemTools::FileIsFullPath(it->c_str())) {
- *it = cmSystemTools::CollapseFullPath(*it);
- }
- }
- this->Depends.insert(this->Depends.end(), result.begin(), result.end());
- }
- }
return this->Depends;
}
diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h
index 0a2adb524..67ee9e0e1 100644
--- a/Source/cmCustomCommandGenerator.h
+++ b/Source/cmCustomCommandGenerator.h
@@ -4,13 +4,13 @@
#define cmCustomCommandGenerator_h
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmCustomCommandLines.h"
#include <string>
#include <vector>
+#include "cmCustomCommandLines.h"
+
class cmCustomCommand;
-class cmGeneratorExpression;
class cmLocalGenerator;
class cmCustomCommandGenerator
@@ -20,18 +20,22 @@ class cmCustomCommandGenerator
cmLocalGenerator* LG;
bool OldStyle;
bool MakeVars;
- cmGeneratorExpression* GE;
- mutable bool DependsDone;
- mutable std::vector<std::string> Depends;
cmCustomCommandLines CommandLines;
+ std::vector<std::vector<std::string>> EmulatorsWithArguments;
+ std::vector<std::string> Byproducts;
+ std::vector<std::string> Depends;
+ std::string WorkingDirectory;
- const char* GetCrossCompilingEmulator(unsigned int c) const;
+ void FillEmulatorsWithArguments();
+ std::vector<std::string> GetCrossCompilingEmulator(unsigned int c) const;
const char* GetArgv0Location(unsigned int c) const;
public:
- cmCustomCommandGenerator(cmCustomCommand const& cc,
- const std::string& config, cmLocalGenerator* lg);
- ~cmCustomCommandGenerator();
+ cmCustomCommandGenerator(cmCustomCommand const& cc, std::string config,
+ cmLocalGenerator* lg);
+ cmCustomCommandGenerator(const cmCustomCommandGenerator&) = delete;
+ cmCustomCommandGenerator& operator=(const cmCustomCommandGenerator&) =
+ delete;
cmCustomCommand const& GetCC() const { return this->CC; }
unsigned int GetNumberOfCommands() const;
std::string GetCommand(unsigned int c) const;
@@ -41,6 +45,7 @@ public:
std::vector<std::string> const& GetOutputs() const;
std::vector<std::string> const& GetByproducts() const;
std::vector<std::string> const& GetDepends() const;
+ bool HasOnlyEmptyCommandLines() const;
};
#endif
diff --git a/Source/cmCustomCommandLines.cxx b/Source/cmCustomCommandLines.cxx
new file mode 100644
index 000000000..37ad75b7c
--- /dev/null
+++ b/Source/cmCustomCommandLines.cxx
@@ -0,0 +1,22 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCustomCommandLines.h"
+
+cmCustomCommandLine cmMakeCommandLine(
+ std::initializer_list<cm::string_view> ilist)
+{
+ cmCustomCommandLine commandLine;
+ commandLine.reserve(ilist.size());
+ for (cm::string_view cmd : ilist) {
+ commandLine.emplace_back(cmd);
+ }
+ return commandLine;
+}
+
+cmCustomCommandLines cmMakeSingleCommandLine(
+ std::initializer_list<cm::string_view> ilist)
+{
+ cmCustomCommandLines commandLines;
+ commandLines.push_back(cmMakeCommandLine(ilist));
+ return commandLines;
+}
diff --git a/Source/cmCustomCommandLines.h b/Source/cmCustomCommandLines.h
index 36838f23f..ead579280 100644
--- a/Source/cmCustomCommandLines.h
+++ b/Source/cmCustomCommandLines.h
@@ -5,25 +5,28 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <initializer_list>
#include <string>
#include <vector>
+#include <cm/string_view> // IWYU pragma: keep
+
/** Data structure to represent a single command line. */
class cmCustomCommandLine : public std::vector<std::string>
{
-public:
- typedef std::vector<std::string> Superclass;
- typedef Superclass::iterator iterator;
- typedef Superclass::const_iterator const_iterator;
};
/** Data structure to represent a list of command lines. */
class cmCustomCommandLines : public std::vector<cmCustomCommandLine>
{
-public:
- typedef std::vector<cmCustomCommandLine> Superclass;
- typedef Superclass::iterator iterator;
- typedef Superclass::const_iterator const_iterator;
};
+/** Return a command line from a list of command line parts. */
+cmCustomCommandLine cmMakeCommandLine(
+ std::initializer_list<cm::string_view> ilist);
+
+/** Return a command line vector with a single command line. */
+cmCustomCommandLines cmMakeSingleCommandLine(
+ std::initializer_list<cm::string_view> ilist);
+
#endif
diff --git a/Source/cmCustomCommandTypes.h b/Source/cmCustomCommandTypes.h
new file mode 100644
index 000000000..d4bf1f9c3
--- /dev/null
+++ b/Source/cmCustomCommandTypes.h
@@ -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. */
+#ifndef cmCustomCommandTypes_h
+#define cmCustomCommandTypes_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+
+/** Target custom command type */
+enum class cmCustomCommandType
+{
+ PRE_BUILD,
+ PRE_LINK,
+ POST_BUILD
+};
+
+/** Where the command originated from. */
+enum class cmCommandOrigin
+{
+ Project,
+ Generator
+};
+
+/** How to handle custom commands for object libraries */
+enum class cmObjectLibraryCommands
+{
+ Reject,
+ Accept
+};
+
+/** Utility target output source file name. */
+struct cmUtilityOutput
+{
+ std::string Name;
+ std::string NameCMP0049;
+};
+
+#endif
diff --git a/Source/cmDefinePropertyCommand.cxx b/Source/cmDefinePropertyCommand.cxx
index 86a83dabe..f4e4fda4d 100644
--- a/Source/cmDefinePropertyCommand.cxx
+++ b/Source/cmDefinePropertyCommand.cxx
@@ -2,19 +2,17 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDefinePropertyCommand.h"
-#include <sstream>
-
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmProperty.h"
#include "cmState.h"
+#include "cmStringAlgorithms.h"
-class cmExecutionStatus;
-
-bool cmDefinePropertyCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmDefinePropertyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
@@ -37,17 +35,17 @@ bool cmDefinePropertyCommand::InitialPass(std::vector<std::string> const& args,
} else if (scope_arg == "CACHED_VARIABLE") {
scope = cmProperty::CACHED_VARIABLE;
} else {
- std::ostringstream e;
- e << "given invalid scope " << scope_arg << ". "
- << "Valid scopes are "
- << "GLOBAL, DIRECTORY, TARGET, SOURCE, "
- << "TEST, VARIABLE, CACHED_VARIABLE.";
- this->SetError(e.str());
+ status.SetError(cmStrCat("given invalid scope ", scope_arg,
+ ". Valid scopes are GLOBAL, DIRECTORY, TARGET, "
+ "SOURCE, TEST, VARIABLE, CACHED_VARIABLE."));
return false;
}
// Parse remaining arguments.
bool inherited = false;
+ std::string PropertyName;
+ std::string BriefDocs;
+ std::string FullDocs;
enum Doing
{
DoingNone,
@@ -68,39 +66,36 @@ bool cmDefinePropertyCommand::InitialPass(std::vector<std::string> const& args,
inherited = true;
} else if (doing == DoingProperty) {
doing = DoingNone;
- this->PropertyName = args[i];
+ PropertyName = args[i];
} else if (doing == DoingBrief) {
- this->BriefDocs += args[i];
+ BriefDocs += args[i];
} else if (doing == DoingFull) {
- this->FullDocs += args[i];
+ FullDocs += args[i];
} else {
- std::ostringstream e;
- e << "given invalid argument \"" << args[i] << "\".";
- this->SetError(e.str());
+ status.SetError(cmStrCat("given invalid argument \"", args[i], "\"."));
return false;
}
}
// Make sure a property name was found.
- if (this->PropertyName.empty()) {
- this->SetError("not given a PROPERTY <name> argument.");
+ if (PropertyName.empty()) {
+ status.SetError("not given a PROPERTY <name> argument.");
return false;
}
// Make sure documentation was given.
- if (this->BriefDocs.empty()) {
- this->SetError("not given a BRIEF_DOCS <brief-doc> argument.");
+ if (BriefDocs.empty()) {
+ status.SetError("not given a BRIEF_DOCS <brief-doc> argument.");
return false;
}
- if (this->FullDocs.empty()) {
- this->SetError("not given a FULL_DOCS <full-doc> argument.");
+ if (FullDocs.empty()) {
+ status.SetError("not given a FULL_DOCS <full-doc> argument.");
return false;
}
// Actually define the property.
- this->Makefile->GetState()->DefineProperty(
- this->PropertyName, scope, this->BriefDocs.c_str(), this->FullDocs.c_str(),
- inherited);
+ status.GetMakefile().GetState()->DefineProperty(
+ PropertyName, scope, BriefDocs.c_str(), FullDocs.c_str(), inherited);
return true;
}
diff --git a/Source/cmDefinePropertyCommand.h b/Source/cmDefinePropertyCommand.h
index bc120c564..60dd76a0d 100644
--- a/Source/cmDefinePropertyCommand.h
+++ b/Source/cmDefinePropertyCommand.h
@@ -3,31 +3,14 @@
#ifndef cmDefinesPropertyCommand_h
#define cmDefinesPropertyCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmDefinePropertyCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE { return new cmDefinePropertyCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the input file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- std::string PropertyName;
- std::string BriefDocs;
- std::string FullDocs;
-};
+bool cmDefinePropertyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx
index 7aa7641e1..69a64276b 100644
--- a/Source/cmDefinitions.cxx
+++ b/Source/cmDefinitions.cxx
@@ -2,11 +2,13 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDefinitions.h"
-#include "cmConfigure.h"
-#include <assert.h>
-#include <set>
+#include <cassert>
+#include <functional>
+#include <unordered_set>
#include <utility>
+#include <cm/string_view>
+
cmDefinitions::Def cmDefinitions::NoDef;
cmDefinitions::Def const& cmDefinitions::GetInternal(const std::string& key,
@@ -14,10 +16,12 @@ cmDefinitions::Def const& cmDefinitions::GetInternal(const std::string& key,
StackIter end, bool raise)
{
assert(begin != end);
- MapType::iterator i = begin->Map.find(key);
- if (i != begin->Map.end()) {
- i->second.Used = true;
- return i->second;
+ {
+ auto it = begin->Map.find(cm::String::borrow(key));
+ if (it != begin->Map.end()) {
+ it->second.Used = true;
+ return it->second;
+ }
}
StackIter it = begin;
++it;
@@ -28,14 +32,14 @@ cmDefinitions::Def const& cmDefinitions::GetInternal(const std::string& key,
if (!raise) {
return def;
}
- return begin->Map.insert(MapType::value_type(key, def)).first->second;
+ return begin->Map.emplace(key, def).first->second;
}
-const char* cmDefinitions::Get(const std::string& key, StackIter begin,
- StackIter end)
+const std::string* cmDefinitions::Get(const std::string& key, StackIter begin,
+ StackIter end)
{
Def const& def = cmDefinitions::GetInternal(key, begin, end, false);
- return def.Exists ? def.c_str() : CM_NULLPTR;
+ return def.Value ? def.Value.str_if_stable() : nullptr;
}
void cmDefinitions::Raise(const std::string& key, StackIter begin,
@@ -48,49 +52,27 @@ bool cmDefinitions::HasKey(const std::string& key, StackIter begin,
StackIter end)
{
for (StackIter it = begin; it != end; ++it) {
- MapType::const_iterator i = it->Map.find(key);
- if (i != it->Map.end()) {
+ if (it->Map.find(cm::String::borrow(key)) != it->Map.end()) {
return true;
}
}
return false;
}
-void cmDefinitions::Set(const std::string& key, const char* value)
-{
- Def def(value);
- this->Map[key] = def;
-}
-
-std::vector<std::string> cmDefinitions::UnusedKeys() const
-{
- std::vector<std::string> keys;
- keys.reserve(this->Map.size());
- // Consider local definitions.
- for (MapType::const_iterator mi = this->Map.begin(); mi != this->Map.end();
- ++mi) {
- if (!mi->second.Used) {
- keys.push_back(mi->first);
- }
- }
- return keys;
-}
-
cmDefinitions cmDefinitions::MakeClosure(StackIter begin, StackIter end)
{
cmDefinitions closure;
- std::set<std::string> undefined;
+ std::unordered_set<cm::string_view> undefined;
for (StackIter it = begin; it != end; ++it) {
// Consider local definitions.
- for (MapType::const_iterator mi = it->Map.begin(); mi != it->Map.end();
- ++mi) {
+ for (auto const& mi : it->Map) {
// Use this key if it is not already set or unset.
- if (closure.Map.find(mi->first) == closure.Map.end() &&
- undefined.find(mi->first) == undefined.end()) {
- if (mi->second.Exists) {
- closure.Map.insert(*mi);
+ if (closure.Map.find(mi.first) == closure.Map.end() &&
+ undefined.find(mi.first.view()) == undefined.end()) {
+ if (mi.second.Value) {
+ closure.Map.insert(mi);
} else {
- undefined.insert(mi->first);
+ undefined.emplace(mi.first.view());
}
}
}
@@ -101,19 +83,41 @@ cmDefinitions cmDefinitions::MakeClosure(StackIter begin, StackIter end)
std::vector<std::string> cmDefinitions::ClosureKeys(StackIter begin,
StackIter end)
{
- std::set<std::string> bound;
std::vector<std::string> defined;
+ std::unordered_set<cm::string_view> bound;
for (StackIter it = begin; it != end; ++it) {
defined.reserve(defined.size() + it->Map.size());
- for (MapType::const_iterator mi = it->Map.begin(); mi != it->Map.end();
- ++mi) {
+ for (auto const& mi : it->Map) {
// Use this key if it is not already set or unset.
- if (bound.insert(mi->first).second && mi->second.Exists) {
- defined.push_back(mi->first);
+ if (bound.emplace(mi.first.view()).second && mi.second.Value) {
+ defined.push_back(*mi.first.str_if_stable());
}
}
}
return defined;
}
+
+void cmDefinitions::Set(const std::string& key, cm::string_view value)
+{
+ this->Map[key] = Def(value);
+}
+
+void cmDefinitions::Unset(const std::string& key)
+{
+ this->Map[key] = Def();
+}
+
+std::vector<std::string> cmDefinitions::UnusedKeys() const
+{
+ std::vector<std::string> keys;
+ keys.reserve(this->Map.size());
+ // Consider local definitions.
+ for (auto const& mi : this->Map) {
+ if (!mi.second.Used) {
+ keys.push_back(*mi.first.str_if_stable());
+ }
+ }
+ return keys;
+}
diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h
index ddb89188c..0e38fb1af 100644
--- a/Source/cmDefinitions.h
+++ b/Source/cmDefinitions.h
@@ -5,11 +5,15 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <functional>
#include <string>
+#include <unordered_map>
#include <vector>
+#include <cm/string_view>
+
#include "cmLinkedTree.h"
-#include "cm_unordered_map.hxx"
+#include "cmString.hxx"
/** \class cmDefinitions
* \brief Store a scope of variable definitions for CMake language.
@@ -20,58 +24,49 @@
*/
class cmDefinitions
{
- typedef cmLinkedTree<cmDefinitions>::iterator StackIter;
+ using StackIter = cmLinkedTree<cmDefinitions>::iterator;
public:
- static const char* Get(const std::string& key, StackIter begin,
- StackIter end);
+ // -- Static member functions
+
+ static const std::string* Get(const std::string& key, StackIter begin,
+ StackIter end);
static void Raise(const std::string& key, StackIter begin, StackIter end);
static bool HasKey(const std::string& key, StackIter begin, StackIter end);
- /** Set (or unset if null) a value associated with a key. */
- void Set(const std::string& key, const char* value);
-
- std::vector<std::string> UnusedKeys() const;
-
static std::vector<std::string> ClosureKeys(StackIter begin, StackIter end);
static cmDefinitions MakeClosure(StackIter begin, StackIter end);
+ // -- Member functions
+
+ /** Set a value associated with a key. */
+ void Set(const std::string& key, cm::string_view value);
+
+ /** Unset a definition. */
+ void Unset(const std::string& key);
+
+ /** List of unused keys. */
+ std::vector<std::string> UnusedKeys() const;
+
private:
- // String with existence boolean.
- struct Def : public std::string
+ /** String with existence boolean. */
+ struct Def
{
- private:
- typedef std::string std_string;
-
public:
- Def()
- : std_string()
- , Exists(false)
- , Used(false)
- {
- }
- Def(const char* v)
- : std_string(v ? v : "")
- , Exists(v ? true : false)
- , Used(false)
- {
- }
- Def(const std_string& v)
- : std_string(v)
- , Exists(true)
- , Used(false)
+ Def() = default;
+ Def(cm::string_view value)
+ : Value(value)
{
}
- bool Exists;
- bool Used;
+ cm::String Value;
+ bool Used = false;
};
static Def NoDef;
- typedef CM_UNORDERED_MAP<std::string, Def> MapType;
- MapType Map;
+ std::unordered_map<cm::String, Def> Map;
static Def const& GetInternal(const std::string& key, StackIter begin,
StackIter end, bool raise);
diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx
index c898d12ba..129a5f72f 100644
--- a/Source/cmDepends.cxx
+++ b/Source/cmDepends.cxx
@@ -2,63 +2,51 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDepends.h"
-#include "cmFileTimeComparison.h"
+#include <sstream>
+#include <utility>
+
+#include "cmsys/FStream.hxx"
+
+#include "cmFileTime.h"
+#include "cmFileTimeCache.h"
#include "cmGeneratedFileStream.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmWorkingDirectory.h"
-#include "cmsys/FStream.hxx"
-#include <sstream>
-#include <string.h>
-#include <utility>
-
-cmDepends::cmDepends(cmLocalGenerator* lg, const char* targetDir)
- : CompileDirectory()
- , LocalGenerator(lg)
- , Verbose(false)
- , FileComparison(CM_NULLPTR)
- , TargetDirectory(targetDir)
- , MaxPath(16384)
- , Dependee(new char[MaxPath])
- , Depender(new char[MaxPath])
+cmDepends::cmDepends(cmLocalGenerator* lg, std::string targetDir)
+ : LocalGenerator(lg)
+ , TargetDirectory(std::move(targetDir))
{
}
-cmDepends::~cmDepends()
-{
- delete[] this->Dependee;
- delete[] this->Depender;
-}
+cmDepends::~cmDepends() = default;
bool cmDepends::Write(std::ostream& makeDepends, std::ostream& internalDepends)
{
- // Lookup the set of sources to scan.
- std::string srcLang = "CMAKE_DEPENDS_CHECK_";
- srcLang += this->Language;
- cmMakefile* mf = this->LocalGenerator->GetMakefile();
- const char* srcStr = mf->GetSafeDefinition(srcLang);
- std::vector<std::string> pairs;
- cmSystemTools::ExpandListArgument(srcStr, pairs);
-
- std::map<std::string, std::set<std::string> > dependencies;
- for (std::vector<std::string>::iterator si = pairs.begin();
- si != pairs.end();) {
- // Get the source and object file.
- std::string const& src = *si++;
- if (si == pairs.end()) {
- break;
+ std::map<std::string, std::set<std::string>> dependencies;
+ {
+ // Lookup the set of sources to scan.
+ std::vector<std::string> pairs;
+ {
+ std::string const srcLang = "CMAKE_DEPENDS_CHECK_" + this->Language;
+ cmMakefile* mf = this->LocalGenerator->GetMakefile();
+ cmExpandList(mf->GetSafeDefinition(srcLang), pairs);
+ }
+ for (auto si = pairs.begin(); si != pairs.end();) {
+ // Get the source and object file.
+ std::string const& src = *si++;
+ if (si == pairs.end()) {
+ break;
+ }
+ std::string const& obj = *si++;
+ dependencies[obj].insert(src);
}
- std::string const& obj = *si++;
- dependencies[obj].insert(src);
}
- for (std::map<std::string, std::set<std::string> >::const_iterator it =
- dependencies.begin();
- it != dependencies.end(); ++it) {
-
+ for (auto const& d : dependencies) {
// Write the dependencies for this pair.
- if (!this->WriteDependencies(it->second, it->first, makeDepends,
+ if (!this->WriteDependencies(d.second, d.first, makeDepends,
internalDepends)) {
return false;
}
@@ -72,32 +60,30 @@ bool cmDepends::Finalize(std::ostream& /*unused*/, std::ostream& /*unused*/)
return true;
}
-bool cmDepends::Check(const char* makeFile, const char* internalFile,
- std::map<std::string, DependencyVector>& validDeps)
+bool cmDepends::Check(const std::string& makeFile,
+ const std::string& internalFile,
+ DependencyMap& validDeps)
{
- // Dependency checks must be done in proper working directory.
- cmWorkingDirectory workdir(this->CompileDirectory);
-
// Check whether dependencies must be regenerated.
bool okay = true;
- cmsys::ifstream fin(internalFile);
+ cmsys::ifstream fin(internalFile.c_str());
if (!(fin && this->CheckDependencies(fin, internalFile, validDeps))) {
// Clear all dependencies so they will be regenerated.
this->Clear(makeFile);
cmSystemTools::RemoveFile(internalFile);
+ this->FileTimeCache->Remove(internalFile);
okay = false;
}
-
return okay;
}
-void cmDepends::Clear(const char* file)
+void cmDepends::Clear(const std::string& file)
{
// Print verbose output.
if (this->Verbose) {
std::ostringstream msg;
msg << "Clearing dependencies in \"" << file << "\"." << std::endl;
- cmSystemTools::Stdout(msg.str().c_str());
+ cmSystemTools::Stdout(msg.str());
}
// Write an empty dependency file.
@@ -116,48 +102,62 @@ bool cmDepends::WriteDependencies(const std::set<std::string>& /*unused*/,
return false;
}
-bool cmDepends::CheckDependencies(
- std::istream& internalDepends, const char* internalDependsFileName,
- std::map<std::string, DependencyVector>& validDeps)
+bool cmDepends::CheckDependencies(std::istream& internalDepends,
+ const std::string& internalDependsFileName,
+ DependencyMap& validDeps)
{
+ // Read internal depends file time
+ cmFileTime internalDependsTime;
+ if (!this->FileTimeCache->Load(internalDependsFileName,
+ internalDependsTime)) {
+ return false;
+ }
+
// Parse dependencies from the stream. If any dependee is missing
// or newer than the depender then dependencies should be
// regenerated.
bool okay = true;
bool dependerExists = false;
- DependencyVector* currentDependencies = CM_NULLPTR;
- while (internalDepends.getline(this->Dependee, this->MaxPath)) {
- if (this->Dependee[0] == 0 || this->Dependee[0] == '#' ||
- this->Dependee[0] == '\r') {
+ std::string line;
+ line.reserve(1024);
+ std::string depender;
+ std::string dependee;
+ cmFileTime dependerTime;
+ cmFileTime dependeeTime;
+ std::vector<std::string>* currentDependencies = nullptr;
+
+ while (std::getline(internalDepends, line)) {
+ // Check if this an empty or a comment line
+ if (line.empty() || line.front() == '#') {
continue;
}
- size_t len = internalDepends.gcount() - 1;
- if (this->Dependee[len - 1] == '\r') {
- len--;
- this->Dependee[len] = 0;
+ // Drop carriage return character at the end
+ if (line.back() == '\r') {
+ line.pop_back();
+ if (line.empty()) {
+ continue;
+ }
}
- if (this->Dependee[0] != ' ') {
- memcpy(this->Depender, this->Dependee, len + 1);
- // Calling FileExists() for the depender here saves in many cases 50%
- // of the calls to FileExists() further down in the loop. E.g. for
- // kdelibs/khtml this reduces the number of calls from 184k down to 92k,
- // or the time for cmake -E cmake_depends from 0.3 s down to 0.21 s.
- dependerExists = cmSystemTools::FileExists(this->Depender);
+ // Check if this a depender line
+ if (line.front() != ' ') {
+ depender = line;
+ dependerExists = this->FileTimeCache->Load(depender, dependerTime);
// If we erase validDeps[this->Depender] by overwriting it with an empty
// vector, we lose dependencies for dependers that have multiple
// entries. No need to initialize the entry, std::map will do so on first
// access.
- currentDependencies = &validDeps[this->Depender];
+ currentDependencies = &validDeps[depender];
continue;
}
- /*
- // Parse the dependency line.
- if(!this->ParseDependency(line.c_str()))
- {
- continue;
- }
- */
+
+ // This is a dependee line
+ dependee = line.substr(1);
+
+ // Add dependee to depender's list
+ if (currentDependencies != nullptr) {
+ currentDependencies->push_back(dependee);
+ }
// Dependencies must be regenerated
// * if the dependee does not exist
@@ -165,13 +165,8 @@ bool cmDepends::CheckDependencies(
// * if the depender does not exist, but the dependee is newer than the
// depends file
bool regenerate = false;
- const char* dependee = this->Dependee + 1;
- const char* depender = this->Depender;
- if (currentDependencies != CM_NULLPTR) {
- currentDependencies->push_back(dependee);
- }
-
- if (!cmSystemTools::FileExists(dependee)) {
+ bool dependeeExists = this->FileTimeCache->Load(dependee, dependeeTime);
+ if (!dependeeExists) {
// The dependee does not exist.
regenerate = true;
@@ -180,61 +175,55 @@ bool cmDepends::CheckDependencies(
std::ostringstream msg;
msg << "Dependee \"" << dependee << "\" does not exist for depender \""
<< depender << "\"." << std::endl;
- cmSystemTools::Stdout(msg.str().c_str());
+ cmSystemTools::Stdout(msg.str());
}
- } else {
- if (dependerExists) {
- // The dependee and depender both exist. Compare file times.
- int result = 0;
- if ((!this->FileComparison->FileTimeCompare(depender, dependee,
- &result) ||
- result < 0)) {
- // The depender is older than the dependee.
- regenerate = true;
-
- // Print verbose output.
- if (this->Verbose) {
- std::ostringstream msg;
- msg << "Dependee \"" << dependee << "\" is newer than depender \""
- << depender << "\"." << std::endl;
- cmSystemTools::Stdout(msg.str().c_str());
- }
+ } else if (dependerExists) {
+ // The dependee and depender both exist. Compare file times.
+ if (dependerTime.Older(dependeeTime)) {
+ // The depender is older than the dependee.
+ regenerate = true;
+
+ // Print verbose output.
+ if (this->Verbose) {
+ std::ostringstream msg;
+ msg << "Dependee \"" << dependee << "\" is newer than depender \""
+ << depender << "\"." << std::endl;
+ cmSystemTools::Stdout(msg.str());
}
- } else {
- // The dependee exists, but the depender doesn't. Regenerate if the
- // internalDepends file is older than the dependee.
- int result = 0;
- if ((!this->FileComparison->FileTimeCompare(internalDependsFileName,
- dependee, &result) ||
- result < 0)) {
- // The depends-file is older than the dependee.
- regenerate = true;
-
- // Print verbose output.
- if (this->Verbose) {
- std::ostringstream msg;
- msg << "Dependee \"" << dependee
- << "\" is newer than depends file \""
- << internalDependsFileName << "\"." << std::endl;
- cmSystemTools::Stdout(msg.str().c_str());
- }
+ }
+ } else {
+ // The dependee exists, but the depender doesn't. Regenerate if the
+ // internalDepends file is older than the dependee.
+ if (internalDependsTime.Older(dependeeTime)) {
+ // The depends-file is older than the dependee.
+ regenerate = true;
+
+ // Print verbose output.
+ if (this->Verbose) {
+ std::ostringstream msg;
+ msg << "Dependee \"" << dependee
+ << "\" is newer than depends file \"" << internalDependsFileName
+ << "\"." << std::endl;
+ cmSystemTools::Stdout(msg.str());
}
}
}
+
if (regenerate) {
// Dependencies must be regenerated.
okay = false;
// Remove the information of this depender from the map, it needs
// to be rescanned
- if (currentDependencies != CM_NULLPTR) {
- validDeps.erase(this->Depender);
- currentDependencies = CM_NULLPTR;
+ if (currentDependencies != nullptr) {
+ validDeps.erase(depender);
+ currentDependencies = nullptr;
}
// Remove the depender to be sure it is rebuilt.
if (dependerExists) {
cmSystemTools::RemoveFile(depender);
+ this->FileTimeCache->Remove(depender);
dependerExists = false;
}
}
@@ -246,22 +235,19 @@ bool cmDepends::CheckDependencies(
void cmDepends::SetIncludePathFromLanguage(const std::string& lang)
{
// Look for the new per "TARGET_" variant first:
- const char* includePath = CM_NULLPTR;
- std::string includePathVar = "CMAKE_";
- includePathVar += lang;
- includePathVar += "_TARGET_INCLUDE_PATH";
+ const char* includePath = nullptr;
+ std::string includePathVar =
+ cmStrCat("CMAKE_", lang, "_TARGET_INCLUDE_PATH");
cmMakefile* mf = this->LocalGenerator->GetMakefile();
includePath = mf->GetDefinition(includePathVar);
if (includePath) {
- cmSystemTools::ExpandListArgument(includePath, this->IncludePath);
+ cmExpandList(includePath, this->IncludePath);
} else {
// Fallback to the old directory level variable if no per-target var:
- includePathVar = "CMAKE_";
- includePathVar += lang;
- includePathVar += "_INCLUDE_PATH";
+ includePathVar = cmStrCat("CMAKE_", lang, "_INCLUDE_PATH");
includePath = mf->GetDefinition(includePathVar);
if (includePath) {
- cmSystemTools::ExpandListArgument(includePath, this->IncludePath);
+ cmExpandList(includePath, this->IncludePath);
}
}
}
diff --git a/Source/cmDepends.h b/Source/cmDepends.h
index b33feb902..d9387758c 100644
--- a/Source/cmDepends.h
+++ b/Source/cmDepends.h
@@ -3,16 +3,15 @@
#ifndef cmDepends_h
#define cmDepends_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <map>
#include <set>
-#include <stddef.h>
#include <string>
#include <vector>
-class cmFileTimeComparison;
+class cmFileTimeCache;
class cmLocalGenerator;
/** \class cmDepends
@@ -24,15 +23,16 @@ class cmLocalGenerator;
*/
class cmDepends
{
- CM_DISABLE_COPY(cmDepends)
+public:
+ using DependencyMap = std::map<std::string, std::vector<std::string>>;
public:
/** Instances need to know the build directory name and the relative
path from the build directory to the target file. */
- cmDepends(cmLocalGenerator* lg = CM_NULLPTR, const char* targetDir = "");
+ cmDepends(cmLocalGenerator* lg = nullptr, std::string targetDir = "");
- /** at what level will the compile be done from */
- void SetCompileDirectory(const char* dir) { this->CompileDirectory = dir; }
+ cmDepends(cmDepends const&) = delete;
+ cmDepends& operator=(cmDepends const&) = delete;
/** Set the local generator for the directory in which we are
scanning dependencies. This is not a full local generator; it
@@ -44,7 +44,10 @@ public:
void SetLanguage(const std::string& lang) { this->Language = lang; }
/** Set the target build directory. */
- void SetTargetDirectory(const char* dir) { this->TargetDirectory = dir; }
+ void SetTargetDirectory(const std::string& dir)
+ {
+ this->TargetDirectory = dir;
+ }
/** should this be verbose in its output */
void SetVerbose(bool verb) { this->Verbose = verb; }
@@ -55,26 +58,19 @@ public:
/** Write dependencies for the target file. */
bool Write(std::ostream& makeDepends, std::ostream& internalDepends);
- class DependencyVector : public std::vector<std::string>
- {
- };
-
/** Check dependencies for the target file. Returns true if
dependencies are okay and false if they must be generated. If
they must be generated Clear has already been called to wipe out
the old dependencies.
Dependencies which are still valid will be stored in validDeps. */
- bool Check(const char* makeFile, const char* internalFile,
- std::map<std::string, DependencyVector>& validDeps);
+ bool Check(const std::string& makeFile, const std::string& internalFile,
+ DependencyMap& validDeps);
/** Clear dependencies for the target file so they will be regenerated. */
- void Clear(const char* file);
+ void Clear(const std::string& file);
/** Set the file comparison object */
- void SetFileComparison(cmFileTimeComparison* fc)
- {
- this->FileComparison = fc;
- }
+ void SetFileTimeCache(cmFileTimeCache* fc) { this->FileTimeCache = fc; }
protected:
// Write dependencies for the target file to the given stream.
@@ -87,33 +83,26 @@ protected:
// Check dependencies for the target file in the given stream.
// Return false if dependencies must be regenerated and true
// otherwise.
- virtual bool CheckDependencies(
- std::istream& internalDepends, const char* internalDependsFileName,
- std::map<std::string, DependencyVector>& validDeps);
+ virtual bool CheckDependencies(std::istream& internalDepends,
+ const std::string& internalDependsFileName,
+ DependencyMap& validDeps);
// Finalize the dependency information for the target.
virtual bool Finalize(std::ostream& makeDepends,
std::ostream& internalDepends);
- // The directory in which the build rule for the target file is executed.
- std::string CompileDirectory;
-
// The local generator.
cmLocalGenerator* LocalGenerator;
// Flag for verbose output.
- bool Verbose;
- cmFileTimeComparison* FileComparison;
+ bool Verbose = false;
+ cmFileTimeCache* FileTimeCache = nullptr;
std::string Language;
// The full path to the target's build directory.
std::string TargetDirectory;
- size_t MaxPath;
- char* Dependee;
- char* Depender;
-
// The include file search path.
std::vector<std::string> IncludePath;
diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx
index 2c464cc9c..e30d9597d 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -2,13 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDependsC.h"
-#include "cmsys/FStream.hxx"
#include <utility>
-#include "cmAlgorithms.h"
-#include "cmFileTimeComparison.h"
+#include "cmsys/FStream.hxx"
+
+#include "cmFileTime.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#define INCLUDE_REGEX_LINE \
@@ -19,14 +20,10 @@
#define INCLUDE_REGEX_COMPLAIN_MARKER "#IncludeRegexComplain: "
#define INCLUDE_REGEX_TRANSFORM_MARKER "#IncludeRegexTransform: "
-cmDependsC::cmDependsC()
- : ValidDeps(CM_NULLPTR)
-{
-}
+cmDependsC::cmDependsC() = default;
-cmDependsC::cmDependsC(
- cmLocalGenerator* lg, const char* targetDir, const std::string& lang,
- const std::map<std::string, DependencyVector>* validDeps)
+cmDependsC::cmDependsC(cmLocalGenerator* lg, const std::string& targetDir,
+ const std::string& lang, const DependencyMap* validDeps)
: cmDepends(lg, targetDir)
, ValidDeps(validDeps)
{
@@ -39,35 +36,30 @@ cmDependsC::cmDependsC(
std::string scanRegex = "^.*$";
std::string complainRegex = "^$";
{
- std::string scanRegexVar = "CMAKE_";
- scanRegexVar += lang;
- scanRegexVar += "_INCLUDE_REGEX_SCAN";
+ std::string scanRegexVar = cmStrCat("CMAKE_", lang, "_INCLUDE_REGEX_SCAN");
if (const char* sr = mf->GetDefinition(scanRegexVar)) {
scanRegex = sr;
}
- std::string complainRegexVar = "CMAKE_";
- complainRegexVar += lang;
- complainRegexVar += "_INCLUDE_REGEX_COMPLAIN";
+ std::string complainRegexVar =
+ cmStrCat("CMAKE_", lang, "_INCLUDE_REGEX_COMPLAIN");
if (const char* cr = mf->GetDefinition(complainRegexVar)) {
complainRegex = cr;
}
}
this->IncludeRegexLine.compile(INCLUDE_REGEX_LINE);
- this->IncludeRegexScan.compile(scanRegex.c_str());
- this->IncludeRegexComplain.compile(complainRegex.c_str());
+ this->IncludeRegexScan.compile(scanRegex);
+ this->IncludeRegexComplain.compile(complainRegex);
this->IncludeRegexLineString = INCLUDE_REGEX_LINE_MARKER INCLUDE_REGEX_LINE;
- this->IncludeRegexScanString = INCLUDE_REGEX_SCAN_MARKER;
- this->IncludeRegexScanString += scanRegex;
- this->IncludeRegexComplainString = INCLUDE_REGEX_COMPLAIN_MARKER;
- this->IncludeRegexComplainString += complainRegex;
+ this->IncludeRegexScanString =
+ cmStrCat(INCLUDE_REGEX_SCAN_MARKER, scanRegex);
+ this->IncludeRegexComplainString =
+ cmStrCat(INCLUDE_REGEX_COMPLAIN_MARKER, complainRegex);
this->SetupTransforms();
- this->CacheFileName = this->TargetDirectory;
- this->CacheFileName += "/";
- this->CacheFileName += lang;
- this->CacheFileName += ".includecache";
+ this->CacheFileName =
+ cmStrCat(this->TargetDirectory, '/', lang, ".includecache");
this->ReadCacheFile();
}
@@ -75,7 +67,6 @@ cmDependsC::cmDependsC(
cmDependsC::~cmDependsC()
{
this->WriteCacheFile();
- cmDeleteAll(this->FileCache);
}
bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
@@ -96,9 +87,16 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
std::set<std::string> dependencies;
bool haveDeps = false;
- if (this->ValidDeps != CM_NULLPTR) {
- std::map<std::string, DependencyVector>::const_iterator tmpIt =
- this->ValidDeps->find(obj);
+ std::string binDir = this->LocalGenerator->GetBinaryDirectory();
+
+ // Compute a path to the object file to write to the internal depend file.
+ // Any existing content of the internal depend file has already been
+ // loaded in ValidDeps with this path as a key.
+ std::string obj_i =
+ this->LocalGenerator->MaybeConvertToRelativePath(binDir, obj);
+
+ if (this->ValidDeps != nullptr) {
+ auto const tmpIt = this->ValidDeps->find(obj_i);
if (tmpIt != this->ValidDeps->end()) {
dependencies.insert(tmpIt->second.begin(), tmpIt->second.end());
haveDeps = true;
@@ -107,24 +105,17 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
if (!haveDeps) {
// Walk the dependency graph starting with the source file.
- int srcFiles = (int)sources.size();
+ int srcFiles = static_cast<int>(sources.size());
this->Encountered.clear();
- for (std::set<std::string>::const_iterator srcIt = sources.begin();
- srcIt != sources.end(); ++srcIt) {
+ for (std::string const& src : sources) {
UnscannedEntry root;
- root.FileName = *srcIt;
+ root.FileName = src;
this->Unscanned.push(root);
- this->Encountered.insert(*srcIt);
+ this->Encountered.insert(src);
}
std::set<std::string> scanned;
-
- // Use reserve to allocate enough memory for tempPathStr
- // so that during the loops no memory is allocated or freed
- std::string tempPathStr;
- tempPathStr.reserve(4 * 1024);
-
while (!this->Unscanned.empty()) {
// Get the next file to scan.
UnscannedEntry current = this->Unscanned.front();
@@ -132,37 +123,32 @@ 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.
fullName = current.QuotedLocation;
} else {
- std::map<std::string, std::string>::iterator headerLocationIt =
+ auto headerLocationIt =
this->HeaderLocationCache.find(current.FileName);
if (headerLocationIt != this->HeaderLocationCache.end()) {
fullName = headerLocationIt->second;
} else {
- for (std::vector<std::string>::const_iterator i =
- this->IncludePath.begin();
- i != this->IncludePath.end(); ++i) {
+ for (std::string const& iPath : this->IncludePath) {
// Construct the name of the file as if it were in the current
// include directory. Avoid using a leading "./".
-
- tempPathStr =
- cmSystemTools::CollapseCombinedPath(*i, current.FileName);
+ std::string tmpPath =
+ cmSystemTools::CollapseFullPath(current.FileName, iPath);
// Look for the file in this location.
- if (cmSystemTools::FileExists(tempPathStr.c_str(), true)) {
- fullName = tempPathStr;
- HeaderLocationCache[current.FileName] = fullName;
+ if (cmSystemTools::FileExists(tmpPath, true)) {
+ fullName = tmpPath;
+ this->HeaderLocationCache[current.FileName] = std::move(tmpPath);
break;
}
}
@@ -172,9 +158,8 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
// Complain if the file cannot be found and matches the complain
// regex.
if (fullName.empty() &&
- this->IncludeRegexComplain.find(current.FileName.c_str())) {
- cmSystemTools::Error("Cannot find file \"", current.FileName.c_str(),
- "\".");
+ this->IncludeRegexComplain.find(current.FileName)) {
+ cmSystemTools::Error("Cannot find file \"" + current.FileName + "\".");
return false;
}
@@ -184,18 +169,15 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
scanned.insert(fullName);
// Check whether this file is already in the cache
- std::map<std::string, cmIncludeLines*>::iterator fileIt =
- this->FileCache.find(fullName);
+ auto fileIt = this->FileCache.find(fullName);
if (fileIt != this->FileCache.end()) {
- fileIt->second->Used = true;
+ fileIt->second.Used = true;
dependencies.insert(fullName);
- for (std::vector<UnscannedEntry>::const_iterator incIt =
- fileIt->second->UnscannedEntries.begin();
- incIt != fileIt->second->UnscannedEntries.end(); ++incIt) {
- if (this->Encountered.find(incIt->FileName) ==
+ for (UnscannedEntry const& inc : fileIt->second.UnscannedEntries) {
+ if (this->Encountered.find(inc.FileName) ==
this->Encountered.end()) {
- this->Encountered.insert(incIt->FileName);
- this->Unscanned.push(*incIt);
+ this->Encountered.insert(inc.FileName);
+ this->Unscanned.push(inc);
}
}
} else {
@@ -213,7 +195,7 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
// Scan this file for new dependencies. Pass the directory
// containing the file to handle double-quote includes.
std::string dir = cmSystemTools::GetFilenamePath(fullName);
- this->Scan(fin, dir.c_str(), fullName);
+ this->Scan(fin, dir, fullName);
} else {
// Skip file with encoding we do not implement.
}
@@ -229,19 +211,16 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
// written by the original local generator for this directory
// convert the dependencies to paths relative to the home output
// 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::set<std::string>::const_iterator i = dependencies.begin();
- i != dependencies.end(); ++i) {
- makeDepends
- << obj_m << ": "
- << cmSystemTools::ConvertToOutputPath(
- this->LocalGenerator->ConvertToRelativePath(binDir, *i).c_str())
- << std::endl;
- internalDepends << " " << *i << std::endl;
+ for (std::string const& dep : dependencies) {
+ makeDepends << obj_m << ": "
+ << cmSystemTools::ConvertToOutputPath(
+ this->LocalGenerator->MaybeConvertToRelativePath(binDir,
+ dep))
+ << std::endl;
+ internalDepends << " " << dep << std::endl;
}
makeDepends << std::endl;
@@ -259,27 +238,28 @@ void cmDependsC::ReadCacheFile()
}
std::string line;
- cmIncludeLines* cacheEntry = CM_NULLPTR;
+ cmIncludeLines* cacheEntry = nullptr;
bool haveFileName = false;
+ cmFileTime cacheFileTime;
+ bool const cacheFileTimeGood = cacheFileTime.Load(this->CacheFileName);
while (cmSystemTools::GetLineFromStream(fin, line)) {
if (line.empty()) {
- cacheEntry = CM_NULLPTR;
+ cacheEntry = nullptr;
haveFileName = false;
continue;
}
// the first line after an empty line is the name of the parsed file
if (!haveFileName) {
haveFileName = true;
- int newer = 0;
- cmFileTimeComparison comp;
- bool res = comp.FileTimeCompare(this->CacheFileName.c_str(),
- line.c_str(), &newer);
- if (res && newer == 1) // cache is newer than the parsed file
+ cmFileTime fileTime;
+ bool const res = cacheFileTimeGood && fileTime.Load(line);
+ bool const newer = res && cacheFileTime.Newer(fileTime);
+
+ if (res && newer) // cache is newer than the parsed file
{
- cacheEntry = new cmIncludeLines;
- this->FileCache[line] = cacheEntry;
+ cacheEntry = &this->FileCache[line];
}
// file doesn't exist, check that the regular expressions
// haven't changed
@@ -302,14 +282,14 @@ void cmDependsC::ReadCacheFile()
}
}
}
- } else if (cacheEntry != CM_NULLPTR) {
+ } else if (cacheEntry != nullptr) {
UnscannedEntry entry;
entry.FileName = line;
if (cmSystemTools::GetLineFromStream(fin, line)) {
if (line != "-") {
entry.QuotedLocation = line;
}
- cacheEntry->UnscannedEntries.push_back(entry);
+ cacheEntry->UnscannedEntries.push_back(std::move(entry));
}
}
}
@@ -330,20 +310,16 @@ void cmDependsC::WriteCacheFile() const
cacheOut << this->IncludeRegexComplainString << "\n\n";
cacheOut << this->IncludeRegexTransformString << "\n\n";
- for (std::map<std::string, cmIncludeLines*>::const_iterator fileIt =
- this->FileCache.begin();
- fileIt != this->FileCache.end(); ++fileIt) {
- if (fileIt->second->Used) {
- cacheOut << fileIt->first << std::endl;
-
- for (std::vector<UnscannedEntry>::const_iterator incIt =
- fileIt->second->UnscannedEntries.begin();
- incIt != fileIt->second->UnscannedEntries.end(); ++incIt) {
- cacheOut << incIt->FileName << std::endl;
- if (incIt->QuotedLocation.empty()) {
+ for (auto const& fileIt : this->FileCache) {
+ if (fileIt.second.Used) {
+ cacheOut << fileIt.first << std::endl;
+
+ for (UnscannedEntry const& inc : fileIt.second.UnscannedEntries) {
+ cacheOut << inc.FileName << std::endl;
+ if (inc.QuotedLocation.empty()) {
cacheOut << "-" << std::endl;
} else {
- cacheOut << incIt->QuotedLocation << std::endl;
+ cacheOut << inc.QuotedLocation << std::endl;
}
}
cacheOut << std::endl;
@@ -351,12 +327,11 @@ void cmDependsC::WriteCacheFile() const
}
}
-void cmDependsC::Scan(std::istream& is, const char* directory,
+void cmDependsC::Scan(std::istream& is, const std::string& directory,
const std::string& fullName)
{
- cmIncludeLines* newCacheEntry = new cmIncludeLines;
- newCacheEntry->Used = true;
- this->FileCache[fullName] = newCacheEntry;
+ cmIncludeLines& newCacheEntry = this->FileCache[fullName];
+ newCacheEntry.Used = true;
// Read one line at a time.
std::string line;
@@ -367,18 +342,18 @@ void cmDependsC::Scan(std::istream& is, const char* directory,
}
// Match include directives.
- if (this->IncludeRegexLine.find(line.c_str())) {
+ if (this->IncludeRegexLine.find(line)) {
// Get the file being included.
UnscannedEntry entry;
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.
entry.QuotedLocation =
- cmSystemTools::CollapseCombinedPath(directory, entry.FileName);
+ cmSystemTools::CollapseFullPath(entry.FileName, directory);
}
// Queue the file if it has not yet been encountered and it
@@ -391,8 +366,8 @@ void cmDependsC::Scan(std::istream& is, const char* directory,
// file their own directory by simply using "filename.h" (#12619)
// This kind of problem will be fixed when a more
// preprocessor-like implementation of this scanner is created.
- if (this->IncludeRegexScan.find(entry.FileName.c_str())) {
- newCacheEntry->UnscannedEntries.push_back(entry);
+ if (this->IncludeRegexScan.find(entry.FileName)) {
+ newCacheEntry.UnscannedEntries.push_back(entry);
if (this->Encountered.find(entry.FileName) ==
this->Encountered.end()) {
this->Encountered.insert(entry.FileName);
@@ -409,11 +384,10 @@ void cmDependsC::SetupTransforms()
std::vector<std::string> transformRules;
cmMakefile* mf = this->LocalGenerator->GetMakefile();
if (const char* xform = mf->GetDefinition("CMAKE_INCLUDE_TRANSFORMS")) {
- cmSystemTools::ExpandListArgument(xform, transformRules, true);
+ cmExpandList(xform, transformRules, true);
}
- for (std::vector<std::string>::const_iterator tri = transformRules.begin();
- tri != transformRules.end(); ++tri) {
- this->ParseTransform(*tri);
+ for (std::string const& tr : transformRules) {
+ this->ParseTransform(tr);
}
this->IncludeRegexTransformString = INCLUDE_REGEX_TRANSFORM_MARKER;
@@ -422,24 +396,22 @@ void cmDependsC::SetupTransforms()
// transformed.
std::string xform = "^([ \t]*[#%][ \t]*(include|import)[ \t]*)(";
const char* sep = "";
- for (TransformRulesType::const_iterator tri = this->TransformRules.begin();
- tri != this->TransformRules.end(); ++tri) {
+ for (auto const& tr : this->TransformRules) {
xform += sep;
- xform += tri->first;
+ xform += tr.first;
sep = "|";
}
xform += ")[ \t]*\\(([^),]*)\\)";
- this->IncludeRegexTransform.compile(xform.c_str());
+ this->IncludeRegexTransform.compile(xform);
// Build a string that encodes all transformation rules and will
// change when rules are changed.
this->IncludeRegexTransformString += xform;
- for (TransformRulesType::const_iterator tri = this->TransformRules.begin();
- tri != this->TransformRules.end(); ++tri) {
+ for (auto const& tr : this->TransformRules) {
this->IncludeRegexTransformString += " ";
- this->IncludeRegexTransformString += tri->first;
+ this->IncludeRegexTransformString += tr.first;
this->IncludeRegexTransformString += "(%)=";
- this->IncludeRegexTransformString += tri->second;
+ this->IncludeRegexTransformString += tr.second;
}
}
}
@@ -460,11 +432,10 @@ void cmDependsC::ParseTransform(std::string const& xform)
void cmDependsC::TransformLine(std::string& line)
{
// Check for a transform rule match. Return if none.
- if (!this->IncludeRegexTransform.find(line.c_str())) {
+ if (!this->IncludeRegexTransform.find(line)) {
return;
}
- TransformRulesType::const_iterator tri =
- this->TransformRules.find(this->IncludeRegexTransform.match(3));
+ auto tri = this->TransformRules.find(this->IncludeRegexTransform.match(3));
if (tri == this->TransformRules.end()) {
return;
}
@@ -472,11 +443,11 @@ void cmDependsC::TransformLine(std::string& line)
// Construct the transformed line.
std::string newline = this->IncludeRegexTransform.match(1);
std::string arg = this->IncludeRegexTransform.match(4);
- for (const char* c = tri->second.c_str(); *c; ++c) {
- if (*c == '%') {
+ for (char c : tri->second) {
+ if (c == '%') {
newline += arg;
} else {
- newline += *c;
+ newline += c;
}
}
diff --git a/Source/cmDependsC.h b/Source/cmDependsC.h
index 250d40f8a..3bb6e36a3 100644
--- a/Source/cmDependsC.h
+++ b/Source/cmDependsC.h
@@ -3,18 +3,20 @@
#ifndef cmDependsC_h
#define cmDependsC_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmDepends.h"
-
-#include "cmsys/RegularExpression.hxx"
#include <iosfwd>
#include <map>
-#include <queue>
#include <set>
#include <string>
#include <vector>
+#include <queue>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmDepends.h"
+
class cmLocalGenerator;
/** \class cmDependsC
@@ -22,27 +24,27 @@ class cmLocalGenerator;
*/
class cmDependsC : public cmDepends
{
- CM_DISABLE_COPY(cmDependsC)
-
public:
/** Checking instances need to know the build directory name and the
relative path from the build directory to the target file. */
cmDependsC();
- cmDependsC(cmLocalGenerator* lg, const char* targetDir,
- const std::string& lang,
- const std::map<std::string, DependencyVector>* validDeps);
+ cmDependsC(cmLocalGenerator* lg, const std::string& targetDir,
+ const std::string& lang, const DependencyMap* validDeps);
/** Virtual destructor to cleanup subclasses properly. */
- ~cmDependsC() CM_OVERRIDE;
+ ~cmDependsC() override;
+
+ cmDependsC(cmDependsC const&) = delete;
+ cmDependsC& operator=(cmDependsC const&) = delete;
protected:
// Implement writing/checking methods required by superclass.
bool WriteDependencies(const std::set<std::string>& sources,
const std::string& obj, std::ostream& makeDepends,
- std::ostream& internalDepends) CM_OVERRIDE;
+ std::ostream& internalDepends) override;
// Method to scan a single file.
- void Scan(std::istream& is, const char* directory,
+ void Scan(std::istream& is, const std::string& directory,
const std::string& fullName);
// Regular expression to identify C preprocessor include directives.
@@ -59,7 +61,7 @@ protected:
// Regex to transform #include lines.
std::string IncludeRegexTransformString;
cmsys::RegularExpression IncludeRegexTransform;
- typedef std::map<std::string, std::string> TransformRulesType;
+ using TransformRulesType = std::map<std::string, std::string>;
TransformRulesType TransformRules;
void SetupTransforms();
void ParseTransform(std::string const& xform);
@@ -75,20 +77,16 @@ public:
struct cmIncludeLines
{
- cmIncludeLines()
- : Used(false)
- {
- }
std::vector<UnscannedEntry> UnscannedEntries;
- bool Used;
+ bool Used = false;
};
protected:
- const std::map<std::string, DependencyVector>* ValidDeps;
+ const DependencyMap* ValidDeps = nullptr;
std::set<std::string> Encountered;
std::queue<UnscannedEntry> Unscanned;
- std::map<std::string, cmIncludeLines*> FileCache;
+ std::map<std::string, cmIncludeLines> FileCache;
std::map<std::string, std::string> HeaderLocationCache;
std::string CacheFileName;
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index 8b05fab49..36922029a 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -2,14 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDependsFortran.h"
-#include "cmsys/FStream.hxx"
-#include <assert.h>
+#include <cassert>
+#include <cstdlib>
#include <iostream>
#include <map>
-#include <stdlib.h>
-#include <string.h>
#include <utility>
+#include "cmsys/FStream.hxx"
+
#include "cmFortranParser.h" /* Interface to parser object. */
#include "cmGeneratedFileStream.h"
#include "cmLocalGenerator.h"
@@ -17,12 +17,31 @@
#include "cmOutputConverter.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
// TODO: Test compiler for the case of the mod file. Some always
// use lower case and some always use upper case. I do not know if any
// use the case from the source code.
+static void cmFortranModuleAppendUpperLower(std::string const& mod,
+ std::string& mod_upper,
+ std::string& mod_lower)
+{
+ std::string::size_type ext_len = 0;
+ if (cmHasLiteralSuffix(mod, ".mod")) {
+ ext_len = 4;
+ } else if (cmHasLiteralSuffix(mod, ".smod")) {
+ ext_len = 5;
+ } else if (cmHasLiteralSuffix(mod, ".sub")) {
+ ext_len = 4;
+ }
+ std::string const& name = mod.substr(0, mod.size() - ext_len);
+ std::string const& ext = mod.substr(mod.size() - ext_len);
+ mod_upper += cmSystemTools::UpperCase(name) + ext;
+ mod_lower += mod;
+}
+
class cmDependsFortranInternals
{
public:
@@ -30,17 +49,17 @@ public:
std::set<std::string> TargetProvides;
// Map modules required by this target to locations.
- typedef std::map<std::string, std::string> TargetRequiresMap;
+ using TargetRequiresMap = std::map<std::string, std::string>;
TargetRequiresMap TargetRequires;
// Information about each object file.
- typedef std::map<std::string, cmFortranSourceInfo> ObjectInfoMap;
+ using ObjectInfoMap = std::map<std::string, cmFortranSourceInfo>;
ObjectInfoMap ObjectInfo;
- cmFortranSourceInfo& CreateObjectInfo(const char* obj, const char* src)
+ cmFortranSourceInfo& CreateObjectInfo(const std::string& obj,
+ const std::string& src)
{
- std::map<std::string, cmFortranSourceInfo>::iterator i =
- this->ObjectInfo.find(obj);
+ auto i = this->ObjectInfo.find(obj);
if (i == this->ObjectInfo.end()) {
std::map<std::string, cmFortranSourceInfo>::value_type entry(
obj, cmFortranSourceInfo());
@@ -51,10 +70,7 @@ public:
}
};
-cmDependsFortran::cmDependsFortran()
- : Internal(CM_NULLPTR)
-{
-}
+cmDependsFortran::cmDependsFortran() = default;
cmDependsFortran::cmDependsFortran(cmLocalGenerator* lg)
: cmDepends(lg)
@@ -68,20 +84,22 @@ cmDependsFortran::cmDependsFortran(cmLocalGenerator* lg)
cmMakefile* mf = this->LocalGenerator->GetMakefile();
if (const char* c_defines =
mf->GetDefinition("CMAKE_TARGET_DEFINITIONS_Fortran")) {
- cmSystemTools::ExpandListArgument(c_defines, definitions);
+ cmExpandList(c_defines, definitions);
}
// translate i.e. FOO=BAR to FOO and add it to the list of defined
// preprocessor symbols
- for (std::vector<std::string>::const_iterator it = definitions.begin();
- it != definitions.end(); ++it) {
- std::string def = *it;
+ for (std::string def : definitions) {
std::string::size_type assignment = def.find('=');
if (assignment != std::string::npos) {
- def = it->substr(0, assignment);
+ def = def.substr(0, assignment);
}
this->PPDefinitions.insert(def);
}
+
+ this->CompilerId = mf->GetSafeDefinition("CMAKE_Fortran_COMPILER_ID");
+ this->SModSep = mf->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_SEP");
+ this->SModExt = mf->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_EXT");
}
cmDependsFortran::~cmDependsFortran()
@@ -104,17 +122,19 @@ bool cmDependsFortran::WriteDependencies(const std::set<std::string>& sources,
return false;
}
+ cmFortranCompiler fc;
+ fc.Id = this->CompilerId;
+ fc.SModSep = this->SModSep;
+ fc.SModExt = this->SModExt;
+
bool okay = true;
- for (std::set<std::string>::const_iterator it = sources.begin();
- it != sources.end(); ++it) {
- const std::string& src = *it;
+ for (std::string const& src : sources) {
// Get the information object for this source.
- cmFortranSourceInfo& info =
- this->Internal->CreateObjectInfo(obj.c_str(), src.c_str());
+ cmFortranSourceInfo& info = this->Internal->CreateObjectInfo(obj, src);
// Create the parser object. The constructor takes info by reference,
// so we may look into the resulting objects later.
- cmFortranParser parser(this->IncludePath, this->PPDefinitions, info);
+ cmFortranParser parser(fc, this->IncludePath, this->PPDefinitions, info);
// Push on the starting file.
cmFortranParser_FilePush(&parser, src.c_str());
@@ -141,7 +161,7 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
this->LocateModules();
// Get the directory in which stamp files will be stored.
- const char* stamp_dir = this->TargetDirectory.c_str();
+ const std::string& stamp_dir = this->TargetDirectory;
// Get the directory in which module files will be created.
cmMakefile* mf = this->LocalGenerator->GetMakefile();
@@ -152,52 +172,39 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
}
// Actually write dependencies to the streams.
- typedef cmDependsFortranInternals::ObjectInfoMap ObjectInfoMap;
+ using ObjectInfoMap = cmDependsFortranInternals::ObjectInfoMap;
ObjectInfoMap const& objInfo = this->Internal->ObjectInfo;
- for (ObjectInfoMap::const_iterator i = objInfo.begin(); i != objInfo.end();
- ++i) {
- if (!this->WriteDependenciesReal(i->first.c_str(), i->second, mod_dir,
- stamp_dir, makeDepends,
- internalDepends)) {
+ for (auto const& i : objInfo) {
+ if (!this->WriteDependenciesReal(i.first, i.second, mod_dir, stamp_dir,
+ makeDepends, internalDepends)) {
return false;
}
}
// Store the list of modules provided by this target.
- std::string fiName = this->TargetDirectory;
- fiName += "/fortran.internal";
- cmGeneratedFileStream fiStream(fiName.c_str());
+ std::string fiName = cmStrCat(this->TargetDirectory, "/fortran.internal");
+ cmGeneratedFileStream fiStream(fiName);
fiStream << "# The fortran modules provided by this target.\n";
fiStream << "provides\n";
std::set<std::string> const& provides = this->Internal->TargetProvides;
- for (std::set<std::string>::const_iterator i = provides.begin();
- i != provides.end(); ++i) {
- fiStream << " " << *i << "\n";
+ for (std::string const& i : provides) {
+ fiStream << " " << i << "\n";
}
// Create a script to clean the modules.
if (!provides.empty()) {
- std::string fcName = this->TargetDirectory;
- fcName += "/cmake_clean_Fortran.cmake";
- cmGeneratedFileStream fcStream(fcName.c_str());
+ std::string fcName =
+ cmStrCat(this->TargetDirectory, "/cmake_clean_Fortran.cmake");
+ cmGeneratedFileStream fcStream(fcName);
fcStream << "# Remove fortran modules provided by this target.\n";
fcStream << "FILE(REMOVE";
std::string currentBinDir =
this->LocalGenerator->GetCurrentBinaryDirectory();
- for (std::set<std::string>::const_iterator i = provides.begin();
- i != provides.end(); ++i) {
- std::string mod_upper = mod_dir;
- mod_upper += "/";
- mod_upper += cmSystemTools::UpperCase(*i);
- mod_upper += ".mod";
- std::string mod_lower = mod_dir;
- mod_lower += "/";
- mod_lower += *i;
- mod_lower += ".mod";
- std::string stamp = stamp_dir;
- stamp += "/";
- stamp += *i;
- stamp += ".mod.stamp";
+ for (std::string const& i : provides) {
+ std::string mod_upper = cmStrCat(mod_dir, '/');
+ std::string mod_lower = cmStrCat(mod_dir, '/');
+ cmFortranModuleAppendUpperLower(i, mod_upper, mod_lower);
+ std::string stamp = cmStrCat(stamp_dir, '/', i, ".stamp");
fcStream << "\n";
fcStream << " \""
<< this->MaybeConvertToRelativePath(currentBinDir, mod_lower)
@@ -217,18 +224,16 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
void cmDependsFortran::LocateModules()
{
// Collect the set of modules provided and required by all sources.
- typedef cmDependsFortranInternals::ObjectInfoMap ObjectInfoMap;
+ using ObjectInfoMap = cmDependsFortranInternals::ObjectInfoMap;
ObjectInfoMap const& objInfo = this->Internal->ObjectInfo;
- for (ObjectInfoMap::const_iterator infoI = objInfo.begin();
- infoI != objInfo.end(); ++infoI) {
- cmFortranSourceInfo const& info = infoI->second;
+ for (auto const& infoI : objInfo) {
+ cmFortranSourceInfo const& info = infoI.second;
// Include this module in the set provided by this target.
this->Internal->TargetProvides.insert(info.Provides.begin(),
info.Provides.end());
- for (std::set<std::string>::const_iterator i = info.Requires.begin();
- i != info.Requires.end(); ++i) {
- this->Internal->TargetRequires[*i] = "";
+ for (std::string const& r : info.Requires) {
+ this->Internal->TargetRequires[r].clear();
}
}
@@ -245,31 +250,29 @@ void cmDependsFortran::LocateModules()
std::vector<std::string> infoFiles;
if (const char* infoFilesValue =
mf->GetDefinition("CMAKE_TARGET_LINKED_INFO_FILES")) {
- cmSystemTools::ExpandListArgument(infoFilesValue, infoFiles);
+ cmExpandList(infoFilesValue, infoFiles);
}
- for (std::vector<std::string>::const_iterator i = infoFiles.begin();
- i != infoFiles.end(); ++i) {
- std::string targetDir = cmSystemTools::GetFilenamePath(*i);
+ for (std::string const& i : infoFiles) {
+ std::string targetDir = cmSystemTools::GetFilenamePath(i);
std::string fname = targetDir + "/fortran.internal";
cmsys::ifstream fin(fname.c_str());
if (fin) {
- this->MatchRemoteModules(fin, targetDir.c_str());
+ this->MatchRemoteModules(fin, targetDir);
}
}
}
void cmDependsFortran::MatchLocalModules()
{
- const char* stampDir = this->TargetDirectory.c_str();
+ std::string const& stampDir = this->TargetDirectory;
std::set<std::string> const& provides = this->Internal->TargetProvides;
- for (std::set<std::string>::const_iterator i = provides.begin();
- i != provides.end(); ++i) {
- this->ConsiderModule(i->c_str(), stampDir);
+ for (std::string const& i : provides) {
+ this->ConsiderModule(i, stampDir);
}
}
void cmDependsFortran::MatchRemoteModules(std::istream& fin,
- const char* stampDir)
+ const std::string& stampDir)
{
std::string line;
bool doing_provides = false;
@@ -281,7 +284,15 @@ void cmDependsFortran::MatchRemoteModules(std::istream& fin,
if (line[0] == ' ') {
if (doing_provides) {
- this->ConsiderModule(line.c_str() + 1, stampDir);
+ std::string mod = line;
+ if (!cmHasLiteralSuffix(mod, ".mod") &&
+ !cmHasLiteralSuffix(mod, ".smod") &&
+ !cmHasLiteralSuffix(mod, ".sub")) {
+ // Support fortran.internal files left by older versions of CMake.
+ // They do not include the ".mod" extension.
+ mod += ".mod";
+ }
+ this->ConsiderModule(mod.substr(1), stampDir);
}
} else if (line == "provides") {
doing_provides = true;
@@ -291,143 +302,109 @@ void cmDependsFortran::MatchRemoteModules(std::istream& fin,
}
}
-void cmDependsFortran::ConsiderModule(const char* name, const char* stampDir)
+void cmDependsFortran::ConsiderModule(const std::string& name,
+ const std::string& stampDir)
{
// Locate each required module.
- typedef cmDependsFortranInternals::TargetRequiresMap TargetRequiresMap;
- TargetRequiresMap::iterator required =
- this->Internal->TargetRequires.find(name);
+ auto required = this->Internal->TargetRequires.find(name);
if (required != this->Internal->TargetRequires.end() &&
required->second.empty()) {
// The module is provided by a CMake target. It will have a stamp file.
- std::string stampFile = stampDir;
- stampFile += "/";
- stampFile += name;
- stampFile += ".mod.stamp";
+ std::string stampFile = cmStrCat(stampDir, '/', name, ".stamp");
required->second = stampFile;
}
}
-bool cmDependsFortran::WriteDependenciesReal(const char* obj,
+bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
cmFortranSourceInfo const& info,
std::string const& mod_dir,
- const char* stamp_dir,
+ std::string const& stamp_dir,
std::ostream& makeDepends,
std::ostream& internalDepends)
{
- typedef cmDependsFortranInternals::TargetRequiresMap TargetRequiresMap;
-
// Get the source file for this object.
- const char* src = info.Source.c_str();
+ std::string const& src = info.Source;
// 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::set<std::string>::const_iterator i = info.Includes.begin();
- i != info.Includes.end(); ++i) {
+ 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;
+ internalDepends << " " << i << std::endl;
}
makeDepends << std::endl;
// Write module requirements to the output stream.
- for (std::set<std::string>::const_iterator i = info.Requires.begin();
- i != info.Requires.end(); ++i) {
+ for (std::string const& i : info.Requires) {
// Require only modules not provided in the same source.
- if (std::set<std::string>::const_iterator(info.Provides.find(*i)) !=
- info.Provides.end()) {
+ if (info.Provides.find(i) != info.Provides.cend()) {
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 =
- this->Internal->TargetRequires.find(*i);
+ auto required = this->Internal->TargetRequires.find(i);
if (required == this->Internal->TargetRequires.end()) {
abort();
}
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
// the compiler will and depend on that.
std::string module;
- if (this->FindModule(*i, 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::set<std::string>::const_iterator i = info.Provides.begin();
- i != info.Provides.end(); ++i) {
- 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::set<std::string>::const_iterator i = info.Provides.begin();
- i != info.Provides.end(); ++i) {
+ for (std::string const& i : info.Provides) {
// Include this module in the set provided by this target.
- this->Internal->TargetProvides.insert(*i);
+ this->Internal->TargetProvides.insert(i);
// Always use lower case for the mod stamp file name. The
// cmake_copy_f90_mod will call back to this class, which will
// try various cases for the real mod file name.
- std::string m = cmSystemTools::LowerCase(*i);
- std::string modFile = mod_dir;
- modFile += "/";
- modFile += *i;
+ std::string modFile = cmStrCat(mod_dir, '/', i);
modFile = this->LocalGenerator->ConvertToOutputFormat(
this->MaybeConvertToRelativePath(binDir, modFile),
cmOutputConverter::SHELL);
- std::string stampFile = stamp_dir;
- stampFile += "/";
- stampFile += m;
- stampFile += ".mod.stamp";
- stampFile = this->LocalGenerator->ConvertToOutputFormat(
- this->MaybeConvertToRelativePath(binDir, stampFile),
- cmOutputConverter::SHELL);
+ std::string stampFile = cmStrCat(stamp_dir, '/', i, ".stamp");
+ 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) {
@@ -435,17 +412,16 @@ 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";
// Make sure the module timestamp rule is evaluated by the time
// the target finishes building.
- std::string driver = this->TargetDirectory;
- driver += "/build";
+ std::string driver = cmStrCat(this->TargetDirectory, "/build");
driver = cmSystemTools::ConvertToOutputPath(
- this->MaybeConvertToRelativePath(binDir, driver).c_str());
+ this->MaybeConvertToRelativePath(binDir, driver));
makeDepends << driver << ": " << obj_m << ".provides.build\n";
}
@@ -455,29 +431,23 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj,
bool cmDependsFortran::FindModule(std::string const& name, std::string& module)
{
// Construct possible names for the module file.
- std::string mod_upper = cmSystemTools::UpperCase(name);
- std::string mod_lower = name;
- mod_upper += ".mod";
- mod_lower += ".mod";
+ std::string mod_upper;
+ std::string mod_lower;
+ cmFortranModuleAppendUpperLower(name, mod_upper, mod_lower);
// Search the include path for the module.
std::string fullName;
- for (std::vector<std::string>::const_iterator i = this->IncludePath.begin();
- i != this->IncludePath.end(); ++i) {
+ for (std::string const& ip : this->IncludePath) {
// Try the lower-case name.
- fullName = *i;
- fullName += "/";
- fullName += mod_lower;
- if (cmSystemTools::FileExists(fullName.c_str(), true)) {
+ fullName = cmStrCat(ip, '/', mod_lower);
+ if (cmSystemTools::FileExists(fullName, true)) {
module = fullName;
return true;
}
// Try the upper-case name.
- fullName = *i;
- fullName += "/";
- fullName += mod_upper;
- if (cmSystemTools::FileExists(fullName.c_str(), true)) {
+ fullName = cmStrCat(ip, '/', mod_upper);
+ if (cmSystemTools::FileExists(fullName, true)) {
module = fullName;
return true;
}
@@ -503,20 +473,22 @@ bool cmDependsFortran::CopyModule(const std::vector<std::string>& args)
if (args.size() >= 5) {
compilerId = args[4];
}
+ if (!cmHasLiteralSuffix(mod, ".mod") && !cmHasLiteralSuffix(mod, ".smod") &&
+ !cmHasLiteralSuffix(mod, ".sub")) {
+ // Support depend.make files left by older versions of CMake.
+ // They do not include the ".mod" extension.
+ mod += ".mod";
+ }
std::string mod_dir = cmSystemTools::GetFilenamePath(mod);
if (!mod_dir.empty()) {
mod_dir += "/";
}
std::string mod_upper = mod_dir;
- mod_upper += cmSystemTools::UpperCase(cmSystemTools::GetFilenameName(mod));
std::string mod_lower = mod_dir;
- mod_lower += cmSystemTools::LowerCase(cmSystemTools::GetFilenameName(mod));
- mod += ".mod";
- mod_upper += ".mod";
- mod_lower += ".mod";
- if (cmSystemTools::FileExists(mod_upper.c_str(), true)) {
- if (cmDependsFortran::ModulesDiffer(mod_upper.c_str(), stamp.c_str(),
- compilerId.c_str())) {
+ cmFortranModuleAppendUpperLower(cmSystemTools::GetFilenameName(mod),
+ mod_upper, mod_lower);
+ if (cmSystemTools::FileExists(mod_upper, true)) {
+ if (cmDependsFortran::ModulesDiffer(mod_upper, stamp, compilerId)) {
if (!cmSystemTools::CopyFileAlways(mod_upper, stamp)) {
std::cerr << "Error copying Fortran module from \"" << mod_upper
<< "\" to \"" << stamp << "\".\n";
@@ -525,9 +497,8 @@ bool cmDependsFortran::CopyModule(const std::vector<std::string>& args)
}
return true;
}
- if (cmSystemTools::FileExists(mod_lower.c_str(), true)) {
- if (cmDependsFortran::ModulesDiffer(mod_lower.c_str(), stamp.c_str(),
- compilerId.c_str())) {
+ if (cmSystemTools::FileExists(mod_lower, true)) {
+ if (cmDependsFortran::ModulesDiffer(mod_lower, stamp, compilerId)) {
if (!cmSystemTools::CopyFileAlways(mod_lower, stamp)) {
std::cerr << "Error copying Fortran module from \"" << mod_lower
<< "\" to \"" << stamp << "\".\n";
@@ -594,9 +565,9 @@ static bool cmFortranStreamsDiffer(std::istream& ifs1, std::istream& ifs2)
return true;
}
-bool cmDependsFortran::ModulesDiffer(const char* modFile,
- const char* stampFile,
- const char* compilerId)
+bool cmDependsFortran::ModulesDiffer(const std::string& modFile,
+ const std::string& stampFile,
+ const std::string& compilerId)
{
/*
gnu >= 4.9:
@@ -616,7 +587,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:
@@ -630,16 +601,17 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile,
* source is compiled twice
* -SunPro
*/
- if (strcmp(compilerId, "SunPro") == 0) {
+ if (compilerId == "SunPro") {
return cmSystemTools::FilesDiffer(modFile, stampFile);
}
#if defined(_WIN32) || defined(__CYGWIN__)
- cmsys::ifstream finModFile(modFile, std::ios::in | std::ios::binary);
- cmsys::ifstream finStampFile(stampFile, std::ios::in | std::ios::binary);
+ cmsys::ifstream finModFile(modFile.c_str(), std::ios::in | std::ios::binary);
+ cmsys::ifstream finStampFile(stampFile.c_str(),
+ std::ios::in | std::ios::binary);
#else
- cmsys::ifstream finModFile(modFile);
- cmsys::ifstream finStampFile(stampFile);
+ cmsys::ifstream finModFile(modFile.c_str());
+ cmsys::ifstream finStampFile(stampFile.c_str());
#endif
if (!finModFile || !finStampFile) {
// At least one of the files does not exist. The modules differ.
@@ -654,7 +626,7 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile,
* Eat the stream content until all recompile only related changes
* are left behind.
*/
- if (strcmp(compilerId, "GNU") == 0) {
+ if (compilerId == "GNU") {
// GNU Fortran 4.9 and later compress .mod files with gzip
// but also do not include a date so we can fall through to
// compare them without skipping any prefix.
@@ -677,7 +649,7 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile,
return true;
}
}
- } else if (strcmp(compilerId, "Intel") == 0) {
+ } else if (compilerId == "Intel") {
const char seq[2] = { '\n', '\0' };
const int seqlen = 2;
@@ -709,9 +681,9 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile,
std::string cmDependsFortran::MaybeConvertToRelativePath(
std::string const& base, std::string const& path)
{
- if (!cmOutputConverter::ContainedInDirectory(
- base, path, this->LocalGenerator->GetStateSnapshot().GetDirectory())) {
+ if (!this->LocalGenerator->GetStateSnapshot().GetDirectory().ContainsBoth(
+ base, path)) {
return path;
}
- return cmOutputConverter::ForceToRelativePath(base, path);
+ return cmSystemTools::ForceToRelativePath(base, path);
}
diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h
index ec208af3a..04851152e 100644
--- a/Source/cmDependsFortran.h
+++ b/Source/cmDependsFortran.h
@@ -3,7 +3,7 @@
#ifndef cmFortran_h
#define cmFortran_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <set>
@@ -21,8 +21,6 @@ class cmLocalGenerator;
*/
class cmDependsFortran : public cmDepends
{
- CM_DISABLE_COPY(cmDependsFortran)
-
public:
/** Checking instances need to know the build directory name and the
relative path from the build directory to the target file. */
@@ -35,7 +33,10 @@ public:
cmDependsFortran(cmLocalGenerator* lg);
/** Virtual destructor to cleanup subclasses properly. */
- ~cmDependsFortran() CM_OVERRIDE;
+ ~cmDependsFortran() override;
+
+ cmDependsFortran(cmDependsFortran const&) = delete;
+ cmDependsFortran& operator=(cmDependsFortran const&) = delete;
/** Callback from build system after a .mod file has been generated
by a Fortran90 compiler to copy the .mod file to the
@@ -44,39 +45,46 @@ public:
/** Determine if a mod file and the corresponding mod.stamp file
are representing different module information. */
- static bool ModulesDiffer(const char* modFile, const char* stampFile,
- const char* compilerId);
+ static bool ModulesDiffer(const std::string& modFile,
+ const std::string& stampFile,
+ const std::string& compilerId);
protected:
// Finalize the dependency information for the target.
bool Finalize(std::ostream& makeDepends,
- std::ostream& internalDepends) CM_OVERRIDE;
+ std::ostream& internalDepends) override;
// Find all the modules required by the target.
void LocateModules();
void MatchLocalModules();
- void MatchRemoteModules(std::istream& fin, const char* stampDir);
- void ConsiderModule(const char* name, const char* stampDir);
+ void MatchRemoteModules(std::istream& fin, const std::string& stampDir);
+ void ConsiderModule(const std::string& name, const std::string& stampDir);
bool FindModule(std::string const& name, std::string& module);
// Implement writing/checking methods required by superclass.
bool WriteDependencies(const std::set<std::string>& sources,
const std::string& file, std::ostream& makeDepends,
- std::ostream& internalDepends) CM_OVERRIDE;
+ std::ostream& internalDepends) override;
- // Actually write the depenencies to the streams.
- bool WriteDependenciesReal(const char* obj, cmFortranSourceInfo const& info,
- std::string const& mod_dir, const char* stamp_dir,
+ // Actually write the dependencies to the streams.
+ bool WriteDependenciesReal(std::string const& obj,
+ cmFortranSourceInfo const& info,
+ std::string const& mod_dir,
+ std::string const& stamp_dir,
std::ostream& makeDepends,
std::ostream& internalDepends);
// The source file from which to start scanning.
std::string SourceFile;
+ std::string CompilerId;
+ std::string SModSep;
+ std::string SModExt;
+
std::set<std::string> PPDefinitions;
// Internal implementation details.
- cmDependsFortranInternals* Internal;
+ cmDependsFortranInternals* Internal = nullptr;
private:
std::string MaybeConvertToRelativePath(std::string const& base,
diff --git a/Source/cmDependsJava.cxx b/Source/cmDependsJava.cxx
index 29938ba36..b17b2ba74 100644
--- a/Source/cmDependsJava.cxx
+++ b/Source/cmDependsJava.cxx
@@ -4,13 +4,9 @@
#include "cmSystemTools.h"
-cmDependsJava::cmDependsJava()
-{
-}
+cmDependsJava::cmDependsJava() = default;
-cmDependsJava::~cmDependsJava()
-{
-}
+cmDependsJava::~cmDependsJava() = default;
bool cmDependsJava::WriteDependencies(const std::set<std::string>& sources,
const std::string& /*obj*/,
@@ -27,8 +23,8 @@ bool cmDependsJava::WriteDependencies(const std::set<std::string>& sources,
}
bool cmDependsJava::CheckDependencies(
- std::istream& /*internalDepends*/, const char* /*internalDependsFileName*/,
- std::map<std::string, DependencyVector>& /*validDeps*/)
+ std::istream& /*internalDepends*/,
+ const std::string& /*internalDependsFileName*/, DependencyMap& /*validDeps*/)
{
return true;
}
diff --git a/Source/cmDependsJava.h b/Source/cmDependsJava.h
index a07bf0979..2a9025101 100644
--- a/Source/cmDependsJava.h
+++ b/Source/cmDependsJava.h
@@ -3,38 +3,38 @@
#ifndef cmDependsJava_h
#define cmDependsJava_h
-#include "cmConfigure.h"
-
-#include "cmDepends.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
-#include <map>
#include <set>
#include <string>
+#include "cmDepends.h"
+
/** \class cmDependsJava
* \brief Dependency scanner for Java class files.
*/
class cmDependsJava : public cmDepends
{
- CM_DISABLE_COPY(cmDependsJava)
-
public:
/** Checking instances need to know the build directory name and the
relative path from the build directory to the target file. */
cmDependsJava();
/** Virtual destructor to cleanup subclasses properly. */
- ~cmDependsJava() CM_OVERRIDE;
+ ~cmDependsJava() override;
+
+ cmDependsJava(cmDependsJava const&) = delete;
+ cmDependsJava& operator=(cmDependsJava const&) = delete;
protected:
// Implement writing/checking methods required by superclass.
bool WriteDependencies(const std::set<std::string>& sources,
const std::string& file, std::ostream& makeDepends,
- std::ostream& internalDepends) CM_OVERRIDE;
- bool CheckDependencies(
- std::istream& internalDepends, const char* internalDependsFileName,
- std::map<std::string, DependencyVector>& validDeps) CM_OVERRIDE;
+ std::ostream& internalDepends) override;
+ bool CheckDependencies(std::istream& internalDepends,
+ const std::string& internalDependsFileName,
+ DependencyMap& validDeps) override;
};
#endif
diff --git a/Source/cmDependsJavaParserHelper.cxx b/Source/cmDependsJavaParserHelper.cxx
index 7bc91bfd4..516bbbfe0 100644
--- a/Source/cmDependsJavaParserHelper.cxx
+++ b/Source/cmDependsJavaParserHelper.cxx
@@ -2,16 +2,18 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDependsJavaParserHelper.h"
-#include "cmConfigure.h"
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <utility>
-#include "cmDependsJavaLexer.h"
-#include "cmSystemTools.h"
+#include <cm/string_view>
#include "cmsys/FStream.hxx"
-#include <iostream>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+
+#include "cmDependsJavaLexer.h"
+#include "cmSystemTools.h"
int cmDependsJava_yyparse(yyscan_t yyscanner);
@@ -24,7 +26,7 @@ cmDependsJavaParserHelper::cmDependsJavaParserHelper()
CurrentClass tl;
tl.Name = "*";
- this->ClassStack.push_back(tl);
+ this->ClassStack.push_back(std::move(tl));
}
cmDependsJavaParserHelper::~cmDependsJavaParserHelper()
@@ -42,10 +44,8 @@ void cmDependsJavaParserHelper::CurrentClass::AddFileNamesForPrinting(
}
rname += this->Name;
files->push_back(rname);
- std::vector<CurrentClass>::const_iterator it;
- for (it = this->NestedClasses.begin(); it != this->NestedClasses.end();
- ++it) {
- it->AddFileNamesForPrinting(files, rname.c_str(), sep);
+ for (CurrentClass const& nc : this->NestedClasses) {
+ nc.AddFileNamesForPrinting(files, rname.c_str(), sep);
}
}
@@ -57,7 +57,7 @@ void cmDependsJavaParserHelper::DeallocateParserType(char** pt)
if (!*pt) {
return;
}
- *pt = CM_NULLPTR;
+ *pt = nullptr;
this->UnionsAvailable--;
}
@@ -66,25 +66,22 @@ void cmDependsJavaParserHelper::AddClassFound(const char* sclass)
if (!sclass) {
return;
}
- std::vector<std::string>::iterator it;
- for (it = this->ClassesFound.begin(); it != this->ClassesFound.end(); it++) {
- if (*it == sclass) {
+ for (std::string const& cf : this->ClassesFound) {
+ if (cf == sclass) {
return;
}
}
- this->ClassesFound.push_back(sclass);
+ this->ClassesFound.emplace_back(sclass);
}
void cmDependsJavaParserHelper::AddPackagesImport(const char* sclass)
{
- std::vector<std::string>::iterator it;
- for (it = this->PackagesImport.begin(); it != this->PackagesImport.end();
- it++) {
- if (*it == sclass) {
+ for (std::string const& pi : this->PackagesImport) {
+ if (pi == sclass) {
return;
}
}
- this->PackagesImport.push_back(sclass);
+ this->PackagesImport.emplace_back(sclass);
}
void cmDependsJavaParserHelper::SafePrintMissing(const char* str, int line,
@@ -96,9 +93,9 @@ void cmDependsJavaParserHelper::SafePrintMissing(const char* str, int line,
for (cc = 0; cc < strlen(str); cc++) {
unsigned char ch = str[cc];
if (ch >= 32 && ch <= 126) {
- std::cout << (char)ch;
+ std::cout << static_cast<char>(ch);
} else {
- std::cout << "<" << (int)ch << ">";
+ std::cout << "<" << static_cast<int>(ch) << ">";
break;
}
}
@@ -158,15 +155,15 @@ void cmDependsJavaParserHelper::PrepareElement(
cmDependsJavaParserHelper::ParserType* me)
{
// Inititalize self
- me->str = CM_NULLPTR;
+ me->str = nullptr;
}
void cmDependsJavaParserHelper::AllocateParserType(
cmDependsJavaParserHelper::ParserType* pt, const char* str, int len)
{
- pt->str = CM_NULLPTR;
+ pt->str = nullptr;
if (len == 0) {
- len = (int)strlen(str);
+ len = static_cast<int>(strlen(str));
}
if (len == 0) {
return;
@@ -182,7 +179,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++;
}
@@ -210,10 +207,8 @@ void cmDependsJavaParserHelper::PrintClasses()
std::cerr << "Error when parsing. No classes on class stack" << std::endl;
abort();
}
- std::vector<std::string> files = this->GetFilesProduced();
- std::vector<std::string>::iterator sit;
- for (sit = files.begin(); sit != files.end(); ++sit) {
- std::cout << " " << *sit << ".class" << std::endl;
+ for (std::string const& f : this->GetFilesProduced()) {
+ std::cout << " " << f << ".class" << std::endl;
}
}
@@ -221,10 +216,8 @@ std::vector<std::string> cmDependsJavaParserHelper::GetFilesProduced()
{
std::vector<std::string> files;
CurrentClass const& toplevel = this->ClassStack.front();
- std::vector<CurrentClass>::const_iterator it;
- for (it = toplevel.NestedClasses.begin(); it != toplevel.NestedClasses.end();
- ++it) {
- it->AddFileNamesForPrinting(&files, CM_NULLPTR, "$");
+ for (CurrentClass const& nc : toplevel.NestedClasses) {
+ nc.AddFileNamesForPrinting(&files, nullptr, "$");
}
return files;
}
@@ -264,10 +257,8 @@ int cmDependsJavaParserHelper::ParseString(const char* str, int verb)
std::cout << std::endl;
std::cout << "Depends on:";
if (!this->ClassesFound.empty()) {
- std::vector<std::string>::iterator it;
- for (it = this->ClassesFound.begin(); it != this->ClassesFound.end();
- ++it) {
- std::cout << " " << *it;
+ for (std::string const& cf : this->ClassesFound) {
+ std::cout << " " << cf;
}
}
std::cout << std::endl;
@@ -284,9 +275,8 @@ int cmDependsJavaParserHelper::ParseString(const char* str, int verb)
void cmDependsJavaParserHelper::CleanupParser()
{
- std::vector<char*>::iterator it;
- for (it = this->Allocates.begin(); it != this->Allocates.end(); ++it) {
- delete[] * it;
+ for (char* allocate : this->Allocates) {
+ delete[] allocate;
}
this->Allocates.erase(this->Allocates.begin(), this->Allocates.end());
}
@@ -311,20 +301,16 @@ void cmDependsJavaParserHelper::Error(const char* str)
unsigned long pos = static_cast<unsigned long>(this->InputBufferPos);
fprintf(stderr, "JPError: %s (%lu / Line: %d)\n", str, pos,
this->CurrentLine);
- int cc;
- std::cerr << "String: [";
- for (cc = 0;
- cc < 30 && *(this->InputBuffer.c_str() + this->InputBufferPos + cc);
- cc++) {
- std::cerr << *(this->InputBuffer.c_str() + this->InputBufferPos + cc);
- }
- std::cerr << "]" << std::endl;
+ std::cerr << "String: ["
+ << cm::string_view{ this->InputBuffer }.substr(
+ this->InputBufferPos, 30)
+ << "]" << std::endl;
}
void cmDependsJavaParserHelper::UpdateCombine(const char* str1,
const char* str2)
{
- if (this->CurrentCombine == "" && str1 != CM_NULLPTR) {
+ if (this->CurrentCombine.empty() && str1 != nullptr) {
this->CurrentCombine = str1;
}
this->CurrentCombine += ".";
diff --git a/Source/cmDependsJavaParserHelper.h b/Source/cmDependsJavaParserHelper.h
index 0b445d924..a673b5bbb 100644
--- a/Source/cmDependsJavaParserHelper.h
+++ b/Source/cmDependsJavaParserHelper.h
@@ -24,6 +24,10 @@ public:
cmDependsJavaParserHelper();
~cmDependsJavaParserHelper();
+ cmDependsJavaParserHelper(const cmDependsJavaParserHelper&) = delete;
+ cmDependsJavaParserHelper& operator=(const cmDependsJavaParserHelper&) =
+ delete;
+
int ParseString(const char* str, int verb);
int ParseFile(const char* file);
diff --git a/Source/cmDisallowedCommand.cxx b/Source/cmDisallowedCommand.cxx
deleted file mode 100644
index ce1965d30..000000000
--- a/Source/cmDisallowedCommand.cxx
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmDisallowedCommand.h"
-
-#include "cmMakefile.h"
-#include "cmake.h"
-
-class cmExecutionStatus;
-
-bool cmDisallowedCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status)
-{
- switch (this->Makefile->GetPolicyStatus(this->Policy)) {
- case cmPolicies::WARN:
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING,
- cmPolicies::GetPolicyWarning(this->Policy));
- break;
- case cmPolicies::OLD:
- break;
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::NEW:
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, this->Message);
- return true;
- }
-
- this->Command->SetMakefile(this->GetMakefile());
- bool const ret = this->Command->InitialPass(args, status);
- this->SetError(this->Command->GetError());
- return ret;
-}
diff --git a/Source/cmDisallowedCommand.h b/Source/cmDisallowedCommand.h
deleted file mode 100644
index 0030116b8..000000000
--- a/Source/cmDisallowedCommand.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmDisallowedCommand_h
-#define cmDisallowedCommand_h
-
-#include "cmConfigure.h"
-
-#include <string>
-#include <vector>
-
-#include "cmCommand.h"
-#include "cmPolicies.h"
-
-class cmExecutionStatus;
-
-class cmDisallowedCommand : public cmCommand
-{
-public:
- cmDisallowedCommand(cmCommand* command, cmPolicies::PolicyID policy,
- const char* message)
- : Command(command)
- , Policy(policy)
- , Message(message)
- {
- }
-
- ~cmDisallowedCommand() CM_OVERRIDE { delete this->Command; }
-
- cmCommand* Clone() CM_OVERRIDE
- {
- return new cmDisallowedCommand(this->Command->Clone(), this->Policy,
- this->Message);
- }
-
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
- void FinalPass() CM_OVERRIDE { this->Command->FinalPass(); }
-
- bool HasFinalPass() const CM_OVERRIDE
- {
- return this->Command->HasFinalPass();
- }
-
-private:
- cmCommand* Command;
- cmPolicies::PolicyID Policy;
- const char* Message;
-};
-
-#endif
diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx
index c6286b35a..1bc453d37 100644
--- a/Source/cmDocumentation.cxx
+++ b/Source/cmDocumentation.cxx
@@ -2,20 +2,20 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDocumentation.h"
-#include "cmAlgorithms.h"
+#include <algorithm>
+#include <cctype>
+#include <cstring>
+#include <utility>
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+
#include "cmDocumentationEntry.h"
#include "cmDocumentationSection.h"
#include "cmRST.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
-#include "cmsys/FStream.hxx"
-#include "cmsys/Glob.hxx"
-#include <algorithm>
-#include <ctype.h>
-#include <string.h>
-#include <utility>
-
static const char* cmDocumentationStandardOptions[][2] = {
{ "--help,-help,-usage,-h,-H,/?", "Print usage information and exit." },
{ "--version,-version,/V [<f>]", "Print version number and exit." },
@@ -41,12 +41,19 @@ static const char* cmDocumentationStandardOptions[][2] = {
{ "--help-variable-list [<f>]",
"List variables with help available and exit." },
{ "--help-variables [<f>]", "Print cmake-variables manual and exit." },
- { CM_NULLPTR, CM_NULLPTR }
+ { nullptr, nullptr }
};
-static const char* cmDocumentationGeneratorsHeader[][2] = {
- { CM_NULLPTR, "The following generators are available on this platform:" },
- { CM_NULLPTR, CM_NULLPTR }
+static const char* cmDocumentationCPackGeneratorsHeader[][2] = {
+ { nullptr, "The following generators are available on this platform:" },
+ { nullptr, nullptr }
+};
+
+static const char* cmDocumentationCMakeGeneratorsHeader[][2] = {
+ { nullptr,
+ "The following generators are available on this platform (* marks "
+ "default):" },
+ { nullptr, nullptr }
};
cmDocumentation::cmDocumentation()
@@ -55,11 +62,6 @@ cmDocumentation::cmDocumentation()
this->ShowGenerators = true;
}
-cmDocumentation::~cmDocumentation()
-{
- cmDeleteAll(this->AllSections);
-}
-
bool cmDocumentation::PrintVersion(std::ostream& os)
{
/* clang-format off */
@@ -123,23 +125,21 @@ bool cmDocumentation::PrintRequestedDocumentation(std::ostream& os)
bool result = true;
// Loop over requested documentation types.
- for (std::vector<RequestedHelpItem>::const_iterator i =
- this->RequestedHelpItems.begin();
- i != this->RequestedHelpItems.end(); ++i) {
- this->CurrentArgument = i->Argument;
+ for (RequestedHelpItem const& rhi : this->RequestedHelpItems) {
+ this->CurrentArgument = rhi.Argument;
// If a file name was given, use it. Otherwise, default to the
// given stream.
cmsys::ofstream fout;
std::ostream* s = &os;
- if (!i->Filename.empty()) {
- fout.open(i->Filename.c_str());
+ if (!rhi.Filename.empty()) {
+ fout.open(rhi.Filename.c_str());
s = &fout;
} else if (++count > 1) {
os << "\n\n";
}
// Print this documentation type to the stream.
- if (!this->PrintDocumentation(i->HelpType, *s) || s->fail()) {
+ if (!this->PrintDocumentation(rhi.HelpType, *s) || s->fail()) {
result = false;
}
}
@@ -147,10 +147,12 @@ bool cmDocumentation::PrintRequestedDocumentation(std::ostream& os)
}
#define GET_OPT_ARGUMENT(target) \
- if ((i + 1 < argc) && !this->IsOption(argv[i + 1])) { \
- (target) = argv[i + 1]; \
- i = i + 1; \
- };
+ do { \
+ if ((i + 1 < argc) && !this->IsOption(argv[i + 1])) { \
+ (target) = argv[i + 1]; \
+ i = i + 1; \
+ }; \
+ } while (false)
void cmDocumentation::WarnFormFromFilename(
cmDocumentation::RequestedHelpItem& request, bool& result)
@@ -176,20 +178,16 @@ void cmDocumentation::WarnFormFromFilename(
void cmDocumentation::addCommonStandardDocSections()
{
- cmDocumentationSection* sec;
-
- sec = new cmDocumentationSection("Options", "OPTIONS");
- sec->Append(cmDocumentationStandardOptions);
- this->AllSections["Options"] = sec;
+ cmDocumentationSection sec{ "Options" };
+ sec.Append(cmDocumentationStandardOptions);
+ this->AllSections.emplace("Options", std::move(sec));
}
void cmDocumentation::addCMakeStandardDocSections()
{
- cmDocumentationSection* sec;
-
- sec = new cmDocumentationSection("Generators", "GENERATORS");
- sec->Append(cmDocumentationGeneratorsHeader);
- this->AllSections["Generators"] = sec;
+ cmDocumentationSection sec{ "Generators" };
+ sec.Append(cmDocumentationCMakeGeneratorsHeader);
+ this->AllSections.emplace("Generators", std::move(sec));
}
void cmDocumentation::addCTestStandardDocSections()
@@ -201,11 +199,9 @@ void cmDocumentation::addCTestStandardDocSections()
void cmDocumentation::addCPackStandardDocSections()
{
- cmDocumentationSection* sec;
-
- sec = new cmDocumentationSection("Generators", "GENERATORS");
- sec->Append(cmDocumentationGeneratorsHeader);
- this->AllSections["Generators"] = sec;
+ cmDocumentationSection sec{ "Generators" };
+ sec.Append(cmDocumentationCPackGeneratorsHeader);
+ this->AllSections.emplace("Generators", std::move(sec));
}
bool cmDocumentation::CheckOptions(int argc, const char* const* argv,
@@ -215,7 +211,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;
}
@@ -354,7 +350,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;
@@ -366,93 +362,59 @@ void cmDocumentation::SetName(const std::string& name)
}
void cmDocumentation::SetSection(const char* name,
- cmDocumentationSection* section)
+ cmDocumentationSection section)
{
- if (this->AllSections.find(name) != this->AllSections.end()) {
- delete this->AllSections[name];
- }
- this->AllSections[name] = section;
+ this->SectionAtName(name) = std::move(section);
}
void cmDocumentation::SetSection(const char* name,
std::vector<cmDocumentationEntry>& docs)
{
- cmDocumentationSection* sec =
- new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str());
- sec->Append(docs);
- this->SetSection(name, sec);
+ cmDocumentationSection sec{ name };
+ sec.Append(docs);
+ this->SetSection(name, std::move(sec));
}
void cmDocumentation::SetSection(const char* name, const char* docs[][2])
{
- cmDocumentationSection* sec =
- new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str());
- sec->Append(docs);
- this->SetSection(name, sec);
+ cmDocumentationSection sec{ name };
+ sec.Append(docs);
+ this->SetSection(name, std::move(sec));
}
void cmDocumentation::SetSections(
- std::map<std::string, cmDocumentationSection*>& sections)
+ std::map<std::string, cmDocumentationSection> sections)
{
- for (std::map<std::string, cmDocumentationSection*>::const_iterator it =
- sections.begin();
- it != sections.end(); ++it) {
- this->SetSection(it->first.c_str(), it->second);
+ for (auto& s : sections) {
+ this->SetSection(s.first.c_str(), std::move(s.second));
}
}
+cmDocumentationSection& cmDocumentation::SectionAtName(const char* name)
+{
+ return this->AllSections.emplace(name, cmDocumentationSection{ name })
+ .first->second;
+}
void cmDocumentation::PrependSection(const char* name, const char* docs[][2])
{
- cmDocumentationSection* sec = CM_NULLPTR;
- if (this->AllSections.find(name) == this->AllSections.end()) {
- sec =
- new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str());
- this->SetSection(name, sec);
- } else {
- sec = this->AllSections[name];
- }
- sec->Prepend(docs);
+ this->SectionAtName(name).Prepend(docs);
}
void cmDocumentation::PrependSection(const char* name,
std::vector<cmDocumentationEntry>& docs)
{
- cmDocumentationSection* sec = CM_NULLPTR;
- if (this->AllSections.find(name) == this->AllSections.end()) {
- sec =
- new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str());
- this->SetSection(name, sec);
- } else {
- sec = this->AllSections[name];
- }
- sec->Prepend(docs);
+ this->SectionAtName(name).Prepend(docs);
}
void cmDocumentation::AppendSection(const char* name, const char* docs[][2])
{
- cmDocumentationSection* sec = CM_NULLPTR;
- if (this->AllSections.find(name) == this->AllSections.end()) {
- sec =
- new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str());
- this->SetSection(name, sec);
- } else {
- sec = this->AllSections[name];
- }
- sec->Append(docs);
+ this->SectionAtName(name).Append(docs);
}
void cmDocumentation::AppendSection(const char* name,
std::vector<cmDocumentationEntry>& docs)
{
- cmDocumentationSection* sec = CM_NULLPTR;
- if (this->AllSections.find(name) == this->AllSections.end()) {
- sec =
- new cmDocumentationSection(name, cmSystemTools::UpperCase(name).c_str());
- this->SetSection(name, sec);
- } else {
- sec = this->AllSections[name];
- }
- sec->Append(docs);
+ this->SectionAtName(name).Append(docs);
}
void cmDocumentation::AppendSection(const char* name,
@@ -489,10 +451,9 @@ void cmDocumentation::PrintNames(std::ostream& os, std::string const& pattern)
std::vector<std::string> files;
this->GlobHelp(files, pattern);
std::vector<std::string> names;
- for (std::vector<std::string>::const_iterator i = files.begin();
- i != files.end(); ++i) {
+ for (std::string const& f : files) {
std::string line;
- cmsys::ifstream fin(i->c_str());
+ cmsys::ifstream fin(f.c_str());
while (fin && cmSystemTools::GetLineFromStream(fin, line)) {
if (!line.empty() && (isalnum(line[0]) || line[0] == '<')) {
names.push_back(line);
@@ -501,9 +462,8 @@ void cmDocumentation::PrintNames(std::ostream& os, std::string const& pattern)
}
}
std::sort(names.begin(), names.end());
- for (std::vector<std::string>::iterator i = names.begin(); i != names.end();
- ++i) {
- os << *i << "\n";
+ for (std::string const& n : names) {
+ os << n << "\n";
}
}
@@ -514,9 +474,8 @@ bool cmDocumentation::PrintFiles(std::ostream& os, std::string const& pattern)
this->GlobHelp(files, pattern);
std::sort(files.begin(), files.end());
cmRST r(os, cmSystemTools::GetCMakeRoot() + "/Help");
- for (std::vector<std::string>::const_iterator i = files.begin();
- i != files.end(); ++i) {
- found = r.ProcessFile(*i) || found;
+ for (std::string const& f : files) {
+ found = r.ProcessFile(f) || found;
}
return found;
}
@@ -586,15 +545,13 @@ bool cmDocumentation::PrintHelpListModules(std::ostream& os)
std::vector<std::string> files;
this->GlobHelp(files, "module/*");
std::vector<std::string> modules;
- for (std::vector<std::string>::iterator fi = files.begin();
- fi != files.end(); ++fi) {
- std::string module = cmSystemTools::GetFilenameName(*fi);
+ for (std::string const& f : files) {
+ std::string module = cmSystemTools::GetFilenameName(f);
modules.push_back(module.substr(0, module.size() - 4));
}
std::sort(modules.begin(), modules.end());
- for (std::vector<std::string>::iterator i = modules.begin();
- i != modules.end(); ++i) {
- os << *i << "\n";
+ for (std::string const& m : modules) {
+ os << m << "\n";
}
return true;
}
@@ -640,11 +597,10 @@ bool cmDocumentation::PrintHelpListPolicies(std::ostream& os)
bool cmDocumentation::PrintHelpListGenerators(std::ostream& os)
{
- std::map<std::string, cmDocumentationSection*>::iterator si;
- si = this->AllSections.find("Generators");
+ const auto si = this->AllSections.find("Generators");
if (si != this->AllSections.end()) {
this->Formatter.SetIndent(" ");
- this->Formatter.PrintSection(os, *si->second);
+ this->Formatter.PrintSection(os, si->second);
}
return true;
}
@@ -670,29 +626,27 @@ bool cmDocumentation::PrintHelpListVariables(std::ostream& os)
bool cmDocumentation::PrintUsage(std::ostream& os)
{
- std::map<std::string, cmDocumentationSection*>::iterator si;
- si = this->AllSections.find("Usage");
+ const auto si = this->AllSections.find("Usage");
if (si != this->AllSections.end()) {
- this->Formatter.PrintSection(os, *si->second);
+ this->Formatter.PrintSection(os, si->second);
}
return true;
}
bool cmDocumentation::PrintHelp(std::ostream& os)
{
- std::map<std::string, cmDocumentationSection*>::iterator si;
- si = this->AllSections.find("Usage");
+ auto si = this->AllSections.find("Usage");
if (si != this->AllSections.end()) {
- this->Formatter.PrintSection(os, *si->second);
+ this->Formatter.PrintSection(os, si->second);
}
si = this->AllSections.find("Options");
if (si != this->AllSections.end()) {
- this->Formatter.PrintSection(os, *si->second);
+ this->Formatter.PrintSection(os, si->second);
}
if (this->ShowGenerators) {
si = this->AllSections.find("Generators");
if (si != this->AllSections.end()) {
- this->Formatter.PrintSection(os, *si->second);
+ this->Formatter.PrintSection(os, si->second);
}
}
return true;
diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h
index 2866fef03..3768e1abe 100644
--- a/Source/cmDocumentation.h
+++ b/Source/cmDocumentation.h
@@ -3,16 +3,16 @@
#ifndef _cmDocumentation_h
#define _cmDocumentation_h
-#include "cmConfigure.h"
-
-#include "cmDocumentationFormatter.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <map>
#include <string>
#include <vector>
-class cmDocumentationSection;
+#include "cmDocumentationFormatter.h"
+#include "cmDocumentationSection.h"
+
struct cmDocumentationEntry;
/** Class to generate documentation. */
@@ -21,8 +21,6 @@ class cmDocumentation : public cmDocumentationEnums
public:
cmDocumentation();
- ~cmDocumentation();
-
/**
* Check command line arguments for documentation options. Returns
* true if documentation options are found, and false otherwise.
@@ -32,7 +30,7 @@ public:
* help arguments.
*/
bool CheckOptions(int argc, const char* const* argv,
- const char* exitOpt = CM_NULLPTR);
+ const char* exitOpt = nullptr);
/**
* Print help requested on the command line. Call after
@@ -52,11 +50,11 @@ public:
/** Set a section of the documentation. Typical sections include Name,
Usage, Description, Options */
- void SetSection(const char* sectionName, cmDocumentationSection* section);
+ void SetSection(const char* sectionName, cmDocumentationSection section);
void SetSection(const char* sectionName,
std::vector<cmDocumentationEntry>& docs);
void SetSection(const char* sectionName, const char* docs[][2]);
- void SetSections(std::map<std::string, cmDocumentationSection*>& sections);
+ void SetSections(std::map<std::string, cmDocumentationSection> sections);
/** Add the documentation to the beginning/end of the section */
void PrependSection(const char* sectionName, const char* docs[][2]);
@@ -110,17 +108,14 @@ private:
bool ShowGenerators;
std::string NameString;
- std::map<std::string, cmDocumentationSection*> AllSections;
+ std::map<std::string, cmDocumentationSection> AllSections;
+ cmDocumentationSection& SectionAtName(const char* name);
std::string CurrentArgument;
struct RequestedHelpItem
{
- RequestedHelpItem()
- : HelpType(None)
- {
- }
- cmDocumentationEnums::Type HelpType;
+ cmDocumentationEnums::Type HelpType = None;
std::string Filename;
std::string Argument;
};
diff --git a/Source/cmDocumentationEntry.h b/Source/cmDocumentationEntry.h
index ea43b88c3..afbca5e4b 100644
--- a/Source/cmDocumentationEntry.h
+++ b/Source/cmDocumentationEntry.h
@@ -12,7 +12,8 @@ struct cmDocumentationEntry
{
std::string Name;
std::string Brief;
- cmDocumentationEntry() {}
+ char CustomNamePrefix = ' ';
+ cmDocumentationEntry() = default;
cmDocumentationEntry(const char* doc[2])
{
if (doc[0]) {
diff --git a/Source/cmDocumentationFormatter.cxx b/Source/cmDocumentationFormatter.cxx
index 001826318..732637e36 100644
--- a/Source/cmDocumentationFormatter.cxx
+++ b/Source/cmDocumentationFormatter.cxx
@@ -2,23 +2,18 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDocumentationFormatter.h"
-#include "cmDocumentationEntry.h"
-#include "cmDocumentationSection.h"
-
+#include <cstring>
+#include <iomanip>
#include <ostream>
-#include <string.h>
#include <string>
#include <vector>
-cmDocumentationFormatter::cmDocumentationFormatter()
- : TextWidth(77)
- , TextIndent("")
-{
-}
+#include "cmDocumentationEntry.h"
+#include "cmDocumentationSection.h"
-cmDocumentationFormatter::~cmDocumentationFormatter()
-{
-}
+cmDocumentationFormatter::cmDocumentationFormatter() = default;
+
+cmDocumentationFormatter::~cmDocumentationFormatter() = default;
void cmDocumentationFormatter::PrintFormatted(std::ostream& os,
const char* text)
@@ -90,7 +85,7 @@ void cmDocumentationFormatter::SetIndent(const char* indent)
void cmDocumentationFormatter::PrintColumn(std::ostream& os, const char* text)
{
- // Print text arranged in an indented column of fixed witdh.
+ // Print text arranged in an indented column of fixed width.
const char* l = text;
long column = 0;
bool newSentence = false;
@@ -168,26 +163,25 @@ void cmDocumentationFormatter::PrintSection(
os << section.GetName() << "\n";
const std::vector<cmDocumentationEntry>& entries = section.GetEntries();
- for (std::vector<cmDocumentationEntry>::const_iterator op = entries.begin();
- op != entries.end(); ++op) {
- if (!op->Name.empty()) {
- os << " " << op->Name;
+ for (cmDocumentationEntry const& entry : entries) {
+ if (!entry.Name.empty()) {
+ os << std::setw(2) << std::left << entry.CustomNamePrefix << entry.Name;
this->TextIndent = " ";
int align = static_cast<int>(strlen(this->TextIndent)) - 4;
- for (int i = static_cast<int>(op->Name.size()); i < align; ++i) {
+ for (int i = static_cast<int>(entry.Name.size()); i < align; ++i) {
os << " ";
}
- if (op->Name.size() > strlen(this->TextIndent) - 4) {
+ if (entry.Name.size() > strlen(this->TextIndent) - 4) {
os << "\n";
os.write(this->TextIndent, strlen(this->TextIndent) - 2);
}
os << "= ";
- this->PrintColumn(os, op->Brief.c_str());
+ this->PrintColumn(os, entry.Brief.c_str());
os << "\n";
} else {
os << "\n";
this->TextIndent = "";
- this->PrintFormatted(os, op->Brief.c_str());
+ this->PrintFormatted(os, entry.Brief.c_str());
}
}
os << "\n";
diff --git a/Source/cmDocumentationFormatter.h b/Source/cmDocumentationFormatter.h
index 1f04250c9..17b63dacc 100644
--- a/Source/cmDocumentationFormatter.h
+++ b/Source/cmDocumentationFormatter.h
@@ -59,8 +59,8 @@ public:
void SetIndent(const char* indent);
private:
- int TextWidth;
- const char* TextIndent;
+ int TextWidth = 77;
+ const char* TextIndent = "";
};
#endif
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/cmDocumentationSection.h b/Source/cmDocumentationSection.h
index d9e8187f8..15cada6de 100644
--- a/Source/cmDocumentationSection.h
+++ b/Source/cmDocumentationSection.h
@@ -5,11 +5,12 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmDocumentationEntry.h"
-
#include <string>
#include <vector>
+#include "cmAlgorithms.h"
+#include "cmDocumentationEntry.h"
+
// Low-level interface for custom documents:
/** Internal class representing a section of the documentation.
* Cares e.g. for the different section titles in the different
@@ -19,7 +20,7 @@ class cmDocumentationSection
{
public:
/** Create a cmSection, with a special name for man-output mode. */
- cmDocumentationSection(const char* name, const char*)
+ explicit cmDocumentationSection(const char* name)
: Name(name)
{
}
@@ -46,7 +47,7 @@ public:
}
void Append(const std::vector<cmDocumentationEntry>& entries)
{
- this->Entries.insert(this->Entries.end(), entries.begin(), entries.end());
+ cmAppend(this->Entries, entries);
}
/** Append an entry to this section using NULL terminated chars */
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..ccd1cc1cc
--- /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>
+
+using cmDuration = std::chrono::duration<double, std::ratio<1>>;
+
+/*
+ * 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/cmDynamicLoader.cxx b/Source/cmDynamicLoader.cxx
index 7fbe75c7b..0b72a94b2 100644
--- a/Source/cmDynamicLoader.cxx
+++ b/Source/cmDynamicLoader.cxx
@@ -22,11 +22,9 @@ private:
static cmDynamicLoaderCache* Instance;
};
-cmDynamicLoaderCache* cmDynamicLoaderCache::Instance = CM_NULLPTR;
+cmDynamicLoaderCache* cmDynamicLoaderCache::Instance = nullptr;
-cmDynamicLoaderCache::~cmDynamicLoaderCache()
-{
-}
+cmDynamicLoaderCache::~cmDynamicLoaderCache() = default;
void cmDynamicLoaderCache::CacheFile(const char* path,
cmsys::DynamicLoader::LibraryHandle p)
@@ -41,8 +39,7 @@ void cmDynamicLoaderCache::CacheFile(const char* path,
bool cmDynamicLoaderCache::GetCacheFile(const char* path,
cmsys::DynamicLoader::LibraryHandle& p)
{
- std::map<std::string, cmsys::DynamicLoader::LibraryHandle>::iterator it =
- this->CacheMap.find(path);
+ auto it = this->CacheMap.find(path);
if (it != this->CacheMap.end()) {
p = it->second;
return true;
@@ -52,8 +49,7 @@ bool cmDynamicLoaderCache::GetCacheFile(const char* path,
bool cmDynamicLoaderCache::FlushCache(const char* path)
{
- std::map<std::string, cmsys::DynamicLoader::LibraryHandle>::iterator it =
- this->CacheMap.find(path);
+ auto it = this->CacheMap.find(path);
bool ret = false;
if (it != this->CacheMap.end()) {
cmsys::DynamicLoader::CloseLibrary(it->second);
@@ -65,13 +61,11 @@ bool cmDynamicLoaderCache::FlushCache(const char* path)
void cmDynamicLoaderCache::FlushCache()
{
- for (std::map<std::string, cmsys::DynamicLoader::LibraryHandle>::iterator
- it = this->CacheMap.begin();
- it != this->CacheMap.end(); it++) {
- cmsys::DynamicLoader::CloseLibrary(it->second);
+ for (auto const& it : this->CacheMap) {
+ cmsys::DynamicLoader::CloseLibrary(it.second);
}
delete cmDynamicLoaderCache::Instance;
- cmDynamicLoaderCache::Instance = CM_NULLPTR;
+ cmDynamicLoaderCache::Instance = nullptr;
}
cmDynamicLoaderCache* cmDynamicLoaderCache::GetInstance()
diff --git a/Source/cmDynamicLoader.h b/Source/cmDynamicLoader.h
index 7c46dd5d4..4b89388e2 100644
--- a/Source/cmDynamicLoader.h
+++ b/Source/cmDynamicLoader.h
@@ -8,14 +8,12 @@
#ifndef cmDynamicLoader_h
#define cmDynamicLoader_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include "cmsys/DynamicLoader.hxx" // IWYU pragma: export
class cmDynamicLoader
{
- CM_DISABLE_COPY(cmDynamicLoader)
-
public:
// Description:
// Load a dynamic library into the current process.
@@ -28,8 +26,8 @@ public:
static void FlushCache();
protected:
- cmDynamicLoader() {}
- ~cmDynamicLoader() {}
+ cmDynamicLoader() = default;
+ ~cmDynamicLoader() = default;
};
#endif
diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx
index fc97bf3b3..5976b2f78 100644
--- a/Source/cmELF.cxx
+++ b/Source/cmELF.cxx
@@ -2,50 +2,56 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmELF.h"
-#include "cm_auto_ptr.hxx"
-#include "cm_kwiml.h"
-#include "cmsys/FStream.hxx"
+#include <cstddef>
#include <map>
+#include <memory>
#include <sstream>
-#include <stddef.h>
#include <utility>
#include <vector>
+#include <cm/memory>
+
+#include "cmsys/FStream.hxx"
+
+#include "cm_kwiml.h"
+
+#include "cmAlgorithms.h"
+
// Include the ELF format information system header.
#if defined(__OpenBSD__)
-#include <elf_abi.h>
-#include <stdint.h>
+# include <elf_abi.h>
+# include <stdint.h>
#elif defined(__HAIKU__)
-#include <elf32.h>
-#include <elf64.h>
-typedef struct Elf32_Ehdr Elf32_Ehdr;
-typedef struct Elf32_Shdr Elf32_Shdr;
-typedef struct Elf32_Sym Elf32_Sym;
-typedef struct Elf32_Rel Elf32_Rel;
-typedef struct Elf32_Rela Elf32_Rela;
-#define ELFMAG0 0x7F
-#define ELFMAG1 'E'
-#define ELFMAG2 'L'
-#define ELFMAG3 'F'
-#define ET_NONE 0
-#define ET_REL 1
-#define ET_EXEC 2
-#define ET_DYN 3
-#define ET_CORE 4
-#define EM_386 3
-#define EM_SPARC 2
-#define EM_PPC 20
+# include <elf32.h>
+# include <elf64.h>
+using Elf32_Ehdr = struct Elf32_Ehdr;
+using Elf32_Shdr = struct Elf32_Shdr;
+using Elf32_Sym = struct Elf32_Sym;
+using Elf32_Rel = struct Elf32_Rel;
+using Elf32_Rela = struct Elf32_Rela;
+# define ELFMAG0 0x7F
+# define ELFMAG1 'E'
+# define ELFMAG2 'L'
+# define ELFMAG3 'F'
+# define ET_NONE 0
+# define ET_REL 1
+# define ET_EXEC 2
+# define ET_DYN 3
+# define ET_CORE 4
+# define EM_386 3
+# define EM_SPARC 2
+# define EM_PPC 20
#else
-#include <elf.h>
+# include <elf.h>
#endif
#if defined(__sun)
-#include <sys/link.h> // For dynamic section information
+# include <sys/link.h> // For dynamic section information
#endif
#ifdef _SCO_DS
-#include <link.h> // For DT_SONAME etc.
+# include <link.h> // For DT_SONAME etc.
#endif
#ifndef DT_RUNPATH
-#define DT_RUNPATH 29
+# define DT_RUNPATH 29
#endif
// Low-level byte swapping implementation.
@@ -100,7 +106,7 @@ void cmELFByteSwap(T& x)
class cmELFInternal
{
public:
- typedef cmELF::StringEntry StringEntry;
+ using StringEntry = cmELF::StringEntry;
enum ByteOrderType
{
ByteOrderMSB,
@@ -108,10 +114,10 @@ public:
};
// Construct and take ownership of the file stream object.
- cmELFInternal(cmELF* external, CM_AUTO_PTR<cmsys::ifstream>& fin,
+ cmELFInternal(cmELF* external, std::unique_ptr<std::istream> fin,
ByteOrderType order)
: External(external)
- , Stream(*fin.release())
+ , Stream(std::move(fin))
, ByteOrder(order)
, ELFType(cmELF::FileTypeInvalid)
{
@@ -131,7 +137,7 @@ public:
}
// Destruct and delete the file stream object.
- virtual ~cmELFInternal() { delete &this->Stream; }
+ virtual ~cmELFInternal() = default;
// Forward to the per-class implementation.
virtual unsigned int GetNumberOfSections() const = 0;
@@ -162,6 +168,7 @@ public:
// Return the recorded ELF type.
cmELF::FileType GetFileType() const { return this->ELFType; }
+
protected:
// Data common to all ELF class implementations.
@@ -169,7 +176,7 @@ protected:
cmELF* External;
// The stream from which to read.
- std::istream& Stream;
+ std::unique_ptr<std::istream> Stream;
// The byte order of the ELF file.
ByteOrderType ByteOrder;
@@ -197,11 +204,11 @@ protected:
// Configure the implementation template for 32-bit ELF files.
struct cmELFTypes32
{
- typedef Elf32_Ehdr ELF_Ehdr;
- typedef Elf32_Shdr ELF_Shdr;
- typedef Elf32_Dyn ELF_Dyn;
- typedef Elf32_Half ELF_Half;
- typedef KWIML_INT_uint32_t tagtype;
+ using ELF_Ehdr = Elf32_Ehdr;
+ using ELF_Shdr = Elf32_Shdr;
+ using ELF_Dyn = Elf32_Dyn;
+ using ELF_Half = Elf32_Half;
+ using tagtype = ::uint32_t;
static const char* GetName() { return "32-bit"; }
};
@@ -209,11 +216,11 @@ struct cmELFTypes32
#ifndef _SCO_DS
struct cmELFTypes64
{
- typedef Elf64_Ehdr ELF_Ehdr;
- typedef Elf64_Shdr ELF_Shdr;
- typedef Elf64_Dyn ELF_Dyn;
- typedef Elf64_Half ELF_Half;
- typedef KWIML_INT_uint64_t tagtype;
+ using ELF_Ehdr = Elf64_Ehdr;
+ using ELF_Shdr = Elf64_Shdr;
+ using ELF_Dyn = Elf64_Dyn;
+ using ELF_Half = Elf64_Half;
+ using tagtype = ::uint64_t;
static const char* GetName() { return "64-bit"; }
};
#endif
@@ -224,34 +231,34 @@ class cmELFInternalImpl : public cmELFInternal
{
public:
// Copy the ELF file format types from our configuration parameter.
- typedef typename Types::ELF_Ehdr ELF_Ehdr;
- typedef typename Types::ELF_Shdr ELF_Shdr;
- typedef typename Types::ELF_Dyn ELF_Dyn;
- typedef typename Types::ELF_Half ELF_Half;
- typedef typename Types::tagtype tagtype;
+ using ELF_Ehdr = typename Types::ELF_Ehdr;
+ using ELF_Shdr = typename Types::ELF_Shdr;
+ using ELF_Dyn = typename Types::ELF_Dyn;
+ using ELF_Half = typename Types::ELF_Half;
+ using tagtype = typename Types::tagtype;
// Construct with a stream and byte swap indicator.
- cmELFInternalImpl(cmELF* external, CM_AUTO_PTR<cmsys::ifstream>& fin,
+ cmELFInternalImpl(cmELF* external, std::unique_ptr<std::istream> fin,
ByteOrderType order);
// Return the number of sections as specified by the ELF header.
- unsigned int GetNumberOfSections() const CM_OVERRIDE
+ unsigned int GetNumberOfSections() const override
{
return static_cast<unsigned int>(this->ELFHeader.e_shnum);
}
// Get the file position of a dynamic section entry.
- unsigned long GetDynamicEntryPosition(int j) CM_OVERRIDE;
+ unsigned long GetDynamicEntryPosition(int j) override;
- cmELF::DynamicEntryList GetDynamicEntries() CM_OVERRIDE;
- std::vector<char> EncodeDynamicEntries(const cmELF::DynamicEntryList&)
- CM_OVERRIDE;
+ cmELF::DynamicEntryList GetDynamicEntries() override;
+ std::vector<char> EncodeDynamicEntries(
+ const cmELF::DynamicEntryList&) override;
// Lookup a string from the dynamic section with the given tag.
- StringEntry const* GetDynamicSectionString(unsigned int tag) CM_OVERRIDE;
+ StringEntry const* GetDynamicSectionString(unsigned int tag) override;
// Print information about the ELF file.
- void PrintInfo(std::ostream& os) const CM_OVERRIDE
+ void PrintInfo(std::ostream& os) const override
{
os << "ELF " << Types::GetName();
if (this->ByteOrder == ByteOrderMSB) {
@@ -286,9 +293,8 @@ public:
}
private:
- // ByteSwap(ELF_Dyn) assumes d_val and d_ptr are the same size
- typedef char dyn_size_assert
- [sizeof(ELF_Dyn().d_un.d_val) == sizeof(ELF_Dyn().d_un.d_ptr) ? 1 : -1];
+ static_assert(sizeof(ELF_Dyn().d_un.d_val) == sizeof(ELF_Dyn().d_un.d_ptr),
+ "ByteSwap(ELF_Dyn) assumes d_val and d_ptr are the same size");
void ByteSwap(ELF_Ehdr& elf_header)
{
@@ -350,7 +356,7 @@ private:
bool Read(ELF_Ehdr& x)
{
// Read the header from the file.
- if (!this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x))) {
+ if (!this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x))) {
return false;
}
@@ -380,26 +386,26 @@ private:
}
bool Read(ELF_Shdr& x)
{
- if (this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
+ if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) &&
this->NeedSwap) {
ByteSwap(x);
}
- return !this->Stream.fail();
+ return !this->Stream->fail();
}
bool Read(ELF_Dyn& x)
{
- if (this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) &&
+ if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) &&
this->NeedSwap) {
ByteSwap(x);
}
- return !this->Stream.fail();
+ return !this->Stream->fail();
}
bool LoadSectionHeader(ELF_Half i)
{
// Read the section header from the file.
- this->Stream.seekg(this->ELFHeader.e_shoff +
- this->ELFHeader.e_shentsize * i);
+ this->Stream->seekg(this->ELFHeader.e_shoff +
+ this->ELFHeader.e_shentsize * i);
if (!this->Read(this->SectionHeaders[i])) {
return false;
}
@@ -425,9 +431,9 @@ private:
template <class Types>
cmELFInternalImpl<Types>::cmELFInternalImpl(cmELF* external,
- CM_AUTO_PTR<cmsys::ifstream>& fin,
+ std::unique_ptr<std::istream> fin,
ByteOrderType order)
- : cmELFInternal(external, fin, order)
+ : cmELFInternal(external, std::move(fin), order)
{
// Read the main header.
if (!this->Read(this->ELFHeader)) {
@@ -509,7 +515,7 @@ bool cmELFInternalImpl<Types>::LoadDynamicSection()
// Read each entry.
for (int j = 0; j < n; ++j) {
// Seek to the beginning of the section entry.
- this->Stream.seekg(sec.sh_offset + sec.sh_entsize * j);
+ this->Stream->seekg(sec.sh_offset + sec.sh_entsize * j);
ELF_Dyn& dyn = this->DynamicSectionEntries[j];
// Try reading the entry.
@@ -547,12 +553,8 @@ cmELF::DynamicEntryList cmELFInternalImpl<Types>::GetDynamicEntries()
// Copy into public array
result.reserve(this->DynamicSectionEntries.size());
- for (typename std::vector<ELF_Dyn>::iterator di =
- this->DynamicSectionEntries.begin();
- di != this->DynamicSectionEntries.end(); ++di) {
- ELF_Dyn& dyn = *di;
- result.push_back(
- std::pair<unsigned long, unsigned long>(dyn.d_tag, dyn.d_un.d_val));
+ for (ELF_Dyn& dyn : this->DynamicSectionEntries) {
+ result.emplace_back(dyn.d_tag, dyn.d_un.d_val);
}
return result;
@@ -565,19 +567,18 @@ std::vector<char> cmELFInternalImpl<Types>::EncodeDynamicEntries(
std::vector<char> result;
result.reserve(sizeof(ELF_Dyn) * entries.size());
- for (cmELF::DynamicEntryList::const_iterator it = entries.begin();
- it != entries.end(); it++) {
+ for (auto const& entry : entries) {
// Store the entry in an ELF_Dyn, byteswap it, then serialize to chars
ELF_Dyn dyn;
- dyn.d_tag = static_cast<tagtype>(it->first);
- dyn.d_un.d_val = static_cast<tagtype>(it->second);
+ dyn.d_tag = static_cast<tagtype>(entry.first);
+ dyn.d_un.d_val = static_cast<tagtype>(entry.second);
if (this->NeedSwap) {
ByteSwap(dyn);
}
char* pdyn = reinterpret_cast<char*>(&dyn);
- result.insert(result.end(), pdyn, pdyn + sizeof(ELF_Dyn));
+ cmAppend(result, pdyn, pdyn + sizeof(ELF_Dyn));
}
return result;
@@ -588,13 +589,12 @@ cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString(
unsigned int tag)
{
// Short-circuit if already checked.
- std::map<unsigned int, StringEntry>::iterator dssi =
- this->DynamicSectionStrings.find(tag);
+ auto dssi = this->DynamicSectionStrings.find(tag);
if (dssi != this->DynamicSectionStrings.end()) {
if (dssi->second.Position > 0) {
return &dssi->second;
}
- return CM_NULLPTR;
+ return nullptr;
}
// Create an entry for this tag. Assume it is missing until found.
@@ -605,20 +605,19 @@ cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString(
// Try reading the dynamic section.
if (!this->LoadDynamicSection()) {
- return CM_NULLPTR;
+ return nullptr;
}
// Get the string table referenced by the DYNAMIC section.
ELF_Shdr const& sec = this->SectionHeaders[this->DynamicSectionIndex];
if (sec.sh_link >= this->SectionHeaders.size()) {
this->SetErrorMessage("Section DYNAMIC has invalid string table index.");
- return CM_NULLPTR;
+ return nullptr;
}
ELF_Shdr const& strtab = this->SectionHeaders[sec.sh_link];
// Look for the requested entry.
- for (typename std::vector<ELF_Dyn>::iterator di =
- this->DynamicSectionEntries.begin();
+ for (auto di = this->DynamicSectionEntries.begin();
di != this->DynamicSectionEntries.end(); ++di) {
ELF_Dyn& dyn = *di;
if (static_cast<tagtype>(dyn.d_tag) == static_cast<tagtype>(tag)) {
@@ -627,14 +626,14 @@ cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString(
if (dyn.d_un.d_val >= strtab.sh_size) {
this->SetErrorMessage("Section DYNAMIC references string beyond "
"the end of its string section.");
- return CM_NULLPTR;
+ return nullptr;
}
// Seek to the position reported by the entry.
unsigned long first = static_cast<unsigned long>(dyn.d_un.d_val);
unsigned long last = first;
unsigned long end = static_cast<unsigned long>(strtab.sh_size);
- this->Stream.seekg(strtab.sh_offset + first);
+ this->Stream->seekg(strtab.sh_offset + first);
// Read the string. It may be followed by more than one NULL
// terminator. Count the total size of the region allocated to
@@ -643,7 +642,7 @@ cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString(
// assumption.
bool terminated = false;
char c;
- while (last != end && this->Stream.get(c) && !(terminated && c)) {
+ while (last != end && this->Stream->get(c) && !(terminated && c)) {
++last;
if (c) {
se.Value += c;
@@ -653,10 +652,10 @@ cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString(
}
// Make sure the whole value was read.
- if (!this->Stream) {
+ if (!(*this->Stream)) {
this->SetErrorMessage("Dynamic section specifies unreadable RPATH.");
se.Value = "";
- return CM_NULLPTR;
+ return nullptr;
}
// The value has been read successfully. Report it.
@@ -667,7 +666,7 @@ cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString(
return &se;
}
}
- return CM_NULLPTR;
+ return nullptr;
}
//============================================================================
@@ -683,13 +682,12 @@ const long cmELF::TagMipsRldMapRel = 0;
#endif
cmELF::cmELF(const char* fname)
- : Internal(CM_NULLPTR)
{
// Try to open the file.
- CM_AUTO_PTR<cmsys::ifstream> fin(new cmsys::ifstream(fname));
+ auto fin = cm::make_unique<cmsys::ifstream>(fname);
// Quit now if the file could not be opened.
- if (!fin.get() || !*fin) {
+ if (!fin || !*fin) {
this->ErrorMessage = "Error opening input file.";
return;
}
@@ -729,12 +727,14 @@ cmELF::cmELF(const char* fname)
// parser implementation.
if (ident[EI_CLASS] == ELFCLASS32) {
// 32-bit ELF
- this->Internal = new cmELFInternalImpl<cmELFTypes32>(this, fin, order);
+ this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes32>>(
+ this, std::move(fin), order);
}
#ifndef _SCO_DS
else if (ident[EI_CLASS] == ELFCLASS64) {
// 64-bit ELF
- this->Internal = new cmELFInternalImpl<cmELFTypes64>(this, fin, order);
+ this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes64>>(
+ this, std::move(fin), order);
}
#endif
else {
@@ -743,10 +743,7 @@ cmELF::cmELF(const char* fname)
}
}
-cmELF::~cmELF()
-{
- delete this->Internal;
-}
+cmELF::~cmELF() = default;
bool cmELF::Valid() const
{
@@ -811,7 +808,7 @@ cmELF::StringEntry const* cmELF::GetSOName()
this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary) {
return this->Internal->GetSOName();
}
- return CM_NULLPTR;
+ return nullptr;
}
cmELF::StringEntry const* cmELF::GetRPath()
@@ -821,7 +818,7 @@ cmELF::StringEntry const* cmELF::GetRPath()
this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)) {
return this->Internal->GetRPath();
}
- return CM_NULLPTR;
+ return nullptr;
}
cmELF::StringEntry const* cmELF::GetRunPath()
@@ -831,7 +828,7 @@ cmELF::StringEntry const* cmELF::GetRunPath()
this->Internal->GetFileType() == cmELF::FileTypeSharedLibrary)) {
return this->Internal->GetRunPath();
}
- return CM_NULLPTR;
+ return nullptr;
}
void cmELF::PrintInfo(std::ostream& os) const
diff --git a/Source/cmELF.h b/Source/cmELF.h
index a6e407fe1..123bf9b1f 100644
--- a/Source/cmELF.h
+++ b/Source/cmELF.h
@@ -3,15 +3,16 @@
#ifndef cmELF_h
#define cmELF_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
+#include <memory>
#include <string>
#include <utility>
#include <vector>
#if !defined(CMAKE_USE_ELF_PARSER)
-#error "This file may be included only if CMAKE_USE_ELF_PARSER is enabled."
+# error "This file may be included only if CMAKE_USE_ELF_PARSER is enabled."
#endif
class cmELFInternal;
@@ -28,11 +29,14 @@ public:
/** Destruct. */
~cmELF();
+ cmELF(const cmELF&) = delete;
+ cmELF& operator=(const cmELF&) = delete;
+
/** Get the error message if any. */
std::string const& GetErrorMessage() const { return this->ErrorMessage; }
/** Boolean conversion. True if the ELF file is valid. */
- operator bool() const { return this->Valid(); }
+ explicit operator bool() const { return this->Valid(); }
/** Enumeration of ELF file types. */
enum FileType
@@ -64,7 +68,7 @@ public:
};
/** Represent entire dynamic section header */
- typedef std::vector<std::pair<long, unsigned long> > DynamicEntryList;
+ using DynamicEntryList = std::vector<std::pair<long, unsigned long>>;
/** Get the type of the file opened. */
FileType GetFileType() const;
@@ -105,7 +109,7 @@ public:
private:
friend class cmELFInternal;
bool Valid() const;
- cmELFInternal* Internal;
+ std::unique_ptr<cmELFInternal> Internal;
std::string ErrorMessage;
};
diff --git a/Source/cmEnableLanguageCommand.cxx b/Source/cmEnableLanguageCommand.cxx
index c57b7b15c..59522c040 100644
--- a/Source/cmEnableLanguageCommand.cxx
+++ b/Source/cmEnableLanguageCommand.cxx
@@ -2,29 +2,27 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmEnableLanguageCommand.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-class cmExecutionStatus;
-
-// cmEnableLanguageCommand
-bool cmEnableLanguageCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmEnableLanguageCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- bool optional = false;
- std::vector<std::string> languages;
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
- for (std::vector<std::string>::const_iterator it = args.begin();
- it != args.end(); ++it) {
- if ((*it) == "OPTIONAL") {
+
+ bool optional = false;
+ std::vector<std::string> languages;
+ for (std::string const& it : args) {
+ if (it == "OPTIONAL") {
optional = true;
} else {
- languages.push_back(*it);
+ languages.push_back(it);
}
}
- this->Makefile->EnableLanguage(languages, optional);
+ status.GetMakefile().EnableLanguage(languages, optional);
return true;
}
diff --git a/Source/cmEnableLanguageCommand.h b/Source/cmEnableLanguageCommand.h
index 33c1c22bf..1f8c4ce7e 100644
--- a/Source/cmEnableLanguageCommand.h
+++ b/Source/cmEnableLanguageCommand.h
@@ -3,37 +3,14 @@
#ifndef cmEnableLanguageCommand_h
#define cmEnableLanguageCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmEnableLanguageCommand
- * \brief Specify the name for this build project.
- *
- * cmEnableLanguageCommand is used to specify a name for this build project.
- * It is defined once per set of CMakeList.txt files (including
- * all subdirectories). Currently it just sets the name of the workspace
- * file for Microsoft Visual C++
- */
-class cmEnableLanguageCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmEnableLanguageCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmEnableLanguageCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmEnableTestingCommand.cxx b/Source/cmEnableTestingCommand.cxx
index 6a64450f5..89212c801 100644
--- a/Source/cmEnableTestingCommand.cxx
+++ b/Source/cmEnableTestingCommand.cxx
@@ -2,15 +2,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmEnableTestingCommand.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-class cmExecutionStatus;
-
-// we do this in the final pass so that we now the subdirs have all
-// been defined
-bool cmEnableTestingCommand::InitialPass(std::vector<std::string> const&,
- cmExecutionStatus&)
+bool cmEnableTestingCommand(std::vector<std::string> const&,
+ cmExecutionStatus& status)
{
- this->Makefile->AddDefinition("CMAKE_TESTING_ENABLED", "1");
+ status.GetMakefile().AddDefinition("CMAKE_TESTING_ENABLED", "1");
return true;
}
diff --git a/Source/cmEnableTestingCommand.h b/Source/cmEnableTestingCommand.h
index e24966221..e4593f2fe 100644
--- a/Source/cmEnableTestingCommand.h
+++ b/Source/cmEnableTestingCommand.h
@@ -3,16 +3,14 @@
#ifndef cmEnableTestingCommand_h
#define cmEnableTestingCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmEnableTestingCommand
+/**
* \brief Enable testing for this directory and below.
*
* Produce the output testfile. This produces a file in the build directory
@@ -25,20 +23,7 @@ class cmExecutionStatus;
* Note that CTest expects to find this file in the build directory root;
* therefore, this command should be in the source directory root too.
*/
-class cmEnableTestingCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmEnableTestingCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const&,
- cmExecutionStatus&) CM_OVERRIDE;
-};
+bool cmEnableTestingCommand(std::vector<std::string> const&,
+ cmExecutionStatus&);
#endif
diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx
index fcc3c45c6..51fb2191a 100644
--- a/Source/cmExecProgramCommand.cxx
+++ b/Source/cmExecProgramCommand.cxx
@@ -2,21 +2,30 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExecProgramCommand.h"
+#include <cstdio>
+
#include "cmsys/Process.h"
-#include <stdio.h>
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmProcessOutput.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
+using Encoding = cmProcessOutput::Encoding;
+
+namespace {
+bool RunCommand(std::string command, std::string& output, int& retVal,
+ const char* directory = nullptr, bool verbose = true,
+ Encoding encoding = cmProcessOutput::Auto);
+}
// cmExecProgramCommand
-bool cmExecProgramCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmExecProgramCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
std::string arguments;
@@ -26,40 +35,40 @@ bool cmExecProgramCommand::InitialPass(std::vector<std::string> const& args,
bool haveoutput_variable = false;
std::string return_variable;
bool havereturn_variable = false;
- for (size_t i = 0; i < args.size(); ++i) {
- if (args[i] == "OUTPUT_VARIABLE") {
+ for (std::string const& arg : args) {
+ if (arg == "OUTPUT_VARIABLE") {
count++;
doingargs = false;
havereturn_variable = false;
haveoutput_variable = true;
} else if (haveoutput_variable) {
if (!output_variable.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
- output_variable = args[i];
+ output_variable = arg;
haveoutput_variable = false;
count++;
- } else if (args[i] == "RETURN_VALUE") {
+ } else if (arg == "RETURN_VALUE") {
count++;
doingargs = false;
haveoutput_variable = false;
havereturn_variable = true;
} else if (havereturn_variable) {
if (!return_variable.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
- return_variable = args[i];
+ return_variable = arg;
havereturn_variable = false;
count++;
- } else if (args[i] == "ARGS") {
+ } else if (arg == "ARGS") {
count++;
havereturn_variable = false;
haveoutput_variable = false;
doingargs = true;
} else if (doingargs) {
- arguments += args[i];
+ arguments += arg;
arguments += " ";
count++;
}
@@ -67,9 +76,8 @@ bool cmExecProgramCommand::InitialPass(std::vector<std::string> const& args,
std::string command;
if (!arguments.empty()) {
- command = cmSystemTools::ConvertToRunCommandPath(args[0].c_str());
- command += " ";
- command += arguments;
+ command = cmStrCat(cmSystemTools::ConvertToRunCommandPath(args[0]), ' ',
+ arguments);
} else {
command = args[0];
}
@@ -81,12 +89,10 @@ 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());
- result = cmExecProgramCommand::RunCommand(command.c_str(), output, retVal,
- args[1].c_str(), verbose);
+ cmSystemTools::MakeDirectory(args[1]);
+ result = RunCommand(command, output, retVal, args[1].c_str(), verbose);
} else {
- result = cmExecProgramCommand::RunCommand(command.c_str(), output, retVal,
- CM_NULLPTR, verbose);
+ result = RunCommand(command, output, retVal, nullptr, verbose);
}
if (!result) {
retVal = -1;
@@ -103,21 +109,21 @@ bool cmExecProgramCommand::InitialPass(std::vector<std::string> const& args,
}
std::string coutput = std::string(output, first, last - first + 1);
- this->Makefile->AddDefinition(output_variable, coutput.c_str());
+ status.GetMakefile().AddDefinition(output_variable, coutput);
}
if (!return_variable.empty()) {
char buffer[100];
sprintf(buffer, "%d", retVal);
- this->Makefile->AddDefinition(return_variable, buffer);
+ status.GetMakefile().AddDefinition(return_variable, buffer);
}
return true;
}
-bool cmExecProgramCommand::RunCommand(const char* command, std::string& output,
- int& retVal, const char* dir,
- bool verbose, Encoding encoding)
+namespace {
+bool RunCommand(std::string command, std::string& output, int& retVal,
+ const char* dir, bool verbose, Encoding encoding)
{
if (cmSystemTools::GetRunCommandOutput()) {
verbose = false;
@@ -128,12 +134,11 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output,
// try to find the program, and if the program can not be
// found use system to run the command as it must be a built in
// shell command like echo or dir
- int count = 0;
- std::string shortCmd;
- if (command[0] == '\"') {
+ if (!command.empty() && command[0] == '\"') {
// count the number of quotes
- for (const char* s = command; *s != 0; ++s) {
- if (*s == '\"') {
+ int count = 0;
+ for (char c : command) {
+ if (c == '\"') {
count++;
if (count > 2) {
break;
@@ -147,20 +152,21 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output,
if (count > 2) {
cmsys::RegularExpression quoted("^\"([^\"]*)\"[ \t](.*)");
if (quoted.find(command)) {
+ std::string shortCmd;
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());
+ } else if (!cmSystemTools::GetShortPath(cmd, shortCmd)) {
+ cmSystemTools::Error("GetShortPath failed for " + cmd);
return false;
}
shortCmd += " ";
shortCmd += args;
- command = shortCmd.c_str();
+ command = shortCmd;
} else {
- cmSystemTools::Error("Could not parse command line with quotes ",
+ cmSystemTools::Error("Could not parse command line with quotes " +
command);
}
}
@@ -182,22 +188,19 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output,
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
}
cmsysProcess_SetOption(cp, cmsysProcess_Option_Verbatim, 1);
- const char* cmd[] = { command, 0 };
+ const char* cmd[] = { command.c_str(), nullptr };
cmsysProcess_SetCommand(cp, cmd);
#else
std::string commandInDir;
if (dir) {
- commandInDir = "cd \"";
- commandInDir += dir;
- commandInDir += "\" && ";
- commandInDir += command;
+ commandInDir = cmStrCat("cd \"", dir, "\" && ", command);
} else {
commandInDir = command;
}
-#ifndef __VMS
+# ifndef __VMS
commandInDir += " 2>&1";
-#endif
- command = commandInDir.c_str();
+# endif
+ command = commandInDir;
if (verbose) {
cmSystemTools::Stdout("running ");
cmSystemTools::Stdout(command);
@@ -205,7 +208,7 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output,
}
fflush(stdout);
fflush(stderr);
- const char* cmd[] = { "/bin/sh", "-c", command, CM_NULLPTR };
+ const char* cmd[] = { "/bin/sh", "-c", command.c_str(), nullptr };
cmsysProcess_SetCommand(cp, cmd);
#endif
@@ -217,11 +220,11 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output,
int p;
cmProcessOutput processOutput(encoding);
std::string strdata;
- while ((p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) {
+ while ((p = cmsysProcess_WaitForData(cp, &data, &length, nullptr))) {
if (p == cmsysProcess_Pipe_STDOUT || p == cmsysProcess_Pipe_STDERR) {
if (verbose) {
processOutput.DecodeText(data, length, strdata);
- cmSystemTools::Stdout(strdata.c_str(), strdata.size());
+ cmSystemTools::Stdout(strdata);
}
output.append(data, length);
}
@@ -230,12 +233,12 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output,
if (verbose) {
processOutput.DecodeText(std::string(), strdata);
if (!strdata.empty()) {
- cmSystemTools::Stdout(strdata.c_str(), strdata.size());
+ cmSystemTools::Stdout(strdata);
}
}
// All output has been read. Wait for the process to exit.
- cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+ cmsysProcess_WaitForExit(cp, nullptr);
processOutput.DecodeText(output, output);
// Check the result of running the process.
@@ -270,7 +273,7 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output,
}
msg += "\n";
if (verbose) {
- cmSystemTools::Stdout(msg.c_str());
+ cmSystemTools::Stdout(msg);
}
output += msg;
#else
@@ -284,3 +287,4 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output,
return true;
}
+}
diff --git a/Source/cmExecProgramCommand.h b/Source/cmExecProgramCommand.h
index 6463c4db5..7c751e154 100644
--- a/Source/cmExecProgramCommand.h
+++ b/Source/cmExecProgramCommand.h
@@ -3,44 +3,21 @@
#ifndef cmExecProgramCommand_h
#define cmExecProgramCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-#include "cmProcessOutput.h"
-
class cmExecutionStatus;
-/** \class cmExecProgramCommand
+/**
* \brief Command that adds a target to the build system.
*
* cmExecProgramCommand adds an extra target to the build system.
* This is useful when you would like to add special
* targets like "install,", "clean," and so on.
*/
-class cmExecProgramCommand : public cmCommand
-{
-public:
- typedef cmProcessOutput::Encoding Encoding;
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmExecProgramCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- static bool RunCommand(const char* command, std::string& output, int& retVal,
- const char* directory = CM_NULLPTR,
- bool verbose = true,
- Encoding encoding = cmProcessOutput::Auto);
-};
+bool cmExecProgramCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx
index 8c10dbe29..80e4bcd63 100644
--- a/Source/cmExecuteProcessCommand.cxx
+++ b/Source/cmExecuteProcessCommand.cxx
@@ -2,193 +2,148 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExecuteProcessCommand.h"
+#include <algorithm>
+#include <cctype> /* isspace */
+#include <cstdio>
+#include <iostream>
+#include <memory>
+#include <vector>
+
#include "cmsys/Process.h"
-#include <ctype.h> /* isspace */
-#include <sstream>
-#include <stdio.h>
+#include "cm_static_string_view.hxx"
+
+#include "cmAlgorithms.h"
+#include "cmArgumentParser.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmProcessOutput.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
-
-static bool cmExecuteProcessCommandIsWhitespace(char c)
+namespace {
+bool cmExecuteProcessCommandIsWhitespace(char c)
{
- return (isspace((int)c) || c == '\n' || c == '\r');
+ return (isspace(static_cast<int>(c)) || c == '\n' || c == '\r');
}
void cmExecuteProcessCommandFixText(std::vector<char>& output,
bool strip_trailing_whitespace);
void cmExecuteProcessCommandAppend(std::vector<char>& output, const char* data,
int length);
+}
// cmExecuteProcessCommand
-bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmExecuteProcessCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
- std::vector<std::vector<const char*> > cmds;
- std::string arguments;
- bool doing_command = false;
- size_t command_index = 0;
- bool output_quiet = false;
- bool error_quiet = false;
- bool output_strip_trailing_whitespace = false;
- bool error_strip_trailing_whitespace = false;
- std::string timeout_string;
- std::string input_file;
- std::string output_file;
- std::string error_file;
- std::string output_variable;
- std::string error_variable;
- std::string result_variable;
- std::string working_directory;
- cmProcessOutput::Encoding encoding = cmProcessOutput::None;
- for (size_t i = 0; i < args.size(); ++i) {
- if (args[i] == "COMMAND") {
- doing_command = true;
- command_index = cmds.size();
- cmds.push_back(std::vector<const char*>());
- } else if (args[i] == "OUTPUT_VARIABLE") {
- doing_command = false;
- if (++i < args.size()) {
- output_variable = args[i];
- } else {
- this->SetError(" called with no value for OUTPUT_VARIABLE.");
- return false;
- }
- } else if (args[i] == "ERROR_VARIABLE") {
- doing_command = false;
- if (++i < args.size()) {
- error_variable = args[i];
- } else {
- this->SetError(" called with no value for ERROR_VARIABLE.");
- return false;
- }
- } else if (args[i] == "RESULT_VARIABLE") {
- doing_command = false;
- if (++i < args.size()) {
- result_variable = args[i];
- } else {
- this->SetError(" called with no value for RESULT_VARIABLE.");
- return false;
- }
- } else if (args[i] == "WORKING_DIRECTORY") {
- doing_command = false;
- if (++i < args.size()) {
- working_directory = args[i];
- } else {
- this->SetError(" called with no value for WORKING_DIRECTORY.");
- return false;
- }
- } else if (args[i] == "INPUT_FILE") {
- doing_command = false;
- if (++i < args.size()) {
- input_file = args[i];
- } else {
- this->SetError(" called with no value for INPUT_FILE.");
- return false;
- }
- } else if (args[i] == "OUTPUT_FILE") {
- doing_command = false;
- if (++i < args.size()) {
- output_file = args[i];
- } else {
- this->SetError(" called with no value for OUTPUT_FILE.");
- return false;
- }
- } else if (args[i] == "ERROR_FILE") {
- doing_command = false;
- if (++i < args.size()) {
- error_file = args[i];
- } else {
- this->SetError(" called with no value for ERROR_FILE.");
- return false;
- }
- } else if (args[i] == "TIMEOUT") {
- doing_command = false;
- if (++i < args.size()) {
- timeout_string = args[i];
- } else {
- this->SetError(" called with no value for TIMEOUT.");
- return false;
- }
- } else if (args[i] == "OUTPUT_QUIET") {
- doing_command = false;
- output_quiet = true;
- } else if (args[i] == "ERROR_QUIET") {
- doing_command = false;
- error_quiet = true;
- } else if (args[i] == "OUTPUT_STRIP_TRAILING_WHITESPACE") {
- doing_command = false;
- output_strip_trailing_whitespace = true;
- } else if (args[i] == "ERROR_STRIP_TRAILING_WHITESPACE") {
- doing_command = false;
- error_strip_trailing_whitespace = true;
- } else if (args[i] == "ENCODING") {
- doing_command = false;
- if (++i < args.size()) {
- encoding = cmProcessOutput::FindEncoding(args[i]);
- } else {
- this->SetError(" called with no value for ENCODING.");
- return false;
- }
- } else if (doing_command) {
- cmds[command_index].push_back(args[i].c_str());
- } else {
- std::ostringstream e;
- e << " given unknown argument \"" << args[i] << "\".";
- this->SetError(e.str());
- return false;
- }
+
+ struct Arguments
+ {
+ std::vector<std::vector<std::string>> Commands;
+ std::string OutputVariable;
+ std::string ErrorVariable;
+ std::string ResultVariable;
+ std::string ResultsVariable;
+ std::string WorkingDirectory;
+ std::string InputFile;
+ std::string OutputFile;
+ std::string ErrorFile;
+ std::string Timeout;
+ std::string CommandEcho;
+ bool OutputQuiet = false;
+ bool ErrorQuiet = false;
+ bool OutputStripTrailingWhitespace = false;
+ bool ErrorStripTrailingWhitespace = false;
+ std::string Encoding;
+ };
+
+ static auto const parser =
+ cmArgumentParser<Arguments>{}
+ .Bind("COMMAND"_s, &Arguments::Commands)
+ .Bind("COMMAND_ECHO"_s, &Arguments::CommandEcho)
+ .Bind("OUTPUT_VARIABLE"_s, &Arguments::OutputVariable)
+ .Bind("ERROR_VARIABLE"_s, &Arguments::ErrorVariable)
+ .Bind("RESULT_VARIABLE"_s, &Arguments::ResultVariable)
+ .Bind("RESULTS_VARIABLE"_s, &Arguments::ResultsVariable)
+ .Bind("WORKING_DIRECTORY"_s, &Arguments::WorkingDirectory)
+ .Bind("INPUT_FILE"_s, &Arguments::InputFile)
+ .Bind("OUTPUT_FILE"_s, &Arguments::OutputFile)
+ .Bind("ERROR_FILE"_s, &Arguments::ErrorFile)
+ .Bind("TIMEOUT"_s, &Arguments::Timeout)
+ .Bind("OUTPUT_QUIET"_s, &Arguments::OutputQuiet)
+ .Bind("ERROR_QUIET"_s, &Arguments::ErrorQuiet)
+ .Bind("OUTPUT_STRIP_TRAILING_WHITESPACE"_s,
+ &Arguments::OutputStripTrailingWhitespace)
+ .Bind("ERROR_STRIP_TRAILING_WHITESPACE"_s,
+ &Arguments::ErrorStripTrailingWhitespace)
+ .Bind("ENCODING"_s, &Arguments::Encoding);
+
+ std::vector<std::string> unparsedArguments;
+ std::vector<std::string> keywordsMissingValue;
+ Arguments const arguments =
+ parser.Parse(args, &unparsedArguments, &keywordsMissingValue);
+
+ if (!keywordsMissingValue.empty()) {
+ status.SetError(" called with no value for " +
+ keywordsMissingValue.front() + ".");
+ return false;
+ }
+ if (!unparsedArguments.empty()) {
+ status.SetError(" given unknown argument \"" + unparsedArguments.front() +
+ "\".");
+ return false;
}
- if (!this->Makefile->CanIWriteThisFile(output_file.c_str())) {
- std::string e = "attempted to output into a file: " + output_file +
- " into a source directory.";
- this->SetError(e);
+ if (!status.GetMakefile().CanIWriteThisFile(arguments.OutputFile)) {
+ status.SetError("attempted to output into a file: " +
+ arguments.OutputFile + " into a source directory.");
cmSystemTools::SetFatalErrorOccured();
return false;
}
// Check for commands given.
- if (cmds.empty()) {
- this->SetError(" called with no COMMAND argument.");
+ if (arguments.Commands.empty()) {
+ status.SetError(" called with no COMMAND argument.");
return false;
}
- for (unsigned int i = 0; i < cmds.size(); ++i) {
- if (cmds[i].empty()) {
- this->SetError(" given COMMAND argument with no value.");
+ for (std::vector<std::string> const& cmd : arguments.Commands) {
+ if (cmd.empty()) {
+ status.SetError(" given COMMAND argument with no value.");
return false;
}
- // Add the null terminating pointer to the command argument list.
- cmds[i].push_back(CM_NULLPTR);
}
// Parse the timeout string.
double timeout = -1;
- if (!timeout_string.empty()) {
- if (sscanf(timeout_string.c_str(), "%lg", &timeout) != 1) {
- this->SetError(" called with TIMEOUT value that could not be parsed.");
+ if (!arguments.Timeout.empty()) {
+ if (sscanf(arguments.Timeout.c_str(), "%lg", &timeout) != 1) {
+ status.SetError(" called with TIMEOUT value that could not be parsed.");
return false;
}
}
-
// Create a process instance.
- cmsysProcess* cp = cmsysProcess_New();
+ std::unique_ptr<cmsysProcess, void (*)(cmsysProcess*)> cp_ptr(
+ cmsysProcess_New(), cmsysProcess_Delete);
+ cmsysProcess* cp = cp_ptr.get();
// Set the command sequence.
- for (unsigned int i = 0; i < cmds.size(); ++i) {
- cmsysProcess_AddCommand(cp, &*cmds[i].begin());
+ for (std::vector<std::string> const& cmd : arguments.Commands) {
+ std::vector<const char*> argv(cmd.size() + 1);
+ std::transform(cmd.begin(), cmd.end(), argv.begin(),
+ [](std::string const& s) { return s.c_str(); });
+ argv.back() = nullptr;
+ cmsysProcess_AddCommand(cp, argv.data());
}
// Set the process working directory.
- if (!working_directory.empty()) {
- cmsysProcess_SetWorkingDirectory(cp, working_directory.c_str());
+ if (!arguments.WorkingDirectory.empty()) {
+ cmsysProcess_SetWorkingDirectory(cp, arguments.WorkingDirectory.c_str());
}
// Always hide the process window.
@@ -196,22 +151,24 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
// Check the output variables.
bool merge_output = false;
- if (!input_file.empty()) {
- cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDIN, input_file.c_str());
+ if (!arguments.InputFile.empty()) {
+ cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDIN,
+ arguments.InputFile.c_str());
}
- if (!output_file.empty()) {
+ if (!arguments.OutputFile.empty()) {
cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDOUT,
- output_file.c_str());
+ arguments.OutputFile.c_str());
}
- if (!error_file.empty()) {
- if (error_file == output_file) {
+ if (!arguments.ErrorFile.empty()) {
+ if (arguments.ErrorFile == arguments.OutputFile) {
merge_output = true;
} else {
cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDERR,
- error_file.c_str());
+ arguments.ErrorFile.c_str());
}
}
- if (!output_variable.empty() && output_variable == error_variable) {
+ if (!arguments.OutputVariable.empty() &&
+ arguments.OutputVariable == arguments.ErrorVariable) {
merge_output = true;
}
if (merge_output) {
@@ -223,6 +180,51 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
cmsysProcess_SetTimeout(cp, timeout);
}
+ bool echo_stdout = false;
+ bool echo_stderr = false;
+ bool echo_output_from_variable = true;
+ std::string echo_output = status.GetMakefile().GetSafeDefinition(
+ "CMAKE_EXECUTE_PROCESS_COMMAND_ECHO");
+ if (!arguments.CommandEcho.empty()) {
+ echo_output_from_variable = false;
+ echo_output = arguments.CommandEcho;
+ }
+
+ if (!echo_output.empty()) {
+ if (echo_output == "STDERR") {
+ echo_stderr = true;
+ } else if (echo_output == "STDOUT") {
+ echo_stdout = true;
+ } else if (echo_output != "NONE") {
+ std::string error;
+ if (echo_output_from_variable) {
+ error = "CMAKE_EXECUTE_PROCESS_COMMAND_ECHO set to '";
+ } else {
+ error = " called with '";
+ }
+ error += echo_output;
+ error += "' expected STDERR|STDOUT|NONE";
+ if (!echo_output_from_variable) {
+ error += " for COMMAND_ECHO.";
+ }
+ status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, error);
+ return true;
+ }
+ }
+ if (echo_stdout || echo_stderr) {
+ std::string command;
+ for (auto& cmd : arguments.Commands) {
+ command += "'";
+ command += cmJoin(cmd, "' '");
+ command += "'";
+ command += "\n";
+ }
+ if (echo_stdout) {
+ std::cout << command;
+ } else if (echo_stderr) {
+ std::cerr << command;
+ }
+ }
// Start the process.
cmsysProcess_Execute(cp);
@@ -232,86 +234,131 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
int length;
char* data;
int p;
- cmProcessOutput processOutput(encoding);
+ cmProcessOutput processOutput(
+ cmProcessOutput::FindEncoding(arguments.Encoding));
std::string strdata;
- while ((p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) {
+ while ((p = cmsysProcess_WaitForData(cp, &data, &length, nullptr))) {
// Put the output in the right place.
- if (p == cmsysProcess_Pipe_STDOUT && !output_quiet) {
- if (output_variable.empty()) {
+ if (p == cmsysProcess_Pipe_STDOUT && !arguments.OutputQuiet) {
+ if (arguments.OutputVariable.empty()) {
processOutput.DecodeText(data, length, strdata, 1);
- cmSystemTools::Stdout(strdata.c_str(), strdata.size());
+ cmSystemTools::Stdout(strdata);
} else {
cmExecuteProcessCommandAppend(tempOutput, data, length);
}
- } else if (p == cmsysProcess_Pipe_STDERR && !error_quiet) {
- if (error_variable.empty()) {
+ } else if (p == cmsysProcess_Pipe_STDERR && !arguments.ErrorQuiet) {
+ if (arguments.ErrorVariable.empty()) {
processOutput.DecodeText(data, length, strdata, 2);
- cmSystemTools::Stderr(strdata.c_str(), strdata.size());
+ cmSystemTools::Stderr(strdata);
} else {
cmExecuteProcessCommandAppend(tempError, data, length);
}
}
}
- if (!output_quiet && output_variable.empty()) {
+ if (!arguments.OutputQuiet && arguments.OutputVariable.empty()) {
processOutput.DecodeText(std::string(), strdata, 1);
if (!strdata.empty()) {
- cmSystemTools::Stdout(strdata.c_str(), strdata.size());
+ cmSystemTools::Stdout(strdata);
}
}
- if (!error_quiet && error_variable.empty()) {
+ if (!arguments.ErrorQuiet && arguments.ErrorVariable.empty()) {
processOutput.DecodeText(std::string(), strdata, 2);
if (!strdata.empty()) {
- cmSystemTools::Stderr(strdata.c_str(), strdata.size());
+ cmSystemTools::Stderr(strdata);
}
}
// All output has been read. Wait for the process to exit.
- cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+ cmsysProcess_WaitForExit(cp, nullptr);
processOutput.DecodeText(tempOutput, tempOutput);
processOutput.DecodeText(tempError, tempError);
// Fix the text in the output strings.
- cmExecuteProcessCommandFixText(tempOutput, output_strip_trailing_whitespace);
- cmExecuteProcessCommandFixText(tempError, error_strip_trailing_whitespace);
+ cmExecuteProcessCommandFixText(tempOutput,
+ arguments.OutputStripTrailingWhitespace);
+ cmExecuteProcessCommandFixText(tempError,
+ arguments.ErrorStripTrailingWhitespace);
// Store the output obtained.
- if (!output_variable.empty() && !tempOutput.empty()) {
- this->Makefile->AddDefinition(output_variable, &*tempOutput.begin());
+ if (!arguments.OutputVariable.empty() && !tempOutput.empty()) {
+ status.GetMakefile().AddDefinition(arguments.OutputVariable,
+ tempOutput.data());
}
- if (!merge_output && !error_variable.empty() && !tempError.empty()) {
- this->Makefile->AddDefinition(error_variable, &*tempError.begin());
+ if (!merge_output && !arguments.ErrorVariable.empty() &&
+ !tempError.empty()) {
+ status.GetMakefile().AddDefinition(arguments.ErrorVariable,
+ tempError.data());
}
// Store the result of running the process.
- if (!result_variable.empty()) {
+ if (!arguments.ResultVariable.empty()) {
switch (cmsysProcess_GetState(cp)) {
case cmsysProcess_State_Exited: {
int v = cmsysProcess_GetExitValue(cp);
- char buf[100];
+ char buf[16];
sprintf(buf, "%d", v);
- this->Makefile->AddDefinition(result_variable, buf);
+ status.GetMakefile().AddDefinition(arguments.ResultVariable, buf);
} break;
case cmsysProcess_State_Exception:
- this->Makefile->AddDefinition(result_variable,
- cmsysProcess_GetExceptionString(cp));
+ status.GetMakefile().AddDefinition(
+ arguments.ResultVariable, cmsysProcess_GetExceptionString(cp));
break;
case cmsysProcess_State_Error:
- this->Makefile->AddDefinition(result_variable,
- cmsysProcess_GetErrorString(cp));
+ status.GetMakefile().AddDefinition(arguments.ResultVariable,
+ cmsysProcess_GetErrorString(cp));
break;
case cmsysProcess_State_Expired:
- this->Makefile->AddDefinition(result_variable,
- "Process terminated due to timeout");
+ status.GetMakefile().AddDefinition(
+ arguments.ResultVariable, "Process terminated due to timeout");
+ break;
+ }
+ }
+ // Store the result of running the processes.
+ if (!arguments.ResultsVariable.empty()) {
+ switch (cmsysProcess_GetState(cp)) {
+ case cmsysProcess_State_Exited: {
+ std::vector<std::string> res;
+ for (size_t i = 0; i < arguments.Commands.size(); ++i) {
+ switch (cmsysProcess_GetStateByIndex(cp, static_cast<int>(i))) {
+ case kwsysProcess_StateByIndex_Exited: {
+ int exitCode =
+ cmsysProcess_GetExitValueByIndex(cp, static_cast<int>(i));
+ char buf[16];
+ sprintf(buf, "%d", exitCode);
+ res.emplace_back(buf);
+ } break;
+ case kwsysProcess_StateByIndex_Exception:
+ res.emplace_back(cmsysProcess_GetExceptionStringByIndex(
+ cp, static_cast<int>(i)));
+ break;
+ case kwsysProcess_StateByIndex_Error:
+ default:
+ res.emplace_back("Error getting the child return code");
+ break;
+ }
+ }
+ status.GetMakefile().AddDefinition(arguments.ResultsVariable,
+ cmJoin(res, ";"));
+ } break;
+ case cmsysProcess_State_Exception:
+ status.GetMakefile().AddDefinition(
+ arguments.ResultsVariable, cmsysProcess_GetExceptionString(cp));
+ break;
+ case cmsysProcess_State_Error:
+ status.GetMakefile().AddDefinition(arguments.ResultsVariable,
+ cmsysProcess_GetErrorString(cp));
+ break;
+ case cmsysProcess_State_Expired:
+ status.GetMakefile().AddDefinition(
+ arguments.ResultsVariable, "Process terminated due to timeout");
break;
}
}
-
- // Delete the process instance.
- cmsysProcess_Delete(cp);
return true;
}
+namespace {
void cmExecuteProcessCommandFixText(std::vector<char>& output,
bool strip_trailing_whitespace)
{
@@ -355,5 +402,6 @@ void cmExecuteProcessCommandAppend(std::vector<char>& output, const char* data,
--length;
}
#endif
- output.insert(output.end(), data, data + length);
+ cmAppend(output, data, data + length);
+}
}
diff --git a/Source/cmExecuteProcessCommand.h b/Source/cmExecuteProcessCommand.h
index 08fde0adc..9c4b6007f 100644
--- a/Source/cmExecuteProcessCommand.h
+++ b/Source/cmExecuteProcessCommand.h
@@ -3,35 +3,20 @@
#ifndef cmExecuteProcessCommand_h
#define cmExecuteProcessCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmExecuteProcessCommand
+/**
* \brief Command that adds a target to the build system.
*
* cmExecuteProcessCommand is a CMake language interface to the KWSys
* Process Execution implementation.
*/
-class cmExecuteProcessCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmExecuteProcessCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmExecuteProcessCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmExecutionStatus.h b/Source/cmExecutionStatus.h
index ac5fe1d72..d2cc9b87a 100644
--- a/Source/cmExecutionStatus.h
+++ b/Source/cmExecutionStatus.h
@@ -3,6 +3,12 @@
#ifndef cmExecutionStatus_h
#define cmExecutionStatus_h
+#include <cmConfigure.h> // IWYU pragma: keep
+
+#include <string>
+
+class cmMakefile;
+
/** \class cmExecutionStatus
* \brief Superclass for all command status classes
*
@@ -11,21 +17,16 @@
class cmExecutionStatus
{
public:
- cmExecutionStatus()
- : ReturnInvoked(false)
- , BreakInvoked(false)
- , ContinueInvoked(false)
- , NestedError(false)
+ cmExecutionStatus(cmMakefile& makefile)
+ : Makefile(makefile)
+ , Error("unknown error.")
{
}
- void Clear()
- {
- this->ReturnInvoked = false;
- this->BreakInvoked = false;
- this->ContinueInvoked = false;
- this->NestedError = false;
- }
+ cmMakefile& GetMakefile() { return this->Makefile; }
+
+ void SetError(std::string const& e) { this->Error = e; }
+ std::string const& GetError() const { return this->Error; }
void SetReturnInvoked() { this->ReturnInvoked = true; }
bool GetReturnInvoked() const { return this->ReturnInvoked; }
@@ -40,10 +41,12 @@ public:
bool GetNestedError() const { return this->NestedError; }
private:
- bool ReturnInvoked;
- bool BreakInvoked;
- bool ContinueInvoked;
- bool NestedError;
+ cmMakefile& Makefile;
+ std::string Error;
+ bool ReturnInvoked = false;
+ bool BreakInvoked = false;
+ bool ContinueInvoked = false;
+ bool NestedError = false;
};
#endif
diff --git a/Source/cmExpandedCommandArgument.cxx b/Source/cmExpandedCommandArgument.cxx
index 0bea65fd0..43f648bc3 100644
--- a/Source/cmExpandedCommandArgument.cxx
+++ b/Source/cmExpandedCommandArgument.cxx
@@ -2,14 +2,13 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExpandedCommandArgument.h"
-cmExpandedCommandArgument::cmExpandedCommandArgument()
- : Quoted(false)
-{
-}
+#include <utility>
-cmExpandedCommandArgument::cmExpandedCommandArgument(std::string const& value,
+cmExpandedCommandArgument::cmExpandedCommandArgument() = default;
+
+cmExpandedCommandArgument::cmExpandedCommandArgument(std::string value,
bool quoted)
- : Value(value)
+ : Value(std::move(value))
, Quoted(quoted)
{
}
@@ -24,6 +23,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..69d35debe 100644
--- a/Source/cmExpandedCommandArgument.h
+++ b/Source/cmExpandedCommandArgument.h
@@ -18,12 +18,13 @@ class cmExpandedCommandArgument
{
public:
cmExpandedCommandArgument();
- cmExpandedCommandArgument(std::string const& value, bool quoted);
+ cmExpandedCommandArgument(std::string value, bool quoted);
std::string const& GetValue() const;
bool WasQuoted() const;
+ bool operator==(const char* value) const;
bool operator==(std::string const& value) const;
bool empty() const;
@@ -32,7 +33,7 @@ public:
private:
std::string Value;
- bool Quoted;
+ bool Quoted = false;
};
#endif
diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx
index b443fb0b4..561e83066 100644
--- a/Source/cmExportBuildAndroidMKGenerator.cxx
+++ b/Source/cmExportBuildAndroidMKGenerator.cxx
@@ -2,27 +2,24 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportBuildAndroidMKGenerator.h"
-#include <algorithm>
-#include <map>
#include <sstream>
#include <utility>
-#include "cmGeneratorExpression.h"
+#include "cmAlgorithms.h"
#include "cmGeneratorTarget.h"
#include "cmLinkItem.h"
-#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
-#include "cm_auto_ptr.hxx"
-#include "cmake.h"
cmExportBuildAndroidMKGenerator::cmExportBuildAndroidMKGenerator()
{
- this->LG = CM_NULLPTR;
- this->ExportSet = CM_NULLPTR;
+ this->LG = nullptr;
+ this->ExportSet = nullptr;
}
void cmExportBuildAndroidMKGenerator::GenerateImportHeaderCode(
@@ -41,16 +38,15 @@ void cmExportBuildAndroidMKGenerator::GenerateExpectedTargetsCode(
}
void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode(
- std::ostream& os, const cmGeneratorTarget* target)
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType /*targetType*/)
{
- std::string targetName = this->Namespace;
- targetName += target->GetExportName();
+ std::string targetName = cmStrCat(this->Namespace, target->GetExportName());
os << "include $(CLEAR_VARS)\n";
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";
}
@@ -94,57 +90,45 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
}
w << " set to OLD for target " << target->Target->GetName() << ". "
<< "The export will only work with CMP0022 set to NEW.";
- target->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ target->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
}
if (!properties.empty()) {
os << "LOCAL_CPP_FEATURES := rtti exceptions\n";
- for (ImportPropertyMap::const_iterator pi = properties.begin();
- pi != properties.end(); ++pi) {
- if (pi->first == "INTERFACE_COMPILE_OPTIONS") {
+ for (auto const& property : properties) {
+ if (property.first == "INTERFACE_COMPILE_OPTIONS") {
os << "LOCAL_CPP_FEATURES += ";
- os << (pi->second) << "\n";
- } else if (pi->first == "INTERFACE_LINK_LIBRARIES") {
- // 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(pi->second, libraries);
+ os << (property.second) << "\n";
+ } else if (property.first == "INTERFACE_LINK_LIBRARIES") {
std::string staticLibs;
std::string sharedLibs;
std::string ldlibs;
- for (std::vector<std::string>::iterator i = libraries.begin();
- i != libraries.end(); ++i) {
- cmGeneratorTarget* gt =
- target->GetLocalGenerator()->FindGeneratorTargetToUse(*i);
+ cmLinkInterfaceLibraries const* linkIFace =
+ target->GetLinkInterfaceLibraries(config, target, false);
+ for (cmLinkItem const& item : linkIFace->Libraries) {
+ cmGeneratorTarget const* gt = item.Target;
+ std::string const& lib = item.AsStr();
if (gt) {
if (gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
gt->GetType() == cmStateEnums::MODULE_LIBRARY) {
- sharedLibs += " " + *i;
+ sharedLibs += " " + lib;
} else {
- staticLibs += " " + *i;
+ staticLibs += " " + lib;
}
} else {
- // evaluate any generator expressions with the current
- // build type of the makefile
- cmGeneratorExpression ge;
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(*i);
- std::string evaluated =
- cge->Evaluate(target->GetLocalGenerator(), config);
bool relpath = false;
if (type == cmExportBuildAndroidMKGenerator::INSTALL) {
- relpath = i->substr(0, 3) == "../";
+ relpath = lib.substr(0, 3) == "../";
}
// 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;
}
}
}
@@ -157,20 +141,23 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
if (!ldlibs.empty()) {
os << "LOCAL_EXPORT_LDLIBS :=" << ldlibs << "\n";
}
- } else if (pi->first == "INTERFACE_INCLUDE_DIRECTORIES") {
- std::string includes = pi->second;
- std::vector<std::string> includeList;
- cmSystemTools::ExpandListArgument(includes, includeList);
+ } else if (property.first == "INTERFACE_INCLUDE_DIRECTORIES") {
+ std::string includes = property.second;
+ std::vector<std::string> includeList = cmExpandedList(includes);
os << "LOCAL_EXPORT_C_INCLUDES := ";
std::string end;
- for (std::vector<std::string>::iterator i = includeList.begin();
- i != includeList.end(); ++i) {
- os << end << *i;
+ for (std::string const& i : includeList) {
+ os << end << i;
end = "\\\n";
}
os << "\n";
+ } else if (property.first == "INTERFACE_LINK_OPTIONS") {
+ os << "LOCAL_EXPORT_LDFLAGS := ";
+ std::vector<std::string> linkFlagsList =
+ cmExpandedList(property.second);
+ os << cmJoin(linkFlagsList, " ") << "\n";
} else {
- os << "# " << pi->first << " " << (pi->second) << "\n";
+ os << "# " << property.first << " " << (property.second) << "\n";
}
}
}
@@ -178,8 +165,7 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
// Tell the NDK build system if prebuilt static libraries use C++.
if (target->GetType() == cmStateEnums::STATIC_LIBRARY) {
cmLinkImplementation const* li = target->GetLinkImplementation(config);
- if (std::find(li->Languages.begin(), li->Languages.end(), "CXX") !=
- li->Languages.end()) {
+ if (cmContains(li->Languages, "CXX")) {
os << "LOCAL_HAS_CPP := true\n";
}
}
diff --git a/Source/cmExportBuildAndroidMKGenerator.h b/Source/cmExportBuildAndroidMKGenerator.h
index d028ef48d..a9b6107f8 100644
--- a/Source/cmExportBuildAndroidMKGenerator.h
+++ b/Source/cmExportBuildAndroidMKGenerator.h
@@ -3,7 +3,7 @@
#ifndef cmExportBuildAndroidMKGenerator_h
#define cmExportBuildAndroidMKGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
@@ -11,6 +11,7 @@
#include "cmExportBuildFileGenerator.h"
#include "cmExportFileGenerator.h"
+#include "cmStateTypes.h"
class cmGeneratorTarget;
@@ -42,25 +43,25 @@ public:
protected:
// Implement virtual methods from the superclass.
- void GeneratePolicyHeaderCode(std::ostream&) CM_OVERRIDE {}
- void GeneratePolicyFooterCode(std::ostream&) CM_OVERRIDE {}
+ void GeneratePolicyHeaderCode(std::ostream&) override {}
+ void GeneratePolicyFooterCode(std::ostream&) override {}
void GenerateImportHeaderCode(std::ostream& os,
- const std::string& config = "") CM_OVERRIDE;
- void GenerateImportFooterCode(std::ostream& os) CM_OVERRIDE;
- void GenerateImportTargetCode(std::ostream& os,
- const cmGeneratorTarget* target) CM_OVERRIDE;
+ const std::string& config = "") override;
+ void GenerateImportFooterCode(std::ostream& os) override;
+ void GenerateImportTargetCode(
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType /*targetType*/) override;
void GenerateExpectedTargetsCode(
- std::ostream& os, const std::string& expectedTargets) CM_OVERRIDE;
- void GenerateImportPropertyCode(std::ostream& os, const std::string& config,
- cmGeneratorTarget const* target,
- ImportPropertyMap const& properties)
- CM_OVERRIDE;
+ std::ostream& os, const std::string& expectedTargets) override;
+ void GenerateImportPropertyCode(
+ std::ostream& os, const std::string& config,
+ cmGeneratorTarget const* target,
+ ImportPropertyMap const& properties) override;
void GenerateMissingTargetsCheckCode(
- std::ostream& os,
- const std::vector<std::string>& missingTargets) CM_OVERRIDE;
+ std::ostream& os, const std::vector<std::string>& missingTargets) override;
void GenerateInterfaceProperties(
cmGeneratorTarget const* target, std::ostream& os,
- const ImportPropertyMap& properties) CM_OVERRIDE;
+ const ImportPropertyMap& properties) override;
};
#endif
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index a1c424aca..7e9a98738 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -2,32 +2,32 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportBuildFileGenerator.h"
-#include "cmAlgorithms.h"
+#include <map>
+#include <memory>
+#include <set>
+#include <sstream>
+#include <utility>
+
#include "cmExportSet.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
-#include "cmSystemTools.h"
+#include "cmStringAlgorithms.h"
#include "cmTarget.h"
#include "cmTargetExport.h"
#include "cmake.h"
-#include <algorithm>
-#include <map>
-#include <set>
-#include <sstream>
-#include <utility>
-
class cmSourceFile;
cmExportBuildFileGenerator::cmExportBuildFileGenerator()
{
- this->LG = CM_NULLPTR;
- this->ExportSet = CM_NULLPTR;
+ this->LG = nullptr;
+ this->ExportSet = nullptr;
}
void cmExportBuildFileGenerator::Compute(cmLocalGenerator* lg)
@@ -44,10 +44,10 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
std::string expectedTargets;
std::string sep;
std::vector<std::string> targets;
+ bool generatedInterfaceRequired = false;
this->GetTargets(targets);
- for (std::vector<std::string>::const_iterator tei = targets.begin();
- tei != targets.end(); ++tei) {
- cmGeneratorTarget* te = this->LG->FindGeneratorTargetToUse(*tei);
+ for (std::string const& tei : targets) {
+ cmGeneratorTarget* te = this->LG->FindGeneratorTargetToUse(tei);
expectedTargets += sep + this->Namespace + te->GetExportName();
sep = " ";
if (this->ExportedTargets.insert(te).second) {
@@ -56,26 +56,25 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
std::ostringstream e;
e << "given target \"" << te->GetName() << "\" more than once.";
this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
- cmake::FATAL_ERROR, e.str(),
+ MessageType::FATAL_ERROR, e.str(),
this->LG->GetMakefile()->GetBacktrace());
return false;
}
- if (te->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
- this->GenerateRequiredCMakeVersion(os, "3.0.0");
- }
+ generatedInterfaceRequired |=
+ this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY;
}
+ if (generatedInterfaceRequired) {
+ this->GenerateRequiredCMakeVersion(os, "3.0.0");
+ }
this->GenerateExpectedTargetsCode(os, expectedTargets);
}
std::vector<std::string> missingTargets;
// Create all the imported targets.
- for (std::vector<cmGeneratorTarget*>::const_iterator tei =
- this->Exports.begin();
- tei != this->Exports.end(); ++tei) {
- cmGeneratorTarget* gte = *tei;
- this->GenerateImportTargetCode(os, gte);
+ for (cmGeneratorTarget* gte : this->Exports) {
+ this->GenerateImportTargetCode(os, gte, this->GetExportTargetType(gte));
gte->Target->AppendBuildInterfaceIncludes();
@@ -93,14 +92,35 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", gte,
cmGeneratorExpression::BuildInterface,
properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_PRECOMPILE_HEADERS", gte,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", gte,
cmGeneratorExpression::BuildInterface,
properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", gte,
cmGeneratorExpression::BuildInterface,
properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gte,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_LINK_DIRECTORIES", gte,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_LINK_DEPENDS", gte,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gte,
properties);
+
+ std::string errorMessage;
+ if (!this->PopulateExportProperties(gte, properties, errorMessage)) {
+ this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR, errorMessage,
+ this->LG->GetMakefile()->GetBacktrace());
+ return false;
+ }
+
const bool newCMP0022Behavior =
gte->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
gte->GetPolicyStatusCMP0022() != cmPolicies::OLD;
@@ -115,10 +135,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
}
// Generate import file content for each configuration.
- for (std::vector<std::string>::const_iterator ci =
- this->Configurations.begin();
- ci != this->Configurations.end(); ++ci) {
- this->GenerateImportConfig(os, *ci, missingTargets);
+ for (std::string const& c : this->Configurations) {
+ this->GenerateImportConfig(os, c, missingTargets);
}
this->GenerateMissingTargetsCheckCode(os, missingTargets);
@@ -130,19 +148,17 @@ void cmExportBuildFileGenerator::GenerateImportTargetsConfig(
std::ostream& os, const std::string& config, std::string const& suffix,
std::vector<std::string>& missingTargets)
{
- for (std::vector<cmGeneratorTarget*>::const_iterator tei =
- this->Exports.begin();
- tei != this->Exports.end(); ++tei) {
+ for (cmGeneratorTarget* target : this->Exports) {
// Collect import properties for this target.
- cmGeneratorTarget* target = *tei;
ImportPropertyMap properties;
- if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetExportTargetType(target) != cmStateEnums::INTERFACE_LIBRARY) {
this->SetImportLocationProperty(config, suffix, target, properties);
}
if (!properties.empty()) {
// Get the rest of the target details.
- if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetExportTargetType(target) !=
+ cmStateEnums::INTERFACE_LIBRARY) {
this->SetImportDetailProperties(config, suffix, target, properties,
missingTargets);
this->SetImportLinkInterface(config, suffix,
@@ -150,7 +166,7 @@ void cmExportBuildFileGenerator::GenerateImportTargetsConfig(
target, properties, missingTargets);
}
- // TOOD: PUBLIC_HEADER_LOCATION
+ // TODO: PUBLIC_HEADER_LOCATION
// This should wait until the build feature propagation stuff
// is done. Then this can be a propagated include directory.
// this->GenerateImportProperty(config, te->HeaderGenerator,
@@ -162,6 +178,21 @@ void cmExportBuildFileGenerator::GenerateImportTargetsConfig(
}
}
+cmStateEnums::TargetType cmExportBuildFileGenerator::GetExportTargetType(
+ cmGeneratorTarget const* target) const
+{
+ cmStateEnums::TargetType targetType = target->GetType();
+ // An object library exports as an interface library if we cannot
+ // tell clients where to find the objects. This is sufficient
+ // to support transitive usage requirements on other targets that
+ // use the object library.
+ if (targetType == cmStateEnums::OBJECT_LIBRARY &&
+ !this->LG->GetGlobalGenerator()->HasKnownObjectFileLocation(nullptr)) {
+ targetType = cmStateEnums::INTERFACE_LIBRARY;
+ }
+ return targetType;
+}
+
void cmExportBuildFileGenerator::SetExportSet(cmExportSet* exportSet)
{
this->ExportSet = exportSet;
@@ -175,8 +206,7 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
cmMakefile* mf = target->Makefile;
if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::string prop = "IMPORTED_OBJECTS";
- prop += suffix;
+ std::string prop = cmStrCat("IMPORTED_OBJECTS", suffix);
// Compute all the object files inside this target and setup
// IMPORTED_OBJECTS as a list of object files
@@ -184,10 +214,8 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
target->GetObjectSources(objectSources, config);
std::string const obj_dir = target->GetObjectDirectory(config);
std::vector<std::string> objects;
- for (std::vector<cmSourceFile const*>::const_iterator si =
- objectSources.begin();
- si != objectSources.end(); ++si) {
- const std::string& obj = target->GetObjectName(*si);
+ for (cmSourceFile const* sf : objectSources) {
+ const std::string& obj = target->GetObjectName(sf);
objects.push_back(obj_dir + obj);
}
@@ -196,8 +224,7 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
} else {
// Add the main target file.
{
- std::string prop = "IMPORTED_LOCATION";
- prop += suffix;
+ std::string prop = cmStrCat("IMPORTED_LOCATION", suffix);
std::string value;
if (target->IsAppBundleOnApple()) {
value =
@@ -210,13 +237,14 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
}
// Add the import library for windows DLLs.
- if (target->HasImportLibrary() &&
- mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
- std::string prop = "IMPORTED_IMPLIB";
- prop += suffix;
+ if (target->HasImportLibrary(config)) {
+ std::string prop = cmStrCat("IMPORTED_IMPLIB", suffix);
std::string value =
target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact);
- target->GetImplibGNUtoMS(value, value, "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
+ if (mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
+ target->GetImplibGNUtoMS(config, value, value,
+ "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
+ }
properties[prop] = value;
}
}
@@ -231,20 +259,20 @@ void cmExportBuildFileGenerator::HandleMissingTarget(
const std::string name = dependee->GetName();
cmGlobalGenerator* gg =
dependee->GetLocalGenerator()->GetGlobalGenerator();
- std::vector<std::string> namespaces = this->FindNamespaces(gg, name);
+ auto exportInfo = this->FindBuildExportInfo(gg, name);
+ std::vector<std::string> const& exportFiles = exportInfo.first;
- int targetOccurrences = (int)namespaces.size();
- if (targetOccurrences == 1) {
- std::string missingTarget = namespaces[0];
+ if (exportFiles.size() == 1) {
+ std::string missingTarget = exportInfo.second;
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
// known here. This is probably user-error.
- this->ComplainAboutMissingTarget(depender, dependee, targetOccurrences);
+ this->ComplainAboutMissingTarget(depender, dependee, exportFiles);
}
// Assume the target will be exported by another command.
// Append it with the export namespace.
@@ -256,59 +284,59 @@ void cmExportBuildFileGenerator::GetTargets(
std::vector<std::string>& targets) const
{
if (this->ExportSet) {
- for (std::vector<cmTargetExport*>::const_iterator tei =
- this->ExportSet->GetTargetExports()->begin();
- tei != this->ExportSet->GetTargetExports()->end(); ++tei) {
- targets.push_back((*tei)->TargetName);
+ for (std::unique_ptr<cmTargetExport> const& te :
+ this->ExportSet->GetTargetExports()) {
+ targets.push_back(te->TargetName);
}
return;
}
targets = this->Targets;
}
-std::vector<std::string> cmExportBuildFileGenerator::FindNamespaces(
- cmGlobalGenerator* gg, const std::string& name)
+std::pair<std::vector<std::string>, std::string>
+cmExportBuildFileGenerator::FindBuildExportInfo(cmGlobalGenerator* gg,
+ const std::string& name)
{
- std::vector<std::string> namespaces;
+ std::vector<std::string> exportFiles;
+ std::string ns;
std::map<std::string, cmExportBuildFileGenerator*>& exportSets =
gg->GetBuildExportSets();
- for (std::map<std::string, cmExportBuildFileGenerator*>::const_iterator
- expIt = exportSets.begin();
- expIt != exportSets.end(); ++expIt) {
- const cmExportBuildFileGenerator* exportSet = expIt->second;
+ for (auto const& exp : exportSets) {
+ const cmExportBuildFileGenerator* exportSet = exp.second;
std::vector<std::string> targets;
exportSet->GetTargets(targets);
- if (std::find(targets.begin(), targets.end(), name) != targets.end()) {
- namespaces.push_back(exportSet->GetNamespace());
+ if (cmContains(targets, name)) {
+ exportFiles.push_back(exp.first);
+ ns = exportSet->GetNamespace();
}
}
- return namespaces;
+ return { exportFiles, ns };
}
void cmExportBuildFileGenerator::ComplainAboutMissingTarget(
- cmGeneratorTarget* depender, cmGeneratorTarget* dependee, int occurrences)
+ cmGeneratorTarget* depender, cmGeneratorTarget* dependee,
+ std::vector<std::string> const& exportFiles)
{
- if (cmSystemTools::GetErrorOccuredFlag()) {
- return;
- }
-
std::ostringstream e;
e << "export called with target \"" << depender->GetName()
<< "\" which requires target \"" << dependee->GetName() << "\" ";
- if (occurrences == 0) {
- e << "that is not in the export set.\n";
+ if (exportFiles.empty()) {
+ e << "that is not in any export set.";
} else {
- e << "that is not in this export set, but " << occurrences
- << " times in others.\n";
+ e << "that is not in this export set, but in multiple other export sets: "
+ << cmJoin(exportFiles, ", ") << ".\n";
+ e << "An exported target cannot depend upon another target which is "
+ "exported multiple times. Consider consolidating the exports of the "
+ "\""
+ << dependee->GetName() << "\" target to a single export.";
}
- e << "If the required target is not easy to reference in this call, "
- << "consider using the APPEND option with multiple separate calls.";
this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
- cmake::FATAL_ERROR, e.str(), this->LG->GetMakefile()->GetBacktrace());
+ MessageType::FATAL_ERROR, e.str(),
+ this->LG->GetMakefile()->GetBacktrace());
}
std::string cmExportBuildFileGenerator::InstallNameDir(
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index 0556983ac..11fbd02d6 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -3,14 +3,17 @@
#ifndef cmExportBuildFileGenerator_h
#define cmExportBuildFileGenerator_h
-#include "cmConfigure.h"
-
-#include "cmExportFileGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
+#include <utility>
#include <vector>
+#include "cmAlgorithms.h"
+#include "cmExportFileGenerator.h"
+#include "cmStateTypes.h"
+
class cmExportSet;
class cmGeneratorTarget;
class cmGlobalGenerator;
@@ -38,7 +41,7 @@ public:
void GetTargets(std::vector<std::string>& targets) const;
void AppendTargets(std::vector<std::string> const& targets)
{
- this->Targets.insert(this->Targets.end(), targets.begin(), targets.end());
+ cmAppend(this->Targets, targets);
}
void SetExportSet(cmExportSet*);
@@ -49,18 +52,20 @@ public:
protected:
// Implement virtual methods from the superclass.
- bool GenerateMainFile(std::ostream& os) CM_OVERRIDE;
+ bool GenerateMainFile(std::ostream& os) override;
void GenerateImportTargetsConfig(
std::ostream& os, const std::string& config, std::string const& suffix,
- std::vector<std::string>& missingTargets) CM_OVERRIDE;
+ std::vector<std::string>& missingTargets) override;
+ cmStateEnums::TargetType GetExportTargetType(
+ cmGeneratorTarget const* target) const;
void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
cmGeneratorTarget* depender,
- cmGeneratorTarget* dependee) CM_OVERRIDE;
+ cmGeneratorTarget* dependee) override;
void ComplainAboutMissingTarget(cmGeneratorTarget* depender,
cmGeneratorTarget* dependee,
- int occurrences);
+ std::vector<std::string> const& namespaces);
/** Fill in properties indicating built file locations. */
void SetImportLocationProperty(const std::string& config,
@@ -69,10 +74,10 @@ protected:
ImportPropertyMap& properties);
std::string InstallNameDir(cmGeneratorTarget* target,
- const std::string& config) CM_OVERRIDE;
+ const std::string& config) override;
- std::vector<std::string> FindNamespaces(cmGlobalGenerator* gg,
- const std::string& name);
+ std::pair<std::vector<std::string>, std::string> FindBuildExportInfo(
+ cmGlobalGenerator* gg, const std::string& name);
std::vector<std::string> Targets;
cmExportSet* ExportSet;
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index 38cd511ea..2a6bf5df7 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -2,178 +2,174 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportCommand.h"
-#include "cmsys/RegularExpression.hxx"
#include <map>
#include <sstream>
+#include <utility>
+
+#include "cmsys/RegularExpression.hxx"
+#include "cm_static_string_view.hxx"
+
+#include "cmAlgorithms.h"
+#include "cmArgumentParser.h"
+#include "cmExecutionStatus.h"
#include "cmExportBuildAndroidMKGenerator.h"
#include "cmExportBuildFileGenerator.h"
-#include "cmExportSetMap.h"
+#include "cmExportSet.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
-#include "cmake.h"
-
-class cmExecutionStatus;
#if defined(__HAIKU__)
-#include <FindDirectory.h>
-#include <StorageDefs.h>
+# include <FindDirectory.h>
+# include <StorageDefs.h>
#endif
-cmExportCommand::cmExportCommand()
- : cmCommand()
- , ArgumentGroup()
- , Targets(&Helper, "TARGETS")
- , Append(&Helper, "APPEND", &ArgumentGroup)
- , ExportSetName(&Helper, "EXPORT", &ArgumentGroup)
- , Namespace(&Helper, "NAMESPACE", &ArgumentGroup)
- , Filename(&Helper, "FILE", &ArgumentGroup)
- , ExportOld(&Helper, "EXPORT_LINK_INTERFACE_LIBRARIES", &ArgumentGroup)
- , AndroidMKFile(&Helper, "ANDROID_MK")
-{
- this->ExportSet = CM_NULLPTR;
-}
+#if defined(_WIN32) && !defined(__CYGWIN__)
+# include <windows.h>
+#endif
+
+static bool HandlePackage(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
-// cmExportCommand
-bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+static void StorePackageRegistry(cmMakefile& mf, std::string const& package,
+ const char* content, const char* hash);
+
+bool cmExportCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("called with too few arguments");
+ status.SetError("called with too few arguments");
return false;
}
if (args[0] == "PACKAGE") {
- return this->HandlePackage(args);
+ return HandlePackage(args, status);
}
+
+ struct Arguments
+ {
+ std::string ExportSetName;
+ std::vector<std::string> Targets;
+ std::string Namespace;
+ std::string Filename;
+ std::string AndroidMKFile;
+ bool Append = false;
+ bool ExportOld = false;
+ };
+
+ auto parser = cmArgumentParser<Arguments>{}
+ .Bind("NAMESPACE"_s, &Arguments::Namespace)
+ .Bind("FILE"_s, &Arguments::Filename);
+
if (args[0] == "EXPORT") {
- this->ExportSetName.Follows(CM_NULLPTR);
- this->ArgumentGroup.Follows(&this->ExportSetName);
+ parser.Bind("EXPORT"_s, &Arguments::ExportSetName);
} else {
- this->Targets.Follows(CM_NULLPTR);
- this->ArgumentGroup.Follows(&this->Targets);
+ parser.Bind("TARGETS"_s, &Arguments::Targets);
+ parser.Bind("ANDROID_MK"_s, &Arguments::AndroidMKFile);
+ parser.Bind("APPEND"_s, &Arguments::Append);
+ parser.Bind("EXPORT_LINK_INTERFACE_LIBRARIES"_s, &Arguments::ExportOld);
}
std::vector<std::string> unknownArgs;
- this->Helper.Parse(&args, &unknownArgs);
+ std::vector<std::string> keywordsMissingValue;
+ Arguments const arguments =
+ parser.Parse(args, &unknownArgs, &keywordsMissingValue);
if (!unknownArgs.empty()) {
- this->SetError("Unknown arguments.");
+ status.SetError("Unknown argument: \"" + unknownArgs.front() + "\".");
return false;
}
std::string fname;
bool android = false;
- if (this->AndroidMKFile.WasFound()) {
- fname = this->AndroidMKFile.GetString();
+ if (!arguments.AndroidMKFile.empty()) {
+ fname = arguments.AndroidMKFile;
android = true;
}
- if (!this->Filename.WasFound() && fname.empty()) {
+ if (arguments.Filename.empty() && fname.empty()) {
if (args[0] != "EXPORT") {
- this->SetError("FILE <filename> option missing.");
+ status.SetError("FILE <filename> option missing.");
return false;
}
- fname = this->ExportSetName.GetString() + ".cmake";
+ fname = arguments.ExportSetName + ".cmake";
} else if (fname.empty()) {
// Make sure the file has a .cmake extension.
- if (cmSystemTools::GetFilenameLastExtension(this->Filename.GetCString()) !=
+ if (cmSystemTools::GetFilenameLastExtension(arguments.Filename) !=
".cmake") {
std::ostringstream e;
- e << "FILE option given filename \"" << this->Filename.GetString()
+ e << "FILE option given filename \"" << arguments.Filename
<< "\" which does not have an extension of \".cmake\".\n";
- this->SetError(e.str());
+ status.SetError(e.str());
return false;
}
- fname = this->Filename.GetString();
+ fname = arguments.Filename;
}
+ cmMakefile& mf = status.GetMakefile();
+
// Get the file to write.
- if (cmSystemTools::FileIsFullPath(fname.c_str())) {
- if (!this->Makefile->CanIWriteThisFile(fname.c_str())) {
+ if (cmSystemTools::FileIsFullPath(fname)) {
+ if (!mf.CanIWriteThisFile(fname)) {
std::ostringstream e;
e << "FILE option given filename \"" << fname
<< "\" which is in the source tree.\n";
- this->SetError(e.str());
+ status.SetError(e.str());
return false;
}
} else {
// Interpret relative paths with respect to the current build dir.
- std::string dir = this->Makefile->GetCurrentBinaryDirectory();
+ std::string const& dir = mf.GetCurrentBinaryDirectory();
fname = dir + "/" + fname;
}
std::vector<std::string> targets;
- cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
+ cmGlobalGenerator* gg = mf.GetGlobalGenerator();
+ cmExportSet* exportSet = nullptr;
if (args[0] == "EXPORT") {
- if (this->Append.IsEnabled()) {
- std::ostringstream e;
- e << "EXPORT signature does not recognise the APPEND option.";
- this->SetError(e.str());
- return false;
- }
-
- if (this->ExportOld.IsEnabled()) {
- std::ostringstream e;
- e << "EXPORT signature does not recognise the "
- "EXPORT_LINK_INTERFACE_LIBRARIES option.";
- this->SetError(e.str());
- return false;
- }
-
cmExportSetMap& setMap = gg->GetExportSets();
- std::string setName = this->ExportSetName.GetString();
- if (setMap.find(setName) == setMap.end()) {
+ auto const it = setMap.find(arguments.ExportSetName);
+ if (it == setMap.end()) {
std::ostringstream e;
- e << "Export set \"" << setName << "\" not found.";
- this->SetError(e.str());
+ e << "Export set \"" << arguments.ExportSetName << "\" not found.";
+ status.SetError(e.str());
return false;
}
- this->ExportSet = setMap[setName];
- } else if (this->Targets.WasFound()) {
- for (std::vector<std::string>::const_iterator currentTarget =
- this->Targets.GetVector().begin();
- currentTarget != this->Targets.GetVector().end(); ++currentTarget) {
- if (this->Makefile->IsAlias(*currentTarget)) {
+ exportSet = &it->second;
+ } else if (!arguments.Targets.empty() ||
+ cmContains(keywordsMissingValue, "TARGETS")) {
+ for (std::string const& currentTarget : arguments.Targets) {
+ if (mf.IsAlias(currentTarget)) {
std::ostringstream e;
- e << "given ALIAS target \"" << *currentTarget
+ e << "given ALIAS target \"" << currentTarget
<< "\" which may not be exported.";
- this->SetError(e.str());
+ status.SetError(e.str());
return false;
}
- if (cmTarget* target = gg->FindTarget(*currentTarget)) {
- if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::string reason;
- if (!this->Makefile->GetGlobalGenerator()
- ->HasKnownObjectFileLocation(&reason)) {
- std::ostringstream e;
- e << "given OBJECT library \"" << *currentTarget
- << "\" which may not be exported" << reason << ".";
- this->SetError(e.str());
- return false;
- }
- }
+ if (cmTarget* target = gg->FindTarget(currentTarget)) {
if (target->GetType() == cmStateEnums::UTILITY) {
- this->SetError("given custom target \"" + *currentTarget +
- "\" which may not be exported.");
+ status.SetError("given custom target \"" + currentTarget +
+ "\" which may not be exported.");
return false;
}
} else {
std::ostringstream e;
- e << "given target \"" << *currentTarget
+ e << "given target \"" << currentTarget
<< "\" which is not built by this project.";
- this->SetError(e.str());
+ status.SetError(e.str());
return false;
}
- targets.push_back(*currentTarget);
+ targets.push_back(currentTarget);
}
- if (this->Append.IsEnabled()) {
+ if (arguments.Append) {
if (cmExportBuildFileGenerator* ebfg =
gg->GetExportedTargetsFile(fname)) {
ebfg->AppendTargets(targets);
@@ -181,40 +177,38 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
}
}
} else {
- this->SetError("EXPORT or TARGETS specifier missing.");
+ status.SetError("EXPORT or TARGETS specifier missing.");
return false;
}
// Setup export file generation.
- cmExportBuildFileGenerator* ebfg = CM_NULLPTR;
+ cmExportBuildFileGenerator* ebfg = nullptr;
if (android) {
ebfg = new cmExportBuildAndroidMKGenerator;
} else {
ebfg = new cmExportBuildFileGenerator;
}
ebfg->SetExportFile(fname.c_str());
- ebfg->SetNamespace(this->Namespace.GetCString());
- ebfg->SetAppendMode(this->Append.IsEnabled());
- if (this->ExportSet) {
- ebfg->SetExportSet(this->ExportSet);
+ ebfg->SetNamespace(arguments.Namespace);
+ ebfg->SetAppendMode(arguments.Append);
+ if (exportSet != nullptr) {
+ ebfg->SetExportSet(exportSet);
} else {
ebfg->SetTargets(targets);
}
- this->Makefile->AddExportBuildFileGenerator(ebfg);
- ebfg->SetExportOld(this->ExportOld.IsEnabled());
+ mf.AddExportBuildFileGenerator(ebfg);
+ ebfg->SetExportOld(arguments.ExportOld);
// Compute the set of configurations exported.
std::vector<std::string> configurationTypes;
- this->Makefile->GetConfigurations(configurationTypes);
+ mf.GetConfigurations(configurationTypes);
if (configurationTypes.empty()) {
- configurationTypes.push_back("");
+ configurationTypes.emplace_back();
}
- for (std::vector<std::string>::const_iterator ci =
- configurationTypes.begin();
- ci != configurationTypes.end(); ++ci) {
- ebfg->AddConfiguration(*ci);
+ for (std::string const& ct : configurationTypes) {
+ ebfg->AddConfiguration(ct);
}
- if (this->ExportSet) {
+ if (exportSet != nullptr) {
gg->AddBuildExportExportSet(ebfg);
} else {
gg->AddBuildExportSet(ebfg);
@@ -223,7 +217,8 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
return true;
}
-bool cmExportCommand::HandlePackage(std::vector<std::string> const& args)
+static bool HandlePackage(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
// Parse PACKAGE mode arguments.
enum Doing
@@ -240,51 +235,61 @@ bool cmExportCommand::HandlePackage(std::vector<std::string> const& args)
} else {
std::ostringstream e;
e << "PACKAGE given unknown argument: " << args[i];
- this->SetError(e.str());
+ status.SetError(e.str());
return false;
}
}
// Verify the package name.
if (package.empty()) {
- this->SetError("PACKAGE must be given a package name.");
+ status.SetError("PACKAGE must be given a package name.");
return false;
}
const char* packageExpr = "^[A-Za-z0-9_.-]+$";
cmsys::RegularExpression packageRegex(packageExpr);
- if (!packageRegex.find(package.c_str())) {
+ if (!packageRegex.find(package)) {
std::ostringstream e;
e << "PACKAGE given invalid package name \"" << package << "\". "
<< "Package names must match \"" << packageExpr << "\".";
- this->SetError(e.str());
+ status.SetError(e.str());
return false;
}
- // If the CMAKE_EXPORT_NO_PACKAGE_REGISTRY variable is set the command
- // export(PACKAGE) does nothing.
- if (this->Makefile->IsOn("CMAKE_EXPORT_NO_PACKAGE_REGISTRY")) {
- return true;
+ cmMakefile& mf = status.GetMakefile();
+
+ // CMP0090 decides both the default and what variable changes it.
+ switch (mf.GetPolicyStatus(cmPolicies::CMP0090)) {
+ case cmPolicies::WARN:
+ case cmPolicies::OLD:
+ // Default is to export, but can be disabled.
+ if (mf.IsOn("CMAKE_EXPORT_NO_PACKAGE_REGISTRY")) {
+ return true;
+ }
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Default is to not export, but can be enabled.
+ if (!mf.IsOn("CMAKE_EXPORT_PACKAGE_REGISTRY")) {
+ return true;
+ }
+ break;
}
// We store the current build directory in the registry as a value
// named by a hash of its own content. This is deterministic and is
// unique with high probability.
- const char* outDir = this->Makefile->GetCurrentBinaryDirectory();
+ const std::string& outDir = mf.GetCurrentBinaryDirectory();
std::string hash = cmSystemTools::ComputeStringMD5(outDir);
-#if defined(_WIN32) && !defined(__CYGWIN__)
- this->StorePackageRegistryWin(package, outDir, hash.c_str());
-#else
- this->StorePackageRegistryDir(package, outDir, hash.c_str());
-#endif
+ StorePackageRegistry(mf, package, outDir.c_str(), hash.c_str());
return true;
}
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <windows.h>
-void cmExportCommand::ReportRegistryError(std::string const& msg,
- std::string const& key, long err)
+static void ReportRegistryError(cmMakefile& mf, std::string const& msg,
+ std::string const& key, long err)
{
std::ostringstream e;
e << msg << "\n"
@@ -296,21 +301,19 @@ void cmExportCommand::ReportRegistryError(std::string const& msg,
e << "Windows reported:\n"
<< " " << cmsys::Encoding::ToNarrow(winmsg);
}
- this->Makefile->IssueMessage(cmake::WARNING, e.str());
+ mf.IssueMessage(MessageType::WARNING, e.str());
}
-void cmExportCommand::StorePackageRegistryWin(std::string const& package,
- const char* content,
- const char* hash)
+static void StorePackageRegistry(cmMakefile& mf, std::string const& package,
+ const char* content, const char* hash)
{
- std::string key = "Software\\Kitware\\CMake\\Packages\\";
- key += package;
+ std::string key = cmStrCat("Software\\Kitware\\CMake\\Packages\\", package);
HKEY hKey;
LONG err =
RegCreateKeyExW(HKEY_CURRENT_USER, cmsys::Encoding::ToWide(key).c_str(), 0,
0, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, 0, &hKey, 0);
if (err != ERROR_SUCCESS) {
- this->ReportRegistryError("Cannot create/open registry key", key, err);
+ ReportRegistryError(mf, "Cannot create/open registry key", key, err);
return;
}
@@ -323,25 +326,22 @@ void cmExportCommand::StorePackageRegistryWin(std::string const& package,
if (err != ERROR_SUCCESS) {
std::ostringstream msg;
msg << "Cannot set registry value \"" << hash << "\" under key";
- this->ReportRegistryError(msg.str(), key, err);
+ ReportRegistryError(mf, msg.str(), key, err);
return;
}
}
#else
-void cmExportCommand::StorePackageRegistryDir(std::string const& package,
- const char* content,
- const char* hash)
+static void StorePackageRegistry(cmMakefile& mf, std::string const& package,
+ const char* content, const char* hash)
{
-#if defined(__HAIKU__)
+# if defined(__HAIKU__)
char dir[B_PATH_NAME_LENGTH];
if (find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, dir, sizeof(dir)) !=
B_OK) {
return;
}
- std::string fname = dir;
- fname += "/cmake/packages/";
- fname += package;
-#else
+ std::string fname = cmStrCat(dir, "/cmake/packages/", package);
+# else
std::string fname;
if (!cmSystemTools::GetEnv("HOME", fname)) {
return;
@@ -349,12 +349,12 @@ void cmExportCommand::StorePackageRegistryDir(std::string const& package,
cmSystemTools::ConvertToUnixSlashes(fname);
fname += "/.cmake/packages/";
fname += package;
-#endif
- cmSystemTools::MakeDirectory(fname.c_str());
+# endif
+ cmSystemTools::MakeDirectory(fname);
fname += "/";
fname += hash;
- if (!cmSystemTools::FileExists(fname.c_str())) {
- cmGeneratedFileStream entry(fname.c_str(), true);
+ if (!cmSystemTools::FileExists(fname)) {
+ cmGeneratedFileStream entry(fname, true);
if (entry) {
entry << content << "\n";
} else {
@@ -364,7 +364,7 @@ void cmExportCommand::StorePackageRegistryDir(std::string const& package,
<< " " << fname << "\n"
<< cmSystemTools::GetLastSystemError() << "\n";
/* clang-format on */
- this->Makefile->IssueMessage(cmake::WARNING, e.str());
+ mf.IssueMessage(MessageType::WARNING, e.str());
}
}
}
diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h
index c47bc42b9..965562820 100644
--- a/Source/cmExportCommand.h
+++ b/Source/cmExportCommand.h
@@ -3,62 +3,14 @@
#ifndef cmExportCommand_h
#define cmExportCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-#include "cmCommandArgumentsHelper.h"
-
class cmExecutionStatus;
-class cmExportSet;
-
-/** \class cmExportLibraryDependenciesCommand
- * \brief Add a test to the lists of tests to run.
- *
- * cmExportLibraryDependenciesCommand adds a test to the list of tests to run
- *
- */
-class cmExportCommand : public cmCommand
-{
-public:
- cmExportCommand();
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmExportCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- cmCommandArgumentsHelper Helper;
- cmCommandArgumentGroup ArgumentGroup;
- cmCAStringVector Targets;
- cmCAEnabler Append;
- cmCAString ExportSetName;
- cmCAString Namespace;
- cmCAString Filename;
- cmCAEnabler ExportOld;
- cmCAString AndroidMKFile;
-
- cmExportSet* ExportSet;
-
- friend class cmExportBuildFileGenerator;
- std::string ErrorMessage;
- bool HandlePackage(std::vector<std::string> const& args);
- void StorePackageRegistryWin(std::string const& package, const char* content,
- const char* hash);
- void StorePackageRegistryDir(std::string const& package, const char* content,
- const char* hash);
- void ReportRegistryError(std::string const& msg, std::string const& key,
- long err);
-};
+bool cmExportCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 972f4b9d1..aeef602bf 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -2,27 +2,30 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportFileGenerator.h"
-#include "cmAlgorithms.h"
+#include <cassert>
+#include <cstring>
+#include <sstream>
+#include <utility>
+
+#include <cm/memory>
+
+#include "cmsys/FStream.hxx"
+
#include "cmComputeLinkInformation.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmLinkItem.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
+#include "cmPropertyMap.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetExport.h"
-#include "cmake.h"
-
-#include "cm_auto_ptr.hxx"
-#include "cmsys/FStream.hxx"
-#include <assert.h>
-#include <sstream>
-#include <string.h>
-#include <utility>
static std::string cmExportFileGeneratorEscape(std::string const& str)
{
@@ -65,24 +68,24 @@ const char* cmExportFileGenerator::GetMainExportFileName() const
bool cmExportFileGenerator::GenerateImportFile()
{
// Open the output file to generate it.
- CM_AUTO_PTR<cmsys::ofstream> foutPtr;
+ std::unique_ptr<cmsys::ofstream> foutPtr;
if (this->AppendMode) {
// Open for append.
- CM_AUTO_PTR<cmsys::ofstream> ap(
- new cmsys::ofstream(this->MainImportFile.c_str(), std::ios::app));
- foutPtr = ap;
+ auto openmodeApp = std::ios::app;
+ foutPtr = cm::make_unique<cmsys::ofstream>(this->MainImportFile.c_str(),
+ openmodeApp);
} else {
// Generate atomically and with copy-if-different.
- CM_AUTO_PTR<cmGeneratedFileStream> ap(
- new cmGeneratedFileStream(this->MainImportFile.c_str(), true));
+ std::unique_ptr<cmGeneratedFileStream> ap(
+ new cmGeneratedFileStream(this->MainImportFile, true));
ap->SetCopyIfDifferent(true);
- foutPtr = ap;
+ foutPtr = std::move(ap);
}
- if (!foutPtr.get() || !*foutPtr) {
+ if (!foutPtr || !*foutPtr) {
std::string se = cmSystemTools::GetLastSystemError();
std::ostringstream e;
e << "cannot write to file \"" << this->MainImportFile << "\": " << se;
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
return false;
}
std::ostream& os = *foutPtr;
@@ -137,7 +140,7 @@ void cmExportFileGenerator::PopulateInterfaceProperty(
if (input) {
if (!*input) {
// Set to empty
- properties[outputName] = "";
+ properties[outputName].clear();
return;
}
@@ -184,7 +187,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));
@@ -194,31 +197,35 @@ static bool checkInterfaceDirs(const std::string& prepro,
cmGeneratorTarget* target,
const std::string& prop)
{
- const char* installDir =
+ std::string const& 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;
- for (std::vector<std::string>::iterator li = parts.begin();
- li != parts.end(); ++li) {
- size_t genexPos = cmGeneratorExpression::Find(*li);
+ for (std::string const& li : parts) {
+ size_t genexPos = cmGeneratorExpression::Find(li);
if (genexPos == 0) {
continue;
}
- cmake::MessageType messageType = cmake::FATAL_ERROR;
+ if (cmHasLiteralPrefix(li, "${_IMPORT_PREFIX}")) {
+ continue;
+ }
+ MessageType messageType = MessageType::FATAL_ERROR;
std::ostringstream e;
if (genexPos != std::string::npos) {
if (prop == "INTERFACE_INCLUDE_DIRECTORIES") {
switch (target->GetPolicyStatusCMP0041()) {
case cmPolicies::WARN:
- messageType = cmake::WARNING;
+ messageType = MessageType::WARNING;
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0041) << "\n";
break;
case cmPolicies::OLD:
@@ -233,20 +240,17 @@ static bool checkInterfaceDirs(const std::string& prepro,
hadFatalError = true;
}
}
- if (cmHasLiteralPrefix(li->c_str(), "${_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"
- " \"" << *li << "\"";
+ " \"" << li << "\"";
/* 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
@@ -261,18 +265,20 @@ static bool checkInterfaceDirs(const std::string& prepro,
case cmPolicies::WARN: {
std::ostringstream s;
s << cmPolicies::GetPolicyWarning(cmPolicies::CMP0052) << "\n";
- s << "Directory:\n \"" << *li
+ s << "Directory:\n \"" << li
<< "\"\nin "
"INTERFACE_INCLUDE_DIRECTORIES of target \""
- << target->GetName() << "\" is a subdirectory of the install "
- "directory:\n \""
- << installDir << "\"\nhowever it is also "
- "a subdirectory of the "
+ << target->GetName()
+ << "\" is a subdirectory of the install "
+ "directory:\n \""
+ << installDir
+ << "\"\nhowever it is also "
+ "a subdirectory of the "
<< (inBinary ? "build" : "source") << " tree:\n \""
<< (inBinary ? topBinaryDir : topSourceDir) << "\""
<< std::endl;
- target->GetLocalGenerator()->IssueMessage(cmake::AUTHOR_WARNING,
- s.str());
+ target->GetLocalGenerator()->IssueMessage(
+ MessageType::AUTHOR_WARNING, s.str());
CM_FALLTHROUGH;
}
case cmPolicies::OLD:
@@ -293,7 +299,7 @@ static bool checkInterfaceDirs(const std::string& prepro,
/* clang-format off */
e << "Target \"" << target->GetName() << "\" " << prop <<
" property contains path:\n"
- " \"" << *li << "\"\nwhich is prefixed in the build directory.";
+ " \"" << li << "\"\nwhich is prefixed in the build directory.";
/* clang-format on */
target->GetLocalGenerator()->IssueMessage(messageType, e.str());
}
@@ -302,7 +308,7 @@ static bool checkInterfaceDirs(const std::string& prepro,
e << "Target \"" << target->GetName() << "\" " << prop
<< " property contains path:\n"
" \""
- << *li << "\"\nwhich is prefixed in the source directory.";
+ << li << "\"\nwhich is prefixed in the source directory.";
target->GetLocalGenerator()->IssueMessage(messageType, e.str());
}
}
@@ -314,17 +320,16 @@ static void prefixItems(std::string& exportDirs)
{
std::vector<std::string> entries;
cmGeneratorExpression::Split(exportDirs, entries);
- exportDirs = "";
+ exportDirs.clear();
const char* sep = "";
- for (std::vector<std::string>::const_iterator ei = entries.begin();
- ei != entries.end(); ++ei) {
+ for (std::string const& e : entries) {
exportDirs += sep;
sep = ";";
- if (!cmSystemTools::FileIsFullPath(ei->c_str()) &&
- ei->find("${_IMPORT_PREFIX}") == std::string::npos) {
+ if (!cmSystemTools::FileIsFullPath(e) &&
+ e.find("${_IMPORT_PREFIX}") == std::string::npos) {
exportDirs += "${_IMPORT_PREFIX}/";
}
- exportDirs += *ei;
+ exportDirs += e;
}
}
@@ -343,7 +348,7 @@ void cmExportFileGenerator::PopulateSourcesInterface(
}
if (!*input) {
- properties[propName] = "";
+ properties[propName].clear();
return;
}
@@ -374,9 +379,9 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
std::string dirs = cmGeneratorExpression::Preprocess(
tei->InterfaceIncludeDirectories, preprocessRule, true);
this->ReplaceInstallPrefix(dirs);
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
std::string exportDirs =
- cge->Evaluate(target->GetLocalGenerator(), "", false, target);
+ cge->Evaluate(target->GetLocalGenerator(), "", target);
if (cge->GetHadContextSensitiveCondition()) {
cmLocalGenerator* lg = target->GetLocalGenerator();
@@ -387,7 +392,7 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
"depend on the configuration, policy values or the link interface "
"are "
"not supported. Consider using target_include_directories instead.";
- lg->IssueMessage(cmake::FATAL_ERROR, e.str());
+ lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
@@ -396,7 +401,7 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
}
if ((input && !*input) && exportDirs.empty()) {
// Set to empty
- properties[propName] = "";
+ properties[propName].clear();
return;
}
@@ -417,6 +422,68 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
}
}
+void cmExportFileGenerator::PopulateLinkDependsInterface(
+ cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
+{
+ cmGeneratorTarget* gt = tei->Target;
+ assert(preprocessRule == cmGeneratorExpression::InstallInterface);
+
+ const char* propName = "INTERFACE_LINK_DEPENDS";
+ const char* input = gt->GetProperty(propName);
+
+ if (!input) {
+ return;
+ }
+
+ if (!*input) {
+ properties[propName].clear();
+ return;
+ }
+
+ std::string prepro =
+ cmGeneratorExpression::Preprocess(input, preprocessRule, true);
+ if (!prepro.empty()) {
+ this->ResolveTargetsInGeneratorExpressions(prepro, gt, missingTargets);
+
+ if (!checkInterfaceDirs(prepro, gt, propName)) {
+ return;
+ }
+ properties[propName] = prepro;
+ }
+}
+
+void cmExportFileGenerator::PopulateLinkDirectoriesInterface(
+ cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
+{
+ cmGeneratorTarget* gt = tei->Target;
+ assert(preprocessRule == cmGeneratorExpression::InstallInterface);
+
+ const char* propName = "INTERFACE_LINK_DIRECTORIES";
+ const char* input = gt->GetProperty(propName);
+
+ if (!input) {
+ return;
+ }
+
+ if (!*input) {
+ properties[propName].clear();
+ return;
+ }
+
+ std::string prepro =
+ cmGeneratorExpression::Preprocess(input, preprocessRule, true);
+ if (!prepro.empty()) {
+ this->ResolveTargetsInGeneratorExpressions(prepro, gt, missingTargets);
+
+ if (!checkInterfaceDirs(prepro, gt, propName)) {
+ return;
+ }
+ properties[propName] = prepro;
+ }
+}
+
void cmExportFileGenerator::PopulateInterfaceProperty(
const std::string& propName, cmGeneratorTarget* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
@@ -433,8 +500,7 @@ void getPropertyContents(cmGeneratorTarget const* tgt, const std::string& prop,
if (!p) {
return;
}
- std::vector<std::string> content;
- cmSystemTools::ExpandListArgument(p, content);
+ std::vector<std::string> content = cmExpandedList(p);
ifaceProperties.insert(content.begin(), content.end());
}
@@ -455,24 +521,23 @@ void getCompatibleInterfaceProperties(cmGeneratorTarget* target,
e << "Exporting the target \"" << target->GetName()
<< "\" is not "
"allowed since its linker language cannot be determined";
- lg->IssueMessage(cmake::FATAL_ERROR, e.str());
+ lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
const cmComputeLinkInformation::ItemVector& deps = info->GetItems();
- for (cmComputeLinkInformation::ItemVector::const_iterator li = deps.begin();
- li != deps.end(); ++li) {
- if (!li->Target) {
+ for (auto const& dep : deps) {
+ if (!dep.Target) {
continue;
}
- getPropertyContents(li->Target, "COMPATIBLE_INTERFACE_BOOL",
+ getPropertyContents(dep.Target, "COMPATIBLE_INTERFACE_BOOL",
ifaceProperties);
- getPropertyContents(li->Target, "COMPATIBLE_INTERFACE_STRING",
+ getPropertyContents(dep.Target, "COMPATIBLE_INTERFACE_STRING",
ifaceProperties);
- getPropertyContents(li->Target, "COMPATIBLE_INTERFACE_NUMBER_MIN",
+ getPropertyContents(dep.Target, "COMPATIBLE_INTERFACE_NUMBER_MIN",
ifaceProperties);
- getPropertyContents(li->Target, "COMPATIBLE_INTERFACE_NUMBER_MAX",
+ getPropertyContents(dep.Target, "COMPATIBLE_INTERFACE_NUMBER_MAX",
ifaceProperties);
}
}
@@ -504,15 +569,13 @@ void cmExportFileGenerator::PopulateCompatibleInterfaceProperties(
std::vector<std::string> configNames;
gtarget->Target->GetMakefile()->GetConfigurations(configNames);
- for (std::vector<std::string>::const_iterator ci = configNames.begin();
- ci != configNames.end(); ++ci) {
- getCompatibleInterfaceProperties(gtarget, ifaceProperties, *ci);
+ for (std::string const& cn : configNames) {
+ getCompatibleInterfaceProperties(gtarget, ifaceProperties, cn);
}
}
- for (std::set<std::string>::const_iterator it = ifaceProperties.begin();
- it != ifaceProperties.end(); ++it) {
- this->PopulateInterfaceProperty("INTERFACE_" + *it, gtarget, properties);
+ for (std::string const& ip : ifaceProperties) {
+ this->PopulateInterfaceProperty("INTERFACE_" + ip, gtarget, properties);
}
}
@@ -521,13 +584,12 @@ void cmExportFileGenerator::GenerateInterfaceProperties(
const ImportPropertyMap& properties)
{
if (!properties.empty()) {
- std::string targetName = this->Namespace;
- targetName += target->GetExportName();
+ std::string targetName =
+ cmStrCat(this->Namespace, target->GetExportName());
os << "set_target_properties(" << targetName << " PROPERTIES\n";
- for (ImportPropertyMap::const_iterator pi = properties.begin();
- pi != properties.end(); ++pi) {
- os << " " << pi->first << " " << cmExportFileGeneratorEscape(pi->second)
- << "\n";
+ for (auto const& property : properties) {
+ os << " " << property.first << " "
+ << cmExportFileGeneratorEscape(property.second) << "\n";
}
os << ")\n\n";
}
@@ -537,14 +599,17 @@ bool cmExportFileGenerator::AddTargetNamespace(
std::string& input, cmGeneratorTarget* target,
std::vector<std::string>& missingTargets)
{
- cmLocalGenerator* lg = target->GetLocalGenerator();
+ cmGeneratorTarget::TargetOrString resolved =
+ target->ResolveTargetReference(input);
- cmGeneratorTarget* tgt = lg->FindGeneratorTargetToUse(input);
+ cmGeneratorTarget* tgt = resolved.Target;
if (!tgt) {
+ input = resolved.String;
return false;
}
if (tgt->IsImported()) {
+ input = tgt->GetName();
return true;
}
if (this->ExportedTargets.find(tgt) != this->ExportedTargets.end()) {
@@ -554,6 +619,8 @@ bool cmExportFileGenerator::AddTargetNamespace(
this->HandleMissingTarget(namespacedTarget, missingTargets, target, tgt);
if (!namespacedTarget.empty()) {
input = namespacedTarget;
+ } else {
+ input = tgt->GetName();
}
}
return true;
@@ -571,15 +638,14 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
cmGeneratorExpression::Split(input, parts);
std::string sep;
- input = "";
- for (std::vector<std::string>::iterator li = parts.begin();
- li != parts.end(); ++li) {
- if (cmGeneratorExpression::Find(*li) == std::string::npos) {
- this->AddTargetNamespace(*li, target, missingTargets);
+ input.clear();
+ for (std::string& li : parts) {
+ if (cmGeneratorExpression::Find(li) == std::string::npos) {
+ this->AddTargetNamespace(li, target, missingTargets);
} else {
- this->ResolveTargetsInGeneratorExpression(*li, target, missingTargets);
+ this->ResolveTargetsInGeneratorExpression(li, target, missingTargets);
}
- input += sep + *li;
+ input += sep + li;
sep = ";";
}
}
@@ -599,7 +665,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
{
@@ -662,7 +728,8 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
this->ReplaceInstallPrefix(input);
if (!errorString.empty()) {
- target->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, errorString);
+ target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
+ errorString);
}
}
@@ -685,9 +752,9 @@ void cmExportFileGenerator::SetImportLinkInterface(
if (iface->ImplementationIsInterface) {
// Policy CMP0022 must not be NEW.
- this->SetImportLinkProperty(suffix, target,
- "IMPORTED_LINK_INTERFACE_LIBRARIES",
- iface->Libraries, properties, missingTargets);
+ this->SetImportLinkProperty(
+ suffix, target, "IMPORTED_LINK_INTERFACE_LIBRARIES", iface->Libraries,
+ properties, missingTargets, ImportLinkPropertyTargetNames::Yes);
return;
}
@@ -715,12 +782,12 @@ void cmExportFileGenerator::SetImportLinkInterface(
"but also has old-style LINK_INTERFACE_LIBRARIES properties "
"populated, but it was exported without the "
"EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties";
- lg->IssueMessage(cmake::FATAL_ERROR, e.str());
+ lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (!*propContent) {
- properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = "";
+ properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix].clear();
return;
}
@@ -765,29 +832,56 @@ void cmExportFileGenerator::SetImportDetailProperties(
// Add the transitive link dependencies for this configuration.
if (cmLinkInterface const* iface =
target->GetLinkInterface(config, target)) {
- this->SetImportLinkProperty(suffix, target,
- "IMPORTED_LINK_INTERFACE_LANGUAGES",
- iface->Languages, properties, missingTargets);
+ this->SetImportLinkProperty(
+ suffix, target, "IMPORTED_LINK_INTERFACE_LANGUAGES", iface->Languages,
+ properties, missingTargets, ImportLinkPropertyTargetNames::No);
std::vector<std::string> dummy;
- this->SetImportLinkProperty(suffix, target,
- "IMPORTED_LINK_DEPENDENT_LIBRARIES",
- iface->SharedDeps, properties, dummy);
+ this->SetImportLinkProperty(
+ suffix, target, "IMPORTED_LINK_DEPENDENT_LIBRARIES", iface->SharedDeps,
+ properties, dummy, ImportLinkPropertyTargetNames::Yes);
if (iface->Multiplicity > 0) {
- std::string prop = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
- prop += suffix;
- std::ostringstream m;
- m << iface->Multiplicity;
- properties[prop] = m.str();
+ std::string prop =
+ cmStrCat("IMPORTED_LINK_INTERFACE_MULTIPLICITY", suffix);
+ properties[prop] = std::to_string(iface->Multiplicity);
}
}
+
+ // Add information if this target is a managed target
+ if (target->GetManagedType(config) !=
+ cmGeneratorTarget::ManagedType::Native) {
+ std::string prop = cmStrCat("IMPORTED_COMMON_LANGUAGE_RUNTIME", suffix);
+ std::string propval;
+ if (auto* p = target->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
+ propval = p;
+ } else if (target->IsCSharpOnly()) {
+ // C# projects do not have the /clr flag, so we set the property
+ // here to mark the target as (only) managed (i.e. no .lib file
+ // to link to). Otherwise the COMMON_LANGUAGE_RUNTIME target
+ // property would have to be set manually for C# targets to make
+ // exporting/importing work.
+ propval = "CSharp";
+ }
+ properties[prop] = propval;
+ }
+}
+
+static std::string const& asString(std::string const& l)
+{
+ return l;
+}
+
+static std::string const& asString(cmLinkItem const& l)
+{
+ return l.AsStr();
}
template <typename T>
void cmExportFileGenerator::SetImportLinkProperty(
std::string const& suffix, cmGeneratorTarget* target,
const std::string& propName, std::vector<T> const& entries,
- ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets,
+ ImportLinkPropertyTargetNames targetNames)
{
// Skip the property if there are no entries.
if (entries.empty()) {
@@ -797,20 +891,22 @@ void cmExportFileGenerator::SetImportLinkProperty(
// Construct the property value.
std::string link_entries;
const char* sep = "";
- for (typename std::vector<T>::const_iterator li = entries.begin();
- li != entries.end(); ++li) {
+ for (T const& l : entries) {
// Separate this from the previous entry.
link_entries += sep;
sep = ";";
- std::string temp = *li;
- this->AddTargetNamespace(temp, target, missingTargets);
- link_entries += temp;
+ if (targetNames == ImportLinkPropertyTargetNames::Yes) {
+ std::string temp = asString(l);
+ this->AddTargetNamespace(temp, target, missingTargets);
+ link_entries += temp;
+ } else {
+ link_entries += asString(l);
+ }
}
// Store the property.
- std::string prop = propName;
- prop += suffix;
+ std::string prop = cmStrCat(propName, suffix);
properties[prop] = link_entries;
}
@@ -908,8 +1004,10 @@ void cmExportFileGenerator::GenerateExpectedTargetsCode(
"\n\n";
/* clang-format on */
}
+
void cmExportFileGenerator::GenerateImportTargetCode(
- std::ostream& os, const cmGeneratorTarget* target)
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType targetType)
{
// Construct the imported target name.
std::string targetName = this->Namespace;
@@ -918,7 +1016,7 @@ void cmExportFileGenerator::GenerateImportTargetCode(
// Create the imported target.
os << "# Create imported target " << targetName << "\n";
- switch (target->GetType()) {
+ switch (targetType) {
case cmStateEnums::EXECUTABLE:
os << "add_executable(" << targetName << " IMPORTED)\n";
break;
@@ -988,10 +1086,9 @@ void cmExportFileGenerator::GenerateImportPropertyCode(
}
os << ")\n";
os << "set_target_properties(" << targetName << " PROPERTIES\n";
- for (ImportPropertyMap::const_iterator pi = properties.begin();
- pi != properties.end(); ++pi) {
- os << " " << pi->first << " " << cmExportFileGeneratorEscape(pi->second)
- << "\n";
+ for (auto const& property : properties) {
+ os << " " << property.first << " "
+ << cmExportFileGeneratorEscape(property.second) << "\n";
}
os << " )\n"
<< "\n";
@@ -1015,9 +1112,9 @@ void cmExportFileGenerator::GenerateMissingTargetsCheckCode(
"foreach(_target ";
/* clang-format on */
std::set<std::string> emitted;
- for (unsigned int i = 0; i < missingTargets.size(); ++i) {
- if (emitted.insert(missingTargets[i]).second) {
- os << "\"" << missingTargets[i] << "\" ";
+ for (std::string const& missingTarget : missingTargets) {
+ if (emitted.insert(missingTarget).second) {
+ os << "\"" << missingTarget << "\" ";
}
}
/* clang-format off */
@@ -1086,17 +1183,15 @@ void cmExportFileGenerator::GenerateImportedFileChecksCode(
const std::set<std::string>& importedLocations)
{
// Construct the imported target name.
- std::string targetName = this->Namespace;
- targetName += target->GetExportName();
+ std::string targetName = cmStrCat(this->Namespace, target->GetExportName());
os << "list(APPEND _IMPORT_CHECK_TARGETS " << targetName
<< " )\n"
"list(APPEND _IMPORT_CHECK_FILES_FOR_"
<< targetName << " ";
- for (std::set<std::string>::const_iterator li = importedLocations.begin();
- li != importedLocations.end(); ++li) {
- ImportPropertyMap::const_iterator pi = properties.find(*li);
+ for (std::string const& li : importedLocations) {
+ auto pi = properties.find(li);
if (pi != properties.end()) {
os << cmExportFileGeneratorEscape(pi->second) << " ";
}
@@ -1104,3 +1199,43 @@ void cmExportFileGenerator::GenerateImportedFileChecksCode(
os << ")\n\n";
}
+
+bool cmExportFileGenerator::PopulateExportProperties(
+ cmGeneratorTarget* gte, ImportPropertyMap& properties,
+ std::string& errorMessage)
+{
+ auto& targetProperties = gte->Target->GetProperties();
+ if (const char* exportProperties =
+ targetProperties.GetPropertyValue("EXPORT_PROPERTIES")) {
+ for (auto& prop : cmExpandedList(exportProperties)) {
+ /* Black list reserved properties */
+ if (cmHasLiteralPrefix(prop, "IMPORTED_") ||
+ cmHasLiteralPrefix(prop, "INTERFACE_")) {
+ std::ostringstream e;
+ e << "Target \"" << gte->Target->GetName() << "\" contains property \""
+ << prop << "\" in EXPORT_PROPERTIES but IMPORTED_* and INTERFACE_* "
+ << "properties are reserved.";
+ errorMessage = e.str();
+ return false;
+ }
+ auto propertyValue = targetProperties.GetPropertyValue(prop);
+ if (propertyValue == nullptr) {
+ // Asked to export a property that isn't defined on the target. Do not
+ // consider this an error, there's just nothing to export.
+ continue;
+ }
+ std::string evaluatedValue = cmGeneratorExpression::Preprocess(
+ propertyValue, cmGeneratorExpression::StripAllGeneratorExpressions);
+ if (evaluatedValue != propertyValue) {
+ std::ostringstream e;
+ e << "Target \"" << gte->Target->GetName() << "\" contains property \""
+ << prop << "\" in EXPORT_PROPERTIES but this property contains a "
+ << "generator expression. This is not allowed.";
+ errorMessage = e.str();
+ return false;
+ }
+ properties[prop] = propertyValue;
+ }
+ }
+ return true;
+}
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 985c8f6bc..0d69779f9 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -5,16 +5,17 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmGeneratorExpression.h"
-#include "cmVersion.h"
-#include "cmVersionConfig.h"
-
#include <iosfwd>
#include <map>
#include <set>
#include <string>
#include <vector>
+#include "cmGeneratorExpression.h"
+#include "cmStateTypes.h"
+#include "cmVersion.h"
+#include "cmVersionConfig.h"
+
class cmGeneratorTarget;
#define STRINGIFY_HELPER(X) #X
@@ -41,7 +42,7 @@ class cmExportFileGenerator
{
public:
cmExportFileGenerator();
- virtual ~cmExportFileGenerator() {}
+ virtual ~cmExportFileGenerator() = default;
/** Set the full path to the export file to generate. */
void SetExportFile(const char* mainFile);
@@ -61,7 +62,7 @@ public:
bool GenerateImportFile();
protected:
- typedef std::map<std::string, std::string> ImportPropertyMap;
+ using ImportPropertyMap = std::map<std::string, std::string>;
// Generate per-configuration target information to the given output
// stream.
@@ -76,7 +77,8 @@ protected:
virtual void GenerateImportFooterCode(std::ostream& os);
void GenerateImportVersionCode(std::ostream& os);
virtual void GenerateImportTargetCode(std::ostream& os,
- cmGeneratorTarget const* target);
+ cmGeneratorTarget const* target,
+ cmStateEnums::TargetType targetType);
virtual void GenerateImportPropertyCode(std::ostream& os,
const std::string& config,
cmGeneratorTarget const* target,
@@ -100,13 +102,19 @@ protected:
ImportPropertyMap& properties,
std::vector<std::string>& missingTargets);
+ enum class ImportLinkPropertyTargetNames
+ {
+ Yes,
+ No,
+ };
template <typename T>
void SetImportLinkProperty(std::string const& suffix,
cmGeneratorTarget* target,
const std::string& propName,
std::vector<T> const& entries,
ImportPropertyMap& properties,
- std::vector<std::string>& missingTargets);
+ std::vector<std::string>& missingTargets,
+ ImportLinkPropertyTargetNames targetNames);
/** Each subclass knows how to generate its kind of export file. */
virtual bool GenerateMainFile(std::ostream& os) = 0;
@@ -145,6 +153,14 @@ protected:
cmTargetExport* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
+ void PopulateLinkDirectoriesInterface(
+ cmTargetExport* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
+ void PopulateLinkDependsInterface(
+ cmTargetExport* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
void SetImportLinkInterface(
const std::string& config, std::string const& suffix,
@@ -166,6 +182,10 @@ protected:
virtual void GenerateRequiredCMakeVersion(std::ostream& os,
const char* versionString);
+ bool PopulateExportProperties(cmGeneratorTarget* gte,
+ ImportPropertyMap& properties,
+ std::string& errorMessage);
+
// The namespace in which the exports are placed in the generated file.
std::string Namespace;
diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx
index 9a1c647d3..2d732c1db 100644
--- a/Source/cmExportInstallAndroidMKGenerator.cxx
+++ b/Source/cmExportInstallAndroidMKGenerator.cxx
@@ -2,8 +2,9 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportInstallAndroidMKGenerator.h"
+#include <cstddef>
+#include <memory>
#include <ostream>
-#include <stddef.h>
#include "cmExportBuildAndroidMKGenerator.h"
#include "cmExportSet.h"
@@ -11,6 +12,7 @@
#include "cmInstallExportGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetExport.h"
@@ -34,11 +36,9 @@ void cmExportInstallAndroidMKGenerator::GenerateImportHeaderCode(
}
os << "_IMPORT_PREFIX := "
<< "$(LOCAL_PATH)" << path << "\n\n";
- for (std::vector<cmTargetExport*>::const_iterator tei =
- this->IEGen->GetExportSet()->GetTargetExports()->begin();
- tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei) {
+ for (std::unique_ptr<cmTargetExport> const& te :
+ this->IEGen->GetExportSet()->GetTargetExports()) {
// Collect import properties for this target.
- cmTargetExport const* te = *tei;
if (te->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
@@ -58,10 +58,10 @@ void cmExportInstallAndroidMKGenerator::GenerateImportFooterCode(std::ostream&)
}
void cmExportInstallAndroidMKGenerator::GenerateImportTargetCode(
- std::ostream& os, const cmGeneratorTarget* target)
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType /*targetType*/)
{
- std::string targetName = this->Namespace;
- targetName += target->GetExportName();
+ std::string targetName = cmStrCat(this->Namespace, target->GetExportName());
os << "include $(CLEAR_VARS)\n";
os << "LOCAL_MODULE := ";
os << targetName << "\n";
diff --git a/Source/cmExportInstallAndroidMKGenerator.h b/Source/cmExportInstallAndroidMKGenerator.h
index ebef78365..8883ffafb 100644
--- a/Source/cmExportInstallAndroidMKGenerator.h
+++ b/Source/cmExportInstallAndroidMKGenerator.h
@@ -3,7 +3,7 @@
#ifndef cmExportInstallAndroidMKGenerator_h
#define cmExportInstallAndroidMKGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <set>
@@ -12,6 +12,7 @@
#include "cmExportFileGenerator.h"
#include "cmExportInstallFileGenerator.h"
+#include "cmStateTypes.h"
class cmGeneratorTarget;
class cmInstallExportGenerator;
@@ -22,7 +23,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.
@@ -36,37 +37,37 @@ public:
protected:
// Implement virtual methods from the superclass.
- void GeneratePolicyHeaderCode(std::ostream&) CM_OVERRIDE {}
- void GeneratePolicyFooterCode(std::ostream&) CM_OVERRIDE {}
+ void GeneratePolicyHeaderCode(std::ostream&) override {}
+ void GeneratePolicyFooterCode(std::ostream&) override {}
void GenerateImportHeaderCode(std::ostream& os,
- const std::string& config = "") CM_OVERRIDE;
- void GenerateImportFooterCode(std::ostream& os) CM_OVERRIDE;
- void GenerateImportTargetCode(std::ostream& os,
- const cmGeneratorTarget* target) CM_OVERRIDE;
+ const std::string& config = "") override;
+ void GenerateImportFooterCode(std::ostream& os) override;
+ void GenerateImportTargetCode(
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType /*targetType*/) override;
void GenerateExpectedTargetsCode(
- std::ostream& os, const std::string& expectedTargets) CM_OVERRIDE;
- void GenerateImportPropertyCode(std::ostream& os, const std::string& config,
- cmGeneratorTarget const* target,
- ImportPropertyMap const& properties)
- CM_OVERRIDE;
+ std::ostream& os, const std::string& expectedTargets) override;
+ void GenerateImportPropertyCode(
+ std::ostream& os, const std::string& config,
+ cmGeneratorTarget const* target,
+ ImportPropertyMap const& properties) override;
void GenerateMissingTargetsCheckCode(
- std::ostream& os,
- const std::vector<std::string>& missingTargets) CM_OVERRIDE;
+ std::ostream& os, const std::vector<std::string>& missingTargets) override;
void GenerateInterfaceProperties(
cmGeneratorTarget const* target, std::ostream& os,
- const ImportPropertyMap& properties) CM_OVERRIDE;
- void GenerateImportPrefix(std::ostream& os) CM_OVERRIDE;
- void LoadConfigFiles(std::ostream&) CM_OVERRIDE;
+ const ImportPropertyMap& properties) override;
+ void GenerateImportPrefix(std::ostream& os) override;
+ void LoadConfigFiles(std::ostream&) override;
void GenerateRequiredCMakeVersion(std::ostream& os,
- const char* versionString) CM_OVERRIDE;
- void CleanupTemporaryVariables(std::ostream&) CM_OVERRIDE;
- void GenerateImportedFileCheckLoop(std::ostream& os) CM_OVERRIDE;
+ const char* versionString) override;
+ void CleanupTemporaryVariables(std::ostream&) override;
+ void GenerateImportedFileCheckLoop(std::ostream& os) override;
void GenerateImportedFileChecksCode(
std::ostream& os, cmGeneratorTarget* target,
ImportPropertyMap const& properties,
- const std::set<std::string>& importedLocations) CM_OVERRIDE;
+ const std::set<std::string>& importedLocations) override;
bool GenerateImportFileConfig(const std::string& config,
- std::vector<std::string>&) CM_OVERRIDE;
+ std::vector<std::string>&) override;
};
#endif
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 664a34276..6d29c9994 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -2,9 +2,11 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportInstallFileGenerator.h"
-#include "cmAlgorithms.h"
+#include <memory>
+#include <sstream>
+#include <utility>
+
#include "cmExportSet.h"
-#include "cmExportSetMap.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
@@ -15,13 +17,11 @@
#include "cmMakefile.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetExport.h"
-#include <sstream>
-#include <utility>
-
cmExportInstallFileGenerator::cmExportInstallFileGenerator(
cmInstallExportGenerator* iegen)
: IEGen(iegen)
@@ -30,9 +30,7 @@ cmExportInstallFileGenerator::cmExportInstallFileGenerator(
std::string cmExportInstallFileGenerator::GetConfigImportFileGlob()
{
- std::string glob = this->FileBase;
- glob += "-*";
- glob += this->FileExt;
+ std::string glob = cmStrCat(this->FileBase, "-*", this->FileExt);
return glob;
}
@@ -42,23 +40,19 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
{
std::string expectedTargets;
std::string sep;
- for (std::vector<cmTargetExport*>::const_iterator tei =
- this->IEGen->GetExportSet()->GetTargetExports()->begin();
- tei != this->IEGen->GetExportSet()->GetTargetExports()->end();
- ++tei) {
- expectedTargets +=
- sep + this->Namespace + (*tei)->Target->GetExportName();
+ for (std::unique_ptr<cmTargetExport> const& te :
+ this->IEGen->GetExportSet()->GetTargetExports()) {
+ expectedTargets += sep + this->Namespace + te->Target->GetExportName();
sep = " ";
- cmTargetExport* te = *tei;
if (this->ExportedTargets.insert(te->Target).second) {
- allTargets.push_back(te);
+ allTargets.push_back(te.get());
} else {
std::ostringstream e;
e << "install(EXPORT \"" << this->IEGen->GetExportSet()->GetName()
<< "\" ...) "
<< "includes target \"" << te->Target->GetName()
<< "\" more than once in the export set.";
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
return false;
}
}
@@ -76,22 +70,20 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
bool require3_1_0 = false;
bool requiresConfigFiles = false;
// Create all the imported targets.
- for (std::vector<cmTargetExport*>::const_iterator tei = allTargets.begin();
- tei != allTargets.end(); ++tei) {
- cmGeneratorTarget* gt = (*tei)->Target;
+ for (cmTargetExport* te : allTargets) {
+ cmGeneratorTarget* gt = te->Target;
+ cmStateEnums::TargetType targetType = this->GetExportTargetType(te);
requiresConfigFiles =
- requiresConfigFiles || gt->GetType() != cmStateEnums::INTERFACE_LIBRARY;
+ requiresConfigFiles || targetType != cmStateEnums::INTERFACE_LIBRARY;
- this->GenerateImportTargetCode(os, gt);
+ this->GenerateImportTargetCode(os, gt, targetType);
ImportPropertyMap properties;
this->PopulateIncludeDirectoriesInterface(
- *tei, cmGeneratorExpression::InstallInterface, properties,
- missingTargets);
- this->PopulateSourcesInterface(*tei,
- cmGeneratorExpression::InstallInterface,
+ te, cmGeneratorExpression::InstallInterface, properties, missingTargets);
+ this->PopulateSourcesInterface(te, cmGeneratorExpression::InstallInterface,
properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", gt,
cmGeneratorExpression::InstallInterface,
@@ -102,12 +94,28 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", gt,
cmGeneratorExpression::InstallInterface,
properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_PRECOMPILE_HEADERS", gt,
+ cmGeneratorExpression::InstallInterface,
+ properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", gt,
cmGeneratorExpression::InstallInterface,
properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", gt,
cmGeneratorExpression::InstallInterface,
properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gt,
+ cmGeneratorExpression::InstallInterface,
+ properties, missingTargets);
+ this->PopulateLinkDirectoriesInterface(
+ te, cmGeneratorExpression::InstallInterface, properties, missingTargets);
+ this->PopulateLinkDependsInterface(
+ te, cmGeneratorExpression::InstallInterface, properties, missingTargets);
+
+ std::string errorMessage;
+ if (!this->PopulateExportProperties(gt, properties, errorMessage)) {
+ cmSystemTools::Error(errorMessage);
+ return false;
+ }
const bool newCMP0022Behavior =
gt->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
@@ -120,7 +128,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
require2_8_12 = true;
}
}
- if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (targetType == cmStateEnums::INTERFACE_LIBRARY) {
require3_0_0 = true;
}
if (gt->GetProperty("INTERFACE_SOURCES")) {
@@ -154,10 +162,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
// Generate an import file for each configuration.
// Don't do this if we only export INTERFACE_LIBRARY targets.
if (requiresConfigFiles) {
- for (std::vector<std::string>::const_iterator ci =
- this->Configurations.begin();
- ci != this->Configurations.end(); ++ci) {
- if (!this->GenerateImportFileConfig(*ci, missingTargets)) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->GenerateImportFileConfig(c, missingTargets)) {
result = false;
}
}
@@ -193,12 +199,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 <<
@@ -272,10 +278,7 @@ bool cmExportInstallFileGenerator::GenerateImportFileConfig(
}
// Construct the name of the file to generate.
- std::string fileName = this->FileDir;
- fileName += "/";
- fileName += this->FileBase;
- fileName += "-";
+ std::string fileName = cmStrCat(this->FileDir, '/', this->FileBase, '-');
if (!config.empty()) {
fileName += cmSystemTools::LowerCase(config);
} else {
@@ -284,12 +287,12 @@ bool cmExportInstallFileGenerator::GenerateImportFileConfig(
fileName += this->FileExt;
// Open the output file to generate it.
- cmGeneratedFileStream exportFileStream(fileName.c_str(), true);
+ cmGeneratedFileStream exportFileStream(fileName, true);
if (!exportFileStream) {
std::string se = cmSystemTools::GetLastSystemError();
std::ostringstream e;
e << "cannot write to file \"" << fileName << "\": " << se;
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
return false;
}
std::ostream& os = exportFileStream;
@@ -314,12 +317,11 @@ void cmExportInstallFileGenerator::GenerateImportTargetsConfig(
std::vector<std::string>& missingTargets)
{
// Add each target in the set to the export.
- for (std::vector<cmTargetExport*>::const_iterator tei =
- this->IEGen->GetExportSet()->GetTargetExports()->begin();
- tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei) {
+ for (std::unique_ptr<cmTargetExport> const& te :
+ this->IEGen->GetExportSet()->GetTargetExports()) {
// Collect import properties for this target.
- cmTargetExport const* te = *tei;
- if (te->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetExportTargetType(te.get()) ==
+ cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
@@ -351,7 +353,7 @@ void cmExportInstallFileGenerator::GenerateImportTargetsConfig(
cmGeneratorExpression::InstallInterface,
gtgt, properties, missingTargets);
- // TOOD: PUBLIC_HEADER_LOCATION
+ // TODO: PUBLIC_HEADER_LOCATION
// This should wait until the build feature propagation stuff
// is done. Then this can be a propagated include directory.
// this->GenerateImportProperty(config, te->HeaderGenerator,
@@ -381,7 +383,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}/";
}
@@ -390,28 +392,25 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
if (itgen->IsImportLibrary()) {
// Construct the property name.
- std::string prop = "IMPORTED_IMPLIB";
- prop += suffix;
+ std::string prop = cmStrCat("IMPORTED_IMPLIB", suffix);
// Append the installed file name.
- value += itgen->GetInstallFilename(target, config,
- cmInstallTargetGenerator::NameImplib);
+ value += cmInstallTargetGenerator::GetInstallFilename(
+ target, config, cmInstallTargetGenerator::NameImplib);
// Store the property.
properties[prop] = value;
importedLocations.insert(prop);
} else if (itgen->GetTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) {
// Construct the property name.
- std::string prop = "IMPORTED_OBJECTS";
- prop += suffix;
+ std::string prop = cmStrCat("IMPORTED_OBJECTS", suffix);
// Compute all the object files inside this target and setup
// IMPORTED_OBJECTS as a list of object files
std::vector<std::string> objects;
itgen->GetInstallObjectNames(config, objects);
- for (std::vector<std::string>::iterator i = objects.begin();
- i != objects.end(); ++i) {
- *i = value + *i;
+ for (std::string& obj : objects) {
+ obj = cmStrCat(value, obj);
}
// Store the property.
@@ -419,17 +418,16 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
importedLocations.insert(prop);
} else {
// Construct the property name.
- std::string prop = "IMPORTED_LOCATION";
- prop += suffix;
+ std::string prop = cmStrCat("IMPORTED_LOCATION", suffix);
// Append the installed file name.
if (target->IsAppBundleOnApple()) {
- value += itgen->GetInstallFilename(target, config);
+ value += cmInstallTargetGenerator::GetInstallFilename(target, config);
value += ".app/Contents/MacOS/";
- value += itgen->GetInstallFilename(target, config);
+ value += cmInstallTargetGenerator::GetInstallFilename(target, config);
} else {
- value += itgen->GetInstallFilename(target, config,
- cmInstallTargetGenerator::NameReal);
+ value += cmInstallTargetGenerator::GetInstallFilename(
+ target, config, cmInstallTargetGenerator::NameReal);
}
// Store the property.
@@ -438,42 +436,54 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
}
}
+cmStateEnums::TargetType cmExportInstallFileGenerator::GetExportTargetType(
+ cmTargetExport const* targetExport) const
+{
+ cmStateEnums::TargetType targetType = targetExport->Target->GetType();
+ // An OBJECT library installed with no OBJECTS DESTINATION
+ // is transformed to an INTERFACE library.
+ if (targetType == cmStateEnums::OBJECT_LIBRARY &&
+ targetExport->ObjectsGenerator == nullptr) {
+ targetType = cmStateEnums::INTERFACE_LIBRARY;
+ }
+ return targetType;
+}
+
void cmExportInstallFileGenerator::HandleMissingTarget(
std::string& link_libs, std::vector<std::string>& missingTargets,
cmGeneratorTarget* depender, cmGeneratorTarget* dependee)
{
const std::string name = dependee->GetName();
cmGlobalGenerator* gg = dependee->GetLocalGenerator()->GetGlobalGenerator();
- std::vector<std::string> namespaces = this->FindNamespaces(gg, name);
- int targetOccurrences = (int)namespaces.size();
- if (targetOccurrences == 1) {
- std::string missingTarget = namespaces[0];
+ auto exportInfo = this->FindNamespaces(gg, name);
+ std::vector<std::string> const& exportFiles = exportInfo.first;
+ if (exportFiles.size() == 1) {
+ std::string missingTarget = exportInfo.second;
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.
- this->ComplainAboutMissingTarget(depender, dependee, targetOccurrences);
+ this->ComplainAboutMissingTarget(depender, dependee, exportFiles);
}
}
-std::vector<std::string> cmExportInstallFileGenerator::FindNamespaces(
- cmGlobalGenerator* gg, const std::string& name)
+std::pair<std::vector<std::string>, std::string>
+cmExportInstallFileGenerator::FindNamespaces(cmGlobalGenerator* gg,
+ const std::string& name)
{
- std::vector<std::string> namespaces;
+ std::vector<std::string> exportFiles;
+ std::string ns;
const cmExportSetMap& exportSets = gg->GetExportSets();
- for (cmExportSetMap::const_iterator expIt = exportSets.begin();
- expIt != exportSets.end(); ++expIt) {
- const cmExportSet* exportSet = expIt->second;
- std::vector<cmTargetExport*> const* targets =
- exportSet->GetTargetExports();
+ for (auto const& expIt : exportSets) {
+ const cmExportSet& exportSet = expIt.second;
bool containsTarget = false;
- for (unsigned int i = 0; i < targets->size(); i++) {
- if (name == (*targets)[i]->TargetName) {
+ for (auto const& target : exportSet.GetTargetExports()) {
+ if (name == target->TargetName) {
containsTarget = true;
break;
}
@@ -481,31 +491,37 @@ std::vector<std::string> cmExportInstallFileGenerator::FindNamespaces(
if (containsTarget) {
std::vector<cmInstallExportGenerator const*> const* installs =
- exportSet->GetInstallations();
- for (unsigned int i = 0; i < installs->size(); i++) {
- namespaces.push_back((*installs)[i]->GetNamespace());
+ exportSet.GetInstallations();
+ for (cmInstallExportGenerator const* install : *installs) {
+ exportFiles.push_back(install->GetDestinationFile());
+ ns = install->GetNamespace();
}
}
}
- return namespaces;
+ return { exportFiles, ns };
}
void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
- cmGeneratorTarget* depender, cmGeneratorTarget* dependee, int occurrences)
+ cmGeneratorTarget* depender, cmGeneratorTarget* dependee,
+ std::vector<std::string> const& exportFiles)
{
std::ostringstream e;
e << "install(EXPORT \"" << this->IEGen->GetExportSet()->GetName()
<< "\" ...) "
<< "includes target \"" << depender->GetName()
<< "\" which requires target \"" << dependee->GetName() << "\" ";
- if (occurrences == 0) {
- e << "that is not in the export set.";
+ if (exportFiles.empty()) {
+ e << "that is not in any export set.";
} else {
- e << "that is not in this export set, but " << occurrences
- << " times in others.";
+ e << "that is not in this export set, but in multiple other export sets: "
+ << cmJoin(exportFiles, ", ") << ".\n";
+ e << "An exported target cannot depend upon another target which is "
+ "exported multiple times. Consider consolidating the exports of the "
+ "\""
+ << dependee->GetName() << "\" target to a single export.";
}
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
}
std::string cmExportInstallFileGenerator::InstallNameDir(
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index 8fa9b7f88..5fa812c58 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -3,20 +3,23 @@
#ifndef cmExportInstallFileGenerator_h
#define cmExportInstallFileGenerator_h
-#include "cmConfigure.h"
-
-#include "cmExportFileGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <map>
#include <set>
#include <string>
+#include <utility>
#include <vector>
+#include "cmExportFileGenerator.h"
+#include "cmStateTypes.h"
+
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmInstallExportGenerator;
class cmInstallTargetGenerator;
+class cmTargetExport;
/** \class cmExportInstallFileGenerator
* \brief Generate a file exporting targets from an install tree.
@@ -39,7 +42,7 @@ public:
files. */
cmExportInstallFileGenerator(cmInstallExportGenerator* iegen);
- /** Get the per-config file generated for each configuraiton. This
+ /** Get the per-config file generated for each configuration. This
maps from the configuration name to the file temporary location
for installation. */
std::map<std::string, std::string> const& GetConfigImportFiles()
@@ -53,23 +56,25 @@ public:
protected:
// Implement virtual methods from the superclass.
- bool GenerateMainFile(std::ostream& os) CM_OVERRIDE;
+ bool GenerateMainFile(std::ostream& os) override;
void GenerateImportTargetsConfig(
std::ostream& os, const std::string& config, std::string const& suffix,
- std::vector<std::string>& missingTargets) CM_OVERRIDE;
+ std::vector<std::string>& missingTargets) override;
+ cmStateEnums::TargetType GetExportTargetType(
+ cmTargetExport const* targetExport) const;
void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
cmGeneratorTarget* depender,
- cmGeneratorTarget* dependee) CM_OVERRIDE;
+ cmGeneratorTarget* dependee) override;
- void ReplaceInstallPrefix(std::string& input) CM_OVERRIDE;
+ void ReplaceInstallPrefix(std::string& input) override;
void ComplainAboutMissingTarget(cmGeneratorTarget* depender,
cmGeneratorTarget* dependee,
- int occurrences);
+ std::vector<std::string> const& exportFiles);
- std::vector<std::string> FindNamespaces(cmGlobalGenerator* gg,
- const std::string& name);
+ std::pair<std::vector<std::string>, std::string> FindNamespaces(
+ cmGlobalGenerator* gg, const std::string& name);
/** Generate the relative import prefix. */
virtual void GenerateImportPrefix(std::ostream&);
@@ -91,7 +96,7 @@ protected:
std::set<std::string>& importedLocations);
std::string InstallNameDir(cmGeneratorTarget* target,
- const std::string& config) CM_OVERRIDE;
+ const std::string& config) override;
cmInstallExportGenerator* IEGen;
diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx
index 69150aee4..89093e95f 100644
--- a/Source/cmExportLibraryDependenciesCommand.cxx
+++ b/Source/cmExportLibraryDependenciesCommand.cxx
@@ -2,85 +2,58 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportLibraryDependenciesCommand.h"
-#include "cmsys/FStream.hxx"
#include <map>
#include <utility>
+#include <cm/memory>
+
+#include "cmsys/FStream.hxx"
+
+#include "cmExecutionStatus.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetLinkLibraryType.h"
-#include "cm_auto_ptr.hxx"
-#include "cm_unordered_map.hxx"
#include "cmake.h"
-class cmExecutionStatus;
-
-bool cmExportLibraryDependenciesCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
-{
- if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
- return false;
- }
-
- // store the arguments for the final pass
- this->Filename = args[0];
- this->Append = false;
- if (args.size() > 1) {
- if (args[1] == "APPEND") {
- this->Append = true;
- }
- }
- return true;
-}
-
-void cmExportLibraryDependenciesCommand::FinalPass()
-{
- // export_library_dependencies() shouldn't modify anything
- // ensure this by calling a const method
- this->ConstFinalPass();
-}
-
-void cmExportLibraryDependenciesCommand::ConstFinalPass() const
+static void FinalAction(cmMakefile& makefile, std::string const& filename,
+ bool append)
{
// Use copy-if-different if not appending.
- CM_AUTO_PTR<cmsys::ofstream> foutPtr;
- if (this->Append) {
- CM_AUTO_PTR<cmsys::ofstream> ap(
- new cmsys::ofstream(this->Filename.c_str(), std::ios::app));
- foutPtr = ap;
+ std::unique_ptr<cmsys::ofstream> foutPtr;
+ if (append) {
+ const auto openmodeApp = std::ios::app;
+ foutPtr = cm::make_unique<cmsys::ofstream>(filename.c_str(), openmodeApp);
} else {
- CM_AUTO_PTR<cmGeneratedFileStream> ap(
- new cmGeneratedFileStream(this->Filename.c_str(), true));
+ std::unique_ptr<cmGeneratedFileStream> ap(
+ new cmGeneratedFileStream(filename, true));
ap->SetCopyIfDifferent(true);
- foutPtr = ap;
+ foutPtr = std::move(ap);
}
std::ostream& fout = *foutPtr;
if (!fout) {
- cmSystemTools::Error("Error Writing ", this->Filename.c_str());
+ cmSystemTools::Error("Error Writing " + filename);
cmSystemTools::ReportLastSystemError("");
return;
}
// Collect dependency information about all library targets built in
// the project.
- cmake* cm = this->Makefile->GetCMakeInstance();
+ cmake* cm = makefile.GetCMakeInstance();
cmGlobalGenerator* global = cm->GetGlobalGenerator();
const std::vector<cmMakefile*>& locals = global->GetMakefiles();
std::map<std::string, std::string> libDepsOld;
std::map<std::string, std::string> libDepsNew;
std::map<std::string, std::string> libTypes;
- for (std::vector<cmMakefile*>::const_iterator i = locals.begin();
- i != locals.end(); ++i) {
- const cmTargets& tgts = (*i)->GetTargets();
- for (cmTargets::const_iterator l = tgts.begin(); l != tgts.end(); ++l) {
+ for (cmMakefile* local : locals) {
+ for (auto const& tgt : local->GetTargets()) {
// Get the current target.
- cmTarget const& target = l->second;
+ cmTarget const& target = tgt.second;
// Skip non-library targets.
if (target.GetType() < cmStateEnums::STATIC_LIBRARY ||
@@ -89,8 +62,7 @@ void cmExportLibraryDependenciesCommand::ConstFinalPass() const
}
// Construct the dependency variable name.
- std::string targetEntry = target.GetName();
- targetEntry += "_LIB_DEPENDS";
+ std::string targetEntry = cmStrCat(target.GetName(), "_LIB_DEPENDS");
// Construct the dependency variable value with the direct link
// dependencies.
@@ -98,12 +70,10 @@ void cmExportLibraryDependenciesCommand::ConstFinalPass() const
std::string valueNew;
cmTarget::LinkLibraryVectorType const& libs =
target.GetOriginalLinkLibraries();
- for (cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
- li != libs.end(); ++li) {
- std::string ltVar = li->first;
- ltVar += "_LINK_TYPE";
+ for (cmTarget::LibraryID const& li : libs) {
+ std::string ltVar = cmStrCat(li.first, "_LINK_TYPE");
std::string ltValue;
- switch (li->second) {
+ switch (li.second) {
case GENERAL_LibraryType:
valueNew += "general;";
ltValue = "general";
@@ -117,7 +87,7 @@ void cmExportLibraryDependenciesCommand::ConstFinalPass() const
ltValue = "optimized";
break;
}
- std::string lib = li->first;
+ std::string lib = li.first;
if (cmTarget* libtgt = global->FindTarget(lib)) {
// Handle simple output name changes. This command is
// deprecated so we do not support full target name
@@ -150,27 +120,40 @@ void cmExportLibraryDependenciesCommand::ConstFinalPass() const
fout << "# Generated by CMake\n\n";
fout << "if(" << vertest << ")\n";
fout << " # Information for CMake 2.6 and above.\n";
- for (std::map<std::string, std::string>::const_iterator i =
- libDepsNew.begin();
- i != libDepsNew.end(); ++i) {
- if (!i->second.empty()) {
- fout << " set(\"" << i->first << "\" \"" << i->second << "\")\n";
+ for (auto const& i : libDepsNew) {
+ if (!i.second.empty()) {
+ fout << " set(\"" << i.first << "\" \"" << i.second << "\")\n";
}
}
fout << "else()\n";
fout << " # Information for CMake 2.4 and lower.\n";
- for (std::map<std::string, std::string>::const_iterator i =
- libDepsOld.begin();
- i != libDepsOld.end(); ++i) {
- if (!i->second.empty()) {
- fout << " set(\"" << i->first << "\" \"" << i->second << "\")\n";
+ for (auto const& i : libDepsOld) {
+ if (!i.second.empty()) {
+ fout << " set(\"" << i.first << "\" \"" << i.second << "\")\n";
}
}
- for (std::map<std::string, std::string>::const_iterator i = libTypes.begin();
- i != libTypes.end(); ++i) {
- if (i->second != "general") {
- fout << " set(\"" << i->first << "\" \"" << i->second << "\")\n";
+ for (auto const& i : libTypes) {
+ if (i.second != "general") {
+ fout << " set(\"" << i.first << "\" \"" << i.second << "\")\n";
}
}
fout << "endif()\n";
}
+
+bool cmExportLibraryDependenciesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.empty()) {
+ status.SetError("called with incorrect number of arguments");
+ return false;
+ }
+
+ std::string const& filename = args[0];
+ bool const append = args.size() > 1 && args[1] == "APPEND";
+ status.GetMakefile().AddFinalAction(
+ [filename, append](cmMakefile& makefile) {
+ FinalAction(makefile, filename, append);
+ });
+
+ return true;
+}
diff --git a/Source/cmExportLibraryDependenciesCommand.h b/Source/cmExportLibraryDependenciesCommand.h
index 5559af94b..230c90616 100644
--- a/Source/cmExportLibraryDependenciesCommand.h
+++ b/Source/cmExportLibraryDependenciesCommand.h
@@ -3,32 +3,14 @@
#ifndef cmExportLibraryDependenciesCommand_h
#define cmExportLibraryDependenciesCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmExportLibraryDependenciesCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE
- {
- return new cmExportLibraryDependenciesCommand;
- }
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
- void FinalPass() CM_OVERRIDE;
- bool HasFinalPass() const CM_OVERRIDE { return true; }
-
-private:
- std::string Filename;
- bool Append;
- void ConstFinalPass() const;
-};
+bool cmExportLibraryDependenciesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmExportSet.cxx b/Source/cmExportSet.cxx
index a93667994..a20aa9a8a 100644
--- a/Source/cmExportSet.cxx
+++ b/Source/cmExportSet.cxx
@@ -2,29 +2,43 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportSet.h"
-#include "cmAlgorithms.h"
+#include <tuple>
+#include <utility>
+
#include "cmLocalGenerator.h"
#include "cmTargetExport.h"
-cmExportSet::~cmExportSet()
+cmExportSet::cmExportSet(std::string name)
+ : Name(std::move(name))
{
- cmDeleteAll(this->TargetExports);
}
+cmExportSet::~cmExportSet() = default;
+
void cmExportSet::Compute(cmLocalGenerator* lg)
{
- for (std::vector<cmTargetExport*>::iterator it = this->TargetExports.begin();
- it != this->TargetExports.end(); ++it) {
- (*it)->Target = lg->FindGeneratorTargetToUse((*it)->TargetName);
+ for (std::unique_ptr<cmTargetExport>& tgtExport : this->TargetExports) {
+ tgtExport->Target = lg->FindGeneratorTargetToUse(tgtExport->TargetName);
}
}
-void cmExportSet::AddTargetExport(cmTargetExport* te)
+void cmExportSet::AddTargetExport(std::unique_ptr<cmTargetExport> te)
{
- this->TargetExports.push_back(te);
+ this->TargetExports.emplace_back(std::move(te));
}
void cmExportSet::AddInstallation(cmInstallExportGenerator const* installation)
{
this->Installations.push_back(installation);
}
+
+cmExportSet& cmExportSetMap::operator[](const std::string& name)
+{
+ auto it = this->find(name);
+ if (it == this->end()) // Export set not found
+ {
+ auto tup_name = std::make_tuple(name);
+ it = this->emplace(std::piecewise_construct, tup_name, tup_name).first;
+ }
+ return it->second;
+}
diff --git a/Source/cmExportSet.h b/Source/cmExportSet.h
index 58ad617d4..f0d921f5e 100644
--- a/Source/cmExportSet.h
+++ b/Source/cmExportSet.h
@@ -5,6 +5,8 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <map>
+#include <memory>
#include <string>
#include <vector>
@@ -17,24 +19,24 @@ class cmExportSet
{
public:
/// Construct an empty export set named \a name
- cmExportSet(const std::string& name)
- : Name(name)
- {
- }
+ cmExportSet(std::string name);
/// Destructor
~cmExportSet();
+ cmExportSet(const cmExportSet&) = delete;
+ cmExportSet& operator=(const cmExportSet&) = delete;
+
void Compute(cmLocalGenerator* lg);
- void AddTargetExport(cmTargetExport* tgt);
+ void AddTargetExport(std::unique_ptr<cmTargetExport> tgt);
void AddInstallation(cmInstallExportGenerator const* installation);
std::string const& GetName() const { return this->Name; }
- std::vector<cmTargetExport*> const* GetTargetExports() const
+ std::vector<std::unique_ptr<cmTargetExport>> const& GetTargetExports() const
{
- return &this->TargetExports;
+ return this->TargetExports;
}
std::vector<cmInstallExportGenerator const*> const* GetInstallations() const
@@ -43,9 +45,21 @@ public:
}
private:
- std::vector<cmTargetExport*> TargetExports;
+ std::vector<std::unique_ptr<cmTargetExport>> TargetExports;
std::string Name;
std::vector<cmInstallExportGenerator const*> Installations;
};
+/// A name -> cmExportSet map with overloaded operator[].
+class cmExportSetMap : public std::map<std::string, cmExportSet>
+{
+public:
+ /** \brief Overloaded operator[].
+ *
+ * The operator is overloaded because cmExportSet has no default constructor:
+ * we do not want unnamed export sets.
+ */
+ cmExportSet& operator[](const std::string& name);
+};
+
#endif
diff --git a/Source/cmExportSetMap.cxx b/Source/cmExportSetMap.cxx
deleted file mode 100644
index 074082835..000000000
--- a/Source/cmExportSetMap.cxx
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmExportSetMap.h"
-
-#include "cmAlgorithms.h"
-#include "cmExportSet.h"
-
-#include <utility>
-
-cmExportSet* cmExportSetMap::operator[](const std::string& name)
-{
- std::map<std::string, cmExportSet*>::iterator it = this->find(name);
- if (it == this->end()) // Export set not found
- {
- it = this->insert(std::make_pair(name, new cmExportSet(name))).first;
- }
- return it->second;
-}
-
-void cmExportSetMap::clear()
-{
- cmDeleteAll(*this);
- this->derived::clear();
-}
-
-cmExportSetMap::~cmExportSetMap()
-{
- this->clear();
-}
diff --git a/Source/cmExportSetMap.h b/Source/cmExportSetMap.h
deleted file mode 100644
index 0f71c790c..000000000
--- a/Source/cmExportSetMap.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmExportSetMap_h
-#define cmExportSetMap_h
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <map>
-#include <string>
-
-class cmExportSet;
-
-/// A name -> cmExportSet map with overloaded operator[].
-class cmExportSetMap : public std::map<std::string, cmExportSet*>
-{
- typedef std::map<std::string, cmExportSet*> derived;
-
-public:
- /** \brief Overloaded operator[].
- *
- * The operator is overloaded because cmExportSet has no default constructor:
- * we do not want unnamed export sets.
- */
- cmExportSet* operator[](const std::string& name);
-
- void clear();
-
- /// Overloaded destructor deletes all member export sets.
- ~cmExportSetMap();
-};
-
-#endif
diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
index cd0a7e69a..fafa51b7b 100644
--- a/Source/cmExportTryCompileFileGenerator.cxx
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -2,6 +2,10 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportTryCompileFileGenerator.h"
+#include <map>
+#include <memory>
+#include <utility>
+
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorTarget.h"
@@ -9,16 +13,13 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmStateTypes.h"
-#include "cmSystemTools.h"
+#include "cmStringAlgorithms.h"
#include "cmTarget.h"
-#include "cm_auto_ptr.hxx"
-
-#include <map>
-#include <utility>
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);
}
@@ -32,16 +33,18 @@ bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)
this->Exports.pop_back();
if (emitted.insert(te).second) {
emittedDeps.insert(te);
- this->GenerateImportTargetCode(os, te);
+ this->GenerateImportTargetCode(os, te, te->GetType());
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) {
@@ -62,10 +65,9 @@ std::string cmExportTryCompileFileGenerator::FindTargets(
cmGeneratorExpression ge;
- cmGeneratorExpressionDAGChecker dagChecker(tgt->GetName(), propName,
- CM_NULLPTR, CM_NULLPTR);
+ cmGeneratorExpressionDAGChecker dagChecker(tgt, propName, nullptr, nullptr);
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
cmTarget dummyHead("try_compile_dummy_exe", cmStateEnums::EXECUTABLE,
cmTarget::VisibilityNormal, tgt->Target->GetMakefile());
@@ -73,15 +75,13 @@ std::string cmExportTryCompileFileGenerator::FindTargets(
cmGeneratorTarget gDummyHead(&dummyHead, tgt->GetLocalGenerator());
std::string result = cge->Evaluate(tgt->GetLocalGenerator(), this->Config,
- false, &gDummyHead, tgt, &dagChecker);
+ &gDummyHead, &dagChecker, tgt, language);
const std::set<cmGeneratorTarget const*>& allTargets =
cge->GetAllTargetsSeen();
- for (std::set<cmGeneratorTarget const*>::const_iterator li =
- allTargets.begin();
- li != allTargets.end(); ++li) {
- if (emitted.insert(*li).second) {
- this->Exports.push_back(*li);
+ for (cmGeneratorTarget const* target : allTargets) {
+ if (emitted.insert(target).second) {
+ this->Exports.push_back(target);
}
}
return result;
@@ -92,22 +92,20 @@ void cmExportTryCompileFileGenerator::PopulateProperties(
std::set<cmGeneratorTarget const*>& emitted)
{
std::vector<std::string> props = target->GetPropertyKeys();
- for (std::vector<std::string>::const_iterator i = props.begin();
- i != props.end(); ++i) {
+ for (std::string const& p : props) {
- properties[*i] = target->GetProperty(*i);
+ properties[p] = target->GetProperty(p);
- if (i->find("IMPORTED_LINK_INTERFACE_LIBRARIES") == 0 ||
- i->find("IMPORTED_LINK_DEPENDENT_LIBRARIES") == 0 ||
- i->find("INTERFACE_LINK_LIBRARIES") == 0) {
- std::string evalResult = this->FindTargets(*i, target, emitted);
+ 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, std::string(), emitted);
- std::vector<std::string> depends;
- cmSystemTools::ExpandListArgument(evalResult, depends);
- for (std::vector<std::string>::const_iterator li = depends.begin();
- li != depends.end(); ++li) {
+ std::vector<std::string> depends = cmExpandedList(evalResult);
+ for (std::string const& li : depends) {
cmGeneratorTarget* tgt =
- target->GetLocalGenerator()->FindGeneratorTargetToUse(*li);
+ target->GetLocalGenerator()->FindGeneratorTargetToUse(li);
if (tgt && emitted.insert(tgt).second) {
this->Exports.push_back(tgt);
}
diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h
index 9671fac8f..7573427f6 100644
--- a/Source/cmExportTryCompileFileGenerator.h
+++ b/Source/cmExportTryCompileFileGenerator.h
@@ -3,15 +3,15 @@
#ifndef cmExportTryCompileFileGenerator_h
#define cmExportTryCompileFileGenerator_h
-#include "cmConfigure.h"
-
-#include "cmExportFileGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <set>
#include <string>
#include <vector>
+#include "cmExportFileGenerator.h"
+
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmMakefile;
@@ -21,21 +21,23 @@ 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; }
+
protected:
// Implement virtual methods from the superclass.
- bool GenerateMainFile(std::ostream& os) CM_OVERRIDE;
+ bool GenerateMainFile(std::ostream& os) override;
void GenerateImportTargetsConfig(std::ostream&, const std::string&,
std::string const&,
- std::vector<std::string>&) CM_OVERRIDE
+ std::vector<std::string>&) override
{
}
void HandleMissingTarget(std::string&, std::vector<std::string>&,
- cmGeneratorTarget*, cmGeneratorTarget*) CM_OVERRIDE
+ cmGeneratorTarget*, cmGeneratorTarget*) override
{
}
@@ -44,15 +46,17 @@ protected:
std::set<const cmGeneratorTarget*>& emitted);
std::string InstallNameDir(cmGeneratorTarget* target,
- const std::string& config) CM_OVERRIDE;
+ const std::string& config) override;
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/cmExprParserHelper.cxx b/Source/cmExprParserHelper.cxx
index c3f026a4e..56dfc6c1d 100644
--- a/Source/cmExprParserHelper.cxx
+++ b/Source/cmExprParserHelper.cxx
@@ -2,25 +2,24 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExprParserHelper.h"
-#include "cmConfigure.h"
-
-#include "cmExprLexer.h"
-
#include <iostream>
#include <sstream>
+#include <stdexcept>
+#include <utility>
+
+#include "cmExprLexer.h"
+#include "cmStringAlgorithms.h"
int cmExpr_yyparse(yyscan_t yyscanner);
//
cmExprParserHelper::cmExprParserHelper()
{
this->FileLine = -1;
- this->FileName = CM_NULLPTR;
+ this->FileName = nullptr;
+ this->Result = 0;
}
-cmExprParserHelper::~cmExprParserHelper()
-{
- this->CleanupParser();
-}
+cmExprParserHelper::~cmExprParserHelper() = default;
int cmExprParserHelper::ParseString(const char* str, int verb)
{
@@ -39,16 +38,31 @@ int cmExprParserHelper::ParseString(const char* str, int verb)
yyscan_t yyscanner;
cmExpr_yylex_init(&yyscanner);
cmExpr_yyset_extra(this, yyscanner);
- int res = cmExpr_yyparse(yyscanner);
+
+ try {
+ int res = cmExpr_yyparse(yyscanner);
+ if (res != 0) {
+ std::string e = cmStrCat("cannot parse the expression: \"", InputBuffer,
+ "\": ", ErrorString, '.');
+ this->SetError(std::move(e));
+ }
+ } catch (std::runtime_error const& fail) {
+ std::string e = cmStrCat("cannot evaluate the expression: \"", InputBuffer,
+ "\": ", fail.what(), '.');
+ this->SetError(std::move(e));
+ } catch (std::out_of_range const&) {
+ std::string e = "cannot evaluate the expression: \"" + InputBuffer +
+ "\": a numeric value is out of range.";
+ this->SetError(std::move(e));
+ } catch (...) {
+ std::string e = "cannot parse the expression: \"" + InputBuffer + "\".";
+ this->SetError(std::move(e));
+ }
cmExpr_yylex_destroy(yyscanner);
- if (res != 0) {
- // str << "CAL_Parser returned: " << res << std::endl;
- // std::cerr << "When parsing: [" << str << "]" << std::endl;
+ if (!this->ErrorString.empty()) {
return 0;
}
- this->CleanupParser();
-
if (Verbose) {
std::cerr << "Expanding [" << str << "] produced: [" << this->Result << "]"
<< std::endl;
@@ -56,10 +70,6 @@ int cmExprParserHelper::ParseString(const char* str, int verb)
return 1;
}
-void cmExprParserHelper::CleanupParser()
-{
-}
-
int cmExprParserHelper::LexInput(char* buf, int maxlen)
{
// std::cout << "JPLexInput ";
@@ -87,7 +97,21 @@ void cmExprParserHelper::Error(const char* str)
this->ErrorString = ostr.str();
}
-void cmExprParserHelper::SetResult(int value)
+void cmExprParserHelper::UnexpectedChar(char c)
+{
+ unsigned long pos = static_cast<unsigned long>(this->InputBufferPos);
+ std::ostringstream ostr;
+ ostr << "Unexpected character in expression at position " << pos << ": " << c
+ << "\n";
+ this->WarningString += ostr.str();
+}
+
+void cmExprParserHelper::SetResult(KWIML_INT_int64_t value)
{
this->Result = value;
}
+
+void cmExprParserHelper::SetError(std::string errorString)
+{
+ this->ErrorString = std::move(errorString);
+}
diff --git a/Source/cmExprParserHelper.h b/Source/cmExprParserHelper.h
index dcdaca967..eaf5dc78a 100644
--- a/Source/cmExprParserHelper.h
+++ b/Source/cmExprParserHelper.h
@@ -8,12 +8,14 @@
#include <string>
#include <vector>
+#include "cm_kwiml.h"
+
class cmExprParserHelper
{
public:
struct ParserType
{
- int Number;
+ KWIML_INT_int64_t Number;
};
cmExprParserHelper();
@@ -24,12 +26,16 @@ public:
int LexInput(char* buf, int maxlen);
void Error(const char* str);
- void SetResult(int value);
+ void SetResult(KWIML_INT_int64_t value);
- int GetResult() { return this->Result; }
+ KWIML_INT_int64_t GetResult() { return this->Result; }
const char* GetError() { return this->ErrorString.c_str(); }
+ void UnexpectedChar(char c);
+
+ std::string const& GetWarning() const { return this->WarningString; }
+
private:
std::string::size_type InputBufferPos;
std::string InputBuffer;
@@ -39,12 +45,13 @@ private:
void Print(const char* place, const char* str);
- void CleanupParser();
+ void SetError(std::string errorString);
- int Result;
+ KWIML_INT_int64_t Result;
const char* FileName;
long FileLine;
std::string ErrorString;
+ std::string WarningString;
};
#define YYSTYPE cmExprParserHelper::ParserType
diff --git a/Source/cmExternalMakefileProjectGenerator.cxx b/Source/cmExternalMakefileProjectGenerator.cxx
index 825ec654e..5895d666e 100644
--- a/Source/cmExternalMakefileProjectGenerator.cxx
+++ b/Source/cmExternalMakefileProjectGenerator.cxx
@@ -2,6 +2,10 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExternalMakefileProjectGenerator.h"
+#include <utility>
+
+#include "cmStringAlgorithms.h"
+
class cmMakefile;
void cmExternalMakefileProjectGenerator::EnableLanguage(
@@ -16,27 +20,30 @@ std::string cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
std::string fullName;
if (!globalGenerator.empty()) {
if (!extraGenerator.empty()) {
- fullName = extraGenerator;
- fullName += " - ";
+ fullName = cmStrCat(extraGenerator, " - ");
}
fullName += globalGenerator;
}
return fullName;
}
-cmExternalMakefileProjectGeneratorFactory::
- cmExternalMakefileProjectGeneratorFactory(const std::string& n,
- const std::string& doc)
- : Name(n)
- , Documentation(doc)
+bool cmExternalMakefileProjectGenerator::Open(
+ const std::string& /*bindir*/, const std::string& /*projectName*/,
+ bool /*dryRun*/)
{
+ return false;
}
cmExternalMakefileProjectGeneratorFactory::
- ~cmExternalMakefileProjectGeneratorFactory()
+ cmExternalMakefileProjectGeneratorFactory(std::string n, std::string doc)
+ : Name(std::move(n))
+ , Documentation(std::move(doc))
{
}
+cmExternalMakefileProjectGeneratorFactory::
+ ~cmExternalMakefileProjectGeneratorFactory() = default;
+
std::string cmExternalMakefileProjectGeneratorFactory::GetName() const
{
return this->Name;
diff --git a/Source/cmExternalMakefileProjectGenerator.h b/Source/cmExternalMakefileProjectGenerator.h
index 6b8903790..a472a0691 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
@@ -26,18 +26,18 @@ class cmMakefile;
class cmExternalMakefileProjectGenerator
{
public:
- virtual ~cmExternalMakefileProjectGenerator() {}
+ virtual ~cmExternalMakefileProjectGenerator() = default;
virtual void EnableLanguage(std::vector<std::string> const& languages,
cmMakefile*, bool optional);
- ///! set the global generator which will generate the makefiles
+ //! set the global generator which will generate the makefiles
virtual void SetGlobalGenerator(cmGlobalGenerator* generator)
{
this->GlobalGenerator = generator;
}
- ///! Return the list of global generators supported by this extra generator
+ //! Return the list of global generators supported by this extra generator
const std::vector<std::string>& GetSupportedGlobalGenerators() const
{
return this->SupportedGlobalGenerators;
@@ -49,17 +49,20 @@ public:
static std::string CreateFullGeneratorName(
const std::string& globalGenerator, const std::string& extraGenerator);
- ///! Generate the project files, the Makefiles have already been generated
+ //! Generate the project files, the Makefiles have already been generated
virtual void Generate() = 0;
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.
+ //! Contains the names of the global generators support by this generator.
std::vector<std::string> SupportedGlobalGenerators;
- ///! the global generator which creates the makefiles
- const cmGlobalGenerator* GlobalGenerator;
+ //! the global generator which creates the makefiles
+ const cmGlobalGenerator* GlobalGenerator = nullptr;
std::string Name;
};
@@ -67,8 +70,7 @@ protected:
class cmExternalMakefileProjectGeneratorFactory
{
public:
- cmExternalMakefileProjectGeneratorFactory(const std::string& n,
- const std::string& doc);
+ cmExternalMakefileProjectGeneratorFactory(std::string n, std::string doc);
virtual ~cmExternalMakefileProjectGeneratorFactory();
std::string GetName() const;
@@ -99,7 +101,7 @@ public:
}
cmExternalMakefileProjectGenerator* CreateExternalMakefileProjectGenerator()
- const CM_OVERRIDE
+ const override
{
T* p = new T;
p->SetName(GetName());
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index 5b7b82762..5a5d95910 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -4,7 +4,7 @@
#include <map>
#include <ostream>
-#include <string.h>
+#include <set>
#include <utility>
#include "cmAlgorithms.h"
@@ -13,8 +13,10 @@
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLWriter.h"
#include "cmake.h"
@@ -32,10 +34,7 @@ Discussion:
http://forums.codeblocks.org/index.php/topic,6789.0.html
*/
-cmExtraCodeBlocksGenerator::cmExtraCodeBlocksGenerator()
- : cmExternalMakefileProjectGenerator()
-{
-}
+cmExtraCodeBlocksGenerator::cmExtraCodeBlocksGenerator() = default;
cmExternalMakefileProjectGeneratorFactory*
cmExtraCodeBlocksGenerator::GetFactory()
@@ -62,11 +61,9 @@ cmExtraCodeBlocksGenerator::GetFactory()
void cmExtraCodeBlocksGenerator::Generate()
{
// for each sub project in the project create a codeblocks project
- for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
- it = this->GlobalGenerator->GetProjectMap().begin();
- it != this->GlobalGenerator->GetProjectMap().end(); ++it) {
+ for (auto const& it : this->GlobalGenerator->GetProjectMap()) {
// create a project file
- this->CreateProjectFile(it->second);
+ this->CreateProjectFile(it.second);
}
}
@@ -77,10 +74,9 @@ void cmExtraCodeBlocksGenerator::CreateProjectFile(
std::string outputDir = lgs[0]->GetCurrentBinaryDirectory();
std::string projectName = lgs[0]->GetProjectName();
- std::string filename = outputDir + "/";
- filename += projectName + ".cbp";
- std::string sessionFilename = outputDir + "/";
- sessionFilename += projectName + ".layout";
+ std::string filename = cmStrCat(outputDir, '/', projectName, ".cbp");
+ std::string sessionFilename =
+ cmStrCat(outputDir, '/', projectName, ".layout");
this->CreateNewProjectFile(lgs, filename);
}
@@ -95,7 +91,7 @@ struct Tree
{
std::string path; // only one component of the path
std::vector<Tree> folders;
- std::vector<std::string> files;
+ std::set<std::string> files;
void InsertPath(const std::vector<std::string>& splitted,
std::vector<std::string>::size_type start,
const std::string& fileName);
@@ -112,18 +108,17 @@ void Tree::InsertPath(const std::vector<std::string>& splitted,
const std::string& fileName)
{
if (start == splitted.size()) {
- files.push_back(fileName);
+ files.insert(fileName);
return;
}
- for (std::vector<Tree>::iterator it = folders.begin(); it != folders.end();
- ++it) {
- if ((*it).path == splitted[start]) {
+ for (Tree& folder : folders) {
+ if (folder.path == splitted[start]) {
if (start + 1 < splitted.size()) {
- it->InsertPath(splitted, start + 1, fileName);
+ folder.InsertPath(splitted, start + 1, fileName);
return;
}
// last part of splitted
- it->files.push_back(fileName);
+ folder.files.insert(fileName);
return;
}
}
@@ -136,7 +131,7 @@ void Tree::InsertPath(const std::vector<std::string>& splitted,
return;
}
// last part of splitted
- newFolder.files.push_back(fileName);
+ newFolder.files.insert(fileName);
folders.push_back(newFolder);
}
@@ -144,9 +139,8 @@ void Tree::BuildVirtualFolder(cmXMLWriter& xml) const
{
xml.StartElement("Option");
std::string virtualFolders = "CMake Files\\;";
- for (std::vector<Tree>::const_iterator it = folders.begin();
- it != folders.end(); ++it) {
- it->BuildVirtualFolderImpl(virtualFolders, "");
+ for (Tree const& folder : folders) {
+ folder.BuildVirtualFolderImpl(virtualFolders, "");
}
xml.Attribute("virtualFolders", virtualFolders);
xml.EndElement();
@@ -156,18 +150,16 @@ void Tree::BuildVirtualFolderImpl(std::string& virtualFolders,
const std::string& prefix) const
{
virtualFolders += "CMake Files\\" + prefix + path + "\\;";
- for (std::vector<Tree>::const_iterator it = folders.begin();
- it != folders.end(); ++it) {
- it->BuildVirtualFolderImpl(virtualFolders, prefix + path + "\\");
+ for (Tree const& folder : folders) {
+ folder.BuildVirtualFolderImpl(virtualFolders, prefix + path + "\\");
}
}
void Tree::BuildUnit(cmXMLWriter& xml, const std::string& fsPath) const
{
- for (std::vector<std::string>::const_iterator it = files.begin();
- it != files.end(); ++it) {
+ for (std::string const& f : files) {
xml.StartElement("Unit");
- xml.Attribute("filename", fsPath + *it);
+ xml.Attribute("filename", fsPath + f);
xml.StartElement("Option");
xml.Attribute("virtualFolder", "CMake Files\\");
@@ -175,9 +167,8 @@ void Tree::BuildUnit(cmXMLWriter& xml, const std::string& fsPath) const
xml.EndElement();
}
- for (std::vector<Tree>::const_iterator it = folders.begin();
- it != folders.end(); ++it) {
- it->BuildUnitImpl(xml, "", fsPath);
+ for (Tree const& folder : folders) {
+ folder.BuildUnitImpl(xml, "", fsPath);
}
}
@@ -185,22 +176,20 @@ void Tree::BuildUnitImpl(cmXMLWriter& xml,
const std::string& virtualFolderPath,
const std::string& fsPath) const
{
- for (std::vector<std::string>::const_iterator it = files.begin();
- it != files.end(); ++it) {
+ for (std::string const& f : files) {
xml.StartElement("Unit");
- xml.Attribute("filename", fsPath + path + "/" + *it);
+ xml.Attribute("filename", cmStrCat(fsPath, path, "/", f));
xml.StartElement("Option");
xml.Attribute("virtualFolder",
- "CMake Files\\" + virtualFolderPath + path + "\\");
+ cmStrCat("CMake Files\\", virtualFolderPath, path, "\\"));
xml.EndElement();
xml.EndElement();
}
- for (std::vector<Tree>::const_iterator it = folders.begin();
- it != folders.end(); ++it) {
- it->BuildUnitImpl(xml, virtualFolderPath + path + "\\",
- fsPath + path + "/");
+ for (Tree const& folder : folders) {
+ folder.BuildUnitImpl(xml, cmStrCat(virtualFolderPath, path, "\\"),
+ cmStrCat(fsPath, path, "/"));
}
}
@@ -208,7 +197,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
const std::vector<cmLocalGenerator*>& lgs, const std::string& filename)
{
const cmMakefile* mf = lgs[0]->GetMakefile();
- cmGeneratedFileStream fout(filename.c_str());
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
@@ -216,29 +205,22 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
Tree tree;
// build tree of virtual folders
- for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
- it = this->GlobalGenerator->GetProjectMap().begin();
- it != this->GlobalGenerator->GetProjectMap().end(); ++it) {
+ for (auto const& it : this->GlobalGenerator->GetProjectMap()) {
// Collect all files
std::vector<std::string> listFiles;
- for (std::vector<cmLocalGenerator*>::const_iterator jt =
- it->second.begin();
- jt != it->second.end(); ++jt) {
- const std::vector<std::string>& files =
- (*jt)->GetMakefile()->GetListFiles();
- listFiles.insert(listFiles.end(), files.begin(), files.end());
+ for (cmLocalGenerator* lg : it.second) {
+ cmAppend(listFiles, lg->GetMakefile()->GetListFiles());
}
// Convert
- for (std::vector<std::string>::const_iterator jt = listFiles.begin();
- jt != listFiles.end(); ++jt) {
+ for (std::string const& listFile : listFiles) {
// don't put cmake's own files into the project (#12110):
- if (jt->find(cmSystemTools::GetCMakeRoot()) == 0) {
+ if (listFile.find(cmSystemTools::GetCMakeRoot()) == 0) {
continue;
}
const std::string& relative = cmSystemTools::RelativePath(
- it->second[0]->GetSourceDirectory(), jt->c_str());
+ it.second[0]->GetSourceDirectory(), listFile);
std::vector<std::string> splitted;
cmSystemTools::SplitPath(relative, splitted, false);
// Split filename from path
@@ -248,7 +230,14 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
// We don't want paths with CMakeFiles in them
// or do we?
// In speedcrunch those where purely internal
+ //
+ // Also we can disable external (outside the project) files by setting ON
+ // CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES variable.
+ const bool excludeExternal =
+ cmIsOn(it.second[0]->GetMakefile()->GetSafeDefinition(
+ "CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES"));
if (!splitted.empty() &&
+ (!excludeExternal || (relative.find("..") == std::string::npos)) &&
relative.find("CMakeFiles") == std::string::npos) {
tree.InsertPath(splitted, 1, fileName);
}
@@ -257,8 +246,8 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
// figure out the compiler
std::string compiler = this->GetCBCompilerId(mf);
- std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
- const std::string makeArgs =
+ const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+ const std::string& makeArgs =
mf->GetSafeDefinition("CMAKE_CODEBLOCKS_MAKE_ARGUMENTS");
cmXMLWriter xml(fout);
@@ -289,25 +278,21 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
xml.StartElement("Build");
- this->AppendTarget(xml, "all", CM_NULLPTR, make.c_str(), lgs[0],
- compiler.c_str(), makeArgs);
+ this->AppendTarget(xml, "all", nullptr, make, lgs[0], compiler, makeArgs);
// add all executable and library targets and some of the GLOBAL
// and UTILITY targets
- for (std::vector<cmLocalGenerator*>::const_iterator lg = lgs.begin();
- lg != lgs.end(); lg++) {
- std::vector<cmGeneratorTarget*> targets = (*lg)->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator ti = targets.begin();
- ti != targets.end(); ti++) {
- std::string targetName = (*ti)->GetName();
- switch ((*ti)->GetType()) {
+ for (cmLocalGenerator* lg : lgs) {
+ const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
+ for (cmGeneratorTarget* target : targets) {
+ std::string targetName = target->GetName();
+ switch (target->GetType()) {
case cmStateEnums::GLOBAL_TARGET: {
// Only add the global targets from CMAKE_BINARY_DIR,
// not from the subdirs
- if (strcmp((*lg)->GetCurrentBinaryDirectory(),
- (*lg)->GetBinaryDirectory()) == 0) {
- this->AppendTarget(xml, targetName, CM_NULLPTR, make.c_str(), *lg,
- compiler.c_str(), makeArgs);
+ if (lg->GetCurrentBinaryDirectory() == lg->GetBinaryDirectory()) {
+ this->AppendTarget(xml, targetName, nullptr, make, lg, compiler,
+ makeArgs);
}
} break;
case cmStateEnums::UTILITY:
@@ -322,21 +307,20 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
break;
}
- this->AppendTarget(xml, targetName, CM_NULLPTR, make.c_str(), *lg,
- compiler.c_str(), makeArgs);
+ this->AppendTarget(xml, targetName, nullptr, make, lg, compiler,
+ makeArgs);
break;
case cmStateEnums::EXECUTABLE:
case cmStateEnums::STATIC_LIBRARY:
case cmStateEnums::SHARED_LIBRARY:
case cmStateEnums::MODULE_LIBRARY:
case cmStateEnums::OBJECT_LIBRARY: {
- cmGeneratorTarget* gt = *ti;
- this->AppendTarget(xml, targetName, gt, make.c_str(), *lg,
- compiler.c_str(), makeArgs);
- std::string fastTarget = targetName;
- fastTarget += "/fast";
- this->AppendTarget(xml, fastTarget, gt, make.c_str(), *lg,
- compiler.c_str(), makeArgs);
+ cmGeneratorTarget* gt = target;
+ this->AppendTarget(xml, targetName, gt, make, lg, compiler,
+ makeArgs);
+ std::string fastTarget = cmStrCat(targetName, "/fast");
+ this->AppendTarget(xml, fastTarget, gt, make, lg, compiler,
+ makeArgs);
} break;
default:
break;
@@ -347,22 +331,19 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
xml.EndElement(); // Build
// Collect all used source files in the project.
- // Keep a list of C/C++ source files which might have an acompanying header
+ // Keep a list of C/C++ source files which might have an accompanying header
// that should be looked for.
- typedef std::map<std::string, CbpUnit> all_files_map_t;
+ using all_files_map_t = std::map<std::string, CbpUnit>;
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 (std::vector<cmLocalGenerator*>::const_iterator lg = lgs.begin();
- lg != lgs.end(); lg++) {
- cmMakefile* makefile = (*lg)->GetMakefile();
- std::vector<cmGeneratorTarget*> targets = (*lg)->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator ti = targets.begin();
- ti != targets.end(); ti++) {
- switch ((*ti)->GetType()) {
+ for (cmLocalGenerator* lg : lgs) {
+ cmMakefile* makefile = lg->GetMakefile();
+ const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
+ for (cmGeneratorTarget* target : targets) {
+ switch (target->GetType()) {
case cmStateEnums::EXECUTABLE:
case cmStateEnums::STATIC_LIBRARY:
case cmStateEnums::SHARED_LIBRARY:
@@ -371,41 +352,46 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
case cmStateEnums::UTILITY: // can have sources since 2.6.3
{
std::vector<cmSourceFile*> sources;
- cmGeneratorTarget* gt = *ti;
+ cmGeneratorTarget* gt = target;
gt->GetSourceFiles(sources,
makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
- for (std::vector<cmSourceFile*>::const_iterator si = sources.begin();
- si != sources.end(); si++) {
+ for (cmSourceFile* s : sources) {
// don't add source files from UTILITY target which have the
// GENERATED property set:
if (gt->GetType() == cmStateEnums::UTILITY &&
- (*si)->GetPropertyAsBool("GENERATED")) {
+ s->GetIsGenerated()) {
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 = (*si)->GetLanguage();
- if (lang == "C" || lang == "CXX") {
- std::string const& srcext = (*si)->GetExtension();
- for (std::vector<std::string>::const_iterator ext =
- srcExts.begin();
- ext != srcExts.end(); ++ext) {
- if (srcext == *ext) {
- isCFile = true;
- break;
- }
- }
+ std::string lang = s->GetOrDetermineLanguage();
+ if (lang == "C" || lang == "CXX" || lang == "CUDA") {
+ std::string const& srcext = s->GetExtension();
+ isCFile = cm->IsSourceExtension(srcext);
}
- std::string const& fullPath = (*si)->GetFullPath();
+ std::string const& fullPath = s->ResolveFullPath();
+
+ // Check file position relative to project root dir.
+ 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 =
+ cmIsOn(lg->GetMakefile()->GetSafeDefinition(
+ "CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES"));
+ if (excludeExternal &&
+ (relative.find("..") != std::string::npos)) {
+ continue;
+ }
if (isCFile) {
cFiles.push_back(fullPath);
}
CbpUnit& cbpUnit = allFiles[fullPath];
- cbpUnit.Targets.push_back(*ti);
+ cbpUnit.Targets.push_back(target);
}
}
default: // intended fallthrough
@@ -422,27 +408,22 @@ 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::vector<std::string>::const_iterator sit = cFiles.begin();
- sit != cFiles.end(); ++sit) {
- std::string const& fileName = *sit;
- std::string headerBasename = cmSystemTools::GetFilenamePath(fileName);
- headerBasename += "/";
- headerBasename += cmSystemTools::GetFilenameWithoutExtension(fileName);
+ for (std::string const& fileName : cFiles) {
+ std::string headerBasename =
+ cmStrCat(cmSystemTools::GetFilenamePath(fileName), '/',
+ cmSystemTools::GetFilenameWithoutExtension(fileName));
// check if there's a matching header around
- for (std::vector<std::string>::const_iterator ext = headerExts.begin();
- ext != headerExts.end(); ++ext) {
- std::string hname = headerBasename;
- hname += ".";
- hname += *ext;
+ for (std::string const& ext : headerExts) {
+ std::string hname = cmStrCat(headerBasename, '.', ext);
// if it's already in the set, don't check if it exists on disk
if (allFiles.find(hname) != allFiles.end()) {
break;
}
- if (cmSystemTools::FileExists(hname.c_str())) {
+ if (cmSystemTools::FileExists(hname)) {
allFiles[hname].Targets = allFiles[fileName].Targets;
break;
}
@@ -450,19 +431,16 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
}
// insert all source files in the CodeBlocks project
- for (all_files_map_t::const_iterator sit = allFiles.begin();
- sit != allFiles.end(); ++sit) {
- std::string const& unitFilename = sit->first;
- CbpUnit const& unit = sit->second;
+ for (auto const& s : allFiles) {
+ std::string const& unitFilename = s.first;
+ CbpUnit const& unit = s.second;
xml.StartElement("Unit");
xml.Attribute("filename", unitFilename);
- for (std::vector<const cmGeneratorTarget*>::const_iterator ti =
- unit.Targets.begin();
- ti != unit.Targets.end(); ++ti) {
+ for (cmGeneratorTarget const* tgt : unit.Targets) {
xml.StartElement("Option");
- xml.Attribute("target", (*ti)->GetName());
+ xml.Attribute("target", tgt->GetName());
xml.EndElement();
}
@@ -470,7 +448,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
}
// Add CMakeLists.txt
- tree.BuildUnit(xml, std::string(mf->GetHomeDirectory()) + "/");
+ tree.BuildUnit(xml, mf->GetHomeDirectory() + "/");
xml.EndElement(); // Project
xml.EndElement(); // CodeBlocks_project_file
@@ -484,13 +462,10 @@ std::string cmExtraCodeBlocksGenerator::CreateDummyTargetFile(
// this file doesn't seem to be used by C::B in custom makefile mode,
// but we generate a unique file for each OBJECT library so in case
// C::B uses it in some way, the targets don't interfere with each other.
- std::string filename = lg->GetCurrentBinaryDirectory();
- filename += "/";
- filename += lg->GetTargetDirectory(target);
- filename += "/";
- filename += target->GetName();
- filename += ".objlib";
- cmGeneratedFileStream fout(filename.c_str());
+ std::string filename = cmStrCat(lg->GetCurrentBinaryDirectory(), '/',
+ lg->GetTargetDirectory(target), '/',
+ target->GetName(), ".objlib");
+ cmGeneratedFileStream fout(filename);
if (fout) {
/* clang-format off */
fout << "# This is a dummy file for the OBJECT library "
@@ -505,17 +480,17 @@ std::string cmExtraCodeBlocksGenerator::CreateDummyTargetFile(
// Generate the xml code for one target.
void cmExtraCodeBlocksGenerator::AppendTarget(
cmXMLWriter& xml, const std::string& targetName, cmGeneratorTarget* target,
- const char* make, const cmLocalGenerator* lg, const char* compiler,
- const std::string& makeFlags)
+ const std::string& make, const cmLocalGenerator* lg,
+ const std::string& compiler, const std::string& makeFlags)
{
cmMakefile const* makefile = lg->GetMakefile();
- std::string makefileName = lg->GetCurrentBinaryDirectory();
- makefileName += "/Makefile";
+ std::string makefileName =
+ cmStrCat(lg->GetCurrentBinaryDirectory(), "/Makefile");
xml.StartElement("Target");
xml.Attribute("title", targetName);
- if (target != CM_NULLPTR) {
+ if (target != nullptr) {
int cbTargetType = this->GetCBTargetType(target);
std::string workingDir = lg->GetCurrentBinaryDirectory();
if (target->GetType() == cmStateEnums::EXECUTABLE) {
@@ -523,12 +498,12 @@ void cmExtraCodeBlocksGenerator::AppendTarget(
// set the working directory to this dir.
const char* runtimeOutputDir =
makefile->GetDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY");
- if (runtimeOutputDir != CM_NULLPTR) {
+ if (runtimeOutputDir != nullptr) {
workingDir = runtimeOutputDir;
} else {
const char* executableOutputDir =
makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
- if (executableOutputDir != CM_NULLPTR) {
+ if (executableOutputDir != nullptr) {
workingDir = executableOutputDir;
}
}
@@ -572,45 +547,37 @@ void cmExtraCodeBlocksGenerator::AppendTarget(
target->GetCompileDefinitions(cdefs, buildType, "C");
// Expand the list.
- for (std::vector<std::string>::const_iterator di = cdefs.begin();
- di != cdefs.end(); ++di) {
+ for (std::string const& d : cdefs) {
xml.StartElement("Add");
- xml.Attribute("option", "-D" + *di);
+ xml.Attribute("option", "-D" + d);
xml.EndElement();
}
// the include directories for this target
std::vector<std::string> allIncludeDirs;
-
- std::vector<std::string> includes;
- lg->GetIncludeDirectories(includes, target, "C", buildType);
-
- allIncludeDirs.insert(allIncludeDirs.end(), includes.begin(),
- includes.end());
+ {
+ std::vector<std::string> includes;
+ lg->GetIncludeDirectories(includes, target, "C", buildType);
+ cmAppend(allIncludeDirs, includes);
+ }
std::string systemIncludeDirs = makefile->GetSafeDefinition(
"CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS");
if (!systemIncludeDirs.empty()) {
- std::vector<std::string> dirs;
- cmSystemTools::ExpandListArgument(systemIncludeDirs, dirs);
- allIncludeDirs.insert(allIncludeDirs.end(), dirs.begin(), dirs.end());
+ cmAppend(allIncludeDirs, cmExpandedList(systemIncludeDirs));
}
systemIncludeDirs = makefile->GetSafeDefinition(
"CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS");
if (!systemIncludeDirs.empty()) {
- std::vector<std::string> dirs;
- cmSystemTools::ExpandListArgument(systemIncludeDirs, dirs);
- allIncludeDirs.insert(allIncludeDirs.end(), dirs.begin(), dirs.end());
+ cmAppend(allIncludeDirs, cmExpandedList(systemIncludeDirs));
}
- std::vector<std::string>::const_iterator end =
- cmRemoveDuplicates(allIncludeDirs);
+ auto end = cmRemoveDuplicates(allIncludeDirs);
- for (std::vector<std::string>::const_iterator i = allIncludeDirs.begin();
- i != end; ++i) {
+ for (std::string const& str : cmMakeRange(allIncludeDirs.cbegin(), end)) {
xml.StartElement("Add");
- xml.Attribute("directory", *i);
+ xml.Attribute("directory", str);
xml.EndElement();
}
@@ -629,23 +596,25 @@ void cmExtraCodeBlocksGenerator::AppendTarget(
xml.StartElement("MakeCommands");
xml.StartElement("Build");
- xml.Attribute("command", this->BuildMakeCommand(make, makefileName.c_str(),
- targetName, makeFlags));
+ xml.Attribute(
+ "command",
+ this->BuildMakeCommand(make, makefileName, targetName, makeFlags));
xml.EndElement();
xml.StartElement("CompileFile");
- xml.Attribute("command", this->BuildMakeCommand(make, makefileName.c_str(),
- "\"$file\"", makeFlags));
+ xml.Attribute(
+ "command",
+ this->BuildMakeCommand(make, makefileName, "\"$file\"", makeFlags));
xml.EndElement();
xml.StartElement("Clean");
- xml.Attribute("command", this->BuildMakeCommand(make, makefileName.c_str(),
- "clean", makeFlags));
+ xml.Attribute(
+ "command", this->BuildMakeCommand(make, makefileName, "clean", makeFlags));
xml.EndElement();
xml.StartElement("DistClean");
- xml.Attribute("command", this->BuildMakeCommand(make, makefileName.c_str(),
- "clean", makeFlags));
+ xml.Attribute(
+ "command", this->BuildMakeCommand(make, makefileName, "clean", makeFlags));
xml.EndElement();
xml.EndElement(); // MakeCommands
@@ -655,6 +624,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
@@ -670,7 +646,7 @@ std::string cmExtraCodeBlocksGenerator::GetCBCompilerId(const cmMakefile* mf)
pureFortran = true;
}
- std::string compilerId = mf->GetSafeDefinition(compilerIdVar);
+ std::string const& compilerId = mf->GetSafeDefinition(compilerIdVar);
std::string compiler = "gcc"; // default to gcc
if (compilerId == "MSVC") {
if (mf->IsDefinitionSet("MSVC10")) {
@@ -732,8 +708,8 @@ int cmExtraCodeBlocksGenerator::GetCBTargetType(cmGeneratorTarget* target)
// Create the command line for building the given target using the selected
// make
std::string cmExtraCodeBlocksGenerator::BuildMakeCommand(
- const std::string& make, const char* makefile, const std::string& target,
- const std::string& makeFlags)
+ const std::string& make, const std::string& makefile,
+ const std::string& target, const std::string& makeFlags)
{
std::string command = make;
if (!makeFlags.empty()) {
@@ -754,7 +730,7 @@ std::string cmExtraCodeBlocksGenerator::BuildMakeCommand(
} else if (generator == "MinGW Makefiles") {
// no escaping of spaces in this case, see
// https://gitlab.kitware.com/cmake/cmake/issues/10014
- std::string makefileName = makefile;
+ std::string const& makefileName = makefile;
command += " -f \"";
command += makefileName;
command += "\" ";
diff --git a/Source/cmExtraCodeBlocksGenerator.h b/Source/cmExtraCodeBlocksGenerator.h
index 450a9d02c..d9f92bde5 100644
--- a/Source/cmExtraCodeBlocksGenerator.h
+++ b/Source/cmExtraCodeBlocksGenerator.h
@@ -3,13 +3,13 @@
#ifndef cmExtraCodeBlocksGenerator_h
#define cmExtraCodeBlocksGenerator_h
-#include "cmConfigure.h"
-
-#include "cmExternalMakefileProjectGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
+#include "cmExternalMakefileProjectGenerator.h"
+
class cmGeneratorTarget;
class cmLocalGenerator;
class cmMakefile;
@@ -25,7 +25,7 @@ public:
static cmExternalMakefileProjectGeneratorFactory* GetFactory();
- void Generate() CM_OVERRIDE;
+ void Generate() override;
private:
struct CbpUnit
@@ -42,12 +42,13 @@ private:
std::string GetCBCompilerId(const cmMakefile* mf);
int GetCBTargetType(cmGeneratorTarget* target);
- std::string BuildMakeCommand(const std::string& make, const char* makefile,
+ std::string BuildMakeCommand(const std::string& make,
+ const std::string& makefile,
const std::string& target,
const std::string& makeFlags);
void AppendTarget(cmXMLWriter& xml, const std::string& targetName,
- cmGeneratorTarget* target, const char* make,
- const cmLocalGenerator* lg, const char* compiler,
+ cmGeneratorTarget* target, const std::string& make,
+ const cmLocalGenerator* lg, const std::string& compiler,
const std::string& makeFlags);
};
diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx
index b478f34fa..c7b74570f 100644
--- a/Source/cmExtraCodeLiteGenerator.cxx
+++ b/Source/cmExtraCodeLiteGenerator.cxx
@@ -2,6 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExtraCodeLiteGenerator.h"
+#include <cstring>
+#include <map>
+#include <set>
+#include <sstream>
+#include <utility>
+
+#include "cmsys/SystemInformation.hxx"
+
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -9,21 +17,13 @@
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLWriter.h"
#include "cmake.h"
-#include "cmsys/SystemInformation.hxx"
-#include <map>
-#include <set>
-#include <sstream>
-#include <string.h>
-#include <utility>
-
cmExtraCodeLiteGenerator::cmExtraCodeLiteGenerator()
- : cmExternalMakefileProjectGenerator()
- , ConfigName("NoConfig")
- , CpuCount(2)
+ : ConfigName("NoConfig")
{
}
@@ -54,32 +54,29 @@ void cmExtraCodeLiteGenerator::Generate()
std::string workspaceFileName;
std::string workspaceSourcePath;
- const std::map<std::string, std::vector<cmLocalGenerator*> >& projectMap =
+ const std::map<std::string, std::vector<cmLocalGenerator*>>& projectMap =
this->GlobalGenerator->GetProjectMap();
// loop projects and locate the root project.
// and extract the information for creating the worspace
// root makefile
- for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
- it = projectMap.begin();
- it != projectMap.end(); ++it) {
- const cmMakefile* mf = it->second[0]->GetMakefile();
+ for (auto const& it : projectMap) {
+ cmLocalGenerator* lg = it.second[0];
+ const cmMakefile* mf = lg->GetMakefile();
this->ConfigName = GetConfigurationName(mf);
- if (strcmp(it->second[0]->GetCurrentBinaryDirectory(),
- it->second[0]->GetBinaryDirectory()) == 0) {
- workspaceOutputDir = it->second[0]->GetCurrentBinaryDirectory();
- workspaceProjectName = it->second[0]->GetProjectName();
- workspaceSourcePath = it->second[0]->GetSourceDirectory();
- workspaceFileName = workspaceOutputDir + "/";
- workspaceFileName += workspaceProjectName + ".workspace";
- this->WorkspacePath = it->second[0]->GetCurrentBinaryDirectory();
- ;
+ if (lg->GetCurrentBinaryDirectory() == lg->GetBinaryDirectory()) {
+ workspaceOutputDir = lg->GetCurrentBinaryDirectory();
+ workspaceProjectName = lg->GetProjectName();
+ workspaceSourcePath = lg->GetSourceDirectory();
+ workspaceFileName =
+ cmStrCat(workspaceOutputDir, '/', workspaceProjectName, ".workspace");
+ this->WorkspacePath = lg->GetCurrentBinaryDirectory();
break;
}
}
- cmGeneratedFileStream fout(workspaceFileName.c_str());
+ cmGeneratedFileStream fout(workspaceFileName);
cmXMLWriter xml(fout);
xml.StartDocument("utf-8");
@@ -101,10 +98,9 @@ void cmExtraCodeLiteGenerator::Generate()
xml.Attribute("Name", this->ConfigName);
xml.Attribute("Selected", "yes");
- for (std::vector<std::string>::iterator it(ProjectNames.begin());
- it != ProjectNames.end(); it++) {
+ for (std::string const& it : ProjectNames) {
xml.StartElement("Project");
- xml.Attribute("Name", *it);
+ xml.Attribute("Name", it);
xml.Attribute("ConfigName", this->ConfigName);
xml.EndElement();
}
@@ -122,25 +118,22 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget(
// for each target in the workspace create a codelite project
const std::vector<cmLocalGenerator*>& lgs =
this->GlobalGenerator->GetLocalGenerators();
- for (std::vector<cmLocalGenerator*>::const_iterator lg(lgs.begin());
- lg != lgs.end(); lg++) {
- for (std::vector<cmGeneratorTarget*>::const_iterator lt =
- (*lg)->GetGeneratorTargets().begin();
- lt != (*lg)->GetGeneratorTargets().end(); lt++) {
- cmStateEnums::TargetType type = (*lt)->GetType();
- std::string outputDir = (*lg)->GetCurrentBinaryDirectory();
- std::string targetName = (*lt)->GetName();
- std::string filename = outputDir + "/" + targetName + ".project";
+ for (cmLocalGenerator* lg : lgs) {
+ for (cmGeneratorTarget* lt : lg->GetGeneratorTargets()) {
+ cmStateEnums::TargetType type = lt->GetType();
+ std::string const& outputDir = lg->GetCurrentBinaryDirectory();
+ std::string targetName = lt->GetName();
+ std::string filename = cmStrCat(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:
case cmStateEnums::STATIC_LIBRARY:
case cmStateEnums::MODULE_LIBRARY:
- visualname = "lib" + visualname;
+ visualname = cmStrCat("lib", visualname);
CM_FALLTHROUGH;
case cmStateEnums::EXECUTABLE:
xml->StartElement("Project");
@@ -149,7 +142,7 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget(
xml->Attribute("Active", "No");
xml->EndElement();
- CreateNewProjectFile(*lt, filename);
+ CreateNewProjectFile(lt, filename);
break;
default:
break;
@@ -165,21 +158,18 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByProjectMaps(
{
std::vector<std::string> retval;
// for each sub project in the workspace create a codelite project
- for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
- it = this->GlobalGenerator->GetProjectMap().begin();
- it != this->GlobalGenerator->GetProjectMap().end(); it++) {
+ for (auto const& it : this->GlobalGenerator->GetProjectMap()) {
- std::string outputDir = it->second[0]->GetCurrentBinaryDirectory();
- std::string projectName = it->second[0]->GetProjectName();
+ std::string const& outputDir = it.second[0]->GetCurrentBinaryDirectory();
+ std::string projectName = it.second[0]->GetProjectName();
retval.push_back(projectName);
- std::string filename = outputDir + "/" + projectName + ".project";
+ std::string filename = cmStrCat(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);
+ this->CreateProjectFile(it.second);
xml->StartElement("Project");
xml->Attribute("Name", projectName);
xml->Attribute("Path", filename);
@@ -193,7 +183,7 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByProjectMaps(
void cmExtraCodeLiteGenerator::CreateProjectFile(
const std::vector<cmLocalGenerator*>& lgs)
{
- std::string outputDir = lgs[0]->GetCurrentBinaryDirectory();
+ std::string const& outputDir = lgs[0]->GetCurrentBinaryDirectory();
std::string projectName = lgs[0]->GetProjectName();
std::string filename = outputDir + "/";
@@ -206,9 +196,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: {
@@ -232,30 +219,21 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles(
case cmStateEnums::STATIC_LIBRARY:
case cmStateEnums::SHARED_LIBRARY:
case cmStateEnums::MODULE_LIBRARY: {
+ cmake const* cm = makefile->GetCMakeInstance();
std::vector<cmSourceFile*> sources;
gt->GetSourceFiles(sources,
makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
- for (std::vector<cmSourceFile*>::const_iterator si = sources.begin();
- si != sources.end(); si++) {
- // check whether it is a C/C++ implementation file
- bool isCFile = false;
- std::string lang = (*si)->GetLanguage();
- if (lang == "C" || lang == "CXX") {
- std::string const& srcext = (*si)->GetExtension();
- for (std::vector<std::string>::const_iterator ext = srcExts.begin();
- ext != srcExts.end(); ++ext) {
- if (srcext == *ext) {
- isCFile = true;
- break;
- }
- }
- }
-
+ for (cmSourceFile* s : sources) {
+ std::string const& fullPath = s->ResolveFullPath();
+ std::string const& extLower =
+ cmSystemTools::LowerCase(s->GetExtension());
+ // check whether it is a source or a include file
// then put it accordingly into one of the two containers
- if (isCFile) {
- cFiles[(*si)->GetFullPath()] = *si;
+ if (cm->IsSourceExtension(extLower) || cm->IsCudaExtension(extLower) ||
+ cm->IsFortranExtension(extLower)) {
+ cFiles[fullPath] = s;
} else {
- otherFiles.insert((*si)->GetFullPath());
+ otherFiles.insert(fullPath);
}
}
}
@@ -269,7 +247,7 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile(
const std::vector<cmLocalGenerator*>& lgs, const std::string& filename)
{
const cmMakefile* mf = lgs[0]->GetMakefile();
- cmGeneratedFileStream fout(filename.c_str());
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
@@ -285,17 +263,15 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile(
// Collect all used source files in the project
// Sort them into two containers, one for C/C++ implementation files
- // which may have an acompanying header, one for all other files
+ // which may have an accompanying header, one for all other files
std::map<std::string, cmSourceFile*> cFiles;
std::set<std::string> otherFiles;
- for (std::vector<cmLocalGenerator*>::const_iterator lg = lgs.begin();
- lg != lgs.end(); lg++) {
- cmMakefile* makefile = (*lg)->GetMakefile();
- std::vector<cmGeneratorTarget*> targets = (*lg)->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator ti = targets.begin();
- ti != targets.end(); ti++) {
- projectType = CollectSourceFiles(makefile, *ti, cFiles, otherFiles);
+ for (cmLocalGenerator* lg : lgs) {
+ cmMakefile* makefile = lg->GetMakefile();
+ const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
+ for (cmGeneratorTarget* target : targets) {
+ projectType = CollectSourceFiles(makefile, target, cFiles, otherFiles);
}
}
@@ -321,28 +297,23 @@ 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 (std::map<std::string, cmSourceFile*>::const_iterator sit =
- cFiles.begin();
- sit != cFiles.end(); ++sit) {
- std::string headerBasename = cmSystemTools::GetFilenamePath(sit->first);
- headerBasename += "/";
- headerBasename += cmSystemTools::GetFilenameWithoutExtension(sit->first);
+ for (auto const& sit : cFiles) {
+ std::string headerBasename =
+ cmStrCat(cmSystemTools::GetFilenamePath(sit.first), '/',
+ cmSystemTools::GetFilenameWithoutExtension(sit.first));
// check if there's a matching header around
- for (std::vector<std::string>::const_iterator ext = headerExts.begin();
- ext != headerExts.end(); ++ext) {
- std::string hname = headerBasename;
- hname += ".";
- hname += *ext;
+ for (std::string const& ext : headerExts) {
+ std::string hname = cmStrCat(headerBasename, '.', ext);
// if it's already in the set, don't check if it exists on disk
- std::set<std::string>::const_iterator headerIt = otherFiles.find(hname);
+ auto headerIt = otherFiles.find(hname);
if (headerIt != otherFiles.end()) {
break;
}
- if (cmSystemTools::FileExists(hname.c_str())) {
+ if (cmSystemTools::FileExists(hname)) {
otherFiles.insert(hname);
break;
}
@@ -358,10 +329,8 @@ void cmExtraCodeLiteGenerator::CreateFoldersAndFiles(
std::vector<std::string> components;
size_t numOfEndEl = 0;
- for (std::set<std::string>::const_iterator it = cFiles.begin();
- it != cFiles.end(); ++it) {
- std::string frelapath =
- cmSystemTools::RelativePath(projectPath.c_str(), it->c_str());
+ for (std::string const& cFile : cFiles) {
+ 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"
@@ -423,10 +392,8 @@ void cmExtraCodeLiteGenerator::CreateFoldersAndFiles(
const std::string& projectPath)
{
std::set<std::string> s;
- for (std::map<std::string, cmSourceFile*>::const_iterator it =
- cFiles.begin();
- it != cFiles.end(); ++it) {
- s.insert(it->first);
+ for (auto const& it : cFiles) {
+ s.insert(it.first);
}
this->CreateFoldersAndFiles(s, xml, projectPath);
}
@@ -437,7 +404,6 @@ void cmExtraCodeLiteGenerator::CreateProjectSourceEntries(
const std::string& projectPath, const cmMakefile* mf,
const std::string& projectType, const std::string& targetName)
{
-
cmXMLWriter& xml(*_xml);
FindMatchingHeaderfiles(cFiles, otherFiles);
// Create 2 virtual folders: src and include
@@ -498,11 +464,14 @@ void cmExtraCodeLiteGenerator::CreateProjectSourceEntries(
xml.EndElement(); // ResourceCompiler
xml.StartElement("General");
- std::string outputPath = mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
+ std::string outputPath =
+ mf->GetSafeDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY");
+ if (outputPath.empty()) {
+ 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(projectPath, outputPath);
xml.Attribute("OutputFile", relapath + "/$(ProjectName)");
} else {
xml.Attribute("OutputFile", "$(IntermediateDirectory)/$(ProjectName)");
@@ -574,7 +543,7 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile(
const cmGeneratorTarget* gt, const std::string& filename)
{
const cmMakefile* mf = gt->Makefile;
- cmGeneratedFileStream fout(filename.c_str());
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
@@ -598,7 +567,7 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile(
// Collect all used source files in the project
// Sort them into two containers, one for C/C++ implementation files
- // which may have an acompanying header, one for all other files
+ // which may have an accompanying header, one for all other files
std::string projectType;
std::map<std::string, cmSourceFile*> cFiles;
@@ -626,7 +595,7 @@ std::string cmExtraCodeLiteGenerator::GetCodeLiteCompilerName(
compilerIdVar = "CMAKE_C_COMPILER_ID";
}
- std::string compilerId = mf->GetSafeDefinition(compilerIdVar);
+ std::string const& compilerId = mf->GetSafeDefinition(compilerIdVar);
std::string compiler = "gnu g++"; // default to g++
// Since we need the compiler for parsing purposes only
@@ -658,14 +627,14 @@ std::string cmExtraCodeLiteGenerator::GetConfigurationName(
std::string cmExtraCodeLiteGenerator::GetBuildCommand(
const cmMakefile* mf, const std::string& targetName) const
{
- std::string generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
- std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+ const std::string& generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
+ const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
std::string buildCommand = make; // Default
std::ostringstream ss;
if (generator == "NMake Makefiles" || generator == "Ninja") {
ss << make;
} else if (generator == "MinGW Makefiles" || generator == "Unix Makefiles") {
- ss << make << " -j " << this->CpuCount;
+ ss << make << " -f$(ProjectPath)/Makefile -j " << this->CpuCount;
}
if (!targetName.empty()) {
ss << " " << targetName;
@@ -699,11 +668,15 @@ std::string cmExtraCodeLiteGenerator::GetSingleFileBuildCommand(
const cmMakefile* mf) const
{
std::string buildCommand;
- std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
- std::string generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
+ const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+ const 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/cmExtraCodeLiteGenerator.h b/Source/cmExtraCodeLiteGenerator.h
index de330988d..0ce90b093 100644
--- a/Source/cmExtraCodeLiteGenerator.h
+++ b/Source/cmExtraCodeLiteGenerator.h
@@ -3,15 +3,15 @@
#ifndef cmGlobalCodeLiteGenerator_h
#define cmGlobalCodeLiteGenerator_h
-#include "cmConfigure.h"
-
-#include "cmExternalMakefileProjectGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
#include <set>
#include <string>
#include <vector>
+#include "cmExternalMakefileProjectGenerator.h"
+
class cmLocalGenerator;
class cmMakefile;
class cmGeneratorTarget;
@@ -23,7 +23,7 @@ class cmExtraCodeLiteGenerator : public cmExternalMakefileProjectGenerator
protected:
std::string ConfigName;
std::string WorkspacePath;
- unsigned int CpuCount;
+ unsigned int CpuCount = 2;
protected:
std::string GetCodeLiteCompilerName(const cmMakefile* mf) const;
@@ -60,7 +60,7 @@ public:
static cmExternalMakefileProjectGeneratorFactory* GetFactory();
- void Generate() CM_OVERRIDE;
+ void Generate() override;
void CreateProjectFile(const std::vector<cmLocalGenerator*>& lgs);
void CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index 2a6ce98a7..b286acf0c 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -2,24 +2,27 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExtraEclipseCDT4Generator.h"
-#include "cmsys/RegularExpression.hxx"
#include <algorithm>
-#include <assert.h>
+#include <cassert>
+#include <cstdio>
#include <map>
#include <sstream>
-#include <stdio.h>
#include <utility>
+#include "cmsys/RegularExpression.hxx"
+
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmSourceFile.h"
#include "cmSourceGroup.h"
#include "cmState.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLWriter.h"
#include "cmake.h"
@@ -42,8 +45,9 @@ void AppendDictionary(cmXMLWriter& xml, const char* key, T const& value)
}
cmExtraEclipseCDT4Generator::cmExtraEclipseCDT4Generator()
- : cmExternalMakefileProjectGenerator()
{
+ this->IsOutOfSourceBuild = false;
+ this->GenerateSourceProject = false;
this->SupportsVirtualFolders = true;
this->GenerateLinkedResources = true;
this->SupportsGmakeErrorParser = true;
@@ -78,16 +82,15 @@ void cmExtraEclipseCDT4Generator::EnableLanguage(
std::vector<std::string> const& languages, cmMakefile* /*unused*/,
bool /*optional*/)
{
- for (std::vector<std::string>::const_iterator lit = languages.begin();
- lit != languages.end(); ++lit) {
- if (*lit == "CXX") {
+ for (std::string const& l : languages) {
+ if (l == "CXX") {
this->Natures.insert("org.eclipse.cdt.core.ccnature");
this->Natures.insert("org.eclipse.cdt.core.cnature");
this->CXXEnabled = true;
- } else if (*lit == "C") {
+ } else if (l == "C") {
this->Natures.insert("org.eclipse.cdt.core.cnature");
this->CEnabled = true;
- } else if (*lit == "Java") {
+ } else if (l == "Java") {
this->Natures.insert("org.eclipse.jdt.core.javanature");
}
}
@@ -100,7 +103,7 @@ void cmExtraEclipseCDT4Generator::Generate()
std::string eclipseVersion = mf->GetSafeDefinition("CMAKE_ECLIPSE_VERSION");
cmsys::RegularExpression regex(".*([0-9]+\\.[0-9]+).*");
- if (regex.find(eclipseVersion.c_str())) {
+ if (regex.find(eclipseVersion)) {
unsigned int majorVersion = 0;
unsigned int minorVersion = 0;
int res =
@@ -136,7 +139,7 @@ void cmExtraEclipseCDT4Generator::Generate()
if (!this->GenerateSourceProject &&
(mf->IsOn("ECLIPSE_CDT4_GENERATE_SOURCE_PROJECT"))) {
mf->IssueMessage(
- cmake::WARNING,
+ MessageType::WARNING,
"ECLIPSE_CDT4_GENERATE_SOURCE_PROJECT is set to TRUE, "
"but this variable is not supported anymore since CMake 2.8.7.\n"
"Enable CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT instead.");
@@ -144,7 +147,7 @@ void cmExtraEclipseCDT4Generator::Generate()
if (cmSystemTools::IsSubDirectory(this->HomeOutputDirectory,
this->HomeDirectory)) {
- mf->IssueMessage(cmake::WARNING,
+ mf->IssueMessage(MessageType::WARNING,
"The build directory is a subdirectory "
"of the source directory.\n"
"This is not supported well by Eclipse. It is strongly "
@@ -165,6 +168,29 @@ void cmExtraEclipseCDT4Generator::Generate()
// create a .cproject file
this->CreateCProjectFile();
+
+ // create resource settings
+ this->CreateSettingsResourcePrefsFile();
+}
+
+void cmExtraEclipseCDT4Generator::CreateSettingsResourcePrefsFile()
+{
+ cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0];
+ cmMakefile* mf = lg->GetMakefile();
+
+ const std::string filename =
+ this->HomeOutputDirectory + "/.settings/org.eclipse.core.resources.prefs";
+
+ cmGeneratedFileStream fout(filename);
+ if (!fout) {
+ return;
+ }
+
+ fout << "eclipse.preferences.version=1" << std::endl;
+ const char* encoding = mf->GetDefinition("CMAKE_ECLIPSE_RESOURCE_ENCODING");
+ if (encoding) {
+ fout << "encoding/<project>=" << encoding << std::endl;
+ }
}
void cmExtraEclipseCDT4Generator::CreateSourceProjectFile()
@@ -173,12 +199,12 @@ void cmExtraEclipseCDT4Generator::CreateSourceProjectFile()
// set up the project name: <project>-Source@<baseSourcePathName>
cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0];
- std::string name =
- this->GenerateProjectName(lg->GetProjectName(), "Source",
- this->GetPathBasename(this->HomeDirectory));
+ std::string name = cmExtraEclipseCDT4Generator::GenerateProjectName(
+ lg->GetProjectName(), "Source",
+ cmExtraEclipseCDT4Generator::GetPathBasename(this->HomeDirectory));
const std::string filename = this->HomeDirectory + "/.project";
- cmGeneratedFileStream fout(filename.c_str());
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
@@ -215,33 +241,32 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out,
std::string envVarValue;
const bool envVarSet = cmSystemTools::GetEnv(envVar, envVarValue);
- std::string cacheEntryName = "CMAKE_ECLIPSE_ENVVAR_";
- cacheEntryName += envVar;
- const char* cacheValue =
+ std::string cacheEntryName = cmStrCat("CMAKE_ECLIPSE_ENVVAR_", envVar);
+ const std::string* cacheValue =
lg->GetState()->GetInitializedCacheValue(cacheEntryName);
// now we have both, decide which one to use
std::string valueToUse;
- if (!envVarSet && cacheValue == CM_NULLPTR) {
+ if (!envVarSet && cacheValue == nullptr) {
// nothing known, do nothing
- valueToUse = "";
- } else if (envVarSet && cacheValue == CM_NULLPTR) {
+ valueToUse.clear();
+ } else if (envVarSet && cacheValue == nullptr) {
// The variable is in the env, but not in the cache. Use it and put it
// in the cache
valueToUse = envVarValue;
mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(),
cacheEntryName.c_str(), cmStateEnums::STRING, true);
mf->GetCMakeInstance()->SaveCache(lg->GetBinaryDirectory());
- } else if (!envVarSet && cacheValue != CM_NULLPTR) {
+ } else if (!envVarSet && cacheValue != nullptr) {
// It is already in the cache, but not in the env, so use it from the cache
- valueToUse = cacheValue;
+ valueToUse = *cacheValue;
} else {
// It is both in the cache and in the env.
// Use the version from the env. except if the value from the env is
// completely contained in the value from the cache (for the case that we
// now have a PATH without MSVC dirs in the env. but had the full PATH with
// all MSVC dirs during the cmake run which stored the var in the cache:
- valueToUse = cacheValue;
+ valueToUse = *cacheValue;
if (valueToUse.find(envVarValue) == std::string::npos) {
valueToUse = envVarValue;
mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(),
@@ -263,7 +288,7 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile()
const std::string filename = this->HomeOutputDirectory + "/.project";
- cmGeneratedFileStream fout(filename.c_str());
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
@@ -279,10 +304,12 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile()
xml.StartDocument("UTF-8");
xml.StartElement("projectDescription");
- xml.Element("name", this->GenerateProjectName(
- lg->GetProjectName(),
- mf->GetSafeDefinition("CMAKE_BUILD_TYPE"),
- this->GetPathBasename(this->HomeOutputDirectory)));
+ xml.Element("name",
+ cmExtraEclipseCDT4Generator::GenerateProjectName(
+ lg->GetProjectName(),
+ mf->GetSafeDefinition("CMAKE_BUILD_TYPE"),
+ cmExtraEclipseCDT4Generator::GetPathBasename(
+ this->HomeOutputDirectory)));
xml.Element("comment", "");
xml.Element("projects", "");
@@ -303,16 +330,17 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile()
// set the make command
AppendDictionary(xml, "org.eclipse.cdt.make.core.enabledIncrementalBuild",
"true");
- AppendDictionary(
- xml, "org.eclipse.cdt.make.core.build.command",
- this->GetEclipsePath(mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM")));
+ AppendDictionary(xml, "org.eclipse.cdt.make.core.build.command",
+ cmExtraEclipseCDT4Generator::GetEclipsePath(
+ mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM")));
AppendDictionary(xml, "org.eclipse.cdt.make.core.contents",
"org.eclipse.cdt.make.core.activeConfigSettings");
AppendDictionary(xml, "org.eclipse.cdt.make.core.build.target.inc", "all");
AppendDictionary(xml, "org.eclipse.cdt.make.core.build.arguments",
mf->GetSafeDefinition("CMAKE_ECLIPSE_MAKE_ARGUMENTS"));
- AppendDictionary(xml, "org.eclipse.cdt.make.core.buildLocation",
- this->GetEclipsePath(this->HomeOutputDirectory));
+ AppendDictionary(
+ xml, "org.eclipse.cdt.make.core.buildLocation",
+ cmExtraEclipseCDT4Generator::GetEclipsePath(this->HomeOutputDirectory));
AppendDictionary(xml, "org.eclipse.cdt.make.core.useDefaultBuildCmd",
"false");
@@ -342,8 +370,9 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile()
"clean");
AppendDictionary(xml, "org.eclipse.cdt.make.core.fullBuildTarget", "all");
AppendDictionary(xml, "org.eclipse.cdt.make.core.buildArguments", "");
- AppendDictionary(xml, "org.eclipse.cdt.make.core.build.location",
- this->GetEclipsePath(this->HomeOutputDirectory));
+ AppendDictionary(
+ xml, "org.eclipse.cdt.make.core.build.location",
+ cmExtraEclipseCDT4Generator::GetEclipsePath(this->HomeOutputDirectory));
AppendDictionary(xml, "org.eclipse.cdt.make.core.autoBuildTarget", "all");
// set error parsers
@@ -380,20 +409,16 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile()
xml.StartElement("natures");
xml.Element("nature", "org.eclipse.cdt.make.core.makeNature");
xml.Element("nature", "org.eclipse.cdt.make.core.ScannerConfigNature");
- ;
- for (std::set<std::string>::const_iterator nit = this->Natures.begin();
- nit != this->Natures.end(); ++nit) {
- xml.Element("nature", *nit);
+ for (std::string const& n : this->Natures) {
+ xml.Element("nature", n);
}
if (const char* extraNaturesProp =
mf->GetState()->GetGlobalProperty("ECLIPSE_EXTRA_NATURES")) {
- std::vector<std::string> extraNatures;
- cmSystemTools::ExpandListArgument(extraNaturesProp, extraNatures);
- for (std::vector<std::string>::const_iterator nit = extraNatures.begin();
- nit != extraNatures.end(); ++nit) {
- xml.Element("nature", *nit);
+ std::vector<std::string> extraNatures = cmExpandedList(extraNaturesProp);
+ for (std::string const& n : extraNatures) {
+ xml.Element("nature", n);
}
}
@@ -410,14 +435,16 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile()
std::string sourceLinkedResourceName = "[Source directory]";
std::string linkSourceDirectory =
- this->GetEclipsePath(lg->GetCurrentSourceDirectory());
+ cmExtraEclipseCDT4Generator::GetEclipsePath(
+ lg->GetCurrentSourceDirectory());
// .project dir can't be subdir of a linked resource dir
if (!cmSystemTools::IsSubDirectory(this->HomeOutputDirectory,
linkSourceDirectory)) {
- this->AppendLinkedResource(xml, sourceLinkedResourceName,
- this->GetEclipsePath(linkSourceDirectory),
- LinkToFolder);
- this->SrcLinkedResources.push_back(sourceLinkedResourceName);
+ cmExtraEclipseCDT4Generator::AppendLinkedResource(
+ xml, sourceLinkedResourceName,
+ cmExtraEclipseCDT4Generator::GetEclipsePath(linkSourceDirectory),
+ LinkToFolder);
+ this->SrcLinkedResources.push_back(std::move(sourceLinkedResourceName));
}
}
@@ -435,32 +462,27 @@ void cmExtraEclipseCDT4Generator::WriteGroups(
std::vector<cmSourceGroup> const& sourceGroups, std::string& linkName,
cmXMLWriter& xml)
{
- for (std::vector<cmSourceGroup>::const_iterator sgIt = sourceGroups.begin();
- sgIt != sourceGroups.end(); ++sgIt) {
- std::string linkName3 = linkName;
- linkName3 += "/";
- linkName3 += sgIt->GetFullName();
+ for (cmSourceGroup const& sg : sourceGroups) {
+ std::string linkName3 = cmStrCat(linkName, '/', sg.GetFullName());
std::replace(linkName3.begin(), linkName3.end(), '\\', '/');
- this->AppendLinkedResource(xml, linkName3, "virtual:/virtual",
- VirtualFolder);
- std::vector<cmSourceGroup> const& children = sgIt->GetGroupChildren();
+ cmExtraEclipseCDT4Generator::AppendLinkedResource(
+ xml, linkName3, "virtual:/virtual", VirtualFolder);
+ std::vector<cmSourceGroup> const& children = sg.GetGroupChildren();
if (!children.empty()) {
this->WriteGroups(children, linkName, xml);
}
- std::vector<const cmSourceFile*> sFiles = sgIt->GetSourceFiles();
- for (std::vector<const cmSourceFile*>::const_iterator fileIt =
- sFiles.begin();
- fileIt != sFiles.end(); ++fileIt) {
- std::string const& fullPath = (*fileIt)->GetFullPath();
+ std::vector<const cmSourceFile*> sFiles = sg.GetSourceFiles();
+ for (cmSourceFile const* file : sFiles) {
+ std::string const& fullPath = file->GetFullPath();
if (!cmSystemTools::FileIsDirectory(fullPath)) {
- std::string linkName4 = linkName3;
- linkName4 += "/";
- linkName4 += cmSystemTools::GetFilenameName(fullPath);
- this->AppendLinkedResource(xml, linkName4,
- this->GetEclipsePath(fullPath), LinkToFile);
+ std::string linkName4 =
+ cmStrCat(linkName3, '/', cmSystemTools::GetFilenameName(fullPath));
+ cmExtraEclipseCDT4Generator::AppendLinkedResource(
+ xml, linkName4,
+ cmExtraEclipseCDT4Generator::GetEclipsePath(fullPath), LinkToFile);
}
}
}
@@ -469,49 +491,44 @@ void cmExtraEclipseCDT4Generator::WriteGroups(
void cmExtraEclipseCDT4Generator::CreateLinksForTargets(cmXMLWriter& xml)
{
std::string linkName = "[Targets]";
- this->AppendLinkedResource(xml, linkName, "virtual:/virtual", VirtualFolder);
-
- for (std::vector<cmLocalGenerator*>::const_iterator lgIt =
- this->GlobalGenerator->GetLocalGenerators().begin();
- lgIt != this->GlobalGenerator->GetLocalGenerators().end(); ++lgIt) {
- cmMakefile* makefile = (*lgIt)->GetMakefile();
- const std::vector<cmGeneratorTarget*> targets =
- (*lgIt)->GetGeneratorTargets();
-
- for (std::vector<cmGeneratorTarget*>::const_iterator ti = targets.begin();
- ti != targets.end(); ++ti) {
- std::string linkName2 = linkName;
- linkName2 += "/";
- switch ((*ti)->GetType()) {
+ cmExtraEclipseCDT4Generator::AppendLinkedResource(
+ xml, linkName, "virtual:/virtual", VirtualFolder);
+
+ for (cmLocalGenerator* lg : this->GlobalGenerator->GetLocalGenerators()) {
+ cmMakefile* makefile = lg->GetMakefile();
+ const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
+
+ for (cmGeneratorTarget* target : targets) {
+ std::string linkName2 = cmStrCat(linkName, '/');
+ switch (target->GetType()) {
case cmStateEnums::EXECUTABLE:
case cmStateEnums::STATIC_LIBRARY:
case cmStateEnums::SHARED_LIBRARY:
case cmStateEnums::MODULE_LIBRARY:
case cmStateEnums::OBJECT_LIBRARY: {
const char* prefix =
- ((*ti)->GetType() == cmStateEnums::EXECUTABLE ? "[exe] "
- : "[lib] ");
+ (target->GetType() == cmStateEnums::EXECUTABLE ? "[exe] "
+ : "[lib] ");
linkName2 += prefix;
- linkName2 += (*ti)->GetName();
- this->AppendLinkedResource(xml, linkName2, "virtual:/virtual",
- VirtualFolder);
+ linkName2 += target->GetName();
+ cmExtraEclipseCDT4Generator::AppendLinkedResource(
+ xml, linkName2, "virtual:/virtual", VirtualFolder);
if (!this->GenerateLinkedResources) {
break; // skip generating the linked resources to the source files
}
std::vector<cmSourceGroup> sourceGroups =
makefile->GetSourceGroups();
// get the files from the source lists then add them to the groups
- cmGeneratorTarget* gt = const_cast<cmGeneratorTarget*>(*ti);
+ cmGeneratorTarget* gt = const_cast<cmGeneratorTarget*>(target);
std::vector<cmSourceFile*> files;
gt->GetSourceFiles(files,
makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
- for (std::vector<cmSourceFile*>::const_iterator sfIt = files.begin();
- sfIt != files.end(); sfIt++) {
+ for (cmSourceFile* sf : files) {
// Add the file to the list of sources.
- std::string const& source = (*sfIt)->GetFullPath();
+ std::string const& source = sf->ResolveFullPath();
cmSourceGroup* sourceGroup =
- makefile->FindSourceGroup(source.c_str(), sourceGroups);
- sourceGroup->AssignSource(*sfIt);
+ makefile->FindSourceGroup(source, sourceGroups);
+ sourceGroup->AssignSource(sf);
}
this->WriteGroups(sourceGroups, linkName2, xml);
@@ -533,23 +550,22 @@ void cmExtraEclipseCDT4Generator::CreateLinksToSubprojects(
// for each sub project create a linked resource to the source dir
// - only if it is an out-of-source build
- this->AppendLinkedResource(xml, "[Subprojects]", "virtual:/virtual",
- VirtualFolder);
+ cmExtraEclipseCDT4Generator::AppendLinkedResource(
+ xml, "[Subprojects]", "virtual:/virtual", VirtualFolder);
- for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
- it = this->GlobalGenerator->GetProjectMap().begin();
- it != this->GlobalGenerator->GetProjectMap().end(); ++it) {
+ for (auto const& it : this->GlobalGenerator->GetProjectMap()) {
std::string linkSourceDirectory =
- this->GetEclipsePath(it->second[0]->GetCurrentSourceDirectory());
+ cmExtraEclipseCDT4Generator::GetEclipsePath(
+ it.second[0]->GetCurrentSourceDirectory());
// a linked resource must not point to a parent directory of .project or
// .project itself
if ((baseDir != linkSourceDirectory) &&
!cmSystemTools::IsSubDirectory(baseDir, linkSourceDirectory)) {
- std::string linkName = "[Subprojects]/";
- linkName += it->first;
- this->AppendLinkedResource(xml, linkName,
- this->GetEclipsePath(linkSourceDirectory),
- LinkToFolder);
+ std::string linkName = cmStrCat("[Subprojects]/", it.first);
+ cmExtraEclipseCDT4Generator::AppendLinkedResource(
+ xml, linkName,
+ cmExtraEclipseCDT4Generator::GetEclipsePath(linkSourceDirectory),
+ LinkToFolder);
// Don't add it to the srcLinkedResources, because listing multiple
// directories confuses the Eclipse indexer (#13596).
}
@@ -560,16 +576,15 @@ void cmExtraEclipseCDT4Generator::AppendIncludeDirectories(
cmXMLWriter& xml, const std::vector<std::string>& includeDirs,
std::set<std::string>& emittedDirs)
{
- for (std::vector<std::string>::const_iterator inc = includeDirs.begin();
- inc != includeDirs.end(); ++inc) {
- if (!inc->empty()) {
- std::string dir = cmSystemTools::CollapseFullPath(*inc);
+ for (std::string const& inc : includeDirs) {
+ if (!inc.empty()) {
+ std::string dir = cmSystemTools::CollapseFullPath(inc);
// handle framework include dirs on OSX, the remainder after the
// Frameworks/ part has to be stripped
// /System/Library/Frameworks/GLUT.framework/Headers
cmsys::RegularExpression frameworkRx("(.+/Frameworks)/.+\\.framework/");
- if (frameworkRx.find(dir.c_str())) {
+ if (frameworkRx.find(dir)) {
dir = frameworkRx.match(1);
}
@@ -596,7 +611,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
const std::string filename = this->HomeOutputDirectory + "/.cproject";
- cmGeneratedFileStream fout(filename.c_str());
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
@@ -656,7 +671,8 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
xml.EndElement(); // extension
} else if (systemName == "Darwin") {
xml.StartElement("extension");
- xml.Attribute("id", this->SupportsMachO64Parser
+ xml.Attribute("id",
+ this->SupportsMachO64Parser
? "org.eclipse.cdt.core.MachO64"
: "org.eclipse.cdt.core.MachO");
xml.Attribute("point", "org.eclipse.cdt.core.BinaryParser");
@@ -712,19 +728,17 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
xml.EndElement();
}
- for (std::vector<std::string>::const_iterator it =
- this->SrcLinkedResources.begin();
- it != this->SrcLinkedResources.end(); ++it) {
+ for (std::string const& p : this->SrcLinkedResources) {
xml.StartElement("pathentry");
xml.Attribute("kind", "src");
- xml.Attribute("path", *it);
+ xml.Attribute("path", p);
xml.EndElement();
- // exlude source directory from output search path
+ // exclude source directory from output search path
// - only if not named the same as an output directory
if (!cmSystemTools::FileIsDirectory(
- std::string(this->HomeOutputDirectory + "/" + *it))) {
- excludeFromOut += *it + "/|";
+ std::string(this->HomeOutputDirectory + "/" + p))) {
+ excludeFromOut += p + "/|";
}
}
@@ -738,34 +752,31 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
// add pre-processor definitions to allow eclipse to gray out sections
emmited.clear();
- for (std::vector<cmLocalGenerator*>::const_iterator it =
- this->GlobalGenerator->GetLocalGenerators().begin();
- it != this->GlobalGenerator->GetLocalGenerators().end(); ++it) {
+ for (cmLocalGenerator* lgen : this->GlobalGenerator->GetLocalGenerators()) {
if (const char* cdefs =
- (*it)->GetMakefile()->GetProperty("COMPILE_DEFINITIONS")) {
+ lgen->GetMakefile()->GetProperty("COMPILE_DEFINITIONS")) {
// Expand the list.
std::vector<std::string> defs;
cmGeneratorExpression::Split(cdefs, defs);
- for (std::vector<std::string>::const_iterator di = defs.begin();
- di != defs.end(); ++di) {
- if (cmGeneratorExpression::Find(*di) != std::string::npos) {
+ for (std::string const& d : defs) {
+ if (cmGeneratorExpression::Find(d) != std::string::npos) {
continue;
}
- std::string::size_type equals = di->find('=', 0);
- std::string::size_type enddef = di->length();
+ std::string::size_type equals = d.find('=', 0);
+ std::string::size_type enddef = d.length();
std::string def;
std::string val;
if (equals != std::string::npos && equals < enddef) {
// we have -DFOO=BAR
- def = di->substr(0, equals);
- val = di->substr(equals + 1, enddef - equals + 1);
+ def = d.substr(0, equals);
+ val = d.substr(equals + 1, enddef - equals + 1);
} else {
// we have -DFOO
- def = *di;
+ def = d;
}
// insert the definition if not already added.
@@ -786,12 +797,11 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
mf->GetDefinition("CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS");
if (this->CEnabled && cDefs) {
// Expand the list.
- std::vector<std::string> defs;
- cmSystemTools::ExpandListArgument(cDefs, defs, true);
+ std::vector<std::string> defs = cmExpandedList(cDefs, true);
// the list must contain only definition-value pairs:
if ((defs.size() % 2) == 0) {
- std::vector<std::string>::const_iterator di = defs.begin();
+ auto di = defs.begin();
while (di != defs.end()) {
std::string def = *di;
++di;
@@ -819,12 +829,11 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
mf->GetDefinition("CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS");
if (this->CXXEnabled && cxxDefs) {
// Expand the list.
- std::vector<std::string> defs;
- cmSystemTools::ExpandListArgument(cxxDefs, defs, true);
+ std::vector<std::string> defs = cmExpandedList(cxxDefs, true);
// the list must contain only definition-value pairs:
if ((defs.size() % 2) == 0) {
- std::vector<std::string>::const_iterator di = defs.begin();
+ auto di = defs.begin();
while (di != defs.end()) {
std::string def = *di;
++di;
@@ -850,15 +859,16 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
// include dirs
emmited.clear();
- for (std::vector<cmLocalGenerator*>::const_iterator it =
- this->GlobalGenerator->GetLocalGenerators().begin();
- it != this->GlobalGenerator->GetLocalGenerators().end(); ++it) {
- std::vector<cmGeneratorTarget*> targets = (*it)->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator l = targets.begin();
- l != targets.end(); ++l) {
+ for (cmLocalGenerator* lgen : this->GlobalGenerator->GetLocalGenerators()) {
+ const std::vector<cmGeneratorTarget*>& targets =
+ lgen->GetGeneratorTargets();
+ for (cmGeneratorTarget* target : targets) {
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
+ }
std::vector<std::string> includeDirs;
std::string config = mf->GetSafeDefinition("CMAKE_BUILD_TYPE");
- (*it)->GetIncludeDirectories(includeDirs, *l, "C", config);
+ lgen->GetIncludeDirectories(includeDirs, target, "C", config);
this->AppendIncludeDirectories(xml, includeDirs, emmited);
}
}
@@ -869,16 +879,14 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
if (this->CEnabled && !compiler.empty()) {
std::string systemIncludeDirs =
mf->GetSafeDefinition("CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS");
- std::vector<std::string> dirs;
- cmSystemTools::ExpandListArgument(systemIncludeDirs, dirs);
+ std::vector<std::string> dirs = cmExpandedList(systemIncludeDirs);
this->AppendIncludeDirectories(xml, dirs, emmited);
}
compiler = mf->GetSafeDefinition("CMAKE_CXX_COMPILER");
if (this->CXXEnabled && !compiler.empty()) {
std::string systemIncludeDirs =
mf->GetSafeDefinition("CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS");
- std::vector<std::string> dirs;
- cmSystemTools::ExpandListArgument(systemIncludeDirs, dirs);
+ std::vector<std::string> dirs = cmExpandedList(systemIncludeDirs);
this->AppendIncludeDirectories(xml, dirs, emmited);
}
@@ -889,8 +897,8 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
xml.Attribute("moduleId", "org.eclipse.cdt.make.core.buildtargets");
xml.StartElement("buildTargets");
emmited.clear();
- const std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
- const std::string makeArgs =
+ const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+ const std::string& makeArgs =
mf->GetSafeDefinition("CMAKE_ECLIPSE_MAKE_ARGUMENTS");
cmGlobalGenerator* generator =
@@ -907,26 +915,24 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
// add all executable and library targets and some of the GLOBAL
// and UTILITY targets
- for (std::vector<cmLocalGenerator*>::const_iterator it =
- this->GlobalGenerator->GetLocalGenerators().begin();
- it != this->GlobalGenerator->GetLocalGenerators().end(); ++it) {
- const std::vector<cmGeneratorTarget*> targets =
- (*it)->GetGeneratorTargets();
- std::string subdir = (*it)->ConvertToRelativePath(
- this->HomeOutputDirectory, (*it)->GetCurrentBinaryDirectory());
+ for (cmLocalGenerator* lgen : this->GlobalGenerator->GetLocalGenerators()) {
+ const std::vector<cmGeneratorTarget*>& targets =
+ lgen->GetGeneratorTargets();
+ std::string subdir = lgen->MaybeConvertToRelativePath(
+ this->HomeOutputDirectory, lgen->GetCurrentBinaryDirectory());
if (subdir == ".") {
- subdir = "";
+ subdir.clear();
}
- for (std::vector<cmGeneratorTarget*>::const_iterator ti = targets.begin();
- ti != targets.end(); ++ti) {
- std::string targetName = (*ti)->GetName();
- switch ((*ti)->GetType()) {
+ for (cmGeneratorTarget* target : targets) {
+ std::string targetName = target->GetName();
+ switch (target->GetType()) {
case cmStateEnums::GLOBAL_TARGET: {
// Only add the global targets from CMAKE_BINARY_DIR,
// not from the subdirs
if (subdir.empty()) {
- this->AppendTarget(xml, targetName, make, makeArgs, subdir, ": ");
+ cmExtraEclipseCDT4Generator::AppendTarget(xml, targetName, make,
+ makeArgs, subdir, ": ");
}
} break;
case cmStateEnums::UTILITY:
@@ -941,7 +947,8 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
break;
}
- this->AppendTarget(xml, targetName, make, makeArgs, subdir, ": ");
+ cmExtraEclipseCDT4Generator::AppendTarget(xml, targetName, make,
+ makeArgs, subdir, ": ");
break;
case cmStateEnums::EXECUTABLE:
case cmStateEnums::STATIC_LIBRARY:
@@ -949,37 +956,35 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
case cmStateEnums::MODULE_LIBRARY:
case cmStateEnums::OBJECT_LIBRARY: {
const char* prefix =
- ((*ti)->GetType() == cmStateEnums::EXECUTABLE ? "[exe] "
- : "[lib] ");
- this->AppendTarget(xml, targetName, make, makeArgs, subdir, prefix);
- std::string fastTarget = targetName;
- fastTarget += "/fast";
- this->AppendTarget(xml, fastTarget, make, makeArgs, subdir, prefix);
+ (target->GetType() == cmStateEnums::EXECUTABLE ? "[exe] "
+ : "[lib] ");
+ cmExtraEclipseCDT4Generator::AppendTarget(xml, targetName, make,
+ makeArgs, subdir, prefix);
+ std::string fastTarget = cmStrCat(targetName, "/fast");
+ cmExtraEclipseCDT4Generator::AppendTarget(xml, fastTarget, make,
+ makeArgs, subdir, prefix);
// Add Build and Clean targets in the virtual folder of targets:
if (this->SupportsVirtualFolders) {
- std::string virtDir = "[Targets]/";
- virtDir += prefix;
- virtDir += targetName;
- std::string buildArgs = "-C \"";
- buildArgs += (*it)->GetBinaryDirectory();
- buildArgs += "\" ";
- buildArgs += makeArgs;
- this->AppendTarget(xml, "Build", make, buildArgs, virtDir, "",
- targetName.c_str());
-
- std::string cleanArgs = "-E chdir \"";
- cleanArgs += (*it)->GetCurrentBinaryDirectory();
- cleanArgs += "\" \"";
- cleanArgs += cmSystemTools::GetCMakeCommand();
- cleanArgs += "\" -P \"";
- cmGeneratorTarget* gt = *ti;
- cleanArgs += (*it)->GetTargetDirectory(gt);
+ std::string virtDir = cmStrCat("[Targets]/", prefix, targetName);
+ std::string buildArgs =
+ cmStrCat("-C \"", lgen->GetBinaryDirectory(), "\" ", makeArgs);
+ cmExtraEclipseCDT4Generator::AppendTarget(
+ xml, "Build", make, buildArgs, virtDir, "", targetName.c_str());
+
+ std::string cleanArgs =
+ cmStrCat("-E chdir \"", lgen->GetCurrentBinaryDirectory(),
+ "\" \"", cmSystemTools::GetCMakeCommand(), "\" -P \"");
+ cmGeneratorTarget* gt = target;
+ cleanArgs += lgen->GetTargetDirectory(gt);
cleanArgs += "/cmake_clean.cmake\"";
- this->AppendTarget(xml, "Clean", cmSystemTools::GetCMakeCommand(),
- cleanArgs, virtDir, "", "");
+ cmExtraEclipseCDT4Generator::AppendTarget(
+ xml, "Clean", cmSystemTools::GetCMakeCommand(), cleanArgs,
+ virtDir, "", "");
}
} break;
+ case cmStateEnums::INTERFACE_LIBRARY:
+ break;
default:
break;
}
@@ -987,33 +992,34 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
// insert the all and clean targets in every subdir
if (!allTarget.empty()) {
- this->AppendTarget(xml, allTarget, make, makeArgs, subdir, ": ");
+ cmExtraEclipseCDT4Generator::AppendTarget(xml, allTarget, make, makeArgs,
+ subdir, ": ");
}
if (!cleanTarget.empty()) {
- this->AppendTarget(xml, cleanTarget, make, makeArgs, subdir, ": ");
+ cmExtraEclipseCDT4Generator::AppendTarget(xml, cleanTarget, make,
+ makeArgs, subdir, ": ");
}
// insert rules for compiling, preprocessing and assembling individual
// files
std::vector<std::string> objectFileTargets;
- (*it)->GetIndividualFileTargets(objectFileTargets);
- for (std::vector<std::string>::const_iterator fit =
- objectFileTargets.begin();
- fit != objectFileTargets.end(); ++fit) {
+ lg->GetIndividualFileTargets(objectFileTargets);
+ for (std::string const& f : objectFileTargets) {
const char* prefix = "[obj] ";
- if ((*fit)[fit->length() - 1] == 's') {
+ if (f.back() == 's') {
prefix = "[to asm] ";
- } else if ((*fit)[fit->length() - 1] == 'i') {
+ } else if (f.back() == 'i') {
prefix = "[pre] ";
}
- this->AppendTarget(xml, *fit, make, makeArgs, subdir, prefix);
+ cmExtraEclipseCDT4Generator::AppendTarget(xml, f, make, makeArgs, subdir,
+ prefix);
}
}
xml.EndElement(); // buildTargets
xml.EndElement(); // storageModule
- this->AppendStorageScanners(xml, *mf);
+ cmExtraEclipseCDT4Generator::AppendStorageScanners(xml, *mf);
xml.EndElement(); // cconfiguration
xml.EndElement(); // storageModule
@@ -1028,6 +1034,13 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
xml.EndElement(); // project
xml.EndElement(); // storageModule
+
+ // Append additional cproject contents without applying any XML formatting
+ if (const char* extraCProjectContents =
+ mf->GetState()->GetGlobalProperty("ECLIPSE_EXTRA_CPROJECT_CONTENTS")) {
+ fout << extraCProjectContents;
+ }
+
xml.EndElement(); // cproject
}
@@ -1053,8 +1066,7 @@ std::string cmExtraEclipseCDT4Generator::GetPathBasename(
{
std::string outputBasename = path;
while (!outputBasename.empty() &&
- (outputBasename[outputBasename.size() - 1] == '/' ||
- outputBasename[outputBasename.size() - 1] == '\\')) {
+ (outputBasename.back() == '/' || outputBasename.back() == '\\')) {
outputBasename.resize(outputBasename.size() - 1);
}
std::string::size_type loc = outputBasename.find_last_of("/\\");
@@ -1076,7 +1088,8 @@ void cmExtraEclipseCDT4Generator::AppendStorageScanners(
cmXMLWriter& xml, const cmMakefile& makefile)
{
// we need the "make" and the C (or C++) compiler which are used, Alex
- std::string make = makefile.GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+ const std::string& make =
+ makefile.GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
std::string compiler = makefile.GetSafeDefinition("CMAKE_C_COMPILER");
std::string arg1 = makefile.GetSafeDefinition("CMAKE_C_COMPILER_ARG1");
if (compiler.empty()) {
diff --git a/Source/cmExtraEclipseCDT4Generator.h b/Source/cmExtraEclipseCDT4Generator.h
index 1380d1867..ff4c59eeb 100644
--- a/Source/cmExtraEclipseCDT4Generator.h
+++ b/Source/cmExtraEclipseCDT4Generator.h
@@ -3,15 +3,15 @@
#ifndef cmExtraEclipseCDT4Generator_h
#define cmExtraEclipseCDT4Generator_h
-#include "cmConfigure.h"
-
-#include "cmExternalMakefileProjectGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <set>
#include <string>
#include <vector>
+#include "cmExternalMakefileProjectGenerator.h"
+
class cmLocalGenerator;
class cmMakefile;
class cmSourceGroup;
@@ -35,14 +35,17 @@ public:
static cmExternalMakefileProjectGeneratorFactory* GetFactory();
void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
- bool optional) CM_OVERRIDE;
+ bool optional) override;
- void Generate() CM_OVERRIDE;
+ void Generate() override;
private:
// create .project file in the source tree
void CreateSourceProjectFile();
+ // create .settings/org.eclipse.core.resources.prefs
+ void CreateSettingsResourcePrefsFile();
+
// create .project file
void CreateProjectFile();
@@ -67,7 +70,7 @@ private:
const std::string& make,
const std::string& makeArguments,
const std::string& path, const char* prefix = "",
- const char* makeTarget = CM_NULLPTR);
+ const char* makeTarget = nullptr);
static void AppendScannerProfile(
cmXMLWriter& xml, const std::string& profileID, bool openActionEnabled,
const std::string& openActionFilePath, bool pParserEnabled,
diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx
index 373043309..e8c9dd002 100644
--- a/Source/cmExtraKateGenerator.cxx
+++ b/Source/cmExtraKateGenerator.cxx
@@ -2,6 +2,11 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExtraKateGenerator.h"
+#include <cstring>
+#include <ostream>
+#include <set>
+#include <vector>
+
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -9,17 +14,10 @@
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include <ostream>
-#include <set>
-#include <string.h>
-#include <vector>
-
-cmExtraKateGenerator::cmExtraKateGenerator()
- : cmExternalMakefileProjectGenerator()
-{
-}
+cmExtraKateGenerator::cmExtraKateGenerator() = default;
cmExternalMakefileProjectGeneratorFactory* cmExtraKateGenerator::GetFactory()
{
@@ -56,9 +54,8 @@ void cmExtraKateGenerator::Generate()
void cmExtraKateGenerator::CreateKateProjectFile(
const cmLocalGenerator* lg) const
{
- std::string filename = lg->GetBinaryDirectory();
- filename += "/.kateproject";
- cmGeneratedFileStream fout(filename.c_str());
+ std::string filename = cmStrCat(lg->GetBinaryDirectory(), "/.kateproject");
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
@@ -78,15 +75,15 @@ void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator* lg,
cmGeneratedFileStream& fout) const
{
cmMakefile const* mf = lg->GetMakefile();
- const std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
- const std::string makeArgs =
+ 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 */
@@ -112,18 +109,16 @@ void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator* lg,
// add all executable and library targets and some of the GLOBAL
// and UTILITY targets
- for (std::vector<cmLocalGenerator*>::const_iterator it =
- this->GlobalGenerator->GetLocalGenerators().begin();
- it != this->GlobalGenerator->GetLocalGenerators().end(); ++it) {
- const std::vector<cmGeneratorTarget*> targets =
- (*it)->GetGeneratorTargets();
- std::string currentDir = (*it)->GetCurrentBinaryDirectory();
- bool topLevel = (currentDir == (*it)->GetBinaryDirectory());
-
- for (std::vector<cmGeneratorTarget*>::const_iterator ti = targets.begin();
- ti != targets.end(); ++ti) {
- std::string targetName = (*ti)->GetName();
- switch ((*ti)->GetType()) {
+ for (cmLocalGenerator* localGen :
+ this->GlobalGenerator->GetLocalGenerators()) {
+ const std::vector<cmGeneratorTarget*>& targets =
+ localGen->GetGeneratorTargets();
+ std::string currentDir = localGen->GetCurrentBinaryDirectory();
+ bool topLevel = (currentDir == localGen->GetBinaryDirectory());
+
+ for (cmGeneratorTarget* target : targets) {
+ std::string const& targetName = target->GetName();
+ switch (target->GetType()) {
case cmStateEnums::GLOBAL_TARGET: {
bool insertTarget = false;
// Only add the global targets from CMAKE_BINARY_DIR,
@@ -134,10 +129,10 @@ void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator* lg,
// this will not work within the IDE
if (targetName == "edit_cache") {
const char* editCommand =
- (*it)->GetMakefile()->GetDefinition("CMAKE_EDIT_COMMAND");
- if (editCommand == CM_NULLPTR) {
+ localGen->GetMakefile()->GetDefinition("CMAKE_EDIT_COMMAND");
+ if (editCommand == nullptr) {
insertTarget = false;
- } else if (strstr(editCommand, "ccmake") != CM_NULLPTR) {
+ } else if (strstr(editCommand, "ccmake") != nullptr) {
insertTarget = false;
}
}
@@ -169,8 +164,7 @@ void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator* lg,
case cmStateEnums::OBJECT_LIBRARY: {
this->AppendTarget(fout, targetName, make, makeArgs, currentDir,
homeOutputDir);
- std::string fastTarget = targetName;
- fastTarget += "/fast";
+ std::string fastTarget = cmStrCat(targetName, "/fast");
this->AppendTarget(fout, fastTarget, make, makeArgs, currentDir,
homeOutputDir);
@@ -183,12 +177,9 @@ void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator* lg,
// insert rules for compiling, preprocessing and assembling individual
// files
std::vector<std::string> objectFileTargets;
- (*it)->GetIndividualFileTargets(objectFileTargets);
- for (std::vector<std::string>::const_iterator fit =
- objectFileTargets.begin();
- fit != objectFileTargets.end(); ++fit) {
- this->AppendTarget(fout, *fit, make, makeArgs, currentDir,
- homeOutputDir);
+ localGen->GetIndividualFileTargets(objectFileTargets);
+ for (std::string const& f : objectFileTargets) {
+ this->AppendTarget(fout, f, make, makeArgs, currentDir, homeOutputDir);
}
}
@@ -200,13 +191,14 @@ 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())
+ fout << "\t\t\t" << JsonSep << R"({"name":")" << target
+ << "\", "
+ "\"build_cmd\":\""
+ << make << " -C \\\"" << (this->UseNinja ? homeOutputDir : path)
<< "\\\" " << makeArgs << " " << target << "\"}\n";
JsonSep = ',';
@@ -215,11 +207,9 @@ void cmExtraKateGenerator::AppendTarget(cmGeneratedFileStream& fout,
void cmExtraKateGenerator::CreateDummyKateProjectFile(
const cmLocalGenerator* lg) const
{
- std::string filename = lg->GetBinaryDirectory();
- filename += "/";
- filename += this->ProjectName;
- filename += ".kateproject";
- cmGeneratedFileStream fout(filename.c_str());
+ std::string filename =
+ cmStrCat(lg->GetBinaryDirectory(), '/', this->ProjectName, ".kateproject");
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
@@ -231,58 +221,50 @@ void cmExtraKateGenerator::CreateDummyKateProjectFile(
std::string cmExtraKateGenerator::GenerateFilesString(
const cmLocalGenerator* lg) const
{
- std::string s = lg->GetSourceDirectory();
- s += "/.git";
- if (cmSystemTools::FileExists(s.c_str())) {
- return std::string("\"git\": 1 ");
+ std::string s = cmStrCat(lg->GetSourceDirectory(), "/.git");
+ if (cmSystemTools::FileExists(s)) {
+ return "\"git\": 1 ";
}
- s = lg->GetSourceDirectory();
- s += "/.svn";
- if (cmSystemTools::FileExists(s.c_str())) {
- return std::string("\"svn\": 1 ");
+ s = cmStrCat(lg->GetSourceDirectory(), "/.svn");
+ if (cmSystemTools::FileExists(s)) {
+ return "\"svn\": 1 ";
}
- s = lg->GetSourceDirectory();
- s += "/";
+ s = cmStrCat(lg->GetSourceDirectory(), '/');
std::set<std::string> files;
std::string tmp;
const std::vector<cmLocalGenerator*>& lgs =
this->GlobalGenerator->GetLocalGenerators();
- for (std::vector<cmLocalGenerator*>::const_iterator it = lgs.begin();
- it != lgs.end(); it++) {
- cmMakefile* makefile = (*it)->GetMakefile();
+ for (cmLocalGenerator* lgen : lgs) {
+ cmMakefile* makefile = lgen->GetMakefile();
const std::vector<std::string>& listFiles = makefile->GetListFiles();
- for (std::vector<std::string>::const_iterator lt = listFiles.begin();
- lt != listFiles.end(); lt++) {
- tmp = *lt;
+ for (std::string const& listFile : listFiles) {
+ tmp = listFile;
{
files.insert(tmp);
}
}
const std::vector<cmSourceFile*>& sources = makefile->GetSourceFiles();
- for (std::vector<cmSourceFile*>::const_iterator sfIt = sources.begin();
- sfIt != sources.end(); sfIt++) {
- cmSourceFile* sf = *sfIt;
- if (sf->GetPropertyAsBool("GENERATED")) {
+ for (cmSourceFile* sf : sources) {
+ if (sf->GetIsGenerated()) {
continue;
}
- tmp = sf->GetFullPath();
+ tmp = sf->ResolveFullPath();
files.insert(tmp);
}
}
const char* sep = "";
tmp = "\"list\": [";
- for (std::set<std::string>::const_iterator it = files.begin();
- it != files.end(); ++it) {
+ for (std::string const& f : files) {
tmp += sep;
tmp += " \"";
- tmp += *it;
+ tmp += f;
tmp += "\"";
sep = ",";
}
@@ -303,8 +285,7 @@ std::string cmExtraKateGenerator::GetPathBasename(
{
std::string outputBasename = path;
while (!outputBasename.empty() &&
- (outputBasename[outputBasename.size() - 1] == '/' ||
- outputBasename[outputBasename.size() - 1] == '\\')) {
+ (outputBasename.back() == '/' || outputBasename.back() == '\\')) {
outputBasename.resize(outputBasename.size() - 1);
}
std::string::size_type loc = outputBasename.find_last_of("/\\");
diff --git a/Source/cmExtraKateGenerator.h b/Source/cmExtraKateGenerator.h
index 6b9c7af5c..be1376aa2 100644
--- a/Source/cmExtraKateGenerator.h
+++ b/Source/cmExtraKateGenerator.h
@@ -3,12 +3,12 @@
#ifndef cmExtraKateGenerator_h
#define cmExtraKateGenerator_h
-#include "cmConfigure.h"
-
-#include "cmExternalMakefileProjectGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
+#include "cmExternalMakefileProjectGenerator.h"
+
class cmGeneratedFileStream;
class cmLocalGenerator;
@@ -22,7 +22,7 @@ public:
static cmExternalMakefileProjectGeneratorFactory* GetFactory();
- void Generate() CM_OVERRIDE;
+ void Generate() override;
private:
void CreateKateProjectFile(const cmLocalGenerator* lg) const;
@@ -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 1fd1418de..495324cbf 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -2,20 +2,23 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExtraSublimeTextGenerator.h"
-#include "cmsys/RegularExpression.hxx"
+#include <cstring>
#include <set>
#include <sstream>
-#include <string.h>
#include <utility>
+#include "cmsys/RegularExpression.hxx"
+
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmSourceFile.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
@@ -55,7 +58,6 @@ cmExtraSublimeTextGenerator::GetFactory()
}
cmExtraSublimeTextGenerator::cmExtraSublimeTextGenerator()
- : cmExternalMakefileProjectGenerator()
{
this->ExcludeBuildFolder = false;
}
@@ -68,11 +70,9 @@ void cmExtraSublimeTextGenerator::Generate()
"CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS");
// for each sub project in the project create a sublime text 2 project
- for (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
- it = this->GlobalGenerator->GetProjectMap().begin();
- it != this->GlobalGenerator->GetProjectMap().end(); ++it) {
+ for (auto const& it : this->GlobalGenerator->GetProjectMap()) {
// create a project file
- this->CreateProjectFile(it->second);
+ this->CreateProjectFile(it.second);
}
}
@@ -93,7 +93,7 @@ void cmExtraSublimeTextGenerator::CreateNewProjectFile(
{
const cmMakefile* mf = lgs[0]->GetMakefile();
- cmGeneratedFileStream fout(filename.c_str());
+ cmGeneratedFileStream fout(filename);
if (!fout) {
return;
}
@@ -135,8 +135,7 @@ void cmExtraSublimeTextGenerator::CreateNewProjectFile(
// End of build_systems
fout << "\n\t]";
std::string systemName = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME");
- std::vector<std::string> tokens;
- cmSystemTools::ExpandListArgument(this->EnvSettings, tokens);
+ std::vector<std::string> tokens = cmExpandedList(this->EnvSettings);
if (!this->EnvSettings.empty()) {
fout << ",";
@@ -144,21 +143,20 @@ void cmExtraSublimeTextGenerator::CreateNewProjectFile(
fout << "\n\t{";
fout << "\n\t\t" << systemName << ":";
fout << "\n\t\t{";
- for (std::vector<std::string>::iterator i = tokens.begin();
- i != tokens.end(); ++i) {
- size_t const pos = i->find_first_of('=');
+ for (std::string const& t : tokens) {
+ size_t const pos = t.find_first_of('=');
if (pos != std::string::npos) {
- std::string varName = i->substr(0, pos);
- std::string varValue = i->substr(pos + 1);
+ std::string varName = t.substr(0, pos);
+ std::string varValue = t.substr(pos + 1);
fout << "\n\t\t\t\"" << varName << "\":\"" << varValue << "\"";
} else {
std::ostringstream e;
e << "Could not parse Env Vars specified in "
"\"CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS\""
- << ", corrupted string " << *i;
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ << ", corrupted string " << t;
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
}
}
fout << "\n\t\t}";
@@ -171,31 +169,28 @@ void cmExtraSublimeTextGenerator::AppendAllTargets(
const std::vector<cmLocalGenerator*>& lgs, const cmMakefile* mf,
cmGeneratedFileStream& fout, MapSourceFileFlags& sourceFileFlags)
{
- std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+ const std::string& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
std::string compiler;
if (!lgs.empty()) {
- this->AppendTarget(fout, "all", lgs[0], CM_NULLPTR, make.c_str(), mf,
+ this->AppendTarget(fout, "all", lgs[0], nullptr, make.c_str(), mf,
compiler.c_str(), sourceFileFlags, true);
- this->AppendTarget(fout, "clean", lgs[0], CM_NULLPTR, make.c_str(), mf,
+ this->AppendTarget(fout, "clean", lgs[0], nullptr, make.c_str(), mf,
compiler.c_str(), sourceFileFlags, false);
}
// add all executable and library targets and some of the GLOBAL
// and UTILITY targets
- for (std::vector<cmLocalGenerator*>::const_iterator lg = lgs.begin();
- lg != lgs.end(); lg++) {
- cmMakefile* makefile = (*lg)->GetMakefile();
- std::vector<cmGeneratorTarget*> targets = (*lg)->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator ti = targets.begin();
- ti != targets.end(); ti++) {
- std::string targetName = (*ti)->GetName();
- switch ((*ti)->GetType()) {
+ for (cmLocalGenerator* lg : lgs) {
+ cmMakefile* makefile = lg->GetMakefile();
+ const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
+ for (cmGeneratorTarget* target : targets) {
+ std::string targetName = target->GetName();
+ switch (target->GetType()) {
case cmStateEnums::GLOBAL_TARGET: {
// Only add the global targets from CMAKE_BINARY_DIR,
// not from the subdirs
- if (strcmp((*lg)->GetCurrentBinaryDirectory(),
- (*lg)->GetBinaryDirectory()) == 0) {
- this->AppendTarget(fout, targetName, *lg, CM_NULLPTR, make.c_str(),
+ if (lg->GetCurrentBinaryDirectory() == lg->GetBinaryDirectory()) {
+ this->AppendTarget(fout, targetName, lg, nullptr, make.c_str(),
makefile, compiler.c_str(), sourceFileFlags,
false);
}
@@ -212,7 +207,7 @@ void cmExtraSublimeTextGenerator::AppendAllTargets(
break;
}
- this->AppendTarget(fout, targetName, *lg, CM_NULLPTR, make.c_str(),
+ this->AppendTarget(fout, targetName, lg, nullptr, make.c_str(),
makefile, compiler.c_str(), sourceFileFlags,
false);
break;
@@ -221,12 +216,11 @@ void cmExtraSublimeTextGenerator::AppendAllTargets(
case cmStateEnums::SHARED_LIBRARY:
case cmStateEnums::MODULE_LIBRARY:
case cmStateEnums::OBJECT_LIBRARY: {
- this->AppendTarget(fout, targetName, *lg, *ti, make.c_str(),
+ this->AppendTarget(fout, targetName, lg, target, make.c_str(),
makefile, compiler.c_str(), sourceFileFlags,
false);
- std::string fastTarget = targetName;
- fastTarget += "/fast";
- this->AppendTarget(fout, fastTarget, *lg, *ti, make.c_str(),
+ std::string fastTarget = cmStrCat(targetName, "/fast");
+ this->AppendTarget(fout, fastTarget, lg, target, make.c_str(),
makefile, compiler.c_str(), sourceFileFlags,
false);
} break;
@@ -244,35 +238,35 @@ void cmExtraSublimeTextGenerator::AppendTarget(
MapSourceFileFlags& sourceFileFlags, bool firstTarget)
{
- if (target != CM_NULLPTR) {
+ if (target != nullptr) {
std::vector<cmSourceFile*> sourceFiles;
target->GetSourceFiles(sourceFiles,
makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
- std::vector<cmSourceFile*>::const_iterator sourceFilesEnd =
- sourceFiles.end();
- for (std::vector<cmSourceFile*>::const_iterator iter = sourceFiles.begin();
- iter != sourceFilesEnd; ++iter) {
- cmSourceFile* sourceFile = *iter;
- MapSourceFileFlags::iterator sourceFileFlagsIter =
- sourceFileFlags.find(sourceFile->GetFullPath());
+ for (cmSourceFile* sourceFile : sourceFiles) {
+ auto sourceFileFlagsIter =
+ sourceFileFlags.find(sourceFile->ResolveFullPath());
if (sourceFileFlagsIter == sourceFileFlags.end()) {
sourceFileFlagsIter =
sourceFileFlags
- .insert(MapSourceFileFlags::value_type(sourceFile->GetFullPath(),
- std::vector<std::string>()))
+ .insert(MapSourceFileFlags::value_type(
+ sourceFile->ResolveFullPath(), std::vector<std::string>()))
.first;
}
std::vector<std::string>& flags = sourceFileFlagsIter->second;
- std::string flagsString = this->ComputeFlagsForObject(*iter, lg, target);
- std::string definesString = this->ComputeDefines(*iter, lg, target);
+ 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
// https://gist.github.com/3944250
const char* regexString =
- "(^|[ ])-[DIOUWfgs][^= ]+(=\\\"[^\"]+\\\"|=[^\"][^ ]+)?";
+ R"((^|[ ])-[DIOUWfgs][^= ]+(=\"[^"]+\"|=[^"][^ ]+)?)";
flagRegex.compile(regexString);
- std::string workString = flagsString + " " + definesString;
+ std::string workString =
+ cmStrCat(flagsString, " ", definesString, " ", includesString);
while (flagRegex.find(workString)) {
std::string::size_type start = flagRegex.start();
if (workString[start] == ' ') {
@@ -282,7 +276,7 @@ void cmExtraSublimeTextGenerator::AppendTarget(
if (flagRegex.end() < workString.size()) {
workString = workString.substr(flagRegex.end());
} else {
- workString = "";
+ workString.clear();
}
}
}
@@ -316,17 +310,16 @@ void cmExtraSublimeTextGenerator::AppendTarget(
std::string cmExtraSublimeTextGenerator::BuildMakeCommand(
const std::string& make, const char* makefile, const std::string& target)
{
- std::string command = "\"";
- command += make + "\"";
+ std::string command = cmStrCat('"', make, '"');
std::string generator = this->GlobalGenerator->GetName();
if (generator == "NMake Makefiles") {
std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
- command += ", \"/NOLOGO\", \"/f\", \"";
+ command += R"(, "/NOLOGO", "/f", ")";
command += makefileName + "\"";
command += ", \"" + target + "\"";
} else if (generator == "Ninja") {
std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
- command += ", \"-f\", \"";
+ command += R"(, "-f", ")";
command += makefileName + "\"";
command += ", \"" + target + "\"";
} else {
@@ -338,7 +331,7 @@ std::string cmExtraSublimeTextGenerator::BuildMakeCommand(
} else {
makefileName = cmSystemTools::ConvertToOutputPath(makefile);
}
- command += ", \"-f\", \"";
+ command += R"(, "-f", ")";
command += makefileName + "\"";
command += ", \"" + target + "\"";
}
@@ -350,7 +343,7 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject(
cmSourceFile* source, cmLocalGenerator* lg, cmGeneratorTarget* gtgt)
{
std::string flags;
- std::string language = source->GetLanguage();
+ std::string language = source->GetOrDetermineLanguage();
if (language.empty()) {
language = "C";
}
@@ -359,20 +352,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, config, gtgt,
+ 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;
@@ -386,21 +378,25 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines(
{
std::set<std::string> defines;
cmMakefile* makefile = lg->GetMakefile();
- const std::string& language = source->GetLanguage();
+ const std::string& language = source->GetOrDetermineLanguage();
const std::string& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target,
+ language);
- // Add the export symbol definition for shared library objects.
- if (const char* exportMacro = target->GetExportMacro()) {
- lg->AppendDefines(defines, exportMacro);
+ // Add preprocessor definitions for this target and configuration.
+ lg->GetTargetDefines(target, config, language, defines);
+ 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));
}
- // 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));
+ std::string defPropName =
+ cmStrCat("COMPILE_DEFINITIONS_", 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;
@@ -408,3 +404,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->GetOrDetermineLanguage();
+ const std::string& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target,
+ 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 (cmIsNOTFOUND(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 9022d3754..7e8f2d4ec 100644
--- a/Source/cmExtraSublimeTextGenerator.h
+++ b/Source/cmExtraSublimeTextGenerator.h
@@ -3,14 +3,14 @@
#ifndef cmExtraSublimeTextGenerator_h
#define cmExtraSublimeTextGenerator_h
-#include "cmConfigure.h"
-
-#include "cmExternalMakefileProjectGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
#include <string>
#include <vector>
+#include "cmExternalMakefileProjectGenerator.h"
+
class cmGeneratedFileStream;
class cmGeneratorTarget;
class cmLocalGenerator;
@@ -24,10 +24,10 @@ class cmExtraSublimeTextGenerator : public cmExternalMakefileProjectGenerator
{
public:
static cmExternalMakefileProjectGeneratorFactory* GetFactory();
- typedef std::map<std::string, std::vector<std::string> > MapSourceFileFlags;
+ using MapSourceFileFlags = std::map<std::string, std::vector<std::string>>;
cmExtraSublimeTextGenerator();
- void Generate() CM_OVERRIDE;
+ void Generate() override;
private:
void CreateProjectFile(const std::vector<cmLocalGenerator*>& lgs);
@@ -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/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx
index ff78f52e3..11844e47d 100644
--- a/Source/cmFLTKWrapUICommand.cxx
+++ b/Source/cmFLTKWrapUICommand.cxx
@@ -2,122 +2,121 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFLTKWrapUICommand.h"
-#include <stddef.h>
+#include <cstddef>
#include "cmCustomCommandLines.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
class cmTarget;
-// cmFLTKWrapUICommand
-bool cmFLTKWrapUICommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+static void FinalAction(cmMakefile& makefile, std::string const& name)
+{
+ // people should add the srcs to the target themselves, but the old command
+ // didn't support that, so check and see if they added the files in and if
+ // they didn;t then print a warning and add then anyhow
+ cmTarget* target = makefile.FindLocalNonAliasTarget(name);
+ if (!target) {
+ std::string msg = cmStrCat(
+ "FLTK_WRAP_UI was called with a target that was never created: ", name,
+ ". The problem was found while processing the source directory: ",
+ makefile.GetCurrentSourceDirectory(),
+ ". This FLTK_WRAP_UI call will be ignored.");
+ cmSystemTools::Message(msg, "Warning");
+ }
+}
+
+bool cmFLTKWrapUICommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
+ cmMakefile& mf = status.GetMakefile();
+
// what is the current source dir
- std::string cdir = this->Makefile->GetCurrentSourceDirectory();
- const char* fluid_exe =
- this->Makefile->GetRequiredDefinition("FLTK_FLUID_EXECUTABLE");
+ std::string cdir = mf.GetCurrentSourceDirectory();
+ std::string const& fluid_exe =
+ mf.GetRequiredDefinition("FLTK_FLUID_EXECUTABLE");
- // get parameter for the command
- this->Target = args[0]; // Target that will use the generated files
+ // Target that will use the generated files
+ std::string const& target = args[0];
// get the list of GUI files from which .cxx and .h will be generated
- std::string outputDirectory = this->Makefile->GetCurrentBinaryDirectory();
+ std::string outputDirectory = mf.GetCurrentBinaryDirectory();
{
// Some of the generated files are *.h so the directory "GUI"
// where they are created have to be added to the include path
std::vector<std::string> outputDirectories;
outputDirectories.push_back(outputDirectory);
- this->Makefile->AddIncludeDirectories(outputDirectories);
+ mf.AddIncludeDirectories(outputDirectories);
}
- for (std::vector<std::string>::const_iterator i = (args.begin() + 1);
- i != args.end(); i++) {
- cmSourceFile* curr = this->Makefile->GetSource(*i);
+ // List of produced files.
+ std::vector<cmSourceFile*> generatedSourcesClasses;
+
+ for (std::string const& arg : cmMakeRange(args).advance(1)) {
+ cmSourceFile* curr = mf.GetSource(arg);
// if we should use the source GUI
// to generate .cxx and .h files
if (!curr || !curr->GetPropertyAsBool("WRAP_EXCLUDE")) {
- std::string outName = outputDirectory;
- outName += "/";
- outName += cmSystemTools::GetFilenameWithoutExtension(*i);
- std::string hname = outName;
- hname += ".h";
- std::string origname = cdir + "/" + *i;
+ std::string outName = cmStrCat(
+ outputDirectory, "/", cmSystemTools::GetFilenameWithoutExtension(arg));
+ std::string hname = cmStrCat(outName, ".h");
+ std::string origname = cmStrCat(cdir, "/", arg);
// add starting depends
std::vector<std::string> depends;
depends.push_back(origname);
depends.push_back(fluid_exe);
- std::string cxxres = outName;
- cxxres += ".cxx";
-
- cmCustomCommandLine commandLine;
- commandLine.push_back(fluid_exe);
- commandLine.push_back("-c"); // instructs Fluid to run in command line
- commandLine.push_back("-h"); // optionally rename .h files
- commandLine.push_back(hname);
- commandLine.push_back("-o"); // optionally rename .cxx files
- commandLine.push_back(cxxres);
- commandLine.push_back(origname); // name of the GUI fluid file
- cmCustomCommandLines commandLines;
- commandLines.push_back(commandLine);
+ std::string cxxres = cmStrCat(outName, ".cxx");
+
+ cmCustomCommandLines commandLines = cmMakeSingleCommandLine({
+ fluid_exe,
+ "-c", // instructs Fluid to run in command line
+ "-h", // optionally rename .h files
+ hname,
+ "-o", // optionally rename .cxx files
+ cxxres,
+ origname // name of the GUI fluid file
+ });
// Add command for generating the .h and .cxx files
std::string no_main_dependency;
- const char* no_comment = CM_NULLPTR;
- const char* no_working_dir = CM_NULLPTR;
- this->Makefile->AddCustomCommandToOutput(
- cxxres, depends, no_main_dependency, commandLines, no_comment,
- no_working_dir);
- this->Makefile->AddCustomCommandToOutput(
- hname, depends, no_main_dependency, commandLines, no_comment,
- no_working_dir);
-
- cmSourceFile* sf = this->Makefile->GetSource(cxxres);
+ const char* no_comment = nullptr;
+ const char* no_working_dir = nullptr;
+ mf.AddCustomCommandToOutput(cxxres, depends, no_main_dependency,
+ commandLines, no_comment, no_working_dir);
+ mf.AddCustomCommandToOutput(hname, depends, no_main_dependency,
+ commandLines, no_comment, no_working_dir);
+
+ cmSourceFile* sf = mf.GetSource(cxxres);
sf->AddDepend(hname);
sf->AddDepend(origname);
- this->GeneratedSourcesClasses.push_back(sf);
+ generatedSourcesClasses.push_back(sf);
}
}
// create the variable with the list of sources in it
- size_t lastHeadersClass = this->GeneratedSourcesClasses.size();
+ size_t lastHeadersClass = generatedSourcesClasses.size();
std::string sourceListValue;
for (size_t classNum = 0; classNum < lastHeadersClass; classNum++) {
if (classNum) {
sourceListValue += ";";
}
- sourceListValue += this->GeneratedSourcesClasses[classNum]->GetFullPath();
+ sourceListValue += generatedSourcesClasses[classNum]->ResolveFullPath();
}
- std::string varName = this->Target;
- varName += "_FLTK_UI_SRCS";
- this->Makefile->AddDefinition(varName, sourceListValue.c_str());
- return true;
-}
+ std::string const varName = target + "_FLTK_UI_SRCS";
+ mf.AddDefinition(varName, sourceListValue);
-void cmFLTKWrapUICommand::FinalPass()
-{
- // people should add the srcs to the target themselves, but the old command
- // didn't support that, so check and see if they added the files in and if
- // they didn;t then print a warning and add then anyhow
- cmTarget* target = this->Makefile->FindLocalNonAliasTarget(this->Target);
- if (!target) {
- std::string msg =
- "FLTK_WRAP_UI was called with a target that was never created: ";
- msg += this->Target;
- msg += ". The problem was found while processing the source directory: ";
- msg += this->Makefile->GetCurrentSourceDirectory();
- msg += ". This FLTK_WRAP_UI call will be ignored.";
- cmSystemTools::Message(msg.c_str(), "Warning");
- return;
- }
+ mf.AddFinalAction(
+ [target](cmMakefile& makefile) { FinalAction(makefile, target); });
+ return true;
}
diff --git a/Source/cmFLTKWrapUICommand.h b/Source/cmFLTKWrapUICommand.h
index d8045ab6a..bb56dbd44 100644
--- a/Source/cmFLTKWrapUICommand.h
+++ b/Source/cmFLTKWrapUICommand.h
@@ -3,57 +3,14 @@
#ifndef cmFLTKWrapUICommand_h
#define cmFLTKWrapUICommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmSourceFile;
-
-/** \class cmFLTKWrapUICommand
- * \brief Create .h and .cxx files rules for FLTK user interfaces files
- *
- * cmFLTKWrapUICommand is used to create wrappers for FLTK classes into
- * normal C++
- */
-class cmFLTKWrapUICommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmFLTKWrapUICommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
- /**
- * This is called at the end after all the information
- * specified by the command is accumulated. Most commands do
- * not implement this method. At this point, reading and
- * writing to the cache can be done.
- */
- void FinalPass() CM_OVERRIDE;
- bool HasFinalPass() const CM_OVERRIDE { return true; }
-
-private:
- /**
- * List of produced files.
- */
- std::vector<cmSourceFile*> GeneratedSourcesClasses;
- /**
- * List of Fluid files that provide the source
- * generating .cxx and .h files
- */
- std::string Target;
-};
+bool cmFLTKWrapUICommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
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..fef72e616
--- /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 <string>
+
+#include "cm_sys_stat.h"
+
+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/cmFileAPI.cxx b/Source/cmFileAPI.cxx
new file mode 100644
index 000000000..a56ad22f6
--- /dev/null
+++ b/Source/cmFileAPI.cxx
@@ -0,0 +1,832 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFileAPI.h"
+
+#include <algorithm>
+#include <cassert>
+#include <chrono>
+#include <cstddef>
+#include <ctime>
+#include <iomanip>
+#include <sstream>
+#include <utility>
+
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+
+#include "cmCryptoHash.h"
+#include "cmFileAPICMakeFiles.h"
+#include "cmFileAPICache.h"
+#include "cmFileAPICodemodel.h"
+#include "cmGlobalGenerator.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmTimestamp.h"
+#include "cmake.h"
+
+cmFileAPI::cmFileAPI(cmake* cm)
+ : CMakeInstance(cm)
+{
+ this->APIv1 =
+ this->CMakeInstance->GetHomeOutputDirectory() + "/.cmake/api/v1";
+
+ Json::CharReaderBuilder rbuilder;
+ rbuilder["collectComments"] = false;
+ rbuilder["failIfExtra"] = true;
+ rbuilder["rejectDupKeys"] = false;
+ rbuilder["strictRoot"] = true;
+ this->JsonReader =
+ std::unique_ptr<Json::CharReader>(rbuilder.newCharReader());
+
+ Json::StreamWriterBuilder wbuilder;
+ wbuilder["indentation"] = "\t";
+ this->JsonWriter =
+ std::unique_ptr<Json::StreamWriter>(wbuilder.newStreamWriter());
+}
+
+void cmFileAPI::ReadQueries()
+{
+ std::string const query_dir = this->APIv1 + "/query";
+ this->QueryExists = cmSystemTools::FileIsDirectory(query_dir);
+ if (!this->QueryExists) {
+ return;
+ }
+
+ // Load queries at the top level.
+ std::vector<std::string> queries = cmFileAPI::LoadDir(query_dir);
+
+ // Read the queries and save for later.
+ for (std::string& query : queries) {
+ if (cmHasLiteralPrefix(query, "client-")) {
+ this->ReadClient(query);
+ } else if (!cmFileAPI::ReadQuery(query, this->TopQuery.Known)) {
+ this->TopQuery.Unknown.push_back(std::move(query));
+ }
+ }
+}
+
+void cmFileAPI::WriteReplies()
+{
+ if (this->QueryExists) {
+ cmSystemTools::MakeDirectory(this->APIv1 + "/reply");
+ this->WriteJsonFile(this->BuildReplyIndex(), "index", ComputeSuffixTime);
+ }
+
+ this->RemoveOldReplyFiles();
+}
+
+std::vector<std::string> cmFileAPI::LoadDir(std::string const& dir)
+{
+ std::vector<std::string> files;
+ cmsys::Directory d;
+ d.Load(dir);
+ for (unsigned long i = 0; i < d.GetNumberOfFiles(); ++i) {
+ std::string f = d.GetFile(i);
+ if (f != "." && f != "..") {
+ files.push_back(std::move(f));
+ }
+ }
+ std::sort(files.begin(), files.end());
+ return files;
+}
+
+void cmFileAPI::RemoveOldReplyFiles()
+{
+ std::string const reply_dir = this->APIv1 + "/reply";
+ std::vector<std::string> files = this->LoadDir(reply_dir);
+ for (std::string const& f : files) {
+ if (this->ReplyFiles.find(f) == this->ReplyFiles.end()) {
+ std::string file = cmStrCat(reply_dir, "/", f);
+ cmSystemTools::RemoveFile(file);
+ }
+ }
+}
+
+bool cmFileAPI::ReadJsonFile(std::string const& file, Json::Value& value,
+ std::string& error)
+{
+ std::vector<char> content;
+
+ cmsys::ifstream fin;
+ if (!cmSystemTools::FileIsDirectory(file)) {
+ fin.open(file.c_str(), std::ios::binary);
+ }
+ auto finEnd = fin.rdbuf()->pubseekoff(0, std::ios::end);
+ if (finEnd > 0) {
+ size_t finSize = finEnd;
+ try {
+ // Allocate a buffer to read the whole file.
+ content.resize(finSize);
+
+ // Now read the file from the beginning.
+ fin.seekg(0, std::ios::beg);
+ fin.read(content.data(), finSize);
+ } catch (...) {
+ fin.setstate(std::ios::failbit);
+ }
+ }
+ fin.close();
+ if (!fin) {
+ value = Json::Value();
+ error = "failed to read from file";
+ return false;
+ }
+
+ // Parse our buffer as json.
+ if (!this->JsonReader->parse(content.data(), content.data() + content.size(),
+ &value, &error)) {
+ value = Json::Value();
+ return false;
+ }
+
+ return true;
+}
+
+std::string cmFileAPI::WriteJsonFile(
+ Json::Value const& value, std::string const& prefix,
+ std::string (*computeSuffix)(std::string const&))
+{
+ std::string fileName;
+
+ // Write the json file with a temporary name.
+ std::string const& tmpFile = this->APIv1 + "/tmp.json";
+ cmsys::ofstream ftmp(tmpFile.c_str());
+ this->JsonWriter->write(value, &ftmp);
+ ftmp << "\n";
+ ftmp.close();
+ if (!ftmp) {
+ cmSystemTools::RemoveFile(tmpFile);
+ return fileName;
+ }
+
+ // Compute the final name for the file.
+ fileName = prefix + "-" + computeSuffix(tmpFile) + ".json";
+
+ // Create the destination.
+ std::string file = this->APIv1 + "/reply";
+ cmSystemTools::MakeDirectory(file);
+ file += "/";
+ file += fileName;
+
+ // If the final name already exists then assume it has proper content.
+ // Otherwise, atomically place the reply file at its final name
+ if (cmSystemTools::FileExists(file, true) ||
+ !cmSystemTools::RenameFile(tmpFile, file)) {
+ cmSystemTools::RemoveFile(tmpFile);
+ }
+
+ // Record this among files we have just written.
+ this->ReplyFiles.insert(fileName);
+
+ return fileName;
+}
+
+Json::Value cmFileAPI::MaybeJsonFile(Json::Value in, std::string const& prefix)
+{
+ Json::Value out;
+ if (in.isObject() || in.isArray()) {
+ out = Json::objectValue;
+ out["jsonFile"] = this->WriteJsonFile(in, prefix);
+ } else {
+ out = std::move(in);
+ }
+ return out;
+}
+
+std::string cmFileAPI::ComputeSuffixHash(std::string const& file)
+{
+ cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_256);
+ std::string hash = hasher.HashFile(file);
+ hash.resize(20, '0');
+ return hash;
+}
+
+std::string cmFileAPI::ComputeSuffixTime(std::string const&)
+{
+ std::chrono::milliseconds ms =
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::system_clock::now().time_since_epoch());
+ std::chrono::seconds s =
+ std::chrono::duration_cast<std::chrono::seconds>(ms);
+
+ std::time_t ts = s.count();
+ std::size_t tms = ms.count() % 1000;
+
+ cmTimestamp cmts;
+ std::ostringstream ss;
+ ss << cmts.CreateTimestampFromTimeT(ts, "%Y-%m-%dT%H-%M-%S", true) << '-'
+ << std::setfill('0') << std::setw(4) << tms;
+ return ss.str();
+}
+
+bool cmFileAPI::ReadQuery(std::string const& query,
+ std::vector<Object>& objects)
+{
+ // Parse the "<kind>-" syntax.
+ std::string::size_type sep_pos = query.find('-');
+ if (sep_pos == std::string::npos) {
+ return false;
+ }
+ std::string kindName = query.substr(0, sep_pos);
+ std::string verStr = query.substr(sep_pos + 1);
+ if (kindName == ObjectKindName(ObjectKind::CodeModel)) {
+ Object o;
+ o.Kind = ObjectKind::CodeModel;
+ if (verStr == "v2") {
+ o.Version = 2;
+ } else {
+ return false;
+ }
+ objects.push_back(o);
+ return true;
+ }
+ if (kindName == ObjectKindName(ObjectKind::Cache)) {
+ Object o;
+ o.Kind = ObjectKind::Cache;
+ if (verStr == "v2") {
+ o.Version = 2;
+ } else {
+ return false;
+ }
+ objects.push_back(o);
+ return true;
+ }
+ if (kindName == ObjectKindName(ObjectKind::CMakeFiles)) {
+ Object o;
+ o.Kind = ObjectKind::CMakeFiles;
+ if (verStr == "v1") {
+ o.Version = 1;
+ } else {
+ return false;
+ }
+ objects.push_back(o);
+ return true;
+ }
+ if (kindName == ObjectKindName(ObjectKind::InternalTest)) {
+ Object o;
+ o.Kind = ObjectKind::InternalTest;
+ if (verStr == "v1") {
+ o.Version = 1;
+ } else if (verStr == "v2") {
+ o.Version = 2;
+ } else {
+ return false;
+ }
+ objects.push_back(o);
+ return true;
+ }
+ return false;
+}
+
+void cmFileAPI::ReadClient(std::string const& client)
+{
+ // Load queries for the client.
+ std::string clientDir = this->APIv1 + "/query/" + client;
+ std::vector<std::string> queries = this->LoadDir(clientDir);
+
+ // Read the queries and save for later.
+ ClientQuery& clientQuery = this->ClientQueries[client];
+ for (std::string& query : queries) {
+ if (query == "query.json") {
+ clientQuery.HaveQueryJson = true;
+ this->ReadClientQuery(client, clientQuery.QueryJson);
+ } else if (!this->ReadQuery(query, clientQuery.DirQuery.Known)) {
+ clientQuery.DirQuery.Unknown.push_back(std::move(query));
+ }
+ }
+}
+
+void cmFileAPI::ReadClientQuery(std::string const& client, ClientQueryJson& q)
+{
+ // Read the query.json file.
+ std::string queryFile = this->APIv1 + "/query/" + client + "/query.json";
+ Json::Value query;
+ if (!this->ReadJsonFile(queryFile, query, q.Error)) {
+ return;
+ }
+ if (!query.isObject()) {
+ q.Error = "query root is not an object";
+ return;
+ }
+
+ Json::Value const& clientValue = query["client"];
+ if (!clientValue.isNull()) {
+ q.ClientValue = clientValue;
+ }
+ q.RequestsValue = std::move(query["requests"]);
+ q.Requests = this->BuildClientRequests(q.RequestsValue);
+}
+
+Json::Value cmFileAPI::BuildReplyIndex()
+{
+ Json::Value index(Json::objectValue);
+
+ // Report information about this version of CMake.
+ index["cmake"] = this->BuildCMake();
+
+ // Reply to all queries that we loaded.
+ Json::Value& reply = index["reply"] = this->BuildReply(this->TopQuery);
+ for (auto const& client : this->ClientQueries) {
+ std::string const& clientName = client.first;
+ ClientQuery const& clientQuery = client.second;
+ reply[clientName] = this->BuildClientReply(clientQuery);
+ }
+
+ // Move our index of generated objects into its field.
+ Json::Value& objects = index["objects"] = Json::arrayValue;
+ for (auto& entry : this->ReplyIndexObjects) {
+ objects.append(std::move(entry.second)); // NOLINT(*)
+ }
+
+ return index;
+}
+
+Json::Value cmFileAPI::BuildCMake()
+{
+ Json::Value cmake = Json::objectValue;
+ cmake["version"] = this->CMakeInstance->ReportVersionJson();
+ Json::Value& cmake_paths = cmake["paths"] = Json::objectValue;
+ cmake_paths["cmake"] = cmSystemTools::GetCMakeCommand();
+ cmake_paths["ctest"] = cmSystemTools::GetCTestCommand();
+ cmake_paths["cpack"] = cmSystemTools::GetCPackCommand();
+ cmake_paths["root"] = cmSystemTools::GetCMakeRoot();
+ cmake["generator"] = this->CMakeInstance->GetGlobalGenerator()->GetJson();
+ return cmake;
+}
+
+Json::Value cmFileAPI::BuildReply(Query const& q)
+{
+ Json::Value reply = Json::objectValue;
+ for (Object const& o : q.Known) {
+ std::string const& name = ObjectName(o);
+ reply[name] = this->AddReplyIndexObject(o);
+ }
+
+ for (std::string const& name : q.Unknown) {
+ reply[name] = cmFileAPI::BuildReplyError("unknown query file");
+ }
+ return reply;
+}
+
+Json::Value cmFileAPI::BuildReplyError(std::string const& error)
+{
+ Json::Value e = Json::objectValue;
+ e["error"] = error;
+ return e;
+}
+
+Json::Value const& cmFileAPI::AddReplyIndexObject(Object const& o)
+{
+ Json::Value& indexEntry = this->ReplyIndexObjects[o];
+ if (!indexEntry.isNull()) {
+ // The reply object has already been generated.
+ return indexEntry;
+ }
+
+ // Generate this reply object.
+ Json::Value const& object = this->BuildObject(o);
+ assert(object.isObject());
+
+ // Populate this index entry.
+ indexEntry = Json::objectValue;
+ indexEntry["kind"] = object["kind"];
+ indexEntry["version"] = object["version"];
+ indexEntry["jsonFile"] = this->WriteJsonFile(object, ObjectName(o));
+ return indexEntry;
+}
+
+const char* cmFileAPI::ObjectKindName(ObjectKind kind)
+{
+ // Keep in sync with ObjectKind enum.
+ static const char* objectKindNames[] = {
+ "codemodel", //
+ "cache", //
+ "cmakeFiles", //
+ "__test" //
+ };
+ return objectKindNames[size_t(kind)];
+}
+
+std::string cmFileAPI::ObjectName(Object const& o)
+{
+ std::string name = cmStrCat(ObjectKindName(o.Kind), "-v", o.Version);
+ return name;
+}
+
+Json::Value cmFileAPI::BuildVersion(unsigned int major, unsigned int minor)
+{
+ Json::Value version;
+ version["major"] = major;
+ version["minor"] = minor;
+ return version;
+}
+
+Json::Value cmFileAPI::BuildObject(Object const& object)
+{
+ Json::Value value;
+
+ switch (object.Kind) {
+ case ObjectKind::CodeModel:
+ value = this->BuildCodeModel(object);
+ break;
+ case ObjectKind::Cache:
+ value = this->BuildCache(object);
+ break;
+ case ObjectKind::CMakeFiles:
+ value = this->BuildCMakeFiles(object);
+ break;
+ case ObjectKind::InternalTest:
+ value = this->BuildInternalTest(object);
+ break;
+ }
+
+ return value;
+}
+
+cmFileAPI::ClientRequests cmFileAPI::BuildClientRequests(
+ Json::Value const& requests)
+{
+ ClientRequests result;
+ if (requests.isNull()) {
+ result.Error = "'requests' member missing";
+ return result;
+ }
+ if (!requests.isArray()) {
+ result.Error = "'requests' member is not an array";
+ return result;
+ }
+
+ result.reserve(requests.size());
+ for (Json::Value const& request : requests) {
+ result.emplace_back(this->BuildClientRequest(request));
+ }
+
+ return result;
+}
+
+cmFileAPI::ClientRequest cmFileAPI::BuildClientRequest(
+ Json::Value const& request)
+{
+ ClientRequest r;
+
+ if (!request.isObject()) {
+ r.Error = "request is not an object";
+ return r;
+ }
+
+ Json::Value const& kind = request["kind"];
+ if (kind.isNull()) {
+ r.Error = "'kind' member missing";
+ return r;
+ }
+ if (!kind.isString()) {
+ r.Error = "'kind' member is not a string";
+ return r;
+ }
+ std::string const& kindName = kind.asString();
+
+ if (kindName == this->ObjectKindName(ObjectKind::CodeModel)) {
+ r.Kind = ObjectKind::CodeModel;
+ } else if (kindName == this->ObjectKindName(ObjectKind::Cache)) {
+ r.Kind = ObjectKind::Cache;
+ } else if (kindName == this->ObjectKindName(ObjectKind::CMakeFiles)) {
+ r.Kind = ObjectKind::CMakeFiles;
+ } else if (kindName == this->ObjectKindName(ObjectKind::InternalTest)) {
+ r.Kind = ObjectKind::InternalTest;
+ } else {
+ r.Error = "unknown request kind '" + kindName + "'";
+ return r;
+ }
+
+ Json::Value const& version = request["version"];
+ if (version.isNull()) {
+ r.Error = "'version' member missing";
+ return r;
+ }
+ std::vector<RequestVersion> versions;
+ if (!cmFileAPI::ReadRequestVersions(version, versions, r.Error)) {
+ return r;
+ }
+
+ switch (r.Kind) {
+ case ObjectKind::CodeModel:
+ this->BuildClientRequestCodeModel(r, versions);
+ break;
+ case ObjectKind::Cache:
+ this->BuildClientRequestCache(r, versions);
+ break;
+ case ObjectKind::CMakeFiles:
+ this->BuildClientRequestCMakeFiles(r, versions);
+ break;
+ case ObjectKind::InternalTest:
+ this->BuildClientRequestInternalTest(r, versions);
+ break;
+ }
+
+ return r;
+}
+
+Json::Value cmFileAPI::BuildClientReply(ClientQuery const& q)
+{
+ Json::Value reply = this->BuildReply(q.DirQuery);
+
+ if (!q.HaveQueryJson) {
+ return reply;
+ }
+
+ Json::Value& reply_query_json = reply["query.json"];
+ ClientQueryJson const& qj = q.QueryJson;
+
+ if (!qj.Error.empty()) {
+ reply_query_json = this->BuildReplyError(qj.Error);
+ return reply;
+ }
+
+ if (!qj.ClientValue.isNull()) {
+ reply_query_json["client"] = qj.ClientValue;
+ }
+
+ if (!qj.RequestsValue.isNull()) {
+ reply_query_json["requests"] = qj.RequestsValue;
+ }
+
+ reply_query_json["responses"] = this->BuildClientReplyResponses(qj.Requests);
+
+ return reply;
+}
+
+Json::Value cmFileAPI::BuildClientReplyResponses(
+ ClientRequests const& requests)
+{
+ Json::Value responses;
+
+ if (!requests.Error.empty()) {
+ responses = this->BuildReplyError(requests.Error);
+ return responses;
+ }
+
+ responses = Json::arrayValue;
+ for (ClientRequest const& request : requests) {
+ responses.append(this->BuildClientReplyResponse(request));
+ }
+
+ return responses;
+}
+
+Json::Value cmFileAPI::BuildClientReplyResponse(ClientRequest const& request)
+{
+ Json::Value response;
+ if (!request.Error.empty()) {
+ response = this->BuildReplyError(request.Error);
+ return response;
+ }
+ response = this->AddReplyIndexObject(request);
+ return response;
+}
+
+bool cmFileAPI::ReadRequestVersions(Json::Value const& version,
+ std::vector<RequestVersion>& versions,
+ std::string& error)
+{
+ if (version.isArray()) {
+ for (Json::Value const& v : version) {
+ if (!ReadRequestVersion(v, /*inArray=*/true, versions, error)) {
+ return false;
+ }
+ }
+ } else {
+ if (!ReadRequestVersion(version, /*inArray=*/false, versions, error)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool cmFileAPI::ReadRequestVersion(Json::Value const& version, bool inArray,
+ std::vector<RequestVersion>& result,
+ std::string& error)
+{
+ if (version.isUInt()) {
+ RequestVersion v;
+ v.Major = version.asUInt();
+ result.push_back(v);
+ return true;
+ }
+
+ if (!version.isObject()) {
+ if (inArray) {
+ error = "'version' array entry is not a non-negative integer or object";
+ } else {
+ error =
+ "'version' member is not a non-negative integer, object, or array";
+ }
+ return false;
+ }
+
+ Json::Value const& major = version["major"];
+ if (major.isNull()) {
+ error = "'version' object 'major' member missing";
+ return false;
+ }
+ if (!major.isUInt()) {
+ error = "'version' object 'major' member is not a non-negative integer";
+ return false;
+ }
+
+ RequestVersion v;
+ v.Major = major.asUInt();
+
+ Json::Value const& minor = version["minor"];
+ if (minor.isUInt()) {
+ v.Minor = minor.asUInt();
+ } else if (!minor.isNull()) {
+ error = "'version' object 'minor' member is not a non-negative integer";
+ return false;
+ }
+
+ result.push_back(v);
+
+ return true;
+}
+
+std::string cmFileAPI::NoSupportedVersion(
+ std::vector<RequestVersion> const& versions)
+{
+ std::ostringstream msg;
+ msg << "no supported version specified";
+ if (!versions.empty()) {
+ msg << " among:";
+ for (RequestVersion const& v : versions) {
+ msg << " " << v.Major << "." << v.Minor;
+ }
+ }
+ return msg.str();
+}
+
+// The "codemodel" object kind.
+
+static unsigned int const CodeModelV2Minor = 0;
+
+void cmFileAPI::BuildClientRequestCodeModel(
+ ClientRequest& r, std::vector<RequestVersion> const& versions)
+{
+ // Select a known version from those requested.
+ for (RequestVersion const& v : versions) {
+ if ((v.Major == 2 && v.Minor <= CodeModelV2Minor)) {
+ r.Version = v.Major;
+ break;
+ }
+ }
+ if (!r.Version) {
+ r.Error = NoSupportedVersion(versions);
+ }
+}
+
+Json::Value cmFileAPI::BuildCodeModel(Object const& object)
+{
+ Json::Value codemodel = cmFileAPICodemodelDump(*this, object.Version);
+ codemodel["kind"] = this->ObjectKindName(object.Kind);
+
+ Json::Value& version = codemodel["version"];
+ if (object.Version == 2) {
+ version = BuildVersion(2, CodeModelV2Minor);
+ } else {
+ return codemodel; // should be unreachable
+ }
+
+ return codemodel;
+}
+
+// The "cache" object kind.
+
+static unsigned int const CacheV2Minor = 0;
+
+void cmFileAPI::BuildClientRequestCache(
+ ClientRequest& r, std::vector<RequestVersion> const& versions)
+{
+ // Select a known version from those requested.
+ for (RequestVersion const& v : versions) {
+ if ((v.Major == 2 && v.Minor <= CacheV2Minor)) {
+ r.Version = v.Major;
+ break;
+ }
+ }
+ if (!r.Version) {
+ r.Error = NoSupportedVersion(versions);
+ }
+}
+
+Json::Value cmFileAPI::BuildCache(Object const& object)
+{
+ Json::Value cache = cmFileAPICacheDump(*this, object.Version);
+ cache["kind"] = this->ObjectKindName(object.Kind);
+
+ Json::Value& version = cache["version"];
+ if (object.Version == 2) {
+ version = BuildVersion(2, CacheV2Minor);
+ } else {
+ return cache; // should be unreachable
+ }
+
+ return cache;
+}
+
+// The "cmakeFiles" object kind.
+
+static unsigned int const CMakeFilesV1Minor = 0;
+
+void cmFileAPI::BuildClientRequestCMakeFiles(
+ ClientRequest& r, std::vector<RequestVersion> const& versions)
+{
+ // Select a known version from those requested.
+ for (RequestVersion const& v : versions) {
+ if ((v.Major == 1 && v.Minor <= CMakeFilesV1Minor)) {
+ r.Version = v.Major;
+ break;
+ }
+ }
+ if (!r.Version) {
+ r.Error = NoSupportedVersion(versions);
+ }
+}
+
+Json::Value cmFileAPI::BuildCMakeFiles(Object const& object)
+{
+ Json::Value cmakeFiles = cmFileAPICMakeFilesDump(*this, object.Version);
+ cmakeFiles["kind"] = this->ObjectKindName(object.Kind);
+
+ Json::Value& version = cmakeFiles["version"];
+ if (object.Version == 1) {
+ version = BuildVersion(1, CMakeFilesV1Minor);
+ } else {
+ return cmakeFiles; // should be unreachable
+ }
+
+ return cmakeFiles;
+}
+
+// The "__test" object kind is for internal testing of CMake.
+
+static unsigned int const InternalTestV1Minor = 3;
+static unsigned int const InternalTestV2Minor = 0;
+
+void cmFileAPI::BuildClientRequestInternalTest(
+ ClientRequest& r, std::vector<RequestVersion> const& versions)
+{
+ // Select a known version from those requested.
+ for (RequestVersion const& v : versions) {
+ if ((v.Major == 1 && v.Minor <= InternalTestV1Minor) || //
+ (v.Major == 2 && v.Minor <= InternalTestV2Minor)) {
+ r.Version = v.Major;
+ break;
+ }
+ }
+ if (!r.Version) {
+ r.Error = NoSupportedVersion(versions);
+ }
+}
+
+Json::Value cmFileAPI::BuildInternalTest(Object const& object)
+{
+ Json::Value test = Json::objectValue;
+ test["kind"] = this->ObjectKindName(object.Kind);
+ Json::Value& version = test["version"];
+ if (object.Version == 2) {
+ version = BuildVersion(2, InternalTestV2Minor);
+ } else {
+ version = BuildVersion(1, InternalTestV1Minor);
+ }
+ return test;
+}
+
+Json::Value cmFileAPI::ReportCapabilities()
+{
+ Json::Value capabilities = Json::objectValue;
+ Json::Value& requests = capabilities["requests"] = Json::arrayValue;
+
+ {
+ Json::Value request = Json::objectValue;
+ request["kind"] = ObjectKindName(ObjectKind::CodeModel);
+ Json::Value& versions = request["version"] = Json::arrayValue;
+ versions.append(BuildVersion(2, CodeModelV2Minor));
+ requests.append(std::move(request)); // NOLINT(*)
+ }
+
+ {
+ Json::Value request = Json::objectValue;
+ request["kind"] = ObjectKindName(ObjectKind::Cache);
+ Json::Value& versions = request["version"] = Json::arrayValue;
+ versions.append(BuildVersion(2, CacheV2Minor));
+ requests.append(std::move(request)); // NOLINT(*)
+ }
+
+ {
+ Json::Value request = Json::objectValue;
+ request["kind"] = ObjectKindName(ObjectKind::CMakeFiles);
+ Json::Value& versions = request["version"] = Json::arrayValue;
+ versions.append(BuildVersion(1, CMakeFilesV1Minor));
+ requests.append(std::move(request)); // NOLINT(*)
+ }
+
+ return capabilities;
+}
diff --git a/Source/cmFileAPI.h b/Source/cmFileAPI.h
new file mode 100644
index 000000000..e183e0d97
--- /dev/null
+++ b/Source/cmFileAPI.h
@@ -0,0 +1,209 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmFileAPI_h
+#define cmFileAPI_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <memory>
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+#include "cm_jsoncpp_reader.h"
+#include "cm_jsoncpp_value.h"
+#include "cm_jsoncpp_writer.h"
+
+class cmake;
+
+class cmFileAPI
+{
+public:
+ cmFileAPI(cmake* cm);
+
+ /** Read fileapi queries from disk. */
+ void ReadQueries();
+
+ /** Write fileapi replies to disk. */
+ void WriteReplies();
+
+ /** Get the "cmake" instance with which this was constructed. */
+ cmake* GetCMakeInstance() const { return this->CMakeInstance; }
+
+ /** Convert a JSON object or array into an object with a single
+ "jsonFile" member specifying a file named with the given prefix
+ and holding the original object. Other JSON types are unchanged. */
+ Json::Value MaybeJsonFile(Json::Value in, std::string const& prefix);
+
+ /** Report file-api capabilities for cmake -E capabilities. */
+ static Json::Value ReportCapabilities();
+
+private:
+ cmake* CMakeInstance;
+
+ /** The api/v1 directory location. */
+ std::string APIv1;
+
+ /** The set of files we have just written to the reply directory. */
+ std::unordered_set<std::string> ReplyFiles;
+
+ static std::vector<std::string> LoadDir(std::string const& dir);
+ void RemoveOldReplyFiles();
+
+ // Keep in sync with ObjectKindName.
+ enum class ObjectKind
+ {
+ CodeModel,
+ Cache,
+ CMakeFiles,
+ InternalTest
+ };
+
+ /** Identify one object kind and major version. */
+ struct Object
+ {
+ ObjectKind Kind;
+ unsigned long Version = 0;
+ friend bool operator<(Object const& l, Object const& r)
+ {
+ if (l.Kind != r.Kind) {
+ return l.Kind < r.Kind;
+ }
+ return l.Version < r.Version;
+ }
+ };
+
+ /** Represent content of a query directory. */
+ struct Query
+ {
+ /** Known object kind-version pairs. */
+ std::vector<Object> Known;
+ /** Unknown object kind names. */
+ std::vector<std::string> Unknown;
+ };
+
+ /** Represent one request in a client 'query.json'. */
+ struct ClientRequest : public Object
+ {
+ /** Empty if request is valid, else the error string. */
+ std::string Error;
+ };
+
+ /** Represent the "requests" in a client 'query.json'. */
+ struct ClientRequests : public std::vector<ClientRequest>
+ {
+ /** Empty if requests field is valid, else the error string. */
+ std::string Error;
+ };
+
+ /** Represent the content of a client query.json file. */
+ struct ClientQueryJson
+ {
+ /** The error string if parsing failed, else empty. */
+ std::string Error;
+
+ /** The 'query.json' object "client" member if it exists, else null. */
+ Json::Value ClientValue;
+
+ /** The 'query.json' object "requests" member if it exists, else null. */
+ Json::Value RequestsValue;
+
+ /** Requests extracted from 'query.json'. */
+ ClientRequests Requests;
+ };
+
+ /** Represent content of a client query directory. */
+ struct ClientQuery
+ {
+ /** The content of the client query directory except 'query.json'. */
+ Query DirQuery;
+
+ /** True if 'query.json' exists. */
+ bool HaveQueryJson = false;
+
+ /** The 'query.json' content. */
+ ClientQueryJson QueryJson;
+ };
+
+ /** Whether the top-level query directory exists at all. */
+ bool QueryExists = false;
+
+ /** The content of the top-level query directory. */
+ Query TopQuery;
+
+ /** The content of each "client-$client" query directory. */
+ std::map<std::string, ClientQuery> ClientQueries;
+
+ /** Reply index object generated for object kind/version.
+ This populates the "objects" field of the reply index. */
+ std::map<Object, Json::Value> ReplyIndexObjects;
+
+ std::unique_ptr<Json::CharReader> JsonReader;
+ std::unique_ptr<Json::StreamWriter> JsonWriter;
+
+ bool ReadJsonFile(std::string const& file, Json::Value& value,
+ std::string& error);
+
+ std::string WriteJsonFile(
+ Json::Value const& value, std::string const& prefix,
+ std::string (*computeSuffix)(std::string const&) = ComputeSuffixHash);
+ static std::string ComputeSuffixHash(std::string const&);
+ static std::string ComputeSuffixTime(std::string const&);
+
+ static bool ReadQuery(std::string const& query,
+ std::vector<Object>& objects);
+ void ReadClient(std::string const& client);
+ void ReadClientQuery(std::string const& client, ClientQueryJson& q);
+
+ Json::Value BuildReplyIndex();
+ Json::Value BuildCMake();
+ Json::Value BuildReply(Query const& q);
+ static Json::Value BuildReplyError(std::string const& error);
+ Json::Value const& AddReplyIndexObject(Object const& o);
+
+ static const char* ObjectKindName(ObjectKind kind);
+ static std::string ObjectName(Object const& o);
+
+ static Json::Value BuildVersion(unsigned int major, unsigned int minor);
+
+ Json::Value BuildObject(Object const& object);
+
+ ClientRequests BuildClientRequests(Json::Value const& requests);
+ ClientRequest BuildClientRequest(Json::Value const& request);
+ Json::Value BuildClientReply(ClientQuery const& q);
+ Json::Value BuildClientReplyResponses(ClientRequests const& requests);
+ Json::Value BuildClientReplyResponse(ClientRequest const& request);
+
+ struct RequestVersion
+ {
+ unsigned int Major = 0;
+ unsigned int Minor = 0;
+ };
+ static bool ReadRequestVersions(Json::Value const& version,
+ std::vector<RequestVersion>& versions,
+ std::string& error);
+ static bool ReadRequestVersion(Json::Value const& version, bool inArray,
+ std::vector<RequestVersion>& result,
+ std::string& error);
+ static std::string NoSupportedVersion(
+ std::vector<RequestVersion> const& versions);
+
+ void BuildClientRequestCodeModel(
+ ClientRequest& r, std::vector<RequestVersion> const& versions);
+ Json::Value BuildCodeModel(Object const& object);
+
+ void BuildClientRequestCache(ClientRequest& r,
+ std::vector<RequestVersion> const& versions);
+ Json::Value BuildCache(Object const& object);
+
+ void BuildClientRequestCMakeFiles(
+ ClientRequest& r, std::vector<RequestVersion> const& versions);
+ Json::Value BuildCMakeFiles(Object const& object);
+
+ void BuildClientRequestInternalTest(
+ ClientRequest& r, std::vector<RequestVersion> const& versions);
+ Json::Value BuildInternalTest(Object const& object);
+};
+
+#endif
diff --git a/Source/cmFileAPICMakeFiles.cxx b/Source/cmFileAPICMakeFiles.cxx
new file mode 100644
index 000000000..f41999771
--- /dev/null
+++ b/Source/cmFileAPICMakeFiles.cxx
@@ -0,0 +1,114 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFileAPICMakeFiles.h"
+
+#include <string>
+#include <vector>
+
+#include "cm_jsoncpp_value.h"
+
+#include "cmFileAPI.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+namespace {
+
+class CMakeFiles
+{
+ cmFileAPI& FileAPI;
+ unsigned long Version;
+ std::string CMakeModules;
+ std::string const& TopSource;
+ std::string const& TopBuild;
+ bool OutOfSource;
+
+ Json::Value DumpPaths();
+ Json::Value DumpInputs();
+ Json::Value DumpInput(std::string const& file);
+
+public:
+ CMakeFiles(cmFileAPI& fileAPI, unsigned long version);
+ Json::Value Dump();
+};
+
+CMakeFiles::CMakeFiles(cmFileAPI& fileAPI, unsigned long version)
+ : FileAPI(fileAPI)
+ , Version(version)
+ , CMakeModules(cmSystemTools::GetCMakeRoot() + "/Modules")
+ , TopSource(this->FileAPI.GetCMakeInstance()->GetHomeDirectory())
+ , TopBuild(this->FileAPI.GetCMakeInstance()->GetHomeOutputDirectory())
+ , OutOfSource(TopBuild != TopSource)
+{
+ static_cast<void>(this->Version);
+}
+
+Json::Value CMakeFiles::Dump()
+{
+ Json::Value cmakeFiles = Json::objectValue;
+ cmakeFiles["paths"] = this->DumpPaths();
+ cmakeFiles["inputs"] = DumpInputs();
+ return cmakeFiles;
+}
+
+Json::Value CMakeFiles::DumpPaths()
+{
+ Json::Value paths = Json::objectValue;
+ paths["source"] = this->TopSource;
+ paths["build"] = this->TopBuild;
+ return paths;
+}
+
+Json::Value CMakeFiles::DumpInputs()
+{
+ Json::Value inputs = Json::arrayValue;
+
+ cmGlobalGenerator* gg =
+ this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
+ for (cmLocalGenerator const* lg : gg->GetLocalGenerators()) {
+ cmMakefile const* mf = lg->GetMakefile();
+ for (std::string const& file : mf->GetListFiles()) {
+ inputs.append(this->DumpInput(file));
+ }
+ }
+
+ return inputs;
+}
+
+Json::Value CMakeFiles::DumpInput(std::string const& file)
+{
+ Json::Value input = Json::objectValue;
+
+ bool const isCMake = cmSystemTools::IsSubDirectory(file, this->CMakeModules);
+ if (isCMake) {
+ input["isCMake"] = true;
+ }
+
+ if (!cmSystemTools::IsSubDirectory(file, this->TopSource) &&
+ !cmSystemTools::IsSubDirectory(file, this->TopBuild)) {
+ input["isExternal"] = true;
+ }
+
+ if (this->OutOfSource &&
+ cmSystemTools::IsSubDirectory(file, this->TopBuild)) {
+ input["isGenerated"] = true;
+ }
+
+ std::string path = file;
+ if (!isCMake && cmSystemTools::IsSubDirectory(path, this->TopSource)) {
+ // Use a relative path within the source directory.
+ path = cmSystemTools::RelativePath(this->TopSource, path);
+ }
+ input["path"] = path;
+
+ return input;
+}
+}
+
+Json::Value cmFileAPICMakeFilesDump(cmFileAPI& fileAPI, unsigned long version)
+{
+ CMakeFiles cmakeFiles(fileAPI, version);
+ return cmakeFiles.Dump();
+}
diff --git a/Source/cmFileAPICMakeFiles.h b/Source/cmFileAPICMakeFiles.h
new file mode 100644
index 000000000..a851c32f4
--- /dev/null
+++ b/Source/cmFileAPICMakeFiles.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 cmFileAPICMakeFiles_h
+#define cmFileAPICMakeFiles_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cm_jsoncpp_value.h"
+
+class cmFileAPI;
+
+extern Json::Value cmFileAPICMakeFilesDump(cmFileAPI& fileAPI,
+ unsigned long version);
+
+#endif
diff --git a/Source/cmFileAPICache.cxx b/Source/cmFileAPICache.cxx
new file mode 100644
index 000000000..ef7779567
--- /dev/null
+++ b/Source/cmFileAPICache.cxx
@@ -0,0 +1,106 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFileAPICache.h"
+
+#include <algorithm>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cm_jsoncpp_value.h"
+
+#include "cmFileAPI.h"
+#include "cmState.h"
+#include "cmake.h"
+
+namespace {
+
+class Cache
+{
+ cmFileAPI& FileAPI;
+ unsigned long Version;
+ cmState* State;
+
+ Json::Value DumpEntries();
+ Json::Value DumpEntry(std::string const& name);
+ Json::Value DumpEntryProperties(std::string const& name);
+ Json::Value DumpEntryProperty(std::string const& name,
+ std::string const& prop);
+
+public:
+ Cache(cmFileAPI& fileAPI, unsigned long version);
+ Json::Value Dump();
+};
+
+Cache::Cache(cmFileAPI& fileAPI, unsigned long version)
+ : FileAPI(fileAPI)
+ , Version(version)
+ , State(this->FileAPI.GetCMakeInstance()->GetState())
+{
+ static_cast<void>(this->Version);
+}
+
+Json::Value Cache::Dump()
+{
+ Json::Value cache = Json::objectValue;
+ cache["entries"] = DumpEntries();
+ return cache;
+}
+
+Json::Value Cache::DumpEntries()
+{
+ Json::Value entries = Json::arrayValue;
+
+ std::vector<std::string> names = this->State->GetCacheEntryKeys();
+ std::sort(names.begin(), names.end());
+
+ for (std::string const& name : names) {
+ entries.append(this->DumpEntry(name));
+ }
+
+ return entries;
+}
+
+Json::Value Cache::DumpEntry(std::string const& name)
+{
+ Json::Value entry = Json::objectValue;
+ entry["name"] = name;
+ entry["type"] =
+ cmState::CacheEntryTypeToString(this->State->GetCacheEntryType(name));
+ entry["value"] = this->State->GetCacheEntryValue(name);
+
+ Json::Value properties = this->DumpEntryProperties(name);
+ if (!properties.empty()) {
+ entry["properties"] = std::move(properties);
+ }
+
+ return entry;
+}
+
+Json::Value Cache::DumpEntryProperties(std::string const& name)
+{
+ Json::Value properties = Json::arrayValue;
+ std::vector<std::string> props =
+ this->State->GetCacheEntryPropertyList(name);
+ std::sort(props.begin(), props.end());
+ for (std::string const& prop : props) {
+ properties.append(this->DumpEntryProperty(name, prop));
+ }
+ return properties;
+}
+
+Json::Value Cache::DumpEntryProperty(std::string const& name,
+ std::string const& prop)
+{
+ Json::Value property = Json::objectValue;
+ property["name"] = prop;
+ property["value"] = this->State->GetCacheEntryProperty(name, prop);
+ return property;
+}
+}
+
+Json::Value cmFileAPICacheDump(cmFileAPI& fileAPI, unsigned long version)
+{
+ Cache cache(fileAPI, version);
+ return cache.Dump();
+}
diff --git a/Source/cmFileAPICache.h b/Source/cmFileAPICache.h
new file mode 100644
index 000000000..09d9e1ce9
--- /dev/null
+++ b/Source/cmFileAPICache.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 cmFileAPICache_h
+#define cmFileAPICache_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cm_jsoncpp_value.h"
+
+class cmFileAPI;
+
+extern Json::Value cmFileAPICacheDump(cmFileAPI& fileAPI,
+ unsigned long version);
+
+#endif
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
new file mode 100644
index 000000000..d7993c7d9
--- /dev/null
+++ b/Source/cmFileAPICodemodel.cxx
@@ -0,0 +1,1424 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFileAPICodemodel.h"
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <functional>
+#include <limits>
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include "cm_jsoncpp_value.h"
+
+#include "cmAlgorithms.h"
+#include "cmCryptoHash.h"
+#include "cmFileAPI.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstallGenerator.h"
+#include "cmInstallSubdirectoryGenerator.h"
+#include "cmInstallTargetGenerator.h"
+#include "cmLinkLineComputer.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmSourceFile.h"
+#include "cmSourceGroup.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmTargetDepend.h"
+#include "cmake.h"
+
+namespace {
+
+class Codemodel
+{
+ cmFileAPI& FileAPI;
+ unsigned long Version;
+
+ Json::Value DumpPaths();
+ Json::Value DumpConfigurations();
+ Json::Value DumpConfiguration(std::string const& config);
+
+public:
+ Codemodel(cmFileAPI& fileAPI, unsigned long version);
+ Json::Value Dump();
+};
+
+class CodemodelConfig
+{
+ cmFileAPI& FileAPI;
+ unsigned long Version;
+ std::string const& Config;
+ std::string TopSource;
+ std::string TopBuild;
+
+ struct Directory
+ {
+ cmStateSnapshot Snapshot;
+ cmLocalGenerator const* LocalGenerator = nullptr;
+ Json::Value TargetIndexes = Json::arrayValue;
+ Json::ArrayIndex ProjectIndex;
+ bool HasInstallRule = false;
+ };
+ std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder>
+ DirectoryMap;
+ std::vector<Directory> Directories;
+
+ struct Project
+ {
+ cmStateSnapshot Snapshot;
+ static const Json::ArrayIndex NoParentIndex =
+ static_cast<Json::ArrayIndex>(-1);
+ Json::ArrayIndex ParentIndex = NoParentIndex;
+ Json::Value ChildIndexes = Json::arrayValue;
+ Json::Value DirectoryIndexes = Json::arrayValue;
+ Json::Value TargetIndexes = Json::arrayValue;
+ };
+ std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder>
+ ProjectMap;
+ std::vector<Project> Projects;
+
+ void ProcessDirectories();
+
+ Json::ArrayIndex GetDirectoryIndex(cmLocalGenerator const* lg);
+ Json::ArrayIndex GetDirectoryIndex(cmStateSnapshot s);
+
+ Json::ArrayIndex AddProject(cmStateSnapshot s);
+
+ Json::Value DumpTargets();
+ Json::Value DumpTarget(cmGeneratorTarget* gt, Json::ArrayIndex ti);
+
+ Json::Value DumpDirectories();
+ Json::Value DumpDirectory(Directory& d);
+
+ Json::Value DumpProjects();
+ Json::Value DumpProject(Project& p);
+
+ Json::Value DumpMinimumCMakeVersion(cmStateSnapshot s);
+
+public:
+ CodemodelConfig(cmFileAPI& fileAPI, unsigned long version,
+ std::string const& config);
+ Json::Value Dump();
+};
+
+std::string RelativeIfUnder(std::string const& top, std::string const& in)
+{
+ std::string out;
+ if (in == top) {
+ out = ".";
+ } else if (cmSystemTools::IsSubDirectory(in, top)) {
+ out = in.substr(top.size() + 1);
+ } else {
+ out = in;
+ }
+ return out;
+}
+
+std::string TargetId(cmGeneratorTarget const* gt, std::string const& topBuild)
+{
+ cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_256);
+ std::string path = RelativeIfUnder(
+ topBuild, gt->GetLocalGenerator()->GetCurrentBinaryDirectory());
+ std::string hash = hasher.HashString(path);
+ hash.resize(20, '0');
+ return gt->GetName() + CMAKE_DIRECTORY_ID_SEP + hash;
+}
+
+class JBTIndex
+{
+public:
+ JBTIndex() = default;
+ explicit operator bool() const { return Index != None; }
+ Json::ArrayIndex Index = None;
+ static Json::ArrayIndex const None = static_cast<Json::ArrayIndex>(-1);
+};
+
+template <typename T>
+class JBT
+{
+public:
+ JBT(T v = T(), JBTIndex bt = JBTIndex())
+ : Value(std::move(v))
+ , Backtrace(bt)
+ {
+ }
+ T Value;
+ JBTIndex Backtrace;
+ friend bool operator==(JBT<T> const& l, JBT<T> const& r)
+ {
+ return l.Value == r.Value && l.Backtrace.Index == r.Backtrace.Index;
+ }
+ static bool ValueEq(JBT<T> const& l, JBT<T> const& r)
+ {
+ return l.Value == r.Value;
+ }
+ static bool ValueLess(JBT<T> const& l, JBT<T> const& r)
+ {
+ return l.Value < r.Value;
+ }
+};
+
+class BacktraceData
+{
+ std::string TopSource;
+ std::unordered_map<std::string, Json::ArrayIndex> CommandMap;
+ std::unordered_map<std::string, Json::ArrayIndex> FileMap;
+ std::unordered_map<cmListFileContext const*, Json::ArrayIndex> NodeMap;
+ Json::Value Commands = Json::arrayValue;
+ Json::Value Files = Json::arrayValue;
+ Json::Value Nodes = Json::arrayValue;
+
+ Json::ArrayIndex AddCommand(std::string const& command)
+ {
+ auto i = this->CommandMap.find(command);
+ if (i == this->CommandMap.end()) {
+ auto cmdIndex = static_cast<Json::ArrayIndex>(this->Commands.size());
+ i = this->CommandMap.emplace(command, cmdIndex).first;
+ this->Commands.append(command);
+ }
+ return i->second;
+ }
+
+ Json::ArrayIndex AddFile(std::string const& file)
+ {
+ auto i = this->FileMap.find(file);
+ if (i == this->FileMap.end()) {
+ auto fileIndex = static_cast<Json::ArrayIndex>(this->Files.size());
+ i = this->FileMap.emplace(file, fileIndex).first;
+ this->Files.append(RelativeIfUnder(this->TopSource, file));
+ }
+ return i->second;
+ }
+
+public:
+ BacktraceData(std::string topSource);
+ JBTIndex Add(cmListFileBacktrace const& bt);
+ Json::Value Dump();
+};
+
+BacktraceData::BacktraceData(std::string topSource)
+ : TopSource(std::move(topSource))
+{
+}
+
+JBTIndex BacktraceData::Add(cmListFileBacktrace const& bt)
+{
+ JBTIndex index;
+ if (bt.Empty()) {
+ return index;
+ }
+ cmListFileContext const* top = &bt.Top();
+ auto found = this->NodeMap.find(top);
+ if (found != this->NodeMap.end()) {
+ index.Index = found->second;
+ return index;
+ }
+ Json::Value entry = Json::objectValue;
+ entry["file"] = this->AddFile(top->FilePath);
+ if (top->Line) {
+ entry["line"] = static_cast<int>(top->Line);
+ }
+ if (!top->Name.empty()) {
+ entry["command"] = this->AddCommand(top->Name);
+ }
+ if (JBTIndex parent = this->Add(bt.Pop())) {
+ entry["parent"] = parent.Index;
+ }
+ index.Index = this->NodeMap[top] = this->Nodes.size();
+ this->Nodes.append(std::move(entry)); // NOLINT(*)
+ return index;
+}
+
+Json::Value BacktraceData::Dump()
+{
+ Json::Value backtraceGraph;
+ this->CommandMap.clear();
+ this->FileMap.clear();
+ this->NodeMap.clear();
+ backtraceGraph["commands"] = std::move(this->Commands);
+ backtraceGraph["files"] = std::move(this->Files);
+ backtraceGraph["nodes"] = std::move(this->Nodes);
+ return backtraceGraph;
+}
+
+struct CompileData
+{
+ struct IncludeEntry
+ {
+ JBT<std::string> Path;
+ bool IsSystem = false;
+ IncludeEntry(JBT<std::string> path, bool isSystem)
+ : Path(std::move(path))
+ , IsSystem(isSystem)
+ {
+ }
+ friend bool operator==(IncludeEntry const& l, IncludeEntry const& r)
+ {
+ return l.Path == r.Path && l.IsSystem == r.IsSystem;
+ }
+ };
+
+ std::string Language;
+ std::string Sysroot;
+ std::vector<JBT<std::string>> Flags;
+ std::vector<JBT<std::string>> Defines;
+ std::vector<IncludeEntry> Includes;
+
+ friend bool operator==(CompileData const& l, CompileData const& r)
+ {
+ return (l.Language == r.Language && l.Sysroot == r.Sysroot &&
+ l.Flags == r.Flags && l.Defines == r.Defines &&
+ l.Includes == r.Includes);
+ }
+};
+}
+
+namespace std {
+
+template <>
+struct hash<CompileData>
+{
+ std::size_t operator()(CompileData const& in) const
+ {
+ using std::hash;
+ size_t result =
+ hash<std::string>()(in.Language) ^ hash<std::string>()(in.Sysroot);
+ for (auto const& i : in.Includes) {
+ result = result ^
+ (hash<std::string>()(i.Path.Value) ^
+ hash<Json::ArrayIndex>()(i.Path.Backtrace.Index) ^
+ (i.IsSystem ? std::numeric_limits<size_t>::max() : 0));
+ }
+ for (auto const& i : in.Flags) {
+ result = result ^ hash<std::string>()(i.Value) ^
+ hash<Json::ArrayIndex>()(i.Backtrace.Index);
+ }
+ for (auto const& i : in.Defines) {
+ result = result ^ hash<std::string>()(i.Value) ^
+ hash<Json::ArrayIndex>()(i.Backtrace.Index);
+ }
+ return result;
+ }
+};
+
+} // namespace std
+
+namespace {
+class Target
+{
+ cmGeneratorTarget* GT;
+ std::string const& Config;
+ std::string TopSource;
+ std::string TopBuild;
+ std::vector<cmSourceGroup> SourceGroupsLocal;
+ BacktraceData Backtraces;
+
+ std::map<std::string, CompileData> CompileDataMap;
+
+ std::unordered_map<cmSourceFile const*, Json::ArrayIndex> SourceMap;
+ Json::Value Sources = Json::arrayValue;
+
+ struct SourceGroup
+ {
+ std::string Name;
+ Json::Value SourceIndexes = Json::arrayValue;
+ };
+ std::unordered_map<cmSourceGroup const*, Json::ArrayIndex> SourceGroupsMap;
+ std::vector<SourceGroup> SourceGroups;
+
+ struct CompileGroup
+ {
+ std::unordered_map<CompileData, Json::ArrayIndex>::iterator Entry;
+ Json::Value SourceIndexes = Json::arrayValue;
+ };
+ std::unordered_map<CompileData, Json::ArrayIndex> CompileGroupMap;
+ std::vector<CompileGroup> CompileGroups;
+
+ template <typename T>
+ JBT<T> ToJBT(BT<T> const& bt)
+ {
+ return JBT<T>(bt.Value, this->Backtraces.Add(bt.Backtrace));
+ }
+
+ void ProcessLanguages();
+ void ProcessLanguage(std::string const& lang);
+
+ Json::ArrayIndex AddSourceGroup(cmSourceGroup* sg, Json::ArrayIndex si);
+ CompileData BuildCompileData(cmSourceFile* sf);
+ CompileData MergeCompileData(CompileData const& fd);
+ Json::ArrayIndex AddSourceCompileGroup(cmSourceFile* sf,
+ Json::ArrayIndex si);
+ void AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt);
+ void AddBacktrace(Json::Value& object, JBTIndex bt);
+ Json::Value DumpPaths();
+ Json::Value DumpCompileData(CompileData const& cd);
+ Json::Value DumpInclude(CompileData::IncludeEntry const& inc);
+ Json::Value DumpDefine(JBT<std::string> const& def);
+ Json::Value DumpSources();
+ Json::Value DumpSource(cmGeneratorTarget::SourceAndKind const& sk,
+ Json::ArrayIndex si);
+ Json::Value DumpSourceGroups();
+ Json::Value DumpSourceGroup(SourceGroup& sg);
+ Json::Value DumpCompileGroups();
+ Json::Value DumpCompileGroup(CompileGroup& cg);
+ Json::Value DumpSysroot(std::string const& path);
+ Json::Value DumpInstall();
+ Json::Value DumpInstallPrefix();
+ Json::Value DumpInstallDestinations();
+ Json::Value DumpInstallDestination(cmInstallTargetGenerator* itGen);
+ Json::Value DumpArtifacts();
+ Json::Value DumpLink();
+ Json::Value DumpArchive();
+ Json::Value DumpLinkCommandFragments();
+ Json::Value DumpCommandFragments(std::vector<JBT<std::string>> const& frags);
+ Json::Value DumpCommandFragment(JBT<std::string> const& frag,
+ std::string const& role = std::string());
+ Json::Value DumpDependencies();
+ Json::Value DumpDependency(cmTargetDepend const& td);
+ Json::Value DumpFolder();
+
+public:
+ Target(cmGeneratorTarget* gt, std::string const& config);
+ Json::Value Dump();
+};
+
+Codemodel::Codemodel(cmFileAPI& fileAPI, unsigned long version)
+ : FileAPI(fileAPI)
+ , Version(version)
+{
+}
+
+Json::Value Codemodel::Dump()
+{
+ Json::Value codemodel = Json::objectValue;
+
+ codemodel["paths"] = this->DumpPaths();
+ codemodel["configurations"] = this->DumpConfigurations();
+
+ return codemodel;
+}
+
+Json::Value Codemodel::DumpPaths()
+{
+ Json::Value paths = Json::objectValue;
+ paths["source"] = this->FileAPI.GetCMakeInstance()->GetHomeDirectory();
+ paths["build"] = this->FileAPI.GetCMakeInstance()->GetHomeOutputDirectory();
+ return paths;
+}
+
+Json::Value Codemodel::DumpConfigurations()
+{
+ Json::Value configurations = Json::arrayValue;
+ cmGlobalGenerator* gg =
+ this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
+ auto makefiles = gg->GetMakefiles();
+ if (!makefiles.empty()) {
+ std::vector<std::string> const& configs =
+ makefiles[0]->GetGeneratorConfigs();
+ for (std::string const& config : configs) {
+ configurations.append(this->DumpConfiguration(config));
+ }
+ }
+ return configurations;
+}
+
+Json::Value Codemodel::DumpConfiguration(std::string const& config)
+{
+ CodemodelConfig configuration(this->FileAPI, this->Version, config);
+ return configuration.Dump();
+}
+
+CodemodelConfig::CodemodelConfig(cmFileAPI& fileAPI, unsigned long version,
+ std::string const& config)
+ : FileAPI(fileAPI)
+ , Version(version)
+ , Config(config)
+ , TopSource(this->FileAPI.GetCMakeInstance()->GetHomeDirectory())
+ , TopBuild(this->FileAPI.GetCMakeInstance()->GetHomeOutputDirectory())
+{
+ static_cast<void>(this->Version);
+}
+
+Json::Value CodemodelConfig::Dump()
+{
+ Json::Value configuration = Json::objectValue;
+ configuration["name"] = this->Config;
+ this->ProcessDirectories();
+ configuration["targets"] = this->DumpTargets();
+ configuration["directories"] = this->DumpDirectories();
+ configuration["projects"] = this->DumpProjects();
+ return configuration;
+}
+
+void CodemodelConfig::ProcessDirectories()
+{
+ cmGlobalGenerator* gg =
+ this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
+ std::vector<cmLocalGenerator*> const& localGens = gg->GetLocalGenerators();
+
+ // Add directories in forward order to process parents before children.
+ this->Directories.reserve(localGens.size());
+ for (cmLocalGenerator* lg : localGens) {
+ auto directoryIndex =
+ static_cast<Json::ArrayIndex>(this->Directories.size());
+ this->Directories.emplace_back();
+ Directory& d = this->Directories[directoryIndex];
+ d.Snapshot = lg->GetStateSnapshot().GetBuildsystemDirectory();
+ d.LocalGenerator = lg;
+ this->DirectoryMap[d.Snapshot] = directoryIndex;
+
+ d.ProjectIndex = this->AddProject(d.Snapshot);
+ this->Projects[d.ProjectIndex].DirectoryIndexes.append(directoryIndex);
+ }
+
+ // Update directories in reverse order to process children before parents.
+ for (auto di = this->Directories.rbegin(); di != this->Directories.rend();
+ ++di) {
+ Directory& d = *di;
+
+ // Accumulate the presence of install rules on the way up.
+ for (auto gen : d.LocalGenerator->GetMakefile()->GetInstallGenerators()) {
+ if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(gen)) {
+ d.HasInstallRule = true;
+ break;
+ }
+ }
+ if (!d.HasInstallRule) {
+ for (cmStateSnapshot const& child : d.Snapshot.GetChildren()) {
+ cmStateSnapshot childDir = child.GetBuildsystemDirectory();
+ Json::ArrayIndex const childIndex = this->GetDirectoryIndex(childDir);
+ if (this->Directories[childIndex].HasInstallRule) {
+ d.HasInstallRule = true;
+ break;
+ }
+ }
+ }
+ }
+}
+
+Json::ArrayIndex CodemodelConfig::GetDirectoryIndex(cmLocalGenerator const* lg)
+{
+ return this->GetDirectoryIndex(
+ lg->GetStateSnapshot().GetBuildsystemDirectory());
+}
+
+Json::ArrayIndex CodemodelConfig::GetDirectoryIndex(cmStateSnapshot s)
+{
+ auto i = this->DirectoryMap.find(s);
+ assert(i != this->DirectoryMap.end());
+ return i->second;
+}
+
+Json::ArrayIndex CodemodelConfig::AddProject(cmStateSnapshot s)
+{
+ cmStateSnapshot ps = s.GetBuildsystemDirectoryParent();
+ if (ps.IsValid() && ps.GetProjectName() == s.GetProjectName()) {
+ // This directory is part of its parent directory project.
+ Json::ArrayIndex const parentDirIndex = this->GetDirectoryIndex(ps);
+ return this->Directories[parentDirIndex].ProjectIndex;
+ }
+
+ // This directory starts a new project.
+ auto projectIndex = static_cast<Json::ArrayIndex>(this->Projects.size());
+ this->Projects.emplace_back();
+ Project& p = this->Projects[projectIndex];
+ p.Snapshot = s;
+ this->ProjectMap[s] = projectIndex;
+ if (ps.IsValid()) {
+ Json::ArrayIndex const parentDirIndex = this->GetDirectoryIndex(ps);
+ p.ParentIndex = this->Directories[parentDirIndex].ProjectIndex;
+ this->Projects[p.ParentIndex].ChildIndexes.append(projectIndex);
+ }
+ return projectIndex;
+}
+
+Json::Value CodemodelConfig::DumpTargets()
+{
+ Json::Value targets = Json::arrayValue;
+
+ std::vector<cmGeneratorTarget*> targetList;
+ cmGlobalGenerator* gg =
+ this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
+ for (cmLocalGenerator const* lg : gg->GetLocalGenerators()) {
+ cmAppend(targetList, lg->GetGeneratorTargets());
+ }
+ std::sort(targetList.begin(), targetList.end(),
+ [](cmGeneratorTarget* l, cmGeneratorTarget* r) {
+ return l->GetName() < r->GetName();
+ });
+
+ for (cmGeneratorTarget* gt : targetList) {
+ if (gt->GetType() == cmStateEnums::GLOBAL_TARGET ||
+ gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
+ }
+
+ targets.append(this->DumpTarget(gt, targets.size()));
+ }
+
+ return targets;
+}
+
+Json::Value CodemodelConfig::DumpTarget(cmGeneratorTarget* gt,
+ Json::ArrayIndex ti)
+{
+ Target t(gt, this->Config);
+ std::string prefix = "target-" + gt->GetName();
+ for (char& c : prefix) {
+ // CMP0037 OLD behavior allows slashes in target names. Remove them.
+ if (c == '/' || c == '\\') {
+ c = '_';
+ }
+ }
+ if (!this->Config.empty()) {
+ prefix += "-" + this->Config;
+ }
+ Json::Value target = this->FileAPI.MaybeJsonFile(t.Dump(), prefix);
+ target["name"] = gt->GetName();
+ target["id"] = TargetId(gt, this->TopBuild);
+
+ // Cross-reference directory containing target.
+ Json::ArrayIndex di = this->GetDirectoryIndex(gt->GetLocalGenerator());
+ target["directoryIndex"] = di;
+ this->Directories[di].TargetIndexes.append(ti);
+
+ // Cross-reference project containing target.
+ Json::ArrayIndex pi = this->Directories[di].ProjectIndex;
+ target["projectIndex"] = pi;
+ this->Projects[pi].TargetIndexes.append(ti);
+
+ return target;
+}
+
+Json::Value CodemodelConfig::DumpDirectories()
+{
+ Json::Value directories = Json::arrayValue;
+ for (Directory& d : this->Directories) {
+ directories.append(this->DumpDirectory(d));
+ }
+ return directories;
+}
+
+Json::Value CodemodelConfig::DumpDirectory(Directory& d)
+{
+ Json::Value directory = Json::objectValue;
+
+ std::string sourceDir = d.Snapshot.GetDirectory().GetCurrentSource();
+ directory["source"] = RelativeIfUnder(this->TopSource, sourceDir);
+
+ std::string buildDir = d.Snapshot.GetDirectory().GetCurrentBinary();
+ directory["build"] = RelativeIfUnder(this->TopBuild, buildDir);
+
+ cmStateSnapshot parentDir = d.Snapshot.GetBuildsystemDirectoryParent();
+ if (parentDir.IsValid()) {
+ directory["parentIndex"] = this->GetDirectoryIndex(parentDir);
+ }
+
+ Json::Value childIndexes = Json::arrayValue;
+ for (cmStateSnapshot const& child : d.Snapshot.GetChildren()) {
+ childIndexes.append(
+ this->GetDirectoryIndex(child.GetBuildsystemDirectory()));
+ }
+ if (!childIndexes.empty()) {
+ directory["childIndexes"] = std::move(childIndexes);
+ }
+
+ directory["projectIndex"] = d.ProjectIndex;
+
+ if (!d.TargetIndexes.empty()) {
+ directory["targetIndexes"] = std::move(d.TargetIndexes);
+ }
+
+ Json::Value minimumCMakeVersion = this->DumpMinimumCMakeVersion(d.Snapshot);
+ if (!minimumCMakeVersion.isNull()) {
+ directory["minimumCMakeVersion"] = std::move(minimumCMakeVersion);
+ }
+
+ if (d.HasInstallRule) {
+ directory["hasInstallRule"] = true;
+ }
+
+ return directory;
+}
+
+Json::Value CodemodelConfig::DumpProjects()
+{
+ Json::Value projects = Json::arrayValue;
+ for (Project& p : this->Projects) {
+ projects.append(this->DumpProject(p));
+ }
+ return projects;
+}
+
+Json::Value CodemodelConfig::DumpProject(Project& p)
+{
+ Json::Value project = Json::objectValue;
+
+ project["name"] = p.Snapshot.GetProjectName();
+
+ if (p.ParentIndex != Project::NoParentIndex) {
+ project["parentIndex"] = p.ParentIndex;
+ }
+
+ if (!p.ChildIndexes.empty()) {
+ project["childIndexes"] = std::move(p.ChildIndexes);
+ }
+
+ project["directoryIndexes"] = std::move(p.DirectoryIndexes);
+
+ if (!p.TargetIndexes.empty()) {
+ project["targetIndexes"] = std::move(p.TargetIndexes);
+ }
+
+ return project;
+}
+
+Json::Value CodemodelConfig::DumpMinimumCMakeVersion(cmStateSnapshot s)
+{
+ Json::Value minimumCMakeVersion;
+ if (std::string const* def =
+ s.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
+ minimumCMakeVersion = Json::objectValue;
+ minimumCMakeVersion["string"] = *def;
+ }
+ return minimumCMakeVersion;
+}
+
+Target::Target(cmGeneratorTarget* gt, std::string const& config)
+ : GT(gt)
+ , Config(config)
+ , TopSource(gt->GetGlobalGenerator()->GetCMakeInstance()->GetHomeDirectory())
+ , TopBuild(
+ gt->GetGlobalGenerator()->GetCMakeInstance()->GetHomeOutputDirectory())
+ , SourceGroupsLocal(this->GT->Makefile->GetSourceGroups())
+ , Backtraces(this->TopSource)
+{
+}
+
+Json::Value Target::Dump()
+{
+ Json::Value target = Json::objectValue;
+
+ cmStateEnums::TargetType const type = this->GT->GetType();
+
+ target["name"] = this->GT->GetName();
+ target["type"] = cmState::GetTargetTypeName(type);
+ target["id"] = TargetId(this->GT, this->TopBuild);
+ target["paths"] = this->DumpPaths();
+ if (this->GT->Target->GetIsGeneratorProvided()) {
+ target["isGeneratorProvided"] = true;
+ }
+
+ this->AddBacktrace(target, this->GT->GetBacktrace());
+
+ if (this->GT->Target->GetHaveInstallRule()) {
+ target["install"] = this->DumpInstall();
+ }
+
+ if (this->GT->HaveWellDefinedOutputFiles()) {
+ Json::Value artifacts = this->DumpArtifacts();
+ if (!artifacts.empty()) {
+ target["artifacts"] = std::move(artifacts);
+ }
+ }
+
+ if (type == cmStateEnums::EXECUTABLE ||
+ type == cmStateEnums::SHARED_LIBRARY ||
+ type == cmStateEnums::MODULE_LIBRARY) {
+ target["nameOnDisk"] = this->GT->GetFullName(this->Config);
+ target["link"] = this->DumpLink();
+ } else if (type == cmStateEnums::STATIC_LIBRARY) {
+ target["nameOnDisk"] = this->GT->GetFullName(this->Config);
+ target["archive"] = this->DumpArchive();
+ }
+
+ Json::Value dependencies = this->DumpDependencies();
+ if (!dependencies.empty()) {
+ target["dependencies"] = dependencies;
+ }
+
+ {
+ this->ProcessLanguages();
+
+ target["sources"] = this->DumpSources();
+
+ Json::Value folder = this->DumpFolder();
+ if (!folder.isNull()) {
+ target["folder"] = std::move(folder);
+ }
+
+ Json::Value sourceGroups = this->DumpSourceGroups();
+ if (!sourceGroups.empty()) {
+ target["sourceGroups"] = std::move(sourceGroups);
+ }
+
+ Json::Value compileGroups = this->DumpCompileGroups();
+ if (!compileGroups.empty()) {
+ target["compileGroups"] = std::move(compileGroups);
+ }
+ }
+
+ target["backtraceGraph"] = this->Backtraces.Dump();
+
+ return target;
+}
+
+void Target::ProcessLanguages()
+{
+ std::set<std::string> languages;
+ this->GT->GetLanguages(languages, this->Config);
+ for (std::string const& lang : languages) {
+ this->ProcessLanguage(lang);
+ }
+}
+
+void Target::ProcessLanguage(std::string const& lang)
+{
+ CompileData& cd = this->CompileDataMap[lang];
+ cd.Language = lang;
+ if (const char* sysrootCompile =
+ this->GT->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) {
+ cd.Sysroot = sysrootCompile;
+ } else if (const char* sysroot =
+ this->GT->Makefile->GetDefinition("CMAKE_SYSROOT")) {
+ cd.Sysroot = sysroot;
+ }
+ cmLocalGenerator* lg = this->GT->GetLocalGenerator();
+ {
+ // FIXME: Add flags from end section of ExpandRuleVariable,
+ // which may need to be factored out.
+ std::vector<BT<std::string>> flags =
+ lg->GetTargetCompileFlags(this->GT, this->Config, lang);
+
+ cd.Flags.reserve(flags.size());
+ for (const BT<std::string>& f : flags) {
+ cd.Flags.emplace_back(this->ToJBT(f));
+ }
+ }
+ std::set<BT<std::string>> defines =
+ lg->GetTargetDefines(this->GT, this->Config, lang);
+ cd.Defines.reserve(defines.size());
+ for (BT<std::string> const& d : defines) {
+ cd.Defines.emplace_back(this->ToJBT(d));
+ }
+ std::vector<BT<std::string>> includePathList =
+ lg->GetIncludeDirectories(this->GT, lang, this->Config);
+ for (BT<std::string> const& i : includePathList) {
+ cd.Includes.emplace_back(
+ this->ToJBT(i),
+ this->GT->IsSystemIncludeDirectory(i.Value, this->Config, lang));
+ }
+}
+
+Json::ArrayIndex Target::AddSourceGroup(cmSourceGroup* sg, Json::ArrayIndex si)
+{
+ auto i = this->SourceGroupsMap.find(sg);
+ if (i == this->SourceGroupsMap.end()) {
+ auto sgIndex = static_cast<Json::ArrayIndex>(this->SourceGroups.size());
+ i = this->SourceGroupsMap.emplace(sg, sgIndex).first;
+ SourceGroup g;
+ g.Name = sg->GetFullName();
+ this->SourceGroups.push_back(std::move(g));
+ }
+ this->SourceGroups[i->second].SourceIndexes.append(si);
+ return i->second;
+}
+
+CompileData Target::BuildCompileData(cmSourceFile* sf)
+{
+ CompileData fd;
+
+ fd.Language = sf->GetOrDetermineLanguage();
+ if (fd.Language.empty()) {
+ return fd;
+ }
+
+ cmLocalGenerator* lg = this->GT->GetLocalGenerator();
+ cmGeneratorExpressionInterpreter genexInterpreter(lg, this->Config, this->GT,
+ fd.Language);
+
+ const std::string COMPILE_FLAGS("COMPILE_FLAGS");
+ if (const char* cflags = sf->GetProperty(COMPILE_FLAGS)) {
+ std::string flags = genexInterpreter.Evaluate(cflags, COMPILE_FLAGS);
+ fd.Flags.emplace_back(std::move(flags), JBTIndex());
+ }
+ const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
+ for (BT<std::string> tmpOpt : sf->GetCompileOptions()) {
+ tmpOpt.Value = genexInterpreter.Evaluate(tmpOpt.Value, COMPILE_OPTIONS);
+ // After generator evaluation we need to use the AppendCompileOptions
+ // method so we handle situations where backtrace entries have lists
+ // and properly escape flags.
+ std::string tmp;
+ lg->AppendCompileOptions(tmp, tmpOpt.Value);
+ BT<std::string> opt(tmp, tmpOpt.Backtrace);
+ fd.Flags.emplace_back(this->ToJBT(opt));
+ }
+
+ // Add precompile headers compile options.
+ const std::string pchSource =
+ this->GT->GetPchSource(this->Config, fd.Language);
+
+ if (!pchSource.empty() && !sf->GetProperty("SKIP_PRECOMPILE_HEADERS")) {
+ std::string pchOptions;
+ if (sf->ResolveFullPath() == pchSource) {
+ pchOptions =
+ this->GT->GetPchCreateCompileOptions(this->Config, fd.Language);
+ } else {
+ pchOptions =
+ this->GT->GetPchUseCompileOptions(this->Config, fd.Language);
+ }
+
+ BT<std::string> tmpOpt(pchOptions);
+ tmpOpt.Value = genexInterpreter.Evaluate(tmpOpt.Value, COMPILE_OPTIONS);
+
+ // After generator evaluation we need to use the AppendCompileOptions
+ // method so we handle situations where backtrace entries have lists
+ // and properly escape flags.
+ std::string tmp;
+ lg->AppendCompileOptions(tmp, tmpOpt.Value);
+ BT<std::string> opt(tmp, tmpOpt.Backtrace);
+ fd.Flags.emplace_back(this->ToJBT(opt));
+ }
+
+ // Add include directories from source file properties.
+ {
+ const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
+ for (BT<std::string> tmpInclude : sf->GetIncludeDirectories()) {
+ tmpInclude.Value =
+ genexInterpreter.Evaluate(tmpInclude.Value, INCLUDE_DIRECTORIES);
+
+ // After generator evaluation we need to use the AppendIncludeDirectories
+ // method so we handle situations where backtrace entries have lists.
+ std::vector<std::string> tmp;
+ lg->AppendIncludeDirectories(tmp, tmpInclude.Value, *sf);
+ for (std::string& i : tmp) {
+ bool const isSystemInclude =
+ this->GT->IsSystemIncludeDirectory(i, this->Config, fd.Language);
+ BT<std::string> include(i, tmpInclude.Backtrace);
+ fd.Includes.emplace_back(this->ToJBT(include), isSystemInclude);
+ }
+ }
+ }
+
+ const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
+ std::set<BT<std::string>> fileDefines;
+ for (BT<std::string> tmpDef : sf->GetCompileDefinitions()) {
+ tmpDef.Value =
+ genexInterpreter.Evaluate(tmpDef.Value, COMPILE_DEFINITIONS);
+
+ // After generator evaluation we need to use the AppendDefines method
+ // so we handle situations where backtrace entries have lists.
+ std::set<std::string> tmp;
+ lg->AppendDefines(tmp, tmpDef.Value);
+ for (const std::string& i : tmp) {
+ BT<std::string> def(i, tmpDef.Backtrace);
+ fileDefines.insert(def);
+ }
+ }
+
+ std::set<std::string> configFileDefines;
+ const std::string defPropName =
+ "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(this->Config);
+ if (const char* config_defs = sf->GetProperty(defPropName)) {
+ lg->AppendDefines(
+ configFileDefines,
+ genexInterpreter.Evaluate(config_defs, COMPILE_DEFINITIONS));
+ }
+
+ fd.Defines.reserve(fileDefines.size() + configFileDefines.size());
+
+ for (BT<std::string> const& def : fileDefines) {
+ fd.Defines.emplace_back(this->ToJBT(def));
+ }
+
+ for (std::string const& d : configFileDefines) {
+ fd.Defines.emplace_back(d, JBTIndex());
+ }
+
+ return fd;
+}
+
+CompileData Target::MergeCompileData(CompileData const& fd)
+{
+ CompileData cd;
+ cd.Language = fd.Language;
+ if (cd.Language.empty()) {
+ return cd;
+ }
+ CompileData const& td = this->CompileDataMap.at(cd.Language);
+
+ // All compile groups share the sysroot of the target.
+ cd.Sysroot = td.Sysroot;
+
+ // Use target-wide flags followed by source-specific flags.
+ cd.Flags.reserve(td.Flags.size() + fd.Flags.size());
+ cd.Flags.insert(cd.Flags.end(), td.Flags.begin(), td.Flags.end());
+ cd.Flags.insert(cd.Flags.end(), fd.Flags.begin(), fd.Flags.end());
+
+ // Use source-specific includes followed by target-wide includes.
+ cd.Includes.reserve(fd.Includes.size() + td.Includes.size());
+ cd.Includes.insert(cd.Includes.end(), fd.Includes.begin(),
+ fd.Includes.end());
+ cd.Includes.insert(cd.Includes.end(), td.Includes.begin(),
+ td.Includes.end());
+
+ // Use target-wide defines followed by source-specific defines.
+ cd.Defines.reserve(td.Defines.size() + fd.Defines.size());
+ cd.Defines.insert(cd.Defines.end(), td.Defines.begin(), td.Defines.end());
+ cd.Defines.insert(cd.Defines.end(), fd.Defines.begin(), fd.Defines.end());
+
+ // De-duplicate defines.
+ std::stable_sort(cd.Defines.begin(), cd.Defines.end(),
+ JBT<std::string>::ValueLess);
+ auto end = std::unique(cd.Defines.begin(), cd.Defines.end(),
+ JBT<std::string>::ValueEq);
+ cd.Defines.erase(end, cd.Defines.end());
+
+ return cd;
+}
+
+Json::ArrayIndex Target::AddSourceCompileGroup(cmSourceFile* sf,
+ Json::ArrayIndex si)
+{
+ CompileData compileData = this->BuildCompileData(sf);
+ auto i = this->CompileGroupMap.find(compileData);
+ if (i == this->CompileGroupMap.end()) {
+ Json::ArrayIndex cgIndex =
+ static_cast<Json::ArrayIndex>(this->CompileGroups.size());
+ i = this->CompileGroupMap.emplace(std::move(compileData), cgIndex).first;
+ CompileGroup g;
+ g.Entry = i;
+ this->CompileGroups.push_back(std::move(g));
+ }
+ this->CompileGroups[i->second].SourceIndexes.append(si);
+ return i->second;
+}
+
+void Target::AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt)
+{
+ if (JBTIndex backtrace = this->Backtraces.Add(bt)) {
+ object["backtrace"] = backtrace.Index;
+ }
+}
+
+void Target::AddBacktrace(Json::Value& object, JBTIndex bt)
+{
+ if (bt) {
+ object["backtrace"] = bt.Index;
+ }
+}
+
+Json::Value Target::DumpPaths()
+{
+ Json::Value paths = Json::objectValue;
+ cmLocalGenerator* lg = this->GT->GetLocalGenerator();
+
+ std::string const& sourceDir = lg->GetCurrentSourceDirectory();
+ paths["source"] = RelativeIfUnder(this->TopSource, sourceDir);
+
+ std::string const& buildDir = lg->GetCurrentBinaryDirectory();
+ paths["build"] = RelativeIfUnder(this->TopBuild, buildDir);
+
+ return paths;
+}
+
+Json::Value Target::DumpSources()
+{
+ Json::Value sources = Json::arrayValue;
+ cmGeneratorTarget::KindedSources const& kinded =
+ this->GT->GetKindedSources(this->Config);
+ for (cmGeneratorTarget::SourceAndKind const& sk : kinded.Sources) {
+ sources.append(this->DumpSource(sk, sources.size()));
+ }
+ return sources;
+}
+
+Json::Value Target::DumpSource(cmGeneratorTarget::SourceAndKind const& sk,
+ Json::ArrayIndex si)
+{
+ Json::Value source = Json::objectValue;
+
+ std::string const path = sk.Source.Value->ResolveFullPath();
+ source["path"] = RelativeIfUnder(this->TopSource, path);
+ if (sk.Source.Value->GetIsGenerated()) {
+ source["isGenerated"] = true;
+ }
+ this->AddBacktrace(source, sk.Source.Backtrace);
+
+ if (cmSourceGroup* sg =
+ this->GT->Makefile->FindSourceGroup(path, this->SourceGroupsLocal)) {
+ source["sourceGroupIndex"] = this->AddSourceGroup(sg, si);
+ }
+
+ switch (sk.Kind) {
+ case cmGeneratorTarget::SourceKindObjectSource: {
+ source["compileGroupIndex"] =
+ this->AddSourceCompileGroup(sk.Source.Value, si);
+ } break;
+ case cmGeneratorTarget::SourceKindAppManifest:
+ case cmGeneratorTarget::SourceKindCertificate:
+ case cmGeneratorTarget::SourceKindCustomCommand:
+ case cmGeneratorTarget::SourceKindExternalObject:
+ case cmGeneratorTarget::SourceKindExtra:
+ case cmGeneratorTarget::SourceKindHeader:
+ case cmGeneratorTarget::SourceKindIDL:
+ case cmGeneratorTarget::SourceKindManifest:
+ case cmGeneratorTarget::SourceKindModuleDefinition:
+ case cmGeneratorTarget::SourceKindResx:
+ case cmGeneratorTarget::SourceKindXaml:
+ case cmGeneratorTarget::SourceKindUnityBatched:
+ break;
+ }
+
+ return source;
+}
+
+Json::Value Target::DumpCompileData(CompileData const& cd)
+{
+ Json::Value result = Json::objectValue;
+
+ if (!cd.Language.empty()) {
+ result["language"] = cd.Language;
+ }
+ if (!cd.Sysroot.empty()) {
+ result["sysroot"] = this->DumpSysroot(cd.Sysroot);
+ }
+ if (!cd.Flags.empty()) {
+ result["compileCommandFragments"] = this->DumpCommandFragments(cd.Flags);
+ }
+ if (!cd.Includes.empty()) {
+ Json::Value includes = Json::arrayValue;
+ for (auto const& i : cd.Includes) {
+ includes.append(this->DumpInclude(i));
+ }
+ result["includes"] = includes;
+ }
+ if (!cd.Defines.empty()) {
+ Json::Value defines = Json::arrayValue;
+ for (JBT<std::string> const& d : cd.Defines) {
+ defines.append(this->DumpDefine(d));
+ }
+ result["defines"] = std::move(defines);
+ }
+
+ return result;
+}
+
+Json::Value Target::DumpInclude(CompileData::IncludeEntry const& inc)
+{
+ Json::Value include = Json::objectValue;
+ include["path"] = inc.Path.Value;
+ if (inc.IsSystem) {
+ include["isSystem"] = true;
+ }
+ this->AddBacktrace(include, inc.Path.Backtrace);
+ return include;
+}
+
+Json::Value Target::DumpDefine(JBT<std::string> const& def)
+{
+ Json::Value define = Json::objectValue;
+ define["define"] = def.Value;
+ this->AddBacktrace(define, def.Backtrace);
+ return define;
+}
+
+Json::Value Target::DumpSourceGroups()
+{
+ Json::Value sourceGroups = Json::arrayValue;
+ for (auto& sg : this->SourceGroups) {
+ sourceGroups.append(this->DumpSourceGroup(sg));
+ }
+ return sourceGroups;
+}
+
+Json::Value Target::DumpSourceGroup(SourceGroup& sg)
+{
+ Json::Value group = Json::objectValue;
+ group["name"] = sg.Name;
+ group["sourceIndexes"] = std::move(sg.SourceIndexes);
+ return group;
+}
+
+Json::Value Target::DumpCompileGroups()
+{
+ Json::Value compileGroups = Json::arrayValue;
+ for (auto& cg : this->CompileGroups) {
+ compileGroups.append(this->DumpCompileGroup(cg));
+ }
+ return compileGroups;
+}
+
+Json::Value Target::DumpCompileGroup(CompileGroup& cg)
+{
+ Json::Value group =
+ this->DumpCompileData(this->MergeCompileData(cg.Entry->first));
+ group["sourceIndexes"] = std::move(cg.SourceIndexes);
+ return group;
+}
+
+Json::Value Target::DumpSysroot(std::string const& path)
+{
+ Json::Value sysroot = Json::objectValue;
+ sysroot["path"] = path;
+ return sysroot;
+}
+
+Json::Value Target::DumpInstall()
+{
+ Json::Value install = Json::objectValue;
+ install["prefix"] = this->DumpInstallPrefix();
+ install["destinations"] = this->DumpInstallDestinations();
+ return install;
+}
+
+Json::Value Target::DumpInstallPrefix()
+{
+ Json::Value prefix = Json::objectValue;
+ std::string p =
+ this->GT->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
+ cmSystemTools::ConvertToUnixSlashes(p);
+ prefix["path"] = p;
+ return prefix;
+}
+
+Json::Value Target::DumpInstallDestinations()
+{
+ Json::Value destinations = Json::arrayValue;
+ auto installGens = this->GT->Target->GetInstallGenerators();
+ for (auto itGen : installGens) {
+ destinations.append(this->DumpInstallDestination(itGen));
+ }
+ return destinations;
+}
+
+Json::Value Target::DumpInstallDestination(cmInstallTargetGenerator* itGen)
+{
+ Json::Value destination = Json::objectValue;
+ destination["path"] = itGen->GetDestination(this->Config);
+ this->AddBacktrace(destination, itGen->GetBacktrace());
+ return destination;
+}
+
+Json::Value Target::DumpArtifacts()
+{
+ Json::Value artifacts = Json::arrayValue;
+
+ // Object libraries have only object files as artifacts.
+ if (this->GT->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ if (!this->GT->GetGlobalGenerator()->HasKnownObjectFileLocation(nullptr)) {
+ return artifacts;
+ }
+ std::vector<cmSourceFile const*> objectSources;
+ this->GT->GetObjectSources(objectSources, this->Config);
+ std::string const obj_dir = this->GT->GetObjectDirectory(this->Config);
+ for (cmSourceFile const* sf : objectSources) {
+ const std::string& obj = this->GT->GetObjectName(sf);
+ Json::Value artifact = Json::objectValue;
+ artifact["path"] = RelativeIfUnder(this->TopBuild, obj_dir + obj);
+ artifacts.append(std::move(artifact)); // NOLINT(*)
+ }
+ return artifacts;
+ }
+
+ // Other target types always have a "main" artifact.
+ {
+ Json::Value artifact = Json::objectValue;
+ artifact["path"] =
+ RelativeIfUnder(this->TopBuild,
+ this->GT->GetFullPath(
+ this->Config, cmStateEnums::RuntimeBinaryArtifact));
+ artifacts.append(std::move(artifact)); // NOLINT(*)
+ }
+
+ // Add Windows-specific artifacts produced by the linker.
+ if (this->GT->HasImportLibrary(this->Config)) {
+ Json::Value artifact = Json::objectValue;
+ artifact["path"] =
+ RelativeIfUnder(this->TopBuild,
+ this->GT->GetFullPath(
+ this->Config, cmStateEnums::ImportLibraryArtifact));
+ artifacts.append(std::move(artifact)); // NOLINT(*)
+ }
+ if (this->GT->IsDLLPlatform() &&
+ this->GT->GetType() != cmStateEnums::STATIC_LIBRARY) {
+ cmGeneratorTarget::OutputInfo const* output =
+ this->GT->GetOutputInfo(this->Config);
+ if (output && !output->PdbDir.empty()) {
+ Json::Value artifact = Json::objectValue;
+ artifact["path"] = RelativeIfUnder(this->TopBuild,
+ output->PdbDir + '/' +
+ this->GT->GetPDBName(this->Config));
+ artifacts.append(std::move(artifact)); // NOLINT(*)
+ }
+ }
+ return artifacts;
+}
+
+Json::Value Target::DumpLink()
+{
+ Json::Value link = Json::objectValue;
+ std::string lang = this->GT->GetLinkerLanguage(this->Config);
+ link["language"] = lang;
+ {
+ Json::Value commandFragments = this->DumpLinkCommandFragments();
+ if (!commandFragments.empty()) {
+ link["commandFragments"] = std::move(commandFragments);
+ }
+ }
+ if (const char* sysrootLink =
+ this->GT->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) {
+ link["sysroot"] = this->DumpSysroot(sysrootLink);
+ } else if (const char* sysroot =
+ this->GT->Makefile->GetDefinition("CMAKE_SYSROOT")) {
+ link["sysroot"] = this->DumpSysroot(sysroot);
+ }
+ if (this->GT->IsIPOEnabled(lang, this->Config)) {
+ link["lto"] = true;
+ }
+ return link;
+}
+
+Json::Value Target::DumpArchive()
+{
+ Json::Value archive = Json::objectValue;
+ {
+ // The "link" fragments not relevant to static libraries are empty.
+ Json::Value commandFragments = this->DumpLinkCommandFragments();
+ if (!commandFragments.empty()) {
+ archive["commandFragments"] = std::move(commandFragments);
+ }
+ }
+ std::string lang = this->GT->GetLinkerLanguage(this->Config);
+ if (this->GT->IsIPOEnabled(lang, this->Config)) {
+ archive["lto"] = true;
+ }
+ return archive;
+}
+
+Json::Value Target::DumpLinkCommandFragments()
+{
+ Json::Value linkFragments = Json::arrayValue;
+
+ std::string linkLanguageFlags;
+ std::vector<BT<std::string>> linkFlags;
+ std::string frameworkPath;
+ std::vector<BT<std::string>> linkPath;
+ std::vector<BT<std::string>> linkLibs;
+ cmLocalGenerator* lg = this->GT->GetLocalGenerator();
+ cmLinkLineComputer linkLineComputer(lg,
+ lg->GetStateSnapshot().GetDirectory());
+ lg->GetTargetFlags(&linkLineComputer, this->Config, linkLibs,
+ linkLanguageFlags, linkFlags, frameworkPath, linkPath,
+ this->GT);
+ linkLanguageFlags = cmTrimWhitespace(linkLanguageFlags);
+ frameworkPath = cmTrimWhitespace(frameworkPath);
+
+ if (!linkLanguageFlags.empty()) {
+ linkFragments.append(
+ this->DumpCommandFragment(std::move(linkLanguageFlags), "flags"));
+ }
+
+ if (!linkFlags.empty()) {
+ for (BT<std::string> frag : linkFlags) {
+ frag.Value = cmTrimWhitespace(frag.Value);
+ linkFragments.append(
+ this->DumpCommandFragment(this->ToJBT(frag), "flags"));
+ }
+ }
+
+ if (!frameworkPath.empty()) {
+ linkFragments.append(
+ this->DumpCommandFragment(std::move(frameworkPath), "frameworkPath"));
+ }
+
+ if (!linkPath.empty()) {
+ for (BT<std::string> frag : linkPath) {
+ frag.Value = cmTrimWhitespace(frag.Value);
+ linkFragments.append(
+ this->DumpCommandFragment(this->ToJBT(frag), "libraryPath"));
+ }
+ }
+
+ if (!linkLibs.empty()) {
+ for (BT<std::string> frag : linkLibs) {
+ frag.Value = cmTrimWhitespace(frag.Value);
+ linkFragments.append(
+ this->DumpCommandFragment(this->ToJBT(frag), "libraries"));
+ }
+ }
+
+ return linkFragments;
+}
+
+Json::Value Target::DumpCommandFragments(
+ std::vector<JBT<std::string>> const& frags)
+{
+ Json::Value commandFragments = Json::arrayValue;
+ for (JBT<std::string> const& f : frags) {
+ commandFragments.append(this->DumpCommandFragment(f));
+ }
+ return commandFragments;
+}
+
+Json::Value Target::DumpCommandFragment(JBT<std::string> const& frag,
+ std::string const& role)
+{
+ Json::Value fragment = Json::objectValue;
+ fragment["fragment"] = frag.Value;
+ if (!role.empty()) {
+ fragment["role"] = role;
+ }
+ this->AddBacktrace(fragment, frag.Backtrace);
+ return fragment;
+}
+
+Json::Value Target::DumpDependencies()
+{
+ Json::Value dependencies = Json::arrayValue;
+ cmGlobalGenerator* gg = this->GT->GetGlobalGenerator();
+ for (cmTargetDepend const& td : gg->GetTargetDirectDepends(this->GT)) {
+ dependencies.append(this->DumpDependency(td));
+ }
+ return dependencies;
+}
+
+Json::Value Target::DumpDependency(cmTargetDepend const& td)
+{
+ Json::Value dependency = Json::objectValue;
+ dependency["id"] = TargetId(td, this->TopBuild);
+ this->AddBacktrace(dependency, td.GetBacktrace());
+ return dependency;
+}
+
+Json::Value Target::DumpFolder()
+{
+ Json::Value folder;
+ if (const char* f = this->GT->GetProperty("FOLDER")) {
+ folder = Json::objectValue;
+ folder["name"] = f;
+ }
+ return folder;
+}
+}
+
+Json::Value cmFileAPICodemodelDump(cmFileAPI& fileAPI, unsigned long version)
+{
+ Codemodel codemodel(fileAPI, version);
+ return codemodel.Dump();
+}
diff --git a/Source/cmFileAPICodemodel.h b/Source/cmFileAPICodemodel.h
new file mode 100644
index 000000000..ffbd92863
--- /dev/null
+++ b/Source/cmFileAPICodemodel.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 cmFileAPICodemodel_h
+#define cmFileAPICodemodel_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cm_jsoncpp_value.h"
+
+class cmFileAPI;
+
+extern Json::Value cmFileAPICodemodelDump(cmFileAPI& fileAPI,
+ unsigned long version);
+
+#endif
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 5777fb204..d45414f72 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -2,85 +2,73 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFileCommand.h"
-#include "cm_kwiml.h"
-#include "cmsys/Directory.hxx"
-#include "cmsys/FStream.hxx"
-#include "cmsys/Glob.hxx"
-#include "cmsys/RegularExpression.hxx"
-#include "cmsys/String.hxx"
#include <algorithm>
-#include <assert.h>
+#include <cassert>
+#include <cctype>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <map>
+#include <set>
#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <utility>
#include <vector>
+#include <cm/memory>
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/RegularExpression.hxx"
+
+#include "cm_kwiml.h"
+#include "cm_static_string_view.hxx"
+#include "cm_sys_stat.h"
+
#include "cmAlgorithms.h"
-#include "cmCommandArgumentsHelper.h"
+#include "cmArgumentParser.h"
#include "cmCryptoHash.h"
+#include "cmExecutionStatus.h"
+#include "cmFileCopier.h"
+#include "cmFileInstaller.h"
#include "cmFileLockPool.h"
-#include "cmFileTimeComparison.h"
+#include "cmFileTimes.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmHexFileConverter.h"
-#include "cmInstallType.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmRange.h"
+#include "cmRuntimeDependencyArchive.h"
+#include "cmState.h"
+#include "cmStringAlgorithms.h"
+#include "cmSubcommandTable.h"
#include "cmSystemTools.h"
#include "cmTimestamp.h"
-#include "cm_auto_ptr.hxx"
-#include "cm_sys_stat.h"
#include "cmake.h"
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmCurl.h"
-#include "cmFileLockResult.h"
-#include "cm_curl.h"
+#if !defined(CMAKE_BOOTSTRAP)
+# include "cm_curl.h"
+
+# include "cmCurl.h"
+# include "cmFileLockResult.h"
#endif
#if defined(CMAKE_USE_ELF_PARSER)
-#include "cmELF.h"
+# include "cmELF.h"
#endif
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
#endif
-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 = 0;
-static mode_t mode_group_write = 0;
-static mode_t mode_group_execute = 0;
-static mode_t mode_world_read = 0;
-static mode_t mode_world_write = 0;
-static mode_t mode_world_execute = 0;
-static mode_t mode_setuid = 0;
-static mode_t mode_setgid = 0;
-#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
+namespace {
#if defined(_WIN32)
// libcurl doesn't support file:// urls for unicode filenames on Windows.
// Convert string from UTF-8 to ACP if this is a file:// URL.
-static std::string fix_file_url_windows(const std::string& url)
+std::string fix_file_url_windows(const std::string& url)
{
std::string ret = url;
if (strncmp(url.c_str(), "file://", 7) == 0) {
@@ -102,228 +90,152 @@ static std::string fix_file_url_windows(const std::string& url)
}
#endif
-// cmLibraryCommand
-bool cmFileCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool HandleWriteImpl(std::vector<std::string> const& args, bool append,
+ cmExecutionStatus& status)
{
- if (args.size() < 2) {
- this->SetError("must be called with at least two arguments.");
- return false;
- }
- std::string const& subCommand = args[0];
- if (subCommand == "WRITE") {
- return this->HandleWriteCommand(args, false);
- }
- if (subCommand == "APPEND") {
- return this->HandleWriteCommand(args, true);
- }
- if (subCommand == "DOWNLOAD") {
- return this->HandleDownloadCommand(args);
- }
- if (subCommand == "UPLOAD") {
- return this->HandleUploadCommand(args);
- }
- if (subCommand == "READ") {
- return this->HandleReadCommand(args);
- }
- if (subCommand == "MD5" || subCommand == "SHA1" || subCommand == "SHA224" ||
- subCommand == "SHA256" || subCommand == "SHA384" ||
- subCommand == "SHA512" || subCommand == "SHA3_224" ||
- subCommand == "SHA3_256" || subCommand == "SHA3_384" ||
- subCommand == "SHA3_512") {
- return this->HandleHashCommand(args);
- }
- if (subCommand == "STRINGS") {
- return this->HandleStringsCommand(args);
- }
- if (subCommand == "GLOB") {
- return this->HandleGlobCommand(args, false);
- }
- if (subCommand == "GLOB_RECURSE") {
- return this->HandleGlobCommand(args, true);
- }
- if (subCommand == "MAKE_DIRECTORY") {
- return this->HandleMakeDirectoryCommand(args);
- }
- if (subCommand == "RENAME") {
- return this->HandleRename(args);
- }
- if (subCommand == "REMOVE") {
- return this->HandleRemove(args, false);
- }
- if (subCommand == "REMOVE_RECURSE") {
- return this->HandleRemove(args, true);
- }
- if (subCommand == "COPY") {
- return this->HandleCopyCommand(args);
- }
- if (subCommand == "INSTALL") {
- return this->HandleInstallCommand(args);
- }
- if (subCommand == "DIFFERENT") {
- return this->HandleDifferentCommand(args);
- }
- if (subCommand == "RPATH_CHANGE" || subCommand == "CHRPATH") {
- return this->HandleRPathChangeCommand(args);
- }
- if (subCommand == "RPATH_CHECK") {
- return this->HandleRPathCheckCommand(args);
- }
- if (subCommand == "RPATH_REMOVE") {
- return this->HandleRPathRemoveCommand(args);
- }
- if (subCommand == "READ_ELF") {
- return this->HandleReadElfCommand(args);
- }
- if (subCommand == "RELATIVE_PATH") {
- return this->HandleRelativePathCommand(args);
- }
- if (subCommand == "TO_CMAKE_PATH") {
- return this->HandleCMakePathCommand(args, false);
- }
- if (subCommand == "TO_NATIVE_PATH") {
- return this->HandleCMakePathCommand(args, true);
- }
- if (subCommand == "TIMESTAMP") {
- return this->HandleTimestampCommand(args);
- }
- if (subCommand == "GENERATE") {
- return this->HandleGenerateCommand(args);
- }
- if (subCommand == "LOCK") {
- return this->HandleLockCommand(args);
- }
-
- std::string e = "does not recognize sub-command " + subCommand;
- this->SetError(e);
- return false;
-}
-
-bool cmFileCommand::HandleWriteCommand(std::vector<std::string> const& args,
- bool append)
-{
- std::vector<std::string>::const_iterator i = args.begin();
+ auto i = args.begin();
i++; // Get rid of subcommand
std::string fileName = *i;
- if (!cmsys::SystemTools::FileIsFullPath(i->c_str())) {
- fileName = this->Makefile->GetCurrentSourceDirectory();
- fileName += "/" + *i;
+ if (!cmsys::SystemTools::FileIsFullPath(*i)) {
+ fileName =
+ cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', *i);
}
i++;
- if (!this->Makefile->CanIWriteThisFile(fileName.c_str())) {
+ if (!status.GetMakefile().CanIWriteThisFile(fileName)) {
std::string e =
"attempted to write a file: " + fileName + " into a source directory.";
- this->SetError(e);
+ status.SetError(e);
cmSystemTools::SetFatalErrorOccured();
return false;
}
std::string dir = cmSystemTools::GetFilenamePath(fileName);
- cmSystemTools::MakeDirectory(dir.c_str());
+ cmSystemTools::MakeDirectory(dir);
mode_t mode = 0;
+ bool writable = false;
// Set permissions to writable
- if (cmSystemTools::GetPermissions(fileName.c_str(), mode)) {
- cmSystemTools::SetPermissions(fileName.c_str(),
+ if (cmSystemTools::GetPermissions(fileName, mode)) {
#if defined(_MSC_VER) || defined(__MINGW32__)
- mode | S_IWRITE
+ writable = (mode & S_IWRITE) != 0;
+ mode_t newMode = mode | S_IWRITE;
#else
- mode | S_IWUSR | S_IWGRP
+ writable = mode & S_IWUSR;
+ mode_t newMode = mode | S_IWUSR | S_IWGRP;
#endif
- );
+ if (!writable) {
+ cmSystemTools::SetPermissions(fileName, newMode);
+ }
}
// If GetPermissions fails, pretend like it is ok. File open will fail if
// the file is not writable
cmsys::ofstream file(fileName.c_str(),
append ? std::ios::app : std::ios::out);
if (!file) {
- std::string error = "failed to open for writing (";
- error += cmSystemTools::GetLastSystemError();
- error += "):\n ";
- error += fileName;
- this->SetError(error);
+ std::string error =
+ cmStrCat("failed to open for writing (",
+ cmSystemTools::GetLastSystemError(), "):\n ", fileName);
+ status.SetError(error);
return false;
}
std::string message = cmJoin(cmMakeRange(i, args.end()), std::string());
file << message;
+ if (!file) {
+ std::string error =
+ cmStrCat("write failed (", cmSystemTools::GetLastSystemError(), "):\n ",
+ fileName);
+ status.SetError(error);
+ return false;
+ }
file.close();
- if (mode) {
- cmSystemTools::SetPermissions(fileName.c_str(), mode);
+ if (mode && !writable) {
+ cmSystemTools::SetPermissions(fileName, mode);
}
return true;
}
-bool cmFileCommand::HandleReadCommand(std::vector<std::string> const& args)
+bool HandleWriteCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return HandleWriteImpl(args, false, status);
+}
+
+bool HandleAppendCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return HandleWriteImpl(args, true, status);
+}
+
+bool HandleReadCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 3) {
- this->SetError("READ must be called with at least two additional "
- "arguments");
+ status.SetError("READ must be called with at least two additional "
+ "arguments");
return false;
}
- cmCommandArgumentsHelper argHelper;
- cmCommandArgumentGroup group;
+ std::string const& fileNameArg = args[1];
+ std::string const& variable = args[2];
- cmCAString readArg(&argHelper, "READ");
- cmCAString fileNameArg(&argHelper, CM_NULLPTR);
- cmCAString resultArg(&argHelper, CM_NULLPTR);
+ struct Arguments
+ {
+ std::string Offset;
+ std::string Limit;
+ bool Hex = false;
+ };
- cmCAString offsetArg(&argHelper, "OFFSET", &group);
- cmCAString limitArg(&argHelper, "LIMIT", &group);
- cmCAEnabler hexOutputArg(&argHelper, "HEX", &group);
- readArg.Follows(CM_NULLPTR);
- fileNameArg.Follows(&readArg);
- resultArg.Follows(&fileNameArg);
- group.Follows(&resultArg);
- argHelper.Parse(&args, CM_NULLPTR);
+ static auto const parser = cmArgumentParser<Arguments>{}
+ .Bind("OFFSET"_s, &Arguments::Offset)
+ .Bind("LIMIT"_s, &Arguments::Limit)
+ .Bind("HEX"_s, &Arguments::Hex);
- std::string fileName = fileNameArg.GetString();
- if (!cmsys::SystemTools::FileIsFullPath(fileName.c_str())) {
- fileName = this->Makefile->GetCurrentSourceDirectory();
- fileName += "/" + fileNameArg.GetString();
- }
+ Arguments const arguments = parser.Parse(cmMakeRange(args).advance(3));
- std::string variable = resultArg.GetString();
+ std::string fileName = fileNameArg;
+ if (!cmsys::SystemTools::FileIsFullPath(fileName)) {
+ fileName = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/',
+ fileNameArg);
+ }
// Open the specified file.
#if defined(_WIN32) || defined(__CYGWIN__)
- cmsys::ifstream file(
- fileName.c_str(), std::ios::in |
- (hexOutputArg.IsEnabled() ? std::ios::binary : std::ios::in));
+ cmsys::ifstream file(fileName.c_str(),
+ arguments.Hex ? (std::ios::binary | std::ios::in)
+ : std::ios::in);
#else
cmsys::ifstream file(fileName.c_str());
#endif
if (!file) {
- std::string error = "failed to open for reading (";
- error += cmSystemTools::GetLastSystemError();
- error += "):\n ";
- error += fileName;
- this->SetError(error);
+ std::string error =
+ cmStrCat("failed to open for reading (",
+ cmSystemTools::GetLastSystemError(), "):\n ", fileName);
+ status.SetError(error);
return false;
}
// is there a limit?
long sizeLimit = -1;
- if (!limitArg.GetString().empty()) {
- sizeLimit = atoi(limitArg.GetCString());
+ if (!arguments.Limit.empty()) {
+ sizeLimit = atoi(arguments.Limit.c_str());
}
// is there an offset?
long offset = 0;
- if (!offsetArg.GetString().empty()) {
- offset = atoi(offsetArg.GetCString());
+ if (!arguments.Offset.empty()) {
+ offset = atoi(arguments.Offset.c_str());
}
file.seekg(offset, std::ios::beg); // explicit ios::beg for IBM VisualAge 6
std::string output;
- if (hexOutputArg.IsEnabled()) {
+ if (arguments.Hex) {
// Convert part of the file into hex code
char c;
while ((sizeLimit != 0) && (file.get(c))) {
@@ -337,8 +249,9 @@ bool cmFileCommand::HandleReadCommand(std::vector<std::string> const& args)
} else {
std::string line;
bool has_newline = false;
- while (sizeLimit != 0 && cmSystemTools::GetLineFromStream(
- file, line, &has_newline, sizeLimit)) {
+ while (
+ sizeLimit != 0 &&
+ cmSystemTools::GetLineFromStream(file, line, &has_newline, sizeLimit)) {
if (sizeLimit > 0) {
sizeLimit = sizeLimit - static_cast<long>(line.size());
if (has_newline) {
@@ -354,53 +267,50 @@ bool cmFileCommand::HandleReadCommand(std::vector<std::string> const& args)
}
}
}
- this->Makefile->AddDefinition(variable, output.c_str());
+ status.GetMakefile().AddDefinition(variable, output);
return true;
}
-bool cmFileCommand::HandleHashCommand(std::vector<std::string> const& args)
+bool HandleHashCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
if (args.size() != 3) {
- std::ostringstream e;
- e << args[0] << " requires a file name and output variable";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat(args[0], " requires a file name and output variable"));
return false;
}
- CM_AUTO_PTR<cmCryptoHash> hash(cmCryptoHash::New(args[0].c_str()));
- if (hash.get()) {
+ std::unique_ptr<cmCryptoHash> hash(cmCryptoHash::New(args[0]));
+ if (hash) {
std::string out = hash->HashFile(args[1]);
if (!out.empty()) {
- this->Makefile->AddDefinition(args[2], out.c_str());
+ status.GetMakefile().AddDefinition(args[2], out);
return true;
}
- std::ostringstream e;
- e << args[0] << " failed to read file \"" << args[1]
- << "\": " << cmSystemTools::GetLastSystemError();
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " failed to read file \"", args[1],
+ "\": ", cmSystemTools::GetLastSystemError()));
}
return false;
#else
- std::ostringstream e;
- e << args[0] << " not available during bootstrap";
- this->SetError(e.str().c_str());
+ status.SetError(cmStrCat(args[0], " not available during bootstrap"));
return false;
#endif
}
-bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
+bool HandleStringsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 3) {
- this->SetError("STRINGS requires a file name and output variable");
+ status.SetError("STRINGS requires a file name and output variable");
return false;
}
// Get the file to read.
std::string fileName = args[1];
- if (!cmsys::SystemTools::FileIsFullPath(fileName.c_str())) {
- fileName = this->Makefile->GetCurrentSourceDirectory();
- fileName += "/" + args[1];
+ if (!cmsys::SystemTools::FileIsFullPath(fileName)) {
+ fileName =
+ cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[1]);
}
// Get the variable in which to store the results.
@@ -463,30 +373,24 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
} else if (arg_mode == arg_limit_input) {
if (sscanf(args[i].c_str(), "%d", &limit_input) != 1 ||
limit_input < 0) {
- std::ostringstream e;
- e << "STRINGS option LIMIT_INPUT value \"" << args[i]
- << "\" is not an unsigned integer.";
- this->SetError(e.str());
+ status.SetError(cmStrCat("STRINGS option LIMIT_INPUT value \"",
+ args[i], "\" is not an unsigned integer."));
return false;
}
arg_mode = arg_none;
} else if (arg_mode == arg_limit_output) {
if (sscanf(args[i].c_str(), "%d", &limit_output) != 1 ||
limit_output < 0) {
- std::ostringstream e;
- e << "STRINGS option LIMIT_OUTPUT value \"" << args[i]
- << "\" is not an unsigned integer.";
- this->SetError(e.str());
+ status.SetError(cmStrCat("STRINGS option LIMIT_OUTPUT value \"",
+ args[i], "\" is not an unsigned integer."));
return false;
}
arg_mode = arg_none;
} else if (arg_mode == arg_limit_count) {
int count;
if (sscanf(args[i].c_str(), "%d", &count) != 1 || count < 0) {
- std::ostringstream e;
- e << "STRINGS option LIMIT_COUNT value \"" << args[i]
- << "\" is not an unsigned integer.";
- this->SetError(e.str());
+ status.SetError(cmStrCat("STRINGS option LIMIT_COUNT value \"",
+ args[i], "\" is not an unsigned integer."));
return false;
}
limit_count = count;
@@ -494,10 +398,8 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
} else if (arg_mode == arg_length_minimum) {
int len;
if (sscanf(args[i].c_str(), "%d", &len) != 1 || len < 0) {
- std::ostringstream e;
- e << "STRINGS option LENGTH_MINIMUM value \"" << args[i]
- << "\" is not an unsigned integer.";
- this->SetError(e.str());
+ status.SetError(cmStrCat("STRINGS option LENGTH_MINIMUM value \"",
+ args[i], "\" is not an unsigned integer."));
return false;
}
minlen = len;
@@ -505,20 +407,16 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
} else if (arg_mode == arg_length_maximum) {
int len;
if (sscanf(args[i].c_str(), "%d", &len) != 1 || len < 0) {
- std::ostringstream e;
- e << "STRINGS option LENGTH_MAXIMUM value \"" << args[i]
- << "\" is not an unsigned integer.";
- this->SetError(e.str());
+ status.SetError(cmStrCat("STRINGS option LENGTH_MAXIMUM value \"",
+ args[i], "\" is not an unsigned integer."));
return false;
}
maxlen = len;
arg_mode = arg_none;
} else if (arg_mode == arg_regex) {
- if (!regex.compile(args[i].c_str())) {
- std::ostringstream e;
- e << "STRINGS option REGEX value \"" << args[i]
- << "\" could not be compiled.";
- this->SetError(e.str());
+ if (!regex.compile(args[i])) {
+ status.SetError(cmStrCat("STRINGS option REGEX value \"", args[i],
+ "\" could not be compiled."));
return false;
}
have_regex = true;
@@ -535,27 +433,24 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
} else if (args[i] == "UTF-32BE") {
encoding = encoding_utf32be;
} else {
- std::ostringstream e;
- e << "STRINGS option ENCODING \"" << args[i] << "\" not recognized.";
- this->SetError(e.str());
+ status.SetError(cmStrCat("STRINGS option ENCODING \"", args[i],
+ "\" not recognized."));
return false;
}
arg_mode = arg_none;
} else {
- std::ostringstream e;
- e << "STRINGS given unknown argument \"" << args[i] << "\"";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("STRINGS given unknown argument \"", args[i], "\""));
return false;
}
}
if (hex_conversion_enabled) {
// TODO: should work without temp file, but just on a memory buffer
- std::string binaryFileName = this->Makefile->GetCurrentBinaryDirectory();
- binaryFileName += cmake::GetCMakeFilesDirectory();
- binaryFileName += "/FileCommandStringsBinaryFile";
- if (cmHexFileConverter::TryConvert(fileName.c_str(),
- binaryFileName.c_str())) {
+ std::string binaryFileName =
+ cmStrCat(status.GetMakefile().GetCurrentBinaryDirectory(),
+ "/CMakeFiles/FileCommandStringsBinaryFile");
+ if (cmHexFileConverter::TryConvert(fileName, binaryFileName)) {
fileName = binaryFileName;
}
}
@@ -567,9 +462,8 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
cmsys::ifstream fin(fileName.c_str());
#endif
if (!fin) {
- std::ostringstream e;
- e << "STRINGS file \"" << fileName << "\" cannot be read.";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("STRINGS file \"", fileName, "\" cannot be read."));
return false;
}
@@ -617,8 +511,8 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
continue;
}
- if ((c >= 0x20 && c < 0x7F) || c == '\t' ||
- (c == '\n' && newline_consume)) {
+ if (c >= 0 && c <= 0xFF &&
+ (isprint(c) || c == '\t' || (c == '\n' && newline_consume))) {
// This is an ASCII character that may be part of a string.
// Cast added to avoid compiler warning. Cast is ok because
// c is guaranteed to fit in char by the above if...
@@ -626,7 +520,9 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
} else if (encoding == encoding_utf8) {
// Check for UTF-8 encoded string (up to 4 octets)
static const unsigned char utf8_check_table[3][2] = {
- { 0xE0, 0xC0 }, { 0xF0, 0xE0 }, { 0xF8, 0xF0 },
+ { 0xE0, 0xC0 },
+ { 0xF0, 0xE0 },
+ { 0xF8, 0xF0 },
};
// how many octets are there?
@@ -656,7 +552,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
c = current_str[current_str.size() - 1 - j];
fin.putback(static_cast<char>(c));
}
- current_str = "";
+ current_str.clear();
}
}
@@ -664,48 +560,48 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
// The current line has been terminated. Check if the current
// string matches the requirements. The length may now be as
// low as zero since blank lines are allowed.
- if (s.length() >= minlen && (!have_regex || regex.find(s.c_str()))) {
+ if (s.length() >= minlen && (!have_regex || regex.find(s))) {
output_size += static_cast<int>(s.size()) + 1;
if (limit_output >= 0 && output_size >= limit_output) {
- s = "";
+ s.clear();
break;
}
strings.push_back(s);
}
// Reset the string to empty.
- s = "";
+ s.clear();
} else if (current_str.empty()) {
// A non-string character has been found. Check if the current
// string matches the requirements. We require that the length
// be at least one no matter what the user specified.
if (s.length() >= minlen && !s.empty() &&
- (!have_regex || regex.find(s.c_str()))) {
+ (!have_regex || regex.find(s))) {
output_size += static_cast<int>(s.size()) + 1;
if (limit_output >= 0 && output_size >= limit_output) {
- s = "";
+ s.clear();
break;
}
strings.push_back(s);
}
// Reset the string to empty.
- s = "";
+ s.clear();
} else {
s += current_str;
}
if (maxlen > 0 && s.size() == maxlen) {
// Terminate a string if the maximum length is reached.
- if (s.length() >= minlen && (!have_regex || regex.find(s.c_str()))) {
+ if (s.length() >= minlen && (!have_regex || regex.find(s))) {
output_size += static_cast<int>(s.size()) + 1;
if (limit_output >= 0 && output_size >= limit_output) {
- s = "";
+ s.clear();
break;
}
strings.push_back(s);
}
- s = "";
+ s.clear();
}
}
@@ -713,7 +609,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
// input file or the input size limit. Check if the current string
// matches the requirements.
if ((!limit_count || strings.size() < limit_count) && !s.empty() &&
- s.length() >= minlen && (!have_regex || regex.find(s.c_str()))) {
+ s.length() >= minlen && (!have_regex || regex.find(s))) {
output_size += static_cast<int>(s.size()) + 1;
if (limit_output < 0 || output_size < limit_output) {
strings.push_back(s);
@@ -723,35 +619,33 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
// Encode the result in a CMake list.
const char* sep = "";
std::string output;
- for (std::vector<std::string>::const_iterator si = strings.begin();
- si != strings.end(); ++si) {
+ for (std::string const& sr : strings) {
// Separate the strings in the output to make it a list.
output += sep;
sep = ";";
// Store the string in the output, but escape semicolons to
// make sure it is a list.
- std::string const& sr = *si;
- for (unsigned int i = 0; i < sr.size(); ++i) {
- if (sr[i] == ';') {
+ for (char i : sr) {
+ if (i == ';') {
output += '\\';
}
- output += sr[i];
+ output += i;
}
}
// Save the output in a makefile variable.
- this->Makefile->AddDefinition(outVar, output.c_str());
+ status.GetMakefile().AddDefinition(outVar, output);
return true;
}
-bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
- bool recurse)
+bool HandleGlobImpl(std::vector<std::string> const& args, bool recurse,
+ cmExecutionStatus& status)
{
// File commands has at least one argument
assert(args.size() > 1);
- std::vector<std::string>::const_iterator i = args.begin();
+ auto i = args.begin();
i++; // Get rid of subcommand
@@ -761,10 +655,10 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
g.SetRecurse(recurse);
bool explicitFollowSymlinks = false;
- cmPolicies::PolicyStatus status =
- this->Makefile->GetPolicyStatus(cmPolicies::CMP0009);
+ cmPolicies::PolicyStatus policyStatus =
+ status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0009);
if (recurse) {
- switch (status) {
+ switch (policyStatus) {
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
@@ -777,172 +671,259 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
}
}
- std::string output;
- bool first = true;
- for (; i != args.end(); ++i) {
+ std::vector<std::string> files;
+ bool configureDepends = false;
+ bool warnConfigureLate = false;
+ bool warnFollowedSymlinks = false;
+ const cmake::WorkingMode workingMode =
+ status.GetMakefile().GetCMakeInstance()->GetWorkingMode();
+ while (i != args.end()) {
if (*i == "LIST_DIRECTORIES") {
- ++i;
+ ++i; // skip LIST_DIRECTORIES
if (i != args.end()) {
- if (cmSystemTools::IsOn(i->c_str())) {
+ if (cmIsOn(*i)) {
g.SetListDirs(true);
g.SetRecurseListDirs(true);
- } else if (cmSystemTools::IsOff(i->c_str())) {
+ } else if (cmIsOff(*i)) {
g.SetListDirs(false);
g.SetRecurseListDirs(false);
} else {
- this->SetError("LIST_DIRECTORIES missing bool value.");
+ status.SetError("LIST_DIRECTORIES missing bool value.");
return false;
}
+ ++i;
} else {
- this->SetError("LIST_DIRECTORIES missing bool value.");
+ status.SetError("LIST_DIRECTORIES missing bool value.");
return false;
}
- continue;
- }
-
- if (recurse && (*i == "FOLLOW_SYMLINKS")) {
- explicitFollowSymlinks = true;
- g.RecurseThroughSymlinksOn();
- ++i;
- if (i == args.end()) {
- this->SetError(
- "GLOB_RECURSE requires a glob expression after FOLLOW_SYMLINKS");
- return false;
+ } else if (*i == "FOLLOW_SYMLINKS") {
+ ++i; // skip FOLLOW_SYMLINKS
+ if (recurse) {
+ explicitFollowSymlinks = true;
+ g.RecurseThroughSymlinksOn();
+ if (i == args.end()) {
+ status.SetError(
+ "GLOB_RECURSE requires a glob expression after FOLLOW_SYMLINKS.");
+ return false;
+ }
}
- }
-
- if (*i == "RELATIVE") {
+ } else if (*i == "RELATIVE") {
++i; // skip RELATIVE
if (i == args.end()) {
- this->SetError("GLOB requires a directory after the RELATIVE tag");
+ status.SetError("GLOB requires a directory after the RELATIVE tag.");
return false;
}
g.SetRelative(i->c_str());
++i;
if (i == args.end()) {
- this->SetError("GLOB requires a glob expression after the directory");
+ status.SetError(
+ "GLOB requires a glob expression after the directory.");
return false;
}
- }
-
- cmsys::Glob::GlobMessages globMessages;
- if (!cmsys::SystemTools::FileIsFullPath(i->c_str())) {
- std::string expr = this->Makefile->GetCurrentSourceDirectory();
- // Handle script mode
- if (!expr.empty()) {
- expr += "/" + *i;
- g.FindFiles(expr, &globMessages);
- } else {
- g.FindFiles(*i, &globMessages);
+ } else if (*i == "CONFIGURE_DEPENDS") {
+ // Generated build system depends on glob results
+ if (!configureDepends && warnConfigureLate) {
+ status.GetMakefile().IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ "CONFIGURE_DEPENDS flag was given after a glob expression was "
+ "already evaluated.");
+ }
+ if (workingMode != cmake::NORMAL_MODE) {
+ status.GetMakefile().IssueMessage(
+ MessageType::FATAL_ERROR,
+ "CONFIGURE_DEPENDS is invalid for script and find package modes.");
+ return false;
+ }
+ configureDepends = true;
+ ++i;
+ if (i == args.end()) {
+ status.SetError(
+ "GLOB requires a glob expression after CONFIGURE_DEPENDS.");
+ return false;
}
} else {
- g.FindFiles(*i, &globMessages);
- }
-
- if (!globMessages.empty()) {
- bool shouldExit = false;
- for (cmsys::Glob::GlobMessagesIterator it = globMessages.begin();
- it != globMessages.end(); ++it) {
- if (it->type == cmsys::Glob::cyclicRecursion) {
- this->Makefile->IssueMessage(
- cmake::AUTHOR_WARNING,
- "Cyclic recursion detected while globbing for '" + *i + "':\n" +
- it->content);
+ std::string expr = *i;
+ if (!cmsys::SystemTools::FileIsFullPath(*i)) {
+ expr = status.GetMakefile().GetCurrentSourceDirectory();
+ // Handle script mode
+ if (!expr.empty()) {
+ expr += "/" + *i;
} else {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR, "Error has occurred while globbing for '" +
- *i + "' - " + it->content);
- shouldExit = true;
+ expr = *i;
}
}
- if (shouldExit) {
- return false;
+
+ cmsys::Glob::GlobMessages globMessages;
+ g.FindFiles(expr, &globMessages);
+
+ if (!globMessages.empty()) {
+ bool shouldExit = false;
+ for (cmsys::Glob::Message const& globMessage : globMessages) {
+ if (globMessage.type == cmsys::Glob::cyclicRecursion) {
+ status.GetMakefile().IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ "Cyclic recursion detected while globbing for '" + *i + "':\n" +
+ globMessage.content);
+ } else {
+ status.GetMakefile().IssueMessage(
+ MessageType::FATAL_ERROR,
+ "Error has occurred while globbing for '" + *i + "' - " +
+ globMessage.content);
+ shouldExit = true;
+ }
+ }
+ if (shouldExit) {
+ return false;
+ }
}
- }
- std::vector<std::string>::size_type cc;
- std::vector<std::string>& files = g.GetFiles();
- std::sort(files.begin(), files.end());
- for (cc = 0; cc < files.size(); cc++) {
- if (!first) {
- output += ";";
+ if (recurse && !explicitFollowSymlinks &&
+ g.GetFollowedSymlinkCount() != 0) {
+ warnFollowedSymlinks = true;
}
- output += files[cc];
- first = false;
+
+ std::vector<std::string>& foundFiles = g.GetFiles();
+ cmAppend(files, foundFiles);
+
+ if (configureDepends) {
+ std::sort(foundFiles.begin(), foundFiles.end());
+ foundFiles.erase(std::unique(foundFiles.begin(), foundFiles.end()),
+ foundFiles.end());
+ status.GetMakefile().GetCMakeInstance()->AddGlobCacheEntry(
+ recurse, (recurse ? g.GetRecurseListDirs() : g.GetListDirs()),
+ (recurse ? g.GetRecurseThroughSymlinks() : false),
+ (g.GetRelative() ? g.GetRelative() : ""), expr, foundFiles, variable,
+ status.GetMakefile().GetBacktrace());
+ } else {
+ warnConfigureLate = true;
+ }
+ ++i;
}
}
- if (recurse && !explicitFollowSymlinks) {
- switch (status) {
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::NEW:
- // Correct behavior, yay!
- break;
- case cmPolicies::OLD:
- // Probably not really the expected behavior, but the author explicitly
- // asked for the old behavior... no warning.
- case cmPolicies::WARN:
- // Possibly unexpected old behavior *and* we actually traversed
- // symlinks without being explicitly asked to: warn the author.
- if (g.GetFollowedSymlinkCount() != 0) {
- this->Makefile->IssueMessage(
- cmake::AUTHOR_WARNING,
- cmPolicies::GetPolicyWarning(cmPolicies::CMP0009));
- }
- break;
- }
+ switch (policyStatus) {
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Correct behavior, yay!
+ break;
+ case cmPolicies::OLD:
+ // Probably not really the expected behavior, but the author explicitly
+ // asked for the old behavior... no warning.
+ case cmPolicies::WARN:
+ // Possibly unexpected old behavior *and* we actually traversed
+ // symlinks without being explicitly asked to: warn the author.
+ if (warnFollowedSymlinks) {
+ status.GetMakefile().IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0009));
+ }
+ break;
}
- this->Makefile->AddDefinition(variable, output.c_str());
+ std::sort(files.begin(), files.end());
+ files.erase(std::unique(files.begin(), files.end()), files.end());
+ status.GetMakefile().AddDefinition(variable, cmJoin(files, ";"));
return true;
}
-bool cmFileCommand::HandleMakeDirectoryCommand(
- std::vector<std::string> const& args)
+bool HandleGlobCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- // File command has at least one argument
- assert(args.size() > 1);
+ return HandleGlobImpl(args, false, status);
+}
- std::vector<std::string>::const_iterator i = args.begin();
+bool HandleGlobRecurseCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return HandleGlobImpl(args, true, status);
+}
- i++; // Get rid of subcommand
+bool HandleMakeDirectoryCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ // File command has at least one argument
+ assert(args.size() > 1);
std::string expr;
- for (; i != args.end(); ++i) {
- const std::string* cdir = &(*i);
- if (!cmsys::SystemTools::FileIsFullPath(i->c_str())) {
- expr = this->Makefile->GetCurrentSourceDirectory();
- expr += "/" + *i;
+ for (std::string const& arg :
+ cmMakeRange(args).advance(1)) // Get rid of subcommand
+ {
+ const std::string* cdir = &arg;
+ if (!cmsys::SystemTools::FileIsFullPath(arg)) {
+ expr =
+ cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', arg);
cdir = &expr;
}
- if (!this->Makefile->CanIWriteThisFile(cdir->c_str())) {
+ if (!status.GetMakefile().CanIWriteThisFile(*cdir)) {
std::string e = "attempted to create a directory: " + *cdir +
" into a source directory.";
- this->SetError(e);
+ status.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);
+ status.SetError(error);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool HandleTouchImpl(std::vector<std::string> const& args, bool create,
+ cmExecutionStatus& status)
+{
+ // File command has at least one argument
+ assert(args.size() > 1);
+
+ for (std::string const& arg :
+ cmMakeRange(args).advance(1)) // Get rid of subcommand
+ {
+ std::string tfile = arg;
+ if (!cmsys::SystemTools::FileIsFullPath(tfile)) {
+ tfile =
+ cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', arg);
+ }
+ if (!status.GetMakefile().CanIWriteThisFile(tfile)) {
+ std::string e =
+ "attempted to touch a file: " + tfile + " in a source directory.";
+ status.SetError(e);
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+ if (!cmSystemTools::Touch(tfile, create)) {
+ std::string error = "problem touching file: " + tfile;
+ status.SetError(error);
return false;
}
}
return true;
}
-bool cmFileCommand::HandleDifferentCommand(
- std::vector<std::string> const& args)
+bool HandleTouchCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return HandleTouchImpl(args, true, status);
+}
+
+bool HandleTouchNocreateCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return HandleTouchImpl(args, false, status);
+}
+
+bool HandleDifferentCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
/*
FILE(DIFFERENT <variable> FILES <lhs> <rhs>)
*/
// Evaluate arguments.
- const char* file_lhs = CM_NULLPTR;
- const char* file_rhs = CM_NULLPTR;
- const char* var = CM_NULLPTR;
+ const char* file_lhs = nullptr;
+ const char* file_rhs = nullptr;
+ const char* var = nullptr;
enum Doing
{
DoingNone,
@@ -964,1073 +945,41 @@ bool cmFileCommand::HandleDifferentCommand(
file_rhs = args[i].c_str();
doing = DoingNone;
} else {
- std::ostringstream e;
- e << "DIFFERENT given unknown argument " << args[i];
- this->SetError(e.str());
+ status.SetError(cmStrCat("DIFFERENT given unknown argument ", args[i]));
return false;
}
}
if (!var) {
- this->SetError("DIFFERENT not given result variable name.");
+ status.SetError("DIFFERENT not given result variable name.");
return false;
}
if (!file_lhs || !file_rhs) {
- this->SetError("DIFFERENT not given FILES option with two file names.");
+ status.SetError("DIFFERENT not given FILES option with two file names.");
return false;
}
// Compare the files.
const char* result =
cmSystemTools::FilesDiffer(file_lhs, file_rhs) ? "1" : "0";
- this->Makefile->AddDefinition(var, result);
- return true;
-}
-
-// File installation helper class.
-struct cmFileCopier
-{
- cmFileCopier(cmFileCommand* command, const char* name = "COPY")
- : FileCommand(command)
- , Makefile(command->GetMakefile())
- , Name(name)
- , Always(false)
- , MatchlessFiles(true)
- , FilePermissions(0)
- , DirPermissions(0)
- , CurrentMatchRule(CM_NULLPTR)
- , UseGivenPermissionsFile(false)
- , UseGivenPermissionsDir(false)
- , UseSourcePermissions(true)
- , Doing(DoingNone)
- {
- }
- virtual ~cmFileCopier() {}
-
- bool Run(std::vector<std::string> const& args);
-
-protected:
- cmFileCommand* FileCommand;
- cmMakefile* Makefile;
- const char* Name;
- bool Always;
- cmFileTimeComparison FileTimes;
-
- // Whether to install a file not matching any expression.
- bool MatchlessFiles;
-
- // Permissions for files and directories installed by this object.
- mode_t FilePermissions;
- mode_t DirPermissions;
-
- // Properties set by pattern and regex match rules.
- struct MatchProperties
- {
- bool Exclude;
- mode_t Permissions;
- MatchProperties()
- : Exclude(false)
- , Permissions(0)
- {
- }
- };
- struct MatchRule
- {
- cmsys::RegularExpression Regex;
- MatchProperties Properties;
- std::string RegexString;
- MatchRule(std::string const& regex)
- : Regex(regex.c_str())
- , RegexString(regex)
- {
- }
- };
- std::vector<MatchRule> MatchRules;
-
- // Get the properties from rules matching this input file.
- MatchProperties CollectMatchProperties(const char* file)
- {
-// Match rules are case-insensitive on some platforms.
-#if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
- std::string lower = cmSystemTools::LowerCase(file);
- const char* file_to_match = lower.c_str();
-#else
- const char* file_to_match = file;
-#endif
-
- // Collect properties from all matching rules.
- bool matched = false;
- MatchProperties result;
- for (std::vector<MatchRule>::iterator mr = this->MatchRules.begin();
- mr != this->MatchRules.end(); ++mr) {
- if (mr->Regex.find(file_to_match)) {
- matched = true;
- result.Exclude |= mr->Properties.Exclude;
- result.Permissions |= mr->Properties.Permissions;
- }
- }
- if (!matched && !this->MatchlessFiles) {
- result.Exclude = !cmSystemTools::FileIsDirectory(file);
- }
- return result;
- }
-
- bool SetPermissions(const char* toFile, mode_t permissions)
- {
- if (permissions && !cmSystemTools::SetPermissions(toFile, permissions)) {
- std::ostringstream e;
- e << this->Name << " cannot set permissions on \"" << toFile << "\"";
- this->FileCommand->SetError(e.str());
- return false;
- }
- return true;
- }
-
- // 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 {
- std::ostringstream e;
- e << this->Name << " given invalid permission \"" << arg << "\".";
- this->FileCommand->SetError(e.str());
- return false;
- }
- return true;
- }
-
- bool InstallSymlink(const char* fromFile, const char* toFile);
- bool InstallFile(const char* fromFile, const char* toFile,
- MatchProperties match_properties);
- bool InstallDirectory(const char* source, const char* destination,
- MatchProperties match_properties);
- virtual bool Install(const char* fromFile, const char* toFile);
- virtual std::string const& ToName(std::string const& fromName)
- {
- return fromName;
- }
-
- enum Type
- {
- TypeFile,
- TypeDir,
- TypeLink
- };
- virtual void ReportCopy(const char*, Type, bool) {}
- virtual bool ReportMissing(const char* fromFile)
- {
- // The input file does not exist and installation is not optional.
- std::ostringstream e;
- e << this->Name << " cannot find \"" << fromFile << "\".";
- this->FileCommand->SetError(e.str());
- return false;
- }
-
- MatchRule* CurrentMatchRule;
- bool UseGivenPermissionsFile;
- bool UseGivenPermissionsDir;
- bool UseSourcePermissions;
- std::string Destination;
- std::string FilesFromDir;
- std::vector<std::string> Files;
- int Doing;
-
- virtual bool Parse(std::vector<std::string> const& args);
- enum
- {
- DoingNone,
- DoingError,
- DoingDestination,
- DoingFilesFromDir,
- DoingFiles,
- DoingPattern,
- DoingRegex,
- DoingPermissionsFile,
- DoingPermissionsDir,
- DoingPermissionsMatch,
- DoingLast1
- };
- virtual bool CheckKeyword(std::string const& arg);
- virtual bool CheckValue(std::string const& arg);
-
- void NotBeforeMatch(std::string const& arg)
- {
- std::ostringstream e;
- e << "option " << arg << " may not appear before PATTERN or REGEX.";
- this->FileCommand->SetError(e.str());
- this->Doing = DoingError;
- }
- void NotAfterMatch(std::string const& arg)
- {
- std::ostringstream e;
- e << "option " << arg << " may not appear after PATTERN or REGEX.";
- this->FileCommand->SetError(e.str());
- this->Doing = DoingError;
- }
- virtual void DefaultFilePermissions()
- {
- // Use read/write permissions.
- this->FilePermissions = 0;
- this->FilePermissions |= mode_owner_read;
- this->FilePermissions |= mode_owner_write;
- this->FilePermissions |= mode_group_read;
- this->FilePermissions |= mode_world_read;
- }
- virtual void DefaultDirectoryPermissions()
- {
- // Use read/write/executable permissions.
- this->DirPermissions = 0;
- this->DirPermissions |= mode_owner_read;
- this->DirPermissions |= mode_owner_write;
- this->DirPermissions |= mode_owner_execute;
- this->DirPermissions |= mode_group_read;
- this->DirPermissions |= mode_group_execute;
- this->DirPermissions |= mode_world_read;
- this->DirPermissions |= mode_world_execute;
- }
-};
-
-bool cmFileCopier::Parse(std::vector<std::string> const& args)
-{
- this->Doing = DoingFiles;
- for (unsigned int i = 1; i < args.size(); ++i) {
- // Check this argument.
- if (!this->CheckKeyword(args[i]) && !this->CheckValue(args[i])) {
- std::ostringstream e;
- e << "called with unknown argument \"" << args[i] << "\".";
- this->FileCommand->SetError(e.str());
- return false;
- }
-
- // Quit if an argument is invalid.
- if (this->Doing == DoingError) {
- return false;
- }
- }
-
- // Require a destination.
- if (this->Destination.empty()) {
- std::ostringstream e;
- e << this->Name << " given no DESTINATION";
- this->FileCommand->SetError(e.str());
- return false;
- }
-
- // If file permissions were not specified set default permissions.
- if (!this->UseGivenPermissionsFile && !this->UseSourcePermissions) {
- this->DefaultFilePermissions();
- }
-
- // If directory permissions were not specified set default permissions.
- if (!this->UseGivenPermissionsDir && !this->UseSourcePermissions) {
- this->DefaultDirectoryPermissions();
- }
-
- return true;
-}
-
-bool cmFileCopier::CheckKeyword(std::string const& arg)
-{
- if (arg == "DESTINATION") {
- if (this->CurrentMatchRule) {
- this->NotAfterMatch(arg);
- } else {
- this->Doing = DoingDestination;
- }
- } else if (arg == "FILES_FROM_DIR") {
- if (this->CurrentMatchRule) {
- this->NotAfterMatch(arg);
- } else {
- this->Doing = DoingFilesFromDir;
- }
- } else if (arg == "PATTERN") {
- this->Doing = DoingPattern;
- } else if (arg == "REGEX") {
- this->Doing = DoingRegex;
- } else if (arg == "EXCLUDE") {
- // Add this property to the current match rule.
- if (this->CurrentMatchRule) {
- this->CurrentMatchRule->Properties.Exclude = true;
- this->Doing = DoingNone;
- } else {
- this->NotBeforeMatch(arg);
- }
- } else if (arg == "PERMISSIONS") {
- if (this->CurrentMatchRule) {
- this->Doing = DoingPermissionsMatch;
- } else {
- this->NotBeforeMatch(arg);
- }
- } else if (arg == "FILE_PERMISSIONS") {
- if (this->CurrentMatchRule) {
- this->NotAfterMatch(arg);
- } else {
- this->Doing = DoingPermissionsFile;
- this->UseGivenPermissionsFile = true;
- }
- } else if (arg == "DIRECTORY_PERMISSIONS") {
- if (this->CurrentMatchRule) {
- this->NotAfterMatch(arg);
- } else {
- this->Doing = DoingPermissionsDir;
- this->UseGivenPermissionsDir = true;
- }
- } else if (arg == "USE_SOURCE_PERMISSIONS") {
- if (this->CurrentMatchRule) {
- this->NotAfterMatch(arg);
- } else {
- this->Doing = DoingNone;
- this->UseSourcePermissions = true;
- }
- } else if (arg == "NO_SOURCE_PERMISSIONS") {
- if (this->CurrentMatchRule) {
- this->NotAfterMatch(arg);
- } else {
- this->Doing = DoingNone;
- this->UseSourcePermissions = false;
- }
- } else if (arg == "FILES_MATCHING") {
- if (this->CurrentMatchRule) {
- this->NotAfterMatch(arg);
- } else {
- this->Doing = DoingNone;
- this->MatchlessFiles = false;
- }
- } else {
- return false;
- }
+ status.GetMakefile().AddDefinition(var, result);
return true;
}
-bool cmFileCopier::CheckValue(std::string const& arg)
+bool HandleCopyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- switch (this->Doing) {
- case DoingFiles:
- this->Files.push_back(arg);
- break;
- case DoingDestination:
- if (arg.empty() || cmSystemTools::FileIsFullPath(arg.c_str())) {
- this->Destination = arg;
- } else {
- this->Destination = this->Makefile->GetCurrentBinaryDirectory();
- this->Destination += "/" + arg;
- }
- this->Doing = DoingNone;
- break;
- case DoingFilesFromDir:
- if (cmSystemTools::FileIsFullPath(arg.c_str())) {
- this->FilesFromDir = arg;
- } else {
- this->FilesFromDir = this->Makefile->GetCurrentSourceDirectory();
- this->FilesFromDir += "/" + arg;
- }
- cmSystemTools::ConvertToUnixSlashes(this->FilesFromDir);
- this->Doing = DoingNone;
- break;
- case DoingPattern: {
- // Convert the pattern to a regular expression. Require a
- // leading slash and trailing end-of-string in the matched
- // string to make sure the pattern matches only whole file
- // names.
- std::string regex = "/";
- regex += cmsys::Glob::PatternToRegex(arg, false);
- regex += "$";
- this->MatchRules.push_back(MatchRule(regex));
- this->CurrentMatchRule = &*(this->MatchRules.end() - 1);
- if (this->CurrentMatchRule->Regex.is_valid()) {
- this->Doing = DoingNone;
- } else {
- std::ostringstream e;
- e << "could not compile PATTERN \"" << arg << "\".";
- this->FileCommand->SetError(e.str());
- this->Doing = DoingError;
- }
- } break;
- case DoingRegex:
- this->MatchRules.push_back(MatchRule(arg));
- this->CurrentMatchRule = &*(this->MatchRules.end() - 1);
- if (this->CurrentMatchRule->Regex.is_valid()) {
- this->Doing = DoingNone;
- } else {
- std::ostringstream e;
- e << "could not compile REGEX \"" << arg << "\".";
- this->FileCommand->SetError(e.str());
- this->Doing = DoingError;
- }
- break;
- case DoingPermissionsFile:
- if (!this->CheckPermissions(arg, this->FilePermissions)) {
- this->Doing = DoingError;
- }
- break;
- case DoingPermissionsDir:
- if (!this->CheckPermissions(arg, this->DirPermissions)) {
- this->Doing = DoingError;
- }
- break;
- case DoingPermissionsMatch:
- if (!this->CheckPermissions(
- arg, this->CurrentMatchRule->Properties.Permissions)) {
- this->Doing = DoingError;
- }
- break;
- default:
- return false;
- }
- return true;
-}
-
-bool cmFileCopier::Run(std::vector<std::string> const& args)
-{
- if (!this->Parse(args)) {
- return false;
- }
-
- for (std::vector<std::string>::const_iterator i = this->Files.begin();
- i != this->Files.end(); ++i) {
- std::string file;
- if (!i->empty() && !cmSystemTools::FileIsFullPath(*i)) {
- if (!this->FilesFromDir.empty()) {
- file = this->FilesFromDir;
- } else {
- file = this->Makefile->GetCurrentSourceDirectory();
- }
- file += "/";
- file += *i;
- } else if (!this->FilesFromDir.empty()) {
- this->FileCommand->SetError("option FILES_FROM_DIR requires all files "
- "to be specified as relative paths.");
- return false;
- } else {
- file = *i;
- }
-
- // Split the input file into its directory and name components.
- std::vector<std::string> fromPathComponents;
- cmSystemTools::SplitPath(file, fromPathComponents);
- std::string fromName = *(fromPathComponents.end() - 1);
- std::string fromDir = cmSystemTools::JoinPath(
- fromPathComponents.begin(), fromPathComponents.end() - 1);
-
- // Compute the full path to the destination file.
- std::string toFile = this->Destination;
- if (!this->FilesFromDir.empty()) {
- std::string dir = cmSystemTools::GetFilenamePath(*i);
- if (!dir.empty()) {
- toFile += "/";
- toFile += dir;
- }
- }
- std::string const& toName = this->ToName(fromName);
- if (!toName.empty()) {
- toFile += "/";
- toFile += toName;
- }
-
- // Construct the full path to the source file. The file name may
- // have been changed above.
- std::string fromFile = fromDir;
- if (!fromName.empty()) {
- fromFile += "/";
- fromFile += fromName;
- }
-
- if (!this->Install(fromFile.c_str(), toFile.c_str())) {
- return false;
- }
- }
- return true;
-}
-
-bool cmFileCopier::Install(const char* fromFile, const char* toFile)
-{
- if (!*fromFile) {
- std::ostringstream e;
- e << "INSTALL encountered an empty string input file name.";
- this->FileCommand->SetError(e.str());
- return false;
- }
-
- // Collect any properties matching this file name.
- MatchProperties match_properties = this->CollectMatchProperties(fromFile);
-
- // Skip the file if it is excluded.
- if (match_properties.Exclude) {
- return true;
- }
-
- if (cmSystemTools::SameFile(fromFile, toFile)) {
- return true;
- }
- if (cmSystemTools::FileIsSymlink(fromFile)) {
- return this->InstallSymlink(fromFile, toFile);
- }
- if (cmSystemTools::FileIsDirectory(fromFile)) {
- return this->InstallDirectory(fromFile, toFile, match_properties);
- }
- if (cmSystemTools::FileExists(fromFile)) {
- return this->InstallFile(fromFile, toFile, match_properties);
- }
- return this->ReportMissing(fromFile);
-}
-
-bool cmFileCopier::InstallSymlink(const char* fromFile, const char* toFile)
-{
- // Read the original symlink.
- std::string symlinkTarget;
- if (!cmSystemTools::ReadSymlink(fromFile, symlinkTarget)) {
- std::ostringstream e;
- e << this->Name << " cannot read symlink \"" << fromFile
- << "\" to duplicate at \"" << toFile << "\".";
- this->FileCommand->SetError(e.str());
- return false;
- }
-
- // Compare the symlink value to that at the destination if not
- // always installing.
- bool copy = true;
- if (!this->Always) {
- std::string oldSymlinkTarget;
- if (cmSystemTools::ReadSymlink(toFile, oldSymlinkTarget)) {
- if (symlinkTarget == oldSymlinkTarget) {
- copy = false;
- }
- }
- }
-
- // Inform the user about this file installation.
- this->ReportCopy(toFile, TypeLink, copy);
-
- if (copy) {
- // Remove the destination file so we can always create the symlink.
- cmSystemTools::RemoveFile(toFile);
-
- // Create destination directory if it doesn't exist
- cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(toFile));
-
- // Create the symlink.
- if (!cmSystemTools::CreateSymlink(symlinkTarget, toFile)) {
- std::ostringstream e;
- e << this->Name << " cannot duplicate symlink \"" << fromFile
- << "\" at \"" << toFile << "\".";
- this->FileCommand->SetError(e.str());
- return false;
- }
- }
-
- return true;
-}
-
-bool cmFileCopier::InstallFile(const char* fromFile, const char* toFile,
- MatchProperties match_properties)
-{
- // Determine whether we will copy the file.
- bool copy = true;
- if (!this->Always) {
- // If both files exist with the same time do not copy.
- if (!this->FileTimes.FileTimesDiffer(fromFile, toFile)) {
- copy = false;
- }
- }
-
- // Inform the user about this file installation.
- this->ReportCopy(toFile, TypeFile, copy);
-
- // Copy the file.
- if (copy && !cmSystemTools::CopyAFile(fromFile, toFile, true)) {
- std::ostringstream e;
- e << this->Name << " cannot copy file \"" << fromFile << "\" to \""
- << toFile << "\".";
- this->FileCommand->SetError(e.str());
- return false;
- }
-
- // Set the file modification time of the destination file.
- if (copy && !this->Always) {
- // Add write permission so we can set the file time.
- // Permissions are set unconditionally below anyway.
- mode_t perm = 0;
- if (cmSystemTools::GetPermissions(toFile, perm)) {
- cmSystemTools::SetPermissions(toFile, perm | mode_owner_write);
- }
- if (!cmSystemTools::CopyFileTime(fromFile, toFile)) {
- std::ostringstream e;
- e << this->Name << " cannot set modification time on \"" << toFile
- << "\"";
- this->FileCommand->SetError(e.str());
- return false;
- }
- }
-
- // Set permissions of the destination file.
- mode_t permissions =
- (match_properties.Permissions ? match_properties.Permissions
- : this->FilePermissions);
- if (!permissions) {
- // No permissions were explicitly provided but the user requested
- // that the source file permissions be used.
- cmSystemTools::GetPermissions(fromFile, permissions);
- }
- return this->SetPermissions(toFile, permissions);
-}
-
-bool cmFileCopier::InstallDirectory(const char* source,
- const char* destination,
- MatchProperties match_properties)
-{
- // Inform the user about this directory installation.
- this->ReportCopy(destination, TypeDir,
- !cmSystemTools::FileIsDirectory(destination));
-
- // Make sure the destination directory exists.
- if (!cmSystemTools::MakeDirectory(destination)) {
- std::ostringstream e;
- e << this->Name << " cannot make directory \"" << destination
- << "\": " << cmSystemTools::GetLastSystemError();
- this->FileCommand->SetError(e.str());
- return false;
- }
-
- // Compute the requested permissions for the destination directory.
- mode_t permissions =
- (match_properties.Permissions ? match_properties.Permissions
- : this->DirPermissions);
- if (!permissions) {
- // No permissions were explicitly provided but the user requested
- // that the source directory permissions be used.
- cmSystemTools::GetPermissions(source, permissions);
- }
-
- // Compute the set of permissions required on this directory to
- // recursively install files and subdirectories safely.
- mode_t required_permissions =
- mode_owner_read | mode_owner_write | mode_owner_execute;
-
- // If the required permissions are specified it is safe to set the
- // final permissions now. Otherwise we must add the required
- // permissions temporarily during file installation.
- mode_t permissions_before = 0;
- mode_t permissions_after = 0;
- if ((permissions & required_permissions) == required_permissions) {
- permissions_before = permissions;
- } else {
- permissions_before = permissions | required_permissions;
- permissions_after = permissions;
- }
-
- // Set the required permissions of the destination directory.
- if (!this->SetPermissions(destination, permissions_before)) {
- return false;
- }
-
- // Load the directory contents to traverse it recursively.
- cmsys::Directory dir;
- if (source && *source) {
- dir.Load(source);
- }
- unsigned long numFiles = static_cast<unsigned long>(dir.GetNumberOfFiles());
- for (unsigned long fileNum = 0; fileNum < numFiles; ++fileNum) {
- if (!(strcmp(dir.GetFile(fileNum), ".") == 0 ||
- strcmp(dir.GetFile(fileNum), "..") == 0)) {
- std::string fromPath = source;
- fromPath += "/";
- fromPath += dir.GetFile(fileNum);
- std::string toPath = destination;
- toPath += "/";
- toPath += dir.GetFile(fileNum);
- if (!this->Install(fromPath.c_str(), toPath.c_str())) {
- return false;
- }
- }
- }
-
- // Set the requested permissions of the destination directory.
- return this->SetPermissions(destination, permissions_after);
-}
-
-bool cmFileCommand::HandleCopyCommand(std::vector<std::string> const& args)
-{
- cmFileCopier copier(this);
+ cmFileCopier copier(status);
return copier.Run(args);
}
-struct cmFileInstaller : public cmFileCopier
-{
- cmFileInstaller(cmFileCommand* command)
- : cmFileCopier(command, "INSTALL")
- , InstallType(cmInstallType_FILES)
- , Optional(false)
- , MessageAlways(false)
- , MessageLazy(false)
- , MessageNever(false)
- , DestDirLength(0)
- {
- // Installation does not use source permissions by default.
- this->UseSourcePermissions = false;
- // Check whether to copy files always or only if they have changed.
- std::string install_always;
- if (cmSystemTools::GetEnv("CMAKE_INSTALL_ALWAYS", install_always)) {
- this->Always = cmSystemTools::IsOn(install_always.c_str());
- }
- // Get the current manifest.
- this->Manifest =
- this->Makefile->GetSafeDefinition("CMAKE_INSTALL_MANIFEST_FILES");
- }
- ~cmFileInstaller() CM_OVERRIDE
- {
- // Save the updated install manifest.
- this->Makefile->AddDefinition("CMAKE_INSTALL_MANIFEST_FILES",
- this->Manifest.c_str());
- }
-
-protected:
- cmInstallType InstallType;
- bool Optional;
- bool MessageAlways;
- bool MessageLazy;
- bool MessageNever;
- int DestDirLength;
- std::string Rename;
-
- std::string Manifest;
- void ManifestAppend(std::string const& file)
- {
- if (!this->Manifest.empty()) {
- this->Manifest += ";";
- }
- this->Manifest += file.substr(this->DestDirLength);
- }
-
- std::string const& ToName(std::string const& fromName) CM_OVERRIDE
- {
- return this->Rename.empty() ? fromName : this->Rename;
- }
-
- void ReportCopy(const char* toFile, Type type, bool copy) CM_OVERRIDE
- {
- if (!this->MessageNever && (copy || !this->MessageLazy)) {
- std::string message = (copy ? "Installing: " : "Up-to-date: ");
- message += toFile;
- this->Makefile->DisplayStatus(message.c_str(), -1);
- }
- if (type != TypeDir) {
- // Add the file to the manifest.
- this->ManifestAppend(toFile);
- }
- }
- bool ReportMissing(const char* fromFile) CM_OVERRIDE
- {
- return (this->Optional || this->cmFileCopier::ReportMissing(fromFile));
- }
- bool Install(const char* fromFile, const char* toFile) CM_OVERRIDE
- {
- // Support installing from empty source to make a directory.
- if (this->InstallType == cmInstallType_DIRECTORY && !*fromFile) {
- return this->InstallDirectory(fromFile, toFile, MatchProperties());
- }
- return this->cmFileCopier::Install(fromFile, toFile);
- }
-
- bool Parse(std::vector<std::string> const& args) CM_OVERRIDE;
- enum
- {
- DoingType = DoingLast1,
- DoingRename,
- DoingLast2
- };
- bool CheckKeyword(std::string const& arg) CM_OVERRIDE;
- bool CheckValue(std::string const& arg) CM_OVERRIDE;
- void DefaultFilePermissions() CM_OVERRIDE
- {
- this->cmFileCopier::DefaultFilePermissions();
- // Add execute permissions based on the target type.
- switch (this->InstallType) {
- case cmInstallType_SHARED_LIBRARY:
- case cmInstallType_MODULE_LIBRARY:
- if (this->Makefile->IsOn("CMAKE_INSTALL_SO_NO_EXE")) {
- break;
- }
- CM_FALLTHROUGH;
- case cmInstallType_EXECUTABLE:
- case cmInstallType_PROGRAMS:
- this->FilePermissions |= mode_owner_execute;
- this->FilePermissions |= mode_group_execute;
- this->FilePermissions |= mode_world_execute;
- break;
- default:
- break;
- }
- }
- bool GetTargetTypeFromString(const std::string& stype);
- bool HandleInstallDestination();
-};
-
-bool cmFileInstaller::Parse(std::vector<std::string> const& args)
-{
- if (!this->cmFileCopier::Parse(args)) {
- return false;
- }
-
- if (!this->Rename.empty()) {
- if (!this->FilesFromDir.empty()) {
- this->FileCommand->SetError("INSTALL option RENAME may not be "
- "combined with FILES_FROM_DIR.");
- return false;
- }
- if (this->InstallType != cmInstallType_FILES &&
- this->InstallType != cmInstallType_PROGRAMS) {
- this->FileCommand->SetError("INSTALL option RENAME may be used "
- "only with FILES or PROGRAMS.");
- return false;
- }
- if (this->Files.size() > 1) {
- this->FileCommand->SetError("INSTALL option RENAME may be used "
- "only with one file.");
- return false;
- }
- }
-
- if (!this->HandleInstallDestination()) {
- return false;
- }
-
- if (((this->MessageAlways ? 1 : 0) + (this->MessageLazy ? 1 : 0) +
- (this->MessageNever ? 1 : 0)) > 1) {
- this->FileCommand->SetError("INSTALL options MESSAGE_ALWAYS, "
- "MESSAGE_LAZY, and MESSAGE_NEVER "
- "are mutually exclusive.");
- return false;
- }
-
- return true;
-}
-
-bool cmFileInstaller::CheckKeyword(std::string const& arg)
-{
- if (arg == "TYPE") {
- if (this->CurrentMatchRule) {
- this->NotAfterMatch(arg);
- } else {
- this->Doing = DoingType;
- }
- } else if (arg == "FILES") {
- if (this->CurrentMatchRule) {
- this->NotAfterMatch(arg);
- } else {
- this->Doing = DoingFiles;
- }
- } else if (arg == "RENAME") {
- if (this->CurrentMatchRule) {
- this->NotAfterMatch(arg);
- } else {
- this->Doing = DoingRename;
- }
- } else if (arg == "OPTIONAL") {
- if (this->CurrentMatchRule) {
- this->NotAfterMatch(arg);
- } else {
- this->Doing = DoingNone;
- this->Optional = true;
- }
- } else if (arg == "MESSAGE_ALWAYS") {
- if (this->CurrentMatchRule) {
- this->NotAfterMatch(arg);
- } else {
- this->Doing = DoingNone;
- this->MessageAlways = true;
- }
- } else if (arg == "MESSAGE_LAZY") {
- if (this->CurrentMatchRule) {
- this->NotAfterMatch(arg);
- } else {
- this->Doing = DoingNone;
- this->MessageLazy = true;
- }
- } else if (arg == "MESSAGE_NEVER") {
- if (this->CurrentMatchRule) {
- this->NotAfterMatch(arg);
- } else {
- this->Doing = DoingNone;
- this->MessageNever = true;
- }
- } else if (arg == "PERMISSIONS") {
- if (this->CurrentMatchRule) {
- this->Doing = DoingPermissionsMatch;
- } else {
- // file(INSTALL) aliases PERMISSIONS to FILE_PERMISSIONS
- this->Doing = DoingPermissionsFile;
- this->UseGivenPermissionsFile = true;
- }
- } else if (arg == "DIR_PERMISSIONS") {
- if (this->CurrentMatchRule) {
- this->NotAfterMatch(arg);
- } else {
- // file(INSTALL) aliases DIR_PERMISSIONS to DIRECTORY_PERMISSIONS
- this->Doing = DoingPermissionsDir;
- this->UseGivenPermissionsDir = true;
- }
- } else if (arg == "COMPONENTS" || arg == "CONFIGURATIONS" ||
- arg == "PROPERTIES") {
- std::ostringstream e;
- e << "INSTALL called with old-style " << arg << " argument. "
- << "This script was generated with an older version of CMake. "
- << "Re-run this cmake version on your build tree.";
- this->FileCommand->SetError(e.str());
- this->Doing = DoingError;
- } else {
- return this->cmFileCopier::CheckKeyword(arg);
- }
- return true;
-}
-
-bool cmFileInstaller::CheckValue(std::string const& arg)
-{
- switch (this->Doing) {
- case DoingType:
- if (!this->GetTargetTypeFromString(arg)) {
- this->Doing = DoingError;
- }
- break;
- case DoingRename:
- this->Rename = arg;
- break;
- default:
- return this->cmFileCopier::CheckValue(arg);
- }
- return true;
-}
-
-bool cmFileInstaller::GetTargetTypeFromString(const std::string& stype)
-{
- if (stype == "EXECUTABLE") {
- this->InstallType = cmInstallType_EXECUTABLE;
- } else if (stype == "FILE") {
- this->InstallType = cmInstallType_FILES;
- } else if (stype == "PROGRAM") {
- this->InstallType = cmInstallType_PROGRAMS;
- } else if (stype == "STATIC_LIBRARY") {
- this->InstallType = cmInstallType_STATIC_LIBRARY;
- } else if (stype == "SHARED_LIBRARY") {
- this->InstallType = cmInstallType_SHARED_LIBRARY;
- } else if (stype == "MODULE") {
- this->InstallType = cmInstallType_MODULE_LIBRARY;
- } else if (stype == "DIRECTORY") {
- this->InstallType = cmInstallType_DIRECTORY;
- } else {
- std::ostringstream e;
- e << "Option TYPE given unknown value \"" << stype << "\".";
- this->FileCommand->SetError(e.str());
- return false;
- }
- return true;
-}
-
-bool cmFileInstaller::HandleInstallDestination()
-{
- std::string& destination = this->Destination;
-
- // allow for / to be a valid destination
- if (destination.size() < 2 && destination != "/") {
- this->FileCommand->SetError("called with inappropriate arguments. "
- "No DESTINATION provided or .");
- return false;
- }
-
- std::string sdestdir;
- if (cmSystemTools::GetEnv("DESTDIR", sdestdir) && !sdestdir.empty()) {
- cmSystemTools::ConvertToUnixSlashes(sdestdir);
- char ch1 = destination[0];
- char ch2 = destination[1];
- char ch3 = 0;
- if (destination.size() > 2) {
- ch3 = destination[2];
- }
- int skip = 0;
- if (ch1 != '/') {
- int relative = 0;
- if (((ch1 >= 'a' && ch1 <= 'z') || (ch1 >= 'A' && ch1 <= 'Z')) &&
- ch2 == ':') {
- // Assume windows
- // let's do some destdir magic:
- skip = 2;
- if (ch3 != '/') {
- relative = 1;
- }
- } else {
- relative = 1;
- }
- if (relative) {
- // This is relative path on unix or windows. Since we are doing
- // destdir, this case does not make sense.
- this->FileCommand->SetError(
- "called with relative DESTINATION. This "
- "does not make sense when using DESTDIR. Specify "
- "absolute path or remove DESTDIR environment variable.");
- return false;
- }
- } else {
- if (ch2 == '/') {
- // looks like a network path.
- std::string message =
- "called with network path DESTINATION. This "
- "does not make sense when using DESTDIR. Specify local "
- "absolute path or remove DESTDIR environment variable."
- "\nDESTINATION=\n";
- message += destination;
- this->FileCommand->SetError(message);
- return false;
- }
- }
- destination = sdestdir + (destination.c_str() + skip);
- this->DestDirLength = int(sdestdir.size());
- }
-
- if (this->InstallType != cmInstallType_DIRECTORY) {
- if (!cmSystemTools::FileExists(destination.c_str())) {
- if (!cmSystemTools::MakeDirectory(destination.c_str())) {
- std::string errstring = "cannot create directory: " + destination +
- ". Maybe need administrative privileges.";
- this->FileCommand->SetError(errstring);
- return false;
- }
- }
- if (!cmSystemTools::FileIsDirectory(destination)) {
- std::string errstring =
- "INSTALL destination: " + destination + " is not a directory.";
- this->FileCommand->SetError(errstring);
- return false;
- }
- }
- return true;
-}
-
-bool cmFileCommand::HandleRPathChangeCommand(
- std::vector<std::string> const& args)
+bool HandleRPathChangeCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
// Evaluate arguments.
- const char* file = CM_NULLPTR;
- const char* oldRPath = CM_NULLPTR;
- const char* newRPath = CM_NULLPTR;
+ std::string file;
+ const char* oldRPath = nullptr;
+ const char* newRPath = nullptr;
+ bool removeEnvironmentRPath = false;
enum Doing
{
DoingNone,
@@ -2046,8 +995,10 @@ bool cmFileCommand::HandleRPathChangeCommand(
doing = DoingNew;
} else if (args[i] == "FILE") {
doing = DoingFile;
+ } else if (args[i] == "INSTALL_REMOVE_ENVIRONMENT_RPATH") {
+ removeEnvironmentRPath = true;
} else if (doing == DoingFile) {
- file = args[i].c_str();
+ file = args[i];
doing = DoingNone;
} else if (doing == DoingOld) {
oldRPath = args[i].c_str();
@@ -2056,69 +1007,56 @@ bool cmFileCommand::HandleRPathChangeCommand(
newRPath = args[i].c_str();
doing = DoingNone;
} else {
- std::ostringstream e;
- e << "RPATH_CHANGE given unknown argument " << args[i];
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("RPATH_CHANGE given unknown argument ", args[i]));
return false;
}
}
- if (!file) {
- this->SetError("RPATH_CHANGE not given FILE option.");
+ if (file.empty()) {
+ status.SetError("RPATH_CHANGE not given FILE option.");
return false;
}
if (!oldRPath) {
- this->SetError("RPATH_CHANGE not given OLD_RPATH option.");
+ status.SetError("RPATH_CHANGE not given OLD_RPATH option.");
return false;
}
if (!newRPath) {
- this->SetError("RPATH_CHANGE not given NEW_RPATH option.");
+ status.SetError("RPATH_CHANGE not given NEW_RPATH option.");
return false;
}
if (!cmSystemTools::FileExists(file, true)) {
- std::ostringstream e;
- e << "RPATH_CHANGE given FILE \"" << file << "\" that does not exist.";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("RPATH_CHANGE given FILE \"", file, "\" that does not exist."));
return false;
}
bool success = true;
- cmSystemToolsFileTime* ft = cmSystemTools::FileTimeNew();
- bool have_ft = cmSystemTools::FileTimeGet(file, ft);
+ cmFileTimes const ft(file);
std::string emsg;
bool changed;
- if (!cmSystemTools::ChangeRPath(file, oldRPath, newRPath, &emsg, &changed)) {
- std::ostringstream e;
- /* clang-format off */
- e << "RPATH_CHANGE could not write new RPATH:\n"
- << " " << newRPath << "\n"
- << "to the file:\n"
- << " " << file << "\n"
- << emsg;
- /* clang-format on */
- this->SetError(e.str());
+
+ if (!cmSystemTools::ChangeRPath(file, oldRPath, newRPath,
+ removeEnvironmentRPath, &emsg, &changed)) {
+ status.SetError(cmStrCat("RPATH_CHANGE could not write new RPATH:\n ",
+ newRPath, "\nto the file:\n ", file, "\n",
+ emsg));
success = false;
}
if (success) {
if (changed) {
- std::string message = "Set runtime path of \"";
- message += file;
- message += "\" to \"";
- message += newRPath;
- message += "\"";
- this->Makefile->DisplayStatus(message.c_str(), -1);
- }
- if (have_ft) {
- cmSystemTools::FileTimeSet(file, ft);
+ std::string message =
+ cmStrCat("Set runtime path of \"", file, "\" to \"", newRPath, '"');
+ status.GetMakefile().DisplayStatus(message, -1);
}
+ ft.Store(file);
}
- cmSystemTools::FileTimeDelete(ft);
return success;
}
-bool cmFileCommand::HandleRPathRemoveCommand(
- std::vector<std::string> const& args)
+bool HandleRPathRemoveCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
// Evaluate arguments.
- const char* file = CM_NULLPTR;
+ std::string file;
enum Doing
{
DoingNone,
@@ -2129,61 +1067,50 @@ bool cmFileCommand::HandleRPathRemoveCommand(
if (args[i] == "FILE") {
doing = DoingFile;
} else if (doing == DoingFile) {
- file = args[i].c_str();
+ file = args[i];
doing = DoingNone;
} else {
- std::ostringstream e;
- e << "RPATH_REMOVE given unknown argument " << args[i];
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("RPATH_REMOVE given unknown argument ", args[i]));
return false;
}
}
- if (!file) {
- this->SetError("RPATH_REMOVE not given FILE option.");
+ if (file.empty()) {
+ status.SetError("RPATH_REMOVE not given FILE option.");
return false;
}
if (!cmSystemTools::FileExists(file, true)) {
- std::ostringstream e;
- e << "RPATH_REMOVE given FILE \"" << file << "\" that does not exist.";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("RPATH_REMOVE given FILE \"", file, "\" that does not exist."));
return false;
}
bool success = true;
- cmSystemToolsFileTime* ft = cmSystemTools::FileTimeNew();
- bool have_ft = cmSystemTools::FileTimeGet(file, ft);
+ cmFileTimes const ft(file);
std::string emsg;
bool removed;
if (!cmSystemTools::RemoveRPath(file, &emsg, &removed)) {
- std::ostringstream e;
- /* clang-format off */
- e << "RPATH_REMOVE could not remove RPATH from file:\n"
- << " " << file << "\n"
- << emsg;
- /* clang-format on */
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("RPATH_REMOVE could not remove RPATH from file: \n ", file,
+ "\n", emsg));
success = false;
}
if (success) {
if (removed) {
- std::string message = "Removed runtime path from \"";
- message += file;
- message += "\"";
- this->Makefile->DisplayStatus(message.c_str(), -1);
- }
- if (have_ft) {
- cmSystemTools::FileTimeSet(file, ft);
+ std::string message =
+ cmStrCat("Removed runtime path from \"", file, '"');
+ status.GetMakefile().DisplayStatus(message, -1);
}
+ ft.Store(file);
}
- cmSystemTools::FileTimeDelete(ft);
return success;
}
-bool cmFileCommand::HandleRPathCheckCommand(
- std::vector<std::string> const& args)
+bool HandleRPathCheckCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
// Evaluate arguments.
- const char* file = CM_NULLPTR;
- const char* rpath = CM_NULLPTR;
+ std::string file;
+ const char* rpath = nullptr;
enum Doing
{
DoingNone,
@@ -2197,24 +1124,23 @@ bool cmFileCommand::HandleRPathCheckCommand(
} else if (args[i] == "FILE") {
doing = DoingFile;
} else if (doing == DoingFile) {
- file = args[i].c_str();
+ file = args[i];
doing = DoingNone;
} else if (doing == DoingRPath) {
rpath = args[i].c_str();
doing = DoingNone;
} else {
- std::ostringstream e;
- e << "RPATH_CHECK given unknown argument " << args[i];
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("RPATH_CHECK given unknown argument ", args[i]));
return false;
}
}
- if (!file) {
- this->SetError("RPATH_CHECK not given FILE option.");
+ if (file.empty()) {
+ status.SetError("RPATH_CHECK not given FILE option.");
return false;
}
if (!rpath) {
- this->SetError("RPATH_CHECK not given RPATH option.");
+ status.SetError("RPATH_CHECK not given RPATH option.");
return false;
}
@@ -2229,79 +1155,78 @@ bool cmFileCommand::HandleRPathCheckCommand(
return true;
}
-bool cmFileCommand::HandleReadElfCommand(std::vector<std::string> const& args)
+bool HandleReadElfCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 4) {
- this->SetError("READ_ELF must be called with at least three additional "
- "arguments.");
+ status.SetError("READ_ELF must be called with at least three additional "
+ "arguments.");
return false;
}
- cmCommandArgumentsHelper argHelper;
- cmCommandArgumentGroup group;
-
- cmCAString readArg(&argHelper, "READ_ELF");
- cmCAString fileNameArg(&argHelper, CM_NULLPTR);
+ std::string const& fileNameArg = args[1];
- cmCAString rpathArg(&argHelper, "RPATH", &group);
- cmCAString runpathArg(&argHelper, "RUNPATH", &group);
- cmCAString errorArg(&argHelper, "CAPTURE_ERROR", &group);
+ struct Arguments
+ {
+ std::string RPath;
+ std::string RunPath;
+ std::string Error;
+ };
- readArg.Follows(CM_NULLPTR);
- fileNameArg.Follows(&readArg);
- group.Follows(&fileNameArg);
- argHelper.Parse(&args, CM_NULLPTR);
+ static auto const parser = cmArgumentParser<Arguments>{}
+ .Bind("RPATH"_s, &Arguments::RPath)
+ .Bind("RUNPATH"_s, &Arguments::RunPath)
+ .Bind("CAPTURE_ERROR"_s, &Arguments::Error);
+ Arguments const arguments = parser.Parse(cmMakeRange(args).advance(2));
- if (!cmSystemTools::FileExists(fileNameArg.GetString(), true)) {
- std::ostringstream e;
- e << "READ_ELF given FILE \"" << fileNameArg.GetString()
- << "\" that does not exist.";
- this->SetError(e.str());
+ if (!cmSystemTools::FileExists(fileNameArg, true)) {
+ status.SetError(cmStrCat("READ_ELF given FILE \"", fileNameArg,
+ "\" that does not exist."));
return false;
}
#if defined(CMAKE_USE_ELF_PARSER)
- cmELF elf(fileNameArg.GetCString());
+ cmELF elf(fileNameArg.c_str());
- if (!rpathArg.GetString().empty()) {
+ if (!arguments.RPath.empty()) {
if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) {
std::string rpath(se_rpath->Value);
std::replace(rpath.begin(), rpath.end(), ':', ';');
- this->Makefile->AddDefinition(rpathArg.GetString(), rpath.c_str());
+ status.GetMakefile().AddDefinition(arguments.RPath, rpath);
}
}
- if (!runpathArg.GetString().empty()) {
+ if (!arguments.RunPath.empty()) {
if (cmELF::StringEntry const* se_runpath = elf.GetRunPath()) {
std::string runpath(se_runpath->Value);
std::replace(runpath.begin(), runpath.end(), ':', ';');
- this->Makefile->AddDefinition(runpathArg.GetString(), runpath.c_str());
+ status.GetMakefile().AddDefinition(arguments.RunPath, runpath);
}
}
return true;
#else
std::string error = "ELF parser not available on this platform.";
- if (errorArg.GetString().empty()) {
- this->SetError(error);
+ if (arguments.Error.empty()) {
+ status.SetError(error);
return false;
- } else {
- this->Makefile->AddDefinition(errorArg.GetString(), error.c_str());
- return true;
}
+ status.GetMakefile().AddDefinition(arguments.Error, error);
+ return true;
#endif
}
-bool cmFileCommand::HandleInstallCommand(std::vector<std::string> const& args)
+bool HandleInstallCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- cmFileInstaller installer(this);
+ cmFileInstaller installer(status);
return installer.Run(args);
}
-bool cmFileCommand::HandleRelativePathCommand(
- std::vector<std::string> const& args)
+bool HandleRelativePathCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() != 4) {
- this->SetError("RELATIVE_PATH called with incorrect number of arguments");
+ status.SetError("RELATIVE_PATH called with incorrect number of arguments");
return false;
}
@@ -2309,79 +1234,78 @@ 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);
+ status.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);
+ status.SetError(errstring);
return false;
}
- std::string res =
- cmSystemTools::RelativePath(directoryName.c_str(), fileName.c_str());
- this->Makefile->AddDefinition(outVar, res.c_str());
+ std::string res = cmSystemTools::RelativePath(directoryName, fileName);
+ status.GetMakefile().AddDefinition(outVar, res);
return true;
}
-bool cmFileCommand::HandleRename(std::vector<std::string> const& args)
+bool HandleRename(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() != 3) {
- this->SetError("RENAME given incorrect number of arguments.");
+ status.SetError("RENAME given incorrect number of arguments.");
return false;
}
// Compute full path for old and new names.
std::string oldname = args[1];
- if (!cmsys::SystemTools::FileIsFullPath(oldname.c_str())) {
- oldname = this->Makefile->GetCurrentSourceDirectory();
- oldname += "/" + args[1];
+ if (!cmsys::SystemTools::FileIsFullPath(oldname)) {
+ oldname =
+ cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[1]);
}
std::string newname = args[2];
- if (!cmsys::SystemTools::FileIsFullPath(newname.c_str())) {
- newname = this->Makefile->GetCurrentSourceDirectory();
- newname += "/" + args[2];
+ if (!cmsys::SystemTools::FileIsFullPath(newname)) {
+ newname =
+ cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[2]);
}
- if (!cmSystemTools::RenameFile(oldname.c_str(), newname.c_str())) {
+ if (!cmSystemTools::RenameFile(oldname, newname)) {
std::string err = cmSystemTools::GetLastSystemError();
- std::ostringstream e;
- /* clang-format off */
- e << "RENAME failed to rename\n"
- << " " << oldname << "\n"
- << "to\n"
- << " " << newname << "\n"
- << "because: " << err << "\n";
- /* clang-format on */
- this->SetError(e.str());
+ status.SetError(cmStrCat("RENAME failed to rename\n ", oldname,
+ "\nto\n ", newname, "\nbecause: ", err, "\n"));
return false;
}
return true;
}
-bool cmFileCommand::HandleRemove(std::vector<std::string> const& args,
- bool recurse)
+bool HandleRemoveImpl(std::vector<std::string> const& args, bool recurse,
+ cmExecutionStatus& status)
{
std::string message;
- std::vector<std::string>::const_iterator i = args.begin();
- i++; // Get rid of subcommand
- for (; i != args.end(); ++i) {
- std::string fileName = *i;
- if (!cmsys::SystemTools::FileIsFullPath(fileName.c_str())) {
- fileName = this->Makefile->GetCurrentSourceDirectory();
- fileName += "/" + *i;
+ for (std::string const& arg :
+ cmMakeRange(args).advance(1)) // Get rid of subcommand
+ {
+ std::string fileName = arg;
+ if (fileName.empty()) {
+ std::string const r = recurse ? "REMOVE_RECURSE" : "REMOVE";
+ status.GetMakefile().IssueMessage(
+ MessageType::AUTHOR_WARNING, "Ignoring empty file name in " + r + ".");
+ continue;
+ }
+ if (!cmsys::SystemTools::FileIsFullPath(fileName)) {
+ fileName =
+ cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', arg);
}
if (cmSystemTools::FileIsDirectory(fileName) &&
!cmSystemTools::FileIsSymlink(fileName) && recurse) {
- cmSystemTools::RemoveADirectory(fileName);
+ cmSystemTools::RepeatedRemoveDirectory(fileName);
} else {
cmSystemTools::RemoveFile(fileName);
}
@@ -2389,57 +1313,76 @@ bool cmFileCommand::HandleRemove(std::vector<std::string> const& args,
return true;
}
-bool cmFileCommand::HandleCMakePathCommand(
- std::vector<std::string> const& args, bool nativePath)
+bool HandleRemove(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return HandleRemoveImpl(args, false, status);
+}
+
+bool HandleRemoveRecurse(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return HandleRemoveImpl(args, true, status);
+}
+
+std::string ToNativePath(const std::string& path)
+{
+ const auto& outPath = cmSystemTools::ConvertToOutputPath(path);
+ if (outPath.size() > 1 && outPath.front() == '\"' &&
+ outPath.back() == '\"') {
+ return outPath.substr(1, outPath.size() - 2);
+ }
+ return outPath;
+}
+
+std::string ToCMakePath(const std::string& path)
+{
+ auto temp = path;
+ cmSystemTools::ConvertToUnixSlashes(temp);
+ return temp;
+}
+
+bool HandlePathCommand(std::vector<std::string> const& args,
+ std::string (*convert)(std::string const&),
+ cmExecutionStatus& status)
{
- std::vector<std::string>::const_iterator i = args.begin();
if (args.size() != 3) {
- this->SetError("FILE([TO_CMAKE_PATH|TO_NATIVE_PATH] path result) must be "
- "called with exactly three arguments.");
+ status.SetError("FILE([TO_CMAKE_PATH|TO_NATIVE_PATH] path result) must be "
+ "called with exactly three arguments.");
return false;
}
- i++; // Get rid of subcommand
#if defined(_WIN32) && !defined(__CYGWIN__)
char pathSep = ';';
#else
char pathSep = ':';
#endif
- std::vector<cmsys::String> path = cmSystemTools::SplitString(*i, pathSep);
- i++;
- const char* var = i->c_str();
- std::string value;
- for (std::vector<cmsys::String>::iterator j = path.begin(); j != path.end();
- ++j) {
- if (j != path.begin()) {
- value += ";";
- }
- if (!nativePath) {
- cmSystemTools::ConvertToUnixSlashes(*j);
- } else {
- *j = cmSystemTools::ConvertToOutputPath(j->c_str());
- // remove double quotes in the path
- cmsys::String& s = *j;
+ std::vector<std::string> path = cmSystemTools::SplitString(args[1], pathSep);
- if (s.size() > 1 && s[0] == '\"' && s[s.size() - 1] == '\"') {
- s = s.substr(1, s.size() - 2);
- }
- }
- value += *j;
- }
- this->Makefile->AddDefinition(var, value.c_str());
+ std::string value = cmJoin(cmMakeRange(path).transform(convert), ";");
+ status.GetMakefile().AddDefinition(args[2], value);
return true;
}
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+bool HandleCMakePathCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return HandlePathCommand(args, ToCMakePath, status);
+}
-// Stuff for curl download/upload
-typedef std::vector<char> cmFileCommandVectorOfChar;
+bool HandleNativePathCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return HandlePathCommand(args, ToNativePath, status);
+}
-namespace {
+#if !defined(CMAKE_BOOTSTRAP)
+
+// Stuff for curl download/upload
+using cmFileCommandVectorOfChar = std::vector<char>;
size_t cmWriteToFileCallback(void* ptr, size_t size, size_t nmemb, void* data)
{
- int realsize = (int)(size * nmemb);
+ int realsize = static_cast<int>(size * nmemb);
cmsys::ofstream* fout = static_cast<cmsys::ofstream*>(data);
const char* chPtr = static_cast<char*>(ptr);
fout->write(chPtr, realsize);
@@ -2449,24 +1392,23 @@ size_t cmWriteToFileCallback(void* ptr, size_t size, size_t nmemb, void* data)
size_t cmWriteToMemoryCallback(void* ptr, size_t size, size_t nmemb,
void* data)
{
- int realsize = (int)(size * nmemb);
- cmFileCommandVectorOfChar* vec =
- static_cast<cmFileCommandVectorOfChar*>(data);
+ int realsize = static_cast<int>(size * nmemb);
const char* chPtr = static_cast<char*>(ptr);
- vec->insert(vec->end(), chPtr, chPtr + realsize);
+ cmAppend(*static_cast<cmFileCommandVectorOfChar*>(data), chPtr,
+ chPtr + realsize);
return realsize;
}
size_t cmFileCommandCurlDebugCallback(CURL*, curl_infotype type, char* chPtr,
size_t size, void* data)
{
- cmFileCommandVectorOfChar* vec =
- static_cast<cmFileCommandVectorOfChar*>(data);
+ cmFileCommandVectorOfChar& vec =
+ *static_cast<cmFileCommandVectorOfChar*>(data);
switch (type) {
case CURLINFO_TEXT:
case CURLINFO_HEADER_IN:
case CURLINFO_HEADER_OUT:
- vec->insert(vec->end(), chPtr, chPtr + size);
+ cmAppend(vec, chPtr, chPtr + size);
break;
case CURLINFO_DATA_IN:
case CURLINFO_DATA_OUT:
@@ -2476,7 +1418,7 @@ size_t cmFileCommandCurlDebugCallback(CURL*, curl_infotype type, char* chPtr,
int n = sprintf(buf, "[%" KWIML_INT_PRIu64 " bytes data]\n",
static_cast<KWIML_INT_uint64_t>(size));
if (n > 0) {
- vec->insert(vec->end(), buf, buf + n);
+ cmAppend(vec, buf, buf + n);
}
} break;
default:
@@ -2488,19 +1430,18 @@ size_t cmFileCommandCurlDebugCallback(CURL*, curl_infotype type, char* chPtr,
class cURLProgressHelper
{
public:
- cURLProgressHelper(cmFileCommand* fc, const char* text)
+ cURLProgressHelper(cmMakefile* mf, const char* text)
+ : Makefile(mf)
+ , Text(text)
{
- this->CurrentPercentage = -1;
- this->FileCommand = fc;
- this->Text = text;
}
bool UpdatePercentage(double value, double total, std::string& status)
{
- int OldPercentage = this->CurrentPercentage;
+ long OldPercentage = this->CurrentPercentage;
if (total > 0.0) {
- this->CurrentPercentage = static_cast<int>(value / total * 100.0 + 0.5);
+ this->CurrentPercentage = std::lround(value / total * 100.0);
if (this->CurrentPercentage > 100) {
// Avoid extra progress reports for unexpected data beyond total.
this->CurrentPercentage = 100;
@@ -2510,20 +1451,18 @@ public:
bool updated = (OldPercentage != this->CurrentPercentage);
if (updated) {
- std::ostringstream oss;
- oss << "[" << this->Text << " " << this->CurrentPercentage
- << "% complete]";
- status = oss.str();
+ status =
+ cmStrCat("[", this->Text, " ", this->CurrentPercentage, "% complete]");
}
return updated;
}
- cmFileCommand* GetFileCommand() { return this->FileCommand; }
+ cmMakefile* GetMakefile() { return this->Makefile; }
private:
- int CurrentPercentage;
- cmFileCommand* FileCommand;
+ long CurrentPercentage = -1;
+ cmMakefile* Makefile;
std::string Text;
};
@@ -2537,9 +1476,8 @@ int cmFileDownloadProgressCallback(void* clientp, double dltotal, double dlnow,
std::string status;
if (helper->UpdatePercentage(dlnow, dltotal, status)) {
- cmFileCommand* fc = helper->GetFileCommand();
- cmMakefile* mf = fc->GetMakefile();
- mf->DisplayStatus(status.c_str(), -1);
+ cmMakefile* mf = helper->GetMakefile();
+ mf->DisplayStatus(status, -1);
}
return 0;
@@ -2555,16 +1493,12 @@ int cmFileUploadProgressCallback(void* clientp, double dltotal, double dlnow,
std::string status;
if (helper->UpdatePercentage(ulnow, ultotal, status)) {
- cmFileCommand* fc = helper->GetFileCommand();
- cmMakefile* mf = fc->GetMakefile();
- mf->DisplayStatus(status.c_str(), -1);
+ cmMakefile* mf = helper->GetMakefile();
+ mf->DisplayStatus(status, -1);
}
return 0;
}
-}
-
-namespace {
class cURLEasyGuard
{
@@ -2581,28 +1515,34 @@ public:
}
}
- void release() { this->Easy = CM_NULLPTR; }
+ cURLEasyGuard(const cURLEasyGuard&) = delete;
+ cURLEasyGuard& operator=(const cURLEasyGuard&) = delete;
+
+ void release() { this->Easy = nullptr; }
private:
::CURL* Easy;
};
-}
+
#endif
#define check_curl_result(result, errstr) \
- if (result != CURLE_OK) { \
- std::string e(errstr); \
- e += ::curl_easy_strerror(result); \
- this->SetError(e); \
- return false; \
- }
-
-bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
+ do { \
+ if (result != CURLE_OK) { \
+ std::string e(errstr); \
+ e += ::curl_easy_strerror(result); \
+ status.SetError(e); \
+ return false; \
+ } \
+ } while (false)
+
+bool HandleDownloadCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
-#if defined(CMAKE_BUILD_WITH_CMAKE)
- std::vector<std::string>::const_iterator i = args.begin();
+#if !defined(CMAKE_BOOTSTRAP)
+ auto i = args.begin();
if (args.size() < 3) {
- this->SetError("DOWNLOAD must be called with at least three arguments.");
+ status.SetError("DOWNLOAD must be called with at least three arguments.");
return false;
}
++i; // Get rid of subcommand
@@ -2615,11 +1555,15 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
long inactivity_timeout = 0;
std::string logVar;
std::string statusVar;
- bool tls_verify = this->Makefile->IsOn("CMAKE_TLS_VERIFY");
- const char* cainfo = this->Makefile->GetDefinition("CMAKE_TLS_CAINFO");
+ bool tls_verify = status.GetMakefile().IsOn("CMAKE_TLS_VERIFY");
+ const char* cainfo = status.GetMakefile().GetDefinition("CMAKE_TLS_CAINFO");
+ std::string netrc_level =
+ status.GetMakefile().GetSafeDefinition("CMAKE_NETRC");
+ std::string netrc_file =
+ status.GetMakefile().GetSafeDefinition("CMAKE_NETRC_FILE");
std::string expectedHash;
std::string hashMatchMSG;
- CM_AUTO_PTR<cmCryptoHash> hash;
+ std::unique_ptr<cmCryptoHash> hash;
bool showProgress = false;
std::string userpwd;
@@ -2631,7 +1575,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
if (i != args.end()) {
timeout = atol(i->c_str());
} else {
- this->SetError("DOWNLOAD missing time for TIMEOUT.");
+ status.SetError("DOWNLOAD missing time for TIMEOUT.");
return false;
}
} else if (*i == "INACTIVITY_TIMEOUT") {
@@ -2639,29 +1583,29 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
if (i != args.end()) {
inactivity_timeout = atol(i->c_str());
} else {
- this->SetError("DOWNLOAD missing time for INACTIVITY_TIMEOUT.");
+ status.SetError("DOWNLOAD missing time for INACTIVITY_TIMEOUT.");
return false;
}
} else if (*i == "LOG") {
++i;
if (i == args.end()) {
- this->SetError("DOWNLOAD missing VAR for LOG.");
+ status.SetError("DOWNLOAD missing VAR for LOG.");
return false;
}
logVar = *i;
} else if (*i == "STATUS") {
++i;
if (i == args.end()) {
- this->SetError("DOWNLOAD missing VAR for STATUS.");
+ status.SetError("DOWNLOAD missing VAR for STATUS.");
return false;
}
statusVar = *i;
} else if (*i == "TLS_VERIFY") {
++i;
if (i != args.end()) {
- tls_verify = cmSystemTools::IsOn(i->c_str());
+ tls_verify = cmIsOn(*i);
} else {
- this->SetError("TLS_VERIFY missing bool value.");
+ status.SetError("TLS_VERIFY missing bool value.");
return false;
}
} else if (*i == "TLS_CAINFO") {
@@ -2669,17 +1613,32 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
if (i != args.end()) {
cainfo = i->c_str();
} else {
- this->SetError("TLS_CAFILE missing file value.");
+ status.SetError("TLS_CAFILE missing file value.");
+ return false;
+ }
+ } else if (*i == "NETRC_FILE") {
+ ++i;
+ if (i != args.end()) {
+ netrc_file = *i;
+ } else {
+ status.SetError("DOWNLOAD missing file value for NETRC_FILE.");
+ return false;
+ }
+ } else if (*i == "NETRC") {
+ ++i;
+ if (i != args.end()) {
+ netrc_level = *i;
+ } else {
+ status.SetError("DOWNLOAD missing level value for NETRC.");
return false;
}
} else if (*i == "EXPECTED_MD5") {
++i;
if (i == args.end()) {
- this->SetError("DOWNLOAD missing sum value for EXPECTED_MD5.");
+ status.SetError("DOWNLOAD missing sum value for EXPECTED_MD5.");
return false;
}
- hash =
- CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(cmCryptoHash::AlgoMD5));
+ hash = cm::make_unique<cmCryptoHash>(cmCryptoHash::AlgoMD5);
hashMatchMSG = "MD5 sum";
expectedHash = cmSystemTools::LowerCase(*i);
} else if (*i == "SHOW_PROGRESS") {
@@ -2687,46 +1646,44 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
} else if (*i == "EXPECTED_HASH") {
++i;
if (i == args.end()) {
- this->SetError("DOWNLOAD missing ALGO=value for EXPECTED_HASH.");
+ status.SetError("DOWNLOAD missing ALGO=value for EXPECTED_HASH.");
return false;
}
std::string::size_type pos = i->find("=");
if (pos == std::string::npos) {
std::string err =
- "DOWNLOAD EXPECTED_HASH expects ALGO=value but got: ";
- err += *i;
- this->SetError(err);
+ cmStrCat("DOWNLOAD EXPECTED_HASH expects ALGO=value but got: ", *i);
+ status.SetError(err);
return false;
}
std::string algo = i->substr(0, pos);
expectedHash = cmSystemTools::LowerCase(i->substr(pos + 1));
- hash = CM_AUTO_PTR<cmCryptoHash>(cmCryptoHash::New(algo.c_str()));
- if (!hash.get()) {
- std::string err = "DOWNLOAD EXPECTED_HASH given unknown ALGO: ";
- err += algo;
- this->SetError(err);
+ hash = std::unique_ptr<cmCryptoHash>(cmCryptoHash::New(algo));
+ if (!hash) {
+ std::string err =
+ cmStrCat("DOWNLOAD EXPECTED_HASH given unknown ALGO: ", algo);
+ status.SetError(err);
return false;
}
hashMatchMSG = algo + " hash";
} else if (*i == "USERPWD") {
++i;
if (i == args.end()) {
- this->SetError("DOWNLOAD missing string for USERPWD.");
+ status.SetError("DOWNLOAD missing string for USERPWD.");
return false;
}
userpwd = *i;
} else if (*i == "HTTPHEADER") {
++i;
if (i == args.end()) {
- this->SetError("DOWNLOAD missing string for HTTPHEADER.");
+ status.SetError("DOWNLOAD missing string for HTTPHEADER.");
return false;
}
curl_headers.push_back(*i);
} else {
// Do not return error for compatibility reason.
- std::string err = "Unexpected argument: ";
- err += *i;
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, err);
+ std::string err = cmStrCat("Unexpected argument: ", *i);
+ status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, err);
}
++i;
}
@@ -2734,17 +1691,14 @@ 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) {
- msg = "returning early; file already exists with expected ";
- msg += hashMatchMSG;
- msg += "\"";
+ msg = cmStrCat("returning early; file already exists with expected ",
+ hashMatchMSG, '"');
if (!statusVar.empty()) {
- std::ostringstream result;
- result << (int)0 << ";\"" << msg;
- this->Makefile->AddDefinition(statusVar, result.str().c_str());
+ status.GetMakefile().AddDefinition(statusVar, cmStrCat(0, ";\"", msg));
}
return true;
}
@@ -2753,30 +1707,29 @@ 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.";
- this->SetError(errstring);
+ status.SetError(errstring);
return false;
}
cmsys::ofstream fout(file.c_str(), std::ios::binary);
if (!fout) {
- this->SetError("DOWNLOAD cannot open file for write.");
+ status.SetError("DOWNLOAD cannot open file for write.");
return false;
}
-#if defined(_WIN32)
+# if defined(_WIN32)
url = fix_file_url_windows(url);
-#endif
+# endif
::CURL* curl;
::curl_global_init(CURL_GLOBAL_DEFAULT);
curl = ::curl_easy_init();
if (!curl) {
- this->SetError("DOWNLOAD error initializing curl.");
+ status.SetError("DOWNLOAD error initializing curl.");
return false;
}
@@ -2810,16 +1763,26 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
// command arg comes first
std::string const& cainfo_err = cmCurlSetCAInfo(curl, cainfo);
if (!cainfo_err.empty()) {
- this->SetError(cainfo_err);
+ status.SetError(cainfo_err);
+ 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()) {
+ status.SetError(netrc_option_err);
return false;
}
cmFileCommandVectorOfChar chunkDebug;
- res = ::curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&fout);
+ res = ::curl_easy_setopt(curl, CURLOPT_WRITEDATA, &fout);
check_curl_result(res, "DOWNLOAD cannot set write data: ");
- res = ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void*)&chunkDebug);
+ res = ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &chunkDebug);
check_curl_result(res, "DOWNLOAD cannot set debug data: ");
res = ::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
@@ -2846,7 +1809,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
// scope intentionally, rather than inside the "if(showProgress)"
// block...
//
- cURLProgressHelper helper(this, "download");
+ cURLProgressHelper helper(&status.GetMakefile(), "download");
if (showProgress) {
res = ::curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
@@ -2866,10 +1829,9 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
check_curl_result(res, "DOWNLOAD cannot set user password: ");
}
- struct curl_slist* headers = CM_NULLPTR;
- for (std::vector<std::string>::const_iterator h = curl_headers.begin();
- h != curl_headers.end(); ++h) {
- headers = ::curl_slist_append(headers, h->c_str());
+ struct curl_slist* headers = nullptr;
+ for (std::string const& h : curl_headers) {
+ headers = ::curl_slist_append(headers, h.c_str());
}
::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
@@ -2882,9 +1844,9 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
::curl_easy_cleanup(curl);
if (!statusVar.empty()) {
- std::ostringstream result;
- result << (int)res << ";\"" << ::curl_easy_strerror(res) << "\"";
- this->Makefile->AddDefinition(statusVar, result.str().c_str());
+ status.GetMakefile().AddDefinition(
+ statusVar,
+ cmStrCat(static_cast<int>(res), ";\"", ::curl_easy_strerror(res), "\""));
}
::curl_global_cleanup();
@@ -2896,54 +1858,60 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
// Verify MD5 sum if requested:
//
- if (hash.get()) {
+ if (hash) {
std::string actualHash = hash->HashFile(file);
if (actualHash.empty()) {
- this->SetError("DOWNLOAD cannot compute hash on downloaded file");
+ status.SetError("DOWNLOAD cannot compute hash on downloaded file");
return false;
}
if (expectedHash != actualHash) {
- std::ostringstream oss;
- oss << "DOWNLOAD HASH mismatch" << std::endl
- << " for file: [" << file << "]" << std::endl
- << " expected hash: [" << expectedHash << "]" << std::endl
- << " actual hash: [" << actualHash << "]" << std::endl
- << " status: [" << (int)res << ";\""
- << ::curl_easy_strerror(res) << "\"]" << std::endl;
-
if (!statusVar.empty() && res == 0) {
- std::string status = "1;HASH mismatch: "
- "expected: " +
- expectedHash + " actual: " + actualHash;
- this->Makefile->AddDefinition(statusVar, status.c_str());
- }
-
- this->SetError(oss.str());
+ status.GetMakefile().AddDefinition(statusVar,
+ "1;HASH mismatch: "
+ "expected: " +
+ expectedHash +
+ " actual: " + actualHash);
+ }
+
+ status.SetError(cmStrCat("DOWNLOAD HASH mismatch\n"
+ " for file: [",
+ file,
+ "]\n"
+ " expected hash: [",
+ expectedHash,
+ "]\n"
+ " actual hash: [",
+ actualHash,
+ "]\n"
+ " status: [",
+ static_cast<int>(res), ";\"",
+ ::curl_easy_strerror(res), "\"]\n"));
return false;
}
}
if (!logVar.empty()) {
chunkDebug.push_back(0);
- this->Makefile->AddDefinition(logVar, &*chunkDebug.begin());
+ status.GetMakefile().AddDefinition(logVar, chunkDebug.data());
}
return true;
#else
- this->SetError("DOWNLOAD not supported by bootstrap cmake.");
+ status.SetError("DOWNLOAD not supported by bootstrap cmake.");
return false;
#endif
}
-bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
+bool HandleUploadCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
if (args.size() < 3) {
- this->SetError("UPLOAD must be called with at least three arguments.");
+ status.SetError("UPLOAD must be called with at least three arguments.");
return false;
}
- std::vector<std::string>::const_iterator i = args.begin();
+ auto i = args.begin();
++i;
std::string filename = *i;
++i;
@@ -2956,6 +1924,10 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
std::string statusVar;
bool showProgress = false;
std::string userpwd;
+ std::string netrc_level =
+ status.GetMakefile().GetSafeDefinition("CMAKE_NETRC");
+ std::string netrc_file =
+ status.GetMakefile().GetSafeDefinition("CMAKE_NETRC_FILE");
std::vector<std::string> curl_headers;
@@ -2965,7 +1937,7 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
if (i != args.end()) {
timeout = atol(i->c_str());
} else {
- this->SetError("UPLOAD missing time for TIMEOUT.");
+ status.SetError("UPLOAD missing time for TIMEOUT.");
return false;
}
} else if (*i == "INACTIVITY_TIMEOUT") {
@@ -2973,44 +1945,59 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
if (i != args.end()) {
inactivity_timeout = atol(i->c_str());
} else {
- this->SetError("UPLOAD missing time for INACTIVITY_TIMEOUT.");
+ status.SetError("UPLOAD missing time for INACTIVITY_TIMEOUT.");
return false;
}
} else if (*i == "LOG") {
++i;
if (i == args.end()) {
- this->SetError("UPLOAD missing VAR for LOG.");
+ status.SetError("UPLOAD missing VAR for LOG.");
return false;
}
logVar = *i;
} else if (*i == "STATUS") {
++i;
if (i == args.end()) {
- this->SetError("UPLOAD missing VAR for STATUS.");
+ status.SetError("UPLOAD missing VAR for STATUS.");
return false;
}
statusVar = *i;
} else if (*i == "SHOW_PROGRESS") {
showProgress = true;
+ } else if (*i == "NETRC_FILE") {
+ ++i;
+ if (i != args.end()) {
+ netrc_file = *i;
+ } else {
+ status.SetError("UPLOAD missing file value for NETRC_FILE.");
+ return false;
+ }
+ } else if (*i == "NETRC") {
+ ++i;
+ if (i != args.end()) {
+ netrc_level = *i;
+ } else {
+ status.SetError("UPLOAD missing level value for NETRC.");
+ return false;
+ }
} else if (*i == "USERPWD") {
++i;
if (i == args.end()) {
- this->SetError("UPLOAD missing string for USERPWD.");
+ status.SetError("UPLOAD missing string for USERPWD.");
return false;
}
userpwd = *i;
} else if (*i == "HTTPHEADER") {
++i;
if (i == args.end()) {
- this->SetError("UPLOAD missing string for HTTPHEADER.");
+ status.SetError("UPLOAD missing string for HTTPHEADER.");
return false;
}
curl_headers.push_back(*i);
} else {
// Do not return error for compatibility reason.
- std::string err = "Unexpected argument: ";
- err += *i;
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, err);
+ std::string err = cmStrCat("Unexpected argument: ", *i);
+ status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, err);
}
++i;
@@ -3020,23 +2007,23 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
//
FILE* fin = cmsys::SystemTools::Fopen(filename, "rb");
if (!fin) {
- std::string errStr = "UPLOAD cannot open file '";
- errStr += filename + "' for reading.";
- this->SetError(errStr);
+ std::string errStr =
+ cmStrCat("UPLOAD cannot open file '", filename, "' for reading.");
+ status.SetError(errStr);
return false;
}
unsigned long file_size = cmsys::SystemTools::FileLength(filename);
-#if defined(_WIN32)
+# if defined(_WIN32)
url = fix_file_url_windows(url);
-#endif
+# endif
::CURL* curl;
::curl_global_init(CURL_GLOBAL_DEFAULT);
curl = ::curl_easy_init();
if (!curl) {
- this->SetError("UPLOAD error initializing curl.");
+ status.SetError("UPLOAD error initializing curl.");
fclose(fin);
return false;
}
@@ -3065,10 +2052,10 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
cmFileCommandVectorOfChar chunkResponse;
cmFileCommandVectorOfChar chunkDebug;
- res = ::curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&chunkResponse);
+ res = ::curl_easy_setopt(curl, CURLOPT_WRITEDATA, &chunkResponse);
check_curl_result(res, "UPLOAD cannot set write data: ");
- res = ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void*)&chunkDebug);
+ res = ::curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &chunkDebug);
check_curl_result(res, "UPLOAD cannot set debug data: ");
res = ::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
@@ -3095,7 +2082,7 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
// scope intentionally, rather than inside the "if(showProgress)"
// block...
//
- cURLProgressHelper helper(this, "upload");
+ cURLProgressHelper helper(&status.GetMakefile(), "upload");
if (showProgress) {
res = ::curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
@@ -3124,10 +2111,19 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
check_curl_result(res, "UPLOAD cannot set user password: ");
}
- struct curl_slist* headers = CM_NULLPTR;
- for (std::vector<std::string>::const_iterator h = curl_headers.begin();
- h != curl_headers.end(); ++h) {
- headers = ::curl_slist_append(headers, h->c_str());
+ // 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()) {
+ status.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());
}
::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
@@ -3140,15 +2136,15 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
::curl_easy_cleanup(curl);
if (!statusVar.empty()) {
- std::ostringstream result;
- result << (int)res << ";\"" << ::curl_easy_strerror(res) << "\"";
- this->Makefile->AddDefinition(statusVar, result.str().c_str());
+ status.GetMakefile().AddDefinition(
+ statusVar,
+ cmStrCat(static_cast<int>(res), ";\"", ::curl_easy_strerror(res), "\""));
}
::curl_global_cleanup();
fclose(fin);
- fin = CM_NULLPTR;
+ fin = nullptr;
if (!logVar.empty()) {
std::string log;
@@ -3156,88 +2152,90 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
if (!chunkResponse.empty()) {
chunkResponse.push_back(0);
log += "Response:\n";
- log += &*chunkResponse.begin();
+ log += chunkResponse.data();
log += "\n";
}
if (!chunkDebug.empty()) {
chunkDebug.push_back(0);
log += "Debug:\n";
- log += &*chunkDebug.begin();
+ log += chunkDebug.data();
log += "\n";
}
- this->Makefile->AddDefinition(logVar, log.c_str());
+ status.GetMakefile().AddDefinition(logVar, log);
}
return true;
#else
- this->SetError("UPLOAD not supported by bootstrap cmake.");
+ status.SetError("UPLOAD not supported by bootstrap cmake.");
return false;
#endif
}
-void cmFileCommand::AddEvaluationFile(const std::string& inputName,
- const std::string& outputExpr,
- const std::string& condition,
- bool inputIsContent)
+void AddEvaluationFile(const std::string& inputName,
+ const std::string& outputExpr,
+ const std::string& condition, bool inputIsContent,
+ cmExecutionStatus& status)
{
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ cmListFileBacktrace lfbt = status.GetMakefile().GetBacktrace();
cmGeneratorExpression outputGe(lfbt);
- CM_AUTO_PTR<cmCompiledGeneratorExpression> outputCge =
+ std::unique_ptr<cmCompiledGeneratorExpression> outputCge =
outputGe.Parse(outputExpr);
cmGeneratorExpression conditionGe(lfbt);
- CM_AUTO_PTR<cmCompiledGeneratorExpression> conditionCge =
+ std::unique_ptr<cmCompiledGeneratorExpression> conditionCge =
conditionGe.Parse(condition);
- this->Makefile->AddEvaluationFile(inputName, outputCge, conditionCge,
- inputIsContent);
+ status.GetMakefile().AddEvaluationFile(
+ inputName, std::move(outputCge), std::move(conditionCge), inputIsContent);
}
-bool cmFileCommand::HandleGenerateCommand(std::vector<std::string> const& args)
+bool HandleGenerateCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 5) {
- this->SetError("Incorrect arguments to GENERATE subcommand.");
+ status.SetError("Incorrect arguments to GENERATE subcommand.");
return false;
}
if (args[1] != "OUTPUT") {
- this->SetError("Incorrect arguments to GENERATE subcommand.");
+ status.SetError("Incorrect arguments to GENERATE subcommand.");
return false;
}
std::string condition;
if (args.size() > 5) {
if (args[5] != "CONDITION") {
- this->SetError("Incorrect arguments to GENERATE subcommand.");
+ status.SetError("Incorrect arguments to GENERATE subcommand.");
return false;
}
if (args.size() != 7) {
- this->SetError("Incorrect arguments to GENERATE subcommand.");
+ status.SetError("Incorrect arguments to GENERATE subcommand.");
return false;
}
condition = args[6];
if (condition.empty()) {
- this->SetError("CONDITION of sub-command GENERATE must not be empty if "
- "specified.");
+ status.SetError("CONDITION of sub-command GENERATE must not be empty if "
+ "specified.");
return false;
}
}
std::string output = args[2];
const bool inputIsContent = args[3] != "INPUT";
if (inputIsContent && args[3] != "CONTENT") {
- this->SetError("Incorrect arguments to GENERATE subcommand.");
+ status.SetError("Incorrect arguments to GENERATE subcommand.");
return false;
}
std::string input = args[4];
- this->AddEvaluationFile(input, output, condition, inputIsContent);
+ AddEvaluationFile(input, output, condition, inputIsContent, status);
return true;
}
-bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args)
+bool HandleLockCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
// Default values
bool directory = false;
bool release = false;
@@ -3253,8 +2251,9 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args)
// Parse arguments
if (args.size() < 2) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR, "sub-command LOCK requires at least two arguments.");
+ status.GetMakefile().IssueMessage(
+ MessageType::FATAL_ERROR,
+ "sub-command LOCK requires at least two arguments.");
return false;
}
@@ -3268,7 +2267,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args)
++i;
const char* merr = "expected FUNCTION, FILE or PROCESS after GUARD";
if (i >= args.size()) {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, merr);
+ status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, merr);
return false;
}
if (args[i] == "FUNCTION") {
@@ -3278,41 +2277,42 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args)
} else if (args[i] == "PROCESS") {
guard = GUARD_PROCESS;
} else {
- std::ostringstream e;
- e << merr << ", but got:\n \"" << args[i] << "\".";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ status.GetMakefile().IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(merr, ", but got:\n \"", args[i], "\"."));
return false;
}
} else if (args[i] == "RESULT_VARIABLE") {
++i;
if (i >= args.size()) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR, "expected variable name after RESULT_VARIABLE");
+ status.GetMakefile().IssueMessage(
+ MessageType::FATAL_ERROR,
+ "expected variable name after RESULT_VARIABLE");
return false;
}
resultVariable = args[i];
} else if (args[i] == "TIMEOUT") {
++i;
if (i >= args.size()) {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
- "expected timeout value after TIMEOUT");
+ status.GetMakefile().IssueMessage(
+ MessageType::FATAL_ERROR, "expected timeout value after TIMEOUT");
return false;
}
long scanned;
- if (!cmSystemTools::StringToLong(args[i].c_str(), &scanned) ||
- scanned < 0) {
- std::ostringstream e;
- e << "TIMEOUT value \"" << args[i] << "\" is not an unsigned integer.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ if (!cmStrToLong(args[i], &scanned) || scanned < 0) {
+ status.GetMakefile().IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("TIMEOUT value \"", args[i],
+ "\" is not an unsigned integer."));
return false;
}
timeout = static_cast<unsigned long>(scanned);
} else {
- std::ostringstream e;
- e << "expected DIRECTORY, RELEASE, GUARD, RESULT_VARIABLE or TIMEOUT\n";
- e << "but got: \"" << args[i] << "\".";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ status.GetMakefile().IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("expected DIRECTORY, RELEASE, GUARD, RESULT_VARIABLE or ",
+ "TIMEOUT\nbut got: \"", args[i], "\"."));
return false;
}
}
@@ -3322,7 +2322,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args)
}
if (!cmsys::SystemTools::FileIsFullPath(path)) {
- path = this->Makefile->GetCurrentSourceDirectory() + ("/" + path);
+ path = status.GetMakefile().GetCurrentSourceDirectory() + "/" + path;
}
// Unify path (remove '//', '/../', ...)
@@ -3331,18 +2331,19 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args)
// Create file and directories if needed
std::string parentDir = cmSystemTools::GetParentDirectory(path);
if (!cmSystemTools::MakeDirectory(parentDir)) {
- std::ostringstream e;
- e << "directory\n \"" << parentDir << "\"\ncreation failed ";
- e << "(check permissions).";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ status.GetMakefile().IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("directory\n \"", parentDir,
+ "\"\ncreation failed (check permissions)."));
cmSystemTools::SetFatalErrorOccured();
return false;
}
FILE* file = cmsys::SystemTools::Fopen(path, "w");
if (!file) {
- std::ostringstream e;
- e << "file\n \"" << path << "\"\ncreation failed (check permissions).";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ status.GetMakefile().IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("file\n \"", path,
+ "\"\ncreation failed (check permissions)."));
cmSystemTools::SetFatalErrorOccured();
return false;
}
@@ -3350,7 +2351,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args)
// Actual lock/unlock
cmFileLockPool& lockPool =
- this->Makefile->GetGlobalGenerator()->GetFileLockPool();
+ status.GetMakefile().GetGlobalGenerator()->GetFileLockPool();
cmFileLockResult fileLockResult(cmFileLockResult::MakeOk());
if (release) {
@@ -3375,34 +2376,34 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args)
const std::string result = fileLockResult.GetOutputMessage();
if (resultVariable.empty() && !fileLockResult.IsOk()) {
- std::ostringstream e;
- e << "error locking file\n \"" << path << "\"\n" << result << ".";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ status.GetMakefile().IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("error locking file\n \"", path, "\"\n", result, "."));
cmSystemTools::SetFatalErrorOccured();
return false;
}
if (!resultVariable.empty()) {
- this->Makefile->AddDefinition(resultVariable, result.c_str());
+ status.GetMakefile().AddDefinition(resultVariable, result);
}
return true;
#else
static_cast<void>(args);
- this->SetError("sub-command LOCK not implemented in bootstrap cmake");
+ status.SetError("sub-command LOCK not implemented in bootstrap cmake");
return false;
#endif
}
-bool cmFileCommand::HandleTimestampCommand(
- std::vector<std::string> const& args)
+bool HandleTimestampCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 3) {
- this->SetError("sub-command TIMESTAMP requires at least two arguments.");
+ status.SetError("sub-command TIMESTAMP requires at least two arguments.");
return false;
}
if (args.size() > 5) {
- this->SetError("sub-command TIMESTAMP takes at most four arguments.");
+ status.SetError("sub-command TIMESTAMP takes at most four arguments.");
return false;
}
@@ -3424,7 +2425,7 @@ bool cmFileCommand::HandleTimestampCommand(
} else {
std::string e = " TIMESTAMP sub-command does not recognize option " +
args[argsIndex] + ".";
- this->SetError(e);
+ status.SetError(e);
return false;
}
}
@@ -3432,7 +2433,401 @@ bool cmFileCommand::HandleTimestampCommand(
cmTimestamp timestamp;
std::string result =
timestamp.FileModificationTime(filename.c_str(), formatString, utcFlag);
- this->Makefile->AddDefinition(outputVariable, result.c_str());
+ status.GetMakefile().AddDefinition(outputVariable, result);
+
+ return true;
+}
+
+bool HandleSizeCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.size() != 3) {
+ status.SetError(
+ cmStrCat(args[0], " requires a file name and output variable"));
+ return false;
+ }
+
+ unsigned int argsIndex = 1;
+
+ const std::string& filename = args[argsIndex++];
+
+ const std::string& outputVariable = args[argsIndex++];
+
+ if (!cmSystemTools::FileExists(filename, true)) {
+ status.SetError(
+ cmStrCat("SIZE requested of path that is not readable:\n ", filename));
+ return false;
+ }
+
+ status.GetMakefile().AddDefinition(
+ outputVariable, std::to_string(cmSystemTools::FileLength(filename)));
+
+ return true;
+}
+
+bool HandleReadSymlinkCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.size() != 3) {
+ status.SetError(
+ cmStrCat(args[0], " requires a file name and output variable"));
+ return false;
+ }
+
+ const std::string& filename = args[1];
+ const std::string& outputVariable = args[2];
+
+ std::string result;
+ if (!cmSystemTools::ReadSymlink(filename, result)) {
+ status.SetError(cmStrCat(
+ "READ_SYMLINK requested of path that is not a symlink:\n ", filename));
+ return false;
+ }
+
+ status.GetMakefile().AddDefinition(outputVariable, result);
+
+ return true;
+}
+
+bool HandleCreateLinkCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.size() < 3) {
+ status.SetError("CREATE_LINK must be called with at least two additional "
+ "arguments");
+ return false;
+ }
+
+ std::string const& fileName = args[1];
+ std::string const& newFileName = args[2];
+
+ struct Arguments
+ {
+ std::string Result;
+ bool CopyOnError = false;
+ bool Symbolic = false;
+ };
+
+ static auto const parser =
+ cmArgumentParser<Arguments>{}
+ .Bind("RESULT"_s, &Arguments::Result)
+ .Bind("COPY_ON_ERROR"_s, &Arguments::CopyOnError)
+ .Bind("SYMBOLIC"_s, &Arguments::Symbolic);
+
+ std::vector<std::string> unconsumedArgs;
+ Arguments const arguments =
+ parser.Parse(cmMakeRange(args).advance(3), &unconsumedArgs);
+ if (!unconsumedArgs.empty()) {
+ status.SetError("unknown argument: \"" + unconsumedArgs.front() + '\"');
+ return false;
+ }
+
+ // The system error message generated in the operation.
+ std::string result;
+
+ // Check if the paths are distinct.
+ if (fileName == newFileName) {
+ result = "CREATE_LINK cannot use same file and newfile";
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result, result);
+ return true;
+ }
+ status.SetError(result);
+ return false;
+ }
+
+ // Hard link requires original file to exist.
+ if (!arguments.Symbolic && !cmSystemTools::FileExists(fileName)) {
+ result = "Cannot hard link \'" + fileName + "\' as it does not exist.";
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result, result);
+ return true;
+ }
+ status.SetError(result);
+ return false;
+ }
+
+ // Check if the new file already exists and remove it.
+ if ((cmSystemTools::FileExists(newFileName) ||
+ cmSystemTools::FileIsSymlink(newFileName)) &&
+ !cmSystemTools::RemoveFile(newFileName)) {
+ std::ostringstream e;
+ e << "Failed to create link '" << newFileName
+ << "' because existing path cannot be removed: "
+ << cmSystemTools::GetLastSystemError() << "\n";
+
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result, e.str());
+ return true;
+ }
+ status.SetError(e.str());
+ return false;
+ }
+
+ // Whether the operation completed successfully.
+ bool completed = false;
+
+ // Check if the command requires a symbolic link.
+ if (arguments.Symbolic) {
+ completed = cmSystemTools::CreateSymlink(fileName, newFileName, &result);
+ } else {
+ completed = cmSystemTools::CreateLink(fileName, newFileName, &result);
+ }
+
+ // Check if copy-on-error is enabled in the arguments.
+ if (!completed && arguments.CopyOnError) {
+ completed = cmsys::SystemTools::CopyFileAlways(fileName, newFileName);
+ if (!completed) {
+ result = "Copy failed: " + cmSystemTools::GetLastSystemError();
+ }
+ }
+
+ // Check if the operation was successful.
+ if (completed) {
+ result = "0";
+ } else if (arguments.Result.empty()) {
+ // The operation failed and the result is not reported in a variable.
+ status.SetError(result);
+ return false;
+ }
+
+ if (!arguments.Result.empty()) {
+ status.GetMakefile().AddDefinition(arguments.Result, result);
+ }
+
+ return true;
+}
+
+bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ static const std::set<std::string> supportedPlatforms = { "Windows", "Linux",
+ "Darwin" };
+ std::string platform =
+ status.GetMakefile().GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
+ if (!supportedPlatforms.count(platform)) {
+ status.SetError(
+ cmStrCat("GET_RUNTIME_DEPENDENCIES is not supported on system \"",
+ platform, "\""));
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+
+ if (status.GetMakefile().GetState()->GetMode() == cmState::Project) {
+ status.GetMakefile().IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ "You have used file(GET_RUNTIME_DEPENDENCIES)"
+ " in project mode. This is probably not what "
+ "you intended to do. Instead, please consider"
+ " using it in an install(CODE) or "
+ "install(SCRIPT) command. For example:"
+ "\n install(CODE [["
+ "\n file(GET_RUNTIME_DEPENDENCIES"
+ "\n # ..."
+ "\n )"
+ "\n ]])");
+ }
+
+ struct Arguments
+ {
+ std::string ResolvedDependenciesVar;
+ std::string UnresolvedDependenciesVar;
+ std::string ConflictingDependenciesPrefix;
+ std::string BundleExecutable;
+ std::vector<std::string> Executables;
+ std::vector<std::string> Libraries;
+ std::vector<std::string> Directories;
+ std::vector<std::string> Modules;
+ std::vector<std::string> PreIncludeRegexes;
+ std::vector<std::string> PreExcludeRegexes;
+ std::vector<std::string> PostIncludeRegexes;
+ std::vector<std::string> PostExcludeRegexes;
+ };
+
+ static auto const parser =
+ cmArgumentParser<Arguments>{}
+ .Bind("RESOLVED_DEPENDENCIES_VAR"_s, &Arguments::ResolvedDependenciesVar)
+ .Bind("UNRESOLVED_DEPENDENCIES_VAR"_s,
+ &Arguments::UnresolvedDependenciesVar)
+ .Bind("CONFLICTING_DEPENDENCIES_PREFIX"_s,
+ &Arguments::ConflictingDependenciesPrefix)
+ .Bind("BUNDLE_EXECUTABLE"_s, &Arguments::BundleExecutable)
+ .Bind("EXECUTABLES"_s, &Arguments::Executables)
+ .Bind("LIBRARIES"_s, &Arguments::Libraries)
+ .Bind("MODULES"_s, &Arguments::Modules)
+ .Bind("DIRECTORIES"_s, &Arguments::Directories)
+ .Bind("PRE_INCLUDE_REGEXES"_s, &Arguments::PreIncludeRegexes)
+ .Bind("PRE_EXCLUDE_REGEXES"_s, &Arguments::PreExcludeRegexes)
+ .Bind("POST_INCLUDE_REGEXES"_s, &Arguments::PostIncludeRegexes)
+ .Bind("POST_EXCLUDE_REGEXES"_s, &Arguments::PostExcludeRegexes);
+
+ std::vector<std::string> unrecognizedArguments;
+ std::vector<std::string> keywordsMissingValues;
+ auto parsedArgs =
+ parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
+ &keywordsMissingValues);
+ auto argIt = unrecognizedArguments.begin();
+ if (argIt != unrecognizedArguments.end()) {
+ status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\""));
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+
+ const std::vector<std::string> LIST_ARGS = { "DIRECTORIES",
+ "EXECUTABLES",
+ "LIBRARIES",
+ "MODULES",
+ "POST_EXCLUDE_REGEXES",
+ "POST_INCLUDE_REGEXES",
+ "PRE_EXCLUDE_REGEXES",
+ "PRE_INCLUDE_REGEXES" };
+ auto kwbegin = keywordsMissingValues.cbegin();
+ auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS);
+ if (kwend != kwbegin) {
+ status.SetError(cmStrCat("Keywords missing values:\n ",
+ cmJoin(cmMakeRange(kwbegin, kwend), "\n ")));
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+
+ cmRuntimeDependencyArchive archive(
+ status, parsedArgs.Directories, parsedArgs.BundleExecutable,
+ parsedArgs.PreIncludeRegexes, parsedArgs.PreExcludeRegexes,
+ parsedArgs.PostIncludeRegexes, parsedArgs.PostExcludeRegexes);
+ if (!archive.Prepare()) {
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+
+ if (!archive.GetRuntimeDependencies(
+ parsedArgs.Executables, parsedArgs.Libraries, parsedArgs.Modules)) {
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+
+ std::vector<std::string> deps;
+ std::vector<std::string> unresolvedDeps;
+ std::vector<std::string> conflictingDeps;
+ for (auto const& val : archive.GetResolvedPaths()) {
+ bool unique = true;
+ auto it = val.second.begin();
+ assert(it != val.second.end());
+ auto const& firstPath = *it;
+ while (++it != val.second.end()) {
+ if (!cmSystemTools::SameFile(firstPath, *it)) {
+ unique = false;
+ break;
+ }
+ }
+
+ if (unique) {
+ deps.push_back(firstPath);
+ } else if (!parsedArgs.ConflictingDependenciesPrefix.empty()) {
+ conflictingDeps.push_back(val.first);
+ std::vector<std::string> paths;
+ paths.insert(paths.begin(), val.second.begin(), val.second.end());
+ std::string varName =
+ parsedArgs.ConflictingDependenciesPrefix + "_" + val.first;
+ std::string pathsStr = cmJoin(paths, ";");
+ status.GetMakefile().AddDefinition(varName, pathsStr);
+ } else {
+ std::ostringstream e;
+ e << "Multiple conflicting paths found for " << val.first << ":";
+ for (auto const& path : val.second) {
+ e << "\n " << path;
+ }
+ status.SetError(e.str());
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+ }
+ if (!archive.GetUnresolvedPaths().empty()) {
+ if (!parsedArgs.UnresolvedDependenciesVar.empty()) {
+ unresolvedDeps.insert(unresolvedDeps.begin(),
+ archive.GetUnresolvedPaths().begin(),
+ archive.GetUnresolvedPaths().end());
+ } else {
+ auto it = archive.GetUnresolvedPaths().begin();
+ assert(it != archive.GetUnresolvedPaths().end());
+ status.SetError(cmStrCat("Could not resolve file ", *it));
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+ }
+
+ if (!parsedArgs.ResolvedDependenciesVar.empty()) {
+ std::string val = cmJoin(deps, ";");
+ status.GetMakefile().AddDefinition(parsedArgs.ResolvedDependenciesVar,
+ val);
+ }
+ if (!parsedArgs.UnresolvedDependenciesVar.empty()) {
+ std::string val = cmJoin(unresolvedDeps, ";");
+ status.GetMakefile().AddDefinition(parsedArgs.UnresolvedDependenciesVar,
+ val);
+ }
+ if (!parsedArgs.ConflictingDependenciesPrefix.empty()) {
+ std::string val = cmJoin(conflictingDeps, ";");
+ status.GetMakefile().AddDefinition(
+ parsedArgs.ConflictingDependenciesPrefix + "_FILENAMES", val);
+ }
return true;
}
+
+} // namespace
+
+bool cmFileCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.size() < 2) {
+ status.SetError("must be called with at least two arguments.");
+ return false;
+ }
+
+ static cmSubcommandTable const subcommand{
+ { "WRITE"_s, HandleWriteCommand },
+ { "APPEND"_s, HandleAppendCommand },
+ { "DOWNLOAD"_s, HandleDownloadCommand },
+ { "UPLOAD"_s, HandleUploadCommand },
+ { "READ"_s, HandleReadCommand },
+ { "MD5"_s, HandleHashCommand },
+ { "SHA1"_s, HandleHashCommand },
+ { "SHA224"_s, HandleHashCommand },
+ { "SHA256"_s, HandleHashCommand },
+ { "SHA384"_s, HandleHashCommand },
+ { "SHA512"_s, HandleHashCommand },
+ { "SHA3_224"_s, HandleHashCommand },
+ { "SHA3_256"_s, HandleHashCommand },
+ { "SHA3_384"_s, HandleHashCommand },
+ { "SHA3_512"_s, HandleHashCommand },
+ { "STRINGS"_s, HandleStringsCommand },
+ { "GLOB"_s, HandleGlobCommand },
+ { "GLOB_RECURSE"_s, HandleGlobRecurseCommand },
+ { "MAKE_DIRECTORY"_s, HandleMakeDirectoryCommand },
+ { "RENAME"_s, HandleRename },
+ { "REMOVE"_s, HandleRemove },
+ { "REMOVE_RECURSE"_s, HandleRemoveRecurse },
+ { "COPY"_s, HandleCopyCommand },
+ { "INSTALL"_s, HandleInstallCommand },
+ { "DIFFERENT"_s, HandleDifferentCommand },
+ { "RPATH_CHANGE"_s, HandleRPathChangeCommand },
+ { "CHRPATH"_s, HandleRPathChangeCommand },
+ { "RPATH_CHECK"_s, HandleRPathCheckCommand },
+ { "RPATH_REMOVE"_s, HandleRPathRemoveCommand },
+ { "READ_ELF"_s, HandleReadElfCommand },
+ { "RELATIVE_PATH"_s, HandleRelativePathCommand },
+ { "TO_CMAKE_PATH"_s, HandleCMakePathCommand },
+ { "TO_NATIVE_PATH"_s, HandleNativePathCommand },
+ { "TOUCH"_s, HandleTouchCommand },
+ { "TOUCH_NOCREATE"_s, HandleTouchNocreateCommand },
+ { "TIMESTAMP"_s, HandleTimestampCommand },
+ { "GENERATE"_s, HandleGenerateCommand },
+ { "LOCK"_s, HandleLockCommand },
+ { "SIZE"_s, HandleSizeCommand },
+ { "READ_SYMLINK"_s, HandleReadSymlinkCommand },
+ { "CREATE_LINK"_s, HandleCreateLinkCommand },
+ { "GET_RUNTIME_DEPENDENCIES"_s, HandleGetRuntimeDependenciesCommand },
+ };
+
+ return subcommand(args[0], args, status);
+}
diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h
index d09ef42f1..8c9b21990 100644
--- a/Source/cmFileCommand.h
+++ b/Source/cmFileCommand.h
@@ -3,66 +3,14 @@
#ifndef cmFileCommand_h
#define cmFileCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmFileCommand
- * \brief Command for manipulation of files
- *
- */
-class cmFileCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmFileCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-protected:
- bool HandleRename(std::vector<std::string> const& args);
- bool HandleRemove(std::vector<std::string> const& args, bool recurse);
- bool HandleWriteCommand(std::vector<std::string> const& args, bool append);
- bool HandleReadCommand(std::vector<std::string> const& args);
- bool HandleHashCommand(std::vector<std::string> const& args);
- bool HandleStringsCommand(std::vector<std::string> const& args);
- bool HandleGlobCommand(std::vector<std::string> const& args, bool recurse);
- bool HandleMakeDirectoryCommand(std::vector<std::string> const& args);
-
- bool HandleRelativePathCommand(std::vector<std::string> const& args);
- bool HandleCMakePathCommand(std::vector<std::string> const& args,
- bool nativePath);
- bool HandleReadElfCommand(std::vector<std::string> const& args);
- bool HandleRPathChangeCommand(std::vector<std::string> const& args);
- bool HandleRPathCheckCommand(std::vector<std::string> const& args);
- bool HandleRPathRemoveCommand(std::vector<std::string> const& args);
- bool HandleDifferentCommand(std::vector<std::string> const& args);
-
- bool HandleCopyCommand(std::vector<std::string> const& args);
- bool HandleInstallCommand(std::vector<std::string> const& args);
- bool HandleDownloadCommand(std::vector<std::string> const& args);
- bool HandleUploadCommand(std::vector<std::string> const& args);
-
- bool HandleTimestampCommand(std::vector<std::string> const& args);
- bool HandleGenerateCommand(std::vector<std::string> const& args);
- bool HandleLockCommand(std::vector<std::string> const& args);
-
-private:
- void AddEvaluationFile(const std::string& inputName,
- const std::string& outputExpr,
- const std::string& condition, bool inputIsContent);
-};
+bool cmFileCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx
new file mode 100644
index 000000000..627e05b58
--- /dev/null
+++ b/Source/cmFileCopier.cxx
@@ -0,0 +1,711 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmFileCopier.h"
+
+#include "cmsys/Directory.hxx"
+#include "cmsys/Glob.hxx"
+
+#include "cmExecutionStatus.h"
+#include "cmFSPermissions.h"
+#include "cmFileTimes.h"
+#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+#ifdef _WIN32
+# include "cmsys/FStream.hxx"
+#endif
+
+#include <cstring>
+#include <sstream>
+
+using namespace cmFSPermissions;
+
+cmFileCopier::cmFileCopier(cmExecutionStatus& status, const char* name)
+ : Status(status)
+ , Makefile(&status.GetMakefile())
+ , Name(name)
+ , Always(false)
+ , MatchlessFiles(true)
+ , FilePermissions(0)
+ , DirPermissions(0)
+ , CurrentMatchRule(nullptr)
+ , UseGivenPermissionsFile(false)
+ , UseGivenPermissionsDir(false)
+ , UseSourcePermissions(true)
+ , FollowSymlinkChain(false)
+ , Doing(DoingNone)
+{
+}
+
+cmFileCopier::~cmFileCopier() = default;
+
+cmFileCopier::MatchProperties cmFileCopier::CollectMatchProperties(
+ const std::string& file)
+{
+ // Match rules are case-insensitive on some platforms.
+#if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
+ const std::string file_to_match = cmSystemTools::LowerCase(file);
+#else
+ const std::string& file_to_match = file;
+#endif
+
+ // Collect properties from all matching rules.
+ bool matched = false;
+ MatchProperties result;
+ for (MatchRule& mr : this->MatchRules) {
+ if (mr.Regex.find(file_to_match)) {
+ matched = true;
+ result.Exclude |= mr.Properties.Exclude;
+ result.Permissions |= mr.Properties.Permissions;
+ }
+ }
+ if (!matched && !this->MatchlessFiles) {
+ result.Exclude = !cmSystemTools::FileIsDirectory(file);
+ }
+ return result;
+}
+
+bool cmFileCopier::SetPermissions(const std::string& toFile,
+ mode_t permissions)
+{
+ if (permissions) {
+#ifdef WIN32
+ if (Makefile->IsOn("CMAKE_CROSSCOMPILING")) {
+ // Store the mode in an NTFS alternate stream.
+ std::string mode_t_adt_filename = toFile + ":cmake_mode_t";
+
+ // Writing to an NTFS alternate stream changes the modification
+ // time, so we need to save and restore its original value.
+ cmFileTimes file_time_orig(toFile);
+ {
+ cmsys::ofstream permissionStream(mode_t_adt_filename.c_str());
+ if (permissionStream) {
+ permissionStream << std::oct << permissions << std::endl;
+ }
+ permissionStream.close();
+ }
+ file_time_orig.Store(toFile);
+ }
+#endif
+
+ if (!cmSystemTools::SetPermissions(toFile, permissions)) {
+ std::ostringstream e;
+ e << this->Name << " cannot set permissions on \"" << toFile
+ << "\": " << cmSystemTools::GetLastSystemError() << ".";
+ this->Status.SetError(e.str());
+ return false;
+ }
+ }
+ return true;
+}
+
+// Translate an argument to a permissions bit.
+bool cmFileCopier::CheckPermissions(std::string const& arg,
+ mode_t& permissions)
+{
+ if (!cmFSPermissions::stringToModeT(arg, permissions)) {
+ std::ostringstream e;
+ e << this->Name << " given invalid permission \"" << arg << "\".";
+ this->Status.SetError(e.str());
+ return false;
+ }
+ return true;
+}
+
+std::string const& cmFileCopier::ToName(std::string const& fromName)
+{
+ return fromName;
+}
+
+bool cmFileCopier::ReportMissing(const std::string& fromFile)
+{
+ // The input file does not exist and installation is not optional.
+ std::ostringstream e;
+ e << this->Name << " cannot find \"" << fromFile
+ << "\": " << cmSystemTools::GetLastSystemError() << ".";
+ this->Status.SetError(e.str());
+ return false;
+}
+
+void cmFileCopier::NotBeforeMatch(std::string const& arg)
+{
+ std::ostringstream e;
+ e << "option " << arg << " may not appear before PATTERN or REGEX.";
+ this->Status.SetError(e.str());
+ this->Doing = DoingError;
+}
+
+void cmFileCopier::NotAfterMatch(std::string const& arg)
+{
+ std::ostringstream e;
+ e << "option " << arg << " may not appear after PATTERN or REGEX.";
+ this->Status.SetError(e.str());
+ this->Doing = DoingError;
+}
+
+void cmFileCopier::DefaultFilePermissions()
+{
+ // Use read/write permissions.
+ this->FilePermissions = 0;
+ this->FilePermissions |= mode_owner_read;
+ this->FilePermissions |= mode_owner_write;
+ this->FilePermissions |= mode_group_read;
+ this->FilePermissions |= mode_world_read;
+}
+
+void cmFileCopier::DefaultDirectoryPermissions()
+{
+ // Use read/write/executable permissions.
+ this->DirPermissions = 0;
+ this->DirPermissions |= mode_owner_read;
+ this->DirPermissions |= mode_owner_write;
+ this->DirPermissions |= mode_owner_execute;
+ this->DirPermissions |= mode_group_read;
+ this->DirPermissions |= mode_group_execute;
+ this->DirPermissions |= mode_world_read;
+ this->DirPermissions |= mode_world_execute;
+}
+
+bool cmFileCopier::GetDefaultDirectoryPermissions(mode_t** mode)
+{
+ // check if default dir creation permissions were set
+ 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 =
+ cmExpandedList(default_dir_install_permissions);
+ for (const auto& arg : items) {
+ if (!this->CheckPermissions(arg, **mode)) {
+ this->Status.SetError(
+ " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS variable.");
+ return false;
+ }
+ }
+ } else {
+ *mode = nullptr;
+ }
+
+ return true;
+}
+
+bool cmFileCopier::Parse(std::vector<std::string> const& args)
+{
+ this->Doing = DoingFiles;
+ for (unsigned int i = 1; i < args.size(); ++i) {
+ // Check this argument.
+ if (!this->CheckKeyword(args[i]) && !this->CheckValue(args[i])) {
+ std::ostringstream e;
+ e << "called with unknown argument \"" << args[i] << "\".";
+ this->Status.SetError(e.str());
+ return false;
+ }
+
+ // Quit if an argument is invalid.
+ if (this->Doing == DoingError) {
+ return false;
+ }
+ }
+
+ // Require a destination.
+ if (this->Destination.empty()) {
+ std::ostringstream e;
+ e << this->Name << " given no DESTINATION";
+ this->Status.SetError(e.str());
+ return false;
+ }
+
+ // If file permissions were not specified set default permissions.
+ if (!this->UseGivenPermissionsFile && !this->UseSourcePermissions) {
+ this->DefaultFilePermissions();
+ }
+
+ // If directory permissions were not specified set default permissions.
+ if (!this->UseGivenPermissionsDir && !this->UseSourcePermissions) {
+ this->DefaultDirectoryPermissions();
+ }
+
+ return true;
+}
+
+bool cmFileCopier::CheckKeyword(std::string const& arg)
+{
+ if (arg == "DESTINATION") {
+ if (this->CurrentMatchRule) {
+ this->NotAfterMatch(arg);
+ } else {
+ this->Doing = DoingDestination;
+ }
+ } else if (arg == "FILES_FROM_DIR") {
+ if (this->CurrentMatchRule) {
+ this->NotAfterMatch(arg);
+ } else {
+ this->Doing = DoingFilesFromDir;
+ }
+ } else if (arg == "PATTERN") {
+ this->Doing = DoingPattern;
+ } else if (arg == "REGEX") {
+ this->Doing = DoingRegex;
+ } else if (arg == "FOLLOW_SYMLINK_CHAIN") {
+ this->FollowSymlinkChain = true;
+ this->Doing = DoingNone;
+ } else if (arg == "EXCLUDE") {
+ // Add this property to the current match rule.
+ if (this->CurrentMatchRule) {
+ this->CurrentMatchRule->Properties.Exclude = true;
+ this->Doing = DoingNone;
+ } else {
+ this->NotBeforeMatch(arg);
+ }
+ } else if (arg == "PERMISSIONS") {
+ if (this->CurrentMatchRule) {
+ this->Doing = DoingPermissionsMatch;
+ } else {
+ this->NotBeforeMatch(arg);
+ }
+ } else if (arg == "FILE_PERMISSIONS") {
+ if (this->CurrentMatchRule) {
+ this->NotAfterMatch(arg);
+ } else {
+ this->Doing = DoingPermissionsFile;
+ this->UseGivenPermissionsFile = true;
+ }
+ } else if (arg == "DIRECTORY_PERMISSIONS") {
+ if (this->CurrentMatchRule) {
+ this->NotAfterMatch(arg);
+ } else {
+ this->Doing = DoingPermissionsDir;
+ this->UseGivenPermissionsDir = true;
+ }
+ } else if (arg == "USE_SOURCE_PERMISSIONS") {
+ if (this->CurrentMatchRule) {
+ this->NotAfterMatch(arg);
+ } else {
+ this->Doing = DoingNone;
+ this->UseSourcePermissions = true;
+ }
+ } else if (arg == "NO_SOURCE_PERMISSIONS") {
+ if (this->CurrentMatchRule) {
+ this->NotAfterMatch(arg);
+ } else {
+ this->Doing = DoingNone;
+ this->UseSourcePermissions = false;
+ }
+ } else if (arg == "FILES_MATCHING") {
+ if (this->CurrentMatchRule) {
+ this->NotAfterMatch(arg);
+ } else {
+ this->Doing = DoingNone;
+ this->MatchlessFiles = false;
+ }
+ } else {
+ return false;
+ }
+ return true;
+}
+
+bool cmFileCopier::CheckValue(std::string const& arg)
+{
+ switch (this->Doing) {
+ case DoingFiles:
+ this->Files.push_back(arg);
+ break;
+ case DoingDestination:
+ if (arg.empty() || cmSystemTools::FileIsFullPath(arg)) {
+ this->Destination = arg;
+ } else {
+ this->Destination =
+ cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', arg);
+ }
+ this->Doing = DoingNone;
+ break;
+ case DoingFilesFromDir:
+ if (cmSystemTools::FileIsFullPath(arg)) {
+ this->FilesFromDir = arg;
+ } else {
+ this->FilesFromDir =
+ cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', arg);
+ }
+ cmSystemTools::ConvertToUnixSlashes(this->FilesFromDir);
+ this->Doing = DoingNone;
+ break;
+ case DoingPattern: {
+ // Convert the pattern to a regular expression. Require a
+ // leading slash and trailing end-of-string in the matched
+ // string to make sure the pattern matches only whole file
+ // names.
+ std::string regex =
+ cmStrCat('/', cmsys::Glob::PatternToRegex(arg, false), '$');
+ this->MatchRules.emplace_back(regex);
+ this->CurrentMatchRule = &*(this->MatchRules.end() - 1);
+ if (this->CurrentMatchRule->Regex.is_valid()) {
+ this->Doing = DoingNone;
+ } else {
+ std::ostringstream e;
+ e << "could not compile PATTERN \"" << arg << "\".";
+ this->Status.SetError(e.str());
+ this->Doing = DoingError;
+ }
+ } break;
+ case DoingRegex:
+ this->MatchRules.emplace_back(arg);
+ this->CurrentMatchRule = &*(this->MatchRules.end() - 1);
+ if (this->CurrentMatchRule->Regex.is_valid()) {
+ this->Doing = DoingNone;
+ } else {
+ std::ostringstream e;
+ e << "could not compile REGEX \"" << arg << "\".";
+ this->Status.SetError(e.str());
+ this->Doing = DoingError;
+ }
+ break;
+ case DoingPermissionsFile:
+ if (!this->CheckPermissions(arg, this->FilePermissions)) {
+ this->Doing = DoingError;
+ }
+ break;
+ case DoingPermissionsDir:
+ if (!this->CheckPermissions(arg, this->DirPermissions)) {
+ this->Doing = DoingError;
+ }
+ break;
+ case DoingPermissionsMatch:
+ if (!this->CheckPermissions(
+ arg, this->CurrentMatchRule->Properties.Permissions)) {
+ this->Doing = DoingError;
+ }
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+bool cmFileCopier::Run(std::vector<std::string> const& args)
+{
+ if (!this->Parse(args)) {
+ return false;
+ }
+
+ for (std::string const& f : this->Files) {
+ std::string file;
+ if (!f.empty() && !cmSystemTools::FileIsFullPath(f)) {
+ if (!this->FilesFromDir.empty()) {
+ file = this->FilesFromDir;
+ } else {
+ file = this->Makefile->GetCurrentSourceDirectory();
+ }
+ file += "/";
+ file += f;
+ } else if (!this->FilesFromDir.empty()) {
+ this->Status.SetError("option FILES_FROM_DIR requires all files "
+ "to be specified as relative paths.");
+ return false;
+ } else {
+ file = f;
+ }
+
+ // Split the input file into its directory and name components.
+ std::vector<std::string> fromPathComponents;
+ cmSystemTools::SplitPath(file, fromPathComponents);
+ std::string fromName = *(fromPathComponents.end() - 1);
+ std::string fromDir = cmSystemTools::JoinPath(
+ fromPathComponents.begin(), fromPathComponents.end() - 1);
+
+ // Compute the full path to the destination file.
+ std::string toFile = this->Destination;
+ if (!this->FilesFromDir.empty()) {
+ std::string dir = cmSystemTools::GetFilenamePath(f);
+ if (!dir.empty()) {
+ toFile += "/";
+ toFile += dir;
+ }
+ }
+ std::string const& toName = this->ToName(fromName);
+ if (!toName.empty()) {
+ toFile += "/";
+ toFile += toName;
+ }
+
+ // Construct the full path to the source file. The file name may
+ // have been changed above.
+ std::string fromFile = fromDir;
+ if (!fromName.empty()) {
+ fromFile += "/";
+ fromFile += fromName;
+ }
+
+ if (!this->Install(fromFile, toFile)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool cmFileCopier::Install(const std::string& fromFile,
+ const std::string& toFile)
+{
+ if (fromFile.empty()) {
+ this->Status.SetError(
+ "INSTALL encountered an empty string input file name.");
+ return false;
+ }
+
+ // Collect any properties matching this file name.
+ MatchProperties match_properties = this->CollectMatchProperties(fromFile);
+
+ // Skip the file if it is excluded.
+ if (match_properties.Exclude) {
+ return true;
+ }
+
+ if (cmSystemTools::SameFile(fromFile, toFile)) {
+ return true;
+ }
+
+ std::string newFromFile = fromFile;
+ std::string newToFile = toFile;
+
+ if (this->FollowSymlinkChain &&
+ !this->InstallSymlinkChain(newFromFile, newToFile)) {
+ return false;
+ }
+
+ if (cmSystemTools::FileIsSymlink(newFromFile)) {
+ return this->InstallSymlink(newFromFile, newToFile);
+ }
+ if (cmSystemTools::FileIsDirectory(newFromFile)) {
+ return this->InstallDirectory(newFromFile, newToFile, match_properties);
+ }
+ if (cmSystemTools::FileExists(newFromFile)) {
+ return this->InstallFile(newFromFile, newToFile, match_properties);
+ }
+ return this->ReportMissing(newFromFile);
+}
+
+bool cmFileCopier::InstallSymlinkChain(std::string& fromFile,
+ std::string& toFile)
+{
+ std::string newFromFile;
+ std::string toFilePath = cmSystemTools::GetFilenamePath(toFile);
+ while (cmSystemTools::ReadSymlink(fromFile, newFromFile)) {
+ if (!cmSystemTools::FileIsFullPath(newFromFile)) {
+ std::string fromFilePath = cmSystemTools::GetFilenamePath(fromFile);
+ newFromFile = cmStrCat(fromFilePath, "/", newFromFile);
+ }
+
+ std::string symlinkTarget = cmSystemTools::GetFilenameName(newFromFile);
+
+ bool copy = true;
+ if (!this->Always) {
+ std::string oldSymlinkTarget;
+ if (cmSystemTools::ReadSymlink(toFile, oldSymlinkTarget)) {
+ if (symlinkTarget == oldSymlinkTarget) {
+ copy = false;
+ }
+ }
+ }
+
+ this->ReportCopy(toFile, TypeLink, copy);
+
+ if (copy) {
+ cmSystemTools::RemoveFile(toFile);
+ cmSystemTools::MakeDirectory(toFilePath);
+
+ if (!cmSystemTools::CreateSymlink(symlinkTarget, toFile)) {
+ std::ostringstream e;
+ e << this->Name << " cannot create symlink \"" << toFile
+ << "\": " << cmSystemTools::GetLastSystemError() << ".";
+ this->Status.SetError(e.str());
+ return false;
+ }
+ }
+
+ fromFile = newFromFile;
+ toFile = cmStrCat(toFilePath, "/", symlinkTarget);
+ }
+
+ return true;
+}
+
+bool cmFileCopier::InstallSymlink(const std::string& fromFile,
+ const std::string& toFile)
+{
+ // Read the original symlink.
+ std::string symlinkTarget;
+ if (!cmSystemTools::ReadSymlink(fromFile, symlinkTarget)) {
+ std::ostringstream e;
+ e << this->Name << " cannot read symlink \"" << fromFile
+ << "\" to duplicate at \"" << toFile
+ << "\": " << cmSystemTools::GetLastSystemError() << ".";
+ this->Status.SetError(e.str());
+ return false;
+ }
+
+ // Compare the symlink value to that at the destination if not
+ // always installing.
+ bool copy = true;
+ if (!this->Always) {
+ std::string oldSymlinkTarget;
+ if (cmSystemTools::ReadSymlink(toFile, oldSymlinkTarget)) {
+ if (symlinkTarget == oldSymlinkTarget) {
+ copy = false;
+ }
+ }
+ }
+
+ // Inform the user about this file installation.
+ this->ReportCopy(toFile, TypeLink, copy);
+
+ if (copy) {
+ // Remove the destination file so we can always create the symlink.
+ cmSystemTools::RemoveFile(toFile);
+
+ // Create destination directory if it doesn't exist
+ cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(toFile));
+
+ // Create the symlink.
+ if (!cmSystemTools::CreateSymlink(symlinkTarget, toFile)) {
+ std::ostringstream e;
+ e << this->Name << " cannot duplicate symlink \"" << fromFile
+ << "\" at \"" << toFile
+ << "\": " << cmSystemTools::GetLastSystemError() << ".";
+ this->Status.SetError(e.str());
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool cmFileCopier::InstallFile(const std::string& fromFile,
+ const std::string& toFile,
+ MatchProperties match_properties)
+{
+ // Determine whether we will copy the file.
+ bool copy = true;
+ if (!this->Always) {
+ // If both files exist with the same time do not copy.
+ if (!this->FileTimes.DifferS(fromFile, toFile)) {
+ copy = false;
+ }
+ }
+
+ // Inform the user about this file installation.
+ this->ReportCopy(toFile, TypeFile, copy);
+
+ // Copy the file.
+ if (copy && !cmSystemTools::CopyAFile(fromFile, toFile, true)) {
+ std::ostringstream e;
+ e << this->Name << " cannot copy file \"" << fromFile << "\" to \""
+ << toFile << "\": " << cmSystemTools::GetLastSystemError() << ".";
+ this->Status.SetError(e.str());
+ return false;
+ }
+
+ // Set the file modification time of the destination file.
+ if (copy && !this->Always) {
+ // Add write permission so we can set the file time.
+ // Permissions are set unconditionally below anyway.
+ mode_t perm = 0;
+ if (cmSystemTools::GetPermissions(toFile, perm)) {
+ cmSystemTools::SetPermissions(toFile, perm | mode_owner_write);
+ }
+ if (!cmFileTimes::Copy(fromFile, toFile)) {
+ std::ostringstream e;
+ e << this->Name << " cannot set modification time on \"" << toFile
+ << "\": " << cmSystemTools::GetLastSystemError() << ".";
+ this->Status.SetError(e.str());
+ return false;
+ }
+ }
+
+ // Set permissions of the destination file.
+ mode_t permissions =
+ (match_properties.Permissions ? match_properties.Permissions
+ : this->FilePermissions);
+ if (!permissions) {
+ // No permissions were explicitly provided but the user requested
+ // that the source file permissions be used.
+ cmSystemTools::GetPermissions(fromFile, permissions);
+ }
+ return this->SetPermissions(toFile, permissions);
+}
+
+bool cmFileCopier::InstallDirectory(const std::string& source,
+ const std::string& destination,
+ MatchProperties match_properties)
+{
+ // Inform the user about this directory installation.
+ this->ReportCopy(destination, TypeDir,
+ !cmSystemTools::FileIsDirectory(destination));
+
+ // check if default dir creation permissions were set
+ mode_t default_dir_mode_v = 0;
+ mode_t* default_dir_mode = &default_dir_mode_v;
+ if (!this->GetDefaultDirectoryPermissions(&default_dir_mode)) {
+ return false;
+ }
+
+ // Make sure the destination directory exists.
+ if (!cmSystemTools::MakeDirectory(destination, default_dir_mode)) {
+ std::ostringstream e;
+ e << this->Name << " cannot make directory \"" << destination
+ << "\": " << cmSystemTools::GetLastSystemError() << ".";
+ this->Status.SetError(e.str());
+ return false;
+ }
+
+ // Compute the requested permissions for the destination directory.
+ mode_t permissions =
+ (match_properties.Permissions ? match_properties.Permissions
+ : this->DirPermissions);
+ if (!permissions) {
+ // No permissions were explicitly provided but the user requested
+ // that the source directory permissions be used.
+ cmSystemTools::GetPermissions(source, permissions);
+ }
+
+ // Compute the set of permissions required on this directory to
+ // recursively install files and subdirectories safely.
+ mode_t required_permissions =
+ mode_owner_read | mode_owner_write | mode_owner_execute;
+
+ // If the required permissions are specified it is safe to set the
+ // final permissions now. Otherwise we must add the required
+ // permissions temporarily during file installation.
+ mode_t permissions_before = 0;
+ mode_t permissions_after = 0;
+ if ((permissions & required_permissions) == required_permissions) {
+ permissions_before = permissions;
+ } else {
+ permissions_before = permissions | required_permissions;
+ permissions_after = permissions;
+ }
+
+ // Set the required permissions of the destination directory.
+ if (!this->SetPermissions(destination, permissions_before)) {
+ return false;
+ }
+
+ // Load the directory contents to traverse it recursively.
+ cmsys::Directory dir;
+ if (!source.empty()) {
+ dir.Load(source);
+ }
+ unsigned long numFiles = static_cast<unsigned long>(dir.GetNumberOfFiles());
+ for (unsigned long fileNum = 0; fileNum < numFiles; ++fileNum) {
+ if (!(strcmp(dir.GetFile(fileNum), ".") == 0 ||
+ strcmp(dir.GetFile(fileNum), "..") == 0)) {
+ std::string fromPath = cmStrCat(source, '/', dir.GetFile(fileNum));
+ std::string toPath = cmStrCat(destination, '/', dir.GetFile(fileNum));
+ if (!this->Install(fromPath, toPath)) {
+ return false;
+ }
+ }
+ }
+
+ // Set the requested permissions of the destination directory.
+ return this->SetPermissions(destination, permissions_after);
+}
diff --git a/Source/cmFileCopier.h b/Source/cmFileCopier.h
new file mode 100644
index 000000000..612a57fef
--- /dev/null
+++ b/Source/cmFileCopier.h
@@ -0,0 +1,124 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmFileCopier_h
+#define cmFileCopier_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cm_sys_stat.h"
+
+#include "cmFileTimeCache.h"
+
+class cmExecutionStatus;
+class cmMakefile;
+
+// File installation helper class.
+struct cmFileCopier
+{
+ cmFileCopier(cmExecutionStatus& status, const char* name = "COPY");
+ virtual ~cmFileCopier();
+
+ bool Run(std::vector<std::string> const& args);
+
+protected:
+ cmExecutionStatus& Status;
+ cmMakefile* Makefile;
+ const char* Name;
+ bool Always;
+ cmFileTimeCache FileTimes;
+
+ // Whether to install a file not matching any expression.
+ bool MatchlessFiles;
+
+ // Permissions for files and directories installed by this object.
+ mode_t FilePermissions;
+ mode_t DirPermissions;
+
+ // Properties set by pattern and regex match rules.
+ struct MatchProperties
+ {
+ bool Exclude = false;
+ mode_t Permissions = 0;
+ };
+ struct MatchRule
+ {
+ cmsys::RegularExpression Regex;
+ MatchProperties Properties;
+ std::string RegexString;
+ MatchRule(std::string const& regex)
+ : Regex(regex)
+ , RegexString(regex)
+ {
+ }
+ };
+ std::vector<MatchRule> MatchRules;
+
+ // Get the properties from rules matching this input file.
+ MatchProperties CollectMatchProperties(const std::string& file);
+
+ bool SetPermissions(const std::string& toFile, mode_t permissions);
+
+ // Translate an argument to a permissions bit.
+ bool CheckPermissions(std::string const& arg, mode_t& permissions);
+
+ bool InstallSymlinkChain(std::string& fromFile, std::string& toFile);
+ bool InstallSymlink(const std::string& fromFile, const std::string& toFile);
+ bool InstallFile(const std::string& fromFile, const std::string& toFile,
+ MatchProperties match_properties);
+ bool InstallDirectory(const std::string& source,
+ const std::string& destination,
+ MatchProperties match_properties);
+ virtual bool Install(const std::string& fromFile, const std::string& toFile);
+ virtual std::string const& ToName(std::string const& fromName);
+
+ enum Type
+ {
+ TypeFile,
+ TypeDir,
+ TypeLink
+ };
+ virtual void ReportCopy(const std::string&, Type, bool) {}
+ virtual bool ReportMissing(const std::string& fromFile);
+
+ MatchRule* CurrentMatchRule;
+ bool UseGivenPermissionsFile;
+ bool UseGivenPermissionsDir;
+ bool UseSourcePermissions;
+ bool FollowSymlinkChain;
+ std::string Destination;
+ std::string FilesFromDir;
+ std::vector<std::string> Files;
+ int Doing;
+
+ virtual bool Parse(std::vector<std::string> const& args);
+ enum
+ {
+ DoingNone,
+ DoingError,
+ DoingDestination,
+ DoingFilesFromDir,
+ DoingFiles,
+ DoingPattern,
+ DoingRegex,
+ DoingPermissionsFile,
+ DoingPermissionsDir,
+ DoingPermissionsMatch,
+ DoingLast1
+ };
+ virtual bool CheckKeyword(std::string const& arg);
+ virtual bool CheckValue(std::string const& arg);
+
+ void NotBeforeMatch(std::string const& arg);
+ void NotAfterMatch(std::string const& arg);
+ virtual void DefaultFilePermissions();
+ virtual void DefaultDirectoryPermissions();
+
+ bool GetDefaultDirectoryPermissions(mode_t** mode);
+};
+
+#endif
diff --git a/Source/cmFileInstaller.cxx b/Source/cmFileInstaller.cxx
new file mode 100644
index 000000000..c89be9628
--- /dev/null
+++ b/Source/cmFileInstaller.cxx
@@ -0,0 +1,351 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmFileInstaller.h"
+
+#include <sstream>
+
+#include "cm_sys_stat.h"
+
+#include "cmExecutionStatus.h"
+#include "cmFSPermissions.h"
+#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+using namespace cmFSPermissions;
+
+cmFileInstaller::cmFileInstaller(cmExecutionStatus& status)
+ : cmFileCopier(status, "INSTALL")
+ , InstallType(cmInstallType_FILES)
+ , Optional(false)
+ , MessageAlways(false)
+ , MessageLazy(false)
+ , MessageNever(false)
+ , DestDirLength(0)
+{
+ // Installation does not use source permissions by default.
+ this->UseSourcePermissions = false;
+ // Check whether to copy files always or only if they have changed.
+ std::string install_always;
+ if (cmSystemTools::GetEnv("CMAKE_INSTALL_ALWAYS", install_always)) {
+ this->Always = cmIsOn(install_always);
+ }
+ // Get the current manifest.
+ this->Manifest =
+ this->Makefile->GetSafeDefinition("CMAKE_INSTALL_MANIFEST_FILES");
+}
+cmFileInstaller::~cmFileInstaller()
+{
+ // Save the updated install manifest.
+ this->Makefile->AddDefinition("CMAKE_INSTALL_MANIFEST_FILES",
+ this->Manifest);
+}
+
+void cmFileInstaller::ManifestAppend(std::string const& file)
+{
+ if (!this->Manifest.empty()) {
+ this->Manifest += ";";
+ }
+ this->Manifest += file.substr(this->DestDirLength);
+}
+
+std::string const& cmFileInstaller::ToName(std::string const& fromName)
+{
+ return this->Rename.empty() ? fromName : this->Rename;
+}
+
+void cmFileInstaller::ReportCopy(const std::string& toFile, Type type,
+ bool copy)
+{
+ if (!this->MessageNever && (copy || !this->MessageLazy)) {
+ std::string message =
+ cmStrCat((copy ? "Installing: " : "Up-to-date: "), toFile);
+ this->Makefile->DisplayStatus(message, -1);
+ }
+ if (type != TypeDir) {
+ // Add the file to the manifest.
+ this->ManifestAppend(toFile);
+ }
+}
+bool cmFileInstaller::ReportMissing(const std::string& fromFile)
+{
+ return (this->Optional || this->cmFileCopier::ReportMissing(fromFile));
+}
+bool cmFileInstaller::Install(const std::string& fromFile,
+ const std::string& toFile)
+{
+ // Support installing from empty source to make a directory.
+ if (this->InstallType == cmInstallType_DIRECTORY && fromFile.empty()) {
+ return this->InstallDirectory(fromFile, toFile, MatchProperties());
+ }
+ return this->cmFileCopier::Install(fromFile, toFile);
+}
+
+void cmFileInstaller::DefaultFilePermissions()
+{
+ this->cmFileCopier::DefaultFilePermissions();
+ // Add execute permissions based on the target type.
+ switch (this->InstallType) {
+ case cmInstallType_SHARED_LIBRARY:
+ case cmInstallType_MODULE_LIBRARY:
+ if (this->Makefile->IsOn("CMAKE_INSTALL_SO_NO_EXE")) {
+ break;
+ }
+ CM_FALLTHROUGH;
+ case cmInstallType_EXECUTABLE:
+ case cmInstallType_PROGRAMS:
+ this->FilePermissions |= mode_owner_execute;
+ this->FilePermissions |= mode_group_execute;
+ this->FilePermissions |= mode_world_execute;
+ break;
+ default:
+ break;
+ }
+}
+
+bool cmFileInstaller::Parse(std::vector<std::string> const& args)
+{
+ if (!this->cmFileCopier::Parse(args)) {
+ return false;
+ }
+
+ if (!this->Rename.empty()) {
+ if (!this->FilesFromDir.empty()) {
+ this->Status.SetError("INSTALL option RENAME may not be "
+ "combined with FILES_FROM_DIR.");
+ return false;
+ }
+ if (this->InstallType != cmInstallType_FILES &&
+ this->InstallType != cmInstallType_PROGRAMS) {
+ this->Status.SetError("INSTALL option RENAME may be used "
+ "only with FILES or PROGRAMS.");
+ return false;
+ }
+ if (this->Files.size() > 1) {
+ this->Status.SetError("INSTALL option RENAME may be used "
+ "only with one file.");
+ return false;
+ }
+ }
+
+ if (!this->HandleInstallDestination()) {
+ return false;
+ }
+
+ if (((this->MessageAlways ? 1 : 0) + (this->MessageLazy ? 1 : 0) +
+ (this->MessageNever ? 1 : 0)) > 1) {
+ this->Status.SetError("INSTALL options MESSAGE_ALWAYS, "
+ "MESSAGE_LAZY, and MESSAGE_NEVER "
+ "are mutually exclusive.");
+ return false;
+ }
+
+ return true;
+}
+
+bool cmFileInstaller::CheckKeyword(std::string const& arg)
+{
+ if (arg == "TYPE") {
+ if (this->CurrentMatchRule) {
+ this->NotAfterMatch(arg);
+ } else {
+ this->Doing = DoingType;
+ }
+ } else if (arg == "FILES") {
+ if (this->CurrentMatchRule) {
+ this->NotAfterMatch(arg);
+ } else {
+ this->Doing = DoingFiles;
+ }
+ } else if (arg == "RENAME") {
+ if (this->CurrentMatchRule) {
+ this->NotAfterMatch(arg);
+ } else {
+ this->Doing = DoingRename;
+ }
+ } else if (arg == "OPTIONAL") {
+ if (this->CurrentMatchRule) {
+ this->NotAfterMatch(arg);
+ } else {
+ this->Doing = DoingNone;
+ this->Optional = true;
+ }
+ } else if (arg == "MESSAGE_ALWAYS") {
+ if (this->CurrentMatchRule) {
+ this->NotAfterMatch(arg);
+ } else {
+ this->Doing = DoingNone;
+ this->MessageAlways = true;
+ }
+ } else if (arg == "MESSAGE_LAZY") {
+ if (this->CurrentMatchRule) {
+ this->NotAfterMatch(arg);
+ } else {
+ this->Doing = DoingNone;
+ this->MessageLazy = true;
+ }
+ } else if (arg == "MESSAGE_NEVER") {
+ if (this->CurrentMatchRule) {
+ this->NotAfterMatch(arg);
+ } else {
+ this->Doing = DoingNone;
+ this->MessageNever = true;
+ }
+ } else if (arg == "PERMISSIONS") {
+ if (this->CurrentMatchRule) {
+ this->Doing = DoingPermissionsMatch;
+ } else {
+ // file(INSTALL) aliases PERMISSIONS to FILE_PERMISSIONS
+ this->Doing = DoingPermissionsFile;
+ this->UseGivenPermissionsFile = true;
+ }
+ } else if (arg == "DIR_PERMISSIONS") {
+ if (this->CurrentMatchRule) {
+ this->NotAfterMatch(arg);
+ } else {
+ // file(INSTALL) aliases DIR_PERMISSIONS to DIRECTORY_PERMISSIONS
+ this->Doing = DoingPermissionsDir;
+ this->UseGivenPermissionsDir = true;
+ }
+ } else if (arg == "COMPONENTS" || arg == "CONFIGURATIONS" ||
+ arg == "PROPERTIES") {
+ std::ostringstream e;
+ e << "INSTALL called with old-style " << arg << " argument. "
+ << "This script was generated with an older version of CMake. "
+ << "Re-run this cmake version on your build tree.";
+ this->Status.SetError(e.str());
+ this->Doing = DoingError;
+ } else {
+ return this->cmFileCopier::CheckKeyword(arg);
+ }
+ return true;
+}
+
+bool cmFileInstaller::CheckValue(std::string const& arg)
+{
+ switch (this->Doing) {
+ case DoingType:
+ if (!this->GetTargetTypeFromString(arg)) {
+ this->Doing = DoingError;
+ }
+ break;
+ case DoingRename:
+ this->Rename = arg;
+ break;
+ default:
+ return this->cmFileCopier::CheckValue(arg);
+ }
+ return true;
+}
+
+bool cmFileInstaller::GetTargetTypeFromString(const std::string& stype)
+{
+ if (stype == "EXECUTABLE") {
+ this->InstallType = cmInstallType_EXECUTABLE;
+ } else if (stype == "FILE") {
+ this->InstallType = cmInstallType_FILES;
+ } else if (stype == "PROGRAM") {
+ this->InstallType = cmInstallType_PROGRAMS;
+ } else if (stype == "STATIC_LIBRARY") {
+ this->InstallType = cmInstallType_STATIC_LIBRARY;
+ } else if (stype == "SHARED_LIBRARY") {
+ this->InstallType = cmInstallType_SHARED_LIBRARY;
+ } else if (stype == "MODULE") {
+ this->InstallType = cmInstallType_MODULE_LIBRARY;
+ } else if (stype == "DIRECTORY") {
+ this->InstallType = cmInstallType_DIRECTORY;
+ } else {
+ std::ostringstream e;
+ e << "Option TYPE given unknown value \"" << stype << "\".";
+ this->Status.SetError(e.str());
+ return false;
+ }
+ return true;
+}
+
+bool cmFileInstaller::HandleInstallDestination()
+{
+ std::string& destination = this->Destination;
+
+ // allow for / to be a valid destination
+ if (destination.size() < 2 && destination != "/") {
+ this->Status.SetError("called with inappropriate arguments. "
+ "No DESTINATION provided or .");
+ return false;
+ }
+
+ std::string sdestdir;
+ if (cmSystemTools::GetEnv("DESTDIR", sdestdir) && !sdestdir.empty()) {
+ cmSystemTools::ConvertToUnixSlashes(sdestdir);
+ char ch1 = destination[0];
+ char ch2 = destination[1];
+ char ch3 = 0;
+ if (destination.size() > 2) {
+ ch3 = destination[2];
+ }
+ int skip = 0;
+ if (ch1 != '/') {
+ int relative = 0;
+ if (((ch1 >= 'a' && ch1 <= 'z') || (ch1 >= 'A' && ch1 <= 'Z')) &&
+ ch2 == ':') {
+ // Assume windows
+ // let's do some destdir magic:
+ skip = 2;
+ if (ch3 != '/') {
+ relative = 1;
+ }
+ } else {
+ relative = 1;
+ }
+ if (relative) {
+ // This is relative path on unix or windows. Since we are doing
+ // destdir, this case does not make sense.
+ this->Status.SetError(
+ "called with relative DESTINATION. This "
+ "does not make sense when using DESTDIR. Specify "
+ "absolute path or remove DESTDIR environment variable.");
+ return false;
+ }
+ } else {
+ if (ch2 == '/') {
+ // looks like a network path.
+ std::string message =
+ cmStrCat("called with network path DESTINATION. This "
+ "does not make sense when using DESTDIR. Specify local "
+ "absolute path or remove DESTDIR environment variable."
+ "\nDESTINATION=\n",
+ destination);
+ this->Status.SetError(message);
+ return false;
+ }
+ }
+ destination = sdestdir + destination.substr(skip);
+ 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 = &default_dir_mode_v;
+ if (!this->GetDefaultDirectoryPermissions(&default_dir_mode)) {
+ return false;
+ }
+
+ if (this->InstallType != cmInstallType_DIRECTORY) {
+ if (!cmSystemTools::FileExists(destination)) {
+ if (!cmSystemTools::MakeDirectory(destination, default_dir_mode)) {
+ std::string errstring = "cannot create directory: " + destination +
+ ". Maybe need administrative privileges.";
+ this->Status.SetError(errstring);
+ return false;
+ }
+ }
+ if (!cmSystemTools::FileIsDirectory(destination)) {
+ std::string errstring =
+ "INSTALL destination: " + destination + " is not a directory.";
+ this->Status.SetError(errstring);
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/Source/cmFileInstaller.h b/Source/cmFileInstaller.h
new file mode 100644
index 000000000..537cd53cb
--- /dev/null
+++ b/Source/cmFileInstaller.h
@@ -0,0 +1,54 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmFileInstaller_h
+#define cmFileInstaller_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+#include "cmFileCopier.h"
+#include "cmInstallType.h"
+
+class cmExecutionStatus;
+
+struct cmFileInstaller : public cmFileCopier
+{
+ cmFileInstaller(cmExecutionStatus& status);
+ ~cmFileInstaller() override;
+
+protected:
+ cmInstallType InstallType;
+ bool Optional;
+ bool MessageAlways;
+ bool MessageLazy;
+ bool MessageNever;
+ int DestDirLength;
+ std::string Rename;
+
+ std::string Manifest;
+ void ManifestAppend(std::string const& file);
+
+ std::string const& ToName(std::string const& fromName) override;
+
+ void ReportCopy(const std::string& toFile, Type type, bool copy) override;
+ bool ReportMissing(const std::string& fromFile) override;
+ bool Install(const std::string& fromFile,
+ const std::string& toFile) override;
+
+ bool Parse(std::vector<std::string> const& args) override;
+ enum
+ {
+ DoingType = DoingLast1,
+ DoingRename,
+ DoingLast2
+ };
+ bool CheckKeyword(std::string const& arg) override;
+ bool CheckValue(std::string const& arg) override;
+ void DefaultFilePermissions() override;
+ bool GetTargetTypeFromString(const std::string& stype);
+ bool HandleInstallDestination();
+};
+
+#endif
diff --git a/Source/cmFileLock.cxx b/Source/cmFileLock.cxx
index 786d6c63f..e90f57140 100644
--- a/Source/cmFileLock.cxx
+++ b/Source/cmFileLock.cxx
@@ -2,8 +2,9 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFileLock.h"
+#include <cassert>
+
#include "cmFileLockResult.h"
-#include <assert.h>
// Common implementation
@@ -42,7 +43,7 @@ cmFileLockResult cmFileLock::Lock(const std::string& filename,
}
if (!result.IsOk()) {
- this->Filename = "";
+ this->Filename.clear();
}
return result;
@@ -54,7 +55,7 @@ bool cmFileLock::IsLocked(const std::string& filename) const
}
#if defined(_WIN32)
-#include "cmFileLockWin32.cxx"
+# include "cmFileLockWin32.cxx"
#else
-#include "cmFileLockUnix.cxx"
+# include "cmFileLockUnix.cxx"
#endif
diff --git a/Source/cmFileLock.h b/Source/cmFileLock.h
index ccef50816..2130d65db 100644
--- a/Source/cmFileLock.h
+++ b/Source/cmFileLock.h
@@ -3,46 +3,47 @@
#ifndef cmFileLock_h
#define cmFileLock_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#if defined(_WIN32)
-#include <windows.h> // HANDLE
+# include <windows.h> // HANDLE
#endif
class cmFileLockResult;
/**
- * @brief Cross-platform file locking.
- * @details Under the hood this class use 'fcntl' for Unix-like platforms and
- * 'LockFileEx'/'UnlockFileEx' for Win32 platform. Locks are exclusive and
- * advisory.
- */
+ * @brief Cross-platform file locking.
+ * @details Under the hood this class use 'fcntl' for Unix-like platforms and
+ * 'LockFileEx'/'UnlockFileEx' for Win32 platform. Locks are exclusive and
+ * advisory.
+ */
class cmFileLock
{
- CM_DISABLE_COPY(cmFileLock)
-
public:
cmFileLock();
~cmFileLock();
+ cmFileLock(cmFileLock const&) = delete;
+ cmFileLock& operator=(cmFileLock const&) = delete;
+
/**
- * @brief Lock the file.
- * @param timeoutSec Lock timeout. If -1 try until success or fatal error.
- */
+ * @brief Lock the file.
+ * @param timeoutSec Lock timeout. If -1 try until success or fatal error.
+ */
cmFileLockResult Lock(const std::string& filename, unsigned long timeoutSec);
/**
- * @brief Unlock the file.
- */
+ * @brief Unlock the file.
+ */
cmFileLockResult Release();
/**
- * @brief Check file is locked by this class.
- * @details This function helps to find double locks (deadlocks) and to do
- * explicit unlocks.
- */
+ * @brief Check file is locked by this class.
+ * @details This function helps to find double locks (deadlocks) and to do
+ * explicit unlocks.
+ */
bool IsLocked(const std::string& filename) const;
private:
@@ -51,14 +52,13 @@ private:
cmFileLockResult LockWithTimeout(unsigned long timeoutSec);
#if defined(_WIN32)
- typedef HANDLE FileId;
+ HANDLE File = INVALID_HANDLE_VALUE;
BOOL LockFile(DWORD flags);
#else
- typedef int FileId;
+ int File = -1;
int LockFile(int cmd, int type);
#endif
- FileId File;
std::string Filename;
};
diff --git a/Source/cmFileLockPool.cxx b/Source/cmFileLockPool.cxx
index 7b1564c34..8db2db210 100644
--- a/Source/cmFileLockPool.cxx
+++ b/Source/cmFileLockPool.cxx
@@ -2,15 +2,13 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFileLockPool.h"
-#include <assert.h>
+#include <cassert>
#include "cmAlgorithms.h"
#include "cmFileLock.h"
#include "cmFileLockResult.h"
-cmFileLockPool::cmFileLockPool()
-{
-}
+cmFileLockPool::cmFileLockPool() = default;
cmFileLockPool::~cmFileLockPool()
{
@@ -75,16 +73,15 @@ cmFileLockResult cmFileLockPool::LockProcessScope(const std::string& filename,
cmFileLockResult cmFileLockPool::Release(const std::string& filename)
{
- for (It i = this->FunctionScopes.begin(); i != this->FunctionScopes.end();
- ++i) {
- const cmFileLockResult result = (*i)->Release(filename);
+ for (auto& funcScope : this->FunctionScopes) {
+ const cmFileLockResult result = funcScope->Release(filename);
if (!result.IsOk()) {
return result;
}
}
- for (It i = this->FileScopes.begin(); i != this->FileScopes.end(); ++i) {
- const cmFileLockResult result = (*i)->Release(filename);
+ for (auto& fileScope : this->FileScopes) {
+ const cmFileLockResult result = fileScope->Release(filename);
if (!result.IsOk()) {
return result;
}
@@ -95,16 +92,15 @@ cmFileLockResult cmFileLockPool::Release(const std::string& filename)
bool cmFileLockPool::IsAlreadyLocked(const std::string& filename) const
{
- for (CIt i = this->FunctionScopes.begin(); i != this->FunctionScopes.end();
- ++i) {
- const bool result = (*i)->IsAlreadyLocked(filename);
+ for (auto const& funcScope : this->FunctionScopes) {
+ const bool result = funcScope->IsAlreadyLocked(filename);
if (result) {
return true;
}
}
- for (CIt i = this->FileScopes.begin(); i != this->FileScopes.end(); ++i) {
- const bool result = (*i)->IsAlreadyLocked(filename);
+ for (auto const& fileScope : this->FileScopes) {
+ const bool result = fileScope->IsAlreadyLocked(filename);
if (result) {
return true;
}
@@ -113,9 +109,7 @@ bool cmFileLockPool::IsAlreadyLocked(const std::string& filename) const
return this->ProcessScope.IsAlreadyLocked(filename);
}
-cmFileLockPool::ScopePool::ScopePool()
-{
-}
+cmFileLockPool::ScopePool::ScopePool() = default;
cmFileLockPool::ScopePool::~ScopePool()
{
@@ -138,9 +132,9 @@ cmFileLockResult cmFileLockPool::ScopePool::Lock(const std::string& filename,
cmFileLockResult cmFileLockPool::ScopePool::Release(
const std::string& filename)
{
- for (It i = this->Locks.begin(); i != this->Locks.end(); ++i) {
- if ((*i)->IsLocked(filename)) {
- return (*i)->Release();
+ for (auto& lock : this->Locks) {
+ if (lock->IsLocked(filename)) {
+ return lock->Release();
}
}
return cmFileLockResult::MakeOk();
@@ -149,8 +143,8 @@ cmFileLockResult cmFileLockPool::ScopePool::Release(
bool cmFileLockPool::ScopePool::IsAlreadyLocked(
const std::string& filename) const
{
- for (CIt i = this->Locks.begin(); i != this->Locks.end(); ++i) {
- if ((*i)->IsLocked(filename)) {
+ for (auto const& lock : this->Locks) {
+ if (lock->IsLocked(filename)) {
return true;
}
}
diff --git a/Source/cmFileLockPool.h b/Source/cmFileLockPool.h
index c96a8c2f8..dae68dd01 100644
--- a/Source/cmFileLockPool.h
+++ b/Source/cmFileLockPool.h
@@ -3,7 +3,7 @@
#ifndef cmFileLockPool_h
#define cmFileLockPool_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
@@ -13,33 +13,34 @@ class cmFileLockResult;
class cmFileLockPool
{
- CM_DISABLE_COPY(cmFileLockPool)
-
public:
cmFileLockPool();
~cmFileLockPool();
+ cmFileLockPool(cmFileLockPool const&) = delete;
+ cmFileLockPool& operator=(cmFileLockPool const&) = delete;
+
//@{
/**
- * @brief Function scope control.
- */
+ * @brief Function scope control.
+ */
void PushFunctionScope();
void PopFunctionScope();
//@}
//@{
/**
- * @brief File scope control.
- */
+ * @brief File scope control.
+ */
void PushFileScope();
void PopFileScope();
//@}
//@{
/**
- * @brief Lock the file in given scope.
- * @param timeoutSec Lock timeout. If -1 try until success or fatal error.
- */
+ * @brief Lock the file in given scope.
+ * @param timeoutSec Lock timeout. If -1 try until success or fatal error.
+ */
cmFileLockResult LockFunctionScope(const std::string& filename,
unsigned long timeoutSec);
cmFileLockResult LockFileScope(const std::string& filename,
@@ -49,8 +50,8 @@ public:
//@}
/**
- * @brief Unlock the file explicitly.
- */
+ * @brief Unlock the file explicitly.
+ */
cmFileLockResult Release(const std::string& filename);
private:
@@ -58,29 +59,30 @@ private:
class ScopePool
{
- CM_DISABLE_COPY(ScopePool)
-
public:
ScopePool();
~ScopePool();
+ ScopePool(ScopePool const&) = delete;
+ ScopePool& operator=(ScopePool const&) = delete;
+
cmFileLockResult Lock(const std::string& filename,
unsigned long timeoutSec);
cmFileLockResult Release(const std::string& filename);
bool IsAlreadyLocked(const std::string& filename) const;
private:
- typedef std::vector<cmFileLock*> List;
- typedef List::iterator It;
- typedef List::const_iterator CIt;
+ using List = std::vector<cmFileLock*>;
+ using It = List::iterator;
+ using CIt = List::const_iterator;
List Locks;
};
- typedef std::vector<ScopePool*> List;
+ using List = std::vector<ScopePool*>;
- typedef List::iterator It;
- typedef List::const_iterator CIt;
+ using It = List::iterator;
+ using CIt = List::const_iterator;
List FunctionScopes;
List FileScopes;
diff --git a/Source/cmFileLockResult.cxx b/Source/cmFileLockResult.cxx
index a040705e8..9d5a6c67a 100644
--- a/Source/cmFileLockResult.cxx
+++ b/Source/cmFileLockResult.cxx
@@ -2,12 +2,13 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFileLockResult.h"
-#include <errno.h>
-#include <string.h>
+#include <cerrno>
+#include <cstring>
+#define WINMSG_BUF_LEN (1024)
cmFileLockResult cmFileLockResult::MakeOk()
{
- return cmFileLockResult(OK, 0);
+ return { OK, 0 };
}
cmFileLockResult cmFileLockResult::MakeSystem()
@@ -17,27 +18,27 @@ cmFileLockResult cmFileLockResult::MakeSystem()
#else
const Error lastError = errno;
#endif
- return cmFileLockResult(SYSTEM, lastError);
+ return { SYSTEM, lastError };
}
cmFileLockResult cmFileLockResult::MakeTimeout()
{
- return cmFileLockResult(TIMEOUT, 0);
+ return { TIMEOUT, 0 };
}
cmFileLockResult cmFileLockResult::MakeAlreadyLocked()
{
- return cmFileLockResult(ALREADY_LOCKED, 0);
+ return { ALREADY_LOCKED, 0 };
}
cmFileLockResult cmFileLockResult::MakeInternal()
{
- return cmFileLockResult(INTERNAL, 0);
+ return { INTERNAL, 0 };
}
cmFileLockResult cmFileLockResult::MakeNoFunction()
{
- return cmFileLockResult(NO_FUNCTION, 0);
+ return { NO_FUNCTION, 0 };
}
bool cmFileLockResult::IsOk() const
@@ -53,18 +54,12 @@ std::string cmFileLockResult::GetOutputMessage() const
case SYSTEM:
#if defined(_WIN32)
{
- char* errorText = NULL;
-
- // http://stackoverflow.com/a/455533/2288008
- DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS;
- ::FormatMessageA(flags, NULL, this->ErrorValue,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPSTR)&errorText, 0, NULL);
-
- if (errorText != NULL) {
- const std::string message = errorText;
- ::LocalFree(errorText);
+ char winmsg[WINMSG_BUF_LEN];
+ DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
+ if (FormatMessageA(flags, NULL, this->ErrorValue,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)winmsg, WINMSG_BUF_LEN, NULL)) {
+ const std::string message = winmsg;
return message;
} else {
return "Internal error (FormatMessageA failed)";
diff --git a/Source/cmFileLockResult.h b/Source/cmFileLockResult.h
index 4cedc0ae6..81c19064d 100644
--- a/Source/cmFileLockResult.h
+++ b/Source/cmFileLockResult.h
@@ -8,50 +8,50 @@
#include <string>
#if defined(_WIN32)
-#include <windows.h> // DWORD
+# include <windows.h> // DWORD
#endif
/**
- * @brief Result of the locking/unlocking file.
- * @note See @c cmFileLock
- */
+ * @brief Result of the locking/unlocking file.
+ * @note See @c cmFileLock
+ */
class cmFileLockResult
{
public:
#if defined(_WIN32)
- typedef DWORD Error;
+ using Error = DWORD;
#else
- typedef int Error;
+ using Error = int;
#endif
/**
- * @brief Successful lock/unlock.
- */
+ * @brief Successful lock/unlock.
+ */
static cmFileLockResult MakeOk();
/**
- * @brief Lock/Unlock failed. Read error/GetLastError.
- */
+ * @brief Lock/Unlock failed. Read error/GetLastError.
+ */
static cmFileLockResult MakeSystem();
/**
- * @brief Lock/Unlock failed. Timeout reached.
- */
+ * @brief Lock/Unlock failed. Timeout reached.
+ */
static cmFileLockResult MakeTimeout();
/**
- * @brief File already locked.
- */
+ * @brief File already locked.
+ */
static cmFileLockResult MakeAlreadyLocked();
/**
- * @brief Internal error.
- */
+ * @brief Internal error.
+ */
static cmFileLockResult MakeInternal();
/**
- * @brief Try to lock with function guard outside of the function
- */
+ * @brief Try to lock with function guard outside of the function
+ */
static cmFileLockResult MakeNoFunction();
bool IsOk() const;
diff --git a/Source/cmFileLockUnix.cxx b/Source/cmFileLockUnix.cxx
index 7353b01fc..1456ea8c1 100644
--- a/Source/cmFileLockUnix.cxx
+++ b/Source/cmFileLockUnix.cxx
@@ -1,17 +1,15 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmFileLock.h"
+#include <cerrno> // errno
+#include <cstdio> // SEEK_SET
-#include "cmSystemTools.h"
-#include <errno.h> // errno
#include <fcntl.h>
-#include <stdio.h> // SEEK_SET
#include <unistd.h>
-cmFileLock::cmFileLock()
- : File(-1)
-{
-}
+#include "cmFileLock.h"
+#include "cmSystemTools.h"
+
+cmFileLock::cmFileLock() = default;
cmFileLockResult cmFileLock::Release()
{
diff --git a/Source/cmFileLockWin32.cxx b/Source/cmFileLockWin32.cxx
index 51ac24993..b8e435aa5 100644
--- a/Source/cmFileLockWin32.cxx
+++ b/Source/cmFileLockWin32.cxx
@@ -1,12 +1,11 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmFileLock.h"
+#include <windows.h> // CreateFileW
+#include "cmFileLock.h"
#include "cmSystemTools.h"
-#include <windows.h> // CreateFileW
cmFileLock::cmFileLock()
- : File(INVALID_HANDLE_VALUE)
{
}
diff --git a/Source/cmFileMonitor.cxx b/Source/cmFileMonitor.cxx
index 80275357c..ac8a37eee 100644
--- a/Source/cmFileMonitor.cxx
+++ b/Source/cmFileMonitor.cxx
@@ -2,14 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFileMonitor.h"
-#include "cmAlgorithms.h"
-#include "cmsys/SystemTools.hxx"
-
#include <cassert>
-#include <stddef.h>
+#include <cstddef>
#include <unordered_map>
#include <utility>
+#include "cmsys/SystemTools.hxx"
+
+#include "cmAlgorithms.h"
+
namespace {
void on_directory_change(uv_fs_event_t* handle, const char* filename,
int events, int status);
@@ -19,7 +20,6 @@ void on_fs_close(uv_handle_t* handle);
class cmIBaseWatcher
{
public:
- cmIBaseWatcher() = default;
virtual ~cmIBaseWatcher() = default;
virtual void Trigger(const std::string& pathSegment, int events,
@@ -49,8 +49,8 @@ public:
int status) const final
{
if (pathSegment.empty()) {
- for (const auto& i : this->Children) {
- i.second->Trigger(std::string(), events, status);
+ for (auto const& child : this->Children) {
+ child.second->Trigger(std::string(), events, status);
}
} else {
const auto i = this->Children.find(pathSegment);
@@ -62,24 +62,24 @@ public:
void StartWatching() override
{
- for (const auto& i : this->Children) {
- i.second->StartWatching();
+ for (auto const& child : this->Children) {
+ child.second->StartWatching();
}
}
void StopWatching() override
{
- for (const auto& i : this->Children) {
- i.second->StopWatching();
+ for (auto const& child : this->Children) {
+ child.second->StopWatching();
}
}
std::vector<std::string> WatchedFiles() const final
{
std::vector<std::string> result;
- for (const auto& i : this->Children) {
- for (const auto& j : i.second->WatchedFiles()) {
- result.push_back(j);
+ for (auto const& child : this->Children) {
+ for (std::string const& f : child.second->WatchedFiles()) {
+ result.push_back(f);
}
}
return result;
@@ -88,9 +88,9 @@ public:
std::vector<std::string> WatchedDirectories() const override
{
std::vector<std::string> result;
- for (const auto& i : this->Children) {
- for (const auto& j : i.second->WatchedDirectories()) {
- result.push_back(j);
+ for (auto const& child : this->Children) {
+ for (std::string const& dir : child.second->WatchedDirectories()) {
+ result.push_back(dir);
}
}
return result;
@@ -150,11 +150,6 @@ public:
p->AddChildWatcher(ps, this);
}
- ~cmRealDirectoryWatcher() override
- {
- // Handle is freed via uv_handle_close callback!
- }
-
void StartWatching() final
{
if (!this->Handle) {
@@ -171,7 +166,9 @@ public:
{
if (this->Handle) {
uv_fs_event_stop(this->Handle);
- uv_close(reinterpret_cast<uv_handle_t*>(this->Handle), &on_fs_close);
+ if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(this->Handle))) {
+ uv_close(reinterpret_cast<uv_handle_t*>(this->Handle), &on_fs_close);
+ }
this->Handle = nullptr;
}
cmVirtualDirectoryWatcher::StopWatching();
@@ -182,8 +179,9 @@ public:
std::vector<std::string> WatchedDirectories() const override
{
std::vector<std::string> result = { Path() };
- for (const auto& j : cmVirtualDirectoryWatcher::WatchedDirectories()) {
- result.push_back(j);
+ for (std::string const& dir :
+ cmVirtualDirectoryWatcher::WatchedDirectories()) {
+ result.push_back(dir);
}
return result;
}
@@ -265,7 +263,7 @@ public:
static_cast<void>(ps);
const std::string path = this->Path();
- for (const auto& cb : this->CbList) {
+ for (cmFileMonitor::Callback const& cb : this->CbList) {
cb(path, events, status);
}
}
@@ -309,9 +307,10 @@ cmFileMonitor::~cmFileMonitor()
void cmFileMonitor::MonitorPaths(const std::vector<std::string>& paths,
Callback const& cb)
{
- for (const auto& p : paths) {
+ for (std::string const& p : paths) {
std::vector<std::string> pathSegments;
cmsys::SystemTools::SplitPath(p, pathSegments, true);
+ const bool pathIsFile = !cmsys::SystemTools::FileIsDirectory(p);
const size_t segmentCount = pathSegments.size();
if (segmentCount < 2) { // Expect at least rootdir and filename
@@ -321,7 +320,7 @@ void cmFileMonitor::MonitorPaths(const std::vector<std::string>& paths,
for (size_t i = 0; i < segmentCount; ++i) {
assert(currentWatcher);
- const bool fileSegment = (i == segmentCount - 1);
+ const bool fileSegment = (i == segmentCount - 1 && pathIsFile);
const bool rootSegment = (i == 0);
assert(
!(fileSegment &&
diff --git a/Source/cmFileMonitor.h b/Source/cmFileMonitor.h
index d7ec92a17..7ffc9294e 100644
--- a/Source/cmFileMonitor.h
+++ b/Source/cmFileMonitor.h
@@ -2,7 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <functional>
#include <string>
@@ -14,12 +14,14 @@ class cmRootWatcher;
class cmFileMonitor
{
- CM_DISABLE_COPY(cmFileMonitor)
public:
cmFileMonitor(uv_loop_t* l);
~cmFileMonitor();
+ cmFileMonitor(cmFileMonitor const&) = delete;
+ cmFileMonitor& operator=(cmFileMonitor const&) = delete;
+
using Callback = std::function<void(const std::string&, int, int)>;
void MonitorPaths(const std::vector<std::string>& paths, Callback const& cb);
void StopMonitoring();
diff --git a/Source/cmFilePathChecksum.cxx b/Source/cmFilePathChecksum.cxx
index 62f52e590..bb3f610d1 100644
--- a/Source/cmFilePathChecksum.cxx
+++ b/Source/cmFilePathChecksum.cxx
@@ -2,21 +2,19 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFilePathChecksum.h"
+#include <vector>
+
#include "cmBase32.h"
#include "cmCryptoHash.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
-#include <vector>
-
-cmFilePathChecksum::cmFilePathChecksum()
-{
-}
+cmFilePathChecksum::cmFilePathChecksum() = default;
-cmFilePathChecksum::cmFilePathChecksum(const std::string& currentSrcDir,
- const std::string& currentBinDir,
- const std::string& projectSrcDir,
- const std::string& projectBinDir)
+cmFilePathChecksum::cmFilePathChecksum(std::string const& currentSrcDir,
+ std::string const& currentBinDir,
+ std::string const& projectSrcDir,
+ std::string const& projectBinDir)
{
setupParentDirs(currentSrcDir, currentBinDir, projectSrcDir, projectBinDir);
}
@@ -29,36 +27,35 @@ cmFilePathChecksum::cmFilePathChecksum(cmMakefile* makefile)
makefile->GetHomeOutputDirectory());
}
-void cmFilePathChecksum::setupParentDirs(const std::string& currentSrcDir,
- const std::string& currentBinDir,
- const std::string& projectSrcDir,
- const std::string& projectBinDir)
+void cmFilePathChecksum::setupParentDirs(std::string const& currentSrcDir,
+ std::string const& currentBinDir,
+ std::string const& projectSrcDir,
+ std::string const& projectBinDir)
{
- parentDirs[0].first = cmsys::SystemTools::GetRealPath(currentSrcDir);
- parentDirs[1].first = cmsys::SystemTools::GetRealPath(currentBinDir);
- parentDirs[2].first = cmsys::SystemTools::GetRealPath(projectSrcDir);
- 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);
- parentDirs[0].second = "CurrentSource";
- parentDirs[1].second = "CurrentBinary";
- parentDirs[2].second = "ProjectSource";
- parentDirs[3].second = "ProjectBinary";
+ this->parentDirs[0].second = "CurrentSource";
+ this->parentDirs[1].second = "CurrentBinary";
+ this->parentDirs[2].second = "ProjectSource";
+ this->parentDirs[3].second = "ProjectBinary";
}
-std::string cmFilePathChecksum::get(const std::string& filePath) const
+std::string cmFilePathChecksum::get(std::string const& filePath) const
{
std::string relPath;
std::string relSeed;
{
- const std::string fileReal = cmsys::SystemTools::GetRealPath(filePath);
+ std::string const fileReal = cmSystemTools::GetRealPath(filePath);
std::string parentDir;
// Find closest project parent directory
- for (size_t ii = 0; ii != numParentDirs; ++ii) {
- const std::string& pDir = parentDirs[ii].first;
- if (!pDir.empty() &&
- cmsys::SystemTools::IsSubDirectory(fileReal, pDir)) {
- relSeed = parentDirs[ii].second;
- parentDir = pDir;
+ for (auto const& pDir : this->parentDirs) {
+ if (!pDir.first.empty() &&
+ cmsys::SystemTools::IsSubDirectory(fileReal, pDir.first)) {
+ parentDir = pDir.first;
+ relSeed = pDir.second;
break;
}
}
@@ -77,11 +74,11 @@ std::string cmFilePathChecksum::get(const std::string& filePath) const
cmCryptoHash(cmCryptoHash::AlgoSHA256).ByteHashString(relSeed + relPath);
// Convert binary checksum to string
- return cmBase32Encoder().encodeString(&hashBytes[0], hashBytes.size(),
+ return cmBase32Encoder().encodeString(hashBytes.data(), hashBytes.size(),
false);
}
-std::string cmFilePathChecksum::getPart(const std::string& filePath,
+std::string cmFilePathChecksum::getPart(std::string const& filePath,
size_t length) const
{
return get(filePath).substr(0, length);
diff --git a/Source/cmFilePathChecksum.h b/Source/cmFilePathChecksum.h
index 9d570eb4d..b7d5cd24c 100644
--- a/Source/cmFilePathChecksum.h
+++ b/Source/cmFilePathChecksum.h
@@ -5,7 +5,8 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include <stddef.h>
+#include <array>
+#include <cstddef>
#include <string>
#include <utility>
@@ -28,38 +29,36 @@ public:
/// @brief Parent directories are empty
cmFilePathChecksum();
- /// @brief Initilizes the parent directories manually
- cmFilePathChecksum(const std::string& currentSrcDir,
- const std::string& currentBinDir,
- const std::string& projectSrcDir,
- const std::string& projectBinDir);
+ /// @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
///
- void setupParentDirs(const std::string& currentSrcDir,
- const std::string& currentBinDir,
- const std::string& projectSrcDir,
- const std::string& projectBinDir);
+ void setupParentDirs(std::string const& currentSrcDir,
+ std::string const& currentBinDir,
+ std::string const& projectSrcDir,
+ std::string const& projectBinDir);
/* @brief Calculates the path checksum for the parent directory of a file
*
*/
- std::string get(const std::string& filePath) const;
+ std::string get(std::string const& filePath) const;
/* @brief Same as get() but returns only the first length characters
*
*/
- std::string getPart(const std::string& filePath,
+ std::string getPart(std::string const& filePath,
size_t length = partLengthDefault) const;
private:
- /// Size of the parent directory list
- static const size_t numParentDirs = 4;
/// List of (directory name, seed name) pairs
- std::pair<std::string, std::string> parentDirs[numParentDirs];
+ std::array<std::pair<std::string, std::string>, 4> parentDirs;
};
#endif
diff --git a/Source/cmFileTime.cxx b/Source/cmFileTime.cxx
new file mode 100644
index 000000000..96c70fef6
--- /dev/null
+++ b/Source/cmFileTime.cxx
@@ -0,0 +1,50 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFileTime.h"
+
+#include <ctime>
+#include <string>
+
+// Use a platform-specific API to get file times efficiently.
+#if !defined(_WIN32) || defined(__CYGWIN__)
+# include "cm_sys_stat.h"
+#else
+# include <windows.h>
+
+# include "cmsys/Encoding.hxx"
+#endif
+
+bool cmFileTime::Load(std::string const& fileName)
+{
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ // POSIX version. Use the stat function.
+ struct stat fst;
+ if (::stat(fileName.c_str(), &fst) != 0) {
+ return false;
+ }
+# if CMake_STAT_HAS_ST_MTIM
+ // Nanosecond resolution
+ this->NS = fst.st_mtim.tv_sec * NsPerS + fst.st_mtim.tv_nsec;
+# elif CMake_STAT_HAS_ST_MTIMESPEC
+ // Nanosecond resolution
+ this->NS = fst.st_mtimespec.tv_sec * NsPerS + fst.st_mtimespec.tv_nsec;
+# else
+ // Second resolution
+ this->NS = fst.st_mtime * NsPerS;
+# endif
+#else
+ // Windows version. Get the modification time from extended file attributes.
+ WIN32_FILE_ATTRIBUTE_DATA fdata;
+ if (!GetFileAttributesExW(cmsys::Encoding::ToWide(fileName).c_str(),
+ GetFileExInfoStandard, &fdata)) {
+ return false;
+ }
+
+ // Copy the file time to the output location.
+ this->NS = (static_cast<NSC>(fdata.ftLastWriteTime.dwHighDateTime) << 32) |
+ static_cast<NSC>(fdata.ftLastWriteTime.dwLowDateTime);
+ // The file time resolution is 100 ns.
+ this->NS *= 100;
+#endif
+ return true;
+}
diff --git a/Source/cmFileTime.h b/Source/cmFileTime.h
new file mode 100644
index 000000000..e9a85598a
--- /dev/null
+++ b/Source/cmFileTime.h
@@ -0,0 +1,130 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmFileTime_h
+#define cmFileTime_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+
+/** \class cmFileTime
+ * \brief Abstract file modification time with support for comparison with
+ * other file modification times.
+ */
+class cmFileTime
+{
+public:
+ using NSC = long long;
+ static constexpr NSC NsPerS = 1000000000;
+
+ cmFileTime() = default;
+ ~cmFileTime() = default;
+
+ /**
+ * @brief Loads the file time of fileName from the file system
+ * @return true on success
+ */
+ bool Load(std::string const& fileName);
+
+ /**
+ * @brief Return true if this is older than ftm
+ */
+ bool Older(cmFileTime const& ftm) const { return (this->NS - ftm.NS) < 0; }
+
+ /**
+ * @brief Return true if this is newer than ftm
+ */
+ bool Newer(cmFileTime const& ftm) const { return (ftm.NS - this->NS) < 0; }
+
+ /**
+ * @brief Return true if this is the same as ftm
+ */
+ bool Equal(cmFileTime const& ftm) const { return this->NS == ftm.NS; }
+
+ /**
+ * @brief Return true if this is not the same as ftm
+ */
+ bool Differ(cmFileTime const& ftm) const { return this->NS != ftm.NS; }
+
+ /**
+ * @brief Compare file modification times.
+ * @return -1, 0, +1 for this older, same, or newer than ftm.
+ */
+ int Compare(cmFileTime const& ftm) const
+ {
+ NSC const diff = this->NS - ftm.NS;
+ if (diff == 0) {
+ return 0;
+ }
+ return (diff < 0) ? -1 : 1;
+ }
+
+ // -- Comparison in second resolution
+
+ /**
+ * @brief Return true if this is at least a second older than ftm
+ */
+ bool OlderS(cmFileTime const& ftm) const
+ {
+ return (ftm.NS - this->NS) >= cmFileTime::NsPerS;
+ }
+
+ /**
+ * @brief Return true if this is at least a second newer than ftm
+ */
+ bool NewerS(cmFileTime const& ftm) const
+ {
+ return (this->NS - ftm.NS) >= cmFileTime::NsPerS;
+ }
+
+ /**
+ * @brief Return true if this is within the same second as ftm
+ */
+ bool EqualS(cmFileTime const& ftm) const
+ {
+ NSC diff = this->NS - ftm.NS;
+ if (diff < 0) {
+ diff = -diff;
+ }
+ return (diff < cmFileTime::NsPerS);
+ }
+
+ /**
+ * @brief Return true if this is older or newer than ftm by at least a second
+ */
+ bool DifferS(cmFileTime const& ftm) const
+ {
+ NSC diff = this->NS - ftm.NS;
+ if (diff < 0) {
+ diff = -diff;
+ }
+ return (diff >= cmFileTime::NsPerS);
+ }
+
+ /**
+ * @brief Compare file modification times.
+ * @return -1: this at least a second older, 0: this within the same second
+ * as ftm, +1: this at least a second newer than ftm.
+ */
+ int CompareS(cmFileTime const& ftm) const
+ {
+ NSC const diff = this->NS - ftm.NS;
+ if (diff <= -cmFileTime::NsPerS) {
+ return -1;
+ }
+ if (diff >= cmFileTime::NsPerS) {
+ return 1;
+ }
+ return 0;
+ }
+
+ /**
+ * @brief The file modification time in nanoseconds
+ */
+ NSC GetNS() const { return this->NS; }
+
+private:
+ NSC NS = 0;
+};
+
+#endif
diff --git a/Source/cmFileTimeCache.cxx b/Source/cmFileTimeCache.cxx
new file mode 100644
index 000000000..0d1dae5e8
--- /dev/null
+++ b/Source/cmFileTimeCache.cxx
@@ -0,0 +1,64 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFileTimeCache.h"
+
+#include <string>
+#include <unordered_map>
+#include <utility>
+
+cmFileTimeCache::cmFileTimeCache() = default;
+
+cmFileTimeCache::~cmFileTimeCache() = default;
+
+bool cmFileTimeCache::Load(std::string const& fileName, cmFileTime& fileTime)
+{
+ // Use the stored time if available.
+ {
+ auto fit = this->Cache.find(fileName);
+ if (fit != this->Cache.end()) {
+ fileTime = fit->second;
+ return true;
+ }
+ }
+ // Read file time from OS
+ if (!fileTime.Load(fileName)) {
+ return false;
+ }
+ // Store file time in cache
+ this->Cache[fileName] = fileTime;
+ return true;
+}
+
+bool cmFileTimeCache::Remove(std::string const& fileName)
+{
+ return (this->Cache.erase(fileName) != 0);
+}
+
+bool cmFileTimeCache::Compare(std::string const& f1, std::string const& f2,
+ int* result)
+{
+ // Get the modification time for each file.
+ cmFileTime ft1;
+ cmFileTime ft2;
+ if (this->Load(f1, ft1) && this->Load(f2, ft2)) {
+ // Compare the two modification times.
+ *result = ft1.Compare(ft2);
+ return true;
+ }
+ // No comparison available. Default to the same time.
+ *result = 0;
+ return false;
+}
+
+bool cmFileTimeCache::DifferS(std::string const& f1, std::string const& f2)
+{
+ // Get the modification time for each file.
+ cmFileTime ft1;
+ cmFileTime ft2;
+ if (this->Load(f1, ft1) && this->Load(f2, ft2)) {
+ // Compare the two modification times.
+ return ft1.DifferS(ft2);
+ }
+ // No comparison available. Default to different times.
+ return true;
+}
diff --git a/Source/cmFileTimeCache.h b/Source/cmFileTimeCache.h
new file mode 100644
index 000000000..83b77b651
--- /dev/null
+++ b/Source/cmFileTimeCache.h
@@ -0,0 +1,57 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmFileTimeCache_h
+#define cmFileTimeCache_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <unordered_map>
+
+#include "cmFileTime.h" // IWYU pragma: keep
+
+/** \class cmFileTimeCache
+ * \brief Caches file modification times in an internal map for fast lookups.
+ */
+class cmFileTimeCache
+{
+public:
+ cmFileTimeCache();
+ ~cmFileTimeCache();
+
+ cmFileTimeCache(const cmFileTimeCache&) = delete;
+ cmFileTimeCache& operator=(const cmFileTimeCache&) = delete;
+
+ /**
+ * @brief Loads the file time from the cache or the file system.
+ * @return true on success
+ */
+ bool Load(std::string const& fileName, cmFileTime& fileTime);
+
+ /**
+ * @brief Removes a file time from the cache
+ * @return true if the file was found in the cache and removed
+ */
+ bool Remove(std::string const& fileName);
+
+ /**
+ * @brief Compare file modification times.
+ * @return true for successful comparison and false for error.
+ *
+ * When true is returned, result has -1, 0, +1 for
+ * f1 older, same, or newer than f2.
+ */
+ bool Compare(std::string const& f1, std::string const& f2, int* result);
+
+ /**
+ * @brief Compare file modification times.
+ * @return true unless both files exist and have modification times less
+ * than 1 second apart.
+ */
+ bool DifferS(std::string const& f1, std::string const& f2);
+
+private:
+ std::unordered_map<std::string, cmFileTime> Cache;
+};
+
+#endif
diff --git a/Source/cmFileTimeComparison.cxx b/Source/cmFileTimeComparison.cxx
deleted file mode 100644
index f591a8dc7..000000000
--- a/Source/cmFileTimeComparison.cxx
+++ /dev/null
@@ -1,227 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmFileTimeComparison.h"
-
-#include <string>
-#include <time.h>
-#include <utility>
-
-#include "cm_unordered_map.hxx"
-
-// Use a platform-specific API to get file times efficiently.
-#if !defined(_WIN32) || defined(__CYGWIN__)
-#include "cm_sys_stat.h"
-#define cmFileTimeComparison_Type struct stat
-#else
-#include "cmsys/Encoding.hxx"
-#include <windows.h>
-#define cmFileTimeComparison_Type FILETIME
-#endif
-
-class cmFileTimeComparisonInternal
-{
-public:
- // Internal comparison method.
- inline bool FileTimeCompare(const char* f1, const char* f2, int* result);
-
- bool FileTimesDiffer(const char* f1, const char* f2);
-
-private:
- typedef CM_UNORDERED_MAP<std::string, cmFileTimeComparison_Type>
- FileStatsMap;
- FileStatsMap Files;
-
- // Internal methods to lookup and compare modification times.
- inline bool Stat(const char* fname, cmFileTimeComparison_Type* st);
- inline int Compare(cmFileTimeComparison_Type* st1,
- cmFileTimeComparison_Type* st2);
- inline bool TimesDiffer(cmFileTimeComparison_Type* st1,
- cmFileTimeComparison_Type* st2);
-};
-
-bool cmFileTimeComparisonInternal::Stat(const char* fname,
- cmFileTimeComparison_Type* st)
-{
- // Use the stored time if available.
- cmFileTimeComparisonInternal::FileStatsMap::iterator fit =
- this->Files.find(fname);
- if (fit != this->Files.end()) {
- *st = fit->second;
- return true;
- }
-
-#if !defined(_WIN32) || defined(__CYGWIN__)
- // POSIX version. Use the stat function.
- int res = ::stat(fname, st);
- if (res != 0) {
- return false;
- }
-#else
- // Windows version. Get the modification time from extended file
- // attributes.
- WIN32_FILE_ATTRIBUTE_DATA fdata;
- if (!GetFileAttributesExW(cmsys::Encoding::ToWide(fname).c_str(),
- GetFileExInfoStandard, &fdata)) {
- return false;
- }
-
- // Copy the file time to the output location.
- *st = fdata.ftLastWriteTime;
-#endif
-
- // Store the time for future use.
- this->Files[fname] = *st;
- return true;
-}
-
-cmFileTimeComparison::cmFileTimeComparison()
-{
- this->Internals = new cmFileTimeComparisonInternal;
-}
-
-cmFileTimeComparison::~cmFileTimeComparison()
-{
- delete this->Internals;
-}
-
-bool cmFileTimeComparison::FileTimeCompare(const char* f1, const char* f2,
- int* result)
-{
- return this->Internals->FileTimeCompare(f1, f2, result);
-}
-
-bool cmFileTimeComparison::FileTimesDiffer(const char* f1, const char* f2)
-{
- return this->Internals->FileTimesDiffer(f1, f2);
-}
-
-int cmFileTimeComparisonInternal::Compare(cmFileTimeComparison_Type* s1,
- cmFileTimeComparison_Type* s2)
-{
-#if !defined(_WIN32) || defined(__CYGWIN__)
-#if CMake_STAT_HAS_ST_MTIM
- // Compare using nanosecond resolution.
- if (s1->st_mtim.tv_sec < s2->st_mtim.tv_sec) {
- return -1;
- }
- if (s1->st_mtim.tv_sec > s2->st_mtim.tv_sec) {
- return 1;
- }
- if (s1->st_mtim.tv_nsec < s2->st_mtim.tv_nsec) {
- return -1;
- }
- if (s1->st_mtim.tv_nsec > s2->st_mtim.tv_nsec) {
- return 1;
- }
-#elif CMake_STAT_HAS_ST_MTIMESPEC
- // Compare using nanosecond resolution.
- if (s1->st_mtimespec.tv_sec < s2->st_mtimespec.tv_sec) {
- return -1;
- } else if (s1->st_mtimespec.tv_sec > s2->st_mtimespec.tv_sec) {
- return 1;
- } else if (s1->st_mtimespec.tv_nsec < s2->st_mtimespec.tv_nsec) {
- return -1;
- } else if (s1->st_mtimespec.tv_nsec > s2->st_mtimespec.tv_nsec) {
- return 1;
- }
-#else
- // Compare using 1 second resolution.
- if (s1->st_mtime < s2->st_mtime) {
- return -1;
- } else if (s1->st_mtime > s2->st_mtime) {
- return 1;
- }
-#endif
- // Files have the same time.
- return 0;
-#else
- // Compare using system-provided function.
- return (int)CompareFileTime(s1, s2);
-#endif
-}
-
-bool cmFileTimeComparisonInternal::TimesDiffer(cmFileTimeComparison_Type* s1,
- cmFileTimeComparison_Type* s2)
-{
-#if !defined(_WIN32) || defined(__CYGWIN__)
-#if CMake_STAT_HAS_ST_MTIM
- // Times are integers in units of 1ns.
- long long bil = 1000000000;
- long long t1 = s1->st_mtim.tv_sec * bil + s1->st_mtim.tv_nsec;
- long long t2 = s2->st_mtim.tv_sec * bil + s2->st_mtim.tv_nsec;
- if (t1 < t2) {
- return (t2 - t1) >= bil;
- }
- if (t2 < t1) {
- return (t1 - t2) >= bil;
- }
- return false;
-#elif CMake_STAT_HAS_ST_MTIMESPEC
- // Times are integers in units of 1ns.
- long long bil = 1000000000;
- long long t1 = s1->st_mtimespec.tv_sec * bil + s1->st_mtimespec.tv_nsec;
- long long t2 = s2->st_mtimespec.tv_sec * bil + s2->st_mtimespec.tv_nsec;
- if (t1 < t2) {
- return (t2 - t1) >= bil;
- } else if (t2 < t1) {
- return (t1 - t2) >= bil;
- } else {
- return false;
- }
-#else
- // Times are integers in units of 1s.
- if (s1->st_mtime < s2->st_mtime) {
- return (s2->st_mtime - s1->st_mtime) >= 1;
- } else if (s1->st_mtime > s2->st_mtime) {
- return (s1->st_mtime - s2->st_mtime) >= 1;
- } else {
- return false;
- }
-#endif
-#else
- // Times are integers in units of 100ns.
- LARGE_INTEGER t1;
- LARGE_INTEGER t2;
- t1.LowPart = s1->dwLowDateTime;
- t1.HighPart = s1->dwHighDateTime;
- t2.LowPart = s2->dwLowDateTime;
- t2.HighPart = s2->dwHighDateTime;
- if (t1.QuadPart < t2.QuadPart) {
- return (t2.QuadPart - t1.QuadPart) >= static_cast<LONGLONG>(10000000);
- } else if (t2.QuadPart < t1.QuadPart) {
- return (t1.QuadPart - t2.QuadPart) >= static_cast<LONGLONG>(10000000);
- } else {
- return false;
- }
-#endif
-}
-
-bool cmFileTimeComparisonInternal::FileTimeCompare(const char* f1,
- const char* f2, int* result)
-{
- // Get the modification time for each file.
- cmFileTimeComparison_Type s1;
- cmFileTimeComparison_Type s2;
- if (this->Stat(f1, &s1) && this->Stat(f2, &s2)) {
- // Compare the two modification times.
- *result = this->Compare(&s1, &s2);
- return true;
- }
- // No comparison available. Default to the same time.
- *result = 0;
- return false;
-}
-
-bool cmFileTimeComparisonInternal::FileTimesDiffer(const char* f1,
- const char* f2)
-{
- // Get the modification time for each file.
- cmFileTimeComparison_Type s1;
- cmFileTimeComparison_Type s2;
- if (this->Stat(f1, &s1) && this->Stat(f2, &s2)) {
- // Compare the two modification times.
- return this->TimesDiffer(&s1, &s2);
- }
- // No comparison available. Default to different times.
- return true;
-}
diff --git a/Source/cmFileTimeComparison.h b/Source/cmFileTimeComparison.h
deleted file mode 100644
index b1f8ed636..000000000
--- a/Source/cmFileTimeComparison.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmFileTimeComparison_h
-#define cmFileTimeComparison_h
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-class cmFileTimeComparisonInternal;
-
-/** \class cmFileTimeComparison
- * \brief Helper class for performing globbing searches.
- *
- * Finds all files that match a given globbing expression.
- */
-class cmFileTimeComparison
-{
-public:
- cmFileTimeComparison();
- ~cmFileTimeComparison();
-
- /**
- * Compare file modification times.
- * Return true for successful comparison and false for error.
- * When true is returned, result has -1, 0, +1 for
- * f1 older, same, or newer than f2.
- */
- bool FileTimeCompare(const char* f1, const char* f2, int* result);
-
- /**
- * Compare file modification times. Return true unless both files
- * exist and have modification times less than 1 second apart.
- */
- bool FileTimesDiffer(const char* f1, const char* f2);
-
-protected:
- cmFileTimeComparisonInternal* Internals;
-};
-
-#endif
diff --git a/Source/cmFileTimes.cxx b/Source/cmFileTimes.cxx
new file mode 100644
index 000000000..d8fe24c5b
--- /dev/null
+++ b/Source/cmFileTimes.cxx
@@ -0,0 +1,129 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFileTimes.h"
+
+#include <utility>
+
+#include <cm/memory>
+
+#include "cm_sys_stat.h"
+
+#if defined(_WIN32)
+# include <windows.h>
+
+# include "cmSystemTools.h"
+#else
+# include <utime.h>
+#endif
+
+#if defined(_WIN32) && \
+ (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__MINGW32__))
+# include <io.h>
+#endif
+
+#ifdef _WIN32
+class cmFileTimes::WindowsHandle
+{
+public:
+ WindowsHandle(HANDLE h)
+ : handle_(h)
+ {
+ }
+ ~WindowsHandle()
+ {
+ if (this->handle_ != INVALID_HANDLE_VALUE) {
+ CloseHandle(this->handle_);
+ }
+ }
+ explicit operator bool() const
+ {
+ return this->handle_ != INVALID_HANDLE_VALUE;
+ }
+ bool operator!() const { return this->handle_ == INVALID_HANDLE_VALUE; }
+ operator HANDLE() const { return this->handle_; }
+
+private:
+ HANDLE handle_;
+};
+#endif
+
+class cmFileTimes::Times
+{
+public:
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ FILETIME timeCreation;
+ FILETIME timeLastAccess;
+ FILETIME timeLastWrite;
+#else
+ struct utimbuf timeBuf;
+#endif
+};
+
+cmFileTimes::cmFileTimes() = default;
+cmFileTimes::cmFileTimes(std::string const& fileName)
+{
+ Load(fileName);
+}
+cmFileTimes::~cmFileTimes() = default;
+
+bool cmFileTimes::Load(std::string const& fileName)
+{
+ std::unique_ptr<Times> ptr;
+ if (IsValid()) {
+ // Invalidate this and re-use times
+ ptr.swap(this->times);
+ } else {
+ ptr = cm::make_unique<Times>();
+ }
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ cmFileTimes::WindowsHandle handle =
+ CreateFileW(cmSystemTools::ConvertToWindowsExtendedPath(fileName).c_str(),
+ GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS, 0);
+ if (!handle) {
+ return false;
+ }
+ if (!GetFileTime(handle, &ptr->timeCreation, &ptr->timeLastAccess,
+ &ptr->timeLastWrite)) {
+ return false;
+ }
+#else
+ struct stat st;
+ if (stat(fileName.c_str(), &st) < 0) {
+ return false;
+ }
+ ptr->timeBuf.actime = st.st_atime;
+ ptr->timeBuf.modtime = st.st_mtime;
+#endif
+ // Accept times
+ this->times = std::move(ptr);
+ return true;
+}
+
+bool cmFileTimes::Store(std::string const& fileName) const
+{
+ if (!IsValid()) {
+ return false;
+ }
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ cmFileTimes::WindowsHandle handle = CreateFileW(
+ cmSystemTools::ConvertToWindowsExtendedPath(fileName).c_str(),
+ FILE_WRITE_ATTRIBUTES, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
+ if (!handle) {
+ return false;
+ }
+ return SetFileTime(handle, &this->times->timeCreation,
+ &this->times->timeLastAccess,
+ &this->times->timeLastWrite) != 0;
+#else
+ return utime(fileName.c_str(), &this->times->timeBuf) >= 0;
+#endif
+}
+
+bool cmFileTimes::Copy(std::string const& fromFile, std::string const& toFile)
+{
+ cmFileTimes fileTimes;
+ return (fileTimes.Load(fromFile) && fileTimes.Store(toFile));
+}
diff --git a/Source/cmFileTimes.h b/Source/cmFileTimes.h
new file mode 100644
index 000000000..191d89e94
--- /dev/null
+++ b/Source/cmFileTimes.h
@@ -0,0 +1,40 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmFileTimes_h
+#define cmFileTimes_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <memory>
+#include <string>
+
+/** \class cmFileTimes
+ * \brief Loads and stores file times.
+ */
+class cmFileTimes
+{
+public:
+ cmFileTimes();
+ //! Calls Load()
+ cmFileTimes(std::string const& fileName);
+ ~cmFileTimes();
+
+ //! @return true, if file times were loaded successfully
+ bool IsValid() const { return (times != nullptr); }
+ //! Try to load the file times from @a fileName and @return IsValid()
+ bool Load(std::string const& fileName);
+ //! Stores the file times at @a fileName (if IsValid())
+ bool Store(std::string const& fileName) const;
+
+ //! Copies the file times of @a fromFile to @a toFile
+ static bool Copy(std::string const& fromFile, std::string const& toFile);
+
+private:
+#ifdef _WIN32
+ class WindowsHandle;
+#endif
+ class Times;
+ std::unique_ptr<Times> times;
+};
+
+#endif
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index 10c6fe46f..7d741182d 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -2,21 +2,24 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFindBase.h"
-#include "cmConfigure.h"
+#include <cstddef>
#include <deque>
#include <iostream>
-#include <iterator>
#include <map>
-#include <stddef.h>
#include "cmAlgorithms.h"
#include "cmMakefile.h"
+#include "cmRange.h"
#include "cmSearchPath.h"
#include "cmState.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-cmFindBase::cmFindBase()
+class cmExecutionStatus;
+
+cmFindBase::cmFindBase(cmExecutionStatus& status)
+ : cmFindCommon(status)
{
this->AlreadyInCache = false;
this->AlreadyInCacheWithoutMetaInfo = false;
@@ -68,7 +71,8 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
}
this->AlreadyInCache = false;
- this->SelectDefaultNoPackageRootPath();
+ // Find what search path locations have been enabled/disable
+ this->SelectDefaultSearchModes();
// Find the current root path mode.
this->SelectDefaultRootPathMode();
@@ -132,25 +136,24 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
this->VariableDocumentation += "the (unknown) library be found";
} else if (this->Names.size() == 1) {
this->VariableDocumentation +=
- "the " + this->Names[0] + " library be found";
+ "the " + this->Names.front() + " library be found";
} else {
this->VariableDocumentation += "one of the ";
this->VariableDocumentation +=
cmJoin(cmMakeRange(this->Names).retreat(1), ", ");
this->VariableDocumentation +=
- " or " + this->Names[this->Names.size() - 1] + " libraries be found";
+ " or " + this->Names.back() + " libraries be found";
}
}
// look for old style
// FIND_*(VAR name path1 path2 ...)
- if (!newStyle) {
+ if (!newStyle && !this->Names.empty()) {
// All the short-hand arguments have been recorded as names.
std::vector<std::string> shortArgs = this->Names;
this->Names.clear(); // clear out any values in Names
this->Names.push_back(shortArgs[0]);
- this->UserGuessArgs.insert(this->UserGuessArgs.end(),
- shortArgs.begin() + 1, shortArgs.end());
+ cmAppend(this->UserGuessArgs, shortArgs.begin() + 1, shortArgs.end());
}
this->ExpandPaths();
@@ -189,9 +192,7 @@ void cmFindBase::FillCMakeEnvironmentPath()
cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeEnvironment];
// Add CMAKE_*_PATH environment variables
- std::string var = "CMAKE_";
- var += this->CMakePathName;
- var += "_PATH";
+ std::string var = cmStrCat("CMAKE_", this->CMakePathName, "_PATH");
paths.AddEnvPrefixPath("CMAKE_PREFIX_PATH");
paths.AddEnvPath(var);
@@ -207,16 +208,10 @@ void cmFindBase::FillPackageRootPath()
{
cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRoot];
- // Add package specific search prefixes
- // NOTE: This should be using const_reverse_iterator but HP aCC and
- // Oracle sunCC both currently have standard library issues
- // with the reverse iterator APIs.
- for (std::deque<std::string>::reverse_iterator pkg =
- this->Makefile->FindPackageModuleStack.rbegin();
- pkg != this->Makefile->FindPackageModuleStack.rend(); ++pkg) {
- std::string varName = *pkg + "_ROOT";
- paths.AddCMakePrefixPath(varName);
- paths.AddEnvPrefixPath(varName);
+ // Add the PACKAGE_ROOT_PATH from each enclosing find_package call.
+ for (std::vector<std::string> const& pkgPaths :
+ cmReverseRange(this->Makefile->FindPackageRootPathStack)) {
+ paths.AddPrefixPaths(pkgPaths);
}
paths.AddSuffixes(this->SearchPathSuffixes);
@@ -226,12 +221,10 @@ void cmFindBase::FillCMakeVariablePath()
{
cmSearchPath& paths = this->LabeledPaths[PathLabel::CMake];
- // Add CMake varibles of the same name as the previous environment
- // varibles CMAKE_*_PATH to be used most of the time with -D
+ // Add CMake variables of the same name as the previous environment
+ // variables CMAKE_*_PATH to be used most of the time with -D
// command line options
- std::string var = "CMAKE_";
- var += this->CMakePathName;
- var += "_PATH";
+ std::string var = cmStrCat("CMAKE_", this->CMakePathName, "_PATH");
paths.AddCMakePrefixPath("CMAKE_PREFIX_PATH");
paths.AddCMakePath(var);
@@ -263,9 +256,7 @@ void cmFindBase::FillCMakeSystemVariablePath()
{
cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeSystem];
- std::string var = "CMAKE_SYSTEM_";
- var += this->CMakePathName;
- var += "_PATH";
+ std::string var = cmStrCat("CMAKE_SYSTEM_", this->CMakePathName, "_PATH");
paths.AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH");
paths.AddCMakePath(var);
@@ -281,10 +272,8 @@ void cmFindBase::FillUserHintsPath()
{
cmSearchPath& paths = this->LabeledPaths[PathLabel::Hints];
- for (std::vector<std::string>::const_iterator p =
- this->UserHintsArgs.begin();
- p != this->UserHintsArgs.end(); ++p) {
- paths.AddUserPath(*p);
+ for (std::string const& p : this->UserHintsArgs) {
+ paths.AddUserPath(p);
}
paths.AddSuffixes(this->SearchPathSuffixes);
}
@@ -293,10 +282,8 @@ void cmFindBase::FillUserGuessPath()
{
cmSearchPath& paths = this->LabeledPaths[PathLabel::Guess];
- for (std::vector<std::string>::const_iterator p =
- this->UserGuessArgs.begin();
- p != this->UserGuessArgs.end(); ++p) {
- paths.AddUserPath(*p);
+ for (std::string const& p : this->UserGuessArgs) {
+ paths.AddUserPath(p);
}
paths.AddSuffixes(this->SearchPathSuffixes);
}
@@ -334,8 +321,8 @@ bool cmFindBase::CheckForVariableInCache()
this->Makefile->GetDefinition(this->VariableName)) {
cmState* state = this->Makefile->GetState();
const char* cacheEntry = state->GetCacheEntryValue(this->VariableName);
- bool found = !cmSystemTools::IsNOTFOUND(cacheValue);
- bool cached = cacheEntry != CM_NULLPTR;
+ bool found = !cmIsNOTFOUND(cacheValue);
+ bool cached = cacheEntry != nullptr;
if (found) {
// If the user specifies the entry on the command line without a
// type we should add the type and docstring but keep the
diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h
index 88b5b6c18..f75db5ff3 100644
--- a/Source/cmFindBase.h
+++ b/Source/cmFindBase.h
@@ -10,6 +10,8 @@
#include "cmFindCommon.h"
+class cmExecutionStatus;
+
/** \class cmFindBase
* \brief Base class for most FIND_XXX commands.
*
@@ -19,7 +21,9 @@
class cmFindBase : public cmFindCommon
{
public:
- cmFindBase();
+ cmFindBase(cmExecutionStatus& status);
+ virtual ~cmFindBase() = default;
+
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index 4ef0f3ec1..badec55a8 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -3,10 +3,14 @@
#include "cmFindCommon.h"
#include <algorithm>
-#include <string.h>
+#include <array>
+#include <cstring>
#include <utility>
+#include "cmAlgorithms.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
cmFindCommon::PathGroup cmFindCommon::PathGroup::All("ALL");
@@ -21,7 +25,9 @@ cmFindCommon::PathLabel cmFindCommon::PathLabel::SystemEnvironment(
cmFindCommon::PathLabel cmFindCommon::PathLabel::CMakeSystem("CMAKE_SYSTEM");
cmFindCommon::PathLabel cmFindCommon::PathLabel::Guess("GUESS");
-cmFindCommon::cmFindCommon()
+cmFindCommon::cmFindCommon(cmExecutionStatus& status)
+ : Makefile(&status.GetMakefile())
+ , Status(status)
{
this->FindRootPathMode = RootPathModeBoth;
this->NoDefaultPath = false;
@@ -48,15 +54,16 @@ cmFindCommon::cmFindCommon()
this->InitializeSearchPathGroups();
}
-cmFindCommon::~cmFindCommon()
+void cmFindCommon::SetError(std::string const& e)
{
+ this->Status.SetError(e);
}
void cmFindCommon::InitializeSearchPathGroups()
{
std::vector<PathLabel>* labels;
- // Define the varoius different groups of path types
+ // Define the various different groups of path types
// All search paths
labels = &this->PathGroupLabelMap[PathGroup::All];
@@ -71,7 +78,7 @@ void cmFindCommon::InitializeSearchPathGroups()
// Define the search group order
this->PathGroupOrder.push_back(PathGroup::All);
- // Create the idividual labeld search paths
+ // Create the individual labeled search paths
this->LabeledPaths.insert(
std::make_pair(PathLabel::PackageRoot, cmSearchPath(this)));
this->LabeledPaths.insert(
@@ -88,18 +95,11 @@ void cmFindCommon::InitializeSearchPathGroups()
std::make_pair(PathLabel::Guess, cmSearchPath(this)));
}
-void cmFindCommon::SelectDefaultNoPackageRootPath()
-{
- if (!this->Makefile->IsOn("__UNDOCUMENTED_CMAKE_FIND_PACKAGE_ROOT")) {
- this->NoPackageRootPath = true;
- }
-}
-
void cmFindCommon::SelectDefaultRootPathMode()
{
// Check the policy variable for this find command type.
- std::string findRootPathVar = "CMAKE_FIND_ROOT_PATH_MODE_";
- findRootPathVar += this->CMakePathName;
+ std::string findRootPathVar =
+ cmStrCat("CMAKE_FIND_ROOT_PATH_MODE_", this->CMakePathName);
std::string rootPathMode =
this->Makefile->GetSafeDefinition(findRootPathVar);
if (rootPathMode == "NEVER") {
@@ -152,13 +152,32 @@ void cmFindCommon::SelectDefaultMacMode()
}
}
+void cmFindCommon::SelectDefaultSearchModes()
+{
+ const std::array<std::pair<bool&, std::string>, 5> search_paths = {
+ { { this->NoPackageRootPath, "CMAKE_FIND_USE_PACKAGE_ROOT_PATH" },
+ { this->NoCMakePath, "CMAKE_FIND_USE_CMAKE_PATH" },
+ { this->NoCMakeEnvironmentPath,
+ "CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH" },
+ { this->NoSystemEnvironmentPath,
+ "CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH" },
+ { this->NoCMakeSystemPath, "CMAKE_FIND_USE_CMAKE_SYSTEM_PATH" } }
+ };
+
+ for (auto& path : search_paths) {
+ const char* def = this->Makefile->GetDefinition(path.second);
+ if (def) {
+ path.first = !cmIsOn(def);
+ }
+ }
+}
+
void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
{
#if 0
- for(std::vector<std::string>::const_iterator i = paths.begin();
- i != paths.end(); ++i)
+ for(std::string const& p : paths)
{
- fprintf(stderr, "[%s]\n", i->c_str());
+ fprintf(stderr, "[%s]\n", p.c_str());
}
#endif
// Short-circuit if there is nothing to do.
@@ -183,20 +202,19 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
// Construct the list of path roots with no trailing slashes.
std::vector<std::string> roots;
if (rootPath) {
- cmSystemTools::ExpandListArgument(rootPath, roots);
+ cmExpandList(rootPath, roots);
}
if (sysrootCompile) {
- roots.push_back(sysrootCompile);
+ roots.emplace_back(sysrootCompile);
}
if (sysrootLink) {
- roots.push_back(sysrootLink);
+ roots.emplace_back(sysrootLink);
}
if (sysroot) {
- roots.push_back(sysroot);
+ roots.emplace_back(sysroot);
}
- for (std::vector<std::string>::iterator ri = roots.begin();
- ri != roots.end(); ++ri) {
- cmSystemTools::ConvertToUnixSlashes(*ri);
+ for (std::string& r : roots) {
+ cmSystemTools::ConvertToUnixSlashes(r);
}
const char* stagePrefix =
@@ -206,24 +224,21 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
std::vector<std::string> unrootedPaths = paths;
paths.clear();
- for (std::vector<std::string>::const_iterator ri = roots.begin();
- ri != roots.end(); ++ri) {
- for (std::vector<std::string>::const_iterator ui = unrootedPaths.begin();
- ui != unrootedPaths.end(); ++ui) {
+ for (std::string const& r : roots) {
+ for (std::string const& up : unrootedPaths) {
// Place the unrooted path under the current root if it is not
// already inside. Skip the unrooted path if it is relative to
// a user home directory or is empty.
std::string rootedDir;
- if (cmSystemTools::IsSubDirectory(*ui, *ri) ||
- (stagePrefix && cmSystemTools::IsSubDirectory(*ui, stagePrefix))) {
- rootedDir = *ui;
- } else if (!ui->empty() && (*ui)[0] != '~') {
+ if (cmSystemTools::IsSubDirectory(up, r) ||
+ (stagePrefix && cmSystemTools::IsSubDirectory(up, stagePrefix))) {
+ rootedDir = up;
+ } else if (!up.empty() && up[0] != '~') {
// Start with the new root.
- rootedDir = *ri;
- rootedDir += "/";
+ rootedDir = cmStrCat(r, '/');
// Append the original path with its old root removed.
- rootedDir += cmSystemTools::SplitPathRootComponent(*ui);
+ rootedDir += cmSystemTools::SplitPathRootComponent(up);
}
// Store the new path.
@@ -234,7 +249,7 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
// If searching both rooted and unrooted paths add the original
// paths again.
if (this->FindRootPathMode == RootPathModeBoth) {
- paths.insert(paths.end(), unrootedPaths.begin(), unrootedPaths.end());
+ cmAppend(paths, unrootedPaths);
}
}
@@ -242,22 +257,21 @@ void cmFindCommon::GetIgnoredPaths(std::vector<std::string>& ignore)
{
// null-terminated list of paths.
static const char* paths[] = { "CMAKE_SYSTEM_IGNORE_PATH",
- "CMAKE_IGNORE_PATH", CM_NULLPTR };
+ "CMAKE_IGNORE_PATH", nullptr };
// Construct the list of path roots with no trailing slashes.
for (const char** pathName = paths; *pathName; ++pathName) {
// Get the list of paths to ignore from the variable.
const char* ignorePath = this->Makefile->GetDefinition(*pathName);
- if ((ignorePath == CM_NULLPTR) || (strlen(ignorePath) == 0)) {
+ if ((ignorePath == nullptr) || (strlen(ignorePath) == 0)) {
continue;
}
- cmSystemTools::ExpandListArgument(ignorePath, ignore);
+ cmExpandList(ignorePath, ignore);
}
- for (std::vector<std::string>::iterator i = ignore.begin();
- i != ignore.end(); ++i) {
- cmSystemTools::ConvertToUnixSlashes(*i);
+ for (std::string& i : ignore) {
+ cmSystemTools::ConvertToUnixSlashes(i);
}
}
@@ -305,13 +319,13 @@ void cmFindCommon::AddPathSuffix(std::string const& arg)
if (suffix.empty()) {
return;
}
- if (suffix[0] == '/') {
+ if (suffix.front() == '/') {
suffix = suffix.substr(1);
}
if (suffix.empty()) {
return;
}
- if (suffix[suffix.size() - 1] == '/') {
+ if (suffix.back() == '/') {
suffix = suffix.substr(0, suffix.size() - 1);
}
if (suffix.empty()) {
@@ -319,12 +333,12 @@ 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)
{
- if (!s.empty() && *s.rbegin() != '/') {
+ if (!s.empty() && s.back() != '/') {
s += '/';
}
}
@@ -334,12 +348,11 @@ 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 (std::vector<PathLabel>::const_iterator l = allLabels.begin();
- l != allLabels.end(); ++l) {
- this->LabeledPaths[*l].ExtractWithout(ignored, this->SearchPaths);
+ for (PathLabel const& l : allLabels) {
+ this->LabeledPaths[l].ExtractWithout(ignored, this->SearchPaths);
}
// Expand list of paths inside all search roots.
diff --git a/Source/cmFindCommon.h b/Source/cmFindCommon.h
index 72dcd355d..8177eacd6 100644
--- a/Source/cmFindCommon.h
+++ b/Source/cmFindCommon.h
@@ -3,17 +3,19 @@
#ifndef cmFindCommon_h
#define cmFindCommon_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
#include <set>
#include <string>
#include <vector>
-#include "cmCommand.h"
#include "cmPathLabel.h"
#include "cmSearchPath.h"
+class cmExecutionStatus;
+class cmMakefile;
+
/** \class cmFindCommon
* \brief Base class for FIND_XXX implementations.
*
@@ -21,11 +23,12 @@
* cmFindProgramCommand, cmFindPathCommand, cmFindLibraryCommand,
* cmFindFileCommand, and cmFindPackageCommand.
*/
-class cmFindCommon : public cmCommand
+class cmFindCommon
{
public:
- cmFindCommon();
- ~cmFindCommon() CM_OVERRIDE;
+ cmFindCommon(cmExecutionStatus& status);
+
+ void SetError(std::string const& e);
protected:
friend class cmSearchPath;
@@ -84,15 +87,15 @@ protected:
/** Compute final search path list (reroot + trailing slash). */
void ComputeFinalPaths();
- /** Decide whether to enable the PACKAGE_ROOT search entries. */
- void SelectDefaultNoPackageRootPath();
-
/** Compute the current default root path mode. */
void SelectDefaultRootPathMode();
/** Compute the current default bundle/framework search policy. */
void SelectDefaultMacMode();
+ /** Compute the current default search modes based on global variables. */
+ void SelectDefaultSearchModes();
+
// Path arguments prior to path manipulation routines
std::vector<std::string> UserHintsArgs;
std::vector<std::string> UserGuessArgs;
@@ -112,7 +115,7 @@ protected:
std::vector<std::string> SearchPathSuffixes;
- std::map<PathGroup, std::vector<PathLabel> > PathGroupLabelMap;
+ std::map<PathGroup, std::vector<PathLabel>> PathGroupLabelMap;
std::vector<PathGroup> PathGroupOrder;
std::map<std::string, PathLabel> PathLabelStringMap;
std::map<PathLabel, cmSearchPath> LabeledPaths;
@@ -127,6 +130,9 @@ protected:
bool SearchAppBundleFirst;
bool SearchAppBundleOnly;
bool SearchAppBundleLast;
+
+ cmMakefile* Makefile;
+ cmExecutionStatus& Status;
};
#endif
diff --git a/Source/cmFindFileCommand.cxx b/Source/cmFindFileCommand.cxx
index 9840c4f49..29a2bc49e 100644
--- a/Source/cmFindFileCommand.cxx
+++ b/Source/cmFindFileCommand.cxx
@@ -2,7 +2,16 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFindFileCommand.h"
-cmFindFileCommand::cmFindFileCommand()
+class cmExecutionStatus;
+
+cmFindFileCommand::cmFindFileCommand(cmExecutionStatus& status)
+ : cmFindPathCommand(status)
{
this->IncludeFileInPath = true;
}
+
+bool cmFindFile(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return cmFindFileCommand(status).InitialPass(args);
+}
diff --git a/Source/cmFindFileCommand.h b/Source/cmFindFileCommand.h
index bf57fecd3..7dc6e5569 100644
--- a/Source/cmFindFileCommand.h
+++ b/Source/cmFindFileCommand.h
@@ -3,11 +3,14 @@
#ifndef cmFindFileCommand_h
#define cmFindFileCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
#include "cmFindPathCommand.h"
-class cmCommand;
+class cmExecutionStatus;
/** \class cmFindFileCommand
* \brief Define a command to search for an executable program.
@@ -20,11 +23,10 @@ class cmCommand;
class cmFindFileCommand : public cmFindPathCommand
{
public:
- cmFindFileCommand();
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmFindFileCommand; }
+ cmFindFileCommand(cmExecutionStatus& status);
};
+bool cmFindFile(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+
#endif
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index a6b1a2155..20221b12e 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -2,29 +2,32 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFindLibraryCommand.h"
-#include "cmsys/RegularExpression.hxx"
#include <algorithm>
+#include <cstdio>
+#include <cstring>
#include <set>
-#include <stdio.h>
-#include <string.h>
+#include <utility>
+
+#include "cmsys/RegularExpression.hxx"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
class cmExecutionStatus;
-cmFindLibraryCommand::cmFindLibraryCommand()
+cmFindLibraryCommand::cmFindLibraryCommand(cmExecutionStatus& status)
+ : cmFindBase(status)
{
this->EnvironmentPath = "LIB";
this->NamesPerDirAllowed = true;
}
// cmFindLibraryCommand
-bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn,
- cmExecutionStatus&)
+bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn)
{
this->VariableDocumentation = "Path to a library.";
this->CMakePathName = "LIBRARY";
@@ -68,8 +71,8 @@ bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn,
this->AddArchitecturePaths("x32");
}
- std::string library = this->FindLibrary();
- if (library != "") {
+ std::string const library = this->FindLibrary();
+ if (!library.empty()) {
// Save the value in the cache
this->Makefile->AddCacheDefinition(this->VariableName, library.c_str(),
this->VariableDocumentation.c_str(),
@@ -87,9 +90,8 @@ void cmFindLibraryCommand::AddArchitecturePaths(const char* suffix)
{
std::vector<std::string> original;
original.swap(this->SearchPaths);
- for (std::vector<std::string>::const_iterator i = original.begin();
- i != original.end(); ++i) {
- this->AddArchitecturePath(*i, 0, suffix);
+ for (std::string const& o : original) {
+ this->AddArchitecturePath(o, 0, suffix);
}
}
@@ -151,7 +153,7 @@ void cmFindLibraryCommand::AddArchitecturePath(
if (use_dirX) {
dirX += "/";
- this->SearchPaths.push_back(dirX);
+ this->SearchPaths.push_back(std::move(dirX));
}
if (use_dir) {
@@ -190,7 +192,7 @@ struct cmFindLibraryHelper
std::string SuffixRegexStr;
// Keep track of the best library file found so far.
- typedef std::vector<std::string>::size_type size_type;
+ using size_type = std::vector<std::string>::size_type;
std::string BestPath;
// Support for OpenBSD shared library naming: lib<name>.so.<major>.<minor>
@@ -199,13 +201,9 @@ struct cmFindLibraryHelper
// Current names under consideration.
struct Name
{
- bool TryRaw;
+ bool TryRaw = false;
std::string Raw;
cmsys::RegularExpression Regex;
- Name()
- : TryRaw(false)
- {
- }
};
std::vector<Name> Names;
@@ -237,12 +235,12 @@ cmFindLibraryHelper::cmFindLibraryHelper(cmMakefile* mf)
this->GG = this->Makefile->GetGlobalGenerator();
// Collect the list of library name prefixes/suffixes to try.
- const char* prefixes_list =
+ std::string const& prefixes_list =
this->Makefile->GetRequiredDefinition("CMAKE_FIND_LIBRARY_PREFIXES");
- const char* suffixes_list =
+ std::string const& suffixes_list =
this->Makefile->GetRequiredDefinition("CMAKE_FIND_LIBRARY_SUFFIXES");
- cmSystemTools::ExpandListArgument(prefixes_list, this->Prefixes, true);
- cmSystemTools::ExpandListArgument(suffixes_list, this->Suffixes, true);
+ cmExpandList(prefixes_list, this->Prefixes, true);
+ cmExpandList(suffixes_list, this->Suffixes, true);
this->RegexFromList(this->PrefixRegexStr, this->Prefixes);
this->RegexFromList(this->SuffixRegexStr, this->Suffixes);
@@ -254,15 +252,14 @@ cmFindLibraryHelper::cmFindLibraryHelper(cmMakefile* mf)
void cmFindLibraryHelper::RegexFromLiteral(std::string& out,
std::string const& in)
{
- for (std::string::const_iterator ci = in.begin(); ci != in.end(); ++ci) {
- char ch = *ci;
+ for (char ch : in) {
if (ch == '[' || ch == ']' || ch == '(' || ch == ')' || ch == '\\' ||
ch == '.' || ch == '*' || ch == '+' || ch == '?' || ch == '-' ||
ch == '^' || ch == '$') {
out += "\\";
}
#if defined(_WIN32) || defined(__APPLE__)
- out += tolower(ch);
+ out += static_cast<char>(tolower(ch));
#else
out += ch;
#endif
@@ -276,23 +273,20 @@ void cmFindLibraryHelper::RegexFromList(std::string& out,
// else and the result can be checked after matching.
out += "(";
const char* sep = "";
- for (std::vector<std::string>::const_iterator si = in.begin();
- si != in.end(); ++si) {
+ for (std::string const& s : in) {
// Separate from previous item.
out += sep;
sep = "|";
// Append this item.
- this->RegexFromLiteral(out, *si);
+ this->RegexFromLiteral(out, s);
}
out += ")";
}
bool cmFindLibraryHelper::HasValidSuffix(std::string const& name)
{
- for (std::vector<std::string>::const_iterator si = this->Suffixes.begin();
- si != this->Suffixes.end(); ++si) {
- std::string suffix = *si;
+ for (std::string suffix : this->Suffixes) {
if (name.length() <= suffix.length()) {
continue;
}
@@ -319,8 +313,7 @@ void cmFindLibraryHelper::AddName(std::string const& name)
entry.Raw = name;
// Build a regular expression to match library names.
- std::string regex = "^";
- regex += this->PrefixRegexStr;
+ std::string regex = cmStrCat('^', this->PrefixRegexStr);
this->RegexFromLiteral(regex, name);
regex += this->SuffixRegexStr;
if (this->OpenBSD) {
@@ -328,7 +321,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)
@@ -339,9 +332,8 @@ void cmFindLibraryHelper::SetName(std::string const& name)
bool cmFindLibraryHelper::CheckDirectory(std::string const& path)
{
- for (std::vector<Name>::iterator i = this->Names.begin();
- i != this->Names.end(); ++i) {
- if (this->CheckDirectoryForName(path, *i)) {
+ for (Name& i : this->Names) {
+ if (this->CheckDirectoryForName(path, i)) {
return true;
}
}
@@ -357,9 +349,8 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
// one cannot tell just from the library name whether it is a static
// library or an import library).
if (name.TryRaw) {
- this->TestPath = path;
- this->TestPath += name.Raw;
- if (cmSystemTools::FileExists(this->TestPath.c_str(), true)) {
+ this->TestPath = cmStrCat(path, name.Raw);
+ if (cmSystemTools::FileExists(this->TestPath, true)) {
this->BestPath = cmSystemTools::CollapseFullPath(this->TestPath);
cmSystemTools::ConvertToUnixSlashes(this->BestPath);
return true;
@@ -376,17 +367,14 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
std::string dir = path;
cmSystemTools::ConvertToUnixSlashes(dir);
std::set<std::string> const& files = this->GG->GetDirectoryContent(dir);
- for (std::set<std::string>::const_iterator fi = files.begin();
- fi != files.end(); ++fi) {
- std::string const& origName = *fi;
+ for (std::string const& origName : files) {
#if defined(_WIN32) || defined(__APPLE__)
std::string testName = cmSystemTools::LowerCase(origName);
#else
std::string const& testName = origName;
#endif
if (name.Regex.find(testName)) {
- this->TestPath = path;
- this->TestPath += origName;
+ this->TestPath = cmStrCat(path, origName);
if (!cmSystemTools::FileIsDirectory(this->TestPath)) {
// This is a matching file. Check if it is better than the
// best name found so far. Earlier prefixes are preferred,
@@ -430,14 +418,12 @@ std::string cmFindLibraryCommand::FindNormalLibraryNamesPerDir()
{
// Search for all names in each directory.
cmFindLibraryHelper helper(this->Makefile);
- for (std::vector<std::string>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni) {
- helper.AddName(*ni);
+ for (std::string const& n : this->Names) {
+ helper.AddName(n);
}
// Search every directory.
- for (std::vector<std::string>::const_iterator p = this->SearchPaths.begin();
- p != this->SearchPaths.end(); ++p) {
- if (helper.CheckDirectory(*p)) {
+ for (std::string const& sp : this->SearchPaths) {
+ if (helper.CheckDirectory(sp)) {
return helper.BestPath;
}
}
@@ -449,16 +435,13 @@ std::string cmFindLibraryCommand::FindNormalLibraryDirsPerName()
{
// Search the entire path for each name.
cmFindLibraryHelper helper(this->Makefile);
- for (std::vector<std::string>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni) {
+ for (std::string const& n : this->Names) {
// Switch to searching for this name.
- helper.SetName(*ni);
+ helper.SetName(n);
// Search every directory.
- for (std::vector<std::string>::const_iterator p =
- this->SearchPaths.begin();
- p != this->SearchPaths.end(); ++p) {
- if (helper.CheckDirectory(*p)) {
+ for (std::string const& sp : this->SearchPaths) {
+ if (helper.CheckDirectory(sp)) {
return helper.BestPath;
}
}
@@ -479,13 +462,9 @@ std::string cmFindLibraryCommand::FindFrameworkLibraryNamesPerDir()
{
std::string fwPath;
// Search for all names in each search path.
- for (std::vector<std::string>::const_iterator di = this->SearchPaths.begin();
- di != this->SearchPaths.end(); ++di) {
- for (std::vector<std::string>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni) {
- fwPath = *di;
- fwPath += *ni;
- fwPath += ".framework";
+ for (std::string const& d : this->SearchPaths) {
+ for (std::string const& n : this->Names) {
+ fwPath = cmStrCat(d, n, ".framework");
if (cmSystemTools::FileIsDirectory(fwPath)) {
return cmSystemTools::CollapseFullPath(fwPath);
}
@@ -500,14 +479,9 @@ std::string cmFindLibraryCommand::FindFrameworkLibraryDirsPerName()
{
std::string fwPath;
// Search for each name in all search paths.
- for (std::vector<std::string>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni) {
- for (std::vector<std::string>::const_iterator di =
- this->SearchPaths.begin();
- di != this->SearchPaths.end(); ++di) {
- fwPath = *di;
- fwPath += *ni;
- fwPath += ".framework";
+ for (std::string const& n : this->Names) {
+ for (std::string const& d : this->SearchPaths) {
+ fwPath = cmStrCat(d, n, ".framework");
if (cmSystemTools::FileIsDirectory(fwPath)) {
return cmSystemTools::CollapseFullPath(fwPath);
}
@@ -517,3 +491,9 @@ std::string cmFindLibraryCommand::FindFrameworkLibraryDirsPerName()
// No framework found.
return "";
}
+
+bool cmFindLibrary(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return cmFindLibraryCommand(status).InitialPass(args);
+}
diff --git a/Source/cmFindLibraryCommand.h b/Source/cmFindLibraryCommand.h
index 9d38eab33..b2f71b3b8 100644
--- a/Source/cmFindLibraryCommand.h
+++ b/Source/cmFindLibraryCommand.h
@@ -3,14 +3,13 @@
#ifndef cmFindLibraryCommand_h
#define cmFindLibraryCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
#include "cmFindBase.h"
-class cmCommand;
class cmExecutionStatus;
/** \class cmFindLibraryCommand
@@ -23,18 +22,9 @@ class cmExecutionStatus;
class cmFindLibraryCommand : public cmFindBase
{
public:
- cmFindLibraryCommand();
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmFindLibraryCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
+ cmFindLibraryCommand(cmExecutionStatus& status);
+
+ bool InitialPass(std::vector<std::string> const& args);
protected:
void AddArchitecturePaths(const char* suffix);
@@ -52,4 +42,7 @@ private:
std::string FindFrameworkLibraryDirsPerName();
};
+bool cmFindLibrary(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+
#endif
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 7797700d6..2b11b62a2 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -2,34 +2,39 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFindPackageCommand.h"
-#include "cmSystemTools.h"
-#include "cmsys/Directory.hxx"
-#include "cmsys/FStream.hxx"
-#include "cmsys/Glob.hxx"
-#include "cmsys/RegularExpression.hxx"
-#include "cmsys/String.h"
#include <algorithm>
-#include <assert.h>
+#include <cassert>
+#include <cstdio>
+#include <cstring>
#include <deque>
#include <functional>
#include <iterator>
#include <sstream>
-#include <stdio.h>
-#include <string.h>
#include <utility>
+#include <cm/memory>
+
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/RegularExpression.hxx"
+#include "cmsys/String.h"
+
#include "cmAlgorithms.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmPolicies.h"
+#include "cmRange.h"
#include "cmSearchPath.h"
#include "cmState.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
#include "cmVersion.h"
-#include "cm_auto_ptr.hxx"
-#include "cmake.h"
#if defined(__HAIKU__)
-#include <FindDirectory.h>
-#include <StorageDefs.h>
+# include <FindDirectory.h>
+# include <StorageDefs.h>
#endif
class cmExecutionStatus;
@@ -81,7 +86,8 @@ void cmFindPackageCommand::Sort(std::vector<std::string>::iterator begin,
// else do not sort
}
-cmFindPackageCommand::cmFindPackageCommand()
+cmFindPackageCommand::cmFindPackageCommand(cmExecutionStatus& status)
+ : cmFindCommon(status)
{
this->CMakePathName = "PACKAGE";
this->Quiet = false;
@@ -94,6 +100,7 @@ cmFindPackageCommand::cmFindPackageCommand()
this->UseLib32Paths = false;
this->UseLib64Paths = false;
this->UseLibx32Paths = false;
+ this->UseRealPath = false;
this->PolicyScope = true;
this->VersionMajor = 0;
this->VersionMinor = 0;
@@ -110,6 +117,8 @@ cmFindPackageCommand::cmFindPackageCommand()
this->SortOrder = None;
this->SortDirection = Asc;
this->AppendSearchPathGroups();
+
+ this->DeprecatedFindModules["Qt"] = cmPolicies::CMP0084;
}
void cmFindPackageCommand::AppendSearchPathGroups()
@@ -136,8 +145,7 @@ void cmFindPackageCommand::AppendSearchPathGroups()
std::make_pair(PathLabel::SystemRegistry, cmSearchPath(this)));
}
-bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
{
if (args.empty()) {
this->SetError("called with incorrect number of arguments");
@@ -183,15 +191,31 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
}
// Check if User Package Registry should be disabled
- if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY")) {
+ // The `CMAKE_FIND_USE_PACKAGE_REGISTRY` has
+ // priority over the deprecated CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY
+ if (const char* def =
+ this->Makefile->GetDefinition("CMAKE_FIND_USE_PACKAGE_REGISTRY")) {
+ this->NoUserRegistry = !cmIsOn(def);
+ } else if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY")) {
this->NoUserRegistry = true;
}
// Check if System Package Registry should be disabled
- if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY")) {
+ // The `CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY` has
+ // priority over the deprecated CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY
+ if (const char* def = this->Makefile->GetDefinition(
+ "CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY")) {
+ this->NoSystemRegistry = !cmIsOn(def);
+ } else if (this->Makefile->IsOn(
+ "CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY")) {
this->NoSystemRegistry = true;
}
+ // Check whether we should resolve symlinks when finding packages
+ if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS")) {
+ this->UseRealPath = true;
+ }
+
// Check if Sorting should be enabled
if (const char* so =
this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_ORDER")) {
@@ -209,7 +233,8 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
this->SortDirection = strcmp(sd, "ASC") == 0 ? Asc : Dec;
}
- this->SelectDefaultNoPackageRootPath();
+ // Find what search path locations have been enabled/disable
+ this->SelectDefaultSearchModes();
// Find the current root path mode.
this->SelectDefaultRootPathMode();
@@ -225,7 +250,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
@@ -330,21 +355,19 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
} else if (doing == DoingConfigs) {
if (args[i].find_first_of(":/\\") != std::string::npos ||
cmSystemTools::GetFilenameLastExtension(args[i]) != ".cmake") {
- std::ostringstream e;
- e << "given CONFIGS option followed by invalid file name \"" << args[i]
- << "\". The names given must be file names without "
- << "a path and with a \".cmake\" extension.";
- this->SetError(e.str());
+ this->SetError(cmStrCat(
+ "given CONFIGS option followed by invalid file name \"", args[i],
+ "\". The names given must be file names without "
+ "a path and with a \".cmake\" extension."));
return false;
}
this->Configs.push_back(args[i]);
- } else if (!haveVersion && version.find(args[i].c_str())) {
+ } else if (!haveVersion && version.find(args[i])) {
haveVersion = true;
this->Version = args[i];
} else {
- std::ostringstream e;
- e << "called with invalid argument \"" << args[i] << "\"";
- this->SetError(e.str());
+ this->SetError(
+ cmStrCat("called with invalid argument \"", args[i], "\""));
return false;
}
}
@@ -354,10 +377,10 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
optionalComponents.begin(), optionalComponents.end(),
std::back_inserter(doubledComponents));
if (!doubledComponents.empty()) {
- std::ostringstream e;
- e << "called with components that are both required and optional:\n";
- e << cmWrap(" ", doubledComponents, "", "\n") << "\n";
- this->SetError(e.str());
+ this->SetError(
+ cmStrCat("called with components that are both required and "
+ "optional:\n",
+ cmWrap(" ", doubledComponents, "", "\n"), "\n"));
return false;
}
@@ -367,14 +390,12 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
if (!this->UseFindModules && !this->UseConfigFiles) {
std::ostringstream e;
e << "given options exclusive to Module mode:\n";
- for (std::set<unsigned int>::const_iterator si = moduleArgs.begin();
- si != moduleArgs.end(); ++si) {
- e << " " << args[*si] << "\n";
+ for (unsigned int si : moduleArgs) {
+ e << " " << args[si] << "\n";
}
e << "and options exclusive to Config mode:\n";
- for (std::set<unsigned int>::const_iterator si = configArgs.begin();
- si != configArgs.end(); ++si) {
- e << " " << args[*si] << "\n";
+ for (unsigned int si : configArgs) {
+ e << " " << args[si] << "\n";
}
e << "The options are incompatible.";
this->SetError(e.str());
@@ -385,25 +406,23 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
if (this->Version.empty() && this->VersionExact) {
this->VersionExact = false;
this->Makefile->IssueMessage(
- cmake::AUTHOR_WARNING, "Ignoring EXACT since no version is requested.");
+ MessageType::AUTHOR_WARNING,
+ "Ignoring EXACT since no version is requested.");
}
if (this->Version.empty() || components.empty()) {
// Check whether we are recursing inside "Find<name>.cmake" within
// another find_package(<name>) call.
- std::string mod = this->Name;
- mod += "_FIND_MODULE";
+ std::string mod = cmStrCat(this->Name, "_FIND_MODULE");
if (this->Makefile->IsOn(mod)) {
if (this->Version.empty()) {
// Get version information from the outer call if necessary.
// Requested version string.
- std::string ver = this->Name;
- ver += "_FIND_VERSION";
+ std::string ver = cmStrCat(this->Name, "_FIND_VERSION");
this->Version = this->Makefile->GetSafeDefinition(ver);
// Whether an exact version is required.
- std::string exact = this->Name;
- exact += "_FIND_VERSION_EXACT";
+ std::string exact = cmStrCat(this->Name, "_FIND_VERSION_EXACT");
this->VersionExact = this->Makefile->IsOn(exact);
}
if (components.empty()) {
@@ -441,75 +460,137 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
}
}
- std::string disableFindPackageVar = "CMAKE_DISABLE_FIND_PACKAGE_";
- disableFindPackageVar += this->Name;
+ std::string disableFindPackageVar =
+ cmStrCat("CMAKE_DISABLE_FIND_PACKAGE_", this->Name);
if (this->Makefile->IsOn(disableFindPackageVar)) {
if (this->Required) {
- std::ostringstream e;
- e << "for module " << this->Name << " called with REQUIRED, but "
- << disableFindPackageVar
- << " is enabled. A REQUIRED package cannot be disabled.";
- this->SetError(e.str());
+ this->SetError(
+ cmStrCat("for module ", this->Name, " called with REQUIRED, but ",
+ disableFindPackageVar,
+ " is enabled. A REQUIRED package cannot be disabled."));
return false;
}
return true;
}
+ {
+ // Allocate a PACKAGE_ROOT_PATH for the current find_package call.
+ this->Makefile->FindPackageRootPathStack.emplace_back();
+ std::vector<std::string>& rootPaths =
+ this->Makefile->FindPackageRootPathStack.back();
+
+ // Add root paths from <PackageName>_ROOT CMake and environment variables,
+ // subject to CMP0074.
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0074)) {
+ case cmPolicies::WARN:
+ this->Makefile->MaybeWarnCMP0074(this->Name);
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // OLD behavior is to ignore the <pkg>_ROOT variables.
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0074));
+ break;
+ case cmPolicies::NEW: {
+ // NEW behavior is to honor the <pkg>_ROOT variables.
+ std::string const rootVar = this->Name + "_ROOT";
+ if (const char* pkgRoot = this->Makefile->GetDefinition(rootVar)) {
+ cmExpandList(pkgRoot, rootPaths, false);
+ }
+ cmSystemTools::GetPath(rootPaths, rootVar.c_str());
+ } break;
+ }
+ }
+
this->SetModuleVariables(components);
- // See if there is a Find<package>.cmake module.
- if (this->UseFindModules) {
- bool foundModule = false;
- if (!this->FindModule(foundModule)) {
- this->AppendSuccessInformation();
- return false;
+ // See if there is a Find<PackageName>.cmake module.
+ bool loadedPackage = false;
+ if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG")) {
+ if (this->UseConfigFiles && this->FindPackageUsingConfigMode()) {
+ loadedPackage = true;
+ } else {
+ if (this->FindPackageUsingModuleMode()) {
+ loadedPackage = true;
+ } else {
+ // The package was not loaded. Report errors.
+ if (HandlePackageMode(HandlePackageModeType::Module)) {
+ loadedPackage = true;
+ }
+ }
}
- if (foundModule) {
- this->AppendSuccessInformation();
- return true;
+ } else {
+ if (this->UseFindModules && this->FindPackageUsingModuleMode()) {
+ loadedPackage = true;
+ } else {
+ // Handle CMAKE_FIND_PACKAGE_WARN_NO_MODULE (warn when CONFIG mode is
+ // implicitly assumed)
+ if (this->UseFindModules && this->UseConfigFiles &&
+ this->Makefile->IsOn("CMAKE_FIND_PACKAGE_WARN_NO_MODULE")) {
+ std::ostringstream aw;
+ if (this->RequiredCMakeVersion >= CMake_VERSION_ENCODE(2, 8, 8)) {
+ aw << "find_package called without either MODULE or CONFIG option "
+ "and "
+ "no Find"
+ << this->Name
+ << ".cmake module is in CMAKE_MODULE_PATH. "
+ "Add MODULE to exclusively request Module mode and fail if "
+ "Find"
+ << this->Name
+ << ".cmake is missing. "
+ "Add CONFIG to exclusively request Config mode and search for "
+ "a "
+ "package configuration file provided by "
+ << this->Name << " (" << this->Name << "Config.cmake or "
+ << cmSystemTools::LowerCase(this->Name) << "-config.cmake). ";
+ } else {
+ aw << "find_package called without NO_MODULE option and no "
+ "Find"
+ << this->Name
+ << ".cmake module is in CMAKE_MODULE_PATH. "
+ "Add NO_MODULE to exclusively request Config mode and search "
+ "for a "
+ "package configuration file provided by "
+ << this->Name << " (" << this->Name << "Config.cmake or "
+ << cmSystemTools::LowerCase(this->Name)
+ << "-config.cmake). "
+ "Otherwise make Find"
+ << this->Name
+ << ".cmake available in "
+ "CMAKE_MODULE_PATH.";
+ }
+ aw << "\n"
+ "(Variable CMAKE_FIND_PACKAGE_WARN_NO_MODULE enabled this "
+ "warning.)";
+ this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, aw.str());
+ }
+
+ if (this->FindPackageUsingConfigMode()) {
+ loadedPackage = true;
+ }
}
}
- if (this->UseFindModules && this->UseConfigFiles &&
- this->Makefile->IsOn("CMAKE_FIND_PACKAGE_WARN_NO_MODULE")) {
- std::ostringstream aw;
- if (this->RequiredCMakeVersion >= CMake_VERSION_ENCODE(2, 8, 8)) {
- aw << "find_package called without either MODULE or CONFIG option and "
- "no Find"
- << this->Name
- << ".cmake module is in CMAKE_MODULE_PATH. "
- "Add MODULE to exclusively request Module mode and fail if "
- "Find"
- << this->Name
- << ".cmake is missing. "
- "Add CONFIG to exclusively request Config mode and search for a "
- "package configuration file provided by "
- << this->Name << " (" << this->Name << "Config.cmake or "
- << cmSystemTools::LowerCase(this->Name) << "-config.cmake). ";
- } else {
- aw
- << "find_package called without NO_MODULE option and no "
- "Find"
- << this->Name
- << ".cmake module is in CMAKE_MODULE_PATH. "
- "Add NO_MODULE to exclusively request Config mode and search for a "
- "package configuration file provided by "
- << this->Name << " (" << this->Name << "Config.cmake or "
- << cmSystemTools::LowerCase(this->Name) << "-config.cmake). "
- "Otherwise make Find"
- << this->Name << ".cmake available in "
- "CMAKE_MODULE_PATH.";
- }
- aw << "\n"
- "(Variable CMAKE_FIND_PACKAGE_WARN_NO_MODULE enabled this warning.)";
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, aw.str());
- }
-
- // No find module. Assume the project has a CMake config file. Use
- // a <package>_DIR cache variable to locate it.
- this->Variable = this->Name;
- this->Variable += "_DIR";
+ this->AppendSuccessInformation();
+ return loadedPackage;
+}
+
+bool cmFindPackageCommand::FindPackageUsingModuleMode()
+{
+ bool foundModule = false;
+ if (!this->FindModule(foundModule)) {
+ return false;
+ }
+ return foundModule;
+}
+
+bool cmFindPackageCommand::FindPackageUsingConfigMode()
+{
+ this->Variable = cmStrCat(this->Name, "_DIR");
// Add the default name.
if (this->Names.empty()) {
@@ -518,15 +599,12 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
// Add the default configs.
if (this->Configs.empty()) {
- for (std::vector<std::string>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni) {
- std::string config = *ni;
- config += "Config.cmake";
+ for (std::string const& n : this->Names) {
+ std::string config = cmStrCat(n, "Config.cmake");
this->Configs.push_back(config);
- config = cmSystemTools::LowerCase(*ni);
- config += "-config.cmake";
- this->Configs.push_back(config);
+ config = cmStrCat(cmSystemTools::LowerCase(n), "-config.cmake");
+ this->Configs.push_back(std::move(config));
}
}
@@ -540,9 +618,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
this->IgnoredPaths.insert(ignored.begin(), ignored.end());
// Find and load the package.
- bool result = this->HandlePackageMode();
- this->AppendSuccessInformation();
- return result;
+ return this->HandlePackageMode(HandlePackageModeType::Config);
}
void cmFindPackageCommand::SetModuleVariables(const std::string& components)
@@ -556,24 +632,21 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components)
if (this->Quiet) {
// Tell the module that is about to be read that it should find
// quietly.
- std::string quietly = this->Name;
- quietly += "_FIND_QUIETLY";
+ std::string quietly = cmStrCat(this->Name, "_FIND_QUIETLY");
this->AddFindDefinition(quietly, "1");
}
if (this->Required) {
// Tell the module that is about to be read that it should report
// a fatal error if the package is not found.
- std::string req = this->Name;
- req += "_FIND_REQUIRED";
+ std::string req = cmStrCat(this->Name, "_FIND_REQUIRED");
this->AddFindDefinition(req, "1");
}
if (!this->Version.empty()) {
// Tell the module that is about to be read what version of the
// package has been requested.
- std::string ver = this->Name;
- ver += "_FIND_VERSION";
+ std::string ver = cmStrCat(this->Name, "_FIND_VERSION");
this->AddFindDefinition(ver, this->Version.c_str());
char buf[64];
sprintf(buf, "%u", this->VersionMajor);
@@ -588,13 +661,9 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components)
this->AddFindDefinition(ver + "_COUNT", buf);
// Tell the module whether an exact version has been requested.
- std::string exact = this->Name;
- exact += "_FIND_VERSION_EXACT";
+ std::string exact = cmStrCat(this->Name, "_FIND_VERSION_EXACT");
this->AddFindDefinition(exact, this->VersionExact ? "1" : "0");
}
-
- // Push on to the pacakge stack
- this->Makefile->FindPackageModuleStack.push_back(this->Name);
}
void cmFindPackageCommand::AddFindDefinition(const std::string& var,
@@ -606,66 +675,81 @@ void cmFindPackageCommand::AddFindDefinition(const std::string& var,
} else {
this->OriginalDefs[var].exists = false;
}
- this->Makefile->AddDefinition(var, val);
+ if (val) {
+ this->Makefile->AddDefinition(var, val);
+ }
}
void cmFindPackageCommand::RestoreFindDefinitions()
{
- for (std::map<std::string, OriginalDef>::iterator i =
- this->OriginalDefs.begin();
- i != this->OriginalDefs.end(); ++i) {
- OriginalDef const& od = i->second;
+ for (auto const& i : this->OriginalDefs) {
+ OriginalDef const& od = i.second;
if (od.exists) {
- this->Makefile->AddDefinition(i->first, od.value.c_str());
+ this->Makefile->AddDefinition(i.first, od.value);
} else {
- this->Makefile->RemoveDefinition(i->first);
+ this->Makefile->RemoveDefinition(i.first);
}
}
}
bool cmFindPackageCommand::FindModule(bool& found)
{
- std::string module = "Find";
- module += this->Name;
- module += ".cmake";
- std::string mfile = this->Makefile->GetModulesFile(module.c_str());
+ std::string module = cmStrCat("Find", this->Name, ".cmake");
+ bool system = false;
+ std::string mfile = this->Makefile->GetModulesFile(module, system);
if (!mfile.empty()) {
+ if (system) {
+ auto it = this->DeprecatedFindModules.find(this->Name);
+ if (it != this->DeprecatedFindModules.end()) {
+ cmPolicies::PolicyStatus status =
+ this->Makefile->GetPolicyStatus(it->second);
+ switch (status) {
+ case cmPolicies::WARN: {
+ this->Makefile->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(cmPolicies::GetPolicyWarning(it->second), "\n"));
+ CM_FALLTHROUGH;
+ }
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ return true;
+ }
+ }
+ }
+
// Load the module we found, and set "<name>_FIND_MODULE" to true
// while inside it.
found = true;
- std::string var = this->Name;
- var += "_FIND_MODULE";
+ std::string var = cmStrCat(this->Name, "_FIND_MODULE");
this->Makefile->AddDefinition(var, "1");
- bool result = this->ReadListFile(mfile.c_str(), DoPolicyScope);
+ bool result = this->ReadListFile(mfile, DoPolicyScope);
this->Makefile->RemoveDefinition(var);
return result;
}
return true;
}
-bool cmFindPackageCommand::HandlePackageMode()
+bool cmFindPackageCommand::HandlePackageMode(
+ HandlePackageModeType handlePackageModeType)
{
this->ConsideredConfigs.clear();
- // Support old capitalization behavior.
- std::string upperDir = cmSystemTools::UpperCase(this->Name);
- std::string upperFound = cmSystemTools::UpperCase(this->Name);
- upperDir += "_DIR";
- upperFound += "_FOUND";
-
// Try to find the config file.
const char* def = this->Makefile->GetDefinition(this->Variable);
// Try to load the config file if the directory is known
bool fileFound = false;
if (this->UseConfigFiles) {
- if (!cmSystemTools::IsOff(def)) {
+ if (!cmIsOff(def)) {
// Get the directory from the variable value.
std::string dir = def;
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;
}
@@ -679,22 +763,21 @@ bool cmFindPackageCommand::HandlePackageMode()
}
// Search for the config file if it is not already found.
- if (cmSystemTools::IsOff(def) || !fileFound) {
+ if (cmIsOff(def) || !fileFound) {
fileFound = this->FindConfig();
}
// Sanity check.
if (fileFound && this->FileFound.empty()) {
this->Makefile->IssueMessage(
- cmake::INTERNAL_ERROR, "fileFound is true but FileFound is empty!");
+ MessageType::INTERNAL_ERROR,
+ "fileFound is true but FileFound is empty!");
fileFound = false;
}
}
- std::string foundVar = this->Name;
- foundVar += "_FOUND";
- std::string notFoundMessageVar = this->Name;
- notFoundMessageVar += "_NOT_FOUND_MESSAGE";
+ std::string foundVar = cmStrCat(this->Name, "_FOUND");
+ std::string notFoundMessageVar = cmStrCat(this->Name, "_NOT_FOUND_MESSAGE");
std::string notFoundMessage;
// If the directory for the config file was found, try to read the file.
@@ -718,7 +801,7 @@ bool cmFindPackageCommand::HandlePackageMode()
this->StoreVersionFound();
// Parse the configuration file.
- if (this->ReadListFile(this->FileFound.c_str(), DoPolicyScope)) {
+ if (this->ReadListFile(this->FileFound, DoPolicyScope)) {
// The package has been found.
found = true;
@@ -737,12 +820,20 @@ bool cmFindPackageCommand::HandlePackageMode()
}
}
+ if (this->UseFindModules && !found &&
+ handlePackageModeType == HandlePackageModeType::Config &&
+ this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG")) {
+ // Config mode failed. Allow Module case.
+ result = false;
+ }
+
// package not found
if (result && !found) {
// warn if package required or neither quiet nor in config mode
if (this->Required ||
- !(this->Quiet || (this->UseConfigFiles && !this->UseFindModules &&
- this->ConsideredConfigs.empty()))) {
+ !(this->Quiet ||
+ (this->UseConfigFiles && !this->UseFindModules &&
+ this->ConsideredConfigs.empty()))) {
// The variable is not set.
std::ostringstream e;
std::ostringstream aw;
@@ -760,25 +851,23 @@ bool cmFindPackageCommand::HandlePackageMode()
// If there are files in ConsideredConfigs, it means that FooConfig.cmake
// have been found, but they didn't have appropriate versions.
else if (!this->ConsideredConfigs.empty()) {
- std::vector<ConfigFileInfo>::const_iterator duplicate_end =
- cmRemoveDuplicates(this->ConsideredConfigs);
+ auto duplicate_end = cmRemoveDuplicates(this->ConsideredConfigs);
e << "Could not find a configuration file for package \"" << this->Name
<< "\" that "
<< (this->VersionExact ? "exactly matches" : "is compatible with")
<< " requested version \"" << this->Version << "\".\n"
<< "The following configuration files were considered but not "
"accepted:\n";
- for (std::vector<ConfigFileInfo>::const_iterator i =
- this->ConsideredConfigs.begin();
- i != duplicate_end; ++i) {
- e << " " << i->filename << ", version: " << i->version << "\n";
+
+ for (ConfigFileInfo const& info :
+ cmMakeRange(this->ConsideredConfigs.cbegin(), duplicate_end)) {
+ e << " " << info.filename << ", version: " << info.version << "\n";
}
} else {
std::string requestedVersionString;
if (!this->Version.empty()) {
- requestedVersionString = " (requested version ";
- requestedVersionString += this->Version;
- requestedVersionString += ")";
+ requestedVersionString =
+ cmStrCat(" (requested version ", this->Version, ')');
}
if (this->UseConfigFiles) {
@@ -787,8 +876,9 @@ bool cmFindPackageCommand::HandlePackageMode()
<< ".cmake\" in "
"CMAKE_MODULE_PATH this project has asked CMake to find a "
"package configuration file provided by \""
- << this->Name << "\", "
- "but CMake did not find one.\n";
+ << this->Name
+ << "\", "
+ "but CMake did not find one.\n";
}
if (this->Configs.size() == 1) {
@@ -809,8 +899,9 @@ bool cmFindPackageCommand::HandlePackageMode()
<< "\" to a "
"directory containing one of the above files. "
"If \""
- << this->Name << "\" provides a separate development "
- "package or SDK, be sure it has been installed.";
+ << this->Name
+ << "\" provides a separate development "
+ "package or SDK, be sure it has been installed.";
} else // if(!this->UseFindModules && !this->UseConfigFiles)
{
e << "No \"Find" << this->Name << ".cmake\" found in "
@@ -834,22 +925,23 @@ bool cmFindPackageCommand::HandlePackageMode()
}
}
- this->Makefile->IssueMessage(
- this->Required ? cmake::FATAL_ERROR : cmake::WARNING, e.str());
+ this->Makefile->IssueMessage(this->Required ? MessageType::FATAL_ERROR
+ : MessageType::WARNING,
+ e.str());
if (this->Required) {
cmSystemTools::SetFatalErrorOccured();
}
if (!aw.str().empty()) {
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, aw.str());
+ this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, aw.str());
}
}
// output result if in config mode but not in quiet mode
else if (!this->Quiet) {
- std::ostringstream aw;
- aw << "Could NOT find " << this->Name << " (missing: " << this->Name
- << "_DIR)";
- this->Makefile->DisplayStatus(aw.str().c_str(), -1);
+ this->Makefile->DisplayStatus(cmStrCat("Could NOT find ", this->Name,
+ " (missing: ", this->Name,
+ "_DIR)"),
+ -1);
}
}
@@ -857,38 +949,33 @@ bool cmFindPackageCommand::HandlePackageMode()
this->Makefile->AddDefinition(foundVar, found ? "1" : "0");
// Set a variable naming the configuration file that was found.
- std::string fileVar = this->Name;
- fileVar += "_CONFIG";
+ std::string fileVar = cmStrCat(this->Name, "_CONFIG");
if (found) {
- this->Makefile->AddDefinition(fileVar, this->FileFound.c_str());
+ this->Makefile->AddDefinition(fileVar, this->FileFound);
} else {
this->Makefile->RemoveDefinition(fileVar);
}
- std::string consideredConfigsVar = this->Name;
- consideredConfigsVar += "_CONSIDERED_CONFIGS";
- std::string consideredVersionsVar = this->Name;
- consideredVersionsVar += "_CONSIDERED_VERSIONS";
+ std::string consideredConfigsVar =
+ cmStrCat(this->Name, "_CONSIDERED_CONFIGS");
+ std::string consideredVersionsVar =
+ cmStrCat(this->Name, "_CONSIDERED_VERSIONS");
std::string consideredConfigFiles;
std::string consideredVersions;
const char* sep = "";
- for (std::vector<ConfigFileInfo>::const_iterator i =
- this->ConsideredConfigs.begin();
- i != this->ConsideredConfigs.end(); ++i) {
+ for (ConfigFileInfo const& i : this->ConsideredConfigs) {
consideredConfigFiles += sep;
consideredVersions += sep;
- consideredConfigFiles += i->filename;
- consideredVersions += i->version;
+ consideredConfigFiles += i.filename;
+ consideredVersions += i.version;
sep = ";";
}
- this->Makefile->AddDefinition(consideredConfigsVar,
- consideredConfigFiles.c_str());
+ this->Makefile->AddDefinition(consideredConfigsVar, consideredConfigFiles);
- this->Makefile->AddDefinition(consideredVersionsVar,
- consideredVersions.c_str());
+ this->Makefile->AddDefinition(consideredVersionsVar, consideredVersions);
return result;
}
@@ -934,9 +1021,8 @@ bool cmFindPackageCommand::FindConfig()
init = this->Variable + "-NOTFOUND";
}
std::string help =
- "The directory containing a CMake configuration file for ";
- help += this->Name;
- help += ".";
+ cmStrCat("The directory containing a CMake configuration file for ",
+ this->Name, '.');
// We force the value since we do not get here if it was already set.
this->Makefile->AddCacheDefinition(this->Variable, init.c_str(),
help.c_str(), cmStateEnums::PATH, true);
@@ -946,9 +1032,8 @@ bool cmFindPackageCommand::FindConfig()
bool cmFindPackageCommand::FindPrefixedConfig()
{
std::vector<std::string> const& prefixes = this->SearchPaths;
- for (std::vector<std::string>::const_iterator pi = prefixes.begin();
- pi != prefixes.end(); ++pi) {
- if (this->SearchPrefix(*pi)) {
+ for (std::string const& p : prefixes) {
+ if (this->SearchPrefix(p)) {
return true;
}
}
@@ -958,9 +1043,8 @@ bool cmFindPackageCommand::FindPrefixedConfig()
bool cmFindPackageCommand::FindFrameworkConfig()
{
std::vector<std::string> const& prefixes = this->SearchPaths;
- for (std::vector<std::string>::const_iterator i = prefixes.begin();
- i != prefixes.end(); ++i) {
- if (this->SearchFrameworkPrefix(*i)) {
+ for (std::string const& p : prefixes) {
+ if (this->SearchFrameworkPrefix(p)) {
return true;
}
}
@@ -970,24 +1054,22 @@ bool cmFindPackageCommand::FindFrameworkConfig()
bool cmFindPackageCommand::FindAppBundleConfig()
{
std::vector<std::string> const& prefixes = this->SearchPaths;
- for (std::vector<std::string>::const_iterator i = prefixes.begin();
- i != prefixes.end(); ++i) {
- if (this->SearchAppBundlePrefix(*i)) {
+ for (std::string const& p : prefixes) {
+ if (this->SearchAppBundlePrefix(p)) {
return true;
}
}
return false;
}
-bool cmFindPackageCommand::ReadListFile(const char* f, PolicyScopeRule psr)
+bool cmFindPackageCommand::ReadListFile(const std::string& f,
+ PolicyScopeRule psr)
{
const bool noPolicyScope = !this->PolicyScope || psr == NoPolicyScope;
if (this->Makefile->ReadDependentFile(f, noPolicyScope)) {
return true;
}
- std::string e = "Error reading CMake code from \"";
- e += f;
- e += "\".";
+ std::string e = cmStrCat("Error reading CMake code from \"", f, "\".");
this->SetError(e);
return false;
}
@@ -1000,8 +1082,8 @@ void cmFindPackageCommand::AppendToFoundProperty(bool found)
if (foundProp && *foundProp) {
std::string tmp = foundProp;
- cmSystemTools::ExpandListArgument(tmp, foundContents, false);
- std::vector<std::string>::iterator nameIt =
+ cmExpandList(tmp, foundContents, false);
+ auto nameIt =
std::find(foundContents.begin(), foundContents.end(), this->Name);
if (nameIt != foundContents.end()) {
foundContents.erase(nameIt);
@@ -1014,8 +1096,8 @@ void cmFindPackageCommand::AppendToFoundProperty(bool found)
if (notFoundProp && *notFoundProp) {
std::string tmp = notFoundProp;
- cmSystemTools::ExpandListArgument(tmp, notFoundContents, false);
- std::vector<std::string>::iterator nameIt =
+ cmExpandList(tmp, notFoundContents, false);
+ auto nameIt =
std::find(notFoundContents.begin(), notFoundContents.end(), this->Name);
if (nameIt != notFoundContents.end()) {
notFoundContents.erase(nameIt);
@@ -1039,45 +1121,38 @@ void cmFindPackageCommand::AppendToFoundProperty(bool found)
void cmFindPackageCommand::AppendSuccessInformation()
{
{
- std::string transitivePropName = "_CMAKE_";
- transitivePropName += this->Name + "_TRANSITIVE_DEPENDENCY";
+ std::string transitivePropName =
+ cmStrCat("_CMAKE_", this->Name, "_TRANSITIVE_DEPENDENCY");
this->Makefile->GetState()->SetGlobalProperty(transitivePropName, "False");
}
- std::string found = this->Name;
- found += "_FOUND";
+ std::string found = cmStrCat(this->Name, "_FOUND");
std::string upperFound = cmSystemTools::UpperCase(found);
const char* upperResult = this->Makefile->GetDefinition(upperFound);
const char* result = this->Makefile->GetDefinition(found);
- bool packageFound =
- ((cmSystemTools::IsOn(result)) || (cmSystemTools::IsOn(upperResult)));
+ bool packageFound = ((cmIsOn(result)) || (cmIsOn(upperResult)));
this->AppendToFoundProperty(packageFound);
// Record whether the find was quiet or not, so this can be used
// e.g. in FeatureSummary.cmake
- std::string quietInfoPropName = "_CMAKE_";
- quietInfoPropName += this->Name;
- quietInfoPropName += "_QUIET";
+ std::string quietInfoPropName = cmStrCat("_CMAKE_", this->Name, "_QUIET");
this->Makefile->GetState()->SetGlobalProperty(
quietInfoPropName, this->Quiet ? "TRUE" : "FALSE");
// set a global property to record the required version of this package
- std::string versionInfoPropName = "_CMAKE_";
- versionInfoPropName += this->Name;
- versionInfoPropName += "_REQUIRED_VERSION";
+ std::string versionInfoPropName =
+ cmStrCat("_CMAKE_", this->Name, "_REQUIRED_VERSION");
std::string versionInfo;
if (!this->Version.empty()) {
- versionInfo = this->VersionExact ? "==" : ">=";
- versionInfo += " ";
- versionInfo += this->Version;
+ versionInfo =
+ cmStrCat(this->VersionExact ? "==" : ">=", ' ', this->Version);
}
this->Makefile->GetState()->SetGlobalProperty(versionInfoPropName,
versionInfo.c_str());
if (this->Required) {
- std::string requiredInfoPropName = "_CMAKE_";
- requiredInfoPropName += this->Name;
- requiredInfoPropName += "_TYPE";
+ std::string requiredInfoPropName =
+ cmStrCat("_CMAKE_", this->Name, "_TYPE");
this->Makefile->GetState()->SetGlobalProperty(requiredInfoPropName,
"REQUIRED");
}
@@ -1086,7 +1161,7 @@ void cmFindPackageCommand::AppendSuccessInformation()
this->RestoreFindDefinitions();
// Pop the package stack
- this->Makefile->FindPackageModuleStack.pop_back();
+ this->Makefile->FindPackageRootPathStack.pop_back();
}
void cmFindPackageCommand::ComputePrefixes()
@@ -1126,16 +1201,13 @@ void cmFindPackageCommand::FillPrefixesPackageRoot()
{
cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRoot];
- // Add package specific search prefixes
- // NOTE: This should be using const_reverse_iterator but HP aCC and
- // Oracle sunCC both currently have standard library issues
- // with the reverse iterator APIs.
- for (std::deque<std::string>::reverse_iterator pkg =
- this->Makefile->FindPackageModuleStack.rbegin();
- pkg != this->Makefile->FindPackageModuleStack.rend(); ++pkg) {
- std::string varName = *pkg + "_ROOT";
- paths.AddCMakePath(varName);
- paths.AddEnvPath(varName);
+ // Add the PACKAGE_ROOT_PATH from each enclosing find_package call.
+ for (auto pkgPaths = this->Makefile->FindPackageRootPathStack.rbegin();
+ pkgPaths != this->Makefile->FindPackageRootPathStack.rend();
+ ++pkgPaths) {
+ for (std::string const& path : *pkgPaths) {
+ paths.AddPath(path);
+ }
}
}
@@ -1171,14 +1243,12 @@ void cmFindPackageCommand::FillPrefixesSystemEnvironment()
// working directory.
std::vector<std::string> tmp;
cmSystemTools::GetPath(tmp);
- for (std::vector<std::string>::iterator i = tmp.begin(); i != tmp.end();
- ++i) {
+ for (std::string const& i : tmp) {
// If the path is a PREFIX/bin case then add its parent instead.
- if ((cmHasLiteralSuffix(*i, "/bin")) ||
- (cmHasLiteralSuffix(*i, "/sbin"))) {
- paths.AddPath(cmSystemTools::GetFilenamePath(*i));
+ if ((cmHasLiteralSuffix(i, "/bin")) || (cmHasLiteralSuffix(i, "/sbin"))) {
+ paths.AddPath(cmSystemTools::GetFilenamePath(i));
} else {
- paths.AddPath(*i);
+ paths.AddPath(i);
}
}
}
@@ -1191,9 +1261,7 @@ void cmFindPackageCommand::FillPrefixesUserRegistry()
char dir[B_PATH_NAME_LENGTH];
if (find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, dir, sizeof(dir)) ==
B_OK) {
- std::string fname = dir;
- fname += "/cmake/packages/";
- fname += Name;
+ std::string fname = cmStrCat(dir, "/cmake/packages/", Name);
this->LoadPackageRegistryDir(fname,
this->LabeledPaths[PathLabel::UserRegistry]);
}
@@ -1220,14 +1288,14 @@ void cmFindPackageCommand::FillPrefixesSystemRegistry()
}
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <windows.h>
+# include <windows.h>
// http://msdn.microsoft.com/en-us/library/aa384253%28v=vs.85%29.aspx
-#if !defined(KEY_WOW64_32KEY)
-#define KEY_WOW64_32KEY 0x0200
-#endif
-#if !defined(KEY_WOW64_64KEY)
-#define KEY_WOW64_64KEY 0x0100
-#endif
+# if !defined(KEY_WOW64_32KEY)
+# define KEY_WOW64_32KEY 0x0200
+# endif
+# if !defined(KEY_WOW64_64KEY)
+# define KEY_WOW64_64KEY 0x0100
+# endif
void cmFindPackageCommand::LoadPackageRegistryWinUser()
{
// HKEY_CURRENT_USER\\Software shares 32-bit and 64-bit views.
@@ -1296,9 +1364,8 @@ void cmFindPackageCommand::LoadPackageRegistryWin(bool user, unsigned int view,
if (user && !bad.empty() &&
RegOpenKeyExW(HKEY_CURRENT_USER, key.c_str(), 0, KEY_SET_VALUE | view,
&hKey) == ERROR_SUCCESS) {
- for (std::set<std::wstring>::const_iterator vi = bad.begin();
- vi != bad.end(); ++vi) {
- RegDeleteValueW(hKey, vi->c_str());
+ for (std::wstring const& v : bad) {
+ RegDeleteValueW(hKey, v.c_str());
}
RegCloseKey(hKey);
}
@@ -1319,7 +1386,10 @@ public:
cmSystemTools::RemoveFile(this->File);
}
}
- void Release() { this->File = CM_NULLPTR; }
+ cmFindPackageCommandHoldFile(const cmFindPackageCommandHoldFile&) = delete;
+ cmFindPackageCommandHoldFile& operator=(
+ const cmFindPackageCommandHoldFile&) = delete;
+ void Release() { this->File = nullptr; }
};
void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir,
@@ -1332,9 +1402,7 @@ void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir,
std::string fname;
for (unsigned long i = 0; i < files.GetNumberOfFiles(); ++i) {
- fname = dir;
- fname += "/";
- fname += files.GetFile(i);
+ fname = cmStrCat(dir, '/', files.GetFile(i));
if (!cmSystemTools::FileIsDirectory(fname)) {
// Hold this file hostage until it behaves.
@@ -1359,10 +1427,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));
@@ -1395,10 +1463,8 @@ void cmFindPackageCommand::FillPrefixesUserGuess()
{
cmSearchPath& paths = this->LabeledPaths[PathLabel::Guess];
- for (std::vector<std::string>::const_iterator p =
- this->UserGuessArgs.begin();
- p != this->UserGuessArgs.end(); ++p) {
- paths.AddUserPath(*p);
+ for (std::string const& p : this->UserGuessArgs) {
+ paths.AddUserPath(p);
}
}
@@ -1406,24 +1472,20 @@ void cmFindPackageCommand::FillPrefixesUserHints()
{
cmSearchPath& paths = this->LabeledPaths[PathLabel::Hints];
- for (std::vector<std::string>::const_iterator p =
- this->UserHintsArgs.begin();
- p != this->UserHintsArgs.end(); ++p) {
- paths.AddUserPath(*p);
+ for (std::string const& p : this->UserHintsArgs) {
+ paths.AddUserPath(p);
}
}
bool cmFindPackageCommand::SearchDirectory(std::string const& dir)
{
- assert(!dir.empty() && dir[dir.size() - 1] == '/');
+ assert(!dir.empty() && dir.back() == '/');
// Check each path suffix on this directory.
- for (std::vector<std::string>::const_iterator si =
- this->SearchPathSuffixes.begin();
- si != this->SearchPathSuffixes.end(); ++si) {
+ for (std::string const& s : this->SearchPathSuffixes) {
std::string d = dir;
- if (!si->empty()) {
- d += *si;
+ if (!s.empty()) {
+ d += s;
d += "/";
}
if (this->CheckDirectory(d)) {
@@ -1435,7 +1497,7 @@ bool cmFindPackageCommand::SearchDirectory(std::string const& dir)
bool cmFindPackageCommand::CheckDirectory(std::string const& dir)
{
- assert(!dir.empty() && dir[dir.size() - 1] == '/');
+ assert(!dir.empty() && dir.back() == '/');
// Look for the file in this directory.
std::string d = dir.substr(0, dir.size() - 1);
@@ -1454,16 +1516,16 @@ bool cmFindPackageCommand::FindConfigFile(std::string const& dir,
return false;
}
- for (std::vector<std::string>::const_iterator ci = this->Configs.begin();
- ci != this->Configs.end(); ++ci) {
- file = dir;
- file += "/";
- file += *ci;
+ for (std::string const& c : this->Configs) {
+ file = cmStrCat(dir, '/', c);
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)) {
+ // Allow resolving symlinks when the config file is found through a link
+ if (this->UseRealPath) {
+ file = cmSystemTools::GetRealPath(file);
+ }
return true;
}
}
@@ -1481,17 +1543,15 @@ bool cmFindPackageCommand::CheckVersion(std::string const& config_file)
std::string version_file_base = config_file.substr(0, pos);
// 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)) {
+ std::string version_file = cmStrCat(version_file_base, "-version.cmake");
+ if (!haveResult && cmSystemTools::FileExists(version_file, true)) {
result = this->CheckVersionFile(version_file, version);
haveResult = true;
}
// Look for fooConfigVersion.cmake
- version_file = version_file_base;
- version_file += "Version.cmake";
- if (!haveResult && cmSystemTools::FileExists(version_file.c_str(), true)) {
+ version_file = cmStrCat(version_file_base, "Version.cmake");
+ if (!haveResult && cmSystemTools::FileExists(version_file, true)) {
result = this->CheckVersionFile(version_file, version);
haveResult = true;
}
@@ -1504,7 +1564,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;
}
@@ -1525,8 +1585,8 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file,
this->Makefile->RemoveDefinition("PACKAGE_VERSION_EXACT");
// Set the input variables.
- this->Makefile->AddDefinition("PACKAGE_FIND_NAME", this->Name.c_str());
- this->Makefile->AddDefinition("PACKAGE_FIND_VERSION", this->Version.c_str());
+ this->Makefile->AddDefinition("PACKAGE_FIND_NAME", this->Name);
+ this->Makefile->AddDefinition("PACKAGE_FIND_VERSION", this->Version);
char buf[64];
sprintf(buf, "%u", this->VersionMajor);
this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_MAJOR", buf);
@@ -1542,7 +1602,7 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file,
// Load the version check file. Pass NoPolicyScope because we do
// our own policy push/pop independent of CMP0011.
bool suitable = false;
- if (this->ReadListFile(version_file.c_str(), NoPolicyScope)) {
+ if (this->ReadListFile(version_file, NoPolicyScope)) {
// Check the output variables.
bool okay = this->Makefile->IsOn("PACKAGE_VERSION_EXACT");
bool unsuitable = this->Makefile->IsOn("PACKAGE_VERSION_UNSUITABLE");
@@ -1598,12 +1658,11 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file,
void cmFindPackageCommand::StoreVersionFound()
{
// Store the whole version string.
- std::string ver = this->Name;
- ver += "_VERSION";
+ std::string ver = cmStrCat(this->Name, "_VERSION");
if (this->VersionFound.empty()) {
this->Makefile->RemoveDefinition(ver);
} else {
- this->Makefile->AddDefinition(ver, this->VersionFound.c_str());
+ this->Makefile->AddDefinition(ver, this->VersionFound);
}
// Store the version components.
@@ -1623,7 +1682,7 @@ void cmFindPackageCommand::StoreVersionFound()
class cmFileListGeneratorBase
{
public:
- virtual ~cmFileListGeneratorBase() {}
+ virtual ~cmFileListGeneratorBase() = default;
protected:
bool Consider(std::string const& fullPath, cmFileList& listing);
@@ -1631,21 +1690,16 @@ protected:
private:
bool Search(cmFileList&);
virtual bool Search(std::string const& parent, cmFileList&) = 0;
- virtual CM_AUTO_PTR<cmFileListGeneratorBase> Clone() const = 0;
+ virtual std::unique_ptr<cmFileListGeneratorBase> Clone() const = 0;
friend class cmFileList;
cmFileListGeneratorBase* SetNext(cmFileListGeneratorBase const& next);
- CM_AUTO_PTR<cmFileListGeneratorBase> Next;
+ std::unique_ptr<cmFileListGeneratorBase> Next;
};
class cmFileList
{
public:
- cmFileList()
- : First()
- , Last(CM_NULLPTR)
- {
- }
- virtual ~cmFileList() {}
+ virtual ~cmFileList() = default;
cmFileList& operator/(cmFileListGeneratorBase const& rhs)
{
if (this->Last) {
@@ -1658,7 +1712,7 @@ public:
}
bool Search()
{
- if (this->First.get()) {
+ if (this->First) {
return this->First->Search(*this);
}
return false;
@@ -1667,22 +1721,21 @@ public:
private:
virtual bool Visit(std::string const& fullPath) = 0;
friend class cmFileListGeneratorBase;
- CM_AUTO_PTR<cmFileListGeneratorBase> First;
- cmFileListGeneratorBase* Last;
+ std::unique_ptr<cmFileListGeneratorBase> First;
+ cmFileListGeneratorBase* Last = nullptr;
};
class cmFindPackageFileList : public cmFileList
{
public:
cmFindPackageFileList(cmFindPackageCommand* fpc, bool use_suffixes = true)
- : cmFileList()
- , FPC(fpc)
+ : FPC(fpc)
, UseSuffixes(use_suffixes)
{
}
private:
- bool Visit(std::string const& fullPath) CM_OVERRIDE
+ bool Visit(std::string const& fullPath) override
{
if (this->UseSuffixes) {
return this->FPC->SearchDirectory(fullPath);
@@ -1708,7 +1761,7 @@ cmFileListGeneratorBase* cmFileListGeneratorBase::SetNext(
bool cmFileListGeneratorBase::Consider(std::string const& fullPath,
cmFileList& listing)
{
- if (this->Next.get()) {
+ if (this->Next) {
return this->Next->Search(fullPath + "/", listing);
}
return listing.Visit(fullPath + "/");
@@ -1717,27 +1770,25 @@ bool cmFileListGeneratorBase::Consider(std::string const& fullPath,
class cmFileListGeneratorFixed : public cmFileListGeneratorBase
{
public:
- cmFileListGeneratorFixed(std::string const& str)
- : cmFileListGeneratorBase()
- , String(str)
+ cmFileListGeneratorFixed(std::string str)
+ : String(std::move(str))
{
}
cmFileListGeneratorFixed(cmFileListGeneratorFixed const& r)
- : cmFileListGeneratorBase()
- , String(r.String)
+ : String(r.String)
{
}
private:
std::string String;
- bool Search(std::string const& parent, cmFileList& lister) CM_OVERRIDE
+ bool Search(std::string const& parent, cmFileList& lister) override
{
std::string fullPath = parent + this->String;
return this->Consider(fullPath, lister);
}
- CM_AUTO_PTR<cmFileListGeneratorBase> Clone() const CM_OVERRIDE
+ std::unique_ptr<cmFileListGeneratorBase> Clone() const override
{
- CM_AUTO_PTR<cmFileListGeneratorBase> g(
+ std::unique_ptr<cmFileListGeneratorBase> g(
new cmFileListGeneratorFixed(*this));
return g;
}
@@ -1747,31 +1798,28 @@ class cmFileListGeneratorEnumerate : public cmFileListGeneratorBase
{
public:
cmFileListGeneratorEnumerate(std::vector<std::string> const& v)
- : cmFileListGeneratorBase()
- , Vector(v)
+ : Vector(v)
{
}
cmFileListGeneratorEnumerate(cmFileListGeneratorEnumerate const& r)
- : cmFileListGeneratorBase()
- , Vector(r.Vector)
+ : Vector(r.Vector)
{
}
private:
std::vector<std::string> const& Vector;
- bool Search(std::string const& parent, cmFileList& lister) CM_OVERRIDE
+ bool Search(std::string const& parent, cmFileList& lister) override
{
- for (std::vector<std::string>::const_iterator i = this->Vector.begin();
- i != this->Vector.end(); ++i) {
- if (this->Consider(parent + *i, lister)) {
+ for (std::string const& i : this->Vector) {
+ if (this->Consider(parent + i, lister)) {
return true;
}
}
return false;
}
- CM_AUTO_PTR<cmFileListGeneratorBase> Clone() const CM_OVERRIDE
+ std::unique_ptr<cmFileListGeneratorBase> Clone() const override
{
- CM_AUTO_PTR<cmFileListGeneratorBase> g(
+ std::unique_ptr<cmFileListGeneratorBase> g(
new cmFileListGeneratorEnumerate(*this));
return g;
}
@@ -1783,14 +1831,12 @@ public:
cmFileListGeneratorProject(std::vector<std::string> const& names,
cmFindPackageCommand::SortOrderType so,
cmFindPackageCommand::SortDirectionType sd)
- : cmFileListGeneratorBase()
- , Names(names)
+ : Names(names)
{
this->SetSort(so, sd);
}
cmFileListGeneratorProject(cmFileListGeneratorProject const& r)
- : cmFileListGeneratorBase()
- , Names(r.Names)
+ : Names(r.Names)
{
this->SetSort(r.SortOrder, r.SortDirection);
}
@@ -1809,7 +1855,7 @@ protected:
private:
std::vector<std::string> const& Names;
- bool Search(std::string const& parent, cmFileList& lister) CM_OVERRIDE
+ bool Search(std::string const& parent, cmFileList& lister) override
{
// Construct a list of matches.
std::vector<std::string> matches;
@@ -1820,10 +1866,9 @@ private:
if (strcmp(fname, ".") == 0 || strcmp(fname, "..") == 0) {
continue;
}
- for (std::vector<std::string>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni) {
- if (cmsysString_strncasecmp(fname, ni->c_str(), ni->length()) == 0) {
- matches.push_back(fname);
+ for (std::string const& n : this->Names) {
+ if (cmsysString_strncasecmp(fname, n.c_str(), n.length()) == 0) {
+ matches.emplace_back(fname);
}
}
}
@@ -1835,17 +1880,16 @@ private:
SortDirection);
}
- for (std::vector<std::string>::const_iterator i = matches.begin();
- i != matches.end(); ++i) {
- if (this->Consider(parent + *i, lister)) {
+ for (std::string const& i : matches) {
+ if (this->Consider(parent + i, lister)) {
return true;
}
}
return false;
}
- CM_AUTO_PTR<cmFileListGeneratorBase> Clone() const CM_OVERRIDE
+ std::unique_ptr<cmFileListGeneratorBase> Clone() const override
{
- CM_AUTO_PTR<cmFileListGeneratorBase> g(
+ std::unique_ptr<cmFileListGeneratorBase> g(
new cmFileListGeneratorProject(*this));
return g;
}
@@ -1856,14 +1900,12 @@ class cmFileListGeneratorMacProject : public cmFileListGeneratorBase
public:
cmFileListGeneratorMacProject(std::vector<std::string> const& names,
const char* ext)
- : cmFileListGeneratorBase()
- , Names(names)
+ : Names(names)
, Extension(ext)
{
}
cmFileListGeneratorMacProject(cmFileListGeneratorMacProject const& r)
- : cmFileListGeneratorBase()
- , Names(r.Names)
+ : Names(r.Names)
, Extension(r.Extension)
{
}
@@ -1871,7 +1913,7 @@ public:
private:
std::vector<std::string> const& Names;
std::string Extension;
- bool Search(std::string const& parent, cmFileList& lister) CM_OVERRIDE
+ bool Search(std::string const& parent, cmFileList& lister) override
{
// Construct a list of matches.
std::vector<std::string> matches;
@@ -1882,27 +1924,24 @@ private:
if (strcmp(fname, ".") == 0 || strcmp(fname, "..") == 0) {
continue;
}
- for (std::vector<std::string>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni) {
- std::string name = *ni;
+ for (std::string name : this->Names) {
name += this->Extension;
if (cmsysString_strcasecmp(fname, name.c_str()) == 0) {
- matches.push_back(fname);
+ matches.emplace_back(fname);
}
}
}
- for (std::vector<std::string>::const_iterator i = matches.begin();
- i != matches.end(); ++i) {
- if (this->Consider(parent + *i, lister)) {
+ for (std::string const& i : matches) {
+ if (this->Consider(parent + i, lister)) {
return true;
}
}
return false;
}
- CM_AUTO_PTR<cmFileListGeneratorBase> Clone() const CM_OVERRIDE
+ std::unique_ptr<cmFileListGeneratorBase> Clone() const override
{
- CM_AUTO_PTR<cmFileListGeneratorBase> g(
+ std::unique_ptr<cmFileListGeneratorBase> g(
new cmFileListGeneratorMacProject(*this));
return g;
}
@@ -1911,21 +1950,19 @@ private:
class cmFileListGeneratorCaseInsensitive : public cmFileListGeneratorBase
{
public:
- cmFileListGeneratorCaseInsensitive(std::string const& str)
- : cmFileListGeneratorBase()
- , String(str)
+ cmFileListGeneratorCaseInsensitive(std::string str)
+ : String(std::move(str))
{
}
cmFileListGeneratorCaseInsensitive(
cmFileListGeneratorCaseInsensitive const& r)
- : cmFileListGeneratorBase()
- , String(r.String)
+ : String(r.String)
{
}
private:
std::string String;
- bool Search(std::string const& parent, cmFileList& lister) CM_OVERRIDE
+ bool Search(std::string const& parent, cmFileList& lister) override
{
// Look for matching files.
std::vector<std::string> matches;
@@ -1944,9 +1981,9 @@ private:
}
return false;
}
- CM_AUTO_PTR<cmFileListGeneratorBase> Clone() const CM_OVERRIDE
+ std::unique_ptr<cmFileListGeneratorBase> Clone() const override
{
- CM_AUTO_PTR<cmFileListGeneratorBase> g(
+ std::unique_ptr<cmFileListGeneratorBase> g(
new cmFileListGeneratorCaseInsensitive(*this));
return g;
}
@@ -1955,24 +1992,21 @@ private:
class cmFileListGeneratorGlob : public cmFileListGeneratorBase
{
public:
- cmFileListGeneratorGlob(std::string const& str)
- : cmFileListGeneratorBase()
- , Pattern(str)
+ cmFileListGeneratorGlob(std::string str)
+ : Pattern(std::move(str))
{
}
cmFileListGeneratorGlob(cmFileListGeneratorGlob const& r)
- : cmFileListGeneratorBase()
- , Pattern(r.Pattern)
+ : Pattern(r.Pattern)
{
}
private:
std::string Pattern;
- bool Search(std::string const& parent, cmFileList& lister) CM_OVERRIDE
+ bool Search(std::string const& parent, cmFileList& lister) override
{
// Glob the set of matching files.
- std::string expr = parent;
- expr += this->Pattern;
+ std::string expr = cmStrCat(parent, this->Pattern);
cmsys::Glob g;
if (!g.FindFiles(expr)) {
return false;
@@ -1980,26 +2014,24 @@ private:
std::vector<std::string> const& files = g.GetFiles();
// Look for directories among the matches.
- for (std::vector<std::string>::const_iterator fi = files.begin();
- fi != files.end(); ++fi) {
- if (cmSystemTools::FileIsDirectory(*fi)) {
- if (this->Consider(*fi, lister)) {
+ for (std::string const& f : files) {
+ if (cmSystemTools::FileIsDirectory(f)) {
+ if (this->Consider(f, lister)) {
return true;
}
}
}
return false;
}
- CM_AUTO_PTR<cmFileListGeneratorBase> Clone() const CM_OVERRIDE
+ std::unique_ptr<cmFileListGeneratorBase> Clone() const override
{
- CM_AUTO_PTR<cmFileListGeneratorBase> g(new cmFileListGeneratorGlob(*this));
- return g;
+ return cm::make_unique<cmFileListGeneratorGlob>(*this);
}
};
bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
{
- assert(!prefix_in.empty() && prefix_in[prefix_in.size() - 1] == '/');
+ assert(!prefix_in.empty() && prefix_in.back() == '/');
if (this->DebugMode) {
fprintf(stderr, "Checking prefix [%s]\n", prefix_in.c_str());
}
@@ -2057,18 +2089,18 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
common.push_back("lib/" + this->LibraryArchitecture);
}
if (this->UseLib32Paths) {
- common.push_back("lib32");
+ common.emplace_back("lib32");
}
if (this->UseLib64Paths) {
- common.push_back("lib64");
+ common.emplace_back("lib64");
}
if (this->UseLibx32Paths) {
- common.push_back("libx32");
+ common.emplace_back("libx32");
}
- common.push_back("lib");
- common.push_back("share");
+ common.emplace_back("lib");
+ common.emplace_back("share");
- // PREFIX/(lib/ARCH|lib|share)/cmake/(Foo|foo|FOO).*/
+ // PREFIX/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
@@ -2081,7 +2113,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
}
}
- // PREFIX/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/
+ // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
@@ -2093,7 +2125,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
}
}
- // PREFIX/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/(cmake|CMake)/
+ // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
@@ -2106,7 +2138,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
}
}
- // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib|share)/cmake/(Foo|foo|FOO).*/
+ // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
@@ -2121,7 +2153,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
}
}
- // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/
+ // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
@@ -2135,7 +2167,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
}
}
- // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib|share)/(Foo|foo|FOO).*/(cmake|CMake)/
+ // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/
{
cmFindPackageFileList lister(this);
lister / cmFileListGeneratorFixed(prefix) /
@@ -2155,7 +2187,7 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
bool cmFindPackageCommand::SearchFrameworkPrefix(std::string const& prefix_in)
{
- assert(!prefix_in.empty() && prefix_in[prefix_in.size() - 1] == '/');
+ assert(!prefix_in.empty() && prefix_in.back() == '/');
if (this->DebugMode) {
fprintf(stderr, "Checking framework prefix [%s]\n", prefix_in.c_str());
}
@@ -2216,7 +2248,7 @@ bool cmFindPackageCommand::SearchFrameworkPrefix(std::string const& prefix_in)
bool cmFindPackageCommand::SearchAppBundlePrefix(std::string const& prefix_in)
{
- assert(!prefix_in.empty() && prefix_in[prefix_in.size() - 1] == '/');
+ assert(!prefix_in.empty() && prefix_in.back() == '/');
if (this->DebugMode) {
fprintf(stderr, "Checking bundle prefix [%s]\n", prefix_in.c_str());
}
@@ -2252,3 +2284,9 @@ bool cmFindPackageCommand::SearchAppBundlePrefix(std::string const& prefix_in)
}
// TODO: Debug cmsys::Glob double slash problem.
+
+bool cmFindPackage(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return cmFindPackageCommand(status).InitialPass(args);
+}
diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h
index 99b0059ba..85fe7b6e5 100644
--- a/Source/cmFindPackageCommand.h
+++ b/Source/cmFindPackageCommand.h
@@ -3,17 +3,31 @@
#ifndef cmFindPackageCommand_h
#define cmFindPackageCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cm_kwiml.h"
+#include <cstddef>
+#include <functional>
#include <map>
#include <set>
#include <string>
#include <vector>
+#include "cm_kwiml.h"
+
#include "cmFindCommon.h"
+#include "cmPolicies.h"
+
+// IWYU insists we should forward-declare instead of including <functional>,
+// but we cannot forward-declare reliably because some C++ standard libraries
+// put the template in an inline namespace.
+#ifdef CMAKE_IWYU_FORWARD_STD_HASH
+/* clang-format off */
+namespace std {
+ template <class T> struct hash;
+}
+/* clang-format on */
+#endif
-class cmCommand;
class cmExecutionStatus;
class cmSearchPath;
@@ -46,19 +60,9 @@ public:
std::vector<std::string>::iterator end, SortOrderType order,
SortDirectionType dir);
- cmFindPackageCommand();
-
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmFindPackageCommand; }
+ cmFindPackageCommand(cmExecutionStatus& status);
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
+ bool InitialPass(std::vector<std::string> const& args);
private:
class PathLabel : public cmFindCommon::PathLabel
@@ -76,6 +80,9 @@ private:
static PathLabel SystemRegistry;
};
+ bool FindPackageUsingModuleMode();
+ bool FindPackageUsingConfigMode();
+
// Add additional search path labels and groups not present in the
// parent class
void AppendSearchPathGroups();
@@ -86,7 +93,14 @@ private:
bool FindModule(bool& found);
void AddFindDefinition(const std::string& var, const char* val);
void RestoreFindDefinitions();
- bool HandlePackageMode();
+
+ enum /*class*/ HandlePackageModeType
+ {
+ Module,
+ Config
+ };
+ bool HandlePackageMode(HandlePackageModeType type);
+
bool FindConfig();
bool FindPrefixedConfig();
bool FindFrameworkConfig();
@@ -96,7 +110,7 @@ private:
NoPolicyScope,
DoPolicyScope
};
- bool ReadListFile(const char* f, PolicyScopeRule psr);
+ bool ReadListFile(const std::string& f, PolicyScopeRule psr);
void StoreVersionFound();
void ComputePrefixes();
@@ -135,6 +149,8 @@ private:
};
std::map<std::string, OriginalDef> OriginalDefs;
+ std::map<std::string, cmPolicies::PolicyID> DeprecatedFindModules;
+
std::string Name;
std::string Variable;
std::string Version;
@@ -162,6 +178,7 @@ private:
bool UseLib32Paths;
bool UseLib64Paths;
bool UseLibx32Paths;
+ bool UseRealPath;
bool PolicyScope;
std::string LibraryArchitecture;
std::vector<std::string> Names;
@@ -194,6 +211,27 @@ private:
}
};
std::vector<ConfigFileInfo> ConsideredConfigs;
+
+ friend struct std::hash<ConfigFileInfo>;
};
+namespace std {
+
+template <>
+struct hash<cmFindPackageCommand::ConfigFileInfo>
+{
+ using argument_type = cmFindPackageCommand::ConfigFileInfo;
+ using result_type = size_t;
+
+ result_type operator()(argument_type const& s) const noexcept
+ {
+ result_type const h(std::hash<std::string>{}(s.filename));
+ return h;
+ }
+};
+}
+
+bool cmFindPackage(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+
#endif
diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx
index d3541ca94..f5e263108 100644
--- a/Source/cmFindPathCommand.cxx
+++ b/Source/cmFindPathCommand.cxx
@@ -6,19 +6,20 @@
#include "cmMakefile.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
class cmExecutionStatus;
-cmFindPathCommand::cmFindPathCommand()
+cmFindPathCommand::cmFindPathCommand(cmExecutionStatus& status)
+ : cmFindBase(status)
{
this->EnvironmentPath = "INCLUDE";
this->IncludeFileInPath = false;
}
// cmFindPathCommand
-bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn,
- cmExecutionStatus&)
+bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn)
{
this->VariableDocumentation = "Path to a file.";
this->CMakePathName = "INCLUDE";
@@ -85,16 +86,12 @@ std::string cmFindPathCommand::FindHeaderInFramework(std::string const& file,
// if the framework has a path in it then just use the filename
if (frameWorkName.find('/') != std::string::npos) {
fileName = file;
- frameWorkName = "";
+ frameWorkName.clear();
}
if (!frameWorkName.empty()) {
- std::string fpath = dir;
- fpath += frameWorkName;
- fpath += ".framework";
- std::string intPath = fpath;
- intPath += "/Headers/";
- intPath += fileName;
- if (cmSystemTools::FileExists(intPath.c_str())) {
+ std::string fpath = cmStrCat(dir, frameWorkName, ".framework");
+ std::string intPath = cmStrCat(fpath, "/Headers/", fileName);
+ if (cmSystemTools::FileExists(intPath)) {
if (this->IncludeFileInPath) {
return intPath;
}
@@ -104,9 +101,7 @@ std::string cmFindPathCommand::FindHeaderInFramework(std::string const& file,
}
// if it is not found yet or not a framework header, then do a glob search
// for all frameworks in the directory: dir/*.framework/Headers/<file>
- std::string glob = dir;
- glob += "*.framework/Headers/";
- glob += file;
+ std::string glob = cmStrCat(dir, "*.framework/Headers/", file);
cmsys::Glob globIt;
globIt.FindFiles(glob);
std::vector<std::string> files = globIt.GetFiles();
@@ -124,18 +119,14 @@ std::string cmFindPathCommand::FindHeaderInFramework(std::string const& file,
std::string cmFindPathCommand::FindNormalHeader()
{
std::string tryPath;
- for (std::vector<std::string>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni) {
- for (std::vector<std::string>::const_iterator p =
- this->SearchPaths.begin();
- p != this->SearchPaths.end(); ++p) {
- tryPath = *p;
- tryPath += *ni;
- if (cmSystemTools::FileExists(tryPath.c_str())) {
+ for (std::string const& n : this->Names) {
+ for (std::string const& sp : this->SearchPaths) {
+ tryPath = cmStrCat(sp, n);
+ if (cmSystemTools::FileExists(tryPath)) {
if (this->IncludeFileInPath) {
return tryPath;
}
- return *p;
+ return sp;
}
}
}
@@ -144,12 +135,9 @@ std::string cmFindPathCommand::FindNormalHeader()
std::string cmFindPathCommand::FindFrameworkHeader()
{
- for (std::vector<std::string>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni) {
- for (std::vector<std::string>::const_iterator p =
- this->SearchPaths.begin();
- p != this->SearchPaths.end(); ++p) {
- std::string fwPath = this->FindHeaderInFramework(*ni, *p);
+ for (std::string const& n : this->Names) {
+ for (std::string const& sp : this->SearchPaths) {
+ std::string fwPath = this->FindHeaderInFramework(n, sp);
if (!fwPath.empty()) {
return fwPath;
}
@@ -157,3 +145,9 @@ std::string cmFindPathCommand::FindFrameworkHeader()
}
return "";
}
+
+bool cmFindPath(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return cmFindPathCommand(status).InitialPass(args);
+}
diff --git a/Source/cmFindPathCommand.h b/Source/cmFindPathCommand.h
index 3761145b2..8d1ea8b60 100644
--- a/Source/cmFindPathCommand.h
+++ b/Source/cmFindPathCommand.h
@@ -3,14 +3,13 @@
#ifndef cmFindPathCommand_h
#define cmFindPathCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
#include "cmFindBase.h"
-class cmCommand;
class cmExecutionStatus;
/** \class cmFindPathCommand
@@ -23,18 +22,9 @@ class cmExecutionStatus;
class cmFindPathCommand : public cmFindBase
{
public:
- cmFindPathCommand();
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmFindPathCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
+ cmFindPathCommand(cmExecutionStatus& status);
+
+ bool InitialPass(std::vector<std::string> const& args);
bool IncludeFileInPath;
@@ -46,4 +36,7 @@ private:
std::string FindFrameworkHeader();
};
+bool cmFindPath(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+
#endif
diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx
index 9327c1805..e0a3fbfcf 100644
--- a/Source/cmFindProgramCommand.cxx
+++ b/Source/cmFindProgramCommand.cxx
@@ -4,12 +4,13 @@
#include "cmMakefile.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
class cmExecutionStatus;
#if defined(__APPLE__)
-#include <CoreFoundation/CoreFoundation.h>
+# include <CoreFoundation/CoreFoundation.h>
#endif
struct cmFindProgramHelper
@@ -22,7 +23,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.
@@ -34,6 +35,9 @@ struct cmFindProgramHelper
// Current names under consideration.
std::vector<std::string> Names;
+ // Current name with extension under consideration.
+ std::string TestNameExt;
+
// Current full path under consideration.
std::string TestPath;
@@ -43,11 +47,23 @@ struct cmFindProgramHelper
this->Names.clear();
this->AddName(name);
}
+ bool CheckCompoundNames()
+ {
+ for (std::string const& n : this->Names) {
+ // Only perform search relative to current directory if the file name
+ // contains a directory separator.
+ if (n.find('/') != std::string::npos) {
+ if (this->CheckDirectoryForName("", n)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
bool CheckDirectory(std::string const& path)
{
- for (std::vector<std::string>::iterator i = this->Names.begin();
- i != this->Names.end(); ++i) {
- if (this->CheckDirectoryForName(path, *i)) {
+ for (std::string const& n : this->Names) {
+ if (this->CheckDirectoryForName(path, n)) {
return true;
}
}
@@ -55,16 +71,16 @@ struct cmFindProgramHelper
}
bool CheckDirectoryForName(std::string const& path, std::string const& name)
{
- for (std::vector<std::string>::iterator ext = this->Extensions.begin();
- ext != this->Extensions.end(); ++ext) {
- this->TestPath = path;
- this->TestPath += name;
- if (!ext->empty() && cmSystemTools::StringEndsWith(name, ext->c_str())) {
+ for (std::string const& ext : this->Extensions) {
+ if (!ext.empty() && cmHasSuffix(name, ext)) {
continue;
}
- this->TestPath += *ext;
+ this->TestNameExt = cmStrCat(name, ext);
+ this->TestPath =
+ cmSystemTools::CollapseFullPath(this->TestNameExt, path);
+
if (cmSystemTools::FileExists(this->TestPath, true)) {
- this->BestPath = cmSystemTools::CollapseFullPath(this->TestPath);
+ this->BestPath = this->TestPath;
return true;
}
}
@@ -72,14 +88,14 @@ struct cmFindProgramHelper
}
};
-cmFindProgramCommand::cmFindProgramCommand()
+cmFindProgramCommand::cmFindProgramCommand(cmExecutionStatus& status)
+ : cmFindBase(status)
{
this->NamesPerDirAllowed = true;
}
// cmFindProgramCommand
-bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn,
- cmExecutionStatus&)
+bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn)
{
this->VariableDocumentation = "Path to a program.";
this->CMakePathName = "PROGRAM";
@@ -99,8 +115,8 @@ bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn,
return true;
}
- std::string result = FindProgram();
- if (result != "") {
+ std::string const result = FindProgram();
+ if (!result.empty()) {
// Save the value in the cache
this->Makefile->AddCacheDefinition(this->VariableName, result.c_str(),
this->VariableDocumentation.c_str(),
@@ -143,20 +159,18 @@ std::string cmFindProgramCommand::FindNormalProgramNamesPerDir()
{
// Search for all names in each directory.
cmFindProgramHelper helper;
- for (std::vector<std::string>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni) {
- helper.AddName(*ni);
+ for (std::string const& n : this->Names) {
+ helper.AddName(n);
}
- // Check for the names themselves (e.g. absolute paths).
- if (helper.CheckDirectory(std::string())) {
+ // Check for the names themselves if they contain a directory separator.
+ if (helper.CheckCompoundNames()) {
return helper.BestPath;
}
// Search every directory.
- for (std::vector<std::string>::const_iterator p = this->SearchPaths.begin();
- p != this->SearchPaths.end(); ++p) {
- if (helper.CheckDirectory(*p)) {
+ for (std::string const& sp : this->SearchPaths) {
+ if (helper.CheckDirectory(sp)) {
return helper.BestPath;
}
}
@@ -168,21 +182,18 @@ std::string cmFindProgramCommand::FindNormalProgramDirsPerName()
{
// Search the entire path for each name.
cmFindProgramHelper helper;
- for (std::vector<std::string>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni) {
+ for (std::string const& n : this->Names) {
// Switch to searching for this name.
- helper.SetName(*ni);
+ helper.SetName(n);
- // Check for the name by itself (e.g. an absolute path).
- if (helper.CheckDirectory(std::string())) {
+ // Check for the names themselves if they contain a directory separator.
+ if (helper.CheckCompoundNames()) {
return helper.BestPath;
}
// Search every directory.
- for (std::vector<std::string>::const_iterator p =
- this->SearchPaths.begin();
- p != this->SearchPaths.end(); ++p) {
- if (helper.CheckDirectory(*p)) {
+ for (std::string const& sp : this->SearchPaths) {
+ if (helper.CheckDirectory(sp)) {
return helper.BestPath;
}
}
@@ -193,10 +204,9 @@ std::string cmFindProgramCommand::FindNormalProgramDirsPerName()
std::string cmFindProgramCommand::FindAppBundle()
{
- for (std::vector<std::string>::const_iterator name = this->Names.begin();
- name != this->Names.end(); ++name) {
+ for (std::string const& name : this->Names) {
- std::string appName = *name + std::string(".app");
+ std::string appName = name + std::string(".app");
std::string appPath =
cmSystemTools::FindDirectory(appName, this->SearchPaths, true);
@@ -237,7 +247,7 @@ std::string cmFindProgramCommand::GetBundleExecutable(
// returned executableURL is relative to <appbundle>/Contents/MacOS/
CFURLRef executableURL = CFBundleCopyExecutableURL(appBundle);
- if (executableURL != NULL) {
+ if (executableURL != nullptr) {
const int MAX_OSX_PATH_SIZE = 1024;
char buffer[MAX_OSX_PATH_SIZE];
@@ -260,3 +270,9 @@ std::string cmFindProgramCommand::GetBundleExecutable(
return executable;
}
+
+bool cmFindProgram(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return cmFindProgramCommand(status).InitialPass(args);
+}
diff --git a/Source/cmFindProgramCommand.h b/Source/cmFindProgramCommand.h
index b0cd42096..043b43c5e 100644
--- a/Source/cmFindProgramCommand.h
+++ b/Source/cmFindProgramCommand.h
@@ -3,14 +3,13 @@
#ifndef cmFindProgramCommand_h
#define cmFindProgramCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
#include "cmFindBase.h"
-class cmCommand;
class cmExecutionStatus;
/** \class cmFindProgramCommand
@@ -24,18 +23,9 @@ class cmExecutionStatus;
class cmFindProgramCommand : public cmFindBase
{
public:
- cmFindProgramCommand();
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmFindProgramCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
+ cmFindProgramCommand(cmExecutionStatus& status);
+
+ bool InitialPass(std::vector<std::string> const& args);
private:
std::string FindProgram();
@@ -46,4 +36,7 @@ private:
std::string GetBundleExecutable(std::string const& bundlePath);
};
+bool cmFindProgram(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+
#endif
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index 8346b2309..44392baa7 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -2,19 +2,50 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmForEachCommand.h"
-#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
+#include <cstdio>
+#include <cstdlib>
+#include <utility>
+
+#include <cm/memory>
+#include <cm/string_view>
+
+#include "cm_static_string_view.hxx"
#include "cmExecutionStatus.h"
+#include "cmFunctionBlocker.h"
+#include "cmListFileCache.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmRange.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cm_auto_ptr.hxx"
-#include "cmake.h"
+
+namespace {
+bool HandleInMode(std::vector<std::string> const& args, cmMakefile& makefile);
+
+class cmForEachFunctionBlocker : public cmFunctionBlocker
+{
+public:
+ cmForEachFunctionBlocker(cmMakefile* mf);
+ ~cmForEachFunctionBlocker() override;
+
+ cm::string_view StartCommandName() const override { return "foreach"_s; }
+ cm::string_view EndCommandName() const override { return "endforeach"_s; }
+
+ bool ArgumentsMatch(cmListFileFunction const& lff,
+ cmMakefile& mf) const override;
+
+ bool Replay(std::vector<cmListFileFunction> functions,
+ cmExecutionStatus& inStatus) override;
+
+ std::vector<std::string> Args;
+
+private:
+ cmMakefile* Makefile;
+};
cmForEachFunctionBlocker::cmForEachFunctionBlocker(cmMakefile* mf)
: Makefile(mf)
- , Depth(0)
{
this->Makefile->PushLoopBlock();
}
@@ -24,103 +55,71 @@ cmForEachFunctionBlocker::~cmForEachFunctionBlocker()
this->Makefile->PopLoopBlock();
}
-bool cmForEachFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
- cmMakefile& mf,
- cmExecutionStatus& inStatus)
+bool cmForEachFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
+ cmMakefile& mf) const
{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "foreach")) {
- // record the number of nested foreach commands
- this->Depth++;
- } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endforeach")) {
- // if this is the endofreach for this statement
- if (!this->Depth) {
- // Remove the function blocker for this scope or bail.
- CM_AUTO_PTR<cmFunctionBlocker> fb(mf.RemoveFunctionBlocker(this, lff));
- if (!fb.get()) {
- return false;
- }
+ std::vector<std::string> expandedArguments;
+ mf.ExpandArguments(lff.Arguments, expandedArguments);
+ return expandedArguments.empty() || expandedArguments[0] == this->Args[0];
+}
+
+bool cmForEachFunctionBlocker::Replay(
+ std::vector<cmListFileFunction> functions, cmExecutionStatus& inStatus)
+{
+ cmMakefile& mf = inStatus.GetMakefile();
+ // at end of for each execute recorded commands
+ // store the old value
+ std::string oldDef;
+ if (mf.GetDefinition(this->Args[0])) {
+ oldDef = mf.GetDefinition(this->Args[0]);
+ }
- // at end of for each execute recorded commands
- // store the old value
- std::string oldDef;
- if (mf.GetDefinition(this->Args[0])) {
- oldDef = mf.GetDefinition(this->Args[0]);
+ for (std::string const& arg : cmMakeRange(this->Args).advance(1)) {
+ // set the variable to the loop value
+ mf.AddDefinition(this->Args[0], arg);
+ // Invoke all the functions that were collected in the block.
+ for (cmListFileFunction const& func : functions) {
+ cmExecutionStatus status(mf);
+ mf.ExecuteCommand(func, status);
+ if (status.GetReturnInvoked()) {
+ inStatus.SetReturnInvoked();
+ // restore the variable to its prior value
+ mf.AddDefinition(this->Args[0], oldDef);
+ return true;
}
- std::vector<std::string>::const_iterator j = this->Args.begin();
- ++j;
-
- for (; j != this->Args.end(); ++j) {
- // set the variable to the loop value
- mf.AddDefinition(this->Args[0], j->c_str());
- // Invoke all the functions that were collected in the block.
- cmExecutionStatus status;
- for (unsigned int c = 0; c < this->Functions.size(); ++c) {
- status.Clear();
- mf.ExecuteCommand(this->Functions[c], status);
- if (status.GetReturnInvoked()) {
- inStatus.SetReturnInvoked();
- // restore the variable to its prior value
- mf.AddDefinition(this->Args[0], oldDef.c_str());
- return true;
- }
- if (status.GetBreakInvoked()) {
- // restore the variable to its prior value
- mf.AddDefinition(this->Args[0], oldDef.c_str());
- return true;
- }
- if (status.GetContinueInvoked()) {
- break;
- }
- if (cmSystemTools::GetFatalErrorOccured()) {
- return true;
- }
- }
+ if (status.GetBreakInvoked()) {
+ // restore the variable to its prior value
+ mf.AddDefinition(this->Args[0], oldDef);
+ return true;
+ }
+ if (status.GetContinueInvoked()) {
+ break;
+ }
+ if (cmSystemTools::GetFatalErrorOccured()) {
+ return true;
}
-
- // restore the variable to its prior value
- mf.AddDefinition(this->Args[0], oldDef.c_str());
- return true;
}
- // close out a nested foreach
- this->Depth--;
}
- // record the command
- this->Functions.push_back(lff);
-
- // always return true
+ // restore the variable to its prior value
+ mf.AddDefinition(this->Args[0], oldDef);
return true;
}
-
-bool cmForEachFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
- cmMakefile& mf)
-{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endforeach")) {
- std::vector<std::string> expandedArguments;
- mf.ExpandArguments(lff.Arguments, expandedArguments);
- // if the endforeach has arguments then make sure
- // they match the begin foreach arguments
- if ((expandedArguments.empty() ||
- (expandedArguments[0] == this->Args[0]))) {
- return true;
- }
- }
- return false;
}
-bool cmForEachCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmForEachCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
if (args.size() > 1 && args[1] == "IN") {
- return this->HandleInMode(args);
+ return HandleInMode(args, status.GetMakefile());
}
// create a function blocker
- cmForEachFunctionBlocker* f = new cmForEachFunctionBlocker(this->Makefile);
+ auto fb = cm::make_unique<cmForEachFunctionBlocker>(&status.GetMakefile());
if (args.size() > 1) {
if (args[1] == "RANGE") {
int start = 0;
@@ -147,10 +146,9 @@ bool cmForEachCommand::InitialPass(std::vector<std::string> const& args,
}
if ((start > stop && step > 0) || (start < stop && step < 0) ||
step == 0) {
- std::ostringstream str;
- str << "called with incorrect range specification: start ";
- str << start << ", stop " << stop << ", step " << step;
- this->SetError(str.str());
+ status.SetError(
+ cmStrCat("called with incorrect range specification: start ", start,
+ ", stop ", stop, ", step ", step));
return false;
}
std::vector<std::string> range;
@@ -162,28 +160,28 @@ bool cmForEachCommand::InitialPass(std::vector<std::string> const& args,
break;
}
sprintf(buffer, "%d", cc);
- range.push_back(buffer);
+ range.emplace_back(buffer);
if (cc == stop) {
break;
}
}
- f->Args = range;
+ fb->Args = range;
} else {
- f->Args = args;
+ fb->Args = args;
}
} else {
- f->Args = args;
+ fb->Args = args;
}
- this->Makefile->AddFunctionBlocker(f);
+ status.GetMakefile().AddFunctionBlocker(std::move(fb));
return true;
}
-bool cmForEachCommand::HandleInMode(std::vector<std::string> const& args)
+namespace {
+bool HandleInMode(std::vector<std::string> const& args, cmMakefile& makefile)
{
- CM_AUTO_PTR<cmForEachFunctionBlocker> f(
- new cmForEachFunctionBlocker(this->Makefile));
- f->Args.push_back(args[0]);
+ auto fb = cm::make_unique<cmForEachFunctionBlocker>(&makefile);
+ fb->Args.push_back(args[0]);
enum Doing
{
@@ -194,26 +192,26 @@ bool cmForEachCommand::HandleInMode(std::vector<std::string> const& args)
Doing doing = DoingNone;
for (unsigned int i = 2; i < args.size(); ++i) {
if (doing == DoingItems) {
- f->Args.push_back(args[i]);
+ fb->Args.push_back(args[i]);
} else if (args[i] == "LISTS") {
doing = DoingLists;
} else if (args[i] == "ITEMS") {
doing = DoingItems;
} else if (doing == DoingLists) {
- const char* value = this->Makefile->GetDefinition(args[i]);
+ const char* value = makefile.GetDefinition(args[i]);
if (value && *value) {
- cmSystemTools::ExpandListArgument(value, f->Args, true);
+ cmExpandList(value, fb->Args, true);
}
} else {
- std::ostringstream e;
- e << "Unknown argument:\n"
- << " " << args[i] << "\n";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ makefile.IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Unknown argument:\n", " ", args[i], "\n"));
return true;
}
}
- this->Makefile->AddFunctionBlocker(f.release()); // TODO: pass auto_ptr
+ makefile.AddFunctionBlocker(std::move(fb));
return true;
}
+}
diff --git a/Source/cmForEachCommand.h b/Source/cmForEachCommand.h
index 7c8a6d836..1feb965ce 100644
--- a/Source/cmForEachCommand.h
+++ b/Source/cmForEachCommand.h
@@ -3,53 +3,14 @@
#ifndef cmForEachCommand_h
#define cmForEachCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-#include "cmFunctionBlocker.h"
-#include "cmListFileCache.h"
-
class cmExecutionStatus;
-class cmMakefile;
-
-class cmForEachFunctionBlocker : public cmFunctionBlocker
-{
-public:
- cmForEachFunctionBlocker(cmMakefile* mf);
- ~cmForEachFunctionBlocker() CM_OVERRIDE;
- bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
- cmExecutionStatus&) CM_OVERRIDE;
- bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) CM_OVERRIDE;
-
- std::vector<std::string> Args;
- std::vector<cmListFileFunction> Functions;
-
-private:
- cmMakefile* Makefile;
- int Depth;
-};
/// Starts foreach() ... endforeach() block
-class cmForEachCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmForEachCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- bool HandleInMode(std::vector<std::string> const& args);
-};
-
+bool cmForEachCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h
index d8b002309..6f97b4243 100644
--- a/Source/cmFortranParser.h
+++ b/Source/cmFortranParser.h
@@ -4,17 +4,18 @@
#define cmFortranParser_h
#if !defined(cmFortranLexer_cxx) && !defined(cmFortranParser_cxx)
-#include "cmConfigure.h"
+# include "cmConfigure.h" // IWYU pragma: keep
-#include <set>
-#include <string>
-#include <vector>
+# include <set>
+# include <string>
+# include <utility>
+# include <vector>
#endif
-#include <stddef.h> /* size_t */
+#include <cstddef> /* size_t */
/* Forward declare parser object type. */
-typedef struct cmFortranParser_s cmFortranParser;
+using cmFortranParser = struct cmFortranParser_s;
/* Functions to enter/exit #include'd files in order. */
bool cmFortranParser_FilePush(cmFortranParser* parser, const char* fname);
@@ -39,11 +40,19 @@ int cmFortranParser_GetOldStartcond(cmFortranParser* parser);
/* Callbacks for parser. */
void cmFortranParser_Error(cmFortranParser* parser, const char* message);
-void cmFortranParser_RuleUse(cmFortranParser* parser, const char* name);
+void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name);
void cmFortranParser_RuleLineDirective(cmFortranParser* parser,
const char* filename);
void cmFortranParser_RuleInclude(cmFortranParser* parser, const char* name);
-void cmFortranParser_RuleModule(cmFortranParser* parser, const char* name);
+void cmFortranParser_RuleModule(cmFortranParser* parser,
+ const char* module_name);
+void cmFortranParser_RuleSubmodule(cmFortranParser* parser,
+ const char* module_name,
+ const char* submodule_name);
+void cmFortranParser_RuleSubmoduleNested(cmFortranParser* parser,
+ const char* module_name,
+ const char* submodule_name,
+ const char* nested_submodule_name);
void cmFortranParser_RuleDefine(cmFortranParser* parser, const char* name);
void cmFortranParser_RuleUndef(cmFortranParser* parser, const char* name);
void cmFortranParser_RuleIfdef(cmFortranParser* parser, const char* name);
@@ -65,20 +74,20 @@ struct cmFortran_yystype
#define YYSTYPE cmFortran_yystype
#define YYSTYPE_IS_DECLARED 1
#if !defined(cmFortranLexer_cxx)
-#define YY_NO_UNISTD_H
-#include "cmFortranLexer.h"
+# define YY_NO_UNISTD_H
+# include "cmFortranLexer.h"
#endif
#if !defined(cmFortranLexer_cxx)
-#if !defined(cmFortranParser_cxx)
-#undef YY_EXTRA_TYPE
-#undef YY_DECL
-#undef YYSTYPE
-#undef YYSTYPE_IS_DECLARED
-#endif
+# if !defined(cmFortranParser_cxx)
+# undef YY_EXTRA_TYPE
+# undef YY_DECL
+# undef YYSTYPE
+# undef YYSTYPE_IS_DECLARED
+# endif
#endif
#if !defined(cmFortranLexer_cxx) && !defined(cmFortranParser_cxx)
-#include <stack>
+# include <stack>
// Information about a single source file.
class cmFortranSourceInfo
@@ -106,10 +115,10 @@ int cmFortran_yyparse(yyscan_t);
// Define parser object internal structure.
struct cmFortranFile
{
- cmFortranFile(FILE* file, YY_BUFFER_STATE buffer, const std::string& dir)
+ cmFortranFile(FILE* file, YY_BUFFER_STATE buffer, std::string dir)
: File(file)
, Buffer(buffer)
- , Directory(dir)
+ , Directory(std::move(dir))
, LastCharWasNewline(false)
{
}
@@ -119,16 +128,32 @@ struct cmFortranFile
bool LastCharWasNewline;
};
+struct cmFortranCompiler
+{
+ std::string Id;
+ std::string SModSep;
+ std::string SModExt;
+};
+
struct cmFortranParser_s
{
- cmFortranParser_s(std::vector<std::string> const& includes,
- std::set<std::string> const& defines,
- cmFortranSourceInfo& info);
+ cmFortranParser_s(cmFortranCompiler fc, std::vector<std::string> includes,
+ std::set<std::string> defines, cmFortranSourceInfo& info);
~cmFortranParser_s();
+ cmFortranParser_s(const cmFortranParser_s&) = delete;
+ cmFortranParser_s& operator=(const cmFortranParser_s&) = delete;
+
bool FindIncludeFile(const char* dir, const char* includeName,
std::string& fileName);
+ std::string ModName(std::string const& mod_name) const;
+ std::string SModName(std::string const& mod_name,
+ std::string const& sub_name) const;
+
+ // What compiler.
+ cmFortranCompiler Compiler;
+
// The include file search path.
std::vector<std::string> IncludePath;
diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx
index 4e23f3691..054a2a93e 100644
--- a/Source/cmFortranParserImpl.cxx
+++ b/Source/cmFortranParserImpl.cxx
@@ -1,16 +1,17 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmFortranParser.h"
-#include "cmSystemTools.h"
-
-#include "cmConfigure.h"
-#include <assert.h>
+#include <cassert>
+#include <cstdio>
#include <set>
#include <stack>
-#include <stdio.h>
#include <string>
+#include <utility>
#include <vector>
+#include "cmFortranParser.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
bool cmFortranParser_s::FindIncludeFile(const char* dir,
const char* includeName,
std::string& fileName)
@@ -18,25 +19,20 @@ 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)) {
+ std::string fullName = cmStrCat(dir, '/', includeName);
+ if (cmSystemTools::FileExists(fullName, true)) {
fileName = fullName;
return true;
}
// Search the include path for the file.
- for (std::vector<std::string>::const_iterator i = this->IncludePath.begin();
- i != this->IncludePath.end(); ++i) {
- fullName = *i;
- fullName += "/";
- fullName += includeName;
- if (cmSystemTools::FileExists(fullName.c_str(), true)) {
+ for (std::string const& i : this->IncludePath) {
+ fullName = cmStrCat(i, '/', includeName);
+ if (cmSystemTools::FileExists(fullName, true)) {
fileName = fullName;
return true;
}
@@ -44,11 +40,13 @@ bool cmFortranParser_s::FindIncludeFile(const char* dir,
return false;
}
-cmFortranParser_s::cmFortranParser_s(std::vector<std::string> const& includes,
- std::set<std::string> const& defines,
+cmFortranParser_s::cmFortranParser_s(cmFortranCompiler fc,
+ std::vector<std::string> includes,
+ std::set<std::string> defines,
cmFortranSourceInfo& info)
- : IncludePath(includes)
- , PPDefinitions(defines)
+ : Compiler(std::move(fc))
+ , IncludePath(std::move(includes))
+ , PPDefinitions(std::move(defines))
, Info(info)
{
this->InInterface = false;
@@ -61,7 +59,7 @@ cmFortranParser_s::cmFortranParser_s(std::vector<std::string> const& includes,
// Create a dummy buffer that is never read but is the fallback
// buffer when the last file is popped off the stack.
YY_BUFFER_STATE buffer =
- cmFortran_yy_create_buffer(CM_NULLPTR, 4, this->Scanner);
+ cmFortran_yy_create_buffer(nullptr, 4, this->Scanner);
cmFortran_yy_switch_to_buffer(buffer, this->Scanner);
}
@@ -70,6 +68,23 @@ cmFortranParser_s::~cmFortranParser_s()
cmFortran_yylex_destroy(this->Scanner);
}
+std::string cmFortranParser_s::ModName(std::string const& mod_name) const
+{
+ return mod_name + ".mod";
+}
+
+std::string cmFortranParser_s::SModName(std::string const& mod_name,
+ std::string const& sub_name) const
+{
+ std::string const& SModExt =
+ this->Compiler.SModExt.empty() ? ".mod" : this->Compiler.SModExt;
+ // An empty separator means that the compiler does not use a prefix.
+ if (this->Compiler.SModSep.empty()) {
+ return sub_name + SModExt;
+ }
+ return mod_name + this->Compiler.SModSep + sub_name + SModExt;
+}
+
bool cmFortranParser_FilePush(cmFortranParser* parser, const char* fname)
{
// Open the new file and push it onto the stack. Save the old
@@ -79,7 +94,7 @@ bool cmFortranParser_FilePush(cmFortranParser* parser, const char* fname)
std::string dir = cmSystemTools::GetParentDirectory(fname);
cmFortranFile f(file, current, dir);
YY_BUFFER_STATE buffer =
- cmFortran_yy_create_buffer(CM_NULLPTR, 16384, parser->Scanner);
+ cmFortran_yy_create_buffer(nullptr, 16384, parser->Scanner);
cmFortran_yy_switch_to_buffer(buffer, parser->Scanner);
parser->FileStack.push(f);
return true;
@@ -121,14 +136,14 @@ int cmFortranParser_Input(cmFortranParser* parser, char* buffer,
n = 1;
ff.LastCharWasNewline = true;
}
- return (int)n;
+ return static_cast<int>(n);
}
return 0;
}
void cmFortranParser_StringStart(cmFortranParser* parser)
{
- parser->TokenString = "";
+ parser->TokenString.clear();
}
const char* cmFortranParser_StringEnd(cmFortranParser* parser)
@@ -170,11 +185,16 @@ void cmFortranParser_Error(cmFortranParser* parser, const char* msg)
parser->Error = msg ? msg : "unknown error";
}
-void cmFortranParser_RuleUse(cmFortranParser* parser, const char* name)
+void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name)
{
- if (!parser->InPPFalseBranch) {
- parser->Info.Requires.insert(cmSystemTools::LowerCase(name));
+ if (parser->InPPFalseBranch) {
+ return;
}
+
+ // syntax: "use module_name"
+ // requires: "module_name.mod"
+ std::string const& mod_name = cmSystemTools::LowerCase(module_name);
+ parser->Info.Requires.insert(parser->ModName(mod_name));
}
void cmFortranParser_RuleLineDirective(cmFortranParser* parser,
@@ -227,11 +247,63 @@ void cmFortranParser_RuleInclude(cmFortranParser* parser, const char* name)
}
}
-void cmFortranParser_RuleModule(cmFortranParser* parser, const char* name)
+void cmFortranParser_RuleModule(cmFortranParser* parser,
+ const char* module_name)
+{
+ if (parser->InPPFalseBranch) {
+ return;
+ }
+
+ if (!parser->InInterface) {
+ // syntax: "module module_name"
+ // provides: "module_name.mod"
+ std::string const& mod_name = cmSystemTools::LowerCase(module_name);
+ parser->Info.Provides.insert(parser->ModName(mod_name));
+ }
+}
+
+void cmFortranParser_RuleSubmodule(cmFortranParser* parser,
+ const char* module_name,
+ const char* submodule_name)
+{
+ if (parser->InPPFalseBranch) {
+ return;
+ }
+
+ // syntax: "submodule (module_name) submodule_name"
+ // requires: "module_name.mod"
+ // provides: "module_name@submodule_name.smod"
+ //
+ // FIXME: Some compilers split the submodule part of a module into a
+ // separate "module_name.smod" file. Whether it is generated or
+ // not depends on conditions more subtle than we currently detect.
+ // For now we depend directly on "module_name.mod".
+
+ std::string const& mod_name = cmSystemTools::LowerCase(module_name);
+ std::string const& sub_name = cmSystemTools::LowerCase(submodule_name);
+ parser->Info.Requires.insert(parser->ModName(mod_name));
+ parser->Info.Provides.insert(parser->SModName(mod_name, sub_name));
+}
+
+void cmFortranParser_RuleSubmoduleNested(cmFortranParser* parser,
+ const char* module_name,
+ const char* submodule_name,
+ const char* nested_submodule_name)
{
- if (!parser->InPPFalseBranch && !parser->InInterface) {
- parser->Info.Provides.insert(cmSystemTools::LowerCase(name));
+ if (parser->InPPFalseBranch) {
+ return;
}
+
+ // syntax: "submodule (module_name:submodule_name) nested_submodule_name"
+ // requires: "module_name@submodule_name.smod"
+ // provides: "module_name@nested_submodule_name.smod"
+
+ std::string const& mod_name = cmSystemTools::LowerCase(module_name);
+ std::string const& sub_name = cmSystemTools::LowerCase(submodule_name);
+ std::string const& nest_name =
+ cmSystemTools::LowerCase(nested_submodule_name);
+ parser->Info.Requires.insert(parser->SModName(mod_name, sub_name));
+ parser->Info.Provides.insert(parser->SModName(mod_name, nest_name));
}
void cmFortranParser_RuleDefine(cmFortranParser* parser, const char* macro)
diff --git a/Source/cmFunctionBlocker.cxx b/Source/cmFunctionBlocker.cxx
new file mode 100644
index 000000000..5778a7152
--- /dev/null
+++ b/Source/cmFunctionBlocker.cxx
@@ -0,0 +1,46 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFunctionBlocker.h"
+
+#include <cassert>
+#include <sstream>
+#include <utility>
+
+#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+
+bool cmFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
+ cmExecutionStatus& status)
+{
+ if (lff.Name.Lower == this->StartCommandName()) {
+ this->ScopeDepth++;
+ } else if (lff.Name.Lower == this->EndCommandName()) {
+ this->ScopeDepth--;
+ if (this->ScopeDepth == 0U) {
+ cmMakefile& mf = status.GetMakefile();
+ auto self = mf.RemoveFunctionBlocker();
+ assert(self.get() == this);
+
+ if (!this->ArgumentsMatch(lff, mf)) {
+ cmListFileContext const& lfc = this->GetStartingContext();
+ cmListFileContext closingContext =
+ cmListFileContext::FromCommandContext(lff, lfc.FilePath);
+ std::ostringstream e;
+ /* clang-format off */
+ e << "A logical block opening on the line\n"
+ << " " << lfc << "\n"
+ << "closes on the line\n"
+ << " " << closingContext << "\n"
+ << "with mis-matching arguments.";
+ /* clang-format on */
+ mf.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
+ }
+
+ return this->Replay(std::move(this->Functions), status);
+ }
+ }
+
+ this->Functions.push_back(lff);
+ return true;
+}
diff --git a/Source/cmFunctionBlocker.h b/Source/cmFunctionBlocker.h
index b3450b3f2..59bb8927f 100644
--- a/Source/cmFunctionBlocker.h
+++ b/Source/cmFunctionBlocker.h
@@ -3,6 +3,12 @@
#ifndef cmFunctionBlocker_h
#define cmFunctionBlocker_h
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <vector>
+
+#include <cm/string_view>
+
#include "cmListFileCache.h"
class cmExecutionStatus;
@@ -14,19 +20,10 @@ public:
/**
* should a function be blocked
*/
- virtual bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
- cmExecutionStatus& status) = 0;
-
- /**
- * should this function blocker be removed, useful when one function adds a
- * blocker and another must remove it
- */
- virtual bool ShouldRemove(const cmListFileFunction&, cmMakefile&)
- {
- return false;
- }
+ bool IsFunctionBlocked(cmListFileFunction const& lff,
+ cmExecutionStatus& status);
- virtual ~cmFunctionBlocker() {}
+ virtual ~cmFunctionBlocker() = default;
/** Set/Get the context in which this blocker is created. */
void SetStartingContext(cmListFileContext const& lfc)
@@ -39,7 +36,19 @@ public:
}
private:
+ virtual cm::string_view StartCommandName() const = 0;
+ virtual cm::string_view EndCommandName() const = 0;
+
+ virtual bool ArgumentsMatch(cmListFileFunction const& lff,
+ cmMakefile& mf) const = 0;
+
+ virtual bool Replay(std::vector<cmListFileFunction> functions,
+ cmExecutionStatus& status) = 0;
+
+private:
cmListFileContext StartingContext;
+ std::vector<cmListFileFunction> Functions;
+ unsigned int ScopeDepth = 1;
};
#endif
diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx
index ee52bde37..b3ddfe01f 100644
--- a/Source/cmFunctionCommand.cxx
+++ b/Source/cmFunctionCommand.cxx
@@ -3,111 +3,96 @@
#include "cmFunctionCommand.h"
#include <sstream>
+#include <utility>
+
+#include <cm/memory>
+#include <cm/string_view>
+
+#include "cm_static_string_view.hxx"
#include "cmAlgorithms.h"
#include "cmExecutionStatus.h"
+#include "cmFunctionBlocker.h"
+#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
+#include "cmRange.h"
#include "cmState.h"
-#include "cmSystemTools.h"
+#include "cmStringAlgorithms.h"
+namespace {
// define the class for function commands
-class cmFunctionHelperCommand : public cmCommand
+class cmFunctionHelperCommand
{
public:
- cmFunctionHelperCommand() {}
-
- ///! clean up any memory allocated by the function
- ~cmFunctionHelperCommand() CM_OVERRIDE {}
-
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE
- {
- cmFunctionHelperCommand* newC = new cmFunctionHelperCommand;
- // we must copy when we clone
- newC->Args = this->Args;
- newC->Functions = this->Functions;
- newC->Policies = this->Policies;
- newC->FilePath = this->FilePath;
- return newC;
- }
-
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
- cmExecutionStatus&) CM_OVERRIDE;
-
- bool InitialPass(std::vector<std::string> const&,
- cmExecutionStatus&) CM_OVERRIDE
- {
- return false;
- }
+ bool operator()(std::vector<cmListFileArgument> const& args,
+ cmExecutionStatus& inStatus) const;
std::vector<std::string> Args;
std::vector<cmListFileFunction> Functions;
cmPolicies::PolicyMap Policies;
std::string FilePath;
};
+}
-bool cmFunctionHelperCommand::InvokeInitialPass(
- const std::vector<cmListFileArgument>& args, cmExecutionStatus& inStatus)
+bool cmFunctionHelperCommand::operator()(
+ std::vector<cmListFileArgument> const& args,
+ cmExecutionStatus& inStatus) const
{
+ cmMakefile& makefile = inStatus.GetMakefile();
+
// Expand the argument list to the function.
std::vector<std::string> expandedArgs;
- this->Makefile->ExpandArguments(args, expandedArgs);
+ makefile.ExpandArguments(args, expandedArgs);
// make sure the number of arguments passed is at least the number
// required by the signature
if (expandedArgs.size() < this->Args.size() - 1) {
- std::string errorMsg =
- "Function invoked with incorrect arguments for function named: ";
- errorMsg += this->Args[0];
- this->SetError(errorMsg);
+ std::string errorMsg = cmStrCat(
+ "Function invoked with incorrect arguments for function named: ",
+ this->Args[0]);
+ inStatus.SetError(errorMsg);
return false;
}
- cmMakefile::FunctionPushPop functionScope(this->Makefile, this->FilePath,
+ cmMakefile::FunctionPushPop functionScope(&makefile, this->FilePath,
this->Policies);
// set the value of argc
- std::ostringstream strStream;
- strStream << expandedArgs.size();
- this->Makefile->AddDefinition("ARGC", strStream.str().c_str());
- this->Makefile->MarkVariableAsUsed("ARGC");
+ makefile.AddDefinition("ARGC", std::to_string(expandedArgs.size()));
+ makefile.MarkVariableAsUsed("ARGC");
// set the values for ARGV0 ARGV1 ...
for (unsigned int t = 0; t < expandedArgs.size(); ++t) {
std::ostringstream tmpStream;
tmpStream << "ARGV" << t;
- this->Makefile->AddDefinition(tmpStream.str(), expandedArgs[t].c_str());
- this->Makefile->MarkVariableAsUsed(tmpStream.str());
+ makefile.AddDefinition(tmpStream.str(), expandedArgs[t]);
+ makefile.MarkVariableAsUsed(tmpStream.str());
}
// define the formal arguments
for (unsigned int j = 1; j < this->Args.size(); ++j) {
- this->Makefile->AddDefinition(this->Args[j], expandedArgs[j - 1].c_str());
+ makefile.AddDefinition(this->Args[j], expandedArgs[j - 1]);
}
// define ARGV and ARGN
std::string argvDef = cmJoin(expandedArgs, ";");
- std::vector<std::string>::const_iterator eit =
- expandedArgs.begin() + (this->Args.size() - 1);
+ auto eit = expandedArgs.begin() + (this->Args.size() - 1);
std::string argnDef = cmJoin(cmMakeRange(eit, expandedArgs.end()), ";");
- this->Makefile->AddDefinition("ARGV", argvDef.c_str());
- this->Makefile->MarkVariableAsUsed("ARGV");
- this->Makefile->AddDefinition("ARGN", argnDef.c_str());
- this->Makefile->MarkVariableAsUsed("ARGN");
+ makefile.AddDefinition("ARGV", argvDef);
+ makefile.MarkVariableAsUsed("ARGV");
+ makefile.AddDefinition("ARGN", argnDef);
+ makefile.MarkVariableAsUsed("ARGN");
// Invoke all the functions that were collected in the block.
// for each function
- for (unsigned int c = 0; c < this->Functions.size(); ++c) {
- cmExecutionStatus status;
- if (!this->Makefile->ExecuteCommand(this->Functions[c], status) ||
- status.GetNestedError()) {
+ for (cmListFileFunction const& func : this->Functions) {
+ cmExecutionStatus status(makefile);
+ if (!makefile.ExecuteCommand(func, status) || status.GetNestedError()) {
// The error message should have already included the call stack
// so we do not need to report an error here.
functionScope.Quiet();
@@ -123,66 +108,57 @@ bool cmFunctionHelperCommand::InvokeInitialPass(
return true;
}
-bool cmFunctionFunctionBlocker::IsFunctionBlocked(
- const cmListFileFunction& lff, cmMakefile& mf, cmExecutionStatus&)
+class cmFunctionFunctionBlocker : public cmFunctionBlocker
{
- // record commands until we hit the ENDFUNCTION
- // at the ENDFUNCTION call we shift gears and start looking for invocations
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "function")) {
- this->Depth++;
- } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endfunction")) {
- // if this is the endfunction for this function then execute
- if (!this->Depth) {
- // create a new command and add it to cmake
- cmFunctionHelperCommand* f = new cmFunctionHelperCommand();
- f->Args = this->Args;
- f->Functions = this->Functions;
- f->FilePath = this->GetStartingContext().FilePath;
- mf.RecordPolicies(f->Policies);
- mf.GetState()->AddScriptedCommand(this->Args[0], f);
- // remove the function blocker now that the function is defined
- mf.RemoveFunctionBlocker(this, lff);
- return true;
- }
- // decrement for each nested function that ends
- this->Depth--;
- }
+public:
+ cm::string_view StartCommandName() const override { return "function"_s; }
+ cm::string_view EndCommandName() const override { return "endfunction"_s; }
- // if it wasn't an endfunction and we are not executing then we must be
- // recording
- this->Functions.push_back(lff);
- return true;
-}
+ bool ArgumentsMatch(cmListFileFunction const&,
+ cmMakefile& mf) const override;
+
+ bool Replay(std::vector<cmListFileFunction> functions,
+ cmExecutionStatus& status) override;
+
+ std::vector<std::string> Args;
+};
-bool cmFunctionFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
- cmMakefile& mf)
+bool cmFunctionFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
+ cmMakefile& mf) const
{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endfunction")) {
- std::vector<std::string> expandedArguments;
- mf.ExpandArguments(lff.Arguments, expandedArguments,
- this->GetStartingContext().FilePath.c_str());
- // if the endfunction has arguments then make sure
- // they match the ones in the opening function command
- if ((expandedArguments.empty() ||
- (expandedArguments[0] == this->Args[0]))) {
- return true;
- }
- }
+ std::vector<std::string> expandedArguments;
+ mf.ExpandArguments(lff.Arguments, expandedArguments,
+ this->GetStartingContext().FilePath.c_str());
+ return expandedArguments.empty() || expandedArguments[0] == this->Args[0];
+}
- return false;
+bool cmFunctionFunctionBlocker::Replay(
+ std::vector<cmListFileFunction> functions, cmExecutionStatus& status)
+{
+ cmMakefile& mf = status.GetMakefile();
+ // create a new command and add it to cmake
+ cmFunctionHelperCommand f;
+ f.Args = this->Args;
+ f.Functions = std::move(functions);
+ f.FilePath = this->GetStartingContext().FilePath;
+ mf.RecordPolicies(f.Policies);
+ mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f));
+ return true;
}
-bool cmFunctionCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmFunctionCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
// create a function blocker
- cmFunctionFunctionBlocker* f = new cmFunctionFunctionBlocker();
- f->Args.insert(f->Args.end(), args.begin(), args.end());
- this->Makefile->AddFunctionBlocker(f);
+ {
+ auto fb = cm::make_unique<cmFunctionFunctionBlocker>();
+ cmAppend(fb->Args, args);
+ status.GetMakefile().AddFunctionBlocker(std::move(fb));
+ }
return true;
}
diff --git a/Source/cmFunctionCommand.h b/Source/cmFunctionCommand.h
index f26312632..d6b549c67 100644
--- a/Source/cmFunctionCommand.h
+++ b/Source/cmFunctionCommand.h
@@ -3,47 +3,15 @@
#ifndef cmFunctionCommand_h
#define cmFunctionCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-#include "cmFunctionBlocker.h"
-#include "cmListFileCache.h"
-
class cmExecutionStatus;
-class cmMakefile;
-
-class cmFunctionFunctionBlocker : public cmFunctionBlocker
-{
-public:
- cmFunctionFunctionBlocker() { this->Depth = 0; }
- ~cmFunctionFunctionBlocker() CM_OVERRIDE {}
- bool IsFunctionBlocked(const cmListFileFunction&, cmMakefile& mf,
- cmExecutionStatus&) CM_OVERRIDE;
- bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) CM_OVERRIDE;
-
- std::vector<std::string> Args;
- std::vector<cmListFileFunction> Functions;
- int Depth;
-};
/// Starts function() ... endfunction() block
-class cmFunctionCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmFunctionCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmFunctionCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx
index 6aa593cc0..2af04b691 100644
--- a/Source/cmGeneratedFileStream.cxx
+++ b/Source/cmGeneratedFileStream.cxx
@@ -2,20 +2,19 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratedFileStream.h"
-#include <stdio.h>
+#include <cstdio>
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cm_codecvt.hxx"
-#include "cm_zlib.h"
+#if !defined(CMAKE_BOOTSTRAP)
+# include "cm_codecvt.hxx"
+# include "cm_zlib.h"
#endif
cmGeneratedFileStream::cmGeneratedFileStream(Encoding encoding)
- : cmGeneratedFileStreamBase()
- , Stream()
{
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
if (encoding != codecvt::None) {
imbue(std::locale(getloc(), new codecvt(encoding)));
}
@@ -24,18 +23,17 @@ cmGeneratedFileStream::cmGeneratedFileStream(Encoding encoding)
#endif
}
-cmGeneratedFileStream::cmGeneratedFileStream(const char* name, bool quiet,
- Encoding encoding)
+cmGeneratedFileStream::cmGeneratedFileStream(std::string const& name,
+ bool quiet, Encoding encoding)
: cmGeneratedFileStreamBase(name)
, Stream(TempName.c_str())
{
// Check if the file opened.
if (!*this && !quiet) {
- cmSystemTools::Error("Cannot open file for write: ",
- this->TempName.c_str());
+ cmSystemTools::Error("Cannot open file for write: " + this->TempName);
cmSystemTools::ReportLastSystemError("");
}
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
if (encoding != codecvt::None) {
imbue(std::locale(getloc(), new codecvt(encoding)));
}
@@ -54,7 +52,7 @@ cmGeneratedFileStream::~cmGeneratedFileStream()
this->Okay = !this->fail();
}
-cmGeneratedFileStream& cmGeneratedFileStream::Open(const char* name,
+cmGeneratedFileStream& cmGeneratedFileStream::Open(std::string const& name,
bool quiet, bool binaryFlag)
{
// Store the file name and construct the temporary file name.
@@ -70,8 +68,7 @@ cmGeneratedFileStream& cmGeneratedFileStream::Open(const char* name,
// Check if the file opened.
if (!*this && !quiet) {
- cmSystemTools::Error("Cannot open file for write: ",
- this->TempName.c_str());
+ cmSystemTools::Error("Cannot open file for write: " + this->TempName);
cmSystemTools::ReportLastSystemError("");
}
return *this;
@@ -104,23 +101,9 @@ void cmGeneratedFileStream::SetCompressionExtraExtension(bool ext)
this->CompressExtraExtension = ext;
}
-cmGeneratedFileStreamBase::cmGeneratedFileStreamBase()
- : Name()
- , TempName()
- , CopyIfDifferent(false)
- , Okay(false)
- , Compress(false)
- , CompressExtraExtension(true)
-{
-}
+cmGeneratedFileStreamBase::cmGeneratedFileStreamBase() = default;
-cmGeneratedFileStreamBase::cmGeneratedFileStreamBase(const char* name)
- : Name()
- , TempName()
- , CopyIfDifferent(false)
- , Okay(false)
- , Compress(false)
- , CompressExtraExtension(true)
+cmGeneratedFileStreamBase::cmGeneratedFileStreamBase(std::string const& name)
{
this->Open(name);
}
@@ -130,7 +113,7 @@ cmGeneratedFileStreamBase::~cmGeneratedFileStreamBase()
this->Close();
}
-void cmGeneratedFileStreamBase::Open(const char* name)
+void cmGeneratedFileStreamBase::Open(std::string const& name)
{
// Save the original name of the file.
this->Name = name;
@@ -147,7 +130,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()
@@ -167,13 +150,13 @@ bool cmGeneratedFileStreamBase::Close()
// The destination is to be replaced. Rename the temporary to the
// destination atomically.
if (this->Compress) {
- std::string gzname = this->TempName + ".temp.gz";
- if (this->CompressFile(this->TempName.c_str(), gzname.c_str())) {
- this->RenameFile(gzname.c_str(), resname.c_str());
+ std::string gzname = cmStrCat(this->TempName, ".temp.gz");
+ if (this->CompressFile(this->TempName, gzname)) {
+ this->RenameFile(gzname, resname);
}
cmSystemTools::RemoveFile(gzname);
} else {
- this->RenameFile(this->TempName.c_str(), resname.c_str());
+ this->RenameFile(this->TempName, resname);
}
replaced = true;
@@ -187,11 +170,11 @@ bool cmGeneratedFileStreamBase::Close()
return replaced;
}
-#ifdef CMAKE_BUILD_WITH_CMAKE
-int cmGeneratedFileStreamBase::CompressFile(const char* oldname,
- const char* newname)
+#ifndef CMAKE_BOOTSTRAP
+int cmGeneratedFileStreamBase::CompressFile(std::string const& oldname,
+ std::string const& newname)
{
- gzFile gf = gzopen(newname, "w");
+ gzFile gf = gzopen(newname.c_str(), "w");
if (!gf) {
return 0;
}
@@ -214,14 +197,15 @@ int cmGeneratedFileStreamBase::CompressFile(const char* oldname,
return 1;
}
#else
-int cmGeneratedFileStreamBase::CompressFile(const char*, const char*)
+int cmGeneratedFileStreamBase::CompressFile(std::string const&,
+ std::string const&)
{
return 0;
}
#endif
-int cmGeneratedFileStreamBase::RenameFile(const char* oldname,
- const char* newname)
+int cmGeneratedFileStreamBase::RenameFile(std::string const& oldname,
+ std::string const& newname)
{
return cmSystemTools::RenameFile(oldname, newname);
}
diff --git a/Source/cmGeneratedFileStream.h b/Source/cmGeneratedFileStream.h
index 56f9988ff..a9088ac8a 100644
--- a/Source/cmGeneratedFileStream.h
+++ b/Source/cmGeneratedFileStream.h
@@ -3,12 +3,14 @@
#ifndef cmGeneratedFileStream_h
#define cmGeneratedFileStream_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cm_codecvt.hxx"
-#include "cmsys/FStream.hxx"
#include <string>
+#include "cmsys/FStream.hxx"
+
+#include "cm_codecvt.hxx"
+
// This is the first base class of cmGeneratedFileStream. It will be
// created before and destroyed after the ofstream portion and can
// therefore be used to manage the temporary file.
@@ -20,7 +22,7 @@ protected:
cmGeneratedFileStreamBase();
// This constructor prepares the temporary output file.
- cmGeneratedFileStreamBase(const char* name);
+ cmGeneratedFileStreamBase(std::string const& name);
// The destructor renames the temporary output file to the real name.
~cmGeneratedFileStreamBase();
@@ -29,14 +31,14 @@ protected:
// called before the real stream is opened. Close is always called
// after the real stream is closed and Okay is set to whether the
// real stream was still valid for writing when it was closed.
- void Open(const char* name);
+ void Open(std::string const& name);
bool Close();
// Internal file replacement implementation.
- int RenameFile(const char* oldname, const char* newname);
+ int RenameFile(std::string const& oldname, std::string const& newname);
// Internal file compression implementation.
- int CompressFile(const char* oldname, const char* newname);
+ int CompressFile(std::string const& oldname, std::string const& newname);
// The name of the final destination file for the output.
std::string Name;
@@ -45,16 +47,16 @@ protected:
std::string TempName;
// Whether to do a copy-if-different.
- bool CopyIfDifferent;
+ bool CopyIfDifferent = false;
// Whether the real file stream was valid when it was closed.
- bool Okay;
+ bool Okay = false;
// Whether the destination file is compressed
- bool Compress;
+ bool Compress = false;
// Whether the destination file is compressed
- bool CompressExtraExtension;
+ bool CompressExtraExtension = true;
};
/** \class cmGeneratedFileStream
@@ -67,12 +69,13 @@ protected:
* contents have changed to prevent the file modification time from
* being updated.
*/
-class cmGeneratedFileStream : private cmGeneratedFileStreamBase,
- public cmsys::ofstream
+class cmGeneratedFileStream
+ : private cmGeneratedFileStreamBase
+ , public cmsys::ofstream
{
public:
- typedef cmsys::ofstream Stream;
- typedef codecvt::Encoding Encoding;
+ using Stream = cmsys::ofstream;
+ using Encoding = codecvt::Encoding;
/**
* This constructor prepares a default stream. The open method must
@@ -86,7 +89,7 @@ public:
* file cannot be opened an error message is produced unless the
* second argument is set to true.
*/
- cmGeneratedFileStream(const char* name, bool quiet = false,
+ cmGeneratedFileStream(std::string const& name, bool quiet = false,
Encoding encoding = codecvt::None);
/**
@@ -94,7 +97,9 @@ public:
* file was successfully written before allowing the original to be
* replaced.
*/
- ~cmGeneratedFileStream() CM_OVERRIDE;
+ ~cmGeneratedFileStream() override;
+
+ cmGeneratedFileStream(cmGeneratedFileStream const&) = delete;
/**
* Open an output file by name. This should be used only with a
@@ -102,13 +107,13 @@ public:
* temporary file. If the file cannot be opened an error message is
* produced unless the second argument is set to true.
*/
- cmGeneratedFileStream& Open(const char* name, bool quiet = false,
+ cmGeneratedFileStream& Open(std::string const& name, bool quiet = false,
bool binaryFlag = false);
/**
* Close the output file. This should be used only with an open
* stream. The temporary file is atomically renamed to the
- * destionation file if the stream is still valid when this method
+ * destination file if the stream is still valid when this method
* is called.
*/
bool Close();
@@ -133,9 +138,6 @@ public:
* the output file to be changed during the use of cmGeneratedFileStream.
*/
void SetName(const std::string& fname);
-
-private:
- cmGeneratedFileStream(cmGeneratedFileStream const&); // not implemented
};
#endif
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 00b5ff4ef..b7f7d1d9b 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -2,86 +2,97 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorExpression.h"
-#include "cmsys/RegularExpression.hxx"
+#include <cassert>
+#include <memory>
#include <utility>
-#include "assert.h"
+#include "cmsys/RegularExpression.hxx"
+
#include "cmAlgorithms.h"
#include "cmGeneratorExpressionContext.h"
+#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorExpressionEvaluator.h"
#include "cmGeneratorExpressionLexer.h"
#include "cmGeneratorExpressionParser.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cm_auto_ptr.hxx"
-cmGeneratorExpression::cmGeneratorExpression(
- const cmListFileBacktrace& backtrace)
- : Backtrace(backtrace)
+cmGeneratorExpression::cmGeneratorExpression(cmListFileBacktrace backtrace)
+ : Backtrace(std::move(backtrace))
{
}
-CM_AUTO_PTR<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse(
- std::string const& input)
+cmGeneratorExpression::~cmGeneratorExpression() = default;
+
+std::unique_ptr<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse(
+ std::string input) const
{
- return CM_AUTO_PTR<cmCompiledGeneratorExpression>(
- new cmCompiledGeneratorExpression(this->Backtrace, input));
+ return std::unique_ptr<cmCompiledGeneratorExpression>(
+ new cmCompiledGeneratorExpression(this->Backtrace, std::move(input)));
}
-CM_AUTO_PTR<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse(
- const char* input)
+std::unique_ptr<cmCompiledGeneratorExpression> cmGeneratorExpression::Parse(
+ const char* input) const
{
return this->Parse(std::string(input ? input : ""));
}
-cmGeneratorExpression::~cmGeneratorExpression()
+std::string cmGeneratorExpression::Evaluate(
+ std::string input, cmLocalGenerator* lg, const std::string& config,
+ cmGeneratorTarget const* headTarget,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ cmGeneratorTarget const* currentTarget, std::string const& language)
{
+ if (Find(input) != std::string::npos) {
+ cmCompiledGeneratorExpression cge(cmListFileBacktrace(), std::move(input));
+ return cge.Evaluate(lg, config, headTarget, dagChecker, currentTarget,
+ language);
+ }
+ return input;
}
-const char* cmCompiledGeneratorExpression::Evaluate(
- cmLocalGenerator* lg, const std::string& config, bool quiet,
- const cmGeneratorTarget* headTarget,
+std::string cmGeneratorExpression::Evaluate(
+ const char* input, cmLocalGenerator* lg, const std::string& config,
+ cmGeneratorTarget const* headTarget,
cmGeneratorExpressionDAGChecker* dagChecker,
- std::string const& language) const
+ cmGeneratorTarget const* currentTarget, std::string const& language)
{
- return this->Evaluate(lg, config, quiet, headTarget, headTarget, dagChecker,
- language);
+ return input ? Evaluate(std::string(input), lg, config, headTarget,
+ dagChecker, currentTarget, language)
+ : "";
}
-const char* cmCompiledGeneratorExpression::Evaluate(
- cmLocalGenerator* lg, const std::string& config, bool quiet,
- const cmGeneratorTarget* headTarget, const cmGeneratorTarget* currentTarget,
+const std::string& cmCompiledGeneratorExpression::Evaluate(
+ cmLocalGenerator* lg, const std::string& config,
+ const cmGeneratorTarget* headTarget,
cmGeneratorExpressionDAGChecker* dagChecker,
- std::string const& language) const
+ const cmGeneratorTarget* currentTarget, std::string const& language) const
{
cmGeneratorExpressionContext context(
- lg, config, quiet, headTarget, currentTarget ? currentTarget : headTarget,
- this->EvaluateForBuildsystem, this->Backtrace, language);
+ lg, config, this->Quiet, headTarget,
+ currentTarget ? currentTarget : headTarget, this->EvaluateForBuildsystem,
+ this->Backtrace, language);
return this->EvaluateWithContext(context, dagChecker);
}
-const char* cmCompiledGeneratorExpression::EvaluateWithContext(
+const std::string& cmCompiledGeneratorExpression::EvaluateWithContext(
cmGeneratorExpressionContext& context,
cmGeneratorExpressionDAGChecker* dagChecker) const
{
if (!this->NeedsEvaluation) {
- return this->Input.c_str();
+ return this->Input;
}
- this->Output = "";
+ this->Output.clear();
- std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it =
- this->Evaluators.begin();
- const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end =
- this->Evaluators.end();
+ for (const cmGeneratorExpressionEvaluator* it : this->Evaluators) {
+ this->Output += it->Evaluate(&context, dagChecker);
- for (; it != end; ++it) {
- this->Output += (*it)->Evaluate(&context, dagChecker);
-
- this->SeenTargetProperties.insert(context.SeenTargetProperties.begin(),
- context.SeenTargetProperties.end());
+ this->SeenTargetProperties.insert(context.SeenTargetProperties.cbegin(),
+ context.SeenTargetProperties.cend());
if (context.HadError) {
- this->Output = "";
+ this->Output.clear();
break;
}
}
@@ -96,17 +107,17 @@ const char* cmCompiledGeneratorExpression::EvaluateWithContext(
this->DependTargets = context.DependTargets;
this->AllTargetsSeen = context.AllTargets;
- // TODO: Return a std::string from here instead?
- return this->Output.c_str();
+ return this->Output;
}
cmCompiledGeneratorExpression::cmCompiledGeneratorExpression(
- cmListFileBacktrace const& backtrace, const std::string& input)
- : Backtrace(backtrace)
- , Input(input)
+ cmListFileBacktrace backtrace, std::string input)
+ : Backtrace(std::move(backtrace))
+ , Input(std::move(input))
+ , EvaluateForBuildsystem(false)
+ , Quiet(false)
, HadContextSensitiveCondition(false)
, HadHeadSensitiveCondition(false)
- , EvaluateForBuildsystem(false)
{
cmGeneratorExpressionLexer l;
std::vector<cmGeneratorExpressionToken> tokens = l.Tokenize(this->Input);
@@ -168,7 +179,7 @@ static std::string stripAllGeneratorExpressions(const std::string& input)
const char* c = input.c_str() + pos;
const char* const cStart = c;
for (; *c; ++c) {
- if (c[0] == '$' && c[1] == '<') {
+ if (cmGeneratorExpression::StartsWithGeneratorExpression(c)) {
++nestingLevel;
++c;
continue;
@@ -199,15 +210,14 @@ static void prefixItems(const std::string& content, std::string& result,
std::vector<std::string> entries;
cmGeneratorExpression::Split(content, entries);
const char* sep = "";
- for (std::vector<std::string>::const_iterator ei = entries.begin();
- ei != entries.end(); ++ei) {
+ for (std::string const& e : entries) {
result += sep;
sep = ";";
- if (!cmSystemTools::FileIsFullPath(ei->c_str()) &&
- cmGeneratorExpression::Find(*ei) != 0) {
+ if (!cmSystemTools::FileIsFullPath(e) &&
+ cmGeneratorExpression::Find(e) != 0) {
result += prefix;
}
- result += *ei;
+ result += e;
}
}
@@ -244,7 +254,7 @@ static std::string stripExportInterface(
const char* c = input.c_str() + pos;
const char* const cStart = c;
for (; *c; ++c) {
- if (c[0] == '$' && c[1] == '<') {
+ if (cmGeneratorExpression::StartsWithGeneratorExpression(c)) {
++nestingLevel;
++c;
continue;
@@ -297,13 +307,13 @@ void cmGeneratorExpression::Split(const std::string& input,
std::string::size_type startPos = input.rfind(';', pos);
if (startPos == std::string::npos) {
preGenex = part;
- part = "";
+ part.clear();
} else if (startPos != pos - 1 && startPos >= lastPos) {
part = input.substr(lastPos, startPos - lastPos);
preGenex = input.substr(startPos + 1, pos - startPos - 1);
}
if (!part.empty()) {
- cmSystemTools::ExpandListArgument(part, output);
+ cmExpandList(part, output);
}
}
pos += 2;
@@ -311,7 +321,7 @@ void cmGeneratorExpression::Split(const std::string& input,
const char* c = input.c_str() + pos;
const char* const cStart = c;
for (; *c; ++c) {
- if (c[0] == '$' && c[1] == '<') {
+ if (cmGeneratorExpression::StartsWithGeneratorExpression(c)) {
++nestingLevel;
++c;
continue;
@@ -336,7 +346,7 @@ void cmGeneratorExpression::Split(const std::string& input,
lastPos = pos;
}
if (lastPos < input.size()) {
- cmSystemTools::ExpandListArgument(input.substr(lastPos), output);
+ cmExpandList(input.substr(lastPos), output);
}
}
@@ -378,11 +388,31 @@ bool cmGeneratorExpression::IsValidTargetName(const std::string& input)
void cmCompiledGeneratorExpression::GetMaxLanguageStandard(
const cmGeneratorTarget* tgt, std::map<std::string, std::string>& mapping)
{
- typedef std::map<cmGeneratorTarget const*,
- std::map<std::string, std::string> >
- MapType;
- MapType::const_iterator it = this->MaxLanguageStandard.find(tgt);
+ auto it = this->MaxLanguageStandard.find(tgt);
if (it != this->MaxLanguageStandard.end()) {
mapping = it->second;
}
}
+
+const std::string& cmGeneratorExpressionInterpreter::Evaluate(
+ std::string expression, const std::string& property)
+{
+ this->CompiledGeneratorExpression =
+ this->GeneratorExpression.Parse(std::move(expression));
+
+ // Specify COMPILE_OPTIONS to DAGchecker, same semantic as COMPILE_FLAGS
+ cmGeneratorExpressionDAGChecker dagChecker(
+ this->HeadTarget,
+ property == "COMPILE_FLAGS" ? "COMPILE_OPTIONS" : property, nullptr,
+ nullptr);
+
+ return this->CompiledGeneratorExpression->Evaluate(
+ this->LocalGenerator, this->Config, this->HeadTarget, &dagChecker, nullptr,
+ this->Language);
+}
+
+const std::string& cmGeneratorExpressionInterpreter::Evaluate(
+ const char* expression, const std::string& property)
+{
+ return this->Evaluate(std::string(expression ? expression : ""), property);
+}
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index 34516f5c5..4bd1c9f88 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -3,16 +3,17 @@
#ifndef cmGeneratorExpression_h
#define cmGeneratorExpression_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmListFileCache.h"
-
-#include "cm_auto_ptr.hxx"
#include <map>
+#include <memory>
#include <set>
#include <string>
+#include <utility>
#include <vector>
+#include "cmListFileCache.h"
+
class cmCompiledGeneratorExpression;
class cmGeneratorTarget;
class cmLocalGenerator;
@@ -31,16 +32,31 @@ struct cmGeneratorExpressionEvaluator;
*/
class cmGeneratorExpression
{
- CM_DISABLE_COPY(cmGeneratorExpression)
-
public:
/** Construct. */
- cmGeneratorExpression(
- cmListFileBacktrace const& backtrace = cmListFileBacktrace());
+ cmGeneratorExpression(cmListFileBacktrace backtrace = cmListFileBacktrace());
~cmGeneratorExpression();
- CM_AUTO_PTR<cmCompiledGeneratorExpression> Parse(std::string const& input);
- CM_AUTO_PTR<cmCompiledGeneratorExpression> Parse(const char* input);
+ cmGeneratorExpression(cmGeneratorExpression const&) = delete;
+ cmGeneratorExpression& operator=(cmGeneratorExpression const&) = delete;
+
+ std::unique_ptr<cmCompiledGeneratorExpression> Parse(
+ std::string input) const;
+ std::unique_ptr<cmCompiledGeneratorExpression> Parse(
+ const char* input) const;
+
+ static std::string Evaluate(
+ std::string input, cmLocalGenerator* lg, const std::string& config,
+ cmGeneratorTarget const* headTarget = nullptr,
+ cmGeneratorExpressionDAGChecker* dagChecker = nullptr,
+ cmGeneratorTarget const* currentTarget = nullptr,
+ std::string const& language = std::string());
+ static std::string Evaluate(
+ const char* input, cmLocalGenerator* lg, const std::string& config,
+ cmGeneratorTarget const* headTarget = nullptr,
+ cmGeneratorExpressionDAGChecker* dagChecker = nullptr,
+ cmGeneratorTarget const* currentTarget = nullptr,
+ std::string const& language = std::string());
enum PreprocessContext
{
@@ -62,25 +78,34 @@ public:
static std::string StripEmptyListElements(const std::string& input);
+ static inline bool StartsWithGeneratorExpression(const std::string& input)
+ {
+ return input.length() >= 2 && input[0] == '$' && input[1] == '<';
+ }
+ static inline bool StartsWithGeneratorExpression(const char* input)
+ {
+ return input != nullptr && input[0] == '$' && input[1] == '<';
+ }
+
private:
cmListFileBacktrace Backtrace;
};
class cmCompiledGeneratorExpression
{
- CM_DISABLE_COPY(cmCompiledGeneratorExpression)
-
public:
- const char* Evaluate(
- cmLocalGenerator* lg, const std::string& config, bool quiet = false,
- cmGeneratorTarget const* headTarget = CM_NULLPTR,
- cmGeneratorTarget const* currentTarget = CM_NULLPTR,
- cmGeneratorExpressionDAGChecker* dagChecker = CM_NULLPTR,
+ ~cmCompiledGeneratorExpression();
+
+ cmCompiledGeneratorExpression(cmCompiledGeneratorExpression const&) = delete;
+ cmCompiledGeneratorExpression& operator=(
+ cmCompiledGeneratorExpression const&) = delete;
+
+ const std::string& Evaluate(
+ cmLocalGenerator* lg, const std::string& config,
+ cmGeneratorTarget const* headTarget = nullptr,
+ cmGeneratorExpressionDAGChecker* dagChecker = nullptr,
+ cmGeneratorTarget const* currentTarget = nullptr,
std::string const& language = std::string()) const;
- const char* Evaluate(cmLocalGenerator* lg, const std::string& config,
- bool quiet, cmGeneratorTarget const* headTarget,
- cmGeneratorExpressionDAGChecker* dagChecker,
- std::string const& language = std::string()) const;
/** Get set of targets found during evaluations. */
std::set<cmGeneratorTarget*> const& GetTargets() const
@@ -98,8 +123,6 @@ public:
return this->AllTargetsSeen;
}
- ~cmCompiledGeneratorExpression();
-
std::string const& GetInput() const { return this->Input; }
cmListFileBacktrace GetBacktrace() const { return this->Backtrace; }
@@ -121,16 +144,18 @@ public:
this->EvaluateForBuildsystem = eval;
}
+ void SetQuiet(bool quiet) { this->Quiet = quiet; }
+
void GetMaxLanguageStandard(cmGeneratorTarget const* tgt,
std::map<std::string, std::string>& mapping);
private:
- const char* EvaluateWithContext(
+ const std::string& EvaluateWithContext(
cmGeneratorExpressionContext& context,
cmGeneratorExpressionDAGChecker* dagChecker) const;
- cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace,
- const std::string& input);
+ cmCompiledGeneratorExpression(cmListFileBacktrace backtrace,
+ std::string input);
friend class cmGeneratorExpression;
@@ -138,18 +163,52 @@ private:
std::vector<cmGeneratorExpressionEvaluator*> Evaluators;
const std::string Input;
bool NeedsEvaluation;
+ bool EvaluateForBuildsystem;
+ bool Quiet;
mutable std::set<cmGeneratorTarget*> DependTargets;
mutable std::set<cmGeneratorTarget const*> AllTargetsSeen;
mutable std::set<std::string> SeenTargetProperties;
mutable std::map<cmGeneratorTarget const*,
- std::map<std::string, std::string> >
+ std::map<std::string, std::string>>
MaxLanguageStandard;
mutable std::string Output;
mutable bool HadContextSensitiveCondition;
mutable bool HadHeadSensitiveCondition;
mutable std::set<cmGeneratorTarget const*> SourceSensitiveTargets;
- bool EvaluateForBuildsystem;
+};
+
+class cmGeneratorExpressionInterpreter
+{
+public:
+ cmGeneratorExpressionInterpreter(cmLocalGenerator* localGenerator,
+ std::string config,
+ cmGeneratorTarget const* headTarget,
+ std::string language = std::string())
+ : LocalGenerator(localGenerator)
+ , Config(std::move(config))
+ , HeadTarget(headTarget)
+ , Language(std::move(language))
+ {
+ }
+
+ cmGeneratorExpressionInterpreter(cmGeneratorExpressionInterpreter const&) =
+ delete;
+ cmGeneratorExpressionInterpreter& operator=(
+ cmGeneratorExpressionInterpreter const&) = delete;
+
+ const std::string& Evaluate(std::string expression,
+ const std::string& property);
+ const std::string& Evaluate(const char* expression,
+ const std::string& property);
+
+protected:
+ cmGeneratorExpression GeneratorExpression;
+ std::unique_ptr<cmCompiledGeneratorExpression> CompiledGeneratorExpression;
+ cmLocalGenerator* LocalGenerator = nullptr;
+ std::string Config;
+ cmGeneratorTarget const* HeadTarget = nullptr;
+ std::string Language;
};
#endif
diff --git a/Source/cmGeneratorExpressionContext.cxx b/Source/cmGeneratorExpressionContext.cxx
index a6dde5d39..6d973310c 100644
--- a/Source/cmGeneratorExpressionContext.cxx
+++ b/Source/cmGeneratorExpressionContext.cxx
@@ -2,15 +2,17 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorExpressionContext.h"
+#include <utility>
+
cmGeneratorExpressionContext::cmGeneratorExpressionContext(
- cmLocalGenerator* lg, std::string const& config, bool quiet,
+ cmLocalGenerator* lg, std::string config, bool quiet,
cmGeneratorTarget const* headTarget, const cmGeneratorTarget* currentTarget,
- bool evaluateForBuildsystem, cmListFileBacktrace const& backtrace,
- std::string const& language)
- : Backtrace(backtrace)
+ bool evaluateForBuildsystem, cmListFileBacktrace backtrace,
+ std::string language)
+ : Backtrace(std::move(backtrace))
, LG(lg)
- , Config(config)
- , Language(language)
+ , Config(std::move(config))
+ , Language(std::move(language))
, HeadTarget(headTarget)
, CurrentTarget(currentTarget)
, Quiet(quiet)
diff --git a/Source/cmGeneratorExpressionContext.h b/Source/cmGeneratorExpressionContext.h
index cf292dcef..4709fa024 100644
--- a/Source/cmGeneratorExpressionContext.h
+++ b/Source/cmGeneratorExpressionContext.h
@@ -3,30 +3,30 @@
#ifndef cmGeneratorExpressionContext_h
#define cmGeneratorExpressionContext_h
-#include "cmListFileCache.h"
-
#include <map>
#include <set>
#include <string>
+#include "cmListFileCache.h"
+
class cmGeneratorTarget;
class cmLocalGenerator;
struct cmGeneratorExpressionContext
{
- cmGeneratorExpressionContext(cmLocalGenerator* lg, std::string const& config,
+ cmGeneratorExpressionContext(cmLocalGenerator* lg, std::string config,
bool quiet, const cmGeneratorTarget* headTarget,
cmGeneratorTarget const* currentTarget,
bool evaluateForBuildsystem,
- cmListFileBacktrace const& backtrace,
- std::string const& language);
+ cmListFileBacktrace backtrace,
+ std::string language);
cmListFileBacktrace Backtrace;
std::set<cmGeneratorTarget*> DependTargets;
std::set<cmGeneratorTarget const*> AllTargets;
std::set<std::string> SeenTargetProperties;
std::set<cmGeneratorTarget const*> SourceSensitiveTargets;
- std::map<cmGeneratorTarget const*, std::map<std::string, std::string> >
+ std::map<cmGeneratorTarget const*, std::map<std::string, std::string>>
MaxLanguageStandard;
cmLocalGenerator* LG;
std::string Config;
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index c0266311b..643ba346d 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -2,38 +2,39 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorExpressionDAGChecker.h"
-#include "cmAlgorithms.h"
+#include <cstring>
+#include <sstream>
+#include <utility>
+
#include "cmGeneratorExpressionContext.h"
#include "cmGeneratorExpressionEvaluator.h"
#include "cmGeneratorTarget.h"
#include "cmLocalGenerator.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
#include "cmake.h"
-#include <sstream>
-#include <string.h>
-#include <utility>
-
cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
- const cmListFileBacktrace& backtrace, const std::string& target,
- const std::string& property, const GeneratorExpressionContent* content,
+ cmListFileBacktrace backtrace, cmGeneratorTarget const* target,
+ std::string property, const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* parent)
: Parent(parent)
, Target(target)
- , Property(property)
+ , Property(std::move(property))
, Content(content)
- , Backtrace(backtrace)
+ , Backtrace(std::move(backtrace))
, TransitivePropertiesOnly(false)
{
Initialize();
}
cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
- const std::string& target, const std::string& property,
+ cmGeneratorTarget const* target, std::string property,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* parent)
: Parent(parent)
, Target(target)
- , Property(property)
+ , Property(std::move(property))
, Content(content)
, Backtrace()
, TransitivePropertiesOnly(false)
@@ -55,11 +56,10 @@ void cmGeneratorExpressionDAGChecker::Initialize()
if (CheckResult == DAG &&
(CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
- TEST_TRANSITIVE_PROPERTY_METHOD) false)) // NOLINT(clang-tidy)
+ TEST_TRANSITIVE_PROPERTY_METHOD) false)) // NOLINT(*)
#undef TEST_TRANSITIVE_PROPERTY_METHOD
{
- std::map<std::string, std::set<std::string> >::const_iterator it =
- top->Seen.find(this->Target);
+ auto it = top->Seen.find(this->Target);
if (it != top->Seen.end()) {
const std::set<std::string>& propSet = it->second;
if (propSet.find(this->Property) != propSet.end()) {
@@ -67,9 +67,7 @@ void cmGeneratorExpressionDAGChecker::Initialize()
return;
}
}
- const_cast<cmGeneratorExpressionDAGChecker*>(top)
- ->Seen[this->Target]
- .insert(this->Property);
+ top->Seen[this->Target].insert(this->Property);
}
}
@@ -99,8 +97,8 @@ void cmGeneratorExpressionDAGChecker::ReportError(
<< " " << expr << "\n"
<< "Self reference on target \"" << context->HeadTarget->GetName()
<< "\".\n";
- context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
- parent->Backtrace);
+ context->LG->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
+ e.str(), parent->Backtrace);
return;
}
@@ -111,8 +109,8 @@ void cmGeneratorExpressionDAGChecker::ReportError(
<< " " << expr << "\n"
<< "Dependency loop found.";
/* clang-format on */
- context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
- context->Backtrace);
+ context->LG->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
+ e.str(), context->Backtrace);
}
int loopStep = 1;
@@ -122,8 +120,8 @@ void cmGeneratorExpressionDAGChecker::ReportError(
<< " "
<< (parent->Content ? parent->Content->GetOriginalExpression() : expr)
<< "\n";
- context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
- parent->Backtrace);
+ context->LG->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
+ e.str(), parent->Backtrace);
parent = parent->Parent;
++loopStep;
}
@@ -154,7 +152,26 @@ bool cmGeneratorExpressionDAGChecker::GetTransitivePropertiesOnly()
return top->TransitivePropertiesOnly;
}
-bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char* tgt)
+bool cmGeneratorExpressionDAGChecker::EvaluatingGenexExpression()
+{
+ return this->Property.find("TARGET_GENEX_EVAL:") == 0 ||
+ this->Property.find("GENEX_EVAL:", 0) == 0;
+}
+
+bool cmGeneratorExpressionDAGChecker::EvaluatingPICExpression()
+{
+ const cmGeneratorExpressionDAGChecker* top = this;
+ const cmGeneratorExpressionDAGChecker* parent = this->Parent;
+ while (parent) {
+ top = parent;
+ parent = parent->Parent;
+ }
+
+ return top->Property == "INTERFACE_POSITION_INDEPENDENT_CODE";
+}
+
+bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(
+ cmGeneratorTarget const* tgt)
{
const cmGeneratorExpressionDAGChecker* top = this;
const cmGeneratorExpressionDAGChecker* parent = this->Parent;
@@ -177,7 +194,7 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char* tgt)
strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0;
}
-std::string cmGeneratorExpressionDAGChecker::TopTarget() const
+cmGeneratorTarget const* cmGeneratorExpressionDAGChecker::TopTarget() const
{
const cmGeneratorExpressionDAGChecker* top = this;
const cmGeneratorExpressionDAGChecker* parent = this->Parent;
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index 557a19220..f2c49bbf2 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -3,16 +3,17 @@
#ifndef cmGeneratorExpressionDAGChecker_h
#define cmGeneratorExpressionDAGChecker_h
-#include "cmConfigure.h"
-
-#include "cmListFileCache.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
#include <set>
#include <string>
+#include "cmListFileCache.h"
+
struct GeneratorExpressionContent;
struct cmGeneratorExpressionContext;
+class cmGeneratorTarget;
#define CM_SELECT_BOTH(F, A1, A2) F(A1, A2)
#define CM_SELECT_FIRST(F, A1, A2) F(A1)
@@ -25,7 +26,11 @@ struct cmGeneratorExpressionContext;
SELECT(F, EvaluatingCompileOptions, COMPILE_OPTIONS) \
SELECT(F, EvaluatingAutoUicOptions, AUTOUIC_OPTIONS) \
SELECT(F, EvaluatingSources, SOURCES) \
- SELECT(F, EvaluatingCompileFeatures, COMPILE_FEATURES)
+ SELECT(F, EvaluatingCompileFeatures, COMPILE_FEATURES) \
+ SELECT(F, EvaluatingLinkOptions, LINK_OPTIONS) \
+ SELECT(F, EvaluatingLinkDirectories, LINK_DIRECTORIES) \
+ SELECT(F, EvaluatingLinkDepends, LINK_DEPENDS) \
+ SELECT(F, EvaluatingPrecompileHeaders, PRECOMPILE_HEADERS)
#define CM_FOR_EACH_TRANSITIVE_PROPERTY(F) \
CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_BOTH)
@@ -38,13 +43,13 @@ struct cmGeneratorExpressionContext;
struct cmGeneratorExpressionDAGChecker
{
- cmGeneratorExpressionDAGChecker(const cmListFileBacktrace& backtrace,
- const std::string& target,
- const std::string& property,
+ cmGeneratorExpressionDAGChecker(cmListFileBacktrace backtrace,
+ cmGeneratorTarget const* target,
+ std::string property,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* parent);
- cmGeneratorExpressionDAGChecker(const std::string& target,
- const std::string& property,
+ cmGeneratorExpressionDAGChecker(cmGeneratorTarget const* target,
+ std::string property,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* parent);
@@ -61,7 +66,9 @@ struct cmGeneratorExpressionDAGChecker
void ReportError(cmGeneratorExpressionContext* context,
const std::string& expr);
- bool EvaluatingLinkLibraries(const char* tgt = CM_NULLPTR);
+ bool EvaluatingGenexExpression();
+ bool EvaluatingPICExpression();
+ bool EvaluatingLinkLibraries(cmGeneratorTarget const* tgt = nullptr);
#define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const;
@@ -72,7 +79,7 @@ struct cmGeneratorExpressionDAGChecker
bool GetTransitivePropertiesOnly();
void SetTransitivePropertiesOnly() { this->TransitivePropertiesOnly = true; }
- std::string TopTarget() const;
+ cmGeneratorTarget const* TopTarget() const;
private:
Result CheckGraph() const;
@@ -80,9 +87,9 @@ private:
private:
const cmGeneratorExpressionDAGChecker* const Parent;
- const std::string Target;
+ cmGeneratorTarget const* Target;
const std::string Property;
- std::map<std::string, std::set<std::string> > Seen;
+ mutable std::map<cmGeneratorTarget const*, std::set<std::string>> Seen;
const GeneratorExpressionContent* const Content;
const cmListFileBacktrace Backtrace;
Result CheckResult;
diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx
index 15264545b..9e8707d9d 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.cxx
+++ b/Source/cmGeneratorExpressionEvaluationFile.cxx
@@ -2,29 +2,32 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorExpressionEvaluationFile.h"
-#include "cmConfigure.h"
-#include "cmsys/FStream.hxx"
+#include <memory>
#include <sstream>
#include <utility>
+#include "cmsys/FStream.hxx"
+
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmSourceFile.h"
+#include "cmSourceFileLocationKind.h"
#include "cmSystemTools.h"
-#include "cm_auto_ptr.hxx"
-#include "cmake.h"
cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile(
- const std::string& input,
- CM_AUTO_PTR<cmCompiledGeneratorExpression> outputFileExpr,
- CM_AUTO_PTR<cmCompiledGeneratorExpression> condition, bool inputIsContent)
- : Input(input)
- , OutputFileExpr(outputFileExpr)
- , Condition(condition)
+ std::string input,
+ std::unique_ptr<cmCompiledGeneratorExpression> outputFileExpr,
+ std::unique_ptr<cmCompiledGeneratorExpression> condition,
+ bool inputIsContent, cmPolicies::PolicyStatus policyStatusCMP0070)
+ : Input(std::move(input))
+ , OutputFileExpr(std::move(outputFileExpr))
+ , Condition(std::move(condition))
, InputIsContent(inputIsContent)
+ , PolicyStatusCMP0070(policyStatusCMP0070)
{
}
@@ -35,8 +38,8 @@ void cmGeneratorExpressionEvaluationFile::Generate(
{
std::string rawCondition = this->Condition->GetInput();
if (!rawCondition.empty()) {
- std::string condResult = this->Condition->Evaluate(
- lg, config, false, CM_NULLPTR, CM_NULLPTR, CM_NULLPTR, lang);
+ std::string condResult =
+ this->Condition->Evaluate(lg, config, nullptr, nullptr, nullptr, lang);
if (condResult == "0") {
return;
}
@@ -46,18 +49,23 @@ void cmGeneratorExpressionEvaluationFile::Generate(
<< "\" did "
"not evaluate to valid content. Got \""
<< condResult << "\".";
- lg->IssueMessage(cmake::FATAL_ERROR, e.str());
+ lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
}
- const std::string outputFileName = this->OutputFileExpr->Evaluate(
- lg, config, false, CM_NULLPTR, CM_NULLPTR, CM_NULLPTR, lang);
- const std::string outputContent = inputExpression->Evaluate(
- lg, config, false, CM_NULLPTR, CM_NULLPTR, CM_NULLPTR, lang);
+ std::string outputFileName = this->OutputFileExpr->Evaluate(
+ lg, config, nullptr, nullptr, nullptr, lang);
+ const std::string& outputContent =
+ inputExpression->Evaluate(lg, config, nullptr, nullptr, nullptr, lang);
+
+ if (cmSystemTools::FileIsFullPath(outputFileName)) {
+ outputFileName = cmSystemTools::CollapseFullPath(outputFileName);
+ } else {
+ outputFileName = this->FixRelativePath(outputFileName, PathForOutput, lg);
+ }
- std::map<std::string, std::string>::iterator it =
- outputFiles.find(outputFileName);
+ auto it = outputFiles.find(outputFileName);
if (it != outputFiles.end()) {
if (it->second == outputContent) {
@@ -69,7 +77,7 @@ void cmGeneratorExpressionEvaluationFile::Generate(
"This is generally caused by the content evaluating the "
"configuration type, language, or location of object files:\n "
<< outputFileName;
- lg->IssueMessage(cmake::FATAL_ERROR, e.str());
+ lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
@@ -77,7 +85,7 @@ void cmGeneratorExpressionEvaluationFile::Generate(
this->Files.push_back(outputFileName);
outputFiles[outputFileName] = outputContent;
- cmGeneratedFileStream fout(outputFileName.c_str());
+ cmGeneratedFileStream fout(outputFileName);
fout.SetCopyIfDifferent(true);
fout << outputContent;
if (fout.Close() && perm) {
@@ -92,13 +100,19 @@ void cmGeneratorExpressionEvaluationFile::CreateOutputFile(
cmGlobalGenerator* gg = lg->GetGlobalGenerator();
gg->GetEnabledLanguages(enabledLanguages);
- for (std::vector<std::string>::const_iterator le = enabledLanguages.begin();
- le != enabledLanguages.end(); ++le) {
- std::string name = this->OutputFileExpr->Evaluate(
- lg, config, false, CM_NULLPTR, CM_NULLPTR, CM_NULLPTR, *le);
- cmSourceFile* sf = lg->GetMakefile()->GetOrCreateSource(name);
+ for (std::string const& le : enabledLanguages) {
+ std::string name = this->OutputFileExpr->Evaluate(lg, config, nullptr,
+ nullptr, nullptr, le);
+ cmSourceFile* sf = lg->GetMakefile()->GetOrCreateSource(
+ name, false, cmSourceFileLocationKind::Known);
+ // Tell TraceDependencies that the file is not expected to exist
+ // on disk yet. We generate it after that runs.
sf->SetProperty("GENERATED", "1");
+ // Tell the build system generators that there is no build rule
+ // to generate the file.
+ sf->SetProperty("__CMAKE_GENERATED_BY_CMAKE", "1");
+
gg->SetFilenameTargetDepends(
sf, this->OutputFileExpr->GetSourceSensitiveTargets());
}
@@ -111,13 +125,19 @@ void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg)
if (this->InputIsContent) {
inputContent = this->Input;
} else {
- lg->GetMakefile()->AddCMakeDependFile(this->Input);
- cmSystemTools::GetPermissions(this->Input.c_str(), perm);
- cmsys::ifstream fin(this->Input.c_str());
+ std::string inputFileName = this->Input;
+ if (cmSystemTools::FileIsFullPath(inputFileName)) {
+ inputFileName = cmSystemTools::CollapseFullPath(inputFileName);
+ } else {
+ inputFileName = this->FixRelativePath(inputFileName, PathForInput, lg);
+ }
+ lg->GetMakefile()->AddCMakeDependFile(inputFileName);
+ cmSystemTools::GetPermissions(inputFileName.c_str(), perm);
+ cmsys::ifstream fin(inputFileName.c_str());
if (!fin) {
std::ostringstream e;
- e << "Evaluation file \"" << this->Input << "\" cannot be read.";
- lg->IssueMessage(cmake::FATAL_ERROR, e.str());
+ e << "Evaluation file \"" << inputFileName << "\" cannot be read.";
+ lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
@@ -132,7 +152,7 @@ void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg)
cmListFileBacktrace lfbt = this->OutputFileExpr->GetBacktrace();
cmGeneratorExpression contentGE(lfbt);
- CM_AUTO_PTR<cmCompiledGeneratorExpression> inputExpression =
+ std::unique_ptr<cmCompiledGeneratorExpression> inputExpression =
contentGE.Parse(inputContent);
std::map<std::string, std::string> outputFiles;
@@ -141,21 +161,73 @@ void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg)
lg->GetMakefile()->GetConfigurations(allConfigs);
if (allConfigs.empty()) {
- allConfigs.push_back("");
+ allConfigs.emplace_back();
}
std::vector<std::string> enabledLanguages;
cmGlobalGenerator* gg = lg->GetGlobalGenerator();
gg->GetEnabledLanguages(enabledLanguages);
- for (std::vector<std::string>::const_iterator le = enabledLanguages.begin();
- le != enabledLanguages.end(); ++le) {
- for (std::vector<std::string>::const_iterator li = allConfigs.begin();
- li != allConfigs.end(); ++li) {
- this->Generate(lg, *li, *le, inputExpression.get(), outputFiles, perm);
+ for (std::string const& le : enabledLanguages) {
+ for (std::string const& li : allConfigs) {
+ this->Generate(lg, li, le, inputExpression.get(), outputFiles, perm);
if (cmSystemTools::GetFatalErrorOccured()) {
return;
}
}
}
}
+
+std::string cmGeneratorExpressionEvaluationFile::FixRelativePath(
+ std::string const& relativePath, PathRole role, cmLocalGenerator* lg)
+{
+ std::string resultPath;
+ switch (this->PolicyStatusCMP0070) {
+ case cmPolicies::WARN: {
+ std::string arg;
+ switch (role) {
+ case PathForInput:
+ arg = "INPUT";
+ break;
+ case PathForOutput:
+ arg = "OUTPUT";
+ break;
+ }
+ std::ostringstream w;
+ /* clang-format off */
+ w <<
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0070) << "\n"
+ "file(GENERATE) given relative " << arg << " path:\n"
+ " " << relativePath << "\n"
+ "This is not defined behavior unless CMP0070 is set to NEW. "
+ "For compatibility with older versions of CMake, the previous "
+ "undefined behavior will be used."
+ ;
+ /* clang-format on */
+ lg->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
+ }
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // OLD behavior is to use the relative path unchanged,
+ // which ends up being used relative to the working dir.
+ resultPath = relativePath;
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // NEW behavior is to interpret the relative path with respect
+ // to the current source or binary directory.
+ switch (role) {
+ case PathForInput:
+ resultPath = cmSystemTools::CollapseFullPath(
+ relativePath, lg->GetCurrentSourceDirectory());
+ break;
+ case PathForOutput:
+ resultPath = cmSystemTools::CollapseFullPath(
+ relativePath, lg->GetCurrentBinaryDirectory());
+ break;
+ }
+ break;
+ }
+ return resultPath;
+}
diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h
index 98727460e..c3bc4c85b 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.h
+++ b/Source/cmGeneratorExpressionEvaluationFile.h
@@ -6,22 +6,25 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
+#include <memory>
#include <string>
#include <vector>
-#include "cmGeneratorExpression.h"
-#include "cm_auto_ptr.hxx"
#include "cm_sys_stat.h"
+#include "cmGeneratorExpression.h"
+#include "cmPolicies.h"
+
class cmLocalGenerator;
class cmGeneratorExpressionEvaluationFile
{
public:
cmGeneratorExpressionEvaluationFile(
- const std::string& input,
- CM_AUTO_PTR<cmCompiledGeneratorExpression> outputFileExpr,
- CM_AUTO_PTR<cmCompiledGeneratorExpression> condition, bool inputIsContent);
+ std::string input,
+ std::unique_ptr<cmCompiledGeneratorExpression> outputFileExpr,
+ std::unique_ptr<cmCompiledGeneratorExpression> condition,
+ bool inputIsContent, cmPolicies::PolicyStatus policyStatusCMP0070);
void Generate(cmLocalGenerator* lg);
@@ -35,12 +38,21 @@ private:
cmCompiledGeneratorExpression* inputExpression,
std::map<std::string, std::string>& outputFiles, mode_t perm);
+ enum PathRole
+ {
+ PathForInput,
+ PathForOutput
+ };
+ std::string FixRelativePath(std::string const& filePath, PathRole role,
+ cmLocalGenerator* lg);
+
private:
const std::string Input;
- const CM_AUTO_PTR<cmCompiledGeneratorExpression> OutputFileExpr;
- const CM_AUTO_PTR<cmCompiledGeneratorExpression> Condition;
+ const std::unique_ptr<cmCompiledGeneratorExpression> OutputFileExpr;
+ const std::unique_ptr<cmCompiledGeneratorExpression> Condition;
std::vector<std::string> Files;
const bool InputIsContent;
+ cmPolicies::PolicyStatus PolicyStatusCMP0070;
};
#endif
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index 6ce4a8e72..e0ae170c0 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -2,13 +2,13 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorExpressionEvaluator.h"
+#include <algorithm>
+#include <sstream>
+
#include "cmAlgorithms.h"
#include "cmGeneratorExpressionContext.h"
#include "cmGeneratorExpressionNode.h"
-#include <algorithm>
-#include <sstream>
-
GeneratorExpressionContent::GeneratorExpressionContent(
const char* startContent, size_t length)
: StartContent(startContent)
@@ -25,28 +25,23 @@ std::string GeneratorExpressionContent::ProcessArbitraryContent(
const cmGeneratorExpressionNode* node, const std::string& identifier,
cmGeneratorExpressionContext* context,
cmGeneratorExpressionDAGChecker* dagChecker,
- std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*>>::const_iterator
pit) const
{
std::string result;
- const std::vector<
- std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator pend =
- this->ParamChildren.end();
+ const auto pend = this->ParamChildren.end();
for (; pit != pend; ++pit) {
- std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it =
- pit->begin();
- const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end =
- pit->end();
- for (; it != end; ++it) {
+ for (cmGeneratorExpressionEvaluator* pExprEval : *pit) {
if (node->RequiresLiteralInput()) {
- if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text) {
- reportError(context, this->GetOriginalExpression(), "$<" +
- identifier + "> expression requires literal input.");
+ if (pExprEval->GetType() != cmGeneratorExpressionEvaluator::Text) {
+ reportError(context, this->GetOriginalExpression(),
+ "$<" + identifier +
+ "> expression requires literal input.");
return std::string();
}
}
- result += (*it)->Evaluate(context, dagChecker);
+ result += pExprEval->Evaluate(context, dagChecker);
if (context->HadError) {
return std::string();
}
@@ -69,12 +64,9 @@ std::string GeneratorExpressionContent::Evaluate(
{
std::string identifier;
{
- std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it =
- this->IdentifierChildren.begin();
- const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end =
- this->IdentifierChildren.end();
- for (; it != end; ++it) {
- identifier += (*it)->Evaluate(context, dagChecker);
+ for (cmGeneratorExpressionEvaluator* pExprEval :
+ this->IdentifierChildren) {
+ identifier += pExprEval->Evaluate(context, dagChecker);
if (context->HadError) {
return std::string();
}
@@ -122,43 +114,36 @@ std::string GeneratorExpressionContent::EvaluateParameters(
{
const int numExpected = node->NumExpectedParameters();
{
- std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
- pit = this->ParamChildren.begin();
- const std::vector<
- std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator pend =
- this->ParamChildren.end();
+ auto pit = this->ParamChildren.begin();
+ const auto pend = this->ParamChildren.end();
const bool acceptsArbitraryContent =
node->AcceptsArbitraryContentParameter();
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;
- std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it =
- pit->begin();
- const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end =
- pit->end();
- for (; it != end; ++it) {
- parameter += (*it)->Evaluate(context, dagChecker);
+ for (cmGeneratorExpressionEvaluator* pExprEval : *pit) {
+ parameter += pExprEval->Evaluate(context, dagChecker);
if (context->HadError) {
return std::string();
}
}
- parameters.push_back(parameter);
+ parameters.push_back(std::move(parameter));
}
}
if ((numExpected > cmGeneratorExpressionNode::DynamicParameters &&
- (unsigned int)numExpected != parameters.size())) {
+ static_cast<unsigned int>(numExpected) != parameters.size())) {
if (numExpected == 0) {
reportError(context, this->GetOriginalExpression(),
"$<" + identifier + "> expression requires no parameters.");
} else if (numExpected == 1) {
- reportError(context, this->GetOriginalExpression(), "$<" + identifier +
+ reportError(context, this->GetOriginalExpression(),
+ "$<" + identifier +
"> expression requires "
"exactly one parameter.");
} else {
@@ -173,12 +158,18 @@ std::string GeneratorExpressionContent::EvaluateParameters(
if (numExpected == cmGeneratorExpressionNode::OneOrMoreParameters &&
parameters.empty()) {
- reportError(context, this->GetOriginalExpression(), "$<" + identifier +
+ reportError(context, this->GetOriginalExpression(),
+ "$<" + identifier +
"> expression requires at least one parameter.");
- }
- if (numExpected == cmGeneratorExpressionNode::OneOrZeroParameters &&
- parameters.size() > 1) {
- reportError(context, this->GetOriginalExpression(), "$<" + identifier +
+ } else if (numExpected == cmGeneratorExpressionNode::TwoOrMoreParameters &&
+ parameters.size() < 2) {
+ reportError(context, this->GetOriginalExpression(),
+ "$<" + identifier +
+ "> expression requires at least two parameters.");
+ } else if (numExpected == cmGeneratorExpressionNode::OneOrZeroParameters &&
+ parameters.size() > 1) {
+ reportError(context, this->GetOriginalExpression(),
+ "$<" + identifier +
"> expression requires one or zero parameters.");
}
return std::string();
@@ -188,5 +179,5 @@ GeneratorExpressionContent::~GeneratorExpressionContent()
{
cmDeleteAll(this->IdentifierChildren);
std::for_each(this->ParamChildren.begin(), this->ParamChildren.end(),
- cmDeleteAll<std::vector<cmGeneratorExpressionEvaluator*> >);
+ cmDeleteAll<std::vector<cmGeneratorExpressionEvaluator*>>);
}
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index a0a826ac6..b10bb5bda 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -3,10 +3,11 @@
#ifndef cmGeneratorExpressionEvaluator_h
#define cmGeneratorExpressionEvaluator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include <stddef.h>
+#include <cstddef>
#include <string>
+#include <utility>
#include <vector>
struct cmGeneratorExpressionContext;
@@ -15,8 +16,13 @@ struct cmGeneratorExpressionNode;
struct cmGeneratorExpressionEvaluator
{
- cmGeneratorExpressionEvaluator() {}
- virtual ~cmGeneratorExpressionEvaluator() {}
+ cmGeneratorExpressionEvaluator() = default;
+ virtual ~cmGeneratorExpressionEvaluator() = default;
+
+ cmGeneratorExpressionEvaluator(cmGeneratorExpressionEvaluator const&) =
+ delete;
+ cmGeneratorExpressionEvaluator& operator=(
+ cmGeneratorExpressionEvaluator const&) = delete;
enum Type
{
@@ -28,9 +34,6 @@ struct cmGeneratorExpressionEvaluator
virtual std::string Evaluate(cmGeneratorExpressionContext* context,
cmGeneratorExpressionDAGChecker*) const = 0;
-
-private:
- CM_DISABLE_COPY(cmGeneratorExpressionEvaluator)
};
struct TextContent : public cmGeneratorExpressionEvaluator
@@ -42,12 +45,12 @@ struct TextContent : public cmGeneratorExpressionEvaluator
}
std::string Evaluate(cmGeneratorExpressionContext*,
- cmGeneratorExpressionDAGChecker*) const CM_OVERRIDE
+ cmGeneratorExpressionDAGChecker*) const override
{
return std::string(this->Content, this->Length);
}
- Type GetType() const CM_OVERRIDE
+ Type GetType() const override
{
return cmGeneratorExpressionEvaluator::Text;
}
@@ -64,30 +67,29 @@ private:
struct GeneratorExpressionContent : public cmGeneratorExpressionEvaluator
{
GeneratorExpressionContent(const char* startContent, size_t length);
- void SetIdentifier(
- std::vector<cmGeneratorExpressionEvaluator*> const& identifier)
+
+ void SetIdentifier(std::vector<cmGeneratorExpressionEvaluator*> identifier)
{
- this->IdentifierChildren = identifier;
+ this->IdentifierChildren = std::move(identifier);
}
void SetParameters(
- std::vector<std::vector<cmGeneratorExpressionEvaluator*> > const&
- parameters)
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*>> parameters)
{
- this->ParamChildren = parameters;
+ this->ParamChildren = std::move(parameters);
}
- Type GetType() const CM_OVERRIDE
+ Type GetType() const override
{
return cmGeneratorExpressionEvaluator::Generator;
}
std::string Evaluate(cmGeneratorExpressionContext* context,
- cmGeneratorExpressionDAGChecker*) const CM_OVERRIDE;
+ cmGeneratorExpressionDAGChecker*) const override;
std::string GetOriginalExpression() const;
- ~GeneratorExpressionContent() CM_OVERRIDE;
+ ~GeneratorExpressionContent() override;
private:
std::string EvaluateParameters(const cmGeneratorExpressionNode* node,
@@ -100,12 +102,12 @@ private:
const cmGeneratorExpressionNode* node, const std::string& identifier,
cmGeneratorExpressionContext* context,
cmGeneratorExpressionDAGChecker* dagChecker,
- std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*>>::const_iterator
pit) const;
private:
std::vector<cmGeneratorExpressionEvaluator*> IdentifierChildren;
- std::vector<std::vector<cmGeneratorExpressionEvaluator*> > ParamChildren;
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*>> ParamChildren;
const char* StartContent;
size_t ContentLength;
};
diff --git a/Source/cmGeneratorExpressionLexer.cxx b/Source/cmGeneratorExpressionLexer.cxx
index 931fd4d62..a7f090ac7 100644
--- a/Source/cmGeneratorExpressionLexer.cxx
+++ b/Source/cmGeneratorExpressionLexer.cxx
@@ -2,18 +2,13 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorExpressionLexer.h"
-cmGeneratorExpressionLexer::cmGeneratorExpressionLexer()
- : SawBeginExpression(false)
- , SawGeneratorExpression(false)
-{
-}
+cmGeneratorExpressionLexer::cmGeneratorExpressionLexer() = default;
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 +17,12 @@ std::vector<cmGeneratorExpressionToken> cmGeneratorExpressionLexer::Tokenize(
{
std::vector<cmGeneratorExpressionToken> result;
+ if (input.find('$') == std::string::npos) {
+ result.emplace_back(cmGeneratorExpressionToken::Text, input.c_str(),
+ input.size());
+ return result;
+ }
+
const char* c = input.c_str();
const char* upto = c;
@@ -30,8 +31,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 +40,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/cmGeneratorExpressionLexer.h b/Source/cmGeneratorExpressionLexer.h
index e53f0b547..9e0194861 100644
--- a/Source/cmGeneratorExpressionLexer.h
+++ b/Source/cmGeneratorExpressionLexer.h
@@ -5,7 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include <stddef.h>
+#include <cstddef>
#include <string>
#include <vector>
@@ -46,8 +46,8 @@ public:
}
private:
- bool SawBeginExpression;
- bool SawGeneratorExpression;
+ bool SawBeginExpression = false;
+ bool SawGeneratorExpression = false;
};
#endif
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index a57d2a0d8..66f1c71f4 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -2,6 +2,24 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorExpressionNode.h"
+#include <algorithm>
+#include <cassert>
+#include <cerrno>
+#include <cstdlib>
+#include <cstring>
+#include <map>
+#include <memory>
+#include <set>
+#include <sstream>
+#include <utility>
+
+#include <cm/iterator>
+
+#include "cmsys/RegularExpression.hxx"
+#include "cmsys/String.h"
+
+#include "cm_static_string_view.hxx"
+
#include "cmAlgorithms.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionContext.h"
@@ -12,39 +30,32 @@
#include "cmLinkItem.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
+#include "cmRange.h"
+#include "cmState.h"
+#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
+#include "cmString.hxx"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
-#include "cm_auto_ptr.hxx"
#include "cmake.h"
-#include "cmConfigure.h"
-#include "cmsys/RegularExpression.hxx"
-#include "cmsys/String.h"
-#include <algorithm>
-#include <assert.h>
-#include <errno.h>
-#include <map>
-#include <set>
-#include <sstream>
-#include <stdlib.h>
-#include <string.h>
-#include <utility>
-
std::string cmGeneratorExpressionNode::EvaluateDependentExpression(
std::string const& prop, cmLocalGenerator* lg,
cmGeneratorExpressionContext* context, cmGeneratorTarget const* headTarget,
- cmGeneratorTarget const* currentTarget,
- cmGeneratorExpressionDAGChecker* dagChecker)
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ cmGeneratorTarget const* currentTarget)
{
cmGeneratorExpression ge(context->Backtrace);
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
cge->SetEvaluateForBuildsystem(context->EvaluateForBuildsystem);
+ cge->SetQuiet(context->Quiet);
std::string result =
- cge->Evaluate(lg, context->Config, context->Quiet, headTarget,
- currentTarget, dagChecker, context->Language);
+ cge->Evaluate(lg, context->Config, headTarget, dagChecker, currentTarget,
+ context->Language);
if (cge->GetHadContextSensitiveCondition()) {
context->HadContextSensitiveCondition = true;
}
@@ -56,17 +67,17 @@ std::string cmGeneratorExpressionNode::EvaluateDependentExpression(
static const struct ZeroNode : public cmGeneratorExpressionNode
{
- ZeroNode() {}
+ ZeroNode() {} // NOLINT(modernize-use-equals-default)
- bool GeneratesContent() const CM_OVERRIDE { return false; }
+ bool GeneratesContent() const override { return false; }
- bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
+ bool AcceptsArbitraryContentParameter() const override { return true; }
- std::string Evaluate(const std::vector<std::string>& /*parameters*/,
- cmGeneratorExpressionContext* /*context*/,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& /*parameters*/,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
return std::string();
}
@@ -74,15 +85,15 @@ static const struct ZeroNode : public cmGeneratorExpressionNode
static const struct OneNode : public cmGeneratorExpressionNode
{
- OneNode() {}
+ OneNode() {} // NOLINT(modernize-use-equals-default)
- bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
+ bool AcceptsArbitraryContentParameter() const override { return true; }
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* /*context*/,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
return parameters.front();
}
@@ -92,85 +103,89 @@ static const struct OneNode buildInterfaceNode;
static const struct ZeroNode installInterfaceNode;
-#define BOOLEAN_OP_NODE(OPNAME, OP, SUCCESS_VALUE, FAILURE_VALUE) \
- static const struct OP##Node : public cmGeneratorExpressionNode \
- { \
- OP##Node() {} \
- virtual int NumExpectedParameters() const { return OneOrMoreParameters; } \
- \
- std::string Evaluate(const std::vector<std::string>& parameters, \
- cmGeneratorExpressionContext* context, \
- const GeneratorExpressionContent* content, \
- cmGeneratorExpressionDAGChecker*) const \
- { \
- std::vector<std::string>::const_iterator it = parameters.begin(); \
- const std::vector<std::string>::const_iterator end = parameters.end(); \
- for (; it != end; ++it) { \
- if (*it == #FAILURE_VALUE) { \
- return #FAILURE_VALUE; \
- } \
- if (*it != #SUCCESS_VALUE) { \
- reportError(context, content->GetOriginalExpression(), \
- "Parameters to $<" #OP \
- "> must resolve to either '0' or '1'."); \
- return std::string(); \
- } \
- } \
- return #SUCCESS_VALUE; \
- } \
- } OPNAME;
-
-BOOLEAN_OP_NODE(andNode, AND, 1, 0)
-BOOLEAN_OP_NODE(orNode, OR, 0, 1)
-
-#undef BOOLEAN_OP_NODE
-
-static const struct NotNode : public cmGeneratorExpressionNode
+struct BooleanOpNode : public cmGeneratorExpressionNode
{
- NotNode() {}
+ BooleanOpNode(const char* op_, const char* successVal_,
+ const char* failureVal_)
+ : op(op_)
+ , successVal(successVal_)
+ , failureVal(failureVal_)
+ {
+ }
+
+ int NumExpectedParameters() const override { return OneOrMoreParameters; }
std::string Evaluate(const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ cmGeneratorExpressionDAGChecker*) const override
{
- if (*parameters.begin() != "0" && *parameters.begin() != "1") {
+ for (std::string const& param : parameters) {
+ if (param == this->failureVal) {
+ return this->failureVal;
+ }
+ if (param != this->successVal) {
+ std::ostringstream e;
+ e << "Parameters to $<" << this->op;
+ e << "> must resolve to either '0' or '1'.";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ return std::string();
+ }
+ }
+ return this->successVal;
+ }
+
+ const char *const op, *const successVal, *const failureVal;
+};
+
+static const BooleanOpNode andNode("AND", "1", "0"), orNode("OR", "0", "1");
+
+static const struct NotNode : public cmGeneratorExpressionNode
+{
+ NotNode() {} // NOLINT(modernize-use-equals-default)
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ if (parameters.front() != "0" && parameters.front() != "1") {
reportError(
context, content->GetOriginalExpression(),
"$<NOT> parameter must resolve to exactly one '0' or '1' value.");
return std::string();
}
- return *parameters.begin() == "0" ? "1" : "0";
+ return parameters.front() == "0" ? "1" : "0";
}
} notNode;
static const struct BoolNode : public cmGeneratorExpressionNode
{
- BoolNode() {}
+ BoolNode() {} // NOLINT(modernize-use-equals-default)
- int NumExpectedParameters() const CM_OVERRIDE { return 1; }
+ int NumExpectedParameters() const override { return 1; }
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* /*context*/,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
- return !cmSystemTools::IsOff(parameters.begin()->c_str()) ? "1" : "0";
+ return !cmIsOff(parameters.front()) ? "1" : "0";
}
} boolNode;
static const struct IfNode : public cmGeneratorExpressionNode
{
- IfNode() {}
+ IfNode() {} // NOLINT(modernize-use-equals-default)
- int NumExpectedParameters() const CM_OVERRIDE { return 3; }
+ int NumExpectedParameters() const override { return 3; }
std::string Evaluate(const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker*) const CM_OVERRIDE
+ cmGeneratorExpressionDAGChecker*) const override
{
if (parameters[0] != "1" && parameters[0] != "0") {
reportError(context, content->GetOriginalExpression(),
@@ -184,109 +199,377 @@ static const struct IfNode : public cmGeneratorExpressionNode
static const struct StrEqualNode : public cmGeneratorExpressionNode
{
- StrEqualNode() {}
+ StrEqualNode() {} // NOLINT(modernize-use-equals-default)
- int NumExpectedParameters() const CM_OVERRIDE { return 2; }
+ int NumExpectedParameters() const override { return 2; }
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* /*context*/,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
- return *parameters.begin() == parameters[1] ? "1" : "0";
+ return parameters.front() == parameters[1] ? "1" : "0";
}
} strEqualNode;
static const struct EqualNode : public cmGeneratorExpressionNode
{
- EqualNode() {}
+ EqualNode() {} // NOLINT(modernize-use-equals-default)
- int NumExpectedParameters() const CM_OVERRIDE { return 2; }
+ int NumExpectedParameters() const override { return 2; }
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
- char* pEnd;
+ long numbers[2];
+ for (int i = 0; i < 2; ++i) {
+ if (!ParameterToLong(parameters[i].c_str(), &numbers[i])) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<EQUAL> parameter " + parameters[i] +
+ " is not a valid integer.");
+ return {};
+ }
+ }
+ return numbers[0] == numbers[1] ? "1" : "0";
+ }
- int base = 0;
- bool flipSign = false;
+ static bool ParameterToLong(const char* param, long* outResult)
+ {
+ const char isNegative = param[0] == '-';
- const char* lhs = parameters[0].c_str();
- if (cmHasLiteralPrefix(lhs, "0b") || cmHasLiteralPrefix(lhs, "0B")) {
+ int base = 0;
+ if (cmHasLiteralPrefix(param, "0b") || cmHasLiteralPrefix(param, "0B")) {
base = 2;
- lhs += 2;
- }
- if (cmHasLiteralPrefix(lhs, "-0b") || cmHasLiteralPrefix(lhs, "-0B")) {
+ param += 2;
+ } else if (cmHasLiteralPrefix(param, "-0b") ||
+ cmHasLiteralPrefix(param, "-0B") ||
+ cmHasLiteralPrefix(param, "+0b") ||
+ cmHasLiteralPrefix(param, "+0B")) {
base = 2;
- lhs += 3;
- flipSign = true;
+ param += 3;
}
- if (cmHasLiteralPrefix(lhs, "+0b") || cmHasLiteralPrefix(lhs, "+0B")) {
- base = 2;
- lhs += 3;
+
+ char* pEnd;
+ long result = strtol(param, &pEnd, base);
+ if (pEnd == param || *pEnd != '\0' || errno == ERANGE) {
+ return false;
+ }
+ if (isNegative && result > 0) {
+ result *= -1;
+ }
+ *outResult = result;
+ return true;
+ }
+} equalNode;
+
+static const struct InListNode : public cmGeneratorExpressionNode
+{
+ InListNode() {} // NOLINT(modernize-use-equals-default)
+
+ int NumExpectedParameters() const override { return 2; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ std::vector<std::string> values;
+ std::vector<std::string> checkValues;
+ bool check = false;
+ switch (context->LG->GetPolicyStatus(cmPolicies::CMP0085)) {
+ case cmPolicies::WARN:
+ if (parameters.front().empty()) {
+ check = true;
+ cmExpandList(parameters[1], checkValues, true);
+ }
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ cmExpandList(parameters[1], values);
+ if (check && values != checkValues) {
+ std::ostringstream e;
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0085)
+ << "\nSearch Item:\n \"" << parameters.front()
+ << "\"\nList:\n \"" << parameters[1] << "\"\n";
+ context->LG->GetCMakeInstance()->IssueMessage(
+ MessageType ::AUTHOR_WARNING, e.str(), context->Backtrace);
+ return "0";
+ }
+ if (values.empty()) {
+ return "0";
+ }
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ cmExpandList(parameters[1], values, true);
+ break;
}
- long lnum = strtol(lhs, &pEnd, base);
- if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE) {
+ return cmContains(values, parameters.front()) ? "1" : "0";
+ }
+} inListNode;
+
+static const struct FilterNode : public cmGeneratorExpressionNode
+{
+ FilterNode() {} // NOLINT(modernize-use-equals-default)
+
+ int NumExpectedParameters() const override { return 3; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ if (parameters.size() != 3) {
reportError(context, content->GetOriginalExpression(),
- "$<EQUAL> parameter " + parameters[0] +
- " is not a valid integer.");
+ "$<FILTER:...> expression requires three parameters");
+ return {};
+ }
+
+ if (parameters[1] != "INCLUDE" && parameters[1] != "EXCLUDE") {
+ reportError(
+ context, content->GetOriginalExpression(),
+ "$<FILTER:...> second parameter must be either INCLUDE or EXCLUDE");
+ return {};
+ }
+
+ const bool exclude = parameters[1] == "EXCLUDE";
+
+ cmsys::RegularExpression re;
+ if (!re.compile(parameters[2])) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<FILTER:...> failed to compile regex");
+ return {};
+ }
+
+ std::vector<std::string> values;
+ std::vector<std::string> result;
+ cmExpandList(parameters.front(), values, true);
+
+ std::copy_if(values.cbegin(), values.cend(), std::back_inserter(result),
+ [&re, exclude](std::string const& input) {
+ return exclude ^ re.find(input);
+ });
+ return cmJoin(cmMakeRange(result.cbegin(), result.cend()), ";");
+ }
+} filterNode;
+
+static const struct RemoveDuplicatesNode : public cmGeneratorExpressionNode
+{
+ RemoveDuplicatesNode() {} // NOLINT(modernize-use-equals-default)
+
+ int NumExpectedParameters() const override { return 1; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ if (parameters.size() != 1) {
+ reportError(
+ context, content->GetOriginalExpression(),
+ "$<REMOVE_DUPLICATES:...> expression requires one parameter");
+ }
+
+ std::vector<std::string> values = cmExpandedList(parameters.front(), true);
+
+ auto valuesEnd = cmRemoveDuplicates(values);
+ auto valuesBegin = values.cbegin();
+ return cmJoin(cmMakeRange(valuesBegin, valuesEnd), ";");
+ }
+
+} removeDuplicatesNode;
+
+static const struct TargetExistsNode : public cmGeneratorExpressionNode
+{
+ TargetExistsNode() {} // NOLINT(modernize-use-equals-default)
+
+ int NumExpectedParameters() const override { return 1; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ if (parameters.size() != 1) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_EXISTS:...> expression requires one parameter");
return std::string();
}
- if (flipSign) {
- lnum = -lnum;
+ std::string targetName = parameters.front();
+ if (targetName.empty() ||
+ !cmGeneratorExpression::IsValidTargetName(targetName)) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_EXISTS:tgt> expression requires a non-empty "
+ "valid target name.");
+ return std::string();
}
- base = 0;
- flipSign = false;
+ return context->LG->GetMakefile()->FindTargetToUse(targetName) ? "1" : "0";
+ }
+} targetExistsNode;
- const char* rhs = parameters[1].c_str();
- if (cmHasLiteralPrefix(rhs, "0b") || cmHasLiteralPrefix(rhs, "0B")) {
- base = 2;
- rhs += 2;
+static const struct TargetNameIfExistsNode : public cmGeneratorExpressionNode
+{
+ TargetNameIfExistsNode() {} // NOLINT(modernize-use-equals-default)
+
+ int NumExpectedParameters() const override { return 1; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ if (parameters.size() != 1) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_NAME_IF_EXISTS:...> expression requires one "
+ "parameter");
+ return std::string();
}
- if (cmHasLiteralPrefix(rhs, "-0b") || cmHasLiteralPrefix(rhs, "-0B")) {
- base = 2;
- rhs += 3;
- flipSign = true;
+
+ std::string targetName = parameters.front();
+ if (targetName.empty() ||
+ !cmGeneratorExpression::IsValidTargetName(targetName)) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_NAME_IF_EXISTS:tgt> expression requires a "
+ "non-empty valid target name.");
+ return std::string();
}
- if (cmHasLiteralPrefix(rhs, "+0b") || cmHasLiteralPrefix(rhs, "+0B")) {
- base = 2;
- rhs += 3;
+
+ return context->LG->GetMakefile()->FindTargetToUse(targetName)
+ ? targetName
+ : std::string();
+ }
+} targetNameIfExistsNode;
+
+struct GenexEvaluator : public cmGeneratorExpressionNode
+{
+ GenexEvaluator() {} // NOLINT(modernize-use-equals-default)
+
+protected:
+ std::string EvaluateExpression(
+ const std::string& genexOperator, const std::string& expression,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagCheckerParent) const
+ {
+ if (context->HeadTarget) {
+ cmGeneratorExpressionDAGChecker dagChecker(
+ context->Backtrace, context->HeadTarget,
+ genexOperator + ":" + expression, content, dagCheckerParent);
+ switch (dagChecker.Check()) {
+ case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
+ case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: {
+ dagChecker.ReportError(context, content->GetOriginalExpression());
+ return std::string();
+ }
+ case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
+ case cmGeneratorExpressionDAGChecker::DAG:
+ break;
+ }
+
+ return this->EvaluateDependentExpression(
+ expression, context->LG, context, context->HeadTarget, &dagChecker,
+ context->CurrentTarget);
}
- long rnum = strtol(rhs, &pEnd, base);
- if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE) {
+ return this->EvaluateDependentExpression(
+ expression, context->LG, context, context->HeadTarget, dagCheckerParent,
+ context->CurrentTarget);
+ }
+};
+
+static const struct TargetGenexEvalNode : public GenexEvaluator
+{
+ TargetGenexEvalNode() {} // NOLINT(modernize-use-equals-default)
+
+ int NumExpectedParameters() const override { return 2; }
+
+ bool AcceptsArbitraryContentParameter() const override { return true; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagCheckerParent) const override
+ {
+ const std::string& targetName = parameters.front();
+ if (targetName.empty() ||
+ !cmGeneratorExpression::IsValidTargetName(targetName)) {
reportError(context, content->GetOriginalExpression(),
- "$<EQUAL> parameter " + parameters[1] +
- " is not a valid integer.");
+ "$<TARGET_GENEX_EVAL:tgt, ...> expression requires a "
+ "non-empty valid target name.");
+ return std::string();
+ }
+
+ const auto* target = context->LG->FindGeneratorTargetToUse(targetName);
+ if (!target) {
+ std::ostringstream e;
+ e << "$<TARGET_GENEX_EVAL:tgt, ...> target \"" << targetName
+ << "\" not found.";
+ reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
}
- if (flipSign) {
- rnum = -rnum;
+ const std::string& expression = parameters[1];
+ if (expression.empty()) {
+ return expression;
}
- return lnum == rnum ? "1" : "0";
+ cmGeneratorExpressionContext targetContext(
+ context->LG, context->Config, context->Quiet, target, target,
+ context->EvaluateForBuildsystem, context->Backtrace, context->Language);
+
+ return this->EvaluateExpression("TARGET_GENEX_EVAL", expression,
+ &targetContext, content, dagCheckerParent);
}
-} equalNode;
+} targetGenexEvalNode;
+
+static const struct GenexEvalNode : public GenexEvaluator
+{
+ GenexEvalNode() {} // NOLINT(modernize-use-equals-default)
+
+ int NumExpectedParameters() const override { return 1; }
+
+ bool AcceptsArbitraryContentParameter() const override { return true; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagCheckerParent) const override
+ {
+ const std::string& expression = parameters[0];
+ if (expression.empty()) {
+ return expression;
+ }
+
+ return this->EvaluateExpression("GENEX_EVAL", expression, context, content,
+ dagCheckerParent);
+ }
+} genexEvalNode;
static const struct LowerCaseNode : public cmGeneratorExpressionNode
{
- LowerCaseNode() {}
+ LowerCaseNode() {} // NOLINT(modernize-use-equals-default)
- bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
+ bool AcceptsArbitraryContentParameter() const override { return true; }
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* /*context*/,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
return cmSystemTools::LowerCase(parameters.front());
}
@@ -294,15 +577,15 @@ static const struct LowerCaseNode : public cmGeneratorExpressionNode
static const struct UpperCaseNode : public cmGeneratorExpressionNode
{
- UpperCaseNode() {}
+ UpperCaseNode() {} // NOLINT(modernize-use-equals-default)
- bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
+ bool AcceptsArbitraryContentParameter() const override { return true; }
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* /*context*/,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
return cmSystemTools::UpperCase(parameters.front());
}
@@ -310,73 +593,66 @@ static const struct UpperCaseNode : public cmGeneratorExpressionNode
static const struct MakeCIdentifierNode : public cmGeneratorExpressionNode
{
- MakeCIdentifierNode() {}
+ MakeCIdentifierNode() {} // NOLINT(modernize-use-equals-default)
- bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
+ bool AcceptsArbitraryContentParameter() const override { return true; }
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* /*context*/,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
return cmSystemTools::MakeCidentifier(parameters.front());
}
} makeCIdentifierNode;
-static const struct Angle_RNode : public cmGeneratorExpressionNode
+template <char C>
+struct CharacterNode : public cmGeneratorExpressionNode
{
- Angle_RNode() {}
+ CharacterNode() {} // NOLINT(modernize-use-equals-default)
- int NumExpectedParameters() const CM_OVERRIDE { return 0; }
+ int NumExpectedParameters() const override { return 0; }
- std::string Evaluate(const std::vector<std::string>& /*parameters*/,
- cmGeneratorExpressionContext* /*context*/,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& /*parameters*/,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
- return ">";
+ return { C };
}
-} angle_rNode;
+};
+static const CharacterNode<'>'> angle_rNode;
+static const CharacterNode<','> commaNode;
+static const CharacterNode<';'> semicolonNode;
-static const struct CommaNode : public cmGeneratorExpressionNode
+struct CompilerIdNode : public cmGeneratorExpressionNode
{
- CommaNode() {}
-
- int NumExpectedParameters() const CM_OVERRIDE { return 0; }
-
- std::string Evaluate(const std::vector<std::string>& /*parameters*/,
- cmGeneratorExpressionContext* /*context*/,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ CompilerIdNode(const char* compilerLang)
+ : CompilerLanguage(compilerLang)
{
- return ",";
}
-} commaNode;
-static const struct SemicolonNode : public cmGeneratorExpressionNode
-{
- SemicolonNode() {}
-
- int NumExpectedParameters() const CM_OVERRIDE { return 0; }
+ int NumExpectedParameters() const override { return ZeroOrMoreParameters; }
- std::string Evaluate(const std::vector<std::string>& /*parameters*/,
- cmGeneratorExpressionContext* /*context*/,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagChecker) const override
{
- return ";";
+ if (!context->HeadTarget) {
+ std::ostringstream e;
+ e << "$<" << this->CompilerLanguage
+ << "_COMPILER_ID> may only be used with binary targets. It may "
+ "not be used with add_custom_command or add_custom_target.";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ return {};
+ }
+ return this->EvaluateWithLanguage(parameters, context, content, dagChecker,
+ this->CompilerLanguage);
}
-} semicolonNode;
-
-struct CompilerIdNode : public cmGeneratorExpressionNode
-{
- CompilerIdNode() {}
-
- int NumExpectedParameters() const CM_OVERRIDE { return OneOrZeroParameters; }
std::string EvaluateWithLanguage(const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
@@ -384,95 +660,83 @@ struct CompilerIdNode : public cmGeneratorExpressionNode
cmGeneratorExpressionDAGChecker* /*unused*/,
const std::string& lang) const
{
- const char* compilerId = context->LG->GetMakefile()->GetSafeDefinition(
- "CMAKE_" + lang + "_COMPILER_ID");
+ std::string const& compilerId =
+ context->LG->GetMakefile()->GetSafeDefinition("CMAKE_" + lang +
+ "_COMPILER_ID");
if (parameters.empty()) {
- return compilerId ? compilerId : "";
- }
- static cmsys::RegularExpression compilerIdValidator("^[A-Za-z0-9_]*$");
- if (!compilerIdValidator.find(*parameters.begin())) {
- reportError(context, content->GetOriginalExpression(),
- "Expression syntax not recognized.");
- return std::string();
+ return compilerId;
}
- if (!compilerId) {
+ if (compilerId.empty()) {
return parameters.front().empty() ? "1" : "0";
}
+ static cmsys::RegularExpression compilerIdValidator("^[A-Za-z0-9_]*$");
- if (strcmp(parameters.begin()->c_str(), compilerId) == 0) {
- return "1";
- }
+ for (auto& param : parameters) {
- if (cmsysString_strcasecmp(parameters.begin()->c_str(), compilerId) == 0) {
- switch (context->LG->GetPolicyStatus(cmPolicies::CMP0044)) {
- case cmPolicies::WARN: {
- std::ostringstream e;
- e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0044);
- context->LG->GetCMakeInstance()->IssueMessage(
- cmake::AUTHOR_WARNING, e.str(), context->Backtrace);
- CM_FALLTHROUGH;
+ if (!compilerIdValidator.find(param)) {
+ reportError(context, content->GetOriginalExpression(),
+ "Expression syntax not recognized.");
+ return std::string();
+ }
+
+ if (strcmp(param.c_str(), compilerId.c_str()) == 0) {
+ return "1";
+ }
+
+ if (cmsysString_strcasecmp(param.c_str(), compilerId.c_str()) == 0) {
+ switch (context->LG->GetPolicyStatus(cmPolicies::CMP0044)) {
+ case cmPolicies::WARN: {
+ context->LG->GetCMakeInstance()->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0044),
+ context->Backtrace);
+ CM_FALLTHROUGH;
+ }
+ case cmPolicies::OLD:
+ return "1";
+ case cmPolicies::NEW:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ break;
}
- case cmPolicies::OLD:
- return "1";
- case cmPolicies::NEW:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::REQUIRED_IF_USED:
- break;
}
}
return "0";
}
+
+ const char* const CompilerLanguage;
};
-static const struct CCompilerIdNode : public CompilerIdNode
-{
- CCompilerIdNode() {}
+static const CompilerIdNode cCompilerIdNode("C"), cxxCompilerIdNode("CXX"),
+ cudaCompilerIdNode("CUDA"), objcCompilerIdNode("OBJC"),
+ objcxxCompilerIdNode("OBJCXX"), fortranCompilerIdNode("Fortran");
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* dagChecker) const
- CM_OVERRIDE
+struct CompilerVersionNode : public cmGeneratorExpressionNode
+{
+ CompilerVersionNode(const char* compilerLang)
+ : CompilerLanguage(compilerLang)
{
- if (!context->HeadTarget) {
- reportError(
- context, content->GetOriginalExpression(),
- "$<C_COMPILER_ID> may only be used with binary targets. It may "
- "not be used with add_custom_command or add_custom_target.");
- return std::string();
- }
- return this->EvaluateWithLanguage(parameters, context, content, dagChecker,
- "C");
}
-} cCompilerIdNode;
-static const struct CXXCompilerIdNode : public CompilerIdNode
-{
- CXXCompilerIdNode() {}
+ int NumExpectedParameters() const override { return OneOrZeroParameters; }
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* dagChecker) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagChecker) const override
{
if (!context->HeadTarget) {
- reportError(
- context, content->GetOriginalExpression(),
- "$<CXX_COMPILER_ID> may only be used with binary targets. It may "
- "not be used with add_custom_command or add_custom_target.");
- return std::string();
+ std::ostringstream e;
+ e << "$<" << this->CompilerLanguage
+ << "_COMPILER_VERSION> may only be used with binary targets. It "
+ "may not be used with add_custom_command or add_custom_target.";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ return {};
}
return this->EvaluateWithLanguage(parameters, context, content, dagChecker,
- "CXX");
+ this->CompilerLanguage);
}
-} cxxCompilerIdNode;
-
-struct CompilerVersionNode : public cmGeneratorExpressionNode
-{
- CompilerVersionNode() {}
-
- int NumExpectedParameters() const CM_OVERRIDE { return OneOrZeroParameters; }
std::string EvaluateWithLanguage(const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
@@ -480,213 +744,104 @@ struct CompilerVersionNode : public cmGeneratorExpressionNode
cmGeneratorExpressionDAGChecker* /*unused*/,
const std::string& lang) const
{
- const char* compilerVersion =
+ std::string const& compilerVersion =
context->LG->GetMakefile()->GetSafeDefinition("CMAKE_" + lang +
"_COMPILER_VERSION");
if (parameters.empty()) {
- return compilerVersion ? compilerVersion : "";
+ return compilerVersion;
}
static cmsys::RegularExpression compilerIdValidator("^[0-9\\.]*$");
- if (!compilerIdValidator.find(*parameters.begin())) {
+ if (!compilerIdValidator.find(parameters.front())) {
reportError(context, content->GetOriginalExpression(),
"Expression syntax not recognized.");
- return std::string();
+ return {};
}
- if (!compilerVersion) {
+ if (compilerVersion.empty()) {
return parameters.front().empty() ? "1" : "0";
}
return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
- parameters.begin()->c_str(),
- compilerVersion)
+ parameters.front().c_str(),
+ compilerVersion.c_str())
? "1"
: "0";
}
-};
-
-static const struct CCompilerVersionNode : public CompilerVersionNode
-{
- CCompilerVersionNode() {}
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* dagChecker) const
- CM_OVERRIDE
- {
- if (!context->HeadTarget) {
- reportError(
- context, content->GetOriginalExpression(),
- "$<C_COMPILER_VERSION> may only be used with binary targets. It "
- "may not be used with add_custom_command or add_custom_target.");
- return std::string();
- }
- return this->EvaluateWithLanguage(parameters, context, content, dagChecker,
- "C");
- }
-} cCompilerVersionNode;
-
-static const struct CxxCompilerVersionNode : public CompilerVersionNode
-{
- CxxCompilerVersionNode() {}
+ const char* const CompilerLanguage;
+};
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* dagChecker) const
- CM_OVERRIDE
- {
- if (!context->HeadTarget) {
- reportError(
- context, content->GetOriginalExpression(),
- "$<CXX_COMPILER_VERSION> may only be used with binary targets. It "
- "may not be used with add_custom_command or add_custom_target.");
- return std::string();
- }
- return this->EvaluateWithLanguage(parameters, context, content, dagChecker,
- "CXX");
- }
-} cxxCompilerVersionNode;
+static const CompilerVersionNode cCompilerVersionNode("C"),
+ cxxCompilerVersionNode("CXX"), cudaCompilerVersionNode("CUDA"),
+ objcCompilerVersionNode("OBJC"), objcxxCompilerVersionNode("OBJCXX"),
+ fortranCompilerVersionNode("Fortran");
struct PlatformIdNode : public cmGeneratorExpressionNode
{
- PlatformIdNode() {}
+ PlatformIdNode() {} // NOLINT(modernize-use-equals-default)
- int NumExpectedParameters() const CM_OVERRIDE { return OneOrZeroParameters; }
+ int NumExpectedParameters() const override { return ZeroOrMoreParameters; }
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
- const char* platformId =
+ std::string const& platformId =
context->LG->GetMakefile()->GetSafeDefinition("CMAKE_SYSTEM_NAME");
if (parameters.empty()) {
- return platformId ? platformId : "";
+ return platformId;
}
- if (!platformId) {
+ if (platformId.empty()) {
return parameters.front().empty() ? "1" : "0";
}
- if (strcmp(parameters.begin()->c_str(), platformId) == 0) {
- return "1";
+ for (auto& param : parameters) {
+ if (param == platformId) {
+ return "1";
+ }
}
return "0";
}
} platformIdNode;
-static const struct VersionGreaterNode : public cmGeneratorExpressionNode
-{
- VersionGreaterNode() {}
-
- int NumExpectedParameters() const CM_OVERRIDE { return 2; }
-
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* /*context*/,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
- {
- return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER,
- parameters.front().c_str(),
- parameters[1].c_str())
- ? "1"
- : "0";
- }
-} versionGreaterNode;
-
-static const struct VersionGreaterEqNode : public cmGeneratorExpressionNode
-{
- VersionGreaterEqNode() {}
-
- int NumExpectedParameters() const CM_OVERRIDE { return 2; }
-
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* /*context*/,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
- {
- return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL,
- parameters.front().c_str(),
- parameters[1].c_str())
- ? "1"
- : "0";
- }
-} versionGreaterEqNode;
-
-static const struct VersionLessNode : public cmGeneratorExpressionNode
-{
- VersionLessNode() {}
-
- int NumExpectedParameters() const CM_OVERRIDE { return 2; }
-
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* /*context*/,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
- {
- return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
- parameters.front().c_str(),
- parameters[1].c_str())
- ? "1"
- : "0";
- }
-} versionLessNode;
-
-static const struct VersionLessEqNode : public cmGeneratorExpressionNode
+template <cmSystemTools::CompareOp Op>
+struct VersionNode : public cmGeneratorExpressionNode
{
- VersionLessEqNode() {}
+ VersionNode() {} // NOLINT(modernize-use-equals-default)
- int NumExpectedParameters() const CM_OVERRIDE { return 2; }
+ int NumExpectedParameters() const override { return 2; }
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* /*context*/,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
- return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS_EQUAL,
- parameters.front().c_str(),
+ return cmSystemTools::VersionCompare(Op, parameters.front().c_str(),
parameters[1].c_str())
? "1"
: "0";
}
-} versionLessEqNode;
-
-static const struct VersionEqualNode : public cmGeneratorExpressionNode
-{
- VersionEqualNode() {}
-
- int NumExpectedParameters() const CM_OVERRIDE { return 2; }
+};
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* /*context*/,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
- {
- return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
- parameters.front().c_str(),
- parameters[1].c_str())
- ? "1"
- : "0";
- }
-} versionEqualNode;
+static const VersionNode<cmSystemTools::OP_GREATER> versionGreaterNode;
+static const VersionNode<cmSystemTools::OP_GREATER_EQUAL> versionGreaterEqNode;
+static const VersionNode<cmSystemTools::OP_LESS> versionLessNode;
+static const VersionNode<cmSystemTools::OP_LESS_EQUAL> versionLessEqNode;
+static const VersionNode<cmSystemTools::OP_EQUAL> versionEqualNode;
static const struct LinkOnlyNode : public cmGeneratorExpressionNode
{
- LinkOnlyNode() {}
+ LinkOnlyNode() {} // NOLINT(modernize-use-equals-default)
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* dagChecker) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagChecker) const override
{
if (!dagChecker) {
reportError(context, content->GetOriginalExpression(),
@@ -702,15 +857,15 @@ static const struct LinkOnlyNode : public cmGeneratorExpressionNode
static const struct ConfigurationNode : public cmGeneratorExpressionNode
{
- ConfigurationNode() {}
+ ConfigurationNode() {} // NOLINT(modernize-use-equals-default)
- int NumExpectedParameters() const CM_OVERRIDE { return 0; }
+ int NumExpectedParameters() const override { return 0; }
- std::string Evaluate(const std::vector<std::string>& /*parameters*/,
- cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& /*parameters*/,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
context->HadContextSensitiveCondition = true;
return context->Config;
@@ -719,22 +874,21 @@ static const struct ConfigurationNode : public cmGeneratorExpressionNode
static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
{
- ConfigurationTestNode() {}
+ ConfigurationTestNode() {} // NOLINT(modernize-use-equals-default)
- int NumExpectedParameters() const CM_OVERRIDE { return OneOrZeroParameters; }
+ int NumExpectedParameters() const override { return OneOrZeroParameters; }
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
if (parameters.empty()) {
- return configurationNode.Evaluate(parameters, context, content,
- CM_NULLPTR);
+ return configurationNode.Evaluate(parameters, context, content, nullptr);
}
static cmsys::RegularExpression configValidator("^[A-Za-z0-9_]*$");
- if (!configValidator.find(*parameters.begin())) {
+ if (!configValidator.find(parameters.front())) {
reportError(context, content->GetOriginalExpression(),
"Expression syntax not recognized.");
return std::string();
@@ -744,14 +898,14 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
return parameters.front().empty() ? "1" : "0";
}
- if (cmsysString_strcasecmp(parameters.begin()->c_str(),
+ if (cmsysString_strcasecmp(parameters.front().c_str(),
context->Config.c_str()) == 0) {
return "1";
}
if (context->CurrentTarget && context->CurrentTarget->IsImported()) {
- const char* loc = CM_NULLPTR;
- const char* imp = CM_NULLPTR;
+ const char* loc = nullptr;
+ const char* imp = nullptr;
std::string suffix;
if (context->CurrentTarget->Target->GetMappedConfig(
context->Config, &loc, &imp, suffix)) {
@@ -759,15 +913,13 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
// for this (possibly mapped) config.
// Check if there is a proper config mapping for the tested config.
std::vector<std::string> mappedConfigs;
- std::string mapProp = "MAP_IMPORTED_CONFIG_";
- mapProp += cmSystemTools::UpperCase(context->Config);
+ std::string mapProp = cmStrCat(
+ "MAP_IMPORTED_CONFIG_", cmSystemTools::UpperCase(context->Config));
if (const char* mapValue =
context->CurrentTarget->GetProperty(mapProp)) {
- cmSystemTools::ExpandListArgument(cmSystemTools::UpperCase(mapValue),
- mappedConfigs);
- return std::find(mappedConfigs.begin(), mappedConfigs.end(),
- cmSystemTools::UpperCase(parameters.front())) !=
- mappedConfigs.end()
+ cmExpandList(cmSystemTools::UpperCase(mapValue), mappedConfigs);
+ return cmContains(mappedConfigs,
+ cmSystemTools::UpperCase(parameters.front()))
? "1"
: "0";
}
@@ -779,201 +931,204 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
static const struct JoinNode : public cmGeneratorExpressionNode
{
- JoinNode() {}
+ JoinNode() {} // NOLINT(modernize-use-equals-default)
- int NumExpectedParameters() const CM_OVERRIDE { return 2; }
+ int NumExpectedParameters() const override { return 2; }
- bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
+ bool AcceptsArbitraryContentParameter() const override { return true; }
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* /*context*/,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
- std::vector<std::string> list;
- cmSystemTools::ExpandListArgument(parameters.front(), list);
+ std::vector<std::string> list = cmExpandedList(parameters.front());
return cmJoin(list, parameters[1]);
}
} joinNode;
static const struct CompileLanguageNode : public cmGeneratorExpressionNode
{
- CompileLanguageNode() {}
+ CompileLanguageNode() {} // NOLINT(modernize-use-equals-default)
- int NumExpectedParameters() const CM_OVERRIDE { return OneOrZeroParameters; }
+ int NumExpectedParameters() const override { return ZeroOrMoreParameters; }
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* dagChecker) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
if (context->Language.empty()) {
reportError(
context, content->GetOriginalExpression(),
"$<COMPILE_LANGUAGE:...> may only be used to specify include "
- "directories compile definitions, compile options and to evaluate "
+ "directories, compile definitions, compile options, and to evaluate "
"components of the file(GENERATE) command.");
return std::string();
}
- std::vector<std::string> enabledLanguages;
cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
- gg->GetEnabledLanguages(enabledLanguages);
- if (!parameters.empty() &&
- std::find(enabledLanguages.begin(), enabledLanguages.end(),
- parameters.front()) == enabledLanguages.end()) {
- reportError(context, content->GetOriginalExpression(),
- "$<COMPILE_LANGUAGE:...> Unknown language.");
- 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;
}
- return context->Language == parameters.front() ? "1" : "0";
+
+ for (auto& param : parameters) {
+ if (context->Language == param) {
+ return "1";
+ }
+ }
+ return "0";
}
} languageNode;
-#define TRANSITIVE_PROPERTY_NAME(PROPERTY) , "INTERFACE_" #PROPERTY
+static const struct CompileLanguageAndIdNode : public cmGeneratorExpressionNode
+{
+ CompileLanguageAndIdNode() {} // NOLINT(modernize-use-equals-default)
-static const char* targetPropertyTransitiveWhitelist[] = {
- CM_NULLPTR CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_NAME)
-};
+ int NumExpectedParameters() const override { return TwoOrMoreParameters; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagChecker) const override
+ {
+ if (!context->HeadTarget || context->Language.empty()) {
+ // reportError(context, content->GetOriginalExpression(), "");
+ reportError(
+ context, content->GetOriginalExpression(),
+ "$<COMPILE_LANG_AND_ID:lang,id> may only be used with binary targets "
+ "to specify include directories, compile definitions, and compile "
+ "options. It may not be used with the add_custom_command, "
+ "add_custom_target, or file(GENERATE) commands.");
+ return std::string();
+ }
+ cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
+ std::string genName = gg->GetName();
+ 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_LANG_AND_ID:lang,id> not supported for this generator.");
+ return std::string();
+ }
-#undef TRANSITIVE_PROPERTY_NAME
+ const std::string& lang = context->Language;
+ if (lang == parameters.front()) {
+ std::vector<std::string> idParameter((parameters.cbegin() + 1),
+ parameters.cend());
+ return CompilerIdNode{ lang.c_str() }.EvaluateWithLanguage(
+ idParameter, context, content, dagChecker, lang);
+ }
+ return "0";
+ }
+} languageAndIdNode;
-template <typename T>
std::string getLinkedTargetsContent(
- std::vector<T> const& libraries, cmGeneratorTarget const* target,
- cmGeneratorTarget const* headTarget, cmGeneratorExpressionContext* context,
- cmGeneratorExpressionDAGChecker* dagChecker,
- const std::string& interfacePropertyName)
-{
- std::string linkedTargetsContent;
- std::string sep;
- std::string depString;
- for (typename std::vector<T>::const_iterator it = libraries.begin();
- it != libraries.end(); ++it) {
- // Broken code can have a target in its own link interface.
- // Don't follow such link interface entries so as not to create a
- // self-referencing loop.
- if (it->Target && it->Target != target) {
- depString += sep + "$<TARGET_PROPERTY:" + it->Target->GetName() + "," +
- interfacePropertyName + ">";
- sep = ";";
- }
- }
- if (!depString.empty()) {
- linkedTargetsContent =
- cmGeneratorExpressionNode::EvaluateDependentExpression(
- depString, target->GetLocalGenerator(), context, headTarget, target,
- dagChecker);
- }
- linkedTargetsContent =
- cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent);
- return linkedTargetsContent;
+ cmGeneratorTarget const* target, std::string const& prop,
+ cmGeneratorExpressionContext* context,
+ cmGeneratorExpressionDAGChecker* dagChecker)
+{
+ std::string result;
+ if (cmLinkImplementationLibraries const* impl =
+ target->GetLinkImplementationLibraries(context->Config)) {
+ for (cmLinkImplItem const& lib : impl->Libraries) {
+ if (lib.Target) {
+ // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our
+ // caller's property and hand-evaluate it as if it were compiled.
+ // Create a context as cmCompiledGeneratorExpression::Evaluate does.
+ cmGeneratorExpressionContext libContext(
+ target->GetLocalGenerator(), context->Config, context->Quiet, target,
+ target, context->EvaluateForBuildsystem, lib.Backtrace,
+ context->Language);
+ std::string libResult =
+ lib.Target->EvaluateInterfaceProperty(prop, &libContext, dagChecker);
+ if (!libResult.empty()) {
+ if (result.empty()) {
+ result = std::move(libResult);
+ } else {
+ result.reserve(result.size() + 1 + libResult.size());
+ result += ";";
+ result += libResult;
+ }
+ }
+ }
+ }
+ }
+ return result;
}
static const struct TargetPropertyNode : public cmGeneratorExpressionNode
{
- TargetPropertyNode() {}
+ TargetPropertyNode() {} // NOLINT(modernize-use-equals-default)
// This node handles errors on parameter count itself.
- int NumExpectedParameters() const CM_OVERRIDE { return OneOrMoreParameters; }
+ int NumExpectedParameters() const override { return OneOrMoreParameters; }
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* dagCheckerParent) const
- CM_OVERRIDE
+ static const char* GetErrorText(std::string const& targetName,
+ std::string const& propertyName)
{
- if (parameters.size() != 1 && parameters.size() != 2) {
- reportError(
- context, content->GetOriginalExpression(),
- "$<TARGET_PROPERTY:...> expression requires one or two parameters");
- return std::string();
- }
static cmsys::RegularExpression propertyNameValidator("^[A-Za-z0-9_]+$");
-
- cmGeneratorTarget const* target = context->HeadTarget;
- std::string propertyName = *parameters.begin();
-
- if (parameters.size() == 1) {
- context->HadHeadSensitiveCondition = true;
+ if (targetName.empty() && propertyName.empty()) {
+ return "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
+ "target name and property name.";
}
- if (!target && parameters.size() == 1) {
- reportError(
- context, content->GetOriginalExpression(),
- "$<TARGET_PROPERTY:prop> may only be used with binary targets. "
- "It may not be used with add_custom_command or add_custom_target. "
- "Specify the target to read a property from using the "
- "$<TARGET_PROPERTY:tgt,prop> signature instead.");
- return std::string();
+ if (targetName.empty()) {
+ return "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
+ "target name.";
}
-
- if (parameters.size() == 2) {
- if (parameters.begin()->empty() && parameters[1].empty()) {
- reportError(
- context, content->GetOriginalExpression(),
- "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
- "target name and property name.");
- return std::string();
- }
- if (parameters.begin()->empty()) {
- reportError(
- context, content->GetOriginalExpression(),
- "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
- "target name.");
- return std::string();
+ if (!cmGeneratorExpression::IsValidTargetName(targetName)) {
+ if (!propertyNameValidator.find(propertyName)) {
+ return "Target name and property name not supported.";
}
+ return "Target name not supported.";
+ }
+ return nullptr;
+ }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagCheckerParent) const override
+ {
+ static cmsys::RegularExpression propertyNameValidator("^[A-Za-z0-9_]+$");
- std::string targetName = parameters.front();
+ cmGeneratorTarget const* target = nullptr;
+ std::string targetName;
+ std::string propertyName;
+
+ if (parameters.size() == 2) {
+ targetName = parameters[0];
propertyName = parameters[1];
- if (!cmGeneratorExpression::IsValidTargetName(targetName)) {
- if (!propertyNameValidator.find(propertyName.c_str())) {
- ::reportError(context, content->GetOriginalExpression(),
- "Target name and property name not supported.");
- return std::string();
- }
- ::reportError(context, content->GetOriginalExpression(),
- "Target name not supported.");
+
+ if (const char* e = GetErrorText(targetName, propertyName)) {
+ reportError(context, content->GetOriginalExpression(), e);
return std::string();
}
- if (propertyName == "ALIASED_TARGET") {
+ if (propertyName == "ALIASED_TARGET"_s) {
if (context->LG->GetMakefile()->IsAlias(targetName)) {
if (cmGeneratorTarget* tgt =
context->LG->FindGeneratorTargetToUse(targetName)) {
return tgt->GetName();
}
}
- return "";
+ return std::string();
}
target = context->LG->FindGeneratorTargetToUse(targetName);
@@ -984,15 +1139,34 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
return std::string();
}
context->AllTargets.insert(target);
- }
- if (target == context->HeadTarget) {
+ } else if (parameters.size() == 1) {
+ target = context->HeadTarget;
+ propertyName = parameters[0];
+
// Keep track of the properties seen while processing.
// The evaluation of the LINK_LIBRARIES generator expressions
// will check this to ensure that properties have one consistent
// value for all evaluations.
context->SeenTargetProperties.insert(propertyName);
+
+ context->HadHeadSensitiveCondition = true;
+ if (!target) {
+ reportError(
+ context, content->GetOriginalExpression(),
+ "$<TARGET_PROPERTY:prop> may only be used with binary targets. "
+ "It may not be used with add_custom_command or add_custom_target. "
+ "Specify the target to read a property from using the "
+ "$<TARGET_PROPERTY:tgt,prop> signature instead.");
+ return std::string();
+ }
+ } else {
+ reportError(
+ context, content->GetOriginalExpression(),
+ "$<TARGET_PROPERTY:...> expression requires one or two parameters");
+ return std::string();
}
+
if (propertyName == "SOURCES") {
context->SourceSensitiveTargets.insert(target);
}
@@ -1026,37 +1200,37 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
return target->GetLinkerLanguage(context->Config);
}
- cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
- target->GetName(), propertyName,
- content, dagCheckerParent);
+ std::string interfacePropertyName;
+ bool isInterfaceProperty = false;
- switch (dagChecker.Check()) {
- case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
- dagChecker.ReportError(context, content->GetOriginalExpression());
- return std::string();
- case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
- // No error. We just skip cyclic references.
- return std::string();
- case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
- for (size_t i = 1; i < cmArraySize(targetPropertyTransitiveWhitelist);
- ++i) {
- if (targetPropertyTransitiveWhitelist[i] == propertyName) {
- // No error. We're not going to find anything new here.
- return std::string();
- }
- }
- case cmGeneratorExpressionDAGChecker::DAG:
- break;
+#define POPULATE_INTERFACE_PROPERTY_NAME(prop) \
+ if (propertyName == #prop) { \
+ interfacePropertyName = "INTERFACE_" #prop; \
+ } else if (propertyName == "INTERFACE_" #prop) { \
+ interfacePropertyName = "INTERFACE_" #prop; \
+ isInterfaceProperty = true; \
+ } else
+
+ CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(POPULATE_INTERFACE_PROPERTY_NAME)
+ // Note that the above macro terminates with an else
+ /* else */ if (cmHasLiteralPrefix(propertyName, "COMPILE_DEFINITIONS_")) {
+ cmPolicies::PolicyStatus polSt =
+ context->LG->GetPolicyStatus(cmPolicies::CMP0043);
+ if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) {
+ interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
+ }
}
+#undef POPULATE_INTERFACE_PROPERTY_NAME
- const char* prop = target->GetProperty(propertyName);
+ bool evaluatingLinkLibraries = false;
if (dagCheckerParent) {
- if (dagCheckerParent->EvaluatingLinkLibraries()) {
-#define TRANSITIVE_PROPERTY_COMPARE(PROPERTY) \
- (#PROPERTY == propertyName || "INTERFACE_" #PROPERTY == propertyName) ||
- if (CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(
- TRANSITIVE_PROPERTY_COMPARE) false) { // NOLINT(clang-tidy)
+ if (dagCheckerParent->EvaluatingGenexExpression() ||
+ dagCheckerParent->EvaluatingPICExpression()) {
+ // No check required.
+ } else if (dagCheckerParent->EvaluatingLinkLibraries()) {
+ evaluatingLinkLibraries = true;
+ if (!interfacePropertyName.empty()) {
reportError(
context, content->GetOriginalExpression(),
"$<TARGET_PROPERTY:...> expression in link libraries "
@@ -1064,70 +1238,47 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
"over the link libraries, creating a recursion.");
return std::string();
}
-#undef TRANSITIVE_PROPERTY_COMPARE
-
- if (!prop) {
- return std::string();
- }
} else {
#define ASSERT_TRANSITIVE_PROPERTY_METHOD(METHOD) dagCheckerParent->METHOD() ||
-
assert(CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
ASSERT_TRANSITIVE_PROPERTY_METHOD) false); // NOLINT(clang-tidy)
#undef ASSERT_TRANSITIVE_PROPERTY_METHOD
}
}
- std::string linkedTargetsContent;
-
- std::string interfacePropertyName;
- bool isInterfaceProperty = false;
+ if (isInterfaceProperty) {
+ return target->EvaluateInterfaceProperty(propertyName, context,
+ dagCheckerParent);
+ }
-#define POPULATE_INTERFACE_PROPERTY_NAME(prop) \
- if (propertyName == #prop) { \
- interfacePropertyName = "INTERFACE_" #prop; \
- } else if (propertyName == "INTERFACE_" #prop) { \
- interfacePropertyName = "INTERFACE_" #prop; \
- isInterfaceProperty = true; \
- } else
+ cmGeneratorExpressionDAGChecker dagChecker(
+ context->Backtrace, target, propertyName, content, dagCheckerParent);
- 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_")) {
- cmPolicies::PolicyStatus polSt =
- context->LG->GetPolicyStatus(cmPolicies::CMP0043);
- if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) {
- interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
- }
+ switch (dagChecker.Check()) {
+ case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
+ dagChecker.ReportError(context, content->GetOriginalExpression());
+ return std::string();
+ case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
+ // No error. We just skip cyclic references.
+ return std::string();
+ case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
+ // We handle transitive properties above. For non-transitive
+ // properties we accept repeats anyway.
+ case cmGeneratorExpressionDAGChecker::DAG:
+ break;
}
-#undef POPULATE_INTERFACE_PROPERTY_NAME
- cmGeneratorTarget const* headTarget =
- context->HeadTarget && isInterfaceProperty ? context->HeadTarget
- : target;
- if (isInterfaceProperty) {
- if (cmLinkInterfaceLibraries const* iface =
- target->GetLinkInterfaceLibraries(context->Config, headTarget,
- true)) {
- linkedTargetsContent =
- getLinkedTargetsContent(iface->Libraries, target, headTarget,
- context, &dagChecker, interfacePropertyName);
- }
- } else if (!interfacePropertyName.empty()) {
- if (cmLinkImplementationLibraries const* impl =
- target->GetLinkImplementationLibraries(context->Config)) {
- linkedTargetsContent =
- getLinkedTargetsContent(impl->Libraries, target, target, context,
- &dagChecker, interfacePropertyName);
- }
+ std::string result;
+ bool haveProp = false;
+ if (const char* p = target->GetProperty(propertyName)) {
+ result = p;
+ haveProp = true;
+ } else if (evaluatingLinkLibraries) {
+ return std::string();
}
- if (!prop) {
- if (target->IsImported() ||
- target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
- return linkedTargetsContent;
- }
+ if (!haveProp && !target->IsImported() &&
+ target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
context->Config)) {
context->HadContextSensitiveCondition = true;
@@ -1160,8 +1311,6 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
context->Config);
return propContent ? propContent : "";
}
-
- return linkedTargetsContent;
}
if (!target->IsImported() && dagCheckerParent &&
@@ -1183,49 +1332,51 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
return propContent ? propContent : "";
}
}
+
if (!interfacePropertyName.empty()) {
- std::string result = this->EvaluateDependentExpression(
- prop, context->LG, context, headTarget, target, &dagChecker);
+ result = this->EvaluateDependentExpression(result, context->LG, context,
+ target, &dagChecker, target);
+ std::string linkedTargetsContent = getLinkedTargetsContent(
+ target, interfacePropertyName, context, &dagChecker);
if (!linkedTargetsContent.empty()) {
result += (result.empty() ? "" : ";") + linkedTargetsContent;
}
- return result;
}
- return prop;
+ return result;
}
} targetPropertyNode;
static const struct TargetNameNode : public cmGeneratorExpressionNode
{
- TargetNameNode() {}
+ TargetNameNode() {} // NOLINT(modernize-use-equals-default)
- bool GeneratesContent() const CM_OVERRIDE { return true; }
+ bool GeneratesContent() const override { return true; }
- bool AcceptsArbitraryContentParameter() const CM_OVERRIDE { return true; }
- bool RequiresLiteralInput() const CM_OVERRIDE { return true; }
+ bool AcceptsArbitraryContentParameter() const override { return true; }
+ bool RequiresLiteralInput() const override { return true; }
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* /*context*/,
- const GeneratorExpressionContent* /*content*/,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
return parameters.front();
}
- int NumExpectedParameters() const CM_OVERRIDE { return 1; }
+ int NumExpectedParameters() const override { return 1; }
} targetNameNode;
static const struct TargetObjectsNode : public cmGeneratorExpressionNode
{
- TargetObjectsNode() {}
+ TargetObjectsNode() {} // NOLINT(modernize-use-equals-default)
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
std::string tgtName = parameters.front();
cmGeneratorTarget* gt = context->LG->FindGeneratorTargetToUse(tgtName);
@@ -1236,10 +1387,16 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
}
- if (gt->GetType() != cmStateEnums::OBJECT_LIBRARY) {
+ cmStateEnums::TargetType type = gt->GetType();
+ if (type != cmStateEnums::EXECUTABLE &&
+ type != cmStateEnums::STATIC_LIBRARY &&
+ type != cmStateEnums::SHARED_LIBRARY &&
+ type != cmStateEnums::MODULE_LIBRARY &&
+ type != cmStateEnums::OBJECT_LIBRARY) {
std::ostringstream e;
e << "Objects of target \"" << tgtName
- << "\" referenced but is not an OBJECT library.";
+ << "\" referenced but is not an allowed library types (EXECUTABLE, "
+ << "STATIC, SHARED, MODULE, OBJECT).";
reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
}
@@ -1250,8 +1407,9 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
std::ostringstream e;
e << "The evaluation of the TARGET_OBJECTS generator expression "
"is only suitable for consumption by CMake (limited"
- << reason << "). "
- "It is not suitable for writing out elsewhere.";
+ << reason
+ << "). "
+ "It is not suitable for writing out elsewhere.";
reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
}
@@ -1260,11 +1418,11 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
std::vector<std::string> objects;
if (gt->IsImported()) {
- const char* loc = CM_NULLPTR;
- const char* imp = CM_NULLPTR;
+ const char* loc = nullptr;
+ const char* imp = nullptr;
std::string suffix;
if (gt->Target->GetMappedConfig(context->Config, &loc, &imp, suffix)) {
- cmSystemTools::ExpandListArgument(loc, objects);
+ cmExpandList(loc, objects);
}
context->HadContextSensitiveCondition = true;
} else {
@@ -1283,17 +1441,15 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
context->HadContextSensitiveCondition = true;
}
- for (std::vector<std::string>::iterator oi = objects.begin();
- oi != objects.end(); ++oi) {
- *oi = obj_dir + *oi;
+ for (std::string& o : objects) {
+ o = cmStrCat(obj_dir, o);
}
}
// Create the cmSourceFile instances in the referencing directory.
cmMakefile* mf = context->LG->GetMakefile();
- for (std::vector<std::string>::iterator oi = objects.begin();
- oi != objects.end(); ++oi) {
- mf->AddTargetObject(tgtName, *oi);
+ for (std::string& o : objects) {
+ mf->AddTargetObject(tgtName, o);
}
return cmJoin(objects, ";");
@@ -1302,15 +1458,15 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
{
- CompileFeaturesNode() {}
+ CompileFeaturesNode() {} // NOLINT(modernize-use-equals-default)
- int NumExpectedParameters() const CM_OVERRIDE { return OneOrMoreParameters; }
+ int NumExpectedParameters() const override { return OneOrMoreParameters; }
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* dagChecker) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagChecker) const override
{
cmGeneratorTarget const* target = context->HeadTarget;
if (!target) {
@@ -1322,21 +1478,20 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
}
context->HadHeadSensitiveCondition = true;
- typedef std::map<std::string, std::vector<std::string> > LangMap;
+ using LangMap = std::map<std::string, std::vector<std::string>>;
static LangMap availableFeatures;
LangMap testedFeatures;
- for (std::vector<std::string>::const_iterator it = parameters.begin();
- it != parameters.end(); ++it) {
+ for (std::string const& p : parameters) {
std::string error;
std::string lang;
if (!context->LG->GetMakefile()->CompileFeatureKnown(
- context->HeadTarget->Target, *it, lang, &error)) {
+ context->HeadTarget->Target, p, lang, &error)) {
reportError(context, content->GetOriginalExpression(), error);
return std::string();
}
- testedFeatures[lang].push_back(*it);
+ testedFeatures[lang].push_back(p);
if (availableFeatures.find(lang) == availableFeatures.end()) {
const char* featuresKnown =
@@ -1345,23 +1500,19 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
reportError(context, content->GetOriginalExpression(), error);
return std::string();
}
- cmSystemTools::ExpandListArgument(featuresKnown,
- availableFeatures[lang]);
+ cmExpandList(featuresKnown, availableFeatures[lang]);
}
}
bool evalLL = dagChecker && dagChecker->EvaluatingLinkLibraries();
- for (LangMap::const_iterator lit = testedFeatures.begin();
- lit != testedFeatures.end(); ++lit) {
+ for (auto const& lit : testedFeatures) {
std::vector<std::string> const& langAvailable =
- availableFeatures[lit->first];
+ availableFeatures[lit.first];
const char* standardDefault = context->LG->GetMakefile()->GetDefinition(
- "CMAKE_" + lit->first + "_STANDARD_DEFAULT");
- for (std::vector<std::string>::const_iterator it = lit->second.begin();
- it != lit->second.end(); ++it) {
- if (std::find(langAvailable.begin(), langAvailable.end(), *it) ==
- langAvailable.end()) {
+ "CMAKE_" + lit.first + "_STANDARD_DEFAULT");
+ for (std::string const& it : lit.second) {
+ if (!cmContains(langAvailable, it)) {
return "0";
}
if (standardDefault && !*standardDefault) {
@@ -1370,14 +1521,14 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
continue;
}
if (!context->LG->GetMakefile()->HaveStandardAvailable(
- target->Target, lit->first, *it)) {
+ target->Target, lit.first, it)) {
if (evalLL) {
- const char* l = target->GetProperty(lit->first + "_STANDARD");
+ const char* l = target->GetProperty(lit.first + "_STANDARD");
if (!l) {
l = standardDefault;
}
assert(l);
- context->MaxLanguageStandard[target][lit->first] = l;
+ context->MaxLanguageStandard[target][lit.first] = l;
} else {
return "0";
}
@@ -1389,10 +1540,10 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
} compileFeaturesNode;
static const char* targetPolicyWhitelist[] = {
- CM_NULLPTR
+ nullptr
#define TARGET_POLICY_STRING(POLICY) , #POLICY
- CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_STRING)
+ CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_STRING)
#undef TARGET_POLICY_STRING
};
@@ -1430,15 +1581,15 @@ cmPolicies::PolicyID policyForString(const char* policy_id)
static const struct TargetPolicyNode : public cmGeneratorExpressionNode
{
- TargetPolicyNode() {}
+ TargetPolicyNode() {} // NOLINT(modernize-use-equals-default)
- int NumExpectedParameters() const CM_OVERRIDE { return 1; }
+ int NumExpectedParameters() const override { return 1; }
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
if (!context->HeadTarget) {
reportError(
@@ -1451,14 +1602,14 @@ 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();
switch (statusForTarget(context->HeadTarget, policy)) {
case cmPolicies::WARN:
lg->IssueMessage(
- cmake::AUTHOR_WARNING,
+ MessageType::AUTHOR_WARNING,
cmPolicies::GetPolicyWarning(policyForString(policy)));
CM_FALLTHROUGH;
case cmPolicies::REQUIRED_IF_USED:
@@ -1483,7 +1634,7 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode
CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_LIST_ITEM)
#undef TARGET_POLICY_LIST_ITEM
- );
+ );
return std::string();
}
@@ -1491,16 +1642,16 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode
static const struct InstallPrefixNode : public cmGeneratorExpressionNode
{
- InstallPrefixNode() {}
+ InstallPrefixNode() {} // NOLINT(modernize-use-equals-default)
- bool GeneratesContent() const CM_OVERRIDE { return true; }
- int NumExpectedParameters() const CM_OVERRIDE { return 0; }
+ bool GeneratesContent() const override { return true; }
+ int NumExpectedParameters() const override { return 0; }
- std::string Evaluate(const std::vector<std::string>& /*parameters*/,
- cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& /*parameters*/,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
reportError(context, content->GetOriginalExpression(),
"INSTALL_PREFIX is a marker for install(EXPORT) only. It "
@@ -1547,9 +1698,8 @@ struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag>
"SHARED libraries.");
return std::string();
}
- std::string result = target->GetDirectory(context->Config);
- result += "/";
- result += target->GetSOName(context->Config);
+ std::string result = cmStrCat(target->GetDirectory(context->Config), '/',
+ target->GetSOName(context->Config));
return result;
}
};
@@ -1588,9 +1738,8 @@ struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag>
return std::string();
}
- std::string result = target->GetPDBDirectory(context->Config);
- result += "/";
- result += target->GetPDBName(context->Config);
+ std::string result = cmStrCat(target->GetPDBDirectory(context->Config),
+ '/', target->GetPDBName(context->Config));
return result;
}
};
@@ -1609,7 +1758,8 @@ struct TargetFilesystemArtifactResultCreator<ArtifactLinkerTag>
"executables with ENABLE_EXPORTS.");
return std::string();
}
- cmStateEnums::ArtifactType artifact = target->HasImportLibrary()
+ cmStateEnums::ArtifactType artifact =
+ target->HasImportLibrary(context->Config)
? cmStateEnums::ImportLibraryArtifact
: cmStateEnums::RuntimeBinaryArtifact;
return target->GetFullPath(context->Config, artifact);
@@ -1708,45 +1858,68 @@ struct TargetFilesystemArtifactResultGetter<ArtifactPathTag>
static std::string Get(const std::string& result) { return result; }
};
-template <typename ArtifactT, typename ComponentT>
-struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
+struct TargetArtifactBase : public cmGeneratorExpressionNode
{
- TargetFilesystemArtifact() {}
-
- int NumExpectedParameters() const CM_OVERRIDE { return 1; }
-
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* dagChecker) const
- CM_OVERRIDE
+ TargetArtifactBase() {} // NOLINT(modernize-use-equals-default)
+
+protected:
+ cmGeneratorTarget* GetTarget(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagChecker) const
{
// Lookup the referenced target.
- std::string name = *parameters.begin();
+ std::string name = parameters.front();
if (!cmGeneratorExpression::IsValidTargetName(name)) {
::reportError(context, content->GetOriginalExpression(),
"Expression syntax not recognized.");
- return std::string();
+ return nullptr;
}
cmGeneratorTarget* target = context->LG->FindGeneratorTargetToUse(name);
if (!target) {
::reportError(context, content->GetOriginalExpression(),
"No target \"" + name + "\"");
- return std::string();
+ return nullptr;
}
if (target->GetType() >= cmStateEnums::OBJECT_LIBRARY &&
target->GetType() != cmStateEnums::UNKNOWN_LIBRARY) {
- ::reportError(context, content->GetOriginalExpression(), "Target \"" +
- name + "\" is not an executable or library.");
- return std::string();
- }
- if (dagChecker && (dagChecker->EvaluatingLinkLibraries(name.c_str()) ||
- (dagChecker->EvaluatingSources() &&
- name == dagChecker->TopTarget()))) {
+ ::reportError(context, content->GetOriginalExpression(),
+ "Target \"" + name +
+ "\" is not an executable or library.");
+ return nullptr;
+ }
+ if (dagChecker &&
+ (dagChecker->EvaluatingLinkLibraries(target) ||
+ (dagChecker->EvaluatingSources() &&
+ target == dagChecker->TopTarget()))) {
::reportError(context, content->GetOriginalExpression(),
"Expressions which require the linker language may not "
"be used while evaluating link libraries");
+ return nullptr;
+ }
+
+ return target;
+ }
+};
+
+template <typename ArtifactT, typename ComponentT>
+struct TargetFilesystemArtifact : public TargetArtifactBase
+{
+ TargetFilesystemArtifact() {} // NOLINT(modernize-use-equals-default)
+
+ int NumExpectedParameters() const override { return 1; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagChecker) const override
+ {
+ cmGeneratorTarget* target =
+ this->GetTarget(parameters, context, content, dagChecker);
+ if (!target) {
return std::string();
}
context->DependTargets.insert(target);
@@ -1765,7 +1938,9 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
template <typename ArtifactT>
struct TargetFilesystemArtifactNodeGroup
{
- TargetFilesystemArtifactNodeGroup() {}
+ TargetFilesystemArtifactNodeGroup() // NOLINT(modernize-use-equals-default)
+ {
+ }
TargetFilesystemArtifact<ArtifactT, ArtifactPathTag> File;
TargetFilesystemArtifact<ArtifactT, ArtifactNameTag> FileName;
@@ -1791,91 +1966,364 @@ static const TargetFilesystemArtifact<ArtifactBundleContentDirTag,
ArtifactPathTag>
targetBundleContentDirNode;
+//
+// To retrieve base name for various artifacts
+//
+template <typename ArtifactT>
+struct TargetOutputNameArtifactResultGetter
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content);
+};
+
+template <>
+struct TargetOutputNameArtifactResultGetter<ArtifactNameTag>
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* /*unused*/)
+ {
+ return target->GetOutputName(context->Config,
+ cmStateEnums::RuntimeBinaryArtifact) +
+ target->GetFilePostfix(context->Config);
+ }
+};
+
+template <>
+struct TargetOutputNameArtifactResultGetter<ArtifactLinkerTag>
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content)
+ {
+ // The file used to link to the target (.so, .lib, .a).
+ if (!target->IsLinkable()) {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_LINKER_FILE_BASE_NAME is allowed only for "
+ "libraries and executables with ENABLE_EXPORTS.");
+ return std::string();
+ }
+ cmStateEnums::ArtifactType artifact =
+ target->HasImportLibrary(context->Config)
+ ? cmStateEnums::ImportLibraryArtifact
+ : cmStateEnums::RuntimeBinaryArtifact;
+ return target->GetOutputName(context->Config, artifact) +
+ target->GetFilePostfix(context->Config);
+ }
+};
+
+template <>
+struct TargetOutputNameArtifactResultGetter<ArtifactPdbTag>
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content)
+ {
+ if (target->IsImported()) {
+ ::reportError(
+ context, content->GetOriginalExpression(),
+ "TARGET_PDB_FILE_BASE_NAME not allowed for IMPORTED targets.");
+ return std::string();
+ }
+
+ std::string language = target->GetLinkerLanguage(context->Config);
+
+ std::string pdbSupportVar = "CMAKE_" + language + "_LINKER_SUPPORTS_PDB";
+
+ if (!context->LG->GetMakefile()->IsOn(pdbSupportVar)) {
+ ::reportError(
+ context, content->GetOriginalExpression(),
+ "TARGET_PDB_FILE_BASE_NAME is not supported by the target linker.");
+ return std::string();
+ }
+
+ cmStateEnums::TargetType targetType = target->GetType();
+
+ if (targetType != cmStateEnums::SHARED_LIBRARY &&
+ targetType != cmStateEnums::MODULE_LIBRARY &&
+ targetType != cmStateEnums::EXECUTABLE) {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_PDB_FILE_BASE_NAME is allowed only for "
+ "targets with linker created artifacts.");
+ return std::string();
+ }
+
+ return target->GetPDBOutputName(context->Config) +
+ target->GetFilePostfix(context->Config);
+ }
+};
+
+template <typename ArtifactT>
+struct TargetFileBaseNameArtifact : public TargetArtifactBase
+{
+ TargetFileBaseNameArtifact() {} // NOLINT(modernize-use-equals-default)
+
+ int NumExpectedParameters() const override { return 1; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagChecker) const override
+ {
+ cmGeneratorTarget* target =
+ this->GetTarget(parameters, context, content, dagChecker);
+ if (!target) {
+ return std::string();
+ }
+
+ std::string result = TargetOutputNameArtifactResultGetter<ArtifactT>::Get(
+ target, context, content);
+ if (context->HadError) {
+ return std::string();
+ }
+ return result;
+ }
+};
+
+static const TargetFileBaseNameArtifact<ArtifactNameTag>
+ targetFileBaseNameNode;
+static const TargetFileBaseNameArtifact<ArtifactLinkerTag>
+ targetLinkerFileBaseNameNode;
+static const TargetFileBaseNameArtifact<ArtifactPdbTag>
+ targetPdbFileBaseNameNode;
+
+class ArtifactFilePrefixTag;
+class ArtifactLinkerFilePrefixTag;
+class ArtifactFileSuffixTag;
+class ArtifactLinkerFileSuffixTag;
+
+template <typename ArtifactT>
+struct TargetFileArtifactResultGetter
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content);
+};
+
+template <>
+struct TargetFileArtifactResultGetter<ArtifactFilePrefixTag>
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent*)
+ {
+ return target->GetFilePrefix(context->Config);
+ }
+};
+template <>
+struct TargetFileArtifactResultGetter<ArtifactLinkerFilePrefixTag>
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content)
+ {
+ if (!target->IsLinkable()) {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_LINKER_PREFIX is allowed only for libraries and "
+ "executables with ENABLE_EXPORTS.");
+ return std::string();
+ }
+
+ cmStateEnums::ArtifactType artifact =
+ target->HasImportLibrary(context->Config)
+ ? cmStateEnums::ImportLibraryArtifact
+ : cmStateEnums::RuntimeBinaryArtifact;
+
+ return target->GetFilePrefix(context->Config, artifact);
+ }
+};
+template <>
+struct TargetFileArtifactResultGetter<ArtifactFileSuffixTag>
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent*)
+ {
+ return target->GetFileSuffix(context->Config);
+ }
+};
+template <>
+struct TargetFileArtifactResultGetter<ArtifactLinkerFileSuffixTag>
+{
+ static std::string Get(cmGeneratorTarget* target,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content)
+ {
+ if (!target->IsLinkable()) {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_LINKER_SUFFIX is allowed only for libraries and "
+ "executables with ENABLE_EXPORTS.");
+ return std::string();
+ }
+
+ cmStateEnums::ArtifactType artifact =
+ target->HasImportLibrary(context->Config)
+ ? cmStateEnums::ImportLibraryArtifact
+ : cmStateEnums::RuntimeBinaryArtifact;
+
+ return target->GetFileSuffix(context->Config, artifact);
+ }
+};
+
+template <typename ArtifactT>
+struct TargetFileArtifact : public TargetArtifactBase
+{
+ TargetFileArtifact() {} // NOLINT(modernize-use-equals-default)
+
+ int NumExpectedParameters() const override { return 1; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* dagChecker) const override
+ {
+ cmGeneratorTarget* target =
+ this->GetTarget(parameters, context, content, dagChecker);
+ if (!target) {
+ return std::string();
+ }
+
+ std::string result =
+ TargetFileArtifactResultGetter<ArtifactT>::Get(target, context, content);
+ if (context->HadError) {
+ return std::string();
+ }
+ return result;
+ }
+};
+
+static const TargetFileArtifact<ArtifactFilePrefixTag> targetFilePrefixNode;
+static const TargetFileArtifact<ArtifactLinkerFilePrefixTag>
+ targetLinkerFilePrefixNode;
+static const TargetFileArtifact<ArtifactFileSuffixTag> targetFileSuffixNode;
+static const TargetFileArtifact<ArtifactLinkerFileSuffixTag>
+ targetLinkerFileSuffixNode;
+
static const struct ShellPathNode : public cmGeneratorExpressionNode
{
- ShellPathNode() {}
+ ShellPathNode() {} // NOLINT(modernize-use-equals-default)
- std::string Evaluate(const std::vector<std::string>& parameters,
- cmGeneratorExpressionContext* context,
- const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* /*dagChecker*/) const
- CM_OVERRIDE
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
- if (!cmSystemTools::FileIsFullPath(parameters.front())) {
+ std::vector<std::string> listIn = cmExpandedList(parameters.front());
+ if (listIn.empty()) {
reportError(context, content->GetOriginalExpression(),
- "\"" + parameters.front() + "\" is not an absolute path.");
+ "\"\" is not an absolute path.");
return std::string();
}
- cmOutputConverter converter(context->LG->GetStateSnapshot());
- return converter.ConvertDirectorySeparatorsForShell(parameters.front());
+ cmStateSnapshot snapshot = context->LG->GetStateSnapshot();
+ cmOutputConverter converter(snapshot);
+ const char* separator = snapshot.GetState()->UseWindowsShell() ? ";" : ":";
+ std::vector<std::string> listOut;
+ listOut.reserve(listIn.size());
+ for (auto const& in : listIn) {
+ if (!cmSystemTools::FileIsFullPath(in)) {
+ reportError(context, content->GetOriginalExpression(),
+ "\"" + in + "\" is not an absolute path.");
+ return std::string();
+ }
+ listOut.emplace_back(converter.ConvertDirectorySeparatorsForShell(in));
+ }
+ return cmJoin(listOut, separator);
}
} shellPathNode;
const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
const std::string& identifier)
{
- typedef std::map<std::string, const cmGeneratorExpressionNode*> NodeMap;
- static NodeMap nodeMap;
- if (nodeMap.empty()) {
- nodeMap["0"] = &zeroNode;
- nodeMap["1"] = &oneNode;
- nodeMap["AND"] = &andNode;
- nodeMap["OR"] = &orNode;
- nodeMap["NOT"] = &notNode;
- nodeMap["C_COMPILER_ID"] = &cCompilerIdNode;
- nodeMap["CXX_COMPILER_ID"] = &cxxCompilerIdNode;
- nodeMap["VERSION_GREATER"] = &versionGreaterNode;
- nodeMap["VERSION_GREATER_EQUAL"] = &versionGreaterEqNode;
- nodeMap["VERSION_LESS"] = &versionLessNode;
- nodeMap["VERSION_LESS_EQUAL"] = &versionLessEqNode;
- nodeMap["VERSION_EQUAL"] = &versionEqualNode;
- nodeMap["C_COMPILER_VERSION"] = &cCompilerVersionNode;
- nodeMap["CXX_COMPILER_VERSION"] = &cxxCompilerVersionNode;
- nodeMap["PLATFORM_ID"] = &platformIdNode;
- nodeMap["COMPILE_FEATURES"] = &compileFeaturesNode;
- nodeMap["CONFIGURATION"] = &configurationNode;
- nodeMap["CONFIG"] = &configurationTestNode;
- nodeMap["TARGET_FILE"] = &targetNodeGroup.File;
- nodeMap["TARGET_LINKER_FILE"] = &targetLinkerNodeGroup.File;
- nodeMap["TARGET_SONAME_FILE"] = &targetSoNameNodeGroup.File;
- nodeMap["TARGET_PDB_FILE"] = &targetPdbNodeGroup.File;
- nodeMap["TARGET_FILE_NAME"] = &targetNodeGroup.FileName;
- nodeMap["TARGET_LINKER_FILE_NAME"] = &targetLinkerNodeGroup.FileName;
- nodeMap["TARGET_SONAME_FILE_NAME"] = &targetSoNameNodeGroup.FileName;
- nodeMap["TARGET_PDB_FILE_NAME"] = &targetPdbNodeGroup.FileName;
- nodeMap["TARGET_FILE_DIR"] = &targetNodeGroup.FileDir;
- nodeMap["TARGET_LINKER_FILE_DIR"] = &targetLinkerNodeGroup.FileDir;
- nodeMap["TARGET_SONAME_FILE_DIR"] = &targetSoNameNodeGroup.FileDir;
- nodeMap["TARGET_PDB_FILE_DIR"] = &targetPdbNodeGroup.FileDir;
- nodeMap["TARGET_BUNDLE_DIR"] = &targetBundleDirNode;
- nodeMap["TARGET_BUNDLE_CONTENT_DIR"] = &targetBundleContentDirNode;
- nodeMap["STREQUAL"] = &strEqualNode;
- nodeMap["EQUAL"] = &equalNode;
- nodeMap["LOWER_CASE"] = &lowerCaseNode;
- nodeMap["UPPER_CASE"] = &upperCaseNode;
- nodeMap["MAKE_C_IDENTIFIER"] = &makeCIdentifierNode;
- nodeMap["BOOL"] = &boolNode;
- nodeMap["IF"] = &ifNode;
- nodeMap["ANGLE-R"] = &angle_rNode;
- nodeMap["COMMA"] = &commaNode;
- nodeMap["SEMICOLON"] = &semicolonNode;
- nodeMap["TARGET_PROPERTY"] = &targetPropertyNode;
- nodeMap["TARGET_NAME"] = &targetNameNode;
- nodeMap["TARGET_OBJECTS"] = &targetObjectsNode;
- nodeMap["TARGET_POLICY"] = &targetPolicyNode;
- nodeMap["BUILD_INTERFACE"] = &buildInterfaceNode;
- nodeMap["INSTALL_INTERFACE"] = &installInterfaceNode;
- nodeMap["INSTALL_PREFIX"] = &installPrefixNode;
- nodeMap["JOIN"] = &joinNode;
- nodeMap["LINK_ONLY"] = &linkOnlyNode;
- nodeMap["COMPILE_LANGUAGE"] = &languageNode;
- nodeMap["SHELL_PATH"] = &shellPathNode;
- }
- NodeMap::const_iterator i = nodeMap.find(identifier);
- if (i == nodeMap.end()) {
- return CM_NULLPTR;
- }
- return i->second;
+ static std::map<std::string, cmGeneratorExpressionNode const*> const nodeMap{
+ { "0", &zeroNode },
+ { "1", &oneNode },
+ { "AND", &andNode },
+ { "OR", &orNode },
+ { "NOT", &notNode },
+ { "C_COMPILER_ID", &cCompilerIdNode },
+ { "CXX_COMPILER_ID", &cxxCompilerIdNode },
+ { "OBJC_COMPILER_ID", &objcCompilerIdNode },
+ { "OBJCXX_COMPILER_ID", &objcxxCompilerIdNode },
+ { "CUDA_COMPILER_ID", &cudaCompilerIdNode },
+ { "Fortran_COMPILER_ID", &fortranCompilerIdNode },
+ { "VERSION_GREATER", &versionGreaterNode },
+ { "VERSION_GREATER_EQUAL", &versionGreaterEqNode },
+ { "VERSION_LESS", &versionLessNode },
+ { "VERSION_LESS_EQUAL", &versionLessEqNode },
+ { "VERSION_EQUAL", &versionEqualNode },
+ { "C_COMPILER_VERSION", &cCompilerVersionNode },
+ { "CXX_COMPILER_VERSION", &cxxCompilerVersionNode },
+ { "CUDA_COMPILER_VERSION", &cudaCompilerVersionNode },
+ { "OBJC_COMPILER_VERSION", &objcCompilerVersionNode },
+ { "OBJCXX_COMPILER_VERSION", &objcxxCompilerVersionNode },
+ { "Fortran_COMPILER_VERSION", &fortranCompilerVersionNode },
+ { "PLATFORM_ID", &platformIdNode },
+ { "COMPILE_FEATURES", &compileFeaturesNode },
+ { "CONFIGURATION", &configurationNode },
+ { "CONFIG", &configurationTestNode },
+ { "TARGET_FILE", &targetNodeGroup.File },
+ { "TARGET_LINKER_FILE", &targetLinkerNodeGroup.File },
+ { "TARGET_SONAME_FILE", &targetSoNameNodeGroup.File },
+ { "TARGET_PDB_FILE", &targetPdbNodeGroup.File },
+ { "TARGET_FILE_BASE_NAME", &targetFileBaseNameNode },
+ { "TARGET_LINKER_FILE_BASE_NAME", &targetLinkerFileBaseNameNode },
+ { "TARGET_PDB_FILE_BASE_NAME", &targetPdbFileBaseNameNode },
+ { "TARGET_FILE_PREFIX", &targetFilePrefixNode },
+ { "TARGET_LINKER_FILE_PREFIX", &targetLinkerFilePrefixNode },
+ { "TARGET_FILE_SUFFIX", &targetFileSuffixNode },
+ { "TARGET_LINKER_FILE_SUFFIX", &targetLinkerFileSuffixNode },
+ { "TARGET_FILE_NAME", &targetNodeGroup.FileName },
+ { "TARGET_LINKER_FILE_NAME", &targetLinkerNodeGroup.FileName },
+ { "TARGET_SONAME_FILE_NAME", &targetSoNameNodeGroup.FileName },
+ { "TARGET_PDB_FILE_NAME", &targetPdbNodeGroup.FileName },
+ { "TARGET_FILE_DIR", &targetNodeGroup.FileDir },
+ { "TARGET_LINKER_FILE_DIR", &targetLinkerNodeGroup.FileDir },
+ { "TARGET_SONAME_FILE_DIR", &targetSoNameNodeGroup.FileDir },
+ { "TARGET_PDB_FILE_DIR", &targetPdbNodeGroup.FileDir },
+ { "TARGET_BUNDLE_DIR", &targetBundleDirNode },
+ { "TARGET_BUNDLE_CONTENT_DIR", &targetBundleContentDirNode },
+ { "STREQUAL", &strEqualNode },
+ { "EQUAL", &equalNode },
+ { "IN_LIST", &inListNode },
+ { "FILTER", &filterNode },
+ { "REMOVE_DUPLICATES", &removeDuplicatesNode },
+ { "LOWER_CASE", &lowerCaseNode },
+ { "UPPER_CASE", &upperCaseNode },
+ { "MAKE_C_IDENTIFIER", &makeCIdentifierNode },
+ { "BOOL", &boolNode },
+ { "IF", &ifNode },
+ { "ANGLE-R", &angle_rNode },
+ { "COMMA", &commaNode },
+ { "SEMICOLON", &semicolonNode },
+ { "TARGET_PROPERTY", &targetPropertyNode },
+ { "TARGET_NAME", &targetNameNode },
+ { "TARGET_OBJECTS", &targetObjectsNode },
+ { "TARGET_POLICY", &targetPolicyNode },
+ { "TARGET_EXISTS", &targetExistsNode },
+ { "TARGET_NAME_IF_EXISTS", &targetNameIfExistsNode },
+ { "TARGET_GENEX_EVAL", &targetGenexEvalNode },
+ { "GENEX_EVAL", &genexEvalNode },
+ { "BUILD_INTERFACE", &buildInterfaceNode },
+ { "INSTALL_INTERFACE", &installInterfaceNode },
+ { "INSTALL_PREFIX", &installPrefixNode },
+ { "JOIN", &joinNode },
+ { "LINK_ONLY", &linkOnlyNode },
+ { "COMPILE_LANG_AND_ID", &languageAndIdNode },
+ { "COMPILE_LANGUAGE", &languageNode },
+ { "SHELL_PATH", &shellPathNode }
+ };
+
+ {
+ auto itr = nodeMap.find(identifier);
+ if (itr != nodeMap.end()) {
+ return itr->second;
+ }
+ }
+ return nullptr;
}
void reportError(cmGeneratorExpressionContext* context,
@@ -1892,6 +2340,6 @@ void reportError(cmGeneratorExpressionContext* context,
<< " " << expr << "\n"
<< result;
/* clang-format on */
- context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
- context->Backtrace);
+ context->LG->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
+ e.str(), context->Backtrace);
}
diff --git a/Source/cmGeneratorExpressionNode.h b/Source/cmGeneratorExpressionNode.h
index ece1c113c..13e8484ef 100644
--- a/Source/cmGeneratorExpressionNode.h
+++ b/Source/cmGeneratorExpressionNode.h
@@ -20,9 +20,11 @@ struct cmGeneratorExpressionNode
{
DynamicParameters = 0,
OneOrMoreParameters = -1,
- OneOrZeroParameters = -2
+ TwoOrMoreParameters = -2,
+ ZeroOrMoreParameters = -3,
+ OneOrZeroParameters = -4
};
- virtual ~cmGeneratorExpressionNode() {}
+ virtual ~cmGeneratorExpressionNode() = default;
virtual bool GeneratesContent() const { return true; }
@@ -41,8 +43,8 @@ struct cmGeneratorExpressionNode
static std::string EvaluateDependentExpression(
std::string const& prop, cmLocalGenerator* lg,
cmGeneratorExpressionContext* context, const cmGeneratorTarget* headTarget,
- const cmGeneratorTarget* currentTarget,
- cmGeneratorExpressionDAGChecker* dagChecker);
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ const cmGeneratorTarget* currentTarget);
static const cmGeneratorExpressionNode* GetNode(
const std::string& identifier);
diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx
index c33349a63..d6cc6ab1c 100644
--- a/Source/cmGeneratorExpressionParser.cxx
+++ b/Source/cmGeneratorExpressionParser.cxx
@@ -2,14 +2,16 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorExpressionParser.h"
-#include "cmGeneratorExpressionEvaluator.h"
+#include <cassert>
+#include <cstddef>
+#include <utility>
-#include <assert.h>
-#include <stddef.h>
+#include "cmAlgorithms.h"
+#include "cmGeneratorExpressionEvaluator.h"
cmGeneratorExpressionParser::cmGeneratorExpressionParser(
- const std::vector<cmGeneratorExpressionToken>& tokens)
- : Tokens(tokens)
+ std::vector<cmGeneratorExpressionToken> tokens)
+ : Tokens(std::move(tokens))
, NestingLevel(0)
{
}
@@ -46,14 +48,14 @@ static void extendResult(
if (!result.empty() &&
(*(result.end() - 1))->GetType() ==
cmGeneratorExpressionEvaluator::Text &&
- (*contents.begin())->GetType() == cmGeneratorExpressionEvaluator::Text) {
+ contents.front()->GetType() == cmGeneratorExpressionEvaluator::Text) {
TextContent* textContent = static_cast<TextContent*>(*(result.end() - 1));
textContent->Extend(
- static_cast<TextContent*>(*contents.begin())->GetLength());
- delete *contents.begin();
- result.insert(result.end(), contents.begin() + 1, contents.end());
+ static_cast<TextContent*>(contents.front())->GetLength());
+ delete contents.front();
+ cmAppend(result, contents.begin() + 1, contents.end());
} else {
- result.insert(result.end(), contents.begin(), contents.end());
+ cmAppend(result, contents);
}
}
@@ -64,8 +66,7 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
unsigned int nestedLevel = this->NestingLevel;
++this->NestingLevel;
- std::vector<cmGeneratorExpressionToken>::const_iterator startToken =
- this->it - 1;
+ auto startToken = this->it - 1;
std::vector<cmGeneratorExpressionEvaluator*> identifier;
while (this->it->TokenType != cmGeneratorExpressionToken::EndExpression &&
@@ -86,18 +87,18 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
if (this->it != this->Tokens.end() &&
this->it->TokenType == cmGeneratorExpressionToken::EndExpression) {
- GeneratorExpressionContent* content =
- new GeneratorExpressionContent(startToken->Content, this->it->Content -
- startToken->Content + this->it->Length);
+ GeneratorExpressionContent* content = new GeneratorExpressionContent(
+ startToken->Content,
+ this->it->Content - startToken->Content + this->it->Length);
assert(this->it != this->Tokens.end());
++this->it;
--this->NestingLevel;
- content->SetIdentifier(identifier);
+ content->SetIdentifier(std::move(identifier));
result.push_back(content);
return;
}
- std::vector<std::vector<cmGeneratorExpressionEvaluator*> > parameters;
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*>> parameters;
std::vector<std::vector<cmGeneratorExpressionToken>::const_iterator>
commaTokens;
std::vector<cmGeneratorExpressionToken>::const_iterator colonToken;
@@ -172,13 +173,9 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
if (!parameters.empty()) {
extendText(result, colonToken);
- typedef std::vector<cmGeneratorExpressionEvaluator*> EvaluatorVector;
- typedef std::vector<cmGeneratorExpressionToken> TokenVector;
- std::vector<EvaluatorVector>::const_iterator pit = parameters.begin();
- const std::vector<EvaluatorVector>::const_iterator pend =
- parameters.end();
- std::vector<TokenVector::const_iterator>::const_iterator commaIt =
- commaTokens.begin();
+ auto pit = parameters.begin();
+ const auto pend = parameters.end();
+ auto commaIt = commaTokens.begin();
assert(parameters.size() > commaTokens.size());
for (; pit != pend; ++pit, ++commaIt) {
if (!pit->empty() && !emptyParamTermination) {
@@ -198,8 +195,8 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
((this->it - 1)->Content - startToken->Content) + (this->it - 1)->Length;
GeneratorExpressionContent* content =
new GeneratorExpressionContent(startToken->Content, contentLength);
- content->SetIdentifier(identifier);
- content->SetParameters(parameters);
+ content->SetIdentifier(std::move(identifier));
+ content->SetParameters(std::move(parameters));
result.push_back(content);
}
diff --git a/Source/cmGeneratorExpressionParser.h b/Source/cmGeneratorExpressionParser.h
index 633381c8a..e663496da 100644
--- a/Source/cmGeneratorExpressionParser.h
+++ b/Source/cmGeneratorExpressionParser.h
@@ -13,8 +13,7 @@ struct cmGeneratorExpressionEvaluator;
struct cmGeneratorExpressionParser
{
- cmGeneratorExpressionParser(
- const std::vector<cmGeneratorExpressionToken>& tokens);
+ cmGeneratorExpressionParser(std::vector<cmGeneratorExpressionToken> tokens);
void Parse(std::vector<cmGeneratorExpressionEvaluator*>& result);
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index c9924f670..171c3ed39 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -2,37 +2,50 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorTarget.h"
-#include "cmsys/RegularExpression.hxx"
#include <algorithm>
-#include <assert.h>
-#include <errno.h>
+#include <cassert>
+#include <cerrno>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
#include <iterator>
-#include <queue>
+#include <memory>
#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <unordered_set>
+#include <utility>
+
+#include <cm/string_view>
+
+#include <queue>
+
+#include "cmsys/RegularExpression.hxx"
#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmCustomCommandLines.h"
+#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionContext.h"
#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmGeneratorExpressionNode.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPropertyMap.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
+#include "cmSourceFileLocationKind.h"
#include "cmState.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetLinkLibraryType.h"
#include "cmTargetPropertyComputer.h"
-#include "cm_auto_ptr.hxx"
-#include "cm_unordered_set.hxx"
#include "cmake.h"
class cmMessenger;
@@ -46,8 +59,9 @@ const char* cmTargetPropertyComputer::GetSources<cmGeneratorTarget>(
}
template <>
-const char* cmTargetPropertyComputer::ComputeLocationForBuild<
- cmGeneratorTarget>(cmGeneratorTarget const* tgt)
+const char*
+cmTargetPropertyComputer::ComputeLocationForBuild<cmGeneratorTarget>(
+ cmGeneratorTarget const* tgt)
{
return tgt->GetLocation("");
}
@@ -61,35 +75,177 @@ const char* cmTargetPropertyComputer::ComputeLocation<cmGeneratorTarget>(
class cmGeneratorTarget::TargetPropertyEntry
{
+protected:
static cmLinkImplItem NoLinkImplItem;
public:
- TargetPropertyEntry(CM_AUTO_PTR<cmCompiledGeneratorExpression> cge,
- cmLinkImplItem const& item = NoLinkImplItem)
- : ge(cge)
- , LinkImplItem(item)
+ TargetPropertyEntry(cmLinkImplItem const& item)
+ : LinkImplItem(item)
{
}
- const CM_AUTO_PTR<cmCompiledGeneratorExpression> ge;
+ virtual ~TargetPropertyEntry() = default;
+
+ virtual const std::string& Evaluate(
+ cmLocalGenerator* lg, const std::string& config,
+ cmGeneratorTarget const* headTarget,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ std::string const& language) const = 0;
+
+ virtual cmListFileBacktrace GetBacktrace() const = 0;
+ virtual std::string const& GetInput() const = 0;
+ virtual bool GetHadContextSensitiveCondition() const { return false; }
+
cmLinkImplItem const& LinkImplItem;
};
cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem;
+class TargetPropertyEntryGenex : public cmGeneratorTarget::TargetPropertyEntry
+{
+public:
+ TargetPropertyEntryGenex(std::unique_ptr<cmCompiledGeneratorExpression> cge,
+ cmLinkImplItem const& item = NoLinkImplItem)
+ : cmGeneratorTarget::TargetPropertyEntry(item)
+ , ge(std::move(cge))
+ {
+ }
+
+ const std::string& Evaluate(cmLocalGenerator* lg, const std::string& config,
+ cmGeneratorTarget const* headTarget,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ std::string const& language) const override
+ {
+ return this->ge->Evaluate(lg, config, headTarget, dagChecker, nullptr,
+ language);
+ }
+
+ cmListFileBacktrace GetBacktrace() const override
+ {
+ return this->ge->GetBacktrace();
+ }
+
+ std::string const& GetInput() const override { return this->ge->GetInput(); }
+
+ bool GetHadContextSensitiveCondition() const override
+ {
+ return this->ge->GetHadContextSensitiveCondition();
+ }
+
+private:
+ const std::unique_ptr<cmCompiledGeneratorExpression> ge;
+};
+
+class TargetPropertyEntryString : public cmGeneratorTarget::TargetPropertyEntry
+{
+public:
+ TargetPropertyEntryString(std::string propertyValue,
+ cmListFileBacktrace backtrace,
+ cmLinkImplItem const& item = NoLinkImplItem)
+ : cmGeneratorTarget::TargetPropertyEntry(item)
+ , PropertyValue(std::move(propertyValue))
+ , Backtrace(std::move(backtrace))
+ {
+ }
+
+ const std::string& Evaluate(cmLocalGenerator*, const std::string&,
+ cmGeneratorTarget const*,
+ cmGeneratorExpressionDAGChecker*,
+ std::string const&) const override
+ {
+ return this->PropertyValue;
+ }
+
+ cmListFileBacktrace GetBacktrace() const override { return this->Backtrace; }
+ std::string const& GetInput() const override { return this->PropertyValue; }
+
+private:
+ std::string PropertyValue;
+ cmListFileBacktrace Backtrace;
+};
+
+cmGeneratorTarget::TargetPropertyEntry* CreateTargetPropertyEntry(
+ const std::string& propertyValue,
+ cmListFileBacktrace backtrace = cmListFileBacktrace(),
+ bool evaluateForBuildsystem = false)
+{
+ if (cmGeneratorExpression::Find(propertyValue) != std::string::npos) {
+ cmGeneratorExpression ge(std::move(backtrace));
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(propertyValue);
+ cge->SetEvaluateForBuildsystem(evaluateForBuildsystem);
+ return new TargetPropertyEntryGenex(std::move(cge));
+ }
+
+ return new TargetPropertyEntryString(propertyValue, std::move(backtrace));
+}
+
void CreatePropertyGeneratorExpressions(
cmStringRange entries, cmBacktraceRange backtraces,
std::vector<cmGeneratorTarget::TargetPropertyEntry*>& items,
bool evaluateForBuildsystem = false)
{
- std::vector<cmListFileBacktrace>::const_iterator btIt = backtraces.begin();
- for (std::vector<std::string>::const_iterator it = entries.begin();
- it != entries.end(); ++it, ++btIt) {
- cmGeneratorExpression ge(*btIt);
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(*it);
- cge->SetEvaluateForBuildsystem(evaluateForBuildsystem);
- items.push_back(new cmGeneratorTarget::TargetPropertyEntry(cge));
+ auto btIt = backtraces.begin();
+ for (auto it = entries.begin(); it != entries.end(); ++it, ++btIt) {
+ items.push_back(
+ CreateTargetPropertyEntry(*it, *btIt, evaluateForBuildsystem));
}
}
+namespace {
+// Represent a target property entry after evaluating generator expressions
+// and splitting up lists.
+struct EvaluatedTargetPropertyEntry
+{
+ EvaluatedTargetPropertyEntry(cmLinkImplItem const& item,
+ cmListFileBacktrace bt)
+ : LinkImplItem(item)
+ , Backtrace(std::move(bt))
+ {
+ }
+
+ // Move-only.
+ EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry&&) = default;
+ EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry const&) = delete;
+ EvaluatedTargetPropertyEntry& operator=(EvaluatedTargetPropertyEntry&&) =
+ delete;
+ EvaluatedTargetPropertyEntry& operator=(
+ EvaluatedTargetPropertyEntry const&) = delete;
+
+ cmLinkImplItem const& LinkImplItem;
+ cmListFileBacktrace Backtrace;
+ std::vector<std::string> Values;
+ bool ContextDependent = false;
+};
+
+EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry(
+ cmGeneratorTarget const* thisTarget, std::string const& config,
+ std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
+ cmGeneratorTarget::TargetPropertyEntry* entry)
+{
+ EvaluatedTargetPropertyEntry ee(entry->LinkImplItem, entry->GetBacktrace());
+ cmExpandList(entry->Evaluate(thisTarget->GetLocalGenerator(), config,
+ thisTarget, dagChecker, lang),
+ ee.Values);
+ if (entry->GetHadContextSensitiveCondition()) {
+ ee.ContextDependent = true;
+ }
+ return ee;
+}
+
+std::vector<EvaluatedTargetPropertyEntry> EvaluateTargetPropertyEntries(
+ cmGeneratorTarget const* thisTarget, std::string const& config,
+ std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*> const& in)
+{
+ std::vector<EvaluatedTargetPropertyEntry> out;
+ out.reserve(in.size());
+ for (cmGeneratorTarget::TargetPropertyEntry* entry : in) {
+ out.emplace_back(EvaluateTargetPropertyEntry(thisTarget, config, lang,
+ dagChecker, entry));
+ }
+ return out;
+}
+}
+
cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
: Target(t)
, FortranModuleDirectoryCreated(false)
@@ -100,6 +256,9 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
, DebugCompileOptionsDone(false)
, DebugCompileFeaturesDone(false)
, DebugCompileDefinitionsDone(false)
+ , DebugLinkOptionsDone(false)
+ , DebugLinkDirectoriesDone(false)
+ , DebugPrecompileHeadersDone(false)
, DebugSourcesDone(false)
, LinkImplementationLanguageIsContextDependent(true)
, UtilityItemsDone(false)
@@ -126,15 +285,23 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
t->GetCompileDefinitionsBacktraces(),
this->CompileDefinitionsEntries);
+ CreatePropertyGeneratorExpressions(t->GetLinkOptionsEntries(),
+ t->GetLinkOptionsBacktraces(),
+ this->LinkOptionsEntries);
+
+ CreatePropertyGeneratorExpressions(t->GetLinkDirectoriesEntries(),
+ t->GetLinkDirectoriesBacktraces(),
+ this->LinkDirectoriesEntries);
+
+ CreatePropertyGeneratorExpressions(t->GetPrecompileHeadersEntries(),
+ t->GetPrecompileHeadersBacktraces(),
+ this->PrecompileHeadersEntries);
+
CreatePropertyGeneratorExpressions(t->GetSourceEntries(),
t->GetSourceBacktraces(),
this->SourceEntries, true);
- this->DLLPlatform =
- (this->Makefile->IsOn("WIN32") || this->Makefile->IsOn("CYGWIN") ||
- this->Makefile->IsOn("MINGW"));
-
- this->PolicyMap = t->PolicyMap;
+ this->PolicyMap = t->GetPolicyMap();
}
cmGeneratorTarget::~cmGeneratorTarget()
@@ -143,6 +310,9 @@ cmGeneratorTarget::~cmGeneratorTarget()
cmDeleteAll(this->CompileOptionsEntries);
cmDeleteAll(this->CompileFeaturesEntries);
cmDeleteAll(this->CompileDefinitionsEntries);
+ cmDeleteAll(this->LinkOptionsEntries);
+ cmDeleteAll(this->LinkDirectoriesEntries);
+ cmDeleteAll(this->PrecompileHeadersEntries);
cmDeleteAll(this->SourceEntries);
cmDeleteAll(this->LinkInformation);
}
@@ -150,11 +320,8 @@ cmGeneratorTarget::~cmGeneratorTarget()
const char* cmGeneratorTarget::GetSourcesProperty() const
{
std::vector<std::string> values;
- for (std::vector<cmGeneratorTarget::TargetPropertyEntry *>::const_iterator
- it = this->SourceEntries.begin(),
- end = this->SourceEntries.end();
- it != end; ++it) {
- values.push_back((*it)->ge->GetInput());
+ for (TargetPropertyEntry* se : this->SourceEntries) {
+ values.push_back(se->GetInput());
}
static std::string value;
value.clear();
@@ -191,7 +358,7 @@ std::string cmGeneratorTarget::GetExportName() const
std::ostringstream e;
e << "EXPORT_NAME property \"" << exportName << "\" for \""
<< this->GetName() << "\": is not valid.";
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
return "";
}
return exportName;
@@ -204,18 +371,27 @@ const char* cmGeneratorTarget::GetProperty(const std::string& prop) const
if (!cmTargetPropertyComputer::PassesWhitelist(
this->GetType(), prop, this->Makefile->GetMessenger(),
this->GetBacktrace())) {
- return CM_NULLPTR;
+ return nullptr;
}
if (const char* result = cmTargetPropertyComputer::GetProperty(
this, prop, this->Makefile->GetMessenger(), this->GetBacktrace())) {
return result;
}
if (cmSystemTools::GetFatalErrorOccured()) {
- return CM_NULLPTR;
+ return nullptr;
}
return this->Target->GetProperty(prop);
}
+const char* cmGeneratorTarget::GetSafeProperty(const std::string& prop) const
+{
+ const char* ret = this->GetProperty(prop);
+ if (!ret) {
+ return "";
+ }
+ return ret;
+}
+
const char* cmGeneratorTarget::GetOutputTargetType(
cmStateEnums::ArtifactType artifact) const
{
@@ -242,13 +418,16 @@ const char* cmGeneratorTarget::GetOutputTargetType(
case cmStateEnums::MODULE_LIBRARY:
switch (artifact) {
case cmStateEnums::RuntimeBinaryArtifact:
- // Module import libraries are treated as archive targets.
+ // Module libraries are always treated as library targets.
return "LIBRARY";
case cmStateEnums::ImportLibraryArtifact:
- // Module libraries are always treated as library targets.
+ // Module import libraries are treated as archive targets.
return "ARCHIVE";
}
break;
+ case cmStateEnums::OBJECT_LIBRARY:
+ // Object libraries are always treated as object targets.
+ return "OBJECT";
case cmStateEnums::EXECUTABLE:
switch (artifact) {
case cmStateEnums::RuntimeBinaryArtifact:
@@ -270,8 +449,7 @@ std::string cmGeneratorTarget::GetOutputName(
{
// Lookup/compute/cache the output name for this configuration.
OutputNameKey key(config, artifact);
- cmGeneratorTarget::OutputNameMapType::iterator i =
- this->OutputNameMap.find(key);
+ auto i = this->OutputNameMap.find(key);
if (i == this->OutputNameMap.end()) {
// Add empty name in map to detect potential recursion.
OutputNameMapType::value_type entry(key, "");
@@ -296,12 +474,11 @@ std::string cmGeneratorTarget::GetOutputName(
props.push_back(configUpper + "_OUTPUT_NAME");
}
// OUTPUT_NAME
- props.push_back("OUTPUT_NAME");
+ props.emplace_back("OUTPUT_NAME");
std::string outName;
- for (std::vector<std::string>::const_iterator it = props.begin();
- it != props.end(); ++it) {
- if (const char* outNameProp = this->GetProperty(*it)) {
+ for (std::string const& p : props) {
+ if (const char* outNameProp = this->GetProperty(p)) {
outName = outNameProp;
break;
}
@@ -312,35 +489,186 @@ std::string cmGeneratorTarget::GetOutputName(
}
// Now evaluate genex and update the previously-prepared map entry.
- cmGeneratorExpression ge;
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(outName);
- i->second = cge->Evaluate(this->LocalGenerator, config);
+ i->second =
+ cmGeneratorExpression::Evaluate(outName, this->LocalGenerator, config);
} else if (i->second.empty()) {
// An empty map entry indicates we have been called recursively
// from the above block.
this->LocalGenerator->GetCMakeInstance()->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"Target '" + this->GetName() + "' OUTPUT_NAME depends on itself.",
this->GetBacktrace());
}
return i->second;
}
-void cmGeneratorTarget::AddSourceCommon(const std::string& src)
+std::string cmGeneratorTarget::GetFilePrefix(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
+{
+ if (this->IsImported()) {
+ const char* prefix = this->GetFilePrefixInternal(config, artifact);
+
+ return prefix ? prefix : std::string();
+ }
+
+ std::string prefix;
+ std::string suffix;
+ std::string base;
+ this->GetFullNameInternal(config, artifact, prefix, base, suffix);
+ return prefix;
+}
+std::string cmGeneratorTarget::GetFileSuffix(
+ const std::string& config, cmStateEnums::ArtifactType artifact) const
+{
+ if (this->IsImported()) {
+ const char* suffix = this->GetFileSuffixInternal(config, artifact);
+
+ return suffix ? suffix : std::string();
+ }
+
+ std::string prefix;
+ std::string suffix;
+ std::string base;
+ this->GetFullNameInternal(config, artifact, prefix, base, suffix);
+ return suffix;
+}
+
+std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const
+{
+ const char* postfix = nullptr;
+ if (!config.empty()) {
+ std::string configProp =
+ cmStrCat(cmSystemTools::UpperCase(config), "_POSTFIX");
+ postfix = this->GetProperty(configProp);
+ // Mac application bundles and frameworks have no postfix.
+ if (!this->IsImported() && postfix &&
+ (this->IsAppBundleOnApple() || this->IsFrameworkOnApple())) {
+ postfix = nullptr;
+ }
+ }
+ return postfix ? postfix : std::string();
+}
+
+const char* cmGeneratorTarget::GetFilePrefixInternal(
+ std::string const& config, cmStateEnums::ArtifactType artifact,
+ const std::string& language) const
+{
+ // no prefix for non-main target types.
+ if (this->GetType() != cmStateEnums::STATIC_LIBRARY &&
+ this->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ this->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ this->GetType() != cmStateEnums::EXECUTABLE) {
+ return nullptr;
+ }
+
+ const bool isImportedLibraryArtifact =
+ (artifact == cmStateEnums::ImportLibraryArtifact);
+
+ // Return an empty prefix for the import library if this platform
+ // does not support import libraries.
+ if (isImportedLibraryArtifact && !this->NeedImportLibraryName(config)) {
+ return nullptr;
+ }
+
+ // The implib option is only allowed for shared libraries, module
+ // libraries, and executables.
+ if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ this->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ this->GetType() != cmStateEnums::EXECUTABLE) {
+ artifact = cmStateEnums::RuntimeBinaryArtifact;
+ }
+
+ // Compute prefix value.
+ const char* targetPrefix =
+ (isImportedLibraryArtifact ? this->GetProperty("IMPORT_PREFIX")
+ : this->GetProperty("PREFIX"));
+
+ if (!targetPrefix) {
+ const char* prefixVar = this->Target->GetPrefixVariableInternal(artifact);
+ if (!language.empty() && prefixVar && *prefixVar) {
+ std::string langPrefix = prefixVar + std::string("_") + language;
+ targetPrefix = this->Makefile->GetDefinition(langPrefix);
+ }
+
+ // if there is no prefix on the target nor specific language
+ // use the cmake definition.
+ if (!targetPrefix && prefixVar) {
+ targetPrefix = this->Makefile->GetDefinition(prefixVar);
+ }
+ }
+
+ return targetPrefix;
+}
+const char* cmGeneratorTarget::GetFileSuffixInternal(
+ std::string const& config, cmStateEnums::ArtifactType artifact,
+ const std::string& language) const
+{
+ // no suffix for non-main target types.
+ if (this->GetType() != cmStateEnums::STATIC_LIBRARY &&
+ this->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ this->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ this->GetType() != cmStateEnums::EXECUTABLE) {
+ return nullptr;
+ }
+
+ const bool isImportedLibraryArtifact =
+ (artifact == cmStateEnums::ImportLibraryArtifact);
+
+ // Return an empty suffix for the import library if this platform
+ // does not support import libraries.
+ if (isImportedLibraryArtifact && !this->NeedImportLibraryName(config)) {
+ return nullptr;
+ }
+
+ // The implib option is only allowed for shared libraries, module
+ // libraries, and executables.
+ if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ this->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ this->GetType() != cmStateEnums::EXECUTABLE) {
+ artifact = cmStateEnums::RuntimeBinaryArtifact;
+ }
+
+ // Compute suffix value.
+ const char* targetSuffix =
+ (isImportedLibraryArtifact ? this->GetProperty("IMPORT_SUFFIX")
+ : this->GetProperty("SUFFIX"));
+
+ if (!targetSuffix) {
+ const char* suffixVar = this->Target->GetSuffixVariableInternal(artifact);
+ if (!language.empty() && suffixVar && *suffixVar) {
+ std::string langSuffix = suffixVar + std::string("_") + language;
+ targetSuffix = this->Makefile->GetDefinition(langSuffix);
+ }
+
+ // if there is no suffix on the target nor specific language
+ // use the cmake definition.
+ if (!targetSuffix && suffixVar) {
+ targetSuffix = this->Makefile->GetDefinition(suffixVar);
+ }
+ }
+
+ return targetSuffix;
+}
+
+void cmGeneratorTarget::ClearSourcesCache()
{
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- cmGeneratorExpression ge(lfbt);
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(src);
- cge->SetEvaluateForBuildsystem(true);
- this->SourceEntries.push_back(new TargetPropertyEntry(cge));
this->KindedSourcesMap.clear();
this->LinkImplementationLanguageIsContextDependent = true;
+ this->Objects.clear();
+}
+
+void cmGeneratorTarget::AddSourceCommon(const std::string& src, bool before)
+{
+ this->SourceEntries.insert(
+ before ? this->SourceEntries.begin() : this->SourceEntries.end(),
+ CreateTargetPropertyEntry(src, this->Makefile->GetBacktrace(), true));
+ this->ClearSourcesCache();
}
-void cmGeneratorTarget::AddSource(const std::string& src)
+void cmGeneratorTarget::AddSource(const std::string& src, bool before)
{
- this->Target->AddSource(src);
- this->AddSourceCommon(src);
+ this->Target->AddSource(src, before);
+ this->AddSourceCommon(src, before);
}
void cmGeneratorTarget::AddTracedSources(std::vector<std::string> const& srcs)
@@ -355,40 +683,36 @@ void cmGeneratorTarget::AddIncludeDirectory(const std::string& src,
bool before)
{
this->Target->InsertInclude(src, this->Makefile->GetBacktrace(), before);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- cmGeneratorExpression ge(lfbt);
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(src);
- cge->SetEvaluateForBuildsystem(true);
- // Insert before begin/end
- std::vector<TargetPropertyEntry*>::iterator pos = before
- ? this->IncludeDirectoriesEntries.begin()
- : this->IncludeDirectoriesEntries.end();
- this->IncludeDirectoriesEntries.insert(pos, new TargetPropertyEntry(cge));
+ this->IncludeDirectoriesEntries.insert(
+ before ? this->IncludeDirectoriesEntries.begin()
+ : this->IncludeDirectoriesEntries.end(),
+ CreateTargetPropertyEntry(src, this->Makefile->GetBacktrace(), true));
}
std::vector<cmSourceFile*> const* cmGeneratorTarget::GetSourceDepends(
cmSourceFile const* sf) const
{
- SourceEntriesType::const_iterator i = this->SourceDepends.find(sf);
+ auto i = this->SourceDepends.find(sf);
if (i != this->SourceDepends.end()) {
return &i->second.Depends;
}
- return CM_NULLPTR;
+ return nullptr;
}
-static void handleSystemIncludesDep(
- cmLocalGenerator* lg, cmGeneratorTarget const* depTgt,
- const std::string& config, cmGeneratorTarget const* headTarget,
- cmGeneratorExpressionDAGChecker* dagChecker,
- std::vector<std::string>& result, bool excludeImported)
+namespace {
+void handleSystemIncludesDep(cmLocalGenerator* lg,
+ cmGeneratorTarget const* depTgt,
+ const std::string& config,
+ cmGeneratorTarget const* headTarget,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ 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),
- result);
+ cmExpandList(cmGeneratorExpression::Evaluate(dirs, lg, config, headTarget,
+ dagChecker, depTgt, language),
+ result);
}
if (!depTgt->IsImported() || excludeImported) {
return;
@@ -396,25 +720,23 @@ static void handleSystemIncludesDep(
if (const char* dirs =
depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) {
- cmGeneratorExpression ge;
- cmSystemTools::ExpandListArgument(
- ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, depTgt,
- dagChecker),
- result);
+ cmExpandList(cmGeneratorExpression::Evaluate(dirs, lg, config, headTarget,
+ dagChecker, depTgt, language),
+ result);
}
}
+}
/* clang-format off */
#define IMPLEMENT_VISIT(KIND) \
- { \
+ do { \
KindedSources const& kinded = this->GetKindedSources(config); \
- for (std::vector<SourceAndKind>::const_iterator \
- si = kinded.Sources.begin(); si != kinded.Sources.end(); ++si) { \
- if (si->Kind == KIND) { \
- data.push_back(si->Source); \
+ for (SourceAndKind const& s : kinded.Sources) { \
+ if (s.Kind == KIND) { \
+ data.push_back(s.Source.Value); \
} \
} \
- }
+ } while (false)
/* clang-format on */
void cmGeneratorTarget::GetObjectSources(
@@ -426,9 +748,8 @@ void cmGeneratorTarget::GetObjectSources(
return;
}
- for (std::vector<cmSourceFile const*>::const_iterator it = data.begin();
- it != data.end(); ++it) {
- this->Objects[*it];
+ for (cmSourceFile const* it : data) {
+ this->Objects[it];
}
this->LocalGenerator->ComputeObjectFilenames(this->Objects, this);
@@ -440,15 +761,11 @@ void cmGeneratorTarget::ComputeObjectMapping()
return;
}
- std::vector<std::string> configs;
- this->Makefile->GetConfigurations(configs);
- if (configs.empty()) {
- configs.push_back("");
- }
- for (std::vector<std::string>::const_iterator ci = configs.begin();
- ci != configs.end(); ++ci) {
+ std::vector<std::string> const& configs =
+ this->Makefile->GetGeneratorConfigs();
+ for (std::string const& c : configs) {
std::vector<cmSourceFile const*> sourceFiles;
- this->GetObjectSources(sourceFiles, *ci);
+ this->GetObjectSources(sourceFiles, c);
}
}
@@ -456,9 +773,8 @@ const char* cmGeneratorTarget::GetFeature(const std::string& feature,
const std::string& config) const
{
if (!config.empty()) {
- std::string featureConfig = feature;
- featureConfig += "_";
- featureConfig += cmSystemTools::UpperCase(config);
+ std::string featureConfig =
+ cmStrCat(feature, '_', cmSystemTools::UpperCase(config));
if (const char* value = this->GetProperty(featureConfig)) {
return value;
}
@@ -469,11 +785,30 @@ const char* cmGeneratorTarget::GetFeature(const std::string& feature,
return this->LocalGenerator->GetFeature(feature, config);
}
+const char* cmGeneratorTarget::GetLinkPIEProperty(
+ const std::string& config) const
+{
+ static std::string PICValue;
+
+ PICValue = this->GetLinkInterfaceDependentStringAsBoolProperty(
+ "POSITION_INDEPENDENT_CODE", config);
+
+ if (PICValue == "(unset)") {
+ // POSITION_INDEPENDENT_CODE is not set
+ return nullptr;
+ }
+
+ auto status = this->GetPolicyStatusCMP0083();
+ return (status != cmPolicies::WARN && status != cmPolicies::OLD)
+ ? PICValue.c_str()
+ : nullptr;
+}
+
bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang,
std::string const& config) const
{
const char* feature = "INTERPROCEDURAL_OPTIMIZATION";
- const bool result = cmSystemTools::IsOn(this->GetFeature(feature, config));
+ const bool result = cmIsOn(this->GetFeature(feature, config));
if (!result) {
// 'INTERPROCEDURAL_OPTIMIZATION' is off, no need to check policies
@@ -503,7 +838,7 @@ bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang,
w << "INTERPROCEDURAL_OPTIMIZATION property will be ignored for target "
<< "'" << this->GetName() << "'.";
this->LocalGenerator->GetCMakeInstance()->IssueMessage(
- cmake::AUTHOR_WARNING, w.str(), this->GetBacktrace());
+ MessageType::AUTHOR_WARNING, w.str(), this->GetBacktrace());
this->PolicyReportedCMP0069 = true;
}
@@ -511,7 +846,7 @@ bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang,
}
// Note: check consistency with messages from CheckIPOSupported
- const char* message = CM_NULLPTR;
+ const char* message = nullptr;
if (!this->Makefile->IsOn("_CMAKE_" + lang + "_IPO_SUPPORTED_BY_CMAKE")) {
message = "CMake doesn't support IPO for current compiler";
} else if (!this->Makefile->IsOn("_CMAKE_" + lang +
@@ -534,7 +869,7 @@ bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang,
this->PolicyReportedCMP0069 = true;
this->LocalGenerator->GetCMakeInstance()->IssueMessage(
- cmake::FATAL_ERROR, message, this->GetBacktrace());
+ MessageType::FATAL_ERROR, message, this->GetBacktrace());
return false;
}
@@ -553,7 +888,7 @@ const char* cmGeneratorTarget::GetCustomObjectExtension() const
extension = ".ptx";
return extension.c_str();
}
- return CM_NULLPTR;
+ return nullptr;
}
void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf)
@@ -564,8 +899,7 @@ void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf)
bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
{
const_cast<cmGeneratorTarget*>(this)->ComputeObjectMapping();
- std::set<cmSourceFile const*>::const_iterator it =
- this->ExplicitObjectName.find(file);
+ auto it = this->ExplicitObjectName.find(file);
return it != this->ExplicitObjectName.end();
}
@@ -648,12 +982,14 @@ std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const
{
if (!this->UtilityItemsDone) {
this->UtilityItemsDone = true;
- std::set<std::string> const& utilities = this->GetUtilities();
- for (std::set<std::string>::const_iterator i = utilities.begin();
- i != utilities.end(); ++i) {
- cmGeneratorTarget* gt =
- this->LocalGenerator->FindGeneratorTargetToUse(*i);
- this->UtilityItems.insert(cmLinkItem(*i, gt));
+ std::set<BT<std::string>> const& utilities = this->GetUtilities();
+ for (BT<std::string> const& i : utilities) {
+ if (cmGeneratorTarget* gt =
+ this->LocalGenerator->FindGeneratorTargetToUse(i.Value)) {
+ this->UtilityItems.insert(cmLinkItem(gt, i.Backtrace));
+ } else {
+ this->UtilityItems.insert(cmLinkItem(i.Value, i.Backtrace));
+ }
}
}
return this->UtilityItems;
@@ -735,7 +1071,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;
@@ -743,35 +1080,28 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(
config_upper = cmSystemTools::UpperCase(config);
}
- typedef std::map<std::string, std::vector<std::string> > IncludeCacheType;
- IncludeCacheType::const_iterator iter =
- this->SystemIncludesCache.find(config_upper);
+ using IncludeCacheType = std::map<std::string, std::vector<std::string>>;
+ auto iter = this->SystemIncludesCache.find(config_upper);
if (iter == this->SystemIncludesCache.end()) {
cmGeneratorExpressionDAGChecker dagChecker(
- this->GetName(), "SYSTEM_INCLUDE_DIRECTORIES", CM_NULLPTR, CM_NULLPTR);
+ this, "SYSTEM_INCLUDE_DIRECTORIES", nullptr, nullptr);
bool excludeImported = this->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED");
std::vector<std::string> result;
- for (std::set<std::string>::const_iterator it =
- this->Target->GetSystemIncludeDirectories().begin();
- it != this->Target->GetSystemIncludeDirectories().end(); ++it) {
- cmGeneratorExpression ge;
- cmSystemTools::ExpandListArgument(
- ge.Parse(*it)->Evaluate(this->LocalGenerator, config, false, this,
- &dagChecker),
- result);
+ for (std::string const& it : this->Target->GetSystemIncludeDirectories()) {
+ cmExpandList(cmGeneratorExpression::Evaluate(it, this->LocalGenerator,
+ config, this, &dagChecker,
+ nullptr, language),
+ result);
}
std::vector<cmGeneratorTarget const*> const& deps =
this->GetLinkImplementationClosure(config);
- for (std::vector<cmGeneratorTarget const *>::const_iterator
- li = deps.begin(),
- le = deps.end();
- li != le; ++li) {
- handleSystemIncludesDep(this->LocalGenerator, *li, config, this,
- &dagChecker, result, excludeImported);
+ for (cmGeneratorTarget const* dep : deps) {
+ handleSystemIncludesDep(this->LocalGenerator, dep, config, this,
+ &dagChecker, result, excludeImported, language);
}
std::for_each(result.begin(), result.end(),
@@ -791,95 +1121,235 @@ bool cmGeneratorTarget::GetPropertyAsBool(const std::string& prop) const
return this->Target->GetPropertyAsBool(prop);
}
-static void AddInterfaceEntries(
- cmGeneratorTarget const* thisTarget, std::string const& config,
- std::string const& prop,
- std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries)
+bool cmGeneratorTarget::MaybeHaveInterfaceProperty(
+ std::string const& prop, cmGeneratorExpressionContext* context) const
+{
+ std::string const key = prop + '@' + context->Config;
+ auto i = this->MaybeInterfacePropertyExists.find(key);
+ if (i == this->MaybeInterfacePropertyExists.end()) {
+ // Insert an entry now in case there is a cycle.
+ i = this->MaybeInterfacePropertyExists.emplace(key, false).first;
+ bool& maybeInterfaceProp = i->second;
+
+ // If this target itself has a non-empty property value, we are done.
+ const char* p = this->GetProperty(prop);
+ maybeInterfaceProp = p && *p;
+
+ // Otherwise, recurse to interface dependencies.
+ if (!maybeInterfaceProp) {
+ cmGeneratorTarget const* headTarget =
+ context->HeadTarget ? context->HeadTarget : this;
+ if (cmLinkInterfaceLibraries const* iface =
+ this->GetLinkInterfaceLibraries(context->Config, headTarget,
+ true)) {
+ if (iface->HadHeadSensitiveCondition) {
+ // With a different head target we may get to a library with
+ // this interface property.
+ maybeInterfaceProp = true;
+ } else {
+ // The transitive interface libraries do not depend on the
+ // head target, so we can follow them.
+ for (cmLinkItem const& lib : iface->Libraries) {
+ if (lib.Target &&
+ lib.Target->MaybeHaveInterfaceProperty(prop, context)) {
+ maybeInterfaceProp = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ return i->second;
+}
+
+std::string cmGeneratorTarget::EvaluateInterfaceProperty(
+ std::string const& prop, cmGeneratorExpressionContext* context,
+ cmGeneratorExpressionDAGChecker* dagCheckerParent) const
+{
+ std::string result;
+
+ // If the property does not appear transitively at all, we are done.
+ if (!this->MaybeHaveInterfaceProperty(prop, context)) {
+ return result;
+ }
+
+ // Evaluate $<TARGET_PROPERTY:this,prop> as if it were compiled. This is
+ // a subset of TargetPropertyNode::Evaluate without stringify/parse steps
+ // but sufficient for transitive interface properties.
+ cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, this, prop,
+ nullptr, dagCheckerParent);
+ switch (dagChecker.Check()) {
+ case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
+ dagChecker.ReportError(
+ context, "$<TARGET_PROPERTY:" + this->GetName() + "," + prop + ">");
+ return result;
+ case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
+ // No error. We just skip cyclic references.
+ return result;
+ case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
+ // No error. We have already seen this transitive property.
+ return result;
+ case cmGeneratorExpressionDAGChecker::DAG:
+ break;
+ }
+
+ cmGeneratorTarget const* headTarget =
+ context->HeadTarget ? context->HeadTarget : this;
+
+ if (const char* p = this->GetProperty(prop)) {
+ result = cmGeneratorExpressionNode::EvaluateDependentExpression(
+ p, context->LG, context, headTarget, &dagChecker, this);
+ }
+
+ if (cmLinkInterfaceLibraries const* iface =
+ this->GetLinkInterfaceLibraries(context->Config, headTarget, true)) {
+ for (cmLinkItem const& lib : iface->Libraries) {
+ // Broken code can have a target in its own link interface.
+ // Don't follow such link interface entries so as not to create a
+ // self-referencing loop.
+ if (lib.Target && lib.Target != this) {
+ // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in the
+ // above property and hand-evaluate it as if it were compiled.
+ // Create a context as cmCompiledGeneratorExpression::Evaluate does.
+ cmGeneratorExpressionContext libContext(
+ context->LG, context->Config, context->Quiet, headTarget, this,
+ context->EvaluateForBuildsystem, context->Backtrace,
+ context->Language);
+ std::string libResult = cmGeneratorExpression::StripEmptyListElements(
+ lib.Target->EvaluateInterfaceProperty(prop, &libContext,
+ &dagChecker));
+ if (!libResult.empty()) {
+ if (result.empty()) {
+ result = std::move(libResult);
+ } else {
+ result.reserve(result.size() + 1 + libResult.size());
+ result += ";";
+ result += libResult;
+ }
+ }
+ context->HadContextSensitiveCondition =
+ context->HadContextSensitiveCondition ||
+ libContext.HadContextSensitiveCondition;
+ context->HadHeadSensitiveCondition =
+ context->HadHeadSensitiveCondition ||
+ libContext.HadHeadSensitiveCondition;
+ }
+ }
+ }
+
+ return result;
+}
+
+namespace {
+void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
+ std::string const& config, std::string const& prop,
+ std::string const& lang,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ std::vector<EvaluatedTargetPropertyEntry>& entries)
+{
+ if (cmLinkImplementationLibraries const* impl =
+ headTarget->GetLinkImplementationLibraries(config)) {
+ for (cmLinkImplItem const& lib : impl->Libraries) {
+ if (lib.Target) {
+ EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
+ // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our
+ // caller's property and hand-evaluate it as if it were compiled.
+ // Create a context as cmCompiledGeneratorExpression::Evaluate does.
+ cmGeneratorExpressionContext context(
+ headTarget->GetLocalGenerator(), config, false, headTarget,
+ headTarget, true, lib.Backtrace, lang);
+ cmExpandList(
+ lib.Target->EvaluateInterfaceProperty(prop, &context, dagChecker),
+ ee.Values);
+ ee.ContextDependent = context.HadContextSensitiveCondition;
+ entries.emplace_back(std::move(ee));
+ }
+ }
+ }
+}
+
+void AddObjectEntries(cmGeneratorTarget const* headTarget,
+ std::string const& config,
+ cmGeneratorExpressionDAGChecker* dagChecker,
+ std::vector<EvaluatedTargetPropertyEntry>& entries)
{
if (cmLinkImplementationLibraries const* impl =
- thisTarget->GetLinkImplementationLibraries(config)) {
- for (std::vector<cmLinkImplItem>::const_iterator
- it = impl->Libraries.begin(),
- end = impl->Libraries.end();
- it != end; ++it) {
- if (it->Target) {
- std::string genex = "$<TARGET_PROPERTY:" + *it + "," + prop + ">";
- cmGeneratorExpression ge(it->Backtrace);
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
+ headTarget->GetLinkImplementationLibraries(config)) {
+ for (cmLinkImplItem const& lib : impl->Libraries) {
+ if (lib.Target &&
+ lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ std::string uniqueName =
+ headTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely(
+ lib.Target);
+ std::string genex = "$<TARGET_OBJECTS:" + std::move(uniqueName) + ">";
+ cmGeneratorExpression ge(lib.Backtrace);
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
cge->SetEvaluateForBuildsystem(true);
- entries.push_back(
- new cmGeneratorTarget::TargetPropertyEntry(cge, *it));
+
+ EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
+ cmExpandList(cge->Evaluate(headTarget->GetLocalGenerator(), config,
+ headTarget, dagChecker),
+ ee.Values);
+ if (cge->GetHadContextSensitiveCondition()) {
+ ee.ContextDependent = true;
+ }
+ entries.emplace_back(std::move(ee));
}
}
}
}
-static bool processSources(
- cmGeneratorTarget const* tgt,
- const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
- std::vector<std::string>& srcs, CM_UNORDERED_SET<std::string>& uniqueSrcs,
- cmGeneratorExpressionDAGChecker* dagChecker, std::string const& config,
- bool debugSources)
+bool processSources(cmGeneratorTarget const* tgt,
+ std::vector<EvaluatedTargetPropertyEntry>& entries,
+ std::vector<BT<std::string>>& srcs,
+ std::unordered_set<std::string>& uniqueSrcs,
+ bool debugSources)
{
cmMakefile* mf = tgt->Target->GetMakefile();
bool contextDependent = false;
- for (std::vector<cmGeneratorTarget::TargetPropertyEntry *>::const_iterator
- it = entries.begin(),
- end = entries.end();
- it != end; ++it) {
- cmLinkImplItem const& item = (*it)->LinkImplItem;
- std::string const& targetName = item;
- std::vector<std::string> entrySources;
- cmSystemTools::ExpandListArgument(
- (*it)->ge->Evaluate(tgt->GetLocalGenerator(), config, false, tgt, tgt,
- dagChecker),
- entrySources);
-
- if ((*it)->ge->GetHadContextSensitiveCondition()) {
+ for (EvaluatedTargetPropertyEntry& entry : entries) {
+ if (entry.ContextDependent) {
contextDependent = true;
}
- for (std::vector<std::string>::iterator i = entrySources.begin();
- i != entrySources.end(); ++i) {
- std::string& src = *i;
+ cmLinkImplItem const& item = entry.LinkImplItem;
+ std::string const& targetName = item.AsStr();
+
+ for (std::string& src : entry.Values) {
cmSourceFile* sf = mf->GetOrCreateSource(src);
std::string e;
- std::string fullPath = sf->GetFullPath(&e);
+ std::string fullPath = sf->ResolveFullPath(&e);
if (fullPath.empty()) {
if (!e.empty()) {
cmake* cm = tgt->GetLocalGenerator()->GetCMakeInstance();
- cm->IssueMessage(cmake::FATAL_ERROR, e, tgt->GetBacktrace());
+ cm->IssueMessage(MessageType::FATAL_ERROR, e, tgt->GetBacktrace());
}
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
- << "\" contains relative "
- "path in its INTERFACE_SOURCES:\n"
- " \""
+ << "\" contains relative path in its INTERFACE_SOURCES:\n \""
<< src << "\"";
} else {
- err << "Found relative path while evaluating sources of "
- "\""
+ err << "Found relative path while evaluating sources of \""
<< tgt->GetName() << "\":\n \"" << src << "\"\n";
}
- tgt->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, err.str());
+ tgt->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
+ err.str());
return contextDependent;
}
src = fullPath;
}
std::string usedSources;
- for (std::vector<std::string>::iterator li = entrySources.begin();
- li != entrySources.end(); ++li) {
- std::string src = *li;
-
+ for (std::string const& src : entry.Values) {
if (uniqueSrcs.insert(src).second) {
- srcs.push_back(src);
+ srcs.emplace_back(src, entry.Backtrace);
if (debugSources) {
usedSources += " * " + src + "\n";
}
@@ -887,17 +1357,20 @@ static bool processSources(
}
if (!usedSources.empty()) {
tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
- cmake::LOG, std::string("Used sources for target ") + tgt->GetName() +
- ":\n" + usedSources,
- (*it)->ge->GetBacktrace());
+ MessageType::LOG,
+ std::string("Used sources for target ") + tgt->GetName() + ":\n" +
+ usedSources,
+ entry.Backtrace);
}
}
return contextDependent;
}
+}
-void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files,
- const std::string& config) const
+std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
+ std::string const& config) const
{
+ std::vector<BT<std::string>> files;
assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
if (!this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) {
@@ -908,69 +1381,85 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files,
// behavior of CMP0024 and CMP0026 only.
cmStringRange sourceEntries = this->Target->GetSourceEntries();
- for (cmStringRange::const_iterator i = sourceEntries.begin();
- i != sourceEntries.end(); ++i) {
- std::string const& entry = *i;
-
- std::vector<std::string> items;
- cmSystemTools::ExpandListArgument(entry, items);
- for (std::vector<std::string>::const_iterator li = items.begin();
- li != items.end(); ++li) {
- if (cmHasLiteralPrefix(*li, "$<TARGET_OBJECTS:") &&
- (*li)[li->size() - 1] == '>') {
+ for (std::string const& entry : sourceEntries) {
+ std::vector<std::string> items = cmExpandedList(entry);
+ for (std::string const& item : items) {
+ if (cmHasLiteralPrefix(item, "$<TARGET_OBJECTS:") &&
+ item.back() == '>') {
continue;
}
- files.push_back(*li);
+ files.emplace_back(item);
}
}
- return;
+ return files;
}
std::vector<std::string> debugProperties;
const char* debugProp =
this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
if (debugProp) {
- cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+ cmExpandList(debugProp, debugProperties);
}
- bool debugSources = !this->DebugSourcesDone &&
- std::find(debugProperties.begin(), debugProperties.end(), "SOURCES") !=
- debugProperties.end();
+ bool debugSources =
+ !this->DebugSourcesDone && cmContains(debugProperties, "SOURCES");
if (this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) {
this->DebugSourcesDone = true;
}
- cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), "SOURCES",
- CM_NULLPTR, CM_NULLPTR);
-
- CM_UNORDERED_SET<std::string> uniqueSrcs;
- bool contextDependentDirectSources =
- processSources(this, this->SourceEntries, files, uniqueSrcs, &dagChecker,
- config, debugSources);
+ cmGeneratorExpressionDAGChecker dagChecker(this, "SOURCES", nullptr,
+ nullptr);
- std::vector<cmGeneratorTarget::TargetPropertyEntry*>
- linkInterfaceSourcesEntries;
+ std::vector<EvaluatedTargetPropertyEntry> entries =
+ EvaluateTargetPropertyEntries(this, config, std::string(), &dagChecker,
+ this->SourceEntries);
- AddInterfaceEntries(this, config, "INTERFACE_SOURCES",
- linkInterfaceSourcesEntries);
+ std::unordered_set<std::string> uniqueSrcs;
+ bool contextDependentDirectSources =
+ processSources(this, entries, files, uniqueSrcs, debugSources);
+ // Collect INTERFACE_SOURCES of all direct link-dependencies.
+ std::vector<EvaluatedTargetPropertyEntry> linkInterfaceSourcesEntries;
+ AddInterfaceEntries(this, config, "INTERFACE_SOURCES", std::string(),
+ &dagChecker, linkInterfaceSourcesEntries);
std::vector<std::string>::size_type numFilesBefore = files.size();
- bool contextDependentInterfaceSources =
- processSources(this, linkInterfaceSourcesEntries, files, uniqueSrcs,
- &dagChecker, config, debugSources);
+ bool contextDependentInterfaceSources = processSources(
+ this, linkInterfaceSourcesEntries, files, uniqueSrcs, debugSources);
+
+ // Collect TARGET_OBJECTS of direct object link-dependencies.
+ bool contextDependentObjects = false;
+ std::vector<std::string>::size_type numFilesBefore2 = files.size();
+ if (this->GetType() != cmStateEnums::OBJECT_LIBRARY) {
+ std::vector<EvaluatedTargetPropertyEntry> linkObjectsEntries;
+ AddObjectEntries(this, config, &dagChecker, linkObjectsEntries);
+ contextDependentObjects = processSources(this, linkObjectsEntries, files,
+ uniqueSrcs, debugSources);
+ }
if (!contextDependentDirectSources &&
- !(contextDependentInterfaceSources && numFilesBefore < files.size())) {
+ !(contextDependentInterfaceSources && numFilesBefore < files.size()) &&
+ !(contextDependentObjects && numFilesBefore2 < files.size())) {
this->LinkImplementationLanguageIsContextDependent = false;
}
- cmDeleteAll(linkInterfaceSourcesEntries);
+ return files;
}
void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
const std::string& config) const
{
+ std::vector<BT<cmSourceFile*>> tmp = this->GetSourceFiles(config);
+ files.reserve(tmp.size());
+ for (BT<cmSourceFile*>& v : tmp) {
+ files.push_back(v.Value);
+ }
+}
+
+std::vector<BT<cmSourceFile*>> cmGeneratorTarget::GetSourceFiles(
+ std::string const& config) const
+{
+ std::vector<BT<cmSourceFile*>> files;
if (!this->GlobalGenerator->GetConfigureDoneCMP0026()) {
// Since we are still configuring not all sources may exist yet,
// so we need to avoid full source classification because that
@@ -978,38 +1467,49 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
// Since this is only for compatibility with old policies that
// projects should not depend on anymore, just compute the files
// without memoizing them.
- std::vector<std::string> srcs;
- this->GetSourceFiles(srcs, config);
+ std::vector<BT<std::string>> srcs = this->GetSourceFilePaths(config);
std::set<cmSourceFile*> emitted;
- for (std::vector<std::string>::const_iterator i = srcs.begin();
- i != srcs.end(); ++i) {
- cmSourceFile* sf = this->Makefile->GetOrCreateSource(*i);
+ for (BT<std::string> const& s : srcs) {
+ cmSourceFile* sf = this->Makefile->GetOrCreateSource(s.Value);
if (emitted.insert(sf).second) {
- files.push_back(sf);
+ files.emplace_back(sf, s.Backtrace);
}
}
- return;
+ return files;
}
KindedSources const& kinded = this->GetKindedSources(config);
files.reserve(kinded.Sources.size());
- for (std::vector<SourceAndKind>::const_iterator si = kinded.Sources.begin();
- si != kinded.Sources.end(); ++si) {
- files.push_back(si->Source);
+ for (SourceAndKind const& si : kinded.Sources) {
+ files.push_back(si.Source);
}
+ return files;
}
void cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
std::vector<cmSourceFile*>& files, const std::string& config) const
{
+ std::vector<BT<cmSourceFile*>> tmp =
+ this->GetSourceFilesWithoutObjectLibraries(config);
+ files.reserve(tmp.size());
+ for (BT<cmSourceFile*>& v : tmp) {
+ files.push_back(v.Value);
+ }
+}
+
+std::vector<BT<cmSourceFile*>>
+cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
+ std::string const& config) const
+{
+ std::vector<BT<cmSourceFile*>> files;
KindedSources const& kinded = this->GetKindedSources(config);
files.reserve(kinded.Sources.size());
- for (std::vector<SourceAndKind>::const_iterator si = kinded.Sources.begin();
- si != kinded.Sources.end(); ++si) {
- if (si->Source->GetObjectLibrary().empty()) {
- files.push_back(si->Source);
+ for (SourceAndKind const& si : kinded.Sources) {
+ if (si.Source.Value->GetObjectLibrary().empty()) {
+ files.push_back(si.Source);
}
}
+ return files;
}
cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources(
@@ -1023,7 +1523,7 @@ cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources(
// Lookup any existing link implementation for this configuration.
std::string const key = cmSystemTools::UpperCase(config);
- KindedSourcesMapType::iterator it = this->KindedSourcesMap.find(key);
+ auto it = this->KindedSourcesMap.find(key);
if (it != this->KindedSourcesMap.end()) {
if (!it->second.Initialized) {
std::ostringstream e;
@@ -1031,7 +1531,7 @@ cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources(
<< "\" use a generator expression that depends on the "
"SOURCES themselves.";
this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
- cmake::FATAL_ERROR, e.str(), this->GetBacktrace());
+ MessageType::FATAL_ERROR, e.str(), this->GetBacktrace());
static KindedSources empty;
return empty;
}
@@ -1049,17 +1549,15 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
std::string const& config) const
{
// Get the source file paths by string.
- std::vector<std::string> srcs;
- this->GetSourceFiles(srcs, config);
+ std::vector<BT<std::string>> srcs = this->GetSourceFilePaths(config);
cmsys::RegularExpression header_regex(CM_HEADER_REGEX);
std::vector<cmSourceFile*> badObjLib;
std::set<cmSourceFile*> emitted;
- for (std::vector<std::string>::const_iterator i = srcs.begin();
- i != srcs.end(); ++i) {
+ for (BT<std::string> const& s : srcs) {
// Create each source at most once.
- cmSourceFile* sf = this->Makefile->GetOrCreateSource(*i);
+ cmSourceFile* sf = this->Makefile->GetOrCreateSource(s.Value);
if (!emitted.insert(sf).second) {
continue;
}
@@ -1071,14 +1569,13 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
kind = SourceKindCustomCommand;
} else if (this->Target->GetType() == cmStateEnums::UTILITY) {
kind = SourceKindExtra;
+ } else if (this->IsSourceFilePartOfUnityBatch(sf->ResolveFullPath())) {
+ kind = SourceKindUnityBatched;
} else if (sf->GetPropertyAsBool("HEADER_FILE_ONLY")) {
kind = SourceKindHeader;
} else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
kind = SourceKindExternalObject;
- if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- badObjLib.push_back(sf);
- }
- } else if (!sf->GetLanguage().empty()) {
+ } else if (!sf->GetOrDetermineLanguage().empty()) {
kind = SourceKindObjectSource;
} else if (ext == "def") {
kind = SourceKindModuleDefinition;
@@ -1097,7 +1594,7 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
// Both names would have been auto generated from Visual Studio
// where the user supplied the file name and Visual Studio
// appended the suffix.
- std::string resx = sf->GetFullPath();
+ std::string resx = sf->ResolveFullPath();
std::string hFileName = resx.substr(0, resx.find_last_of('.')) + ".h";
files.ExpectedResxHeaders.insert(hFileName);
} else if (ext == "appxmanifest") {
@@ -1113,33 +1610,31 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
// Both names would have been auto generated from Visual Studio
// where the user supplied the file name and Visual Studio
// appended the suffix.
- std::string xaml = sf->GetFullPath();
+ std::string xaml = sf->ResolveFullPath();
std::string hFileName = xaml + ".h";
std::string cppFileName = xaml + ".cpp";
files.ExpectedXamlHeaders.insert(hFileName);
files.ExpectedXamlSources.insert(cppFileName);
- } else if (header_regex.find(sf->GetFullPath().c_str())) {
+ } else if (header_regex.find(sf->ResolveFullPath())) {
kind = SourceKindHeader;
} else {
kind = SourceKindExtra;
}
// Save this classified source file in the result vector.
- SourceAndKind entry = { sf, kind };
- files.Sources.push_back(entry);
+ files.Sources.push_back({ BT<cmSourceFile*>(sf, s.Backtrace), kind });
}
if (!badObjLib.empty()) {
std::ostringstream e;
e << "OBJECT library \"" << this->GetName() << "\" contains:\n";
- for (std::vector<cmSourceFile*>::const_iterator i = badObjLib.begin();
- i != badObjLib.end(); ++i) {
- e << " " << (*i)->GetLocation().GetName() << "\n";
+ for (cmSourceFile* i : badObjLib) {
+ e << " " << i->GetLocation().GetName() << "\n";
}
e << "but may contain only sources that compile, header files, and "
"other files that would not affect linking of a normal library.";
this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
- cmake::FATAL_ERROR, e.str(), this->GetBacktrace());
+ MessageType::FATAL_ERROR, e.str(), this->GetBacktrace());
}
}
@@ -1161,18 +1656,15 @@ void cmGeneratorTarget::ComputeAllConfigSources() const
for (size_t ci = 0; ci < configs.size(); ++ci) {
KindedSources const& sources = this->GetKindedSources(configs[ci]);
- for (std::vector<cmGeneratorTarget::SourceAndKind>::const_iterator si =
- sources.Sources.begin();
- si != sources.Sources.end(); ++si) {
- std::map<cmSourceFile const*, size_t>::iterator mi =
- index.find(si->Source);
+ for (SourceAndKind const& src : sources.Sources) {
+ auto mi = index.find(src.Source.Value);
if (mi == index.end()) {
AllConfigSource acs;
- acs.Source = si->Source;
- acs.Kind = si->Kind;
- this->AllConfigSources.push_back(acs);
+ acs.Source = src.Source.Value;
+ acs.Kind = src.Kind;
+ this->AllConfigSources.push_back(std::move(acs));
std::map<cmSourceFile const*, size_t>::value_type entry(
- si->Source, this->AllConfigSources.size() - 1);
+ src.Source.Value, this->AllConfigSources.size() - 1);
mi = index.insert(entry).first;
}
this->AllConfigSources[mi->second].Configs.push_back(ci);
@@ -1191,8 +1683,7 @@ std::string cmGeneratorTarget::GetCompilePDBName(
// Check for a per-configuration output directory target property.
std::string configUpper = cmSystemTools::UpperCase(config);
- std::string configProp = "COMPILE_PDB_NAME_";
- configProp += configUpper;
+ std::string configProp = cmStrCat("COMPILE_PDB_NAME_", configUpper);
const char* config_name = this->GetProperty(configProp);
if (config_name && *config_name) {
return prefix + config_name + ".pdb";
@@ -1264,9 +1755,8 @@ bool cmGeneratorTarget::NeedRelinkBeforeInstall(
// Check for rpath support on this platform.
std::string ll = this->GetLinkerLanguage(config);
if (!ll.empty()) {
- std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
- flagVar += ll;
- flagVar += "_FLAG";
+ std::string flagVar =
+ cmStrCat("CMAKE_SHARED_LIBRARY_RUNTIME_", ll, "_FLAG");
if (!this->Makefile->IsSet(flagVar)) {
// There is no rpath support on this platform so nothing needs
// relinking.
@@ -1282,7 +1772,7 @@ bool cmGeneratorTarget::NeedRelinkBeforeInstall(
// will likely change between the build tree and install tree and
// this target must be relinked.
bool have_rpath =
- this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH();
+ this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH(config);
bool is_ninja =
this->LocalGenerator->GetGlobalGenerator()->GetName() == "Ninja";
@@ -1299,7 +1789,7 @@ bool cmGeneratorTarget::NeedRelinkBeforeInstall(
/* clang-format on */
cmake* cm = this->LocalGenerator->GetCMakeInstance();
- cm->IssueMessage(cmake::FATAL_ERROR, w.str(), this->GetBacktrace());
+ cm->IssueMessage(MessageType::FATAL_ERROR, w.str(), this->GetBacktrace());
}
return have_rpath;
@@ -1344,9 +1834,8 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const
// binaries.
std::string ll = this->GetLinkerLanguage(config);
if (!ll.empty()) {
- std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
- sepVar += ll;
- sepVar += "_FLAG_SEP";
+ std::string sepVar =
+ cmStrCat("CMAKE_SHARED_LIBRARY_RUNTIME_", ll, "_FLAG_SEP");
const char* sep = this->Makefile->GetDefinition(sepVar);
if (sep && *sep) {
// TODO: Add ELF check to ABI detection and get rid of
@@ -1430,7 +1919,7 @@ bool cmGeneratorTarget::HasMacOSXRpathInstallNameDir(
w << " less than 10.5 or because CMake's platform configuration is";
w << " corrupt.";
cmake* cm = this->LocalGenerator->GetCMakeInstance();
- cm->IssueMessage(cmake::FATAL_ERROR, w.str(), this->GetBacktrace());
+ cm->IssueMessage(MessageType::FATAL_ERROR, w.str(), this->GetBacktrace());
}
return true;
@@ -1463,7 +1952,7 @@ bool cmGeneratorTarget::MacOSXUseInstallNameDir() const
const char* build_with_install_name =
this->GetProperty("BUILD_WITH_INSTALL_NAME_DIR");
if (build_with_install_name) {
- return cmSystemTools::IsOn(build_with_install_name);
+ return cmIsOn(build_with_install_name);
}
cmPolicies::PolicyStatus cmp0068 = this->GetPolicyStatusCMP0068();
@@ -1525,38 +2014,33 @@ std::string cmGeneratorTarget::GetSOName(const std::string& config) const
return "";
}
// Compute the soname that will be built.
- std::string name;
- std::string soName;
- std::string realName;
- std::string impName;
- std::string pdbName;
- this->GetLibraryNames(name, soName, realName, impName, pdbName, config);
- return soName;
+ return this->GetLibraryNames(config).SharedObject;
}
-static bool shouldAddFullLevel(cmGeneratorTarget::BundleDirectoryLevel level)
+namespace {
+bool shouldAddFullLevel(cmGeneratorTarget::BundleDirectoryLevel level)
{
return level == cmGeneratorTarget::FullLevel;
}
-static bool shouldAddContentLevel(
- cmGeneratorTarget::BundleDirectoryLevel level)
+bool shouldAddContentLevel(cmGeneratorTarget::BundleDirectoryLevel level)
{
return level == cmGeneratorTarget::ContentLevel || shouldAddFullLevel(level);
}
+}
std::string cmGeneratorTarget::GetAppBundleDirectory(
const std::string& config, BundleDirectoryLevel level) const
{
- std::string fpath =
- this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact);
- fpath += ".";
+ std::string fpath = cmStrCat(
+ this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact), '.');
const char* ext = this->GetProperty("BUNDLE_EXTENSION");
if (!ext) {
ext = "app";
}
fpath += ext;
- if (shouldAddContentLevel(level) && !this->Makefile->PlatformIsAppleIos()) {
+ if (shouldAddContentLevel(level) &&
+ !this->Makefile->PlatformIsAppleEmbedded()) {
fpath += "/Contents";
if (shouldAddFullLevel(level)) {
fpath += "/MacOS";
@@ -1574,9 +2058,8 @@ bool cmGeneratorTarget::IsBundleOnApple() const
std::string cmGeneratorTarget::GetCFBundleDirectory(
const std::string& config, BundleDirectoryLevel level) const
{
- std::string fpath;
- fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact);
- fpath += ".";
+ std::string fpath = cmStrCat(
+ this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact), '.');
const char* ext = this->GetProperty("BUNDLE_EXTENSION");
if (!ext) {
if (this->IsXCTestOnApple()) {
@@ -1586,7 +2069,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";
@@ -1598,15 +2082,15 @@ std::string cmGeneratorTarget::GetCFBundleDirectory(
std::string cmGeneratorTarget::GetFrameworkDirectory(
const std::string& config, BundleDirectoryLevel level) const
{
- std::string fpath;
- fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact);
- fpath += ".";
+ std::string fpath = cmStrCat(
+ this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact), '.');
const char* ext = this->GetProperty("BUNDLE_EXTENSION");
if (!ext) {
ext = "framework";
}
fpath += ext;
- if (shouldAddFullLevel(level) && !this->Makefile->PlatformIsAppleIos()) {
+ if (shouldAddFullLevel(level) &&
+ !this->Makefile->PlatformIsAppleEmbedded()) {
fpath += "/Versions/";
fpath += this->GetFrameworkVersion();
}
@@ -1656,8 +2140,7 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const
if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) {
if (install_name_dir && *install_name_dir) {
- dir = install_name_dir;
- dir += "/";
+ dir = cmStrCat(install_name_dir, '/');
}
}
if (!install_name_dir) {
@@ -1675,31 +2158,21 @@ cmListFileBacktrace cmGeneratorTarget::GetBacktrace() const
return this->Target->GetBacktrace();
}
-const std::vector<std::string>& cmGeneratorTarget::GetLinkDirectories() const
-{
- return this->Target->GetLinkDirectories();
-}
-
-const std::set<std::string>& cmGeneratorTarget::GetUtilities() const
+const std::set<BT<std::string>>& cmGeneratorTarget::GetUtilities() const
{
return this->Target->GetUtilities();
}
-const cmListFileBacktrace* cmGeneratorTarget::GetUtilityBacktrace(
- const std::string& u) const
-{
- return this->Target->GetUtilityBacktrace(u);
-}
-
bool cmGeneratorTarget::HaveWellDefinedOutputFiles() const
{
return this->GetType() == cmStateEnums::STATIC_LIBRARY ||
this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
this->GetType() == cmStateEnums::EXECUTABLE;
}
-const char* cmGeneratorTarget::GetExportMacro() const
+const std::string* cmGeneratorTarget::GetExportMacro() const
{
// Define the symbol for targets that export symbols.
if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
@@ -1708,23 +2181,22 @@ const char* cmGeneratorTarget::GetExportMacro() const
if (const char* custom_export_name = this->GetProperty("DEFINE_SYMBOL")) {
this->ExportMacro = custom_export_name;
} else {
- std::string in = this->GetName();
- in += "_EXPORTS";
+ std::string in = cmStrCat(this->GetName(), "_EXPORTS");
this->ExportMacro = cmSystemTools::MakeCidentifier(in);
}
- return this->ExportMacro.c_str();
+ return &this->ExportMacro;
}
- return CM_NULLPTR;
+ return nullptr;
}
class cmTargetCollectLinkLanguages
{
public:
cmTargetCollectLinkLanguages(cmGeneratorTarget const* target,
- const std::string& config,
- CM_UNORDERED_SET<std::string>& languages,
+ std::string config,
+ std::unordered_set<std::string>& languages,
cmGeneratorTarget const* head)
- : Config(config)
+ : Config(std::move(config))
, Languages(languages)
, HeadTarget(head)
, Target(target)
@@ -1735,15 +2207,15 @@ public:
void Visit(cmLinkItem const& item)
{
if (!item.Target) {
- if (item.find("::") != std::string::npos) {
+ if (item.AsStr().find("::") != std::string::npos) {
bool noMessage = false;
- cmake::MessageType messageType = cmake::FATAL_ERROR;
+ MessageType messageType = MessageType::FATAL_ERROR;
std::ostringstream e;
switch (this->Target->GetLocalGenerator()->GetPolicyStatus(
cmPolicies::CMP0028)) {
case cmPolicies::WARN: {
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0028) << "\n";
- messageType = cmake::AUTHOR_WARNING;
+ messageType = MessageType::AUTHOR_WARNING;
} break;
case cmPolicies::OLD:
noMessage = true;
@@ -1756,7 +2228,7 @@ public:
if (!noMessage) {
e << "Target \"" << this->Target->GetName()
- << "\" links to target \"" << item
+ << "\" links to target \"" << item.AsStr()
<< "\" but the target was not found. Perhaps a find_package() "
"call is missing for an IMPORTED target, or an ALIAS target is "
"missing?";
@@ -1775,21 +2247,18 @@ public:
return;
}
- for (std::vector<std::string>::const_iterator li =
- iface->Languages.begin();
- li != iface->Languages.end(); ++li) {
- this->Languages.insert(*li);
+ for (std::string const& language : iface->Languages) {
+ this->Languages.insert(language);
}
- for (std::vector<cmLinkItem>::const_iterator li = iface->Libraries.begin();
- li != iface->Libraries.end(); ++li) {
- this->Visit(*li);
+ for (cmLinkItem const& lib : iface->Libraries) {
+ this->Visit(lib);
}
}
private:
std::string Config;
- CM_UNORDERED_SET<std::string>& Languages;
+ std::unordered_set<std::string>& Languages;
cmGeneratorTarget const* HeadTarget;
const cmGeneratorTarget* Target;
std::set<cmGeneratorTarget const*> Visited;
@@ -1799,7 +2268,7 @@ cmGeneratorTarget::LinkClosure const* cmGeneratorTarget::GetLinkClosure(
const std::string& config) const
{
std::string key(cmSystemTools::UpperCase(config));
- LinkClosureMapType::iterator i = this->LinkClosureMap.find(key);
+ auto i = this->LinkClosureMap.find(key);
if (i == this->LinkClosureMap.end()) {
LinkClosure lc;
this->ComputeLinkClosure(config, lc);
@@ -1844,13 +2313,12 @@ public:
e << "Target " << this->Target->GetName()
<< " contains multiple languages with the highest linker preference"
<< " (" << this->Preference << "):\n";
- for (std::set<std::string>::const_iterator li = this->Preferred.begin();
- li != this->Preferred.end(); ++li) {
- e << " " << *li << "\n";
+ for (std::string const& li : this->Preferred) {
+ e << " " << li << "\n";
}
e << "Set the LINKER_LANGUAGE property for this target.";
cmake* cm = this->Target->GetLocalGenerator()->GetCMakeInstance();
- cm->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ cm->IssueMessage(MessageType::FATAL_ERROR, e.str(),
this->Target->GetBacktrace());
}
return *this->Preferred.begin();
@@ -1861,26 +2329,22 @@ void cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
LinkClosure& lc) const
{
// Get languages built in this target.
- CM_UNORDERED_SET<std::string> languages;
+ std::unordered_set<std::string> languages;
cmLinkImplementation const* impl = this->GetLinkImplementation(config);
assert(impl);
- for (std::vector<std::string>::const_iterator li = impl->Languages.begin();
- li != impl->Languages.end(); ++li) {
- languages.insert(*li);
+ for (std::string const& li : impl->Languages) {
+ languages.insert(li);
}
// Add interface languages from linked targets.
cmTargetCollectLinkLanguages cll(this, config, languages, this);
- for (std::vector<cmLinkImplItem>::const_iterator li =
- impl->Libraries.begin();
- li != impl->Libraries.end(); ++li) {
- cll.Visit(*li);
+ for (cmLinkImplItem const& lib : impl->Libraries) {
+ cll.Visit(lib);
}
// Store the transitive closure of languages.
- for (CM_UNORDERED_SET<std::string>::const_iterator li = languages.begin();
- li != languages.end(); ++li) {
- lc.Languages.push_back(*li);
+ for (std::string const& lang : languages) {
+ lc.Languages.push_back(lang);
}
// Choose the language whose linker should be used.
@@ -1893,18 +2357,16 @@ void cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
cmTargetSelectLinker tsl(this);
// First select from the languages compiled directly in this target.
- for (std::vector<std::string>::const_iterator li = impl->Languages.begin();
- li != impl->Languages.end(); ++li) {
- tsl.Consider(li->c_str());
+ for (std::string const& l : impl->Languages) {
+ tsl.Consider(l.c_str());
}
// Now consider languages that propagate from linked targets.
- for (CM_UNORDERED_SET<std::string>::const_iterator sit = languages.begin();
- sit != languages.end(); ++sit) {
+ for (std::string const& lang : languages) {
std::string propagates =
- "CMAKE_" + *sit + "_LINKER_PREFERENCE_PROPAGATES";
+ "CMAKE_" + lang + "_LINKER_PREFERENCE_PROPAGATES";
if (this->Makefile->IsOn(propagates)) {
- tsl.Consider(sit->c_str());
+ tsl.Consider(lang.c_str());
}
}
@@ -1940,8 +2402,7 @@ std::string cmGeneratorTarget::GetMacContentDirectory(
const std::string& config, cmStateEnums::ArtifactType artifact) const
{
// Start with the output directory for the target.
- std::string fpath = this->GetDirectory(config, artifact);
- fpath += "/";
+ std::string fpath = cmStrCat(this->GetDirectory(config, artifact), '/');
BundleDirectoryLevel level = ContentLevel;
if (this->IsFrameworkOnApple()) {
// additional files with a framework go into the version specific
@@ -1973,16 +2434,15 @@ cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo(
{
// There is no compile information for imported targets.
if (this->IsImported()) {
- return CM_NULLPTR;
+ return nullptr;
}
if (this->GetType() > cmStateEnums::OBJECT_LIBRARY) {
- std::string msg = "cmTarget::GetCompileInfo called for ";
- msg += this->GetName();
- msg += " which has type ";
- msg += cmState::GetTargetTypeName(this->GetType());
- this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg);
- return CM_NULLPTR;
+ std::string msg = cmStrCat("cmTarget::GetCompileInfo called for ",
+ this->GetName(), " which has type ",
+ cmState::GetTargetTypeName(this->GetType()));
+ this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
+ return nullptr;
}
// Lookup/compute/cache the compile information for this configuration.
@@ -1990,8 +2450,7 @@ cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo(
if (!config.empty()) {
config_upper = cmSystemTools::UpperCase(config);
}
- CompileInfoMapType::const_iterator i =
- this->CompileInfoMap.find(config_upper);
+ auto i = this->CompileInfoMap.find(config_upper);
if (i == this->CompileInfoMap.end()) {
CompileInfo info;
this->ComputePDBOutputDir("COMPILE_PDB", config, info.CompilePdbDir);
@@ -2008,7 +2467,7 @@ cmGeneratorTarget::GetModuleDefinitionInfo(std::string const& config) const
if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
this->GetType() != cmStateEnums::MODULE_LIBRARY &&
!this->IsExecutableWithExports()) {
- return CM_NULLPTR;
+ return nullptr;
}
// Lookup/compute/cache the compile information for this configuration.
@@ -2016,8 +2475,7 @@ cmGeneratorTarget::GetModuleDefinitionInfo(std::string const& config) const
if (!config.empty()) {
config_upper = cmSystemTools::UpperCase(config);
}
- ModuleDefinitionInfoMapType::const_iterator i =
- this->ModuleDefinitionInfoMap.find(config_upper);
+ auto i = this->ModuleDefinitionInfoMap.find(config_upper);
if (i == this->ModuleDefinitionInfoMap.end()) {
ModuleDefinitionInfo info;
this->ComputeModuleDefinitionInfo(config, info);
@@ -2034,8 +2492,13 @@ void cmGeneratorTarget::ComputeModuleDefinitionInfo(
info.WindowsExportAllSymbols =
this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") &&
this->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS");
+#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
info.DefFileGenerated =
info.WindowsExportAllSymbols || info.Sources.size() > 1;
+#else
+ // Our __create_def helper is only available on Windows.
+ info.DefFileGenerated = false;
+#endif
if (info.DefFileGenerated) {
info.DefFile = this->ObjectDirectory /* has slash */ + "exports.def";
} else if (!info.Sources.empty()) {
@@ -2045,7 +2508,7 @@ void cmGeneratorTarget::ComputeModuleDefinitionInfo(
bool cmGeneratorTarget::IsDLLPlatform() const
{
- return this->DLLPlatform;
+ return this->Target->IsDLLPlatform();
}
void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result,
@@ -2056,14 +2519,12 @@ void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result,
if (!prop) {
return;
}
- cmGeneratorExpression ge;
- cmGeneratorExpressionDAGChecker dagChecker(
- this->GetName(), "AUTOUIC_OPTIONS", CM_NULLPTR, CM_NULLPTR);
- cmSystemTools::ExpandListArgument(
- ge.Parse(prop)->Evaluate(this->LocalGenerator, config, false, this,
- &dagChecker),
- result);
+ cmGeneratorExpressionDAGChecker dagChecker(this, "AUTOUIC_OPTIONS", nullptr,
+ nullptr);
+ cmExpandList(cmGeneratorExpression::Evaluate(prop, this->LocalGenerator,
+ config, this, &dagChecker),
+ result);
}
void processILibs(const std::string& config,
@@ -2076,10 +2537,8 @@ void processILibs(const std::string& config,
tgts.push_back(item.Target);
if (cmLinkInterfaceLibraries const* iface =
item.Target->GetLinkInterfaceLibraries(config, headTarget, true)) {
- for (std::vector<cmLinkItem>::const_iterator it =
- iface->Libraries.begin();
- it != iface->Libraries.end(); ++it) {
- processILibs(config, headTarget, *it, gg, tgts, emitted);
+ for (cmLinkItem const& lib : iface->Libraries) {
+ processILibs(config, headTarget, lib, gg, tgts, emitted);
}
}
}
@@ -2097,10 +2556,8 @@ cmGeneratorTarget::GetLinkImplementationClosure(
cmLinkImplementationLibraries const* impl =
this->GetLinkImplementationLibraries(config);
- for (std::vector<cmLinkImplItem>::const_iterator it =
- impl->Libraries.begin();
- it != impl->Libraries.end(); ++it) {
- processILibs(config, this, *it,
+ for (cmLinkImplItem const& lib : impl->Libraries) {
+ processILibs(config, this, lib,
this->LocalGenerator->GetGlobalGenerator(), tgts, emitted);
}
}
@@ -2118,11 +2575,11 @@ private:
cmMakefile* Makefile;
cmLocalGenerator* LocalGenerator;
cmGlobalGenerator const* GlobalGenerator;
- typedef cmGeneratorTarget::SourceEntry SourceEntry;
+ using SourceEntry = cmGeneratorTarget::SourceEntry;
SourceEntry* CurrentEntry;
std::queue<cmSourceFile*> SourceQueue;
std::set<cmSourceFile*> SourcesQueued;
- typedef std::map<std::string, cmSourceFile*> NameMapType;
+ using NameMapType = std::map<std::string, cmSourcesWithOutput>;
NameMapType NameMap;
std::vector<std::string> NewSources;
@@ -2144,32 +2601,26 @@ cmTargetTraceDependencies::cmTargetTraceDependencies(cmGeneratorTarget* target)
this->Makefile = target->Target->GetMakefile();
this->LocalGenerator = target->GetLocalGenerator();
this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
- this->CurrentEntry = CM_NULLPTR;
+ this->CurrentEntry = nullptr;
// Queue all the source files already specified for the target.
if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
- std::vector<std::string> configs;
- this->Makefile->GetConfigurations(configs);
- if (configs.empty()) {
- configs.push_back("");
- }
std::set<cmSourceFile*> emitted;
- for (std::vector<std::string>::const_iterator ci = configs.begin();
- ci != configs.end(); ++ci) {
+ std::vector<std::string> const& configs =
+ this->Makefile->GetGeneratorConfigs();
+ for (std::string const& c : configs) {
std::vector<cmSourceFile*> sources;
- this->GeneratorTarget->GetSourceFiles(sources, *ci);
- for (std::vector<cmSourceFile*>::const_iterator si = sources.begin();
- si != sources.end(); ++si) {
- cmSourceFile* sf = *si;
+ this->GeneratorTarget->GetSourceFiles(sources, c);
+ for (cmSourceFile* sf : sources) {
const std::set<cmGeneratorTarget const*> tgts =
this->GlobalGenerator->GetFilenameTargetDepends(sf);
- if (tgts.find(this->GeneratorTarget) != tgts.end()) {
+ if (cmContains(tgts, this->GeneratorTarget)) {
std::ostringstream e;
- e << "Evaluation output file\n \"" << sf->GetFullPath()
+ e << "Evaluation output file\n \"" << sf->ResolveFullPath()
<< "\"\ndepends on the sources of a target it is used in. This "
"is a dependency loop and is not allowed.";
this->GeneratorTarget->LocalGenerator->IssueMessage(
- cmake::FATAL_ERROR, e.str());
+ MessageType::FATAL_ERROR, e.str());
return;
}
if (emitted.insert(sf).second &&
@@ -2197,21 +2648,19 @@ void cmTargetTraceDependencies::Trace()
// Queue dependencies added explicitly by the user.
if (const char* additionalDeps = sf->GetProperty("OBJECT_DEPENDS")) {
- std::vector<std::string> objDeps;
- cmSystemTools::ExpandListArgument(additionalDeps, objDeps);
- for (std::vector<std::string>::iterator odi = objDeps.begin();
- odi != objDeps.end(); ++odi) {
- if (cmSystemTools::FileIsFullPath(*odi)) {
- *odi = cmSystemTools::CollapseFullPath(*odi);
+ std::vector<std::string> objDeps = cmExpandedList(additionalDeps);
+ for (std::string& objDep : objDeps) {
+ if (cmSystemTools::FileIsFullPath(objDep)) {
+ objDep = cmSystemTools::CollapseFullPath(objDep);
}
}
this->FollowNames(objDeps);
}
// Queue the source needed to generate this file, if any.
- this->FollowName(sf->GetFullPath());
+ this->FollowName(sf->ResolveFullPath());
- // Queue dependencies added programatically by commands.
+ // Queue dependencies added programmatically by commands.
this->FollowNames(sf->GetDepends());
// Queue custom command dependencies.
@@ -2219,7 +2668,7 @@ void cmTargetTraceDependencies::Trace()
this->CheckCustomCommand(*cc);
}
}
- this->CurrentEntry = CM_NULLPTR;
+ this->CurrentEntry = nullptr;
this->GeneratorTarget->AddTracedSources(this->NewSources);
}
@@ -2230,34 +2679,44 @@ void cmTargetTraceDependencies::QueueSource(cmSourceFile* sf)
this->SourceQueue.push(sf);
// Make sure this file is in the target at the end.
- this->NewSources.push_back(sf->GetFullPath());
+ this->NewSources.push_back(sf->ResolveFullPath());
}
}
void cmTargetTraceDependencies::FollowName(std::string const& name)
{
- NameMapType::iterator i = this->NameMap.find(name);
- if (i == this->NameMap.end()) {
+ // Use lower bound with key comparison to not repeat the search for the
+ // insert position if the name could not be found (which is the common case).
+ auto i = this->NameMap.lower_bound(name);
+ if (i == this->NameMap.end() || i->first != name) {
// Check if we know how to generate this file.
- cmSourceFile* sf = this->Makefile->GetSourceFileWithOutput(name);
- NameMapType::value_type entry(name, sf);
- i = this->NameMap.insert(entry).first;
- }
- if (cmSourceFile* sf = i->second) {
- // Record the dependency we just followed.
- if (this->CurrentEntry) {
- this->CurrentEntry->Depends.push_back(sf);
+ cmSourcesWithOutput sources = this->Makefile->GetSourcesWithOutput(name);
+ i = this->NameMap.emplace_hint(i, name, sources);
+ }
+ if (cmTarget* t = i->second.Target) {
+ // The name is a byproduct of a utility target or a PRE_BUILD, PRE_LINK, or
+ // POST_BUILD command.
+ this->GeneratorTarget->Target->AddUtility(t->GetName());
+ }
+ if (cmSourceFile* sf = i->second.Source) {
+ // For now only follow the dependency if the source file is not a
+ // byproduct. Semantics of byproducts in a non-Ninja context will have to
+ // be defined first.
+ if (!i->second.SourceIsByproduct) {
+ // Record the dependency we just followed.
+ if (this->CurrentEntry) {
+ this->CurrentEntry->Depends.push_back(sf);
+ }
+ this->QueueSource(sf);
}
- this->QueueSource(sf);
}
}
void cmTargetTraceDependencies::FollowNames(
std::vector<std::string> const& names)
{
- for (std::vector<std::string>::const_iterator i = names.begin();
- i != names.end(); ++i) {
- this->FollowName(*i);
+ for (std::string const& name : names) {
+ this->FollowName(name);
}
}
@@ -2281,7 +2740,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
@@ -2317,9 +2776,8 @@ void cmTargetTraceDependencies::CheckCustomCommand(cmCustomCommand const& cc)
// Add target-level dependencies referenced by generator expressions.
std::set<cmGeneratorTarget*> targets;
- for (cmCustomCommandLines::const_iterator cit = cc.GetCommandLines().begin();
- cit != cc.GetCommandLines().end(); ++cit) {
- std::string const& command = *cit->begin();
+ for (cmCustomCommandLine const& cCmdLine : cc.GetCommandLines()) {
+ std::string const& command = cCmdLine.front();
// Check for a target with this name.
if (cmGeneratorTarget* t =
this->LocalGenerator->FindGeneratorTargetToUse(command)) {
@@ -2333,30 +2791,25 @@ void cmTargetTraceDependencies::CheckCustomCommand(cmCustomCommand const& cc)
}
// Check for target references in generator expressions.
- for (cmCustomCommandLine::const_iterator cli = cit->begin();
- cli != cit->end(); ++cli) {
- const CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(*cli);
- cge->Evaluate(this->GeneratorTarget->GetLocalGenerator(), "", true);
+ for (std::string const& cl : cCmdLine) {
+ const std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(cl);
+ cge->SetQuiet(true);
+ cge->Evaluate(this->GeneratorTarget->GetLocalGenerator(), "");
std::set<cmGeneratorTarget*> geTargets = cge->GetTargets();
targets.insert(geTargets.begin(), geTargets.end());
}
}
- for (std::set<cmGeneratorTarget*>::iterator ti = targets.begin();
- ti != targets.end(); ++ti) {
- this->GeneratorTarget->Target->AddUtility((*ti)->GetName());
+ for (cmGeneratorTarget* target : targets) {
+ this->GeneratorTarget->Target->AddUtility(target->GetName());
}
// Queue the custom command dependencies.
- std::vector<std::string> configs;
std::set<std::string> emitted;
- this->Makefile->GetConfigurations(configs);
- if (configs.empty()) {
- configs.push_back("");
- }
- for (std::vector<std::string>::const_iterator ci = configs.begin();
- ci != configs.end(); ++ci) {
- this->FollowCommandDepends(cc, *ci, emitted);
+ std::vector<std::string> const& configs =
+ this->Makefile->GetGeneratorConfigs();
+ for (std::string const& conf : configs) {
+ this->FollowCommandDepends(cc, conf, emitted);
}
}
@@ -2369,9 +2822,7 @@ void cmTargetTraceDependencies::FollowCommandDepends(
const std::vector<std::string>& depends = ccg.GetDepends();
- for (std::vector<std::string>::const_iterator di = depends.begin();
- di != depends.end(); ++di) {
- std::string const& dep = *di;
+ for (std::string const& dep : depends) {
if (emitted.insert(dep).second) {
if (!this->IsUtility(dep)) {
// The dependency does not name a target and may be a file we
@@ -2385,9 +2836,8 @@ void cmTargetTraceDependencies::FollowCommandDepends(
void cmTargetTraceDependencies::CheckCustomCommands(
const std::vector<cmCustomCommand>& commands)
{
- for (std::vector<cmCustomCommand>::const_iterator cli = commands.begin();
- cli != commands.end(); ++cli) {
- this->CheckCustomCommand(*cli);
+ for (cmCustomCommand const& command : commands) {
+ this->CheckCustomCommand(command);
}
}
@@ -2418,17 +2868,17 @@ std::string cmGeneratorTarget::GetCompilePDBDirectory(
void cmGeneratorTarget::GetAppleArchs(const std::string& config,
std::vector<std::string>& archVec) const
{
- const char* archs = CM_NULLPTR;
+ const char* archs = nullptr;
if (!config.empty()) {
- std::string defVarName = "OSX_ARCHITECTURES_";
- defVarName += cmSystemTools::UpperCase(config);
+ std::string defVarName =
+ cmStrCat("OSX_ARCHITECTURES_", cmSystemTools::UpperCase(config));
archs = this->GetProperty(defVarName);
}
if (!archs) {
archs = this->GetProperty("OSX_ARCHITECTURES");
}
if (archs) {
- cmSystemTools::ExpandListArgument(std::string(archs), archVec);
+ cmExpandList(std::string(archs), archVec);
}
}
@@ -2461,47 +2911,45 @@ std::string cmGeneratorTarget::GetCreateRuleVariable(
case cmStateEnums::MODULE_LIBRARY:
return "CMAKE_" + lang + "_CREATE_SHARED_MODULE";
case cmStateEnums::EXECUTABLE:
+ if (this->IsExecutableWithExports()) {
+ std::string linkExeWithExports =
+ "CMAKE_" + lang + "_LINK_EXECUTABLE_WITH_EXPORTS";
+ if (this->Makefile->IsDefinitionSet(linkExeWithExports)) {
+ return linkExeWithExports;
+ }
+ }
return "CMAKE_" + lang + "_LINK_EXECUTABLE";
default:
break;
}
return "";
}
-static void processIncludeDirectories(
+
+namespace {
+void processIncludeDirectories(
cmGeneratorTarget const* tgt,
- const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
- std::vector<std::string>& includes,
- CM_UNORDERED_SET<std::string>& uniqueIncludes,
- cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
- bool debugIncludes, const std::string& language)
-{
- for (std::vector<cmGeneratorTarget::TargetPropertyEntry *>::const_iterator
- it = entries.begin(),
- end = entries.end();
- it != end; ++it) {
- cmLinkImplItem const& item = (*it)->LinkImplItem;
- std::string const& targetName = item;
+ std::vector<EvaluatedTargetPropertyEntry>& entries,
+ std::vector<BT<std::string>>& includes,
+ std::unordered_set<std::string>& uniqueIncludes, bool debugIncludes)
+{
+ for (EvaluatedTargetPropertyEntry& entry : entries) {
+ cmLinkImplItem const& item = entry.LinkImplItem;
+ std::string const& targetName = item.AsStr();
bool const fromImported = item.Target && item.Target->IsImported();
bool const checkCMP0027 = item.FromGenex;
- std::vector<std::string> entryIncludes;
- cmSystemTools::ExpandListArgument(
- (*it)->ge->Evaluate(tgt->GetLocalGenerator(), config, false, tgt,
- dagChecker, language),
- entryIncludes);
std::string usedIncludes;
- for (std::vector<std::string>::iterator li = entryIncludes.begin();
- li != entryIncludes.end(); ++li) {
- if (fromImported && !cmSystemTools::FileExists(li->c_str())) {
+ for (std::string& entryInclude : entry.Values) {
+ if (fromImported && !cmSystemTools::FileExists(entryInclude)) {
std::ostringstream e;
- cmake::MessageType messageType = cmake::FATAL_ERROR;
+ MessageType messageType = MessageType::FATAL_ERROR;
if (checkCMP0027) {
switch (tgt->GetPolicyStatusCMP0027()) {
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0027) << "\n";
CM_FALLTHROUGH;
case cmPolicies::OLD:
- messageType = cmake::AUTHOR_WARNING;
+ messageType = MessageType::AUTHOR_WARNING;
break;
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::REQUIRED_IF_USED:
@@ -2511,7 +2959,7 @@ static void processIncludeDirectories(
}
/* clang-format off */
e << "Imported target \"" << targetName << "\" includes "
- "non-existent path\n \"" << *li << "\"\nin its "
+ "non-existent path\n \"" << entryInclude << "\"\nin its "
"INTERFACE_INCLUDE_DIRECTORIES. Possible reasons include:\n"
"* The path was deleted, renamed, or moved to another "
"location.\n"
@@ -2524,21 +2972,21 @@ static void processIncludeDirectories(
return;
}
- if (!cmSystemTools::FileIsFullPath(li->c_str())) {
+ if (!cmSystemTools::FileIsFullPath(entryInclude)) {
std::ostringstream e;
bool noMessage = false;
- cmake::MessageType messageType = cmake::FATAL_ERROR;
+ MessageType messageType = MessageType::FATAL_ERROR;
if (!targetName.empty()) {
/* clang-format off */
e << "Target \"" << targetName << "\" contains relative "
"path in its INTERFACE_INCLUDE_DIRECTORIES:\n"
- " \"" << *li << "\"";
+ " \"" << entryInclude << "\"";
/* clang-format on */
} else {
switch (tgt->GetPolicyStatusCMP0021()) {
case cmPolicies::WARN: {
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0021) << "\n";
- messageType = cmake::AUTHOR_WARNING;
+ messageType = MessageType::AUTHOR_WARNING;
} break;
case cmPolicies::OLD:
noMessage = true;
@@ -2550,77 +2998,73 @@ static void processIncludeDirectories(
}
e << "Found relative path while evaluating include directories of "
"\""
- << tgt->GetName() << "\":\n \"" << *li << "\"\n";
+ << tgt->GetName() << "\":\n \"" << entryInclude << "\"\n";
}
if (!noMessage) {
tgt->GetLocalGenerator()->IssueMessage(messageType, e.str());
- if (messageType == cmake::FATAL_ERROR) {
+ if (messageType == MessageType::FATAL_ERROR) {
return;
}
}
}
- if (!cmSystemTools::IsOff(li->c_str())) {
- cmSystemTools::ConvertToUnixSlashes(*li);
+ if (!cmIsOff(entryInclude)) {
+ cmSystemTools::ConvertToUnixSlashes(entryInclude);
}
- std::string inc = *li;
- if (uniqueIncludes.insert(inc).second) {
- includes.push_back(inc);
+ if (uniqueIncludes.insert(entryInclude).second) {
+ includes.emplace_back(entryInclude, entry.Backtrace);
if (debugIncludes) {
- usedIncludes += " * " + inc + "\n";
+ usedIncludes += " * " + entryInclude + "\n";
}
}
}
if (!usedIncludes.empty()) {
tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
- cmake::LOG, std::string("Used includes for target ") + tgt->GetName() +
- ":\n" + usedIncludes,
- (*it)->ge->GetBacktrace());
+ MessageType::LOG,
+ std::string("Used includes for target ") + tgt->GetName() + ":\n" +
+ usedIncludes,
+ entry.Backtrace);
}
}
}
+}
-std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
+std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories(
const std::string& config, const std::string& lang) const
{
- std::vector<std::string> includes;
- CM_UNORDERED_SET<std::string> uniqueIncludes;
+ std::vector<BT<std::string>> includes;
+ std::unordered_set<std::string> uniqueIncludes;
- cmGeneratorExpressionDAGChecker dagChecker(
- this->GetName(), "INCLUDE_DIRECTORIES", CM_NULLPTR, CM_NULLPTR);
+ cmGeneratorExpressionDAGChecker dagChecker(this, "INCLUDE_DIRECTORIES",
+ nullptr, nullptr);
std::vector<std::string> debugProperties;
const char* debugProp =
this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
if (debugProp) {
- cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+ cmExpandList(debugProp, debugProperties);
}
bool debugIncludes = !this->DebugIncludesDone &&
- std::find(debugProperties.begin(), debugProperties.end(),
- "INCLUDE_DIRECTORIES") != debugProperties.end();
+ cmContains(debugProperties, "INCLUDE_DIRECTORIES");
if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
this->DebugIncludesDone = true;
}
- processIncludeDirectories(this, this->IncludeDirectoriesEntries, includes,
- uniqueIncludes, &dagChecker, config, debugIncludes,
- lang);
+ std::vector<EvaluatedTargetPropertyEntry> entries =
+ EvaluateTargetPropertyEntries(this, config, lang, &dagChecker,
+ this->IncludeDirectoriesEntries);
- std::vector<cmGeneratorTarget::TargetPropertyEntry*>
- linkInterfaceIncludeDirectoriesEntries;
- AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES",
- linkInterfaceIncludeDirectoriesEntries);
+ AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES", lang,
+ &dagChecker, entries);
if (this->Makefile->IsOn("APPLE")) {
cmLinkImplementationLibraries const* impl =
this->GetLinkImplementationLibraries(config);
- for (std::vector<cmLinkImplItem>::const_iterator it =
- impl->Libraries.begin();
- it != impl->Libraries.end(); ++it) {
- std::string libDir = cmSystemTools::CollapseFullPath(*it);
+ for (cmLinkImplItem const& lib : impl->Libraries) {
+ std::string libDir = cmSystemTools::CollapseFullPath(lib.AsStr());
static cmsys::RegularExpression frameworkCheck(
"(.*\\.framework)(/Versions/[^/]+)?/[^/]+$");
@@ -2630,47 +3074,45 @@ std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
libDir = frameworkCheck.match(1);
- cmGeneratorExpression ge;
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge =
- ge.Parse(libDir.c_str());
- linkInterfaceIncludeDirectoriesEntries.push_back(
- new cmGeneratorTarget::TargetPropertyEntry(cge));
+ EvaluatedTargetPropertyEntry ee(lib, cmListFileBacktrace());
+ ee.Values.emplace_back(std::move(libDir));
+ entries.emplace_back(std::move(ee));
}
}
- processIncludeDirectories(this, linkInterfaceIncludeDirectoriesEntries,
- includes, uniqueIncludes, &dagChecker, config,
- debugIncludes, lang);
-
- cmDeleteAll(linkInterfaceIncludeDirectoriesEntries);
+ processIncludeDirectories(this, entries, includes, uniqueIncludes,
+ debugIncludes);
return includes;
}
-static void processCompileOptionsInternal(
- cmGeneratorTarget const* tgt,
- const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
- std::vector<std::string>& options,
- CM_UNORDERED_SET<std::string>& uniqueOptions,
- cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
- bool debugOptions, const char* logName, std::string const& language)
-{
- for (std::vector<cmGeneratorTarget::TargetPropertyEntry *>::const_iterator
- it = entries.begin(),
- end = entries.end();
- it != end; ++it) {
- std::vector<std::string> entryOptions;
- cmSystemTools::ExpandListArgument(
- (*it)->ge->Evaluate(tgt->GetLocalGenerator(), config, false, tgt,
- dagChecker, language),
- entryOptions);
- std::string usedOptions;
- for (std::vector<std::string>::iterator li = entryOptions.begin();
- li != entryOptions.end(); ++li) {
- std::string const& opt = *li;
+enum class OptionsParse
+{
+ None,
+ Shell
+};
+namespace {
+void processOptions(cmGeneratorTarget const* tgt,
+ std::vector<EvaluatedTargetPropertyEntry> const& entries,
+ std::vector<BT<std::string>>& options,
+ std::unordered_set<std::string>& uniqueOptions,
+ bool debugOptions, const char* logName, OptionsParse parse)
+{
+ for (EvaluatedTargetPropertyEntry const& entry : entries) {
+ std::string usedOptions;
+ for (std::string const& opt : entry.Values) {
if (uniqueOptions.insert(opt).second) {
- options.push_back(opt);
+ if (parse == OptionsParse::Shell &&
+ cmHasLiteralPrefix(opt, "SHELL:")) {
+ std::vector<std::string> tmp;
+ cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, tmp);
+ for (std::string& o : tmp) {
+ options.emplace_back(std::move(o), entry.Backtrace);
+ }
+ } else {
+ options.emplace_back(opt, entry.Backtrace);
+ }
if (debugOptions) {
usedOptions += " * " + opt + "\n";
}
@@ -2678,162 +3120,150 @@ static void processCompileOptionsInternal(
}
if (!usedOptions.empty()) {
tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
- cmake::LOG, std::string("Used compile ") + logName +
- std::string(" for target ") + tgt->GetName() + ":\n" + usedOptions,
- (*it)->ge->GetBacktrace());
+ MessageType::LOG,
+ std::string("Used ") + logName + std::string(" for target ") +
+ tgt->GetName() + ":\n" + usedOptions,
+ entry.Backtrace);
}
}
}
-
-static void processCompileOptions(
- cmGeneratorTarget const* tgt,
- const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
- std::vector<std::string>& options,
- CM_UNORDERED_SET<std::string>& uniqueOptions,
- cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
- bool debugOptions, std::string const& language)
-{
- processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
- dagChecker, config, debugOptions, "options",
- language);
}
void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const
{
- CM_UNORDERED_SET<std::string> uniqueOptions;
+ std::vector<BT<std::string>> tmp = this->GetCompileOptions(config, language);
+ result.reserve(tmp.size());
+ for (BT<std::string>& v : tmp) {
+ result.emplace_back(std::move(v.Value));
+ }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetCompileOptions(
+ std::string const& config, std::string const& language) const
+{
+ std::vector<BT<std::string>> result;
+ std::unordered_set<std::string> uniqueOptions;
- cmGeneratorExpressionDAGChecker dagChecker(
- this->GetName(), "COMPILE_OPTIONS", CM_NULLPTR, CM_NULLPTR);
+ cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_OPTIONS", nullptr,
+ nullptr);
std::vector<std::string> debugProperties;
const char* debugProp =
this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
if (debugProp) {
- cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+ cmExpandList(debugProp, debugProperties);
}
bool debugOptions = !this->DebugCompileOptionsDone &&
- std::find(debugProperties.begin(), debugProperties.end(),
- "COMPILE_OPTIONS") != debugProperties.end();
+ cmContains(debugProperties, "COMPILE_OPTIONS");
if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
this->DebugCompileOptionsDone = true;
}
- processCompileOptions(this, this->CompileOptionsEntries, result,
- uniqueOptions, &dagChecker, config, debugOptions,
- language);
+ std::vector<EvaluatedTargetPropertyEntry> entries =
+ EvaluateTargetPropertyEntries(this, config, language, &dagChecker,
+ this->CompileOptionsEntries);
- std::vector<cmGeneratorTarget::TargetPropertyEntry*>
- linkInterfaceCompileOptionsEntries;
+ AddInterfaceEntries(this, config, "INTERFACE_COMPILE_OPTIONS", language,
+ &dagChecker, entries);
- AddInterfaceEntries(this, config, "INTERFACE_COMPILE_OPTIONS",
- linkInterfaceCompileOptionsEntries);
+ processOptions(this, entries, result, uniqueOptions, debugOptions,
+ "compile options", OptionsParse::Shell);
- processCompileOptions(this, linkInterfaceCompileOptionsEntries, result,
- uniqueOptions, &dagChecker, config, debugOptions,
- language);
-
- cmDeleteAll(linkInterfaceCompileOptionsEntries);
+ return result;
}
-static void processCompileFeatures(
- cmGeneratorTarget const* tgt,
- const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
- std::vector<std::string>& options,
- CM_UNORDERED_SET<std::string>& uniqueOptions,
- cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
- bool debugOptions)
+void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result,
+ const std::string& config) const
{
- processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
- dagChecker, config, debugOptions, "features",
- std::string());
+ std::vector<BT<std::string>> tmp = this->GetCompileFeatures(config);
+ result.reserve(tmp.size());
+ for (BT<std::string>& v : tmp) {
+ result.emplace_back(std::move(v.Value));
+ }
}
-void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result,
- const std::string& config) const
+std::vector<BT<std::string>> cmGeneratorTarget::GetCompileFeatures(
+ std::string const& config) const
{
- CM_UNORDERED_SET<std::string> uniqueFeatures;
+ std::vector<BT<std::string>> result;
+ std::unordered_set<std::string> uniqueFeatures;
- cmGeneratorExpressionDAGChecker dagChecker(
- this->GetName(), "COMPILE_FEATURES", CM_NULLPTR, CM_NULLPTR);
+ cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_FEATURES", nullptr,
+ nullptr);
std::vector<std::string> debugProperties;
const char* debugProp =
this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
if (debugProp) {
- cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+ cmExpandList(debugProp, debugProperties);
}
bool debugFeatures = !this->DebugCompileFeaturesDone &&
- std::find(debugProperties.begin(), debugProperties.end(),
- "COMPILE_FEATURES") != debugProperties.end();
+ cmContains(debugProperties, "COMPILE_FEATURES");
if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
this->DebugCompileFeaturesDone = true;
}
- processCompileFeatures(this, this->CompileFeaturesEntries, result,
- uniqueFeatures, &dagChecker, config, debugFeatures);
+ std::vector<EvaluatedTargetPropertyEntry> entries =
+ EvaluateTargetPropertyEntries(this, config, std::string(), &dagChecker,
+ this->CompileFeaturesEntries);
- std::vector<cmGeneratorTarget::TargetPropertyEntry*>
- linkInterfaceCompileFeaturesEntries;
AddInterfaceEntries(this, config, "INTERFACE_COMPILE_FEATURES",
- linkInterfaceCompileFeaturesEntries);
+ std::string(), &dagChecker, entries);
- processCompileFeatures(this, linkInterfaceCompileFeaturesEntries, result,
- uniqueFeatures, &dagChecker, config, debugFeatures);
+ processOptions(this, entries, result, uniqueFeatures, debugFeatures,
+ "compile features", OptionsParse::None);
- cmDeleteAll(linkInterfaceCompileFeaturesEntries);
+ return result;
}
-static void processCompileDefinitions(
- cmGeneratorTarget const* tgt,
- const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
- std::vector<std::string>& options,
- CM_UNORDERED_SET<std::string>& uniqueOptions,
- cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
- bool debugOptions, std::string const& language)
+void cmGeneratorTarget::GetCompileDefinitions(
+ std::vector<std::string>& result, const std::string& config,
+ const std::string& language) const
{
- processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
- dagChecker, config, debugOptions,
- "definitions", language);
+ std::vector<BT<std::string>> tmp =
+ this->GetCompileDefinitions(config, language);
+ result.reserve(tmp.size());
+ for (BT<std::string>& v : tmp) {
+ result.emplace_back(std::move(v.Value));
+ }
}
-void cmGeneratorTarget::GetCompileDefinitions(
- std::vector<std::string>& list, const std::string& config,
- const std::string& language) const
+std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions(
+ std::string const& config, std::string const& language) const
{
- CM_UNORDERED_SET<std::string> uniqueOptions;
+ std::vector<BT<std::string>> list;
+ std::unordered_set<std::string> uniqueOptions;
- cmGeneratorExpressionDAGChecker dagChecker(
- this->GetName(), "COMPILE_DEFINITIONS", CM_NULLPTR, CM_NULLPTR);
+ cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_DEFINITIONS",
+ nullptr, nullptr);
std::vector<std::string> debugProperties;
const char* debugProp =
this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
if (debugProp) {
- cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+ cmExpandList(debugProp, debugProperties);
}
bool debugDefines = !this->DebugCompileDefinitionsDone &&
- std::find(debugProperties.begin(), debugProperties.end(),
- "COMPILE_DEFINITIONS") != debugProperties.end();
+ cmContains(debugProperties, "COMPILE_DEFINITIONS");
if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
this->DebugCompileDefinitionsDone = true;
}
- processCompileDefinitions(this, this->CompileDefinitionsEntries, list,
- uniqueOptions, &dagChecker, config, debugDefines,
- language);
+ std::vector<EvaluatedTargetPropertyEntry> entries =
+ EvaluateTargetPropertyEntries(this, config, language, &dagChecker,
+ this->CompileDefinitionsEntries);
+
+ AddInterfaceEntries(this, config, "INTERFACE_COMPILE_DEFINITIONS", language,
+ &dagChecker, entries);
- std::vector<cmGeneratorTarget::TargetPropertyEntry*>
- linkInterfaceCompileDefinitionsEntries;
- AddInterfaceEntries(this, config, "INTERFACE_COMPILE_DEFINITIONS",
- linkInterfaceCompileDefinitionsEntries);
if (!config.empty()) {
std::string configPropName =
"COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config);
@@ -2841,17 +3271,16 @@ void cmGeneratorTarget::GetCompileDefinitions(
if (configProp) {
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0043)) {
case cmPolicies::WARN: {
- std::ostringstream e;
- e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0043);
- this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ this->LocalGenerator->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0043));
CM_FALLTHROUGH;
}
case cmPolicies::OLD: {
- cmGeneratorExpression ge;
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge =
- ge.Parse(configProp);
- linkInterfaceCompileDefinitionsEntries.push_back(
- new cmGeneratorTarget::TargetPropertyEntry(cge));
+ std::unique_ptr<TargetPropertyEntry> entry(
+ CreateTargetPropertyEntry(configProp));
+ entries.emplace_back(EvaluateTargetPropertyEntry(
+ this, config, language, &dagChecker, entry.get()));
} break;
case cmPolicies::NEW:
case cmPolicies::REQUIRED_ALWAYS:
@@ -2861,11 +3290,662 @@ void cmGeneratorTarget::GetCompileDefinitions(
}
}
- processCompileDefinitions(this, linkInterfaceCompileDefinitionsEntries, list,
- uniqueOptions, &dagChecker, config, debugDefines,
- language);
+ processOptions(this, entries, list, uniqueOptions, debugDefines,
+ "compile definitions", OptionsParse::None);
+
+ return list;
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetPrecompileHeaders(
+ const std::string& config, const std::string& language) const
+{
+ std::unordered_set<std::string> uniqueOptions;
+
+ cmGeneratorExpressionDAGChecker dagChecker(this, "PRECOMPILE_HEADERS",
+ nullptr, nullptr);
+
+ std::vector<std::string> debugProperties;
+ const char* debugProp =
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+ if (debugProp) {
+ cmExpandList(debugProp, debugProperties);
+ }
+
+ bool debugDefines = !this->DebugPrecompileHeadersDone &&
+ std::find(debugProperties.begin(), debugProperties.end(),
+ "PRECOMPILE_HEADERS") != debugProperties.end();
+
+ if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
+ this->DebugPrecompileHeadersDone = true;
+ }
+
+ std::vector<EvaluatedTargetPropertyEntry> entries =
+ EvaluateTargetPropertyEntries(this, config, language, &dagChecker,
+ this->PrecompileHeadersEntries);
+
+ AddInterfaceEntries(this, config, "INTERFACE_PRECOMPILE_HEADERS", language,
+ &dagChecker, entries);
+
+ std::vector<BT<std::string>> list;
+ processOptions(this, entries, list, uniqueOptions, debugDefines,
+ "precompile headers", OptionsParse::None);
+
+ return list;
+}
+
+std::string cmGeneratorTarget::GetPchHeader(const std::string& config,
+ const std::string& language) const
+{
+ if (language != "C" && language != "CXX" && language != "OBJC" &&
+ language != "OBJCXX") {
+ return std::string();
+ }
+
+ if (this->GetPropertyAsBool("DISABLE_PRECOMPILE_HEADERS")) {
+ return std::string();
+ }
+ const cmGeneratorTarget* generatorTarget = this;
+ const char* pchReuseFrom =
+ generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
+
+ const auto inserted =
+ this->PchHeaders.insert(std::make_pair(language + config, ""));
+ if (inserted.second) {
+ const std::vector<BT<std::string>> headers =
+ this->GetPrecompileHeaders(config, language);
+ if (headers.empty() && !pchReuseFrom) {
+ return std::string();
+ }
+ std::string& filename = inserted.first->second;
+
+ if (pchReuseFrom) {
+ generatorTarget =
+ this->GetGlobalGenerator()->FindGeneratorTarget(pchReuseFrom);
+ }
+
+ filename = cmStrCat(
+ generatorTarget->LocalGenerator->GetCurrentBinaryDirectory(), "/");
+
+ const std::map<std::string, std::string> languageToExtension = {
+ { "C", ".h" },
+ { "CXX", ".hxx" },
+ { "OBJC", ".objc.h" },
+ { "OBJCXX", ".objcxx.hxx" }
+ };
+
+ filename = cmStrCat(filename, "CMakeFiles/", generatorTarget->GetName(),
+ ".dir/cmake_pch", languageToExtension.at(language));
+
+ const std::string filename_tmp = cmStrCat(filename, ".tmp");
+ if (!pchReuseFrom) {
+ auto pchPrologue = this->Makefile->GetDefinition("CMAKE_PCH_PROLOGUE");
+ auto pchEpilogue = this->Makefile->GetDefinition("CMAKE_PCH_EPILOGUE");
+
+ {
+ cmGeneratedFileStream file(
+ filename_tmp, false,
+ this->GetGlobalGenerator()->GetMakefileEncoding());
+ file << "/* generated by CMake */\n\n";
+ if (pchPrologue) {
+ file << pchPrologue << "\n";
+ }
+ if (this->GetGlobalGenerator()->IsXcode()) {
+ file << "#ifndef CMAKE_SKIP_PRECOMPILE_HEADERS\n";
+ }
+ if (language == "CXX") {
+ file << "#ifdef __cplusplus\n";
+ }
+ for (auto const& header_bt : headers) {
+ if (header_bt.Value.empty()) {
+ continue;
+ }
+ if (header_bt.Value[0] == '<' || header_bt.Value[0] == '\"') {
+ file << "#include " << header_bt.Value << "\n";
+ } else {
+ file << "#include \"" << header_bt.Value << "\"\n";
+ }
+ }
+ if (language == "CXX") {
+ file << "#endif // __cplusplus\n";
+ }
+ if (this->GetGlobalGenerator()->IsXcode()) {
+ file << "#endif // CMAKE_SKIP_PRECOMPILE_HEADERS\n";
+ }
+ if (pchEpilogue) {
+ file << pchEpilogue << "\n";
+ }
+ }
+ cmSystemTools::MoveFileIfDifferent(filename_tmp, filename);
+ }
+ }
+ return inserted.first->second;
+}
+
+std::string cmGeneratorTarget::GetPchSource(const std::string& config,
+ const std::string& language) const
+{
+ if (language != "C" && language != "CXX" && language != "OBJC" &&
+ language != "OBJCXX") {
+ return std::string();
+ }
+ const auto inserted =
+ this->PchSources.insert(std::make_pair(language + config, ""));
+ if (inserted.second) {
+ const std::string pchHeader = this->GetPchHeader(config, language);
+ if (pchHeader.empty()) {
+ return std::string();
+ }
+ std::string& filename = inserted.first->second;
+
+ const cmGeneratorTarget* generatorTarget = this;
+ const char* pchReuseFrom =
+ generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
+ if (pchReuseFrom) {
+ generatorTarget =
+ this->GetGlobalGenerator()->FindGeneratorTarget(pchReuseFrom);
+ }
+
+ filename =
+ cmStrCat(generatorTarget->LocalGenerator->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/", generatorTarget->GetName(), ".dir/cmake_pch");
+
+ // For GCC the source extension will be tranformed into .h[xx].gch
+ if (!this->Makefile->IsOn("CMAKE_LINK_PCH")) {
+ const std::map<std::string, std::string> languageToExtension = {
+ { "C", ".h.c" },
+ { "CXX", ".hxx.cxx" },
+ { "OBJC", ".objc.h.m" },
+ { "OBJCXX", ".objcxx.hxx.mm" }
+ };
+
+ filename += languageToExtension.at(language);
+ } else {
+ const std::map<std::string, std::string> languageToExtension = {
+ { "C", ".c" }, { "CXX", ".cxx" }, { "OBJC", ".m" }, { "OBJCXX", ".mm" }
+ };
+
+ filename += languageToExtension.at(language);
+ }
- cmDeleteAll(linkInterfaceCompileDefinitionsEntries);
+ const std::string filename_tmp = cmStrCat(filename, ".tmp");
+ if (!pchReuseFrom) {
+ {
+ cmGeneratedFileStream file(filename_tmp);
+ file << "/* generated by CMake */\n";
+ }
+ cmSystemTools::MoveFileIfDifferent(filename_tmp, filename);
+ }
+ }
+ return inserted.first->second;
+}
+
+std::string cmGeneratorTarget::GetPchFileObject(const std::string& config,
+ const std::string& language)
+{
+ if (language != "C" && language != "CXX" && language != "OBJC" &&
+ language != "OBJCXX") {
+ return std::string();
+ }
+ const auto inserted =
+ this->PchObjectFiles.insert(std::make_pair(language + config, ""));
+ if (inserted.second) {
+ const std::string pchSource = this->GetPchSource(config, language);
+ if (pchSource.empty()) {
+ return std::string();
+ }
+ std::string& filename = inserted.first->second;
+
+ this->AddSource(pchSource, true);
+
+ auto pchSf = this->Makefile->GetOrCreateSource(
+ pchSource, false, cmSourceFileLocationKind::Known);
+
+ filename = cmStrCat(this->ObjectDirectory, this->GetObjectName(pchSf));
+ }
+ return inserted.first->second;
+}
+
+std::string cmGeneratorTarget::GetPchFile(const std::string& config,
+ const std::string& language)
+{
+ const auto inserted =
+ this->PchFiles.insert(std::make_pair(language + config, ""));
+ if (inserted.second) {
+ std::string& pchFile = inserted.first->second;
+
+ const std::string pchExtension =
+ this->Makefile->GetSafeDefinition("CMAKE_PCH_EXTENSION");
+
+ if (this->Makefile->IsOn("CMAKE_LINK_PCH")) {
+ auto replaceExtension = [](const std::string& str,
+ const std::string& ext) -> std::string {
+ auto dot_pos = str.rfind('.');
+ std::string result;
+ if (dot_pos != std::string::npos) {
+ result = str.substr(0, dot_pos);
+ }
+ result += ext;
+ return result;
+ };
+
+ cmGeneratorTarget* generatorTarget = this;
+ const char* pchReuseFrom =
+ generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
+ if (pchReuseFrom) {
+ generatorTarget =
+ this->GetGlobalGenerator()->FindGeneratorTarget(pchReuseFrom);
+ }
+
+ const std::string pchFileObject =
+ generatorTarget->GetPchFileObject(config, language);
+ if (!pchExtension.empty()) {
+ pchFile = replaceExtension(pchFileObject, pchExtension);
+ }
+ } else {
+ pchFile = this->GetPchHeader(config, language);
+ pchFile += pchExtension;
+ }
+ }
+ return inserted.first->second;
+}
+
+std::string cmGeneratorTarget::GetPchCreateCompileOptions(
+ const std::string& config, const std::string& language)
+{
+ const auto inserted = this->PchCreateCompileOptions.insert(
+ std::make_pair(language + config, ""));
+ if (inserted.second) {
+ std::string& createOptionList = inserted.first->second;
+
+ const std::string createOptVar =
+ cmStrCat("CMAKE_", language, "_COMPILE_OPTIONS_CREATE_PCH");
+ createOptionList = this->Makefile->GetSafeDefinition(createOptVar);
+
+ const std::string pchHeader = this->GetPchHeader(config, language);
+ const std::string pchFile = this->GetPchFile(config, language);
+
+ cmSystemTools::ReplaceString(createOptionList, "<PCH_HEADER>", pchHeader);
+ cmSystemTools::ReplaceString(createOptionList, "<PCH_FILE>", pchFile);
+ }
+ return inserted.first->second;
+}
+
+std::string cmGeneratorTarget::GetPchUseCompileOptions(
+ const std::string& config, const std::string& language)
+{
+ const auto inserted =
+ this->PchUseCompileOptions.insert(std::make_pair(language + config, ""));
+ if (inserted.second) {
+ std::string& useOptionList = inserted.first->second;
+
+ const std::string useOptVar =
+ cmStrCat("CMAKE_", language, "_COMPILE_OPTIONS_USE_PCH");
+ useOptionList = this->Makefile->GetSafeDefinition(useOptVar);
+
+ const std::string pchHeader = this->GetPchHeader(config, language);
+ const std::string pchFile = this->GetPchFile(config, language);
+
+ cmSystemTools::ReplaceString(useOptionList, "<PCH_HEADER>", pchHeader);
+ cmSystemTools::ReplaceString(useOptionList, "<PCH_FILE>", pchFile);
+ }
+ return inserted.first->second;
+}
+
+void cmGeneratorTarget::AddSourceFileToUnityBatch(
+ const std::string& sourceFilename)
+{
+ this->UnityBatchedSourceFiles.insert(sourceFilename);
+}
+
+bool cmGeneratorTarget::IsSourceFilePartOfUnityBatch(
+ const std::string& sourceFilename) const
+{
+ if (!this->GetPropertyAsBool("UNITY_BUILD")) {
+ return false;
+ }
+
+ return this->UnityBatchedSourceFiles.find(sourceFilename) !=
+ this->UnityBatchedSourceFiles.end();
+}
+
+void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result,
+ const std::string& config,
+ const std::string& language) const
+{
+ std::vector<BT<std::string>> tmp = this->GetLinkOptions(config, language);
+ result.reserve(tmp.size());
+ for (BT<std::string>& v : tmp) {
+ result.emplace_back(std::move(v.Value));
+ }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions(
+ std::string const& config, std::string const& language) const
+{
+ std::vector<BT<std::string>> result;
+ std::unordered_set<std::string> uniqueOptions;
+
+ cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_OPTIONS", nullptr,
+ nullptr);
+
+ std::vector<std::string> debugProperties;
+ const char* debugProp =
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+ if (debugProp) {
+ cmExpandList(debugProp, debugProperties);
+ }
+
+ bool debugOptions =
+ !this->DebugLinkOptionsDone && cmContains(debugProperties, "LINK_OPTIONS");
+
+ if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
+ this->DebugLinkOptionsDone = true;
+ }
+
+ std::vector<EvaluatedTargetPropertyEntry> entries =
+ EvaluateTargetPropertyEntries(this, config, language, &dagChecker,
+ this->LinkOptionsEntries);
+
+ AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS", language,
+ &dagChecker, entries);
+
+ processOptions(this, entries, result, uniqueOptions, debugOptions,
+ "link options", OptionsParse::Shell);
+
+ // Last step: replace "LINKER:" prefixed elements by
+ // actual linker wrapper
+ const std::string wrapper(this->Makefile->GetSafeDefinition(
+ "CMAKE_" + language + "_LINKER_WRAPPER_FLAG"));
+ std::vector<std::string> wrapperFlag = cmExpandedList(wrapper);
+ const std::string wrapperSep(this->Makefile->GetSafeDefinition(
+ "CMAKE_" + language + "_LINKER_WRAPPER_FLAG_SEP"));
+ bool concatFlagAndArgs = true;
+ if (!wrapperFlag.empty() && wrapperFlag.back() == " ") {
+ concatFlagAndArgs = false;
+ wrapperFlag.pop_back();
+ }
+
+ const std::string LINKER{ "LINKER:" };
+ const std::string SHELL{ "SHELL:" };
+ const std::string LINKER_SHELL = LINKER + SHELL;
+
+ std::vector<BT<std::string>>::iterator entry;
+ while ((entry = std::find_if(result.begin(), result.end(),
+ [&LINKER](BT<std::string> const& item) -> bool {
+ return item.Value.compare(0, LINKER.length(),
+ LINKER) == 0;
+ })) != result.end()) {
+ std::string value = std::move(entry->Value);
+ cmListFileBacktrace bt = std::move(entry->Backtrace);
+ entry = result.erase(entry);
+
+ std::vector<std::string> linkerOptions;
+ if (value.compare(0, LINKER_SHELL.length(), LINKER_SHELL) == 0) {
+ cmSystemTools::ParseUnixCommandLine(
+ value.c_str() + LINKER_SHELL.length(), linkerOptions);
+ } else {
+ linkerOptions = cmTokenize(value.substr(LINKER.length()), ",");
+ }
+
+ if (linkerOptions.empty() ||
+ (linkerOptions.size() == 1 && linkerOptions.front().empty())) {
+ continue;
+ }
+
+ // for now, raise an error if prefix SHELL: is part of arguments
+ if (std::find_if(linkerOptions.begin(), linkerOptions.end(),
+ [&SHELL](const std::string& item) -> bool {
+ return item.find(SHELL) != std::string::npos;
+ }) != linkerOptions.end()) {
+ this->LocalGenerator->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "'SHELL:' prefix is not supported as part of 'LINKER:' arguments.",
+ this->GetBacktrace());
+ return result;
+ }
+
+ std::vector<BT<std::string>> options;
+ if (wrapperFlag.empty()) {
+ // nothing specified, insert elements as is
+ options.reserve(linkerOptions.size());
+ for (std::string& o : linkerOptions) {
+ options.emplace_back(std::move(o), bt);
+ }
+ } else {
+ if (!wrapperSep.empty()) {
+ if (concatFlagAndArgs) {
+ // insert flag elements except last one
+ for (auto i = wrapperFlag.begin(); i != wrapperFlag.end() - 1; ++i) {
+ options.emplace_back(*i, bt);
+ }
+ // concatenate last flag element and all LINKER list values
+ // in one option
+ options.emplace_back(
+ wrapperFlag.back() + cmJoin(linkerOptions, wrapperSep), bt);
+ } else {
+ for (std::string const& i : wrapperFlag) {
+ options.emplace_back(i, bt);
+ }
+ // concatenate all LINKER list values in one option
+ options.emplace_back(cmJoin(linkerOptions, wrapperSep), bt);
+ }
+ } else {
+ // prefix each element of LINKER list with wrapper
+ if (concatFlagAndArgs) {
+ std::transform(linkerOptions.begin(), linkerOptions.end(),
+ linkerOptions.begin(),
+ [&wrapperFlag](std::string const& o) -> std::string {
+ return wrapperFlag.back() + o;
+ });
+ }
+ for (std::string& o : linkerOptions) {
+ for (auto i = wrapperFlag.begin(),
+ e = concatFlagAndArgs ? wrapperFlag.end() - 1
+ : wrapperFlag.end();
+ i != e; ++i) {
+ options.emplace_back(*i, bt);
+ }
+ options.emplace_back(std::move(o), bt);
+ }
+ }
+ }
+ result.insert(entry, options.begin(), options.end());
+ }
+ return result;
+}
+
+void cmGeneratorTarget::GetStaticLibraryLinkOptions(
+ std::vector<std::string>& result, const std::string& config,
+ const std::string& language) const
+{
+ std::vector<BT<std::string>> tmp =
+ this->GetStaticLibraryLinkOptions(config, language);
+ result.reserve(tmp.size());
+ for (BT<std::string>& v : tmp) {
+ result.emplace_back(std::move(v.Value));
+ }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetStaticLibraryLinkOptions(
+ std::string const& config, std::string const& language) const
+{
+ std::vector<BT<std::string>> result;
+ std::unordered_set<std::string> uniqueOptions;
+
+ cmGeneratorExpressionDAGChecker dagChecker(this, "STATIC_LIBRARY_OPTIONS",
+ nullptr, nullptr);
+
+ std::vector<EvaluatedTargetPropertyEntry> entries;
+ if (const char* linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) {
+ std::vector<std::string> options = cmExpandedList(linkOptions);
+ for (const auto& option : options) {
+ std::unique_ptr<TargetPropertyEntry> entry(
+ CreateTargetPropertyEntry(option));
+ entries.emplace_back(EvaluateTargetPropertyEntry(
+ this, config, language, &dagChecker, entry.get()));
+ }
+ }
+ processOptions(this, entries, result, uniqueOptions, false,
+ "static library link options", OptionsParse::Shell);
+
+ return result;
+}
+
+namespace {
+void processLinkDirectories(cmGeneratorTarget const* tgt,
+ std::vector<EvaluatedTargetPropertyEntry>& entries,
+ std::vector<BT<std::string>>& directories,
+ std::unordered_set<std::string>& uniqueDirectories,
+ bool debugDirectories)
+{
+ for (EvaluatedTargetPropertyEntry& entry : entries) {
+ cmLinkImplItem const& item = entry.LinkImplItem;
+ std::string const& targetName = item.AsStr();
+
+ std::string usedDirectories;
+ for (std::string& entryDirectory : entry.Values) {
+ if (!cmSystemTools::FileIsFullPath(entryDirectory)) {
+ std::ostringstream e;
+ bool noMessage = false;
+ MessageType messageType = MessageType::FATAL_ERROR;
+ if (!targetName.empty()) {
+ /* clang-format off */
+ e << "Target \"" << targetName << "\" contains relative "
+ "path in its INTERFACE_LINK_DIRECTORIES:\n"
+ " \"" << entryDirectory << "\"";
+ /* clang-format on */
+ } else {
+ switch (tgt->GetPolicyStatusCMP0081()) {
+ case cmPolicies::WARN: {
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0081) << "\n";
+ messageType = MessageType::AUTHOR_WARNING;
+ } break;
+ case cmPolicies::OLD:
+ noMessage = true;
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Issue the fatal message.
+ break;
+ }
+ e << "Found relative path while evaluating link directories of "
+ "\""
+ << tgt->GetName() << "\":\n \"" << entryDirectory << "\"\n";
+ }
+ if (!noMessage) {
+ tgt->GetLocalGenerator()->IssueMessage(messageType, e.str());
+ if (messageType == MessageType::FATAL_ERROR) {
+ return;
+ }
+ }
+ }
+
+ // Sanitize the path the same way the link_directories command does
+ // in case projects set the LINK_DIRECTORIES property directly.
+ cmSystemTools::ConvertToUnixSlashes(entryDirectory);
+ if (uniqueDirectories.insert(entryDirectory).second) {
+ directories.emplace_back(entryDirectory, entry.Backtrace);
+ if (debugDirectories) {
+ usedDirectories += " * " + entryDirectory + "\n";
+ }
+ }
+ }
+ if (!usedDirectories.empty()) {
+ tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
+ MessageType::LOG,
+ std::string("Used link directories for target ") + tgt->GetName() +
+ ":\n" + usedDirectories,
+ entry.Backtrace);
+ }
+ }
+}
+}
+
+void cmGeneratorTarget::GetLinkDirectories(std::vector<std::string>& result,
+ const std::string& config,
+ const std::string& language) const
+{
+ std::vector<BT<std::string>> tmp =
+ this->GetLinkDirectories(config, language);
+ result.reserve(tmp.size());
+ for (BT<std::string>& v : tmp) {
+ result.emplace_back(std::move(v.Value));
+ }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDirectories(
+ std::string const& config, std::string const& language) const
+{
+ std::vector<BT<std::string>> result;
+ std::unordered_set<std::string> uniqueDirectories;
+
+ cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DIRECTORIES", nullptr,
+ nullptr);
+
+ std::vector<std::string> debugProperties;
+ const char* debugProp =
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+ if (debugProp) {
+ cmExpandList(debugProp, debugProperties);
+ }
+
+ bool debugDirectories = !this->DebugLinkDirectoriesDone &&
+ cmContains(debugProperties, "LINK_DIRECTORIES");
+
+ if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
+ this->DebugLinkDirectoriesDone = true;
+ }
+
+ std::vector<EvaluatedTargetPropertyEntry> entries =
+ EvaluateTargetPropertyEntries(this, config, language, &dagChecker,
+ this->LinkDirectoriesEntries);
+
+ AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES", language,
+ &dagChecker, entries);
+
+ processLinkDirectories(this, entries, result, uniqueDirectories,
+ debugDirectories);
+
+ return result;
+}
+
+void cmGeneratorTarget::GetLinkDepends(std::vector<std::string>& result,
+ const std::string& config,
+ const std::string& language) const
+{
+ std::vector<BT<std::string>> tmp = this->GetLinkDepends(config, language);
+ result.reserve(tmp.size());
+ for (BT<std::string>& v : tmp) {
+ result.emplace_back(std::move(v.Value));
+ }
+}
+
+std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends(
+ std::string const& config, std::string const& language) const
+{
+ std::vector<BT<std::string>> result;
+ std::unordered_set<std::string> uniqueOptions;
+ cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DEPENDS", nullptr,
+ nullptr);
+
+ std::vector<EvaluatedTargetPropertyEntry> entries;
+ if (const char* linkDepends = this->GetProperty("LINK_DEPENDS")) {
+ std::vector<std::string> depends = cmExpandedList(linkDepends);
+ for (const auto& depend : depends) {
+ std::unique_ptr<TargetPropertyEntry> entry(
+ CreateTargetPropertyEntry(depend));
+ entries.emplace_back(EvaluateTargetPropertyEntry(
+ this, config, language, &dagChecker, entry.get()));
+ }
+ }
+ AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS", language,
+ &dagChecker, entries);
+
+ processOptions(this, entries, result, uniqueOptions, false, "link depends",
+ OptionsParse::None);
+
+ return result;
}
void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
@@ -2876,17 +3956,13 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
cmGlobalGenerator* gg = this->LocalGenerator->GetGlobalGenerator();
// Get the names.
- std::string name;
- std::string soName;
- std::string realName;
- std::string impName;
- std::string pdbName;
+ cmGeneratorTarget::Names targetNames;
if (this->GetType() == cmStateEnums::EXECUTABLE) {
- this->GetExecutableNames(name, realName, impName, pdbName, config);
+ targetNames = this->GetExecutableNames(config);
} else if (this->GetType() == cmStateEnums::STATIC_LIBRARY ||
this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::MODULE_LIBRARY) {
- this->GetLibraryNames(name, soName, realName, impName, pdbName, config);
+ targetNames = this->GetLibraryNames(config);
} else {
return;
}
@@ -2897,45 +3973,35 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
// Add each name.
std::string f;
- if (!name.empty()) {
- f = dir;
- f += "/";
- f += name;
+ if (!targetNames.Output.empty()) {
+ f = cmStrCat(dir, '/', targetNames.Output);
gg->AddToManifest(f);
}
- if (!soName.empty()) {
- f = dir;
- f += "/";
- f += soName;
+ if (!targetNames.SharedObject.empty()) {
+ f = cmStrCat(dir, '/', targetNames.SharedObject);
gg->AddToManifest(f);
}
- if (!realName.empty()) {
- f = dir;
- f += "/";
- f += realName;
+ if (!targetNames.Real.empty()) {
+ f = cmStrCat(dir, '/', targetNames.Real);
gg->AddToManifest(f);
}
- if (!pdbName.empty()) {
- f = dir;
- f += "/";
- f += pdbName;
+ if (!targetNames.PDB.empty()) {
+ f = cmStrCat(dir, '/', targetNames.PDB);
gg->AddToManifest(f);
}
- if (!impName.empty()) {
- f = this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact);
- f += "/";
- f += impName;
+ if (!targetNames.ImportLibrary.empty()) {
+ f =
+ cmStrCat(this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact),
+ '/', targetNames.ImportLibrary);
gg->AddToManifest(f);
}
}
bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const
{
- std::vector<std::string> features;
- this->GetCompileFeatures(features, config);
- for (std::vector<std::string>::const_iterator it = features.begin();
- it != features.end(); ++it) {
- if (!this->Makefile->AddRequiredTargetFeature(this->Target, *it)) {
+ std::vector<BT<std::string>> features = this->GetCompileFeatures(config);
+ for (BT<std::string> const& f : features) {
+ if (!this->Makefile->AddRequiredTargetFeature(this->Target, f.Value)) {
return false;
}
}
@@ -2966,11 +4032,10 @@ std::string cmGeneratorTarget::NormalGetFullPath(
const std::string& config, cmStateEnums::ArtifactType artifact,
bool realname) const
{
- std::string fpath = this->GetDirectory(config, artifact);
- fpath += "/";
+ std::string fpath = cmStrCat(this->GetDirectory(config, artifact), '/');
if (this->IsAppBundleOnApple()) {
- fpath = this->BuildBundleDirectory(fpath, config, FullLevel);
- fpath += "/";
+ fpath =
+ cmStrCat(this->BuildBundleDirectory(fpath, config, FullLevel), '/');
}
// Add the full name of the target.
@@ -2997,44 +4062,31 @@ std::string cmGeneratorTarget::NormalGetRealName(
// TODO: Split cmTarget into a class hierarchy to get compile-time
// enforcement of the limited imported target API.
if (this->IsImported()) {
- std::string msg = "NormalGetRealName called on imported target: ";
- msg += this->GetName();
- this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg);
+ std::string msg = cmStrCat("NormalGetRealName called on imported target: ",
+ this->GetName());
+ this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
}
if (this->GetType() == cmStateEnums::EXECUTABLE) {
// Compute the real name that will be built.
- std::string name;
- std::string realName;
- std::string impName;
- std::string pdbName;
- this->GetExecutableNames(name, realName, impName, pdbName, config);
- return realName;
+ return this->GetExecutableNames(config).Real;
}
// Compute the real name that will be built.
- std::string name;
- std::string soName;
- std::string realName;
- std::string impName;
- std::string pdbName;
- this->GetLibraryNames(name, soName, realName, impName, pdbName, config);
- return realName;
-}
-
-void cmGeneratorTarget::GetLibraryNames(std::string& name, std::string& soName,
- std::string& realName,
- std::string& impName,
- std::string& pdbName,
- const std::string& config) const
+ return this->GetLibraryNames(config).Real;
+}
+
+cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames(
+ const std::string& config) const
{
+ cmGeneratorTarget::Names targetNames;
+
// This should not be called for imported targets.
// TODO: Split cmTarget into a class hierarchy to get compile-time
// enforcement of the limited imported target API.
if (this->IsImported()) {
- std::string msg = "GetLibraryNames called on imported target: ";
- msg += this->GetName();
- this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg);
- return;
+ std::string msg =
+ cmStrCat("GetLibraryNames called on imported target: ", this->GetName());
+ this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
}
// Check for library version properties.
@@ -3045,8 +4097,8 @@ void cmGeneratorTarget::GetLibraryNames(std::string& name, std::string& soName,
this->IsFrameworkOnApple()) {
// Versioning is supported only for shared libraries and modules,
// and then only when the platform supports an soname flag.
- version = CM_NULLPTR;
- soversion = CM_NULLPTR;
+ version = nullptr;
+ soversion = nullptr;
}
if (version && !soversion) {
// The soversion must be set if the library version is set. Use
@@ -3060,57 +4112,58 @@ void cmGeneratorTarget::GetLibraryNames(std::string& name, std::string& soName,
// Get the components of the library name.
std::string prefix;
- std::string base;
std::string suffix;
this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
- prefix, base, suffix);
+ prefix, targetNames.Base, suffix);
// The library name.
- name = prefix + base + suffix;
+ targetNames.Output = prefix + targetNames.Base + suffix;
if (this->IsFrameworkOnApple()) {
- realName = prefix;
- if (!this->Makefile->PlatformIsAppleIos()) {
- realName += "Versions/";
- realName += this->GetFrameworkVersion();
- realName += "/";
- }
- realName += base;
- soName = realName;
+ targetNames.Real = prefix;
+ if (!this->Makefile->PlatformIsAppleEmbedded()) {
+ targetNames.Real += "Versions/";
+ targetNames.Real += this->GetFrameworkVersion();
+ targetNames.Real += "/";
+ }
+ targetNames.Real += targetNames.Base;
+ targetNames.SharedObject = targetNames.Real;
} else {
// The library's soname.
- this->ComputeVersionedName(soName, prefix, base, suffix, name, soversion);
+ this->ComputeVersionedName(targetNames.SharedObject, prefix,
+ targetNames.Base, suffix, targetNames.Output,
+ soversion);
// The library's real name on disk.
- this->ComputeVersionedName(realName, prefix, base, suffix, name, version);
+ this->ComputeVersionedName(targetNames.Real, prefix, targetNames.Base,
+ suffix, targetNames.Output, version);
}
// The import library name.
if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::MODULE_LIBRARY) {
- impName =
+ targetNames.ImportLibrary =
this->GetFullNameInternal(config, cmStateEnums::ImportLibraryArtifact);
- } else {
- impName = "";
}
// The program database file name.
- pdbName = this->GetPDBName(config);
+ targetNames.PDB = this->GetPDBName(config);
+
+ return targetNames;
}
-void cmGeneratorTarget::GetExecutableNames(std::string& name,
- std::string& realName,
- std::string& impName,
- std::string& pdbName,
- const std::string& config) const
+cmGeneratorTarget::Names cmGeneratorTarget::GetExecutableNames(
+ const std::string& config) const
{
+ cmGeneratorTarget::Names targetNames;
+
// This should not be called for imported targets.
// TODO: Split cmTarget into a class hierarchy to get compile-time
// enforcement of the limited imported target API.
if (this->IsImported()) {
- std::string msg = "GetExecutableNames called on imported target: ";
- msg += this->GetName();
- this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg);
+ std::string msg = cmStrCat(
+ "GetExecutableNames called on imported target: ", this->GetName());
+ this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
}
// This versioning is supported only for executables and then only
@@ -3122,40 +4175,41 @@ void cmGeneratorTarget::GetExecutableNames(std::string& name,
const char* version = this->GetProperty("VERSION");
if (this->GetType() != cmStateEnums::EXECUTABLE ||
this->Makefile->IsOn("XCODE")) {
- version = CM_NULLPTR;
+ version = nullptr;
}
#endif
// Get the components of the executable name.
std::string prefix;
- std::string base;
std::string suffix;
this->GetFullNameInternal(config, cmStateEnums::RuntimeBinaryArtifact,
- prefix, base, suffix);
+ prefix, targetNames.Base, suffix);
// The executable name.
- name = prefix + base + suffix;
+ targetNames.Output = prefix + targetNames.Base + suffix;
// The executable's real name on disk.
#if defined(__CYGWIN__)
- realName = prefix + base;
+ targetNames.Real = prefix + targetNames.Base;
#else
- realName = name;
+ targetNames.Real = targetNames.Output;
#endif
if (version) {
- realName += "-";
- realName += version;
+ targetNames.Real += "-";
+ targetNames.Real += version;
}
#if defined(__CYGWIN__)
- realName += suffix;
+ targetNames.Real += suffix;
#endif
// The import library name.
- impName =
+ targetNames.ImportLibrary =
this->GetFullNameInternal(config, cmStateEnums::ImportLibraryArtifact);
// The program database file name.
- pdbName = this->GetPDBName(config);
+ targetNames.PDB = this->GetPDBName(config);
+
+ return targetNames;
}
std::string cmGeneratorTarget::GetFullNameInternal(
@@ -3168,14 +4222,12 @@ std::string cmGeneratorTarget::GetFullNameInternal(
return prefix + base + suffix;
}
-const char* cmGeneratorTarget::ImportedGetLocation(
+std::string cmGeneratorTarget::ImportedGetLocation(
const std::string& config) const
{
- static std::string location;
assert(this->IsImported());
- location = this->Target->ImportedGetFullPath(
+ return this->Target->ImportedGetFullPath(
config, cmStateEnums::RuntimeBinaryArtifact);
- return location.c_str();
}
std::string cmGeneratorTarget::GetFullNameImported(
@@ -3194,9 +4246,9 @@ void cmGeneratorTarget::GetFullNameInternal(
this->GetType() != cmStateEnums::SHARED_LIBRARY &&
this->GetType() != cmStateEnums::MODULE_LIBRARY &&
this->GetType() != cmStateEnums::EXECUTABLE) {
- outPrefix = "";
+ outPrefix.clear();
outBase = this->GetName();
- outSuffix = "";
+ outSuffix.clear();
return;
}
@@ -3205,14 +4257,18 @@ void cmGeneratorTarget::GetFullNameInternal(
// Return an empty name for the import library if this platform
// does not support import libraries.
- if (isImportedLibraryArtifact &&
- !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
- outPrefix = "";
- outBase = "";
- outSuffix = "";
+ if (isImportedLibraryArtifact && !this->NeedImportLibraryName(config)) {
+ outPrefix.clear();
+ outBase.clear();
+ outSuffix.clear();
return;
}
+ // retrieve prefix and suffix
+ std::string ll = this->GetLinkerLanguage(config);
+ const char* targetPrefix = this->GetFilePrefixInternal(config, artifact, ll);
+ const char* targetSuffix = this->GetFileSuffixInternal(config, artifact, ll);
+
// The implib option is only allowed for shared libraries, module
// libraries, and executables.
if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
@@ -3222,62 +4278,21 @@ void cmGeneratorTarget::GetFullNameInternal(
}
// Compute the full name for main target types.
- const char* targetPrefix =
- (isImportedLibraryArtifact ? this->GetProperty("IMPORT_PREFIX")
- : this->GetProperty("PREFIX"));
- const char* targetSuffix =
- (isImportedLibraryArtifact ? this->GetProperty("IMPORT_SUFFIX")
- : this->GetProperty("SUFFIX"));
- const char* configPostfix = CM_NULLPTR;
- if (!config.empty()) {
- std::string configProp = cmSystemTools::UpperCase(config);
- configProp += "_POSTFIX";
- configPostfix = this->GetProperty(configProp);
- // Mac application bundles and frameworks have no postfix.
- if (configPostfix &&
- (this->IsAppBundleOnApple() || this->IsFrameworkOnApple())) {
- configPostfix = CM_NULLPTR;
- }
- }
- const char* prefixVar = this->Target->GetPrefixVariableInternal(artifact);
- const char* suffixVar = this->Target->GetSuffixVariableInternal(artifact);
-
- // Check for language-specific default prefix and suffix.
- std::string ll = this->GetLinkerLanguage(config);
- if (!ll.empty()) {
- if (!targetSuffix && suffixVar && *suffixVar) {
- std::string langSuff = suffixVar + std::string("_") + ll;
- targetSuffix = this->Makefile->GetDefinition(langSuff);
- }
- if (!targetPrefix && prefixVar && *prefixVar) {
- std::string langPrefix = prefixVar + std::string("_") + ll;
- targetPrefix = this->Makefile->GetDefinition(langPrefix);
- }
- }
-
- // if there is no prefix on the target use the cmake definition
- if (!targetPrefix && prefixVar) {
- targetPrefix = this->Makefile->GetSafeDefinition(prefixVar);
- }
- // if there is no suffix on the target use the cmake definition
- if (!targetSuffix && suffixVar) {
- targetSuffix = this->Makefile->GetSafeDefinition(suffixVar);
- }
+ const std::string configPostfix = this->GetFilePostfix(config);
// frameworks have directory prefix but no suffix
std::string fw_prefix;
if (this->IsFrameworkOnApple()) {
- fw_prefix = this->GetFrameworkDirectory(config, ContentLevel);
- fw_prefix += "/";
+ fw_prefix =
+ cmStrCat(this->GetFrameworkDirectory(config, ContentLevel), '/');
targetPrefix = fw_prefix.c_str();
- targetSuffix = CM_NULLPTR;
+ targetSuffix = nullptr;
}
if (this->IsCFBundleOnApple()) {
- fw_prefix = this->GetCFBundleDirectory(config, FullLevel);
- fw_prefix += "/";
+ fw_prefix = cmStrCat(this->GetCFBundleDirectory(config, FullLevel), '/');
targetPrefix = fw_prefix.c_str();
- targetSuffix = CM_NULLPTR;
+ targetSuffix = nullptr;
}
// Begin the final name with the prefix.
@@ -3287,7 +4302,7 @@ void cmGeneratorTarget::GetFullNameInternal(
outBase += this->GetOutputName(config, artifact);
// Append the per-configuration postfix.
- outBase += configPostfix ? configPostfix : "";
+ outBase += configPostfix;
// Name shared libraries with their version number on some platforms.
if (const char* soversion = this->GetProperty("SOVERSION")) {
@@ -3309,6 +4324,31 @@ std::string cmGeneratorTarget::GetLinkerLanguage(
return this->GetLinkClosure(config)->LinkerLanguage;
}
+std::string cmGeneratorTarget::GetPDBOutputName(
+ const std::string& config) const
+{
+ std::string base =
+ this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact);
+
+ std::vector<std::string> props;
+ std::string configUpper = cmSystemTools::UpperCase(config);
+ if (!configUpper.empty()) {
+ // PDB_NAME_<CONFIG>
+ props.push_back("PDB_NAME_" + configUpper);
+ }
+
+ // PDB_NAME
+ props.emplace_back("PDB_NAME");
+
+ for (std::string const& p : props) {
+ if (const char* outName = this->GetProperty(p)) {
+ base = outName;
+ break;
+ }
+ }
+ return base;
+}
+
std::string cmGeneratorTarget::GetPDBName(const std::string& config) const
{
std::string prefix;
@@ -3325,11 +4365,10 @@ std::string cmGeneratorTarget::GetPDBName(const std::string& config) const
}
// PDB_NAME
- props.push_back("PDB_NAME");
+ props.emplace_back("PDB_NAME");
- for (std::vector<std::string>::const_iterator i = props.begin();
- i != props.end(); ++i) {
- if (const char* outName = this->GetProperty(*i)) {
+ for (std::string const& p : props) {
+ if (const char* outName = this->GetProperty(p)) {
base = outName;
break;
}
@@ -3346,6 +4385,13 @@ std::string cmGeneratorTarget::GetObjectDirectory(
// find and replace $(PROJECT_NAME) xcode placeholder
const std::string projectName = this->LocalGenerator->GetProjectName();
cmSystemTools::ReplaceString(obj_dir, "$(PROJECT_NAME)", projectName);
+ // Replace Xcode's placeholder for the object file directory since
+ // installation and export scripts need to know the real directory.
+ // Xcode has build-time settings (e.g. for sanitizers) that affect this,
+ // but we use the default here. Users that want to enable sanitizers
+ // will do so at the cost of object library installation and export.
+ cmSystemTools::ReplaceString(obj_dir, "$(OBJECT_FILE_DIR_normal:base)",
+ "Objects-normal");
#endif
return obj_dir;
}
@@ -3357,20 +4403,15 @@ void cmGeneratorTarget::GetTargetObjectNames(
this->GetObjectSources(objectSources, config);
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* sf : objectSources) {
+ mapping[sf];
}
this->LocalGenerator->ComputeObjectFilenames(mapping, this);
- for (std::vector<cmSourceFile const*>::const_iterator it =
- objectSources.begin();
- it != objectSources.end(); ++it) {
+ for (cmSourceFile const* src : objectSources) {
// Find the object file name corresponding to this source file.
- std::map<cmSourceFile const*, std::string>::const_iterator map_it =
- mapping.find(*it);
+ auto map_it = mapping.find(src);
// It must exist because we populated the mapping just above.
assert(!map_it->second.empty());
objects.push_back(map_it->second);
@@ -3382,8 +4423,9 @@ bool cmGeneratorTarget::StrictTargetComparison::operator()(
{
int nameResult = strcmp(t1->GetName().c_str(), t2->GetName().c_str());
if (nameResult == 0) {
- return strcmp(t1->GetLocalGenerator()->GetCurrentBinaryDirectory(),
- t2->GetLocalGenerator()->GetCurrentBinaryDirectory()) < 0;
+ return strcmp(
+ t1->GetLocalGenerator()->GetCurrentBinaryDirectory().c_str(),
+ t2->GetLocalGenerator()->GetCurrentBinaryDirectory().c_str()) < 0;
}
return nameResult < 0;
}
@@ -3393,8 +4435,7 @@ cmGeneratorTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const
{
struct SourceFileFlags flags;
this->ConstructSourceFileFlags();
- std::map<cmSourceFile const*, SourceFileFlags>::iterator si =
- this->SourceFlagsMap.find(sf);
+ auto si = this->SourceFlagsMap.find(sf);
if (si != this->SourceFlagsMap.end()) {
flags = si->second;
} else {
@@ -3409,7 +4450,7 @@ cmGeneratorTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const
if (stripResources) {
flags.MacFolder = "";
}
- } else if (cmSystemTools::StringStartsWith(location, "Resources/")) {
+ } else if (cmHasLiteralPrefix(location, "Resources/")) {
flags.Type = cmGeneratorTarget::SourceFileTypeDeepResource;
if (stripResources) {
flags.MacFolder += strlen("Resources/");
@@ -3431,11 +4472,9 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const
// Process public headers to mark the source files.
if (const char* files = this->GetProperty("PUBLIC_HEADER")) {
- std::vector<std::string> relFiles;
- cmSystemTools::ExpandListArgument(files, relFiles);
- for (std::vector<std::string>::iterator it = relFiles.begin();
- it != relFiles.end(); ++it) {
- if (cmSourceFile* sf = this->Makefile->GetSource(*it)) {
+ std::vector<std::string> relFiles = cmExpandedList(files);
+ for (std::string const& relFile : relFiles) {
+ if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) {
SourceFileFlags& flags = this->SourceFlagsMap[sf];
flags.MacFolder = "Headers";
flags.Type = cmGeneratorTarget::SourceFileTypePublicHeader;
@@ -3446,11 +4485,9 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const
// Process private headers after public headers so that they take
// precedence if a file is listed in both.
if (const char* files = this->GetProperty("PRIVATE_HEADER")) {
- std::vector<std::string> relFiles;
- cmSystemTools::ExpandListArgument(files, relFiles);
- for (std::vector<std::string>::iterator it = relFiles.begin();
- it != relFiles.end(); ++it) {
- if (cmSourceFile* sf = this->Makefile->GetSource(*it)) {
+ std::vector<std::string> relFiles = cmExpandedList(files);
+ for (std::string const& relFile : relFiles) {
+ if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) {
SourceFileFlags& flags = this->SourceFlagsMap[sf];
flags.MacFolder = "PrivateHeaders";
flags.Type = cmGeneratorTarget::SourceFileTypePrivateHeader;
@@ -3460,11 +4497,9 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const
// Mark sources listed as resources.
if (const char* files = this->GetProperty("RESOURCE")) {
- std::vector<std::string> relFiles;
- cmSystemTools::ExpandListArgument(files, relFiles);
- for (std::vector<std::string>::iterator it = relFiles.begin();
- it != relFiles.end(); ++it) {
- if (cmSourceFile* sf = this->Makefile->GetSource(*it)) {
+ std::vector<std::string> relFiles = cmExpandedList(files);
+ for (std::string const& relFile : relFiles) {
+ if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) {
SourceFileFlags& flags = this->SourceFlagsMap[sf];
flags.MacFolder = "";
if (!this->GlobalGenerator->ShouldStripResourcePath(this->Makefile)) {
@@ -3487,13 +4522,11 @@ cmGeneratorTarget::GetCompatibleInterfaces(std::string const& config) const
compat.PropsString.insert("AUTOUIC_OPTIONS");
std::vector<cmGeneratorTarget const*> const& deps =
this->GetLinkImplementationClosure(config);
- for (std::vector<cmGeneratorTarget const*>::const_iterator li =
- deps.begin();
- li != deps.end(); ++li) {
+ for (cmGeneratorTarget const* li : deps) {
#define CM_READ_COMPATIBLE_INTERFACE(X, x) \
- if (const char* prop = (*li)->GetProperty("COMPATIBLE_INTERFACE_" #X)) { \
+ if (const char* prop = li->GetProperty("COMPATIBLE_INTERFACE_" #X)) { \
std::vector<std::string> props; \
- cmSystemTools::ExpandListArgument(prop, props); \
+ cmExpandList(prop, props); \
compat.Props##x.insert(props.begin(), props.end()); \
}
CM_READ_COMPATIBLE_INTERFACE(BOOL, Bool)
@@ -3581,7 +4614,7 @@ const char* getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
case BoolType:
assert(false &&
"String compatibility check function called for boolean");
- return CM_NULLPTR;
+ return nullptr;
case StringType:
return tgt->GetLinkInterfaceDependentStringProperty(prop, config);
case NumberMinType:
@@ -3590,7 +4623,7 @@ const char* getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
return tgt->GetLinkInterfaceDependentNumberMaxProperty(prop, config);
}
assert(false && "Unreachable!");
- return CM_NULLPTR;
+ return nullptr;
}
template <typename PropertyType>
@@ -3606,29 +4639,28 @@ void checkPropertyConsistency(cmGeneratorTarget const* depender,
return;
}
- std::vector<std::string> props;
- cmSystemTools::ExpandListArgument(prop, props);
- std::string pdir = cmSystemTools::GetCMakeRoot();
- pdir += "/Help/prop_tgt/";
+ std::vector<std::string> props = cmExpandedList(prop);
+ std::string pdir =
+ cmStrCat(cmSystemTools::GetCMakeRoot(), "/Help/prop_tgt/");
- for (std::vector<std::string>::iterator pi = props.begin();
- pi != props.end(); ++pi) {
- std::string pname = cmSystemTools::HelpFileName(*pi);
+ 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 \"" << *pi
+ e << "Target \"" << dependee->GetName() << "\" has property \"" << p
<< "\" listed in its " << propName
<< " property. "
"This is not allowed. Only user-defined properties may appear "
"listed in the "
<< propName << " property.";
- depender->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, e.str());
+ depender->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
+ e.str());
return;
}
- if (emitted.insert(*pi).second) {
- getLinkInterfaceDependentProperty<PropertyType>(depender, *pi, config, t,
- CM_NULLPTR);
+ if (emitted.insert(p).second) {
+ getLinkInterfaceDependentProperty<PropertyType>(depender, p, config, t,
+ nullptr);
if (cmSystemTools::GetErrorOccuredFlag()) {
return;
}
@@ -3636,8 +4668,9 @@ void checkPropertyConsistency(cmGeneratorTarget const* depender,
}
}
-static std::string intersect(const std::set<std::string>& s1,
- const std::set<std::string>& s2)
+namespace {
+std::string intersect(const std::set<std::string>& s1,
+ const std::set<std::string>& s2)
{
std::set<std::string> intersect;
std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(),
@@ -3648,9 +4681,9 @@ static std::string intersect(const std::set<std::string>& s1,
return "";
}
-static std::string intersect(const std::set<std::string>& s1,
- const std::set<std::string>& s2,
- const std::set<std::string>& s3)
+std::string intersect(const std::set<std::string>& s1,
+ const std::set<std::string>& s2,
+ const std::set<std::string>& s3)
{
std::string result;
result = intersect(s1, s2);
@@ -3664,10 +4697,10 @@ static std::string intersect(const std::set<std::string>& s1,
return intersect(s2, s3);
}
-static std::string intersect(const std::set<std::string>& s1,
- const std::set<std::string>& s2,
- const std::set<std::string>& s3,
- const std::set<std::string>& s4)
+std::string intersect(const std::set<std::string>& s1,
+ const std::set<std::string>& s2,
+ const std::set<std::string>& s3,
+ const std::set<std::string>& s4)
{
std::string result;
result = intersect(s1, s2);
@@ -3684,6 +4717,7 @@ static std::string intersect(const std::set<std::string>& s1,
}
return intersect(s2, s3, s4);
}
+}
void cmGeneratorTarget::CheckPropertyCompatibility(
cmComputeLinkInformation* info, const std::string& config) const
@@ -3691,40 +4725,39 @@ 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 (cmComputeLinkInformation::ItemVector::const_iterator li = deps.begin();
- li != deps.end(); ++li) {
- if (!li->Target) {
+ for (auto const& dep : deps) {
+ if (!dep.Target) {
continue;
}
- checkPropertyConsistency<bool>(this, li->Target, strBool, emittedBools,
- config, BoolType, CM_NULLPTR);
+ checkPropertyConsistency<bool>(this, dep.Target, strBool, emittedBools,
+ config, BoolType, nullptr);
if (cmSystemTools::GetErrorOccuredFlag()) {
return;
}
- checkPropertyConsistency<const char*>(this, li->Target, strString,
+ checkPropertyConsistency<const char*>(this, dep.Target, strString,
emittedStrings, config, StringType,
- CM_NULLPTR);
+ nullptr);
if (cmSystemTools::GetErrorOccuredFlag()) {
return;
}
- checkPropertyConsistency<const char*>(this, li->Target, strNumMin,
+ checkPropertyConsistency<const char*>(this, dep.Target, strNumMin,
emittedMinNumbers, config,
- NumberMinType, CM_NULLPTR);
+ NumberMinType, nullptr);
if (cmSystemTools::GetErrorOccuredFlag()) {
return;
}
- checkPropertyConsistency<const char*>(this, li->Target, strNumMax,
+ checkPropertyConsistency<const char*>(this, dep.Target, strNumMax,
emittedMaxNumbers, config,
- NumberMaxType, CM_NULLPTR);
+ NumberMaxType, nullptr);
if (cmSystemTools::GetErrorOccuredFlag()) {
return;
}
@@ -3736,7 +4769,7 @@ void cmGeneratorTarget::CheckPropertyCompatibility(
if (!prop.empty()) {
// Use a sorted std::vector to keep the error message sorted.
std::vector<std::string> props;
- std::set<std::string>::const_iterator i = emittedBools.find(prop);
+ auto i = emittedBools.find(prop);
if (i != emittedBools.end()) {
props.push_back(strBool);
}
@@ -3754,8 +4787,8 @@ void cmGeneratorTarget::CheckPropertyCompatibility(
}
std::sort(props.begin(), props.end());
- std::string propsString = cmJoin(cmMakeRange(props).retreat(1), ", ");
- propsString += " and the " + props.back();
+ std::string propsString = cmStrCat(
+ cmJoin(cmMakeRange(props).retreat(1), ", "), " and the ", props.back());
std::ostringstream e;
e << "Property \"" << prop << "\" appears in both the " << propsString
@@ -3764,10 +4797,33 @@ void cmGeneratorTarget::CheckPropertyCompatibility(
"in a boolean interpretation, a numeric minimum, a numeric maximum "
"or a "
"string interpretation, but not a mixture.";
- this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str());
+ this->LocalGenerator->IssueMessage(MessageType::FATAL_ERROR, e.str());
}
}
+template <typename PropertyType>
+std::string valueAsString(PropertyType);
+template <>
+std::string valueAsString<bool>(bool value)
+{
+ return value ? "TRUE" : "FALSE";
+}
+template <>
+std::string valueAsString<const char*>(const char* value)
+{
+ return value ? value : "(unset)";
+}
+template <>
+std::string valueAsString<std::string>(std::string value)
+{
+ return value;
+}
+template <>
+std::string valueAsString<std::nullptr_t>(std::nullptr_t /*unused*/)
+{
+ return "(unset)";
+}
+
std::string compatibilityType(CompatibleType t)
{
switch (t) {
@@ -3799,34 +4855,49 @@ std::string compatibilityAgree(CompatibleType t, bool dominant)
}
template <typename PropertyType>
-PropertyType getTypedProperty(cmGeneratorTarget const* tgt,
- const std::string& prop);
+PropertyType getTypedProperty(
+ cmGeneratorTarget const* tgt, const std::string& prop,
+ cmGeneratorExpressionInterpreter* genexInterpreter = nullptr);
template <>
bool getTypedProperty<bool>(cmGeneratorTarget const* tgt,
- const std::string& prop)
+ const std::string& prop,
+ cmGeneratorExpressionInterpreter* genexInterpreter)
{
- return tgt->GetPropertyAsBool(prop);
-}
+ if (genexInterpreter == nullptr) {
+ return tgt->GetPropertyAsBool(prop);
+ }
-template <>
-const char* getTypedProperty<const char*>(cmGeneratorTarget const* tgt,
- const std::string& prop)
-{
- return tgt->GetProperty(prop);
+ const char* value = tgt->GetProperty(prop);
+ return cmIsOn(genexInterpreter->Evaluate(value, prop));
}
-template <typename PropertyType>
-std::string valueAsString(PropertyType);
template <>
-std::string valueAsString<bool>(bool value)
+const char* getTypedProperty<const char*>(
+ cmGeneratorTarget const* tgt, const std::string& prop,
+ cmGeneratorExpressionInterpreter* genexInterpreter)
{
- return value ? "TRUE" : "FALSE";
+ const char* value = tgt->GetProperty(prop);
+
+ if (genexInterpreter == nullptr) {
+ return value;
+ }
+
+ return genexInterpreter->Evaluate(value, prop).c_str();
}
+
template <>
-std::string valueAsString<const char*>(const char* value)
+std::string getTypedProperty<std::string>(
+ cmGeneratorTarget const* tgt, const std::string& prop,
+ cmGeneratorExpressionInterpreter* genexInterpreter)
{
- return value ? value : "(unset)";
+ const char* value = tgt->GetProperty(prop);
+
+ if (genexInterpreter == nullptr) {
+ return valueAsString(value);
+ }
+
+ return genexInterpreter->Evaluate(value, prop);
}
template <typename PropertyType>
@@ -3841,6 +4912,11 @@ const char* impliedValue<const char*>(const char* /*unused*/)
{
return "";
}
+template <>
+std::string impliedValue<std::string>(std::string /*unused*/) // NOLINT(*)
+{
+ return std::string();
+}
template <typename PropertyType>
std::pair<bool, PropertyType> consistentProperty(PropertyType lhs,
@@ -3851,14 +4927,21 @@ template <>
std::pair<bool, bool> consistentProperty(bool lhs, bool rhs,
CompatibleType /*unused*/)
{
- return std::make_pair(lhs == rhs, lhs);
+ return { lhs == rhs, lhs };
}
std::pair<bool, const char*> consistentStringProperty(const char* lhs,
const char* rhs)
{
const bool b = strcmp(lhs, rhs) == 0;
- return std::make_pair(b, b ? lhs : CM_NULLPTR);
+ return { b, b ? lhs : nullptr };
+}
+
+std::pair<bool, std::string> consistentStringProperty(const std::string& lhs,
+ const std::string& rhs)
+{
+ const bool b = lhs == rhs;
+ return { b, b ? lhs : valueAsString(nullptr) };
}
std::pair<bool, const char*> consistentNumberProperty(const char* lhs,
@@ -3867,22 +4950,21 @@ std::pair<bool, const char*> consistentNumberProperty(const char* lhs,
{
char* pEnd;
- const char* const null_ptr = CM_NULLPTR;
-
long lnum = strtol(lhs, &pEnd, 0);
if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE) {
- return std::pair<bool, const char*>(false, null_ptr);
+ return { false, nullptr };
}
long rnum = strtol(rhs, &pEnd, 0);
if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE) {
- return std::pair<bool, const char*>(false, null_ptr);
+ return { false, nullptr };
}
if (t == NumberMaxType) {
- return std::make_pair(true, std::max(lnum, rnum) == lnum ? lhs : rhs);
+ return { true, std::max(lnum, rnum) == lnum ? lhs : rhs };
}
- return std::make_pair(true, std::min(lnum, rnum) == lnum ? lhs : rhs);
+
+ return { true, std::min(lnum, rnum) == lnum ? lhs : rhs };
}
template <>
@@ -3891,21 +4973,20 @@ std::pair<bool, const char*> consistentProperty(const char* lhs,
CompatibleType t)
{
if (!lhs && !rhs) {
- return std::make_pair(true, lhs);
+ return { true, lhs };
}
if (!lhs) {
- return std::make_pair(true, rhs);
+ return { true, rhs };
}
if (!rhs) {
- return std::make_pair(true, lhs);
+ return { true, lhs };
}
- const char* const null_ptr = CM_NULLPTR;
-
switch (t) {
- case BoolType:
- assert(false && "consistentProperty for strings called with BoolType");
- return std::pair<bool, const char*>(false, null_ptr);
+ case BoolType: {
+ bool same = cmIsOn(lhs) == cmIsOn(rhs);
+ return { same, same ? lhs : nullptr };
+ }
case StringType:
return consistentStringProperty(lhs, rhs);
case NumberMinType:
@@ -3913,7 +4994,41 @@ std::pair<bool, const char*> consistentProperty(const char* lhs,
return consistentNumberProperty(lhs, rhs, t);
}
assert(false && "Unreachable!");
- return std::pair<bool, const char*>(false, null_ptr);
+ return { false, nullptr };
+}
+
+std::pair<bool, std::string> consistentProperty(const std::string& lhs,
+ const std::string& rhs,
+ CompatibleType t)
+{
+ const std::string null_ptr = valueAsString(nullptr);
+
+ if (lhs == null_ptr && rhs == null_ptr) {
+ return { true, lhs };
+ }
+ if (lhs == null_ptr) {
+ return { true, rhs };
+ }
+ if (rhs == null_ptr) {
+ return { true, lhs };
+ }
+
+ switch (t) {
+ case BoolType: {
+ bool same = cmIsOn(lhs) == cmIsOn(rhs);
+ return { same, same ? lhs : null_ptr };
+ }
+ case StringType:
+ return consistentStringProperty(lhs, rhs);
+ case NumberMinType:
+ case NumberMaxType: {
+ auto value = consistentNumberProperty(lhs.c_str(), rhs.c_str(), t);
+ return { value.first,
+ value.first ? std::string(value.second) : null_ptr };
+ }
+ }
+ assert(false && "Unreachable!");
+ return { false, null_ptr };
}
template <typename PropertyType>
@@ -3925,10 +5040,9 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
PropertyType* /*unused*/)
{
PropertyType propContent = getTypedProperty<PropertyType>(tgt, p);
+
std::vector<std::string> headPropKeys = tgt->GetPropertyKeys();
- const bool explicitlySet =
- std::find(headPropKeys.begin(), headPropKeys.end(), p) !=
- headPropKeys.end();
+ const bool explicitlySet = cmContains(headPropKeys, p);
const bool impliedByUse = tgt->IsNullImpliedByLinkLibraries(p);
assert((impliedByUse ^ explicitlySet) || (!impliedByUse && !explicitlySet));
@@ -3941,8 +5055,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
}
bool propInitialized = explicitlySet;
- std::string report = " * Target \"";
- report += tgt->GetName();
+ std::string report = cmStrCat(" * Target \"", tgt->GetName());
if (explicitlySet) {
report += "\" has property content \"";
report += valueAsString<PropertyType>(propContent);
@@ -3954,22 +5067,23 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
}
std::string interfaceProperty = "INTERFACE_" + p;
- for (std::vector<cmGeneratorTarget const*>::const_iterator li = deps.begin();
- li != deps.end(); ++li) {
+ std::unique_ptr<cmGeneratorExpressionInterpreter> genexInterpreter(
+ p == "POSITION_INDEPENDENT_CODE" ? new cmGeneratorExpressionInterpreter(
+ tgt->GetLocalGenerator(), config, tgt)
+ : nullptr);
+
+ for (cmGeneratorTarget const* theTarget : deps) {
// An error should be reported if one dependency
// has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other
// has INTERFACE_POSITION_INDEPENDENT_CODE OFF, or if the
// target itself has a POSITION_INDEPENDENT_CODE which disagrees
// with a dependency.
- cmGeneratorTarget const* theTarget = *li;
-
std::vector<std::string> propKeys = theTarget->GetPropertyKeys();
- const bool ifaceIsSet = std::find(propKeys.begin(), propKeys.end(),
- interfaceProperty) != propKeys.end();
- PropertyType ifacePropContent =
- getTypedProperty<PropertyType>(theTarget, interfaceProperty);
+ const bool ifaceIsSet = cmContains(propKeys, interfaceProperty);
+ PropertyType ifacePropContent = getTypedProperty<PropertyType>(
+ theTarget, interfaceProperty, genexInterpreter.get());
std::string reportEntry;
if (ifaceIsSet) {
@@ -3991,10 +5105,11 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
e << "Property " << p << " on target \"" << tgt->GetName()
<< "\" does\nnot match the "
"INTERFACE_"
- << p << " property requirement\nof "
- "dependency \""
+ << p
+ << " property requirement\nof "
+ "dependency \""
<< theTarget->GetName() << "\".\n";
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
break;
}
propContent = consistent.second;
@@ -4019,7 +5134,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
"already. The INTERFACE_"
<< p << " property on\ndependency \"" << theTarget->GetName()
<< "\" is in conflict.\n";
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
break;
}
propContent = consistent.second;
@@ -4039,7 +5154,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
e << "The INTERFACE_" << p << " property of \""
<< theTarget->GetName() << "\" does\nnot agree with the value of "
<< p << " already determined\nfor \"" << tgt->GetName() << "\".\n";
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
break;
}
propContent = consistent.second;
@@ -4063,28 +5178,35 @@ bool cmGeneratorTarget::GetLinkInterfaceDependentBoolProperty(
const std::string& p, const std::string& config) const
{
return checkInterfacePropertyCompatibility<bool>(this, p, config, "FALSE",
- BoolType, CM_NULLPTR);
+ BoolType, nullptr);
+}
+
+std::string cmGeneratorTarget::GetLinkInterfaceDependentStringAsBoolProperty(
+ const std::string& p, const std::string& config) const
+{
+ return checkInterfacePropertyCompatibility<std::string>(
+ this, p, config, "FALSE", BoolType, nullptr);
}
const char* cmGeneratorTarget::GetLinkInterfaceDependentStringProperty(
const std::string& p, const std::string& config) const
{
return checkInterfacePropertyCompatibility<const char*>(
- this, p, config, "empty", StringType, CM_NULLPTR);
+ this, p, config, "empty", StringType, nullptr);
}
const char* cmGeneratorTarget::GetLinkInterfaceDependentNumberMinProperty(
const std::string& p, const std::string& config) const
{
return checkInterfacePropertyCompatibility<const char*>(
- this, p, config, "empty", NumberMinType, CM_NULLPTR);
+ this, p, config, "empty", NumberMinType, nullptr);
}
const char* cmGeneratorTarget::GetLinkInterfaceDependentNumberMaxProperty(
const std::string& p, const std::string& config) const
{
return checkInterfacePropertyCompatibility<const char*>(
- this, p, config, "empty", NumberMaxType, CM_NULLPTR);
+ this, p, config, "empty", NumberMaxType, nullptr);
}
cmComputeLinkInformation* cmGeneratorTarget::GetLinkInformation(
@@ -4092,14 +5214,14 @@ cmComputeLinkInformation* cmGeneratorTarget::GetLinkInformation(
{
// Lookup any existing information for this configuration.
std::string key(cmSystemTools::UpperCase(config));
- cmTargetLinkInformationMap::iterator i = this->LinkInformation.find(key);
+ auto i = this->LinkInformation.find(key);
if (i == this->LinkInformation.end()) {
// Compute information for this configuration.
cmComputeLinkInformation* info =
new cmComputeLinkInformation(this, config);
if (!info || !info->Compute()) {
delete info;
- info = CM_NULLPTR;
+ info = nullptr;
}
// Store the information for this configuration.
@@ -4189,9 +5311,8 @@ std::string cmGeneratorTarget::CreateFortranModuleDirectory(
mod_dir = target_mod_dir;
} else {
// Interpret relative to the current output directory.
- mod_dir = this->LocalGenerator->GetCurrentBinaryDirectory();
- mod_dir += "/";
- mod_dir += target_mod_dir;
+ mod_dir = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(),
+ '/', target_mod_dir);
}
// Make sure the module output directory exists.
@@ -4230,14 +5351,7 @@ void cmGeneratorTarget::ComputeVersionedName(std::string& vName,
std::vector<std::string> cmGeneratorTarget::GetPropertyKeys() const
{
- cmPropertyMap const& propsObject = this->Target->GetProperties();
- std::vector<std::string> props;
- props.reserve(propsObject.size());
- for (cmPropertyMap::const_iterator it = propsObject.begin();
- it != propsObject.end(); ++it) {
- props.push_back(it->first);
- }
- return props;
+ return this->Target->GetProperties().GetKeys();
}
void cmGeneratorTarget::ReportPropertyOrigin(
@@ -4248,12 +5362,11 @@ void cmGeneratorTarget::ReportPropertyOrigin(
const char* debugProp = this->Target->GetMakefile()->GetDefinition(
"CMAKE_DEBUG_TARGET_PROPERTIES");
if (debugProp) {
- cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+ cmExpandList(debugProp, debugProperties);
}
- bool debugOrigin = !this->DebugCompatiblePropertiesDone[p] &&
- std::find(debugProperties.begin(), debugProperties.end(), p) !=
- debugProperties.end();
+ bool debugOrigin =
+ !this->DebugCompatiblePropertiesDone[p] && cmContains(debugProperties, p);
if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
this->DebugCompatiblePropertiesDone[p] = true;
@@ -4262,26 +5375,24 @@ void cmGeneratorTarget::ReportPropertyOrigin(
return;
}
- std::string areport = compatibilityType;
- areport += std::string(" of property \"") + p + "\" for target \"";
- areport += std::string(this->GetName());
- areport += "\" (result: \"";
- areport += result;
- areport += "\"):\n" + report;
+ std::string areport =
+ cmStrCat(compatibilityType, " of property \"", p, "\" for target \"",
+ this->GetName(), "\" (result: \"", result, "\"):\n", report);
- this->LocalGenerator->GetCMakeInstance()->IssueMessage(cmake::LOG, areport);
+ this->LocalGenerator->GetCMakeInstance()->IssueMessage(MessageType::LOG,
+ areport);
}
void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names,
+ cmListFileBacktrace const& bt,
std::vector<cmLinkItem>& items) const
{
- for (std::vector<std::string>::const_iterator i = names.begin();
- i != names.end(); ++i) {
- std::string name = this->CheckCMP0004(*i);
+ for (std::string const& n : names) {
+ std::string name = this->CheckCMP0004(n);
if (name == this->GetName() || name.empty()) {
continue;
}
- items.push_back(cmLinkItem(name, this->FindTargetToLink(name)));
+ items.push_back(this->ResolveLinkItem(name, bt));
}
}
@@ -4291,20 +5402,18 @@ void cmGeneratorTarget::ExpandLinkItems(
std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition) const
{
cmGeneratorExpression ge;
- cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), prop, CM_NULLPTR,
- CM_NULLPTR);
+ cmGeneratorExpressionDAGChecker dagChecker(this, prop, nullptr, nullptr);
// The $<LINK_ONLY> expression may be in a link interface to specify private
// link dependencies that are otherwise excluded from usage requirements.
if (usage_requirements_only) {
dagChecker.SetTransitivePropertiesOnly();
}
std::vector<std::string> libs;
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(value);
- cmSystemTools::ExpandListArgument(cge->Evaluate(this->LocalGenerator, config,
- false, headTarget, this,
- &dagChecker),
- libs);
- this->LookupLinkItems(libs, items);
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
+ cmExpandList(
+ cge->Evaluate(this->LocalGenerator, config, headTarget, &dagChecker, this),
+ libs);
+ this->LookupLinkItems(libs, cge->GetBacktrace(), items);
hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition();
}
@@ -4320,7 +5429,7 @@ cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
// export symbols.
if (this->GetType() == cmStateEnums::EXECUTABLE &&
!this->IsExecutableWithExports()) {
- return CM_NULLPTR;
+ return nullptr;
}
// Lookup any existing link interface for this configuration.
@@ -4344,35 +5453,31 @@ cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
}
}
- return iface.Exists ? &iface : CM_NULLPTR;
+ return iface.Exists ? &iface : nullptr;
}
void cmGeneratorTarget::ComputeLinkInterface(
const std::string& config, cmOptionalLinkInterface& iface,
cmGeneratorTarget const* headTarget) const
{
- if (iface.ExplicitLibraries) {
+ if (iface.Explicit) {
if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::STATIC_LIBRARY ||
this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
// Shared libraries may have runtime implementation dependencies
// on other shared libraries that are not in the interface.
- CM_UNORDERED_SET<std::string> emitted;
- for (std::vector<cmLinkItem>::const_iterator li =
- iface.Libraries.begin();
- li != iface.Libraries.end(); ++li) {
- emitted.insert(*li);
+ std::set<cmLinkItem> emitted;
+ for (cmLinkItem const& lib : iface.Libraries) {
+ emitted.insert(lib);
}
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
cmLinkImplementation const* impl = this->GetLinkImplementation(config);
- for (std::vector<cmLinkImplItem>::const_iterator li =
- impl->Libraries.begin();
- li != impl->Libraries.end(); ++li) {
- if (emitted.insert(*li).second) {
- if (li->Target) {
+ for (cmLinkImplItem const& lib : impl->Libraries) {
+ if (emitted.insert(lib).second) {
+ if (lib.Target) {
// This is a runtime dependency on another shared library.
- if (li->Target->GetType() == cmStateEnums::SHARED_LIBRARY) {
- iface.SharedDeps.push_back(*li);
+ if (lib.Target->GetType() == cmStateEnums::SHARED_LIBRARY) {
+ iface.SharedDeps.push_back(lib);
}
} else {
// TODO: Recognize shared library file names. Perhaps this
@@ -4412,8 +5517,7 @@ void cmGeneratorTarget::ComputeLinkInterface(
// How many repetitions are needed if this library has cyclic
// dependencies?
- std::string propName = "LINK_INTERFACE_MULTIPLICITY";
- propName += suffix;
+ std::string propName = cmStrCat("LINK_INTERFACE_MULTIPLICITY", suffix);
if (const char* config_reps = this->GetProperty(propName)) {
sscanf(config_reps, "%u", &iface.Multiplicity);
} else if (const char* reps =
@@ -4436,7 +5540,7 @@ const cmLinkInterfaceLibraries* cmGeneratorTarget::GetLinkInterfaceLibraries(
// export symbols.
if (this->GetType() == cmStateEnums::EXECUTABLE &&
!this->IsExecutableWithExports()) {
- return CM_NULLPTR;
+ return nullptr;
}
// Lookup any existing link interface for this configuration.
@@ -4459,7 +5563,7 @@ const cmLinkInterfaceLibraries* cmGeneratorTarget::GetLinkInterfaceLibraries(
usage_requirements_only);
}
- return iface.Exists ? &iface : CM_NULLPTR;
+ return iface.Exists ? &iface : nullptr;
}
std::string cmGeneratorTarget::GetDirectory(
@@ -4494,17 +5598,16 @@ cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo(
{
// There is no output information for imported targets.
if (this->IsImported()) {
- return CM_NULLPTR;
+ return nullptr;
}
// Only libraries and executables have well-defined output files.
if (!this->HaveWellDefinedOutputFiles()) {
- std::string msg = "cmGeneratorTarget::GetOutputInfo called for ";
- msg += this->GetName();
- msg += " which has type ";
- msg += cmState::GetTargetTypeName(this->GetType());
- this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg);
- return CM_NULLPTR;
+ std::string msg = cmStrCat("cmGeneratorTarget::GetOutputInfo called for ",
+ this->GetName(), " which has type ",
+ cmState::GetTargetTypeName(this->GetType()));
+ this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
+ return nullptr;
}
// Lookup/compute/cache the output information for this configuration.
@@ -4512,7 +5615,7 @@ cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo(
if (!config.empty()) {
config_upper = cmSystemTools::UpperCase(config);
}
- OutputInfoMapType::iterator i = this->OutputInfoMap.find(config_upper);
+ auto i = this->OutputInfoMap.find(config_upper);
if (i == this->OutputInfoMap.end()) {
// Add empty info in map to detect potential recursion.
OutputInfo info;
@@ -4534,10 +5637,10 @@ cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo(
// An empty map entry indicates we have been called recursively
// from the above block.
this->LocalGenerator->GetCMakeInstance()->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"Target '" + this->GetName() + "' OUTPUT_DIRECTORY depends on itself.",
this->GetBacktrace());
- return CM_NULLPTR;
+ return nullptr;
}
return &i->second;
}
@@ -4552,7 +5655,7 @@ bool cmGeneratorTarget::ComputeOutputDir(const std::string& config,
// Look for a target property defining the target output directory
// based on the target type.
std::string targetTypeName = this->GetOutputTargetType(artifact);
- const char* propertyName = CM_NULLPTR;
+ const char* propertyName = nullptr;
std::string propertyNameStr = targetTypeName;
if (!propertyNameStr.empty()) {
propertyNameStr += "_OUTPUT_DIRECTORY";
@@ -4561,7 +5664,7 @@ bool cmGeneratorTarget::ComputeOutputDir(const std::string& config,
// Check for a per-configuration output directory target property.
std::string configUpper = cmSystemTools::UpperCase(conf);
- const char* configProp = CM_NULLPTR;
+ const char* configProp = nullptr;
std::string configPropStr = targetTypeName;
if (!configPropStr.empty()) {
configPropStr += "_OUTPUT_DIRECTORY_";
@@ -4572,22 +5675,20 @@ bool cmGeneratorTarget::ComputeOutputDir(const std::string& config,
// Select an output directory.
if (const char* config_outdir = this->GetProperty(configProp)) {
// Use the user-specified per-configuration output directory.
- cmGeneratorExpression ge;
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(config_outdir);
- out = cge->Evaluate(this->LocalGenerator, config);
+ out = cmGeneratorExpression::Evaluate(config_outdir, this->LocalGenerator,
+ config);
// Skip per-configuration subdirectory.
- conf = "";
+ conf.clear();
} else if (const char* outdir = this->GetProperty(propertyName)) {
// Use the user-specified output directory.
- cmGeneratorExpression ge;
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(outdir);
- out = cge->Evaluate(this->LocalGenerator, config);
+ out =
+ cmGeneratorExpression::Evaluate(outdir, this->LocalGenerator, config);
// Skip per-configuration subdirectory if the value contained a
// generator expression.
if (out != outdir) {
- conf = "";
+ conf.clear();
}
} else if (this->GetType() == cmStateEnums::EXECUTABLE) {
// Lookup the output path for executables.
@@ -4629,7 +5730,7 @@ bool cmGeneratorTarget::ComputePDBOutputDir(const std::string& kind,
{
// Look for a target property defining the target output directory
// based on the target type.
- const char* propertyName = CM_NULLPTR;
+ const char* propertyName = nullptr;
std::string propertyNameStr = kind;
if (!propertyNameStr.empty()) {
propertyNameStr += "_OUTPUT_DIRECTORY";
@@ -4639,7 +5740,7 @@ bool cmGeneratorTarget::ComputePDBOutputDir(const std::string& kind,
// Check for a per-configuration output directory target property.
std::string configUpper = cmSystemTools::UpperCase(conf);
- const char* configProp = CM_NULLPTR;
+ const char* configProp = nullptr;
std::string configPropStr = kind;
if (!configPropStr.empty()) {
configPropStr += "_OUTPUT_DIRECTORY_";
@@ -4650,13 +5751,21 @@ bool cmGeneratorTarget::ComputePDBOutputDir(const std::string& kind,
// Select an output directory.
if (const char* config_outdir = this->GetProperty(configProp)) {
// Use the user-specified per-configuration output directory.
- out = config_outdir;
+ out = cmGeneratorExpression::Evaluate(config_outdir, this->LocalGenerator,
+ config);
// Skip per-configuration subdirectory.
- conf = "";
+ conf.clear();
} else if (const char* outdir = this->GetProperty(propertyName)) {
// Use the user-specified output directory.
- out = outdir;
+ out =
+ cmGeneratorExpression::Evaluate(outdir, this->LocalGenerator, config);
+
+ // Skip per-configuration subdirectory if the value contained a
+ // generator expression.
+ if (out != outdir) {
+ conf.clear();
+ }
}
if (out.empty()) {
return false;
@@ -4676,13 +5785,40 @@ bool cmGeneratorTarget::ComputePDBOutputDir(const std::string& kind,
return true;
}
-bool cmGeneratorTarget::HaveInstallTreeRPATH() const
+bool cmGeneratorTarget::HaveInstallTreeRPATH(const std::string& config) const
{
- const char* install_rpath = this->GetProperty("INSTALL_RPATH");
- return (install_rpath && *install_rpath) &&
+ std::string install_rpath;
+ this->GetInstallRPATH(config, install_rpath);
+ return !install_rpath.empty() &&
!this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH");
}
+bool cmGeneratorTarget::GetBuildRPATH(const std::string& config,
+ std::string& rpath) const
+{
+ return this->GetRPATH(config, "BUILD_RPATH", rpath);
+}
+
+bool cmGeneratorTarget::GetInstallRPATH(const std::string& config,
+ std::string& rpath) const
+{
+ return this->GetRPATH(config, "INSTALL_RPATH", rpath);
+}
+
+bool cmGeneratorTarget::GetRPATH(const std::string& config,
+ const std::string& prop,
+ std::string& rpath) const
+{
+ const char* value = this->GetProperty(prop);
+ if (!value) {
+ return false;
+ }
+
+ rpath = cmGeneratorExpression::Evaluate(value, this->LocalGenerator, config);
+
+ return true;
+}
+
void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
const std::string& config, cmOptionalLinkInterface& iface,
cmGeneratorTarget const* headTarget, bool usage_requirements_only) const
@@ -4697,10 +5833,11 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
// An explicit list of interface libraries may be set for shared
// libraries and executables that export symbols.
- const char* explicitLibraries = CM_NULLPTR;
+ const char* explicitLibraries = nullptr;
std::string linkIfaceProp;
- if (this->GetPolicyStatusCMP0022() != cmPolicies::OLD &&
- this->GetPolicyStatusCMP0022() != cmPolicies::WARN) {
+ bool const cmp0022NEW = (this->GetPolicyStatusCMP0022() != cmPolicies::OLD &&
+ this->GetPolicyStatusCMP0022() != cmPolicies::WARN);
+ if (cmp0022NEW) {
// CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES.
linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
explicitLibraries = this->GetProperty(linkIfaceProp);
@@ -4710,8 +5847,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
// shared lib or executable.
// Lookup the per-configuration property.
- linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
- linkIfaceProp += suffix;
+ linkIfaceProp = cmStrCat("LINK_INTERFACE_LIBRARIES", suffix);
explicitLibraries = this->GetProperty(linkIfaceProp);
// If not set, try the generic property.
@@ -4740,9 +5876,9 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
"INTERFACE_LINK_LIBRARIES:\n"
" " << newExplicitLibraries << "\n" <<
linkIfaceProp << ":\n"
- " " << (explicitLibraries ? explicitLibraries : "(empty)") << "\n";
+ " " << explicitLibraries << "\n";
/* clang-format on */
- this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ this->LocalGenerator->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
this->PolicyWarnedCMP0022 = true;
}
}
@@ -4755,15 +5891,14 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
return;
}
iface.Exists = true;
- iface.ExplicitLibraries = explicitLibraries;
+ iface.Explicit = cmp0022NEW || explicitLibraries != nullptr;
if (explicitLibraries) {
// The interface libraries have been explicitly set.
this->ExpandLinkItems(linkIfaceProp, explicitLibraries, config, headTarget,
usage_requirements_only, iface.Libraries,
iface.HadHeadSensitiveCondition);
- } else if (this->GetPolicyStatusCMP0022() == cmPolicies::WARN ||
- this->GetPolicyStatusCMP0022() == cmPolicies::OLD)
+ } else if (!cmp0022NEW)
// If CMP0022 is NEW then the plain tll signature sets the
// INTERFACE_LINK_LIBRARIES, so if we get here then the project
// cleared the property explicitly and we should not fall back
@@ -4811,7 +5946,8 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
"Link implementation:\n"
" " << oldLibraries << "\n";
/* clang-format on */
- this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ this->LocalGenerator->IssueMessage(MessageType::AUTHOR_WARNING,
+ w.str());
this->PolicyWarnedCMP0022 = true;
}
}
@@ -4824,7 +5960,7 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
{
cmGeneratorTarget::ImportInfo const* info = this->GetImportInfo(config);
if (!info) {
- return CM_NULLPTR;
+ return nullptr;
}
std::string CONFIG = cmSystemTools::UpperCase(config);
@@ -4843,13 +5979,12 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
if (!iface.AllDone) {
iface.AllDone = true;
iface.Multiplicity = info->Multiplicity;
- cmSystemTools::ExpandListArgument(info->Languages, iface.Languages);
+ cmExpandList(info->Languages, iface.Languages);
this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config,
headTarget, usage_requirements_only, iface.Libraries,
iface.HadHeadSensitiveCondition);
- std::vector<std::string> deps;
- cmSystemTools::ExpandListArgument(info->SharedDeps, deps);
- this->LookupLinkItems(deps, iface.SharedDeps);
+ std::vector<std::string> deps = cmExpandedList(info->SharedDeps);
+ this->LookupLinkItems(deps, cmListFileBacktrace(), iface.SharedDeps);
}
return &iface;
@@ -4860,7 +5995,7 @@ cmGeneratorTarget::ImportInfo const* cmGeneratorTarget::GetImportInfo(
{
// There is no imported information for non-imported targets.
if (!this->IsImported()) {
- return CM_NULLPTR;
+ return nullptr;
}
// Lookup/compute/cache the import information for this
@@ -4872,7 +6007,7 @@ cmGeneratorTarget::ImportInfo const* cmGeneratorTarget::GetImportInfo(
config_upper = "NOCONFIG";
}
- ImportInfoMapType::const_iterator i = this->ImportInfoMap.find(config_upper);
+ auto i = this->ImportInfoMap.find(config_upper);
if (i == this->ImportInfoMap.end()) {
ImportInfo info;
this->ComputeImportInfo(config_upper, info);
@@ -4886,7 +6021,7 @@ cmGeneratorTarget::ImportInfo const* cmGeneratorTarget::GetImportInfo(
// If the location is empty then the target is not available for
// this configuration.
if (i->second.Location.empty() && i->second.ImportLibrary.empty()) {
- return CM_NULLPTR;
+ return nullptr;
}
// Return the import information.
@@ -4903,8 +6038,8 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
// Initialize members.
info.NoSOName = false;
- const char* loc = CM_NULLPTR;
- const char* imp = CM_NULLPTR;
+ const char* loc = nullptr;
+ const char* imp = nullptr;
std::string suffix;
if (!this->Target->GetMappedConfig(desired_config, &loc, &imp, suffix)) {
return;
@@ -4917,8 +6052,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
if (!propertyLibs) {
- linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
- linkProp += suffix;
+ linkProp = cmStrCat("IMPORTED_LINK_INTERFACE_LIBRARIES", suffix);
propertyLibs = this->GetProperty(linkProp);
}
@@ -4946,8 +6080,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
if (loc) {
info.Location = loc;
} else {
- std::string impProp = "IMPORTED_LOCATION";
- impProp += suffix;
+ std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix);
if (const char* config_location = this->GetProperty(impProp)) {
info.Location = config_location;
} else if (const char* location = this->GetProperty("IMPORTED_LOCATION")) {
@@ -4957,8 +6090,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
// Get the soname.
if (this->GetType() == cmStateEnums::SHARED_LIBRARY) {
- std::string soProp = "IMPORTED_SONAME";
- soProp += suffix;
+ std::string soProp = cmStrCat("IMPORTED_SONAME", suffix);
if (const char* config_soname = this->GetProperty(soProp)) {
info.SOName = config_soname;
} else if (const char* soname = this->GetProperty("IMPORTED_SONAME")) {
@@ -4968,13 +6100,12 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
// Get the "no-soname" mark.
if (this->GetType() == cmStateEnums::SHARED_LIBRARY) {
- std::string soProp = "IMPORTED_NO_SONAME";
- soProp += suffix;
+ std::string soProp = cmStrCat("IMPORTED_NO_SONAME", suffix);
if (const char* config_no_soname = this->GetProperty(soProp)) {
- info.NoSOName = cmSystemTools::IsOn(config_no_soname);
+ info.NoSOName = cmIsOn(config_no_soname);
} else if (const char* no_soname =
this->GetProperty("IMPORTED_NO_SONAME")) {
- info.NoSOName = cmSystemTools::IsOn(no_soname);
+ info.NoSOName = cmIsOn(no_soname);
}
}
@@ -4983,8 +6114,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
info.ImportLibrary = imp;
} else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->IsExecutableWithExports()) {
- std::string impProp = "IMPORTED_IMPLIB";
- impProp += suffix;
+ std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
if (const char* config_implib = this->GetProperty(impProp)) {
info.ImportLibrary = config_implib;
} else if (const char* implib = this->GetProperty("IMPORTED_IMPLIB")) {
@@ -4994,8 +6124,8 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
// Get the link dependencies.
{
- std::string linkProp = "IMPORTED_LINK_DEPENDENT_LIBRARIES";
- linkProp += suffix;
+ std::string linkProp =
+ cmStrCat("IMPORTED_LINK_DEPENDENT_LIBRARIES", suffix);
if (const char* config_libs = this->GetProperty(linkProp)) {
info.SharedDeps = config_libs;
} else if (const char* libs =
@@ -5006,8 +6136,8 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
// Get the link languages.
if (this->LinkLanguagePropagatesToDependents()) {
- std::string linkProp = "IMPORTED_LINK_INTERFACE_LANGUAGES";
- linkProp += suffix;
+ std::string linkProp =
+ cmStrCat("IMPORTED_LINK_INTERFACE_LANGUAGES", suffix);
if (const char* config_libs = this->GetProperty(linkProp)) {
info.Languages = config_libs;
} else if (const char* libs =
@@ -5016,10 +6146,20 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
}
}
+ // Get information if target is managed assembly.
+ {
+ std::string linkProp = "IMPORTED_COMMON_LANGUAGE_RUNTIME";
+ if (auto pc = this->GetProperty(linkProp + suffix)) {
+ info.Managed = this->CheckManagedType(pc);
+ } else if (auto p = this->GetProperty(linkProp)) {
+ info.Managed = this->CheckManagedType(p);
+ }
+ }
+
// Get the cyclic repetition count.
if (this->GetType() == cmStateEnums::STATIC_LIBRARY) {
- std::string linkProp = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
- linkProp += suffix;
+ std::string linkProp =
+ cmStrCat("IMPORTED_LINK_INTERFACE_MULTIPLICITY", suffix);
if (const char* config_reps = this->GetProperty(linkProp)) {
sscanf(config_reps, "%u", &info.Multiplicity);
} else if (const char* reps =
@@ -5049,7 +6189,7 @@ const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
{
// There is no link implementation for imported targets.
if (this->IsImported()) {
- return CM_NULLPTR;
+ return nullptr;
}
std::string CONFIG = cmSystemTools::UpperCase(config);
@@ -5068,13 +6208,10 @@ const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
bool cmGeneratorTarget::GetConfigCommonSourceFiles(
std::vector<cmSourceFile*>& files) const
{
- std::vector<std::string> configs;
- this->Makefile->GetConfigurations(configs);
- if (configs.empty()) {
- configs.push_back("");
- }
+ std::vector<std::string> const& configs =
+ this->Makefile->GetGeneratorConfigs();
- std::vector<std::string>::const_iterator it = configs.begin();
+ auto it = configs.begin();
const std::string& firstConfig = *it;
this->GetSourceFilesWithoutObjectLibraries(files, firstConfig);
@@ -5084,19 +6221,17 @@ bool cmGeneratorTarget::GetConfigCommonSourceFiles(
if (configFiles != files) {
std::string firstConfigFiles;
const char* sep = "";
- for (std::vector<cmSourceFile*>::const_iterator fi = files.begin();
- fi != files.end(); ++fi) {
+ for (cmSourceFile* f : files) {
firstConfigFiles += sep;
- firstConfigFiles += (*fi)->GetFullPath();
+ firstConfigFiles += f->ResolveFullPath();
sep = "\n ";
}
std::string thisConfigFiles;
sep = "";
- for (std::vector<cmSourceFile*>::const_iterator fi = configFiles.begin();
- fi != configFiles.end(); ++fi) {
+ for (cmSourceFile* f : configFiles) {
thisConfigFiles += sep;
- thisConfigFiles += (*fi)->GetFullPath();
+ thisConfigFiles += f->ResolveFullPath();
sep = "\n ";
}
std::ostringstream e;
@@ -5111,7 +6246,7 @@ bool cmGeneratorTarget::GetConfigCommonSourceFiles(
"Config \"" << *it << "\":\n"
" " << thisConfigFiles << "\n";
/* clang-format on */
- this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str());
+ this->LocalGenerator->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
}
@@ -5127,17 +6262,11 @@ void cmGeneratorTarget::GetObjectLibrariesCMP0026(
// for TARGET_OBJECTS instead for backwards compatibility with OLD
// behavior of CMP0024 and CMP0026 only.
cmStringRange rng = this->Target->GetSourceEntries();
- for (std::vector<std::string>::const_iterator i = rng.begin();
- i != rng.end(); ++i) {
- std::string const& entry = *i;
-
- std::vector<std::string> files;
- cmSystemTools::ExpandListArgument(entry, files);
- for (std::vector<std::string>::const_iterator li = files.begin();
- li != files.end(); ++li) {
- if (cmHasLiteralPrefix(*li, "$<TARGET_OBJECTS:") &&
- (*li)[li->size() - 1] == '>') {
- std::string objLibName = li->substr(17, li->size() - 18);
+ for (std::string const& entry : rng) {
+ std::vector<std::string> files = cmExpandedList(entry);
+ for (std::string const& li : files) {
+ if (cmHasLiteralPrefix(li, "$<TARGET_OBJECTS:") && li.back() == '>') {
+ std::string objLibName = li.substr(17, li.size() - 18);
if (cmGeneratorExpression::Find(objLibName) != std::string::npos) {
continue;
@@ -5174,7 +6303,8 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const
w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0004) << "\n"
<< "Target \"" << this->GetName() << "\" links to item \"" << item
<< "\" which has leading or trailing whitespace.";
- cm->IssueMessage(cmake::AUTHOR_WARNING, w.str(), this->GetBacktrace());
+ cm->IssueMessage(MessageType::AUTHOR_WARNING, w.str(),
+ this->GetBacktrace());
}
case cmPolicies::OLD:
break;
@@ -5183,7 +6313,8 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const
e << "Target \"" << this->GetName() << "\" links to item \"" << item
<< "\" which has leading or trailing whitespace. "
<< "This is now an error according to policy CMP0004.";
- cm->IssueMessage(cmake::FATAL_ERROR, e.str(), this->GetBacktrace());
+ cm->IssueMessage(MessageType::FATAL_ERROR, e.str(),
+ this->GetBacktrace());
} break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS: {
@@ -5191,7 +6322,8 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const
e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0004) << "\n"
<< "Target \"" << this->GetName() << "\" links to item \"" << item
<< "\" which has leading or trailing whitespace.";
- cm->IssueMessage(cmake::FATAL_ERROR, e.str(), this->GetBacktrace());
+ cm->IssueMessage(MessageType::FATAL_ERROR, e.str(),
+ this->GetBacktrace());
} break;
}
}
@@ -5203,9 +6335,8 @@ void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages,
{
std::vector<cmSourceFile*> sourceFiles;
this->GetSourceFiles(sourceFiles, config);
- for (std::vector<cmSourceFile*>::const_iterator i = sourceFiles.begin();
- i != sourceFiles.end(); ++i) {
- const std::string& lang = (*i)->GetLanguage();
+ for (cmSourceFile* src : sourceFiles) {
+ const std::string& lang = src->GetOrDetermineLanguage();
if (!lang.empty()) {
languages.insert(lang);
}
@@ -5217,28 +6348,46 @@ void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages,
std::vector<cmGeneratorTarget*> objectTargets;
this->GetObjectLibrariesCMP0026(objectTargets);
objectLibraries.reserve(objectTargets.size());
- for (std::vector<cmGeneratorTarget*>::const_iterator it =
- objectTargets.begin();
- it != objectTargets.end(); ++it) {
- objectLibraries.push_back(*it);
+ for (cmGeneratorTarget* gt : objectTargets) {
+ objectLibraries.push_back(gt);
}
} else {
this->GetExternalObjects(externalObjects, config);
- for (std::vector<cmSourceFile const*>::const_iterator i =
- externalObjects.begin();
- i != externalObjects.end(); ++i) {
- std::string objLib = (*i)->GetObjectLibrary();
+ for (cmSourceFile const* extObj : externalObjects) {
+ 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);
+ }
}
}
}
- for (std::vector<cmGeneratorTarget*>::const_iterator i =
- objectLibraries.begin();
- i != objectLibraries.end(); ++i) {
- (*i)->GetLanguages(languages, config);
+ for (cmGeneratorTarget* objLib : objectLibraries) {
+ objLib->GetLanguages(languages, config);
+ }
+}
+
+bool cmGeneratorTarget::IsCSharpOnly() const
+{
+ // Only certain target types may compile CSharp.
+ if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ this->GetType() != cmStateEnums::STATIC_LIBRARY &&
+ this->GetType() != cmStateEnums::EXECUTABLE) {
+ return false;
+ }
+ std::set<std::string> languages;
+ this->GetLanguages(languages, "");
+ // Consider an explicit linker language property, but *not* the
+ // computed linker language that may depend on linked targets.
+ const char* linkLang = this->GetProperty("LINKER_LANGUAGE");
+ if (linkLang && *linkLang) {
+ languages.insert(linkLang);
}
+ return languages.size() == 1 && languages.count("CSharp") > 0;
}
void cmGeneratorTarget::ComputeLinkImplementationLanguages(
@@ -5248,7 +6397,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());
}
@@ -5258,7 +6407,8 @@ bool cmGeneratorTarget::HaveBuildTreeRPATH(const std::string& config) const
if (this->GetPropertyAsBool("SKIP_BUILD_RPATH")) {
return false;
}
- if (this->GetProperty("BUILD_RPATH")) {
+ std::string build_rpath;
+ if (this->GetBuildRPATH(config, build_rpath)) {
return true;
}
if (cmLinkImplementationLibraries const* impl =
@@ -5281,7 +6431,7 @@ cmGeneratorTarget::GetLinkImplementationLibrariesInternal(
{
// There is no link implementation for imported targets.
if (this->IsImported()) {
- return CM_NULLPTR;
+ return nullptr;
}
// Populate the link implementation libraries for this configuration.
@@ -5305,8 +6455,7 @@ cmGeneratorTarget::GetLinkImplementationLibrariesInternal(
bool cmGeneratorTarget::IsNullImpliedByLinkLibraries(
const std::string& p) const
{
- return this->LinkImplicitNullProperties.find(p) !=
- this->LinkImplicitNullProperties.end();
+ return cmContains(this->LinkImplicitNullProperties, p);
}
void cmGeneratorTarget::ComputeLinkImplementationLibraries(
@@ -5321,30 +6470,29 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
end = entryRange.end();
le != end; ++le, ++btIt) {
std::vector<std::string> llibs;
- cmGeneratorExpressionDAGChecker dagChecker(
- this->GetName(), "LINK_LIBRARIES", CM_NULLPTR, CM_NULLPTR);
+ cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr,
+ nullptr);
cmGeneratorExpression ge(*btIt);
- CM_AUTO_PTR<cmCompiledGeneratorExpression> const cge = ge.Parse(*le);
- std::string const evaluated =
- cge->Evaluate(this->LocalGenerator, config, false, head, &dagChecker);
- cmSystemTools::ExpandListArgument(evaluated, llibs);
+ std::unique_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(*le);
+ std::string const& evaluated =
+ cge->Evaluate(this->LocalGenerator, config, head, &dagChecker);
+ cmExpandList(evaluated, llibs);
if (cge->GetHadHeadSensitiveCondition()) {
impl.HadHeadSensitiveCondition = true;
}
- for (std::vector<std::string>::const_iterator li = llibs.begin();
- li != llibs.end(); ++li) {
+ for (std::string const& lib : llibs) {
// Skip entries that resolve to the target itself or are empty.
- std::string name = this->CheckCMP0004(*li);
+ std::string name = this->CheckCMP0004(lib);
if (name == this->GetName() || name.empty()) {
if (name == this->GetName()) {
bool noMessage = false;
- cmake::MessageType messageType = cmake::FATAL_ERROR;
+ MessageType messageType = MessageType::FATAL_ERROR;
std::ostringstream e;
switch (this->GetPolicyStatusCMP0038()) {
case cmPolicies::WARN: {
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0038) << "\n";
- messageType = cmake::AUTHOR_WARNING;
+ messageType = MessageType::AUTHOR_WARNING;
} break;
case cmPolicies::OLD:
noMessage = true;
@@ -5359,7 +6507,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
e << "Target \"" << this->GetName() << "\" links to itself.";
this->LocalGenerator->GetCMakeInstance()->IssueMessage(
messageType, e.str(), this->GetBacktrace());
- if (messageType == cmake::FATAL_ERROR) {
+ if (messageType == MessageType::FATAL_ERROR) {
return;
}
}
@@ -5368,15 +6516,14 @@ 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(this->ResolveLinkItem(name, *btIt),
+ evaluated != *le);
}
std::set<std::string> const& seenProps = cge->GetSeenTargetProperties();
- for (std::set<std::string>::const_iterator it = seenProps.begin();
- it != seenProps.end(); ++it) {
- if (!this->GetProperty(*it)) {
- this->LinkImplicitNullProperties.insert(*it);
+ for (std::string const& sp : seenProps) {
+ if (!this->GetProperty(sp)) {
+ this->LinkImplicitNullProperties.insert(sp);
}
}
cge->GetMaxLanguageStandard(this, this->MaxLanguageStandards);
@@ -5390,49 +6537,79 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
CMP0003_ComputeLinkType(config, debugConfigs);
cmTarget::LinkLibraryVectorType const& oldllibs =
this->Target->GetOriginalLinkLibraries();
- for (cmTarget::LinkLibraryVectorType::const_iterator li = oldllibs.begin();
- li != oldllibs.end(); ++li) {
- if (li->second != GENERAL_LibraryType && li->second != linkType) {
- std::string name = this->CheckCMP0004(li->first);
+ for (cmTarget::LibraryID const& oldllib : oldllibs) {
+ if (oldllib.second != GENERAL_LibraryType && oldllib.second != linkType) {
+ std::string name = this->CheckCMP0004(oldllib.first);
if (name == this->GetName() || name.empty()) {
continue;
}
// Support OLD behavior for CMP0003.
impl.WrongConfigLibraries.push_back(
- cmLinkItem(name, this->FindTargetToLink(name)));
+ this->ResolveLinkItem(name, cmListFileBacktrace()));
}
}
}
-cmGeneratorTarget* cmGeneratorTarget::FindTargetToLink(
+cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference(
std::string const& name) const
{
- cmGeneratorTarget* tgt =
- this->LocalGenerator->FindGeneratorTargetToUse(name);
+ cmLocalGenerator const* lg = this->LocalGenerator;
+ std::string const* lookupName = &name;
+
+ // When target_link_libraries() is called with a LHS target that is
+ // not created in the calling directory it adds a directory id suffix
+ // that we can use to look up the calling directory. It is that scope
+ // in which the item name is meaningful. This case is relatively rare
+ // so we allocate a separate string only when the directory id is present.
+ std::string::size_type pos = name.find(CMAKE_DIRECTORY_ID_SEP);
+ std::string plainName;
+ if (pos != std::string::npos) {
+ // We will look up the plain name without the directory id suffix.
+ plainName = name.substr(0, pos);
+
+ // We will look up in the scope of the directory id.
+ // If we do not recognize the id then leave the original
+ // syntax in place to produce an indicative error later.
+ cmDirectoryId const dirId =
+ name.substr(pos + sizeof(CMAKE_DIRECTORY_ID_SEP) - 1);
+ if (cmLocalGenerator const* otherLG =
+ this->GlobalGenerator->FindLocalGenerator(dirId)) {
+ lg = otherLG;
+ lookupName = &plainName;
+ }
+ }
+
+ TargetOrString resolved;
+
+ if (cmGeneratorTarget* tgt = lg->FindGeneratorTargetToUse(*lookupName)) {
+ resolved.Target = tgt;
+ } else if (lookupName == &plainName) {
+ resolved.String = std::move(plainName);
+ } else {
+ resolved.String = name;
+ }
+
+ return resolved;
+}
+
+cmLinkItem cmGeneratorTarget::ResolveLinkItem(
+ std::string const& name, cmListFileBacktrace const& bt) const
+{
+ TargetOrString resolved = this->ResolveTargetReference(name);
+
+ if (!resolved.Target) {
+ return cmLinkItem(resolved.String, bt);
+ }
// Skip targets that will not really be linked. This is probably a
// name conflict between an external library and an executable
// within the project.
- if (tgt && tgt->GetType() == cmStateEnums::EXECUTABLE &&
- !tgt->IsExecutableWithExports()) {
- tgt = CM_NULLPTR;
- }
-
- if (tgt && tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::ostringstream e;
- e << "Target \"" << this->GetName() << "\" links to "
- "OBJECT library \""
- << tgt->GetName()
- << "\" but this is not "
- "allowed. "
- "One may link only to STATIC or SHARED libraries, or to executables "
- "with the ENABLE_EXPORTS property set.";
- cmake* cm = this->LocalGenerator->GetCMakeInstance();
- cm->IssueMessage(cmake::FATAL_ERROR, e.str(), this->GetBacktrace());
- tgt = CM_NULLPTR;
+ if (resolved.Target->GetType() == cmStateEnums::EXECUTABLE &&
+ !resolved.Target->IsExecutableWithExports()) {
+ return cmLinkItem(resolved.Target->GetName(), bt);
}
- return tgt;
+ return cmLinkItem(resolved.Target, bt);
}
std::string cmGeneratorTarget::GetPDBDirectory(const std::string& config) const
@@ -5444,19 +6621,20 @@ std::string cmGeneratorTarget::GetPDBDirectory(const std::string& config) const
return "";
}
-bool cmGeneratorTarget::HasImplibGNUtoMS() const
+bool cmGeneratorTarget::HasImplibGNUtoMS(std::string const& config) const
{
- return this->HasImportLibrary() && this->GetPropertyAsBool("GNUtoMS");
+ return this->HasImportLibrary(config) && this->GetPropertyAsBool("GNUtoMS");
}
-bool cmGeneratorTarget::GetImplibGNUtoMS(std::string const& gnuName,
+bool cmGeneratorTarget::GetImplibGNUtoMS(std::string const& config,
+ std::string const& gnuName,
std::string& out,
const char* newExt) const
{
- if (this->HasImplibGNUtoMS() && gnuName.size() > 6 &&
+ if (this->HasImplibGNUtoMS(config) && gnuName.size() > 6 &&
gnuName.substr(gnuName.size() - 6) == ".dll.a") {
- out = gnuName.substr(0, gnuName.size() - 6);
- out += newExt ? newExt : ".lib";
+ out = cmStrCat(cm::string_view(gnuName).substr(0, gnuName.size() - 6),
+ newExt ? newExt : ".lib");
return true;
}
return false;
@@ -5468,19 +6646,31 @@ bool cmGeneratorTarget::IsExecutableWithExports() const
this->GetPropertyAsBool("ENABLE_EXPORTS"));
}
-bool cmGeneratorTarget::HasImportLibrary() const
+bool cmGeneratorTarget::HasImportLibrary(std::string const& config) const
{
return (this->IsDLLPlatform() &&
(this->GetType() == cmStateEnums::SHARED_LIBRARY ||
- this->IsExecutableWithExports()));
+ this->IsExecutableWithExports()) &&
+ // Assemblies which have only managed code do not have
+ // import libraries.
+ this->GetManagedType(config) != ManagedType::Managed) ||
+ (this->Target->IsAIX() && this->IsExecutableWithExports());
+}
+
+bool cmGeneratorTarget::NeedImportLibraryName(std::string const& config) const
+{
+ return this->HasImportLibrary(config) ||
+ // On DLL platforms we always generate the import library name
+ // just in case the sources have export markup.
+ (this->IsDLLPlatform() &&
+ (this->GetType() == cmStateEnums::EXECUTABLE ||
+ this->GetType() == cmStateEnums::MODULE_LIBRARY));
}
std::string cmGeneratorTarget::GetSupportDirectory() const
{
- std::string dir = this->LocalGenerator->GetCurrentBinaryDirectory();
- dir += cmake::GetCMakeFilesDirectory();
- dir += "/";
- dir += this->GetName();
+ std::string dir = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/", this->GetName());
#if defined(__VMS)
dir += "_dir";
#else
@@ -5495,6 +6685,7 @@ bool cmGeneratorTarget::IsLinkable() const
this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::MODULE_LIBRARY ||
this->GetType() == cmStateEnums::UNKNOWN_LIBRARY ||
+ this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
this->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
this->IsExecutableWithExports());
}
@@ -5524,3 +6715,52 @@ bool cmGeneratorTarget::IsCFBundleOnApple() const
return (this->GetType() == cmStateEnums::MODULE_LIBRARY &&
this->Makefile->IsOn("APPLE") && this->GetPropertyAsBool("BUNDLE"));
}
+
+cmGeneratorTarget::ManagedType cmGeneratorTarget::CheckManagedType(
+ std::string const& propval) const
+{
+ // The type of the managed assembly (mixed unmanaged C++ and C++/CLI,
+ // or only C++/CLI) does only depend on whether the property is an empty
+ // string or contains any value at all. In Visual Studio generators
+ // this propval is prepended with /clr[:] which results in:
+ //
+ // 1. propval does not exist: no /clr flag, unmanaged target, has import
+ // lib
+ // 2. empty propval: add /clr as flag, mixed unmanaged/managed
+ // target, has import lib
+ // 3. any value (safe,pure): add /clr:[propval] as flag, target with
+ // managed code only, no import lib
+ return propval.empty() ? ManagedType::Mixed : ManagedType::Managed;
+}
+
+cmGeneratorTarget::ManagedType cmGeneratorTarget::GetManagedType(
+ const std::string& config) const
+{
+ // Only libraries and executables can be managed targets.
+ if (this->GetType() > cmStateEnums::SHARED_LIBRARY) {
+ return ManagedType::Undefined;
+ }
+
+ if (this->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ return ManagedType::Native;
+ }
+
+ // Check imported target.
+ if (this->IsImported()) {
+ if (cmGeneratorTarget::ImportInfo const* info =
+ this->GetImportInfo(config)) {
+ return info->Managed;
+ }
+ return ManagedType::Undefined;
+ }
+
+ // Check for explicitly set clr target property.
+ if (auto* clr = this->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
+ return this->CheckManagedType(clr);
+ }
+
+ // C# targets are always managed. This language specific check
+ // is added to avoid that the COMMON_LANGUAGE_RUNTIME target property
+ // has to be set manually for C# targets.
+ return this->IsCSharpOnly() ? ManagedType::Managed : ManagedType::Native;
+}
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 52147e319..493eafcf0 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -3,20 +3,22 @@
#ifndef cmGeneratorTarget_h
#define cmGeneratorTarget_h
-#include "cmConfigure.h"
-
-#include "cmLinkItem.h"
-#include "cmListFileCache.h"
-#include "cmPolicies.h"
-#include "cmStateTypes.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <map>
#include <set>
-#include <stddef.h>
#include <string>
+#include <unordered_map>
+#include <unordered_set>
#include <utility>
#include <vector>
+#include "cmLinkItem.h"
+#include "cmListFileCache.h"
+#include "cmPolicies.h"
+#include "cmStateTypes.h"
+
class cmComputeLinkInformation;
class cmCustomCommand;
class cmGlobalGenerator;
@@ -25,14 +27,18 @@ class cmMakefile;
class cmSourceFile;
class cmTarget;
+struct cmGeneratorExpressionContext;
+struct cmGeneratorExpressionDAGChecker;
+
class cmGeneratorTarget
{
- CM_DISABLE_COPY(cmGeneratorTarget)
-
public:
cmGeneratorTarget(cmTarget*, cmLocalGenerator* lg);
~cmGeneratorTarget();
+ cmGeneratorTarget(cmGeneratorTarget const&) = delete;
+ cmGeneratorTarget& operator=(cmGeneratorTarget const&) = delete;
+
cmLocalGenerator* GetLocalGenerator() const;
cmGlobalGenerator* GetGlobalGenerator() const;
@@ -68,12 +74,15 @@ public:
std::string GetExportName() const;
std::vector<std::string> GetPropertyKeys() const;
+ //! Might return a nullptr if the property is not set or invalid
const char* GetProperty(const std::string& prop) const;
+ //! Always returns a valid pointer
+ const char* GetSafeProperty(const std::string& prop) const;
bool GetPropertyAsBool(const std::string& prop) const;
void GetSourceFiles(std::vector<cmSourceFile*>& files,
const std::string& config) const;
- void GetSourceFilesWithoutObjectLibraries(std::vector<cmSourceFile*>& files,
- const std::string& config) const;
+ std::vector<BT<cmSourceFile*>> GetSourceFiles(
+ std::string const& config) const;
/** Source file kinds (classifications).
Generators use this to decide how to treat a source file. */
@@ -90,13 +99,14 @@ public:
SourceKindModuleDefinition,
SourceKindObjectSource,
SourceKindResx,
- SourceKindXaml
+ SourceKindXaml,
+ SourceKindUnityBatched
};
/** A source file paired with a kind (classification). */
struct SourceAndKind
{
- cmSourceFile* Source;
+ BT<cmSourceFile*> Source;
SourceKind Kind;
};
@@ -107,11 +117,7 @@ public:
std::set<std::string> ExpectedResxHeaders;
std::set<std::string> ExpectedXamlHeaders;
std::set<std::string> ExpectedXamlSources;
- bool Initialized;
- KindedSources()
- : Initialized(false)
- {
- }
+ bool Initialized = false;
};
/** Get all sources needed for a configuration with kinds assigned. */
@@ -170,6 +176,8 @@ public:
const char* GetFeature(const std::string& feature,
const std::string& config) const;
+ const char* GetLinkPIEProperty(const std::string& config) const;
+
bool IsIPOEnabled(std::string const& lang, std::string const& config) const;
bool IsLinkInterfaceDependentBoolProperty(const std::string& p,
@@ -260,20 +268,17 @@ public:
BundleDirectoryLevel level) const;
/** Return the install name directory for the target in the
- * build tree. For example: "\@rpath/", "\@loader_path/",
- * or "/full/path/to/library". */
+ * build tree. For example: "\@rpath/", "\@loader_path/",
+ * or "/full/path/to/library". */
std::string GetInstallNameDirForBuildTree(const std::string& config) const;
/** Return the install name directory for the target in the
- * install tree. For example: "\@rpath/" or "\@loader_path/". */
+ * install tree. For example: "\@rpath/" or "\@loader_path/". */
std::string GetInstallNameDirForInstallTree() const;
cmListFileBacktrace GetBacktrace() const;
- const std::vector<std::string>& GetLinkDirectories() const;
-
- std::set<std::string> const& GetUtilities() const;
- cmListFileBacktrace const* GetUtilityBacktrace(const std::string& u) const;
+ std::set<BT<std::string>> const& GetUtilities() const;
bool LinkLanguagePropagatesToDependents() const
{
@@ -282,7 +287,7 @@ public:
/** Get the macro to define when building sources in this target.
If no macro should be defined null is returned. */
- const char* GetExportMacro() const;
+ const std::string* GetExportMacro() const;
/** Get the soname of the target. Allowed only for a shared library. */
std::string GetSOName(const std::string& config) const;
@@ -354,7 +359,15 @@ public:
cmOptionalLinkImplementation& impl,
const cmGeneratorTarget* head) const;
- cmGeneratorTarget* FindTargetToLink(std::string const& name) const;
+ struct TargetOrString
+ {
+ std::string String;
+ cmGeneratorTarget* Target = nullptr;
+ };
+ TargetOrString ResolveTargetReference(std::string const& name) const;
+
+ cmLinkItem ResolveLinkItem(std::string const& name,
+ cmListFileBacktrace const& bt) const;
// Compute the set of languages compiled by the target. This is
// computed every time it is called because the languages can change
@@ -364,6 +377,8 @@ public:
void GetLanguages(std::set<std::string>& languages,
std::string const& config) const;
+ bool IsCSharpOnly() const;
+
void GetObjectLibrariesCMP0026(
std::vector<cmGeneratorTarget*>& objlibs) const;
@@ -398,22 +413,72 @@ public:
std::string const& config) const;
/** Get the include directories for this target. */
- std::vector<std::string> GetIncludeDirectories(
+ std::vector<BT<std::string>> GetIncludeDirectories(
const std::string& config, const std::string& lang) const;
void GetCompileOptions(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const;
+ std::vector<BT<std::string>> GetCompileOptions(
+ std::string const& config, std::string const& language) const;
void GetCompileFeatures(std::vector<std::string>& features,
const std::string& config) const;
+ std::vector<BT<std::string>> GetCompileFeatures(
+ std::string const& config) const;
void GetCompileDefinitions(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const;
+ std::vector<BT<std::string>> GetCompileDefinitions(
+ std::string const& config, std::string const& language) const;
+
+ void GetLinkOptions(std::vector<std::string>& result,
+ const std::string& config,
+ const std::string& language) const;
+ std::vector<BT<std::string>> GetLinkOptions(
+ std::string const& config, std::string const& language) const;
+
+ void GetStaticLibraryLinkOptions(std::vector<std::string>& result,
+ const std::string& config,
+ const std::string& language) const;
+ std::vector<BT<std::string>> GetStaticLibraryLinkOptions(
+ std::string const& config, std::string const& language) const;
+
+ void GetLinkDirectories(std::vector<std::string>& result,
+ const std::string& config,
+ const std::string& language) const;
+ std::vector<BT<std::string>> GetLinkDirectories(
+ std::string const& config, std::string const& language) const;
+
+ void GetLinkDepends(std::vector<std::string>& result,
+ const std::string& config,
+ const std::string& language) const;
+ std::vector<BT<std::string>> GetLinkDepends(
+ std::string const& config, std::string const& language) const;
+
+ std::vector<BT<std::string>> GetPrecompileHeaders(
+ const std::string& config, const std::string& language) const;
+
+ std::string GetPchHeader(const std::string& config,
+ const std::string& language) const;
+ std::string GetPchSource(const std::string& config,
+ const std::string& language) const;
+ std::string GetPchFileObject(const std::string& config,
+ const std::string& language);
+ std::string GetPchFile(const std::string& config,
+ const std::string& language);
+ std::string GetPchCreateCompileOptions(const std::string& config,
+ const std::string& language);
+ std::string GetPchUseCompileOptions(const std::string& config,
+ const std::string& language);
+
+ void AddSourceFileToUnityBatch(const std::string& sourceFilename);
+ bool IsSourceFilePartOfUnityBatch(const std::string& sourceFilename) 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;
@@ -463,6 +528,9 @@ public:
OutputInfo const* GetOutputInfo(const std::string& config) const;
+ // Get the target PDB base name.
+ std::string GetPDBOutputName(const std::string& config) const;
+
/** Get the name of the pdb file for the target. */
std::string GetPDBName(const std::string& config = "") const;
@@ -476,7 +544,7 @@ public:
CompileInfo const* GetCompileInfo(const std::string& config) const;
- typedef std::map<std::string, CompileInfo> CompileInfoMapType;
+ using CompileInfoMapType = std::map<std::string, CompileInfo>;
mutable CompileInfoMapType CompileInfoMap;
bool IsNullImpliedByLinkLibraries(const std::string& p) const;
@@ -491,7 +559,24 @@ public:
std::string GetOutputName(const std::string& config,
cmStateEnums::ArtifactType artifact) const;
- void AddSource(const std::string& src);
+ /** Get target file prefix */
+ std::string GetFilePrefix(const std::string& config,
+ cmStateEnums::ArtifactType artifact =
+ cmStateEnums::RuntimeBinaryArtifact) const;
+ /** Get target file prefix */
+ std::string GetFileSuffix(const std::string& config,
+ cmStateEnums::ArtifactType artifact =
+ cmStateEnums::RuntimeBinaryArtifact) const;
+
+ /** Get target file postfix */
+ std::string GetFilePostfix(const std::string& config) const;
+
+ /** Clears cached meta data for local and external source files.
+ * The meta data will be recomputed on demand.
+ */
+ void ClearSourcesCache();
+
+ void AddSource(const std::string& src, bool before = false);
void AddTracedSources(std::vector<std::string> const& srcs);
/**
@@ -517,30 +602,31 @@ public:
};
struct SourceFileFlags
{
- SourceFileFlags()
- : Type(SourceFileTypeNormal)
- , MacFolder(CM_NULLPTR)
- {
- }
- SourceFileType Type;
- const char* MacFolder; // location inside Mac content folders
+ SourceFileType Type = SourceFileTypeNormal;
+ const char* MacFolder = nullptr; // location inside Mac content folders
};
void GetAutoUicOptions(std::vector<std::string>& result,
const std::string& config) const;
+ struct Names
+ {
+ std::string Base;
+ std::string Output;
+ std::string Real;
+ std::string ImportLibrary;
+ std::string PDB;
+ std::string SharedObject;
+ };
+
/** Get the names of the executable needed to generate a build rule
that takes into account executable version numbers. This should
be called only on an executable target. */
- void GetExecutableNames(std::string& name, std::string& realName,
- std::string& impName, std::string& pdbName,
- const std::string& config) const;
+ Names GetExecutableNames(const std::string& config) const;
/** Get the names of the library needed to generate a build rule
that takes into account shared library version numbers. This
should be called only on a library target. */
- void GetLibraryNames(std::string& name, std::string& soName,
- std::string& realName, std::string& impName,
- std::string& pdbName, const std::string& config) const;
+ Names GetLibraryNames(const std::string& config) const;
/**
* Compute whether this target must be relinked before installing.
@@ -556,21 +642,21 @@ public:
pdb output directory is given. */
std::string GetPDBDirectory(const std::string& config) const;
- ///! Return the preferred linker language for this target
+ //! Return the preferred linker language for this target
std::string GetLinkerLanguage(const std::string& config) const;
/** Does this target have a GNU implib to convert to MS format? */
- bool HasImplibGNUtoMS() const;
+ bool HasImplibGNUtoMS(std::string const& config) const;
/** Convert the given GNU import library name (.dll.a) to a name with a new
extension (.lib or ${CMAKE_IMPORT_LIBRARY_SUFFIX}). */
- bool GetImplibGNUtoMS(std::string const& gnuName, std::string& out,
- const char* newExt = CM_NULLPTR) const;
+ bool GetImplibGNUtoMS(std::string const& config, std::string const& gnuName,
+ std::string& out, const char* newExt = nullptr) const;
bool IsExecutableWithExports() const;
/** Return whether or not the target has a DLL import library. */
- bool HasImportLibrary() const;
+ bool HasImportLibrary(std::string const& config) const;
/** Get a build-tree directory in which to place target support files. */
std::string GetSupportDirectory() const;
@@ -591,6 +677,19 @@ public:
/** Return whether this target is a CFBundle (plugin) on Apple. */
bool IsCFBundleOnApple() const;
+ /** Assembly types. The order of the values of this enum is relevant
+ because of smaller/larger comparison operations! */
+ enum ManagedType
+ {
+ Undefined = 0, // target is no lib or executable
+ Native, // target compiles to unmanaged binary.
+ Mixed, // target compiles to mixed (managed and unmanaged) binary.
+ Managed // target compiles to managed binary.
+ };
+
+ /** Return the type of assembly this target compiles to. */
+ ManagedType GetManagedType(const std::string& config) const;
+
struct SourceFileFlags GetTargetSourceFileFlags(
const cmSourceFile* sf) const;
@@ -600,7 +699,14 @@ public:
class TargetPropertyEntry;
- bool HaveInstallTreeRPATH() const;
+ std::string EvaluateInterfaceProperty(
+ std::string const& prop, cmGeneratorExpressionContext* context,
+ cmGeneratorExpressionDAGChecker* dagCheckerParent) const;
+
+ bool HaveInstallTreeRPATH(const std::string& config) const;
+
+ bool GetBuildRPATH(const std::string& config, std::string& rpath) const;
+ bool GetInstallRPATH(const std::string& config, std::string& rpath) const;
/** Whether this library has \@rpath and platform supports it. */
bool HasMacOSXRpathInstallNameDir(const std::string& config) const;
@@ -622,7 +728,7 @@ public:
no soname at all. */
bool IsImportedSharedLibWithoutSOName(const std::string& config) const;
- const char* ImportedGetLocation(const std::string& config) const;
+ std::string ImportedGetLocation(const std::string& config) const;
/** Get the target major and minor version numbers interpreted from
the VERSION property. Version 0 is returned if the property is
@@ -640,7 +746,7 @@ public:
const char* GetSourcesProperty() const;
private:
- void AddSourceCommon(const std::string& src);
+ void AddSourceCommon(const std::string& src, bool before = false);
std::string CreateFortranModuleDirectory(
std::string const& working_dir) const;
@@ -652,11 +758,11 @@ private:
{
std::vector<cmSourceFile*> Depends;
};
- typedef std::map<cmSourceFile const*, SourceEntry> SourceEntriesType;
+ using SourceEntriesType = std::map<cmSourceFile const*, SourceEntry>;
SourceEntriesType SourceDepends;
mutable std::map<cmSourceFile const*, std::string> Objects;
std::set<cmSourceFile const*> ExplicitObjectName;
- mutable std::map<std::string, std::vector<std::string> > SystemIncludesCache;
+ mutable std::map<std::string, std::vector<std::string>> SystemIncludesCache;
mutable std::string ExportMacro;
@@ -666,6 +772,15 @@ private:
mutable std::map<std::string, bool> DebugCompatiblePropertiesDone;
+ bool NeedImportLibraryName(std::string const& config) const;
+
+ const char* GetFilePrefixInternal(std::string const& config,
+ cmStateEnums::ArtifactType artifact,
+ const std::string& language = "") const;
+ const char* GetFileSuffixInternal(std::string const& config,
+ cmStateEnums::ArtifactType artifact,
+ const std::string& language = "") const;
+
std::string GetFullNameInternal(const std::string& config,
cmStateEnums::ArtifactType artifact) const;
void GetFullNameInternal(const std::string& config,
@@ -673,7 +788,7 @@ private:
std::string& outPrefix, std::string& outBase,
std::string& outSuffix) const;
- typedef std::map<std::string, LinkClosure> LinkClosureMapType;
+ using LinkClosureMapType = std::map<std::string, LinkClosure>;
mutable LinkClosureMapType LinkClosureMap;
// Returns ARCHIVE, LIBRARY, or RUNTIME based on platform and type.
@@ -696,16 +811,12 @@ private:
struct CompatibleInterfaces : public CompatibleInterfacesBase
{
- CompatibleInterfaces()
- : Done(false)
- {
- }
- bool Done;
+ bool Done = false;
};
mutable std::map<std::string, CompatibleInterfaces> CompatibleInterfacesMap;
- typedef std::map<std::string, cmComputeLinkInformation*>
- cmTargetLinkInformationMap;
+ using cmTargetLinkInformationMap =
+ std::map<std::string, cmComputeLinkInformation*>;
mutable cmTargetLinkInformationMap LinkInformation;
void CheckPropertyCompatibility(cmComputeLinkInformation* info,
@@ -713,15 +824,11 @@ private:
struct LinkImplClosure : public std::vector<cmGeneratorTarget const*>
{
- LinkImplClosure()
- : Done(false)
- {
- }
- bool Done;
+ bool Done = false;
};
mutable std::map<std::string, LinkImplClosure> LinkImplClosureMap;
- typedef std::map<std::string, cmHeadToLinkInterfaceMap> LinkInterfaceMapType;
+ using LinkInterfaceMapType = std::map<std::string, cmHeadToLinkInterfaceMap>;
mutable LinkInterfaceMapType LinkInterfaceMap;
mutable LinkInterfaceMapType LinkInterfaceUsageRequirementsOnlyMap;
@@ -730,16 +837,15 @@ private:
cmHeadToLinkInterfaceMap& GetHeadToLinkInterfaceUsageRequirementsMap(
std::string const& config) const;
+ std::string GetLinkInterfaceDependentStringAsBoolProperty(
+ const std::string& p, const std::string& config) const;
+
// Cache import information from properties for each configuration.
struct ImportInfo
{
- ImportInfo()
- : NoSOName(false)
- , Multiplicity(0)
- {
- }
- bool NoSOName;
- unsigned int Multiplicity;
+ bool NoSOName = false;
+ ManagedType Managed = Native;
+ unsigned int Multiplicity = 0;
std::string Location;
std::string SOName;
std::string ImportLibrary;
@@ -750,7 +856,7 @@ private:
std::string SharedDeps;
};
- typedef std::map<std::string, ImportInfo> ImportInfoMapType;
+ using ImportInfoMapType = std::map<std::string, ImportInfo>;
mutable ImportInfoMapType ImportInfoMap;
void ComputeImportInfo(std::string const& desired_config,
ImportInfo& info) const;
@@ -764,7 +870,7 @@ private:
const std::string& config, const cmGeneratorTarget* head,
bool usage_requirements_only) const;
- typedef std::map<std::string, KindedSources> KindedSourcesMapType;
+ using KindedSourcesMapType = std::map<std::string, KindedSources>;
mutable KindedSourcesMapType KindedSourcesMap;
void ComputeKindedSources(KindedSources& files,
std::string const& config) const;
@@ -772,12 +878,27 @@ private:
mutable std::vector<AllConfigSource> AllConfigSources;
void ComputeAllConfigSources() const;
+ mutable std::unordered_map<std::string, bool> MaybeInterfacePropertyExists;
+ bool MaybeHaveInterfaceProperty(std::string const& prop,
+ cmGeneratorExpressionContext* context) const;
+
std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
std::vector<TargetPropertyEntry*> CompileOptionsEntries;
std::vector<TargetPropertyEntry*> CompileFeaturesEntries;
std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
+ std::vector<TargetPropertyEntry*> LinkOptionsEntries;
+ std::vector<TargetPropertyEntry*> LinkDirectoriesEntries;
+ std::vector<TargetPropertyEntry*> PrecompileHeadersEntries;
std::vector<TargetPropertyEntry*> SourceEntries;
mutable std::set<std::string> LinkImplicitNullProperties;
+ mutable std::map<std::string, std::string> PchHeaders;
+ mutable std::map<std::string, std::string> PchSources;
+ mutable std::map<std::string, std::string> PchObjectFiles;
+ mutable std::map<std::string, std::string> PchFiles;
+ mutable std::map<std::string, std::string> PchCreateCompileOptions;
+ mutable std::map<std::string, std::string> PchUseCompileOptions;
+
+ std::unordered_set<std::string> UnityBatchedSourceFiles;
void ExpandLinkItems(std::string const& prop, std::string const& value,
std::string const& config,
@@ -786,16 +907,21 @@ private:
std::vector<cmLinkItem>& items,
bool& hadHeadSensitiveCondition) const;
void LookupLinkItems(std::vector<std::string> const& names,
+ cmListFileBacktrace const& bt,
std::vector<cmLinkItem>& items) const;
- void GetSourceFiles(std::vector<std::string>& files,
- const std::string& config) const;
+ std::vector<BT<std::string>> GetSourceFilePaths(
+ std::string const& config) const;
+ std::vector<BT<cmSourceFile*>> GetSourceFilesWithoutObjectLibraries(
+ std::string const& config) const;
+ void GetSourceFilesWithoutObjectLibraries(std::vector<cmSourceFile*>& files,
+ const std::string& config) const;
struct HeadToLinkImplementationMap
: public std::map<cmGeneratorTarget const*, cmOptionalLinkImplementation>
{
};
- typedef std::map<std::string, HeadToLinkImplementationMap> LinkImplMapType;
+ using LinkImplMapType = std::map<std::string, HeadToLinkImplementationMap>;
mutable LinkImplMapType LinkImplMap;
cmLinkImplementationLibraries const* GetLinkImplementationLibrariesInternal(
@@ -804,17 +930,17 @@ private:
cmStateEnums::ArtifactType artifact,
std::string& out) const;
- typedef std::map<std::string, OutputInfo> OutputInfoMapType;
+ using OutputInfoMapType = std::map<std::string, OutputInfo>;
mutable OutputInfoMapType OutputInfoMap;
- typedef std::map<std::string, ModuleDefinitionInfo>
- ModuleDefinitionInfoMapType;
+ using ModuleDefinitionInfoMapType =
+ std::map<std::string, ModuleDefinitionInfo>;
mutable ModuleDefinitionInfoMapType ModuleDefinitionInfoMap;
void ComputeModuleDefinitionInfo(std::string const& config,
ModuleDefinitionInfo& info) const;
- typedef std::pair<std::string, cmStateEnums::ArtifactType> OutputNameKey;
- typedef std::map<OutputNameKey, std::string> OutputNameMapType;
+ using OutputNameKey = std::pair<std::string, cmStateEnums::ArtifactType>;
+ using OutputNameMapType = std::map<OutputNameKey, std::string>;
mutable OutputNameMapType OutputNameMap;
mutable std::set<cmLinkItem> UtilityItems;
cmPolicies::PolicyMap PolicyMap;
@@ -824,14 +950,21 @@ private:
mutable bool DebugCompileOptionsDone;
mutable bool DebugCompileFeaturesDone;
mutable bool DebugCompileDefinitionsDone;
+ mutable bool DebugLinkOptionsDone;
+ mutable bool DebugLinkDirectoriesDone;
+ mutable bool DebugPrecompileHeadersDone;
mutable bool DebugSourcesDone;
mutable bool LinkImplementationLanguageIsContextDependent;
mutable bool UtilityItemsDone;
- bool DLLPlatform;
bool ComputePDBOutputDir(const std::string& kind, const std::string& config,
std::string& out) const;
+ ManagedType CheckManagedType(std::string const& propval) const;
+
+ bool GetRPATH(const std::string& config, const std::string& prop,
+ std::string& rpath) const;
+
public:
const std::vector<const cmGeneratorTarget*>& GetLinkImplementationClosure(
const std::string& config) const;
diff --git a/Source/cmGetCMakePropertyCommand.cxx b/Source/cmGetCMakePropertyCommand.cxx
index 5ba3326cb..ff4e312f3 100644
--- a/Source/cmGetCMakePropertyCommand.cxx
+++ b/Source/cmGetCMakePropertyCommand.cxx
@@ -4,19 +4,18 @@
#include <set>
-#include "cmAlgorithms.h"
+#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmState.h"
-
-class cmExecutionStatus;
+#include "cmStringAlgorithms.h"
// cmGetCMakePropertyCommand
-bool cmGetCMakePropertyCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmGetCMakePropertyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
@@ -24,29 +23,29 @@ bool cmGetCMakePropertyCommand::InitialPass(
std::string output = "NOTFOUND";
if (args[1] == "VARIABLES") {
- if (const char* varsProp = this->Makefile->GetProperty("VARIABLES")) {
+ if (const char* varsProp = status.GetMakefile().GetProperty("VARIABLES")) {
output = varsProp;
}
} else if (args[1] == "MACROS") {
output.clear();
- if (const char* macrosProp = this->Makefile->GetProperty("MACROS")) {
+ if (const char* macrosProp = status.GetMakefile().GetProperty("MACROS")) {
output = macrosProp;
}
} else if (args[1] == "COMPONENTS") {
const std::set<std::string>* components =
- this->Makefile->GetGlobalGenerator()->GetInstallComponents();
+ status.GetMakefile().GetGlobalGenerator()->GetInstallComponents();
output = cmJoin(*components, ";");
} else {
- const char* prop = CM_NULLPTR;
+ const char* prop = nullptr;
if (!args[1].empty()) {
- prop = this->Makefile->GetState()->GetGlobalProperty(args[1]);
+ prop = status.GetMakefile().GetState()->GetGlobalProperty(args[1]);
}
if (prop) {
output = prop;
}
}
- this->Makefile->AddDefinition(variable, output.c_str());
+ status.GetMakefile().AddDefinition(variable, output);
return true;
}
diff --git a/Source/cmGetCMakePropertyCommand.h b/Source/cmGetCMakePropertyCommand.h
index 9dfc40fda..7a6728cfe 100644
--- a/Source/cmGetCMakePropertyCommand.h
+++ b/Source/cmGetCMakePropertyCommand.h
@@ -3,26 +3,14 @@
#ifndef cmGetCMakePropertyCommand_h
#define cmGetCMakePropertyCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmGetCMakePropertyCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE { return new cmGetCMakePropertyCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the input file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmGetCMakePropertyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx
index 1005b1543..64438d50a 100644
--- a/Source/cmGetDirectoryPropertyCommand.cxx
+++ b/Source/cmGetDirectoryPropertyCommand.cxx
@@ -2,51 +2,54 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGetDirectoryPropertyCommand.h"
+#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmake.h"
-class cmExecutionStatus;
+namespace {
+void StoreResult(cmMakefile& makefile, std::string const& variable,
+ const char* prop);
+}
// cmGetDirectoryPropertyCommand
-bool cmGetDirectoryPropertyCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
- std::vector<std::string>::const_iterator i = args.begin();
+ auto i = args.begin();
std::string const& variable = *i;
++i;
// get the directory argument if there is one
- cmMakefile* dir = this->Makefile;
+ cmMakefile* dir = &status.GetMakefile();
if (*i == "DIRECTORY") {
++i;
if (i == args.end()) {
- this->SetError(
+ status.SetError(
"DIRECTORY argument provided without subsequent arguments");
return false;
}
std::string sd = *i;
// make sure the start dir is a full path
- if (!cmSystemTools::FileIsFullPath(sd.c_str())) {
- sd = this->Makefile->GetCurrentSourceDirectory();
- sd += "/";
- sd += *i;
+ if (!cmSystemTools::FileIsFullPath(sd)) {
+ sd = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', *i);
}
// The local generators are associated with collapsed paths.
sd = cmSystemTools::CollapseFullPath(sd);
// lookup the makefile from the directory name
- dir = this->Makefile->GetGlobalGenerator()->FindMakefile(sd);
+ dir = status.GetMakefile().GetGlobalGenerator()->FindMakefile(sd);
if (!dir) {
- this->SetError(
+ status.SetError(
"DIRECTORY argument provided but requested directory not found. "
"This could be because the directory argument was invalid or, "
"it is valid but has not been processed yet.");
@@ -61,26 +64,27 @@ bool cmGetDirectoryPropertyCommand::InitialPass(
if (*i == "DEFINITION") {
++i;
if (i == args.end()) {
- this->SetError("A request for a variable definition was made without "
- "providing the name of the variable to get.");
+ status.SetError("A request for a variable definition was made without "
+ "providing the name of the variable to get.");
return false;
}
- std::string output = dir->GetSafeDefinition(*i);
- this->Makefile->AddDefinition(variable, output.c_str());
+ std::string const& output = dir->GetSafeDefinition(*i);
+ status.GetMakefile().AddDefinition(variable, output);
return true;
}
- const char* prop = CM_NULLPTR;
+ const char* prop = nullptr;
if (!i->empty()) {
if (*i == "DEFINITIONS") {
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0059)) {
+ switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0059)) {
case cmPolicies::WARN:
- this->Makefile->IssueMessage(
- cmake::AUTHOR_WARNING,
+ status.GetMakefile().IssueMessage(
+ MessageType::AUTHOR_WARNING,
cmPolicies::GetPolicyWarning(cmPolicies::CMP0059));
CM_FALLTHROUGH;
case cmPolicies::OLD:
- this->StoreResult(variable, this->Makefile->GetDefineFlagsCMP0059());
+ StoreResult(status.GetMakefile(), variable,
+ status.GetMakefile().GetDefineFlagsCMP0059());
return true;
case cmPolicies::NEW:
case cmPolicies::REQUIRED_ALWAYS:
@@ -90,16 +94,14 @@ bool cmGetDirectoryPropertyCommand::InitialPass(
}
prop = dir->GetProperty(*i);
}
- this->StoreResult(variable, prop);
+ StoreResult(status.GetMakefile(), variable, prop);
return true;
}
-void cmGetDirectoryPropertyCommand::StoreResult(std::string const& variable,
- const char* prop)
+namespace {
+void StoreResult(cmMakefile& makefile, std::string const& variable,
+ const char* prop)
{
- if (prop) {
- this->Makefile->AddDefinition(variable, prop);
- return;
- }
- this->Makefile->AddDefinition(variable, "");
+ makefile.AddDefinition(variable, prop ? prop : "");
+}
}
diff --git a/Source/cmGetDirectoryPropertyCommand.h b/Source/cmGetDirectoryPropertyCommand.h
index 7d9795065..f356ea5b4 100644
--- a/Source/cmGetDirectoryPropertyCommand.h
+++ b/Source/cmGetDirectoryPropertyCommand.h
@@ -3,29 +3,14 @@
#ifndef cmGetDirectoryPropertyCommand_h
#define cmGetDirectoryPropertyCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmGetDirectoryPropertyCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE { return new cmGetDirectoryPropertyCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the input file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- void StoreResult(const std::string& variable, const char* prop);
-};
+bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx
index c23684c22..7d91a7570 100644
--- a/Source/cmGetFilenameComponentCommand.cxx
+++ b/Source/cmGetFilenameComponentCommand.cxx
@@ -2,26 +2,26 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGetFilenameComponentCommand.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
-
// cmGetFilenameComponentCommand
-bool cmGetFilenameComponentCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmGetFilenameComponentCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 3) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
// Check and see if the value has been stored in the cache
// already, if so use that value
- if (args.size() >= 4 && args[args.size() - 1] == "CACHE") {
- const char* cacheValue = this->Makefile->GetDefinition(args[0]);
- if (cacheValue && !cmSystemTools::IsNOTFOUND(cacheValue)) {
+ if (args.size() >= 4 && args.back() == "CACHE") {
+ const char* cacheValue = status.GetMakefile().GetDefinition(args.front());
+ if (cacheValue && !cmIsNOTFOUND(cacheValue)) {
return true;
}
}
@@ -32,7 +32,7 @@ bool cmGetFilenameComponentCommand::InitialPass(
// Check the registry as the target application would view it.
cmSystemTools::KeyWOW64 view = cmSystemTools::KeyWOW64_32;
cmSystemTools::KeyWOW64 other_view = cmSystemTools::KeyWOW64_64;
- if (this->Makefile->PlatformIs64Bit()) {
+ if (status.GetMakefile().PlatformIs64Bit()) {
view = cmSystemTools::KeyWOW64_64;
other_view = cmSystemTools::KeyWOW64_32;
}
@@ -60,16 +60,43 @@ bool cmGetFilenameComponentCommand::InitialPass(
}
}
}
- cmSystemTools::SplitProgramFromArgs(filename, result, programArgs);
+
+ // First assume the path to the program was specified with no
+ // arguments and with no quoting or escaping for spaces.
+ // Only bother doing this if there is non-whitespace.
+ if (!cmTrimWhitespace(filename).empty()) {
+ result = cmSystemTools::FindProgram(filename);
+ }
+
+ // If that failed then assume a command-line string was given
+ // and split the program part from the rest of the arguments.
+ if (result.empty()) {
+ std::string program;
+ if (cmSystemTools::SplitProgramFromArgs(filename, program,
+ programArgs)) {
+ if (cmSystemTools::FileExists(program)) {
+ result = program;
+ } else {
+ result = cmSystemTools::FindProgram(program);
+ }
+ }
+ if (result.empty()) {
+ programArgs.clear();
+ }
+ }
} else if (args[2] == "EXT") {
result = cmSystemTools::GetFilenameExtension(filename);
} else if (args[2] == "NAME_WE") {
result = cmSystemTools::GetFilenameWithoutExtension(filename);
+ } else if (args[2] == "LAST_EXT") {
+ result = cmSystemTools::GetFilenameLastExtension(filename);
+ } else if (args[2] == "NAME_WLE") {
+ result = cmSystemTools::GetFilenameWithoutLastExtension(filename);
} else if (args[2] == "ABSOLUTE" || args[2] == "REALPATH") {
// If the path given is relative, evaluate it relative to the
// current source directory unless the user passes a different
// base directory.
- std::string baseDir = this->Makefile->GetCurrentSourceDirectory();
+ std::string baseDir = status.GetMakefile().GetCurrentSourceDirectory();
for (unsigned int i = 3; i < args.size(); ++i) {
if (args[i] == "BASE_DIR") {
++i;
@@ -86,24 +113,24 @@ bool cmGetFilenameComponentCommand::InitialPass(
}
} else {
std::string err = "unknown component " + args[2];
- this->SetError(err);
+ status.SetError(err);
return false;
}
- if (args.size() >= 4 && args[args.size() - 1] == "CACHE") {
+ if (args.size() >= 4 && args.back() == "CACHE") {
if (!programArgs.empty() && !storeArgs.empty()) {
- this->Makefile->AddCacheDefinition(
+ status.GetMakefile().AddCacheDefinition(
storeArgs, programArgs.c_str(), "",
args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING);
}
- this->Makefile->AddCacheDefinition(
- args[0], result.c_str(), "",
+ status.GetMakefile().AddCacheDefinition(
+ args.front(), result.c_str(), "",
args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING);
} else {
if (!programArgs.empty() && !storeArgs.empty()) {
- this->Makefile->AddDefinition(storeArgs, programArgs.c_str());
+ status.GetMakefile().AddDefinition(storeArgs, programArgs);
}
- this->Makefile->AddDefinition(args[0], result.c_str());
+ status.GetMakefile().AddDefinition(args.front(), result);
}
return true;
diff --git a/Source/cmGetFilenameComponentCommand.h b/Source/cmGetFilenameComponentCommand.h
index c8a23c70e..db5293b2a 100644
--- a/Source/cmGetFilenameComponentCommand.h
+++ b/Source/cmGetFilenameComponentCommand.h
@@ -3,35 +3,20 @@
#ifndef cmGetFilenameComponentCommand_h
#define cmGetFilenameComponentCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmGetFilenameComponentCommand
+/**
* \brief Get a specific component of a filename.
*
* cmGetFilenameComponentCommand is a utility command used to get the path,
* name, extension or name without extension of a full filename.
*/
-class cmGetFilenameComponentCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmGetFilenameComponentCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmGetFilenameComponentCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmGetPipes.cxx b/Source/cmGetPipes.cxx
new file mode 100644
index 000000000..4eda1c54a
--- /dev/null
+++ b/Source/cmGetPipes.cxx
@@ -0,0 +1,49 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmGetPipes.h"
+
+#include <fcntl.h>
+
+#include "cm_uv.h"
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+# include <io.h>
+
+int cmGetPipes(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 <cerrno>
+
+# include <unistd.h>
+
+int cmGetPipes(int* fds)
+{
+ 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
diff --git a/Source/cmGetPipes.h b/Source/cmGetPipes.h
new file mode 100644
index 000000000..2a46b51b3
--- /dev/null
+++ b/Source/cmGetPipes.h
@@ -0,0 +1,8 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmGetPipes_h
+#define cmGetPipes_h
+
+int cmGetPipes(int* fds);
+
+#endif
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index ddecdf621..947d893db 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -2,41 +2,81 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGetPropertyCommand.h"
-#include <sstream>
-
+#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmInstalledFile.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmPropertyDefinition.h"
#include "cmSourceFile.h"
#include "cmState.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetPropertyComputer.h"
#include "cmTest.h"
#include "cmake.h"
-class cmExecutionStatus;
class cmMessenger;
-cmGetPropertyCommand::cmGetPropertyCommand()
+namespace {
+enum OutType
{
- this->InfoType = OutValue;
+ OutValue,
+ OutDefined,
+ OutBriefDoc,
+ OutFullDoc,
+ OutSet
+};
+
+// Implementation of result storage.
+bool StoreResult(OutType infoType, cmMakefile& makefile,
+ const std::string& variable, const char* value);
+
+// Implementation of each property type.
+bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name,
+ OutType infoType, const std::string& variable,
+ const std::string& propertyName);
+bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name,
+ OutType infoType, const std::string& variable,
+ const std::string& propertyName);
+bool HandleTargetMode(cmExecutionStatus& status, const std::string& name,
+ OutType infoType, const std::string& variable,
+ const std::string& propertyName);
+bool HandleSourceMode(cmExecutionStatus& status, const std::string& name,
+ OutType infoType, const std::string& variable,
+ const std::string& propertyName);
+bool HandleTestMode(cmExecutionStatus& status, const std::string& name,
+ OutType infoType, const std::string& variable,
+ const std::string& propertyName);
+bool HandleVariableMode(cmExecutionStatus& status, const std::string& name,
+ OutType infoType, const std::string& variable,
+ const std::string& propertyName);
+bool HandleCacheMode(cmExecutionStatus& status, const std::string& name,
+ OutType infoType, const std::string& variable,
+ const std::string& propertyName);
+bool HandleInstallMode(cmExecutionStatus& status, const std::string& name,
+ OutType infoType, const std::string& variable,
+ const std::string& propertyName);
}
-bool cmGetPropertyCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmGetPropertyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
+ OutType infoType = OutValue;
if (args.size() < 3) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
// The cmake variable in which to store the result.
- this->Variable = args[0];
+ const std::string variable = args[0];
+
+ std::string name;
+ std::string propertyName;
// Get the scope from which to get the property.
cmProperty::ScopeType scope;
@@ -57,11 +97,11 @@ bool cmGetPropertyCommand::InitialPass(std::vector<std::string> const& args,
} else if (args[1] == "INSTALL") {
scope = cmProperty::INSTALL;
} else {
- std::ostringstream e;
- e << "given invalid scope " << args[1] << ". "
- << "Valid scopes are "
- << "GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, VARIABLE, CACHE, INSTALL.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(
+ "given invalid scope ", args[1],
+ ". "
+ "Valid scopes are "
+ "GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, VARIABLE, CACHE, INSTALL."));
return false;
}
@@ -79,86 +119,90 @@ bool cmGetPropertyCommand::InitialPass(std::vector<std::string> const& args,
doing = DoingProperty;
} else if (args[i] == "BRIEF_DOCS") {
doing = DoingNone;
- this->InfoType = OutBriefDoc;
+ infoType = OutBriefDoc;
} else if (args[i] == "FULL_DOCS") {
doing = DoingNone;
- this->InfoType = OutFullDoc;
+ infoType = OutFullDoc;
} else if (args[i] == "SET") {
doing = DoingNone;
- this->InfoType = OutSet;
+ infoType = OutSet;
} else if (args[i] == "DEFINED") {
doing = DoingNone;
- this->InfoType = OutDefined;
+ infoType = OutDefined;
} else if (doing == DoingName) {
doing = DoingNone;
- this->Name = args[i];
+ name = args[i];
} else if (doing == DoingProperty) {
doing = DoingNone;
- this->PropertyName = args[i];
+ propertyName = args[i];
} else {
- std::ostringstream e;
- e << "given invalid argument \"" << args[i] << "\".";
- this->SetError(e.str());
+ status.SetError(cmStrCat("given invalid argument \"", args[i], "\"."));
return false;
}
}
// Make sure a property name was found.
- if (this->PropertyName.empty()) {
- this->SetError("not given a PROPERTY <name> argument.");
+ if (propertyName.empty()) {
+ status.SetError("not given a PROPERTY <name> argument.");
return false;
}
// Compute requested output.
- if (this->InfoType == OutBriefDoc) {
+ if (infoType == OutBriefDoc) {
// Lookup brief documentation.
std::string output;
if (cmPropertyDefinition const* def =
- this->Makefile->GetState()->GetPropertyDefinition(this->PropertyName,
- scope)) {
+ status.GetMakefile().GetState()->GetPropertyDefinition(propertyName,
+ scope)) {
output = def->GetShortDescription();
} else {
output = "NOTFOUND";
}
- this->Makefile->AddDefinition(this->Variable, output.c_str());
- } else if (this->InfoType == OutFullDoc) {
+ status.GetMakefile().AddDefinition(variable, output);
+ } else if (infoType == OutFullDoc) {
// Lookup full documentation.
std::string output;
if (cmPropertyDefinition const* def =
- this->Makefile->GetState()->GetPropertyDefinition(this->PropertyName,
- scope)) {
+ status.GetMakefile().GetState()->GetPropertyDefinition(propertyName,
+ scope)) {
output = def->GetFullDescription();
} else {
output = "NOTFOUND";
}
- this->Makefile->AddDefinition(this->Variable, output.c_str());
- } else if (this->InfoType == OutDefined) {
+ status.GetMakefile().AddDefinition(variable, output);
+ } else if (infoType == OutDefined) {
// Lookup if the property is defined
- if (this->Makefile->GetState()->GetPropertyDefinition(this->PropertyName,
- scope)) {
- this->Makefile->AddDefinition(this->Variable, "1");
+ if (status.GetMakefile().GetState()->GetPropertyDefinition(propertyName,
+ scope)) {
+ status.GetMakefile().AddDefinition(variable, "1");
} else {
- this->Makefile->AddDefinition(this->Variable, "0");
+ status.GetMakefile().AddDefinition(variable, "0");
}
} else {
// Dispatch property getting.
switch (scope) {
case cmProperty::GLOBAL:
- return this->HandleGlobalMode();
+ return HandleGlobalMode(status, name, infoType, variable,
+ propertyName);
case cmProperty::DIRECTORY:
- return this->HandleDirectoryMode();
+ return HandleDirectoryMode(status, name, infoType, variable,
+ propertyName);
case cmProperty::TARGET:
- return this->HandleTargetMode();
+ return HandleTargetMode(status, name, infoType, variable,
+ propertyName);
case cmProperty::SOURCE_FILE:
- return this->HandleSourceMode();
+ return HandleSourceMode(status, name, infoType, variable,
+ propertyName);
case cmProperty::TEST:
- return this->HandleTestMode();
+ return HandleTestMode(status, name, infoType, variable, propertyName);
case cmProperty::VARIABLE:
- return this->HandleVariableMode();
+ return HandleVariableMode(status, name, infoType, variable,
+ propertyName);
case cmProperty::CACHE:
- return this->HandleCacheMode();
+ return HandleCacheMode(status, name, infoType, variable, propertyName);
case cmProperty::INSTALL:
- return this->HandleInstallMode();
+ return HandleInstallMode(status, name, infoType, variable,
+ propertyName);
case cmProperty::CACHED_VARIABLE:
break; // should never happen
@@ -168,58 +212,64 @@ bool cmGetPropertyCommand::InitialPass(std::vector<std::string> const& args,
return true;
}
-bool cmGetPropertyCommand::StoreResult(const char* value)
+namespace {
+
+bool StoreResult(OutType infoType, cmMakefile& makefile,
+ const std::string& variable, const char* value)
{
- if (this->InfoType == OutSet) {
- this->Makefile->AddDefinition(this->Variable, value ? "1" : "0");
- } else // if(this->InfoType == OutValue)
+ if (infoType == OutSet) {
+ makefile.AddDefinition(variable, value ? "1" : "0");
+ } else // if(infoType == OutValue)
{
if (value) {
- this->Makefile->AddDefinition(this->Variable, value);
+ makefile.AddDefinition(variable, value);
} else {
- this->Makefile->RemoveDefinition(this->Variable);
+ makefile.RemoveDefinition(variable);
}
}
return true;
}
-bool cmGetPropertyCommand::HandleGlobalMode()
+bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name,
+ OutType infoType, const std::string& variable,
+ const std::string& propertyName)
{
- if (!this->Name.empty()) {
- this->SetError("given name for GLOBAL scope.");
+ if (!name.empty()) {
+ status.SetError("given name for GLOBAL scope.");
return false;
}
// Get the property.
- cmake* cm = this->Makefile->GetCMakeInstance();
- return this->StoreResult(
- cm->GetState()->GetGlobalProperty(this->PropertyName));
+ cmake* cm = status.GetMakefile().GetCMakeInstance();
+ return StoreResult(infoType, status.GetMakefile(), variable,
+ cm->GetState()->GetGlobalProperty(propertyName));
}
-bool cmGetPropertyCommand::HandleDirectoryMode()
+bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name,
+ OutType infoType, const std::string& variable,
+ const std::string& propertyName)
{
// Default to the current directory.
- cmMakefile* mf = this->Makefile;
+ cmMakefile* mf = &status.GetMakefile();
// Lookup the directory if given.
- if (!this->Name.empty()) {
+ if (!name.empty()) {
// Construct the directory name. Interpret relative paths with
// respect to the current directory.
- std::string dir = this->Name;
- if (!cmSystemTools::FileIsFullPath(dir.c_str())) {
- dir = this->Makefile->GetCurrentSourceDirectory();
- dir += "/";
- dir += this->Name;
+ std::string dir = name;
+ if (!cmSystemTools::FileIsFullPath(dir)) {
+ dir =
+ cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', name);
}
// The local generators are associated with collapsed paths.
dir = cmSystemTools::CollapseFullPath(dir);
// Lookup the generator.
- mf = this->Makefile->GetGlobalGenerator()->FindMakefile(dir);
+ mf = status.GetMakefile().GetGlobalGenerator()->FindMakefile(dir);
if (!mf) {
// Could not find the directory.
- this->SetError(
+ status.SetError(
"DIRECTORY scope provided but requested directory was not found. "
"This could be because the directory argument was invalid or, "
"it is valid but has not been processed yet.");
@@ -227,14 +277,15 @@ bool cmGetPropertyCommand::HandleDirectoryMode()
}
}
- if (this->PropertyName == "DEFINITIONS") {
+ if (propertyName == "DEFINITIONS") {
switch (mf->GetPolicyStatus(cmPolicies::CMP0059)) {
case cmPolicies::WARN:
- mf->IssueMessage(cmake::AUTHOR_WARNING,
+ mf->IssueMessage(MessageType::AUTHOR_WARNING,
cmPolicies::GetPolicyWarning(cmPolicies::CMP0059));
CM_FALLTHROUGH;
case cmPolicies::OLD:
- return this->StoreResult(mf->GetDefineFlagsCMP0059());
+ return StoreResult(infoType, status.GetMakefile(), variable,
+ mf->GetDefineFlagsCMP0059());
case cmPolicies::NEW:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::REQUIRED_IF_USED:
@@ -243,124 +294,136 @@ bool cmGetPropertyCommand::HandleDirectoryMode()
}
// Get the property.
- return this->StoreResult(mf->GetProperty(this->PropertyName));
+ return StoreResult(infoType, status.GetMakefile(), variable,
+ mf->GetProperty(propertyName));
}
-bool cmGetPropertyCommand::HandleTargetMode()
+bool HandleTargetMode(cmExecutionStatus& status, const std::string& name,
+ OutType infoType, const std::string& variable,
+ const std::string& propertyName)
{
- if (this->Name.empty()) {
- this->SetError("not given name for TARGET scope.");
+ if (name.empty()) {
+ status.SetError("not given name for TARGET scope.");
return false;
}
- if (cmTarget* target = this->Makefile->FindTargetToUse(this->Name)) {
- if (this->PropertyName == "ALIASED_TARGET") {
- if (this->Makefile->IsAlias(this->Name)) {
- return this->StoreResult(target->GetName().c_str());
+ if (cmTarget* target = status.GetMakefile().FindTargetToUse(name)) {
+ if (propertyName == "ALIASED_TARGET") {
+ if (status.GetMakefile().IsAlias(name)) {
+ return StoreResult(infoType, status.GetMakefile(), variable,
+ target->GetName().c_str());
}
- return this->StoreResult(CM_NULLPTR);
+ return StoreResult(infoType, status.GetMakefile(), variable, nullptr);
}
- const char* prop_cstr = CM_NULLPTR;
- cmListFileBacktrace bt = this->Makefile->GetBacktrace();
- cmMessenger* messenger = this->Makefile->GetMessenger();
+ const char* prop_cstr = nullptr;
+ cmListFileBacktrace bt = status.GetMakefile().GetBacktrace();
+ cmMessenger* messenger = status.GetMakefile().GetMessenger();
if (cmTargetPropertyComputer::PassesWhitelist(
- target->GetType(), this->PropertyName, messenger, bt)) {
- prop_cstr =
- target->GetComputedProperty(this->PropertyName, messenger, bt);
+ target->GetType(), propertyName, messenger, bt)) {
+ prop_cstr = target->GetComputedProperty(propertyName, messenger, bt);
if (!prop_cstr) {
- prop_cstr = target->GetProperty(this->PropertyName);
+ prop_cstr = target->GetProperty(propertyName);
}
}
- return this->StoreResult(prop_cstr);
+ return StoreResult(infoType, status.GetMakefile(), variable, prop_cstr);
}
- std::ostringstream e;
- e << "could not find TARGET " << this->Name
- << ". Perhaps it has not yet been created.";
- this->SetError(e.str());
+ status.SetError(cmStrCat("could not find TARGET ", name,
+ ". Perhaps it has not yet been created."));
return false;
}
-bool cmGetPropertyCommand::HandleSourceMode()
+bool HandleSourceMode(cmExecutionStatus& status, const std::string& name,
+ OutType infoType, const std::string& variable,
+ const std::string& propertyName)
{
- if (this->Name.empty()) {
- this->SetError("not given name for SOURCE scope.");
+ if (name.empty()) {
+ status.SetError("not given name for SOURCE scope.");
return false;
}
// Get the source file.
- if (cmSourceFile* sf = this->Makefile->GetOrCreateSource(this->Name)) {
- return this->StoreResult(sf->GetPropertyForUser(this->PropertyName));
+ if (cmSourceFile* sf = status.GetMakefile().GetOrCreateSource(name)) {
+ return StoreResult(infoType, status.GetMakefile(), variable,
+ sf->GetPropertyForUser(propertyName));
}
- std::ostringstream e;
- e << "given SOURCE name that could not be found or created: " << this->Name;
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("given SOURCE name that could not be found or created: ", name));
return false;
}
-bool cmGetPropertyCommand::HandleTestMode()
+bool HandleTestMode(cmExecutionStatus& status, const std::string& name,
+ OutType infoType, const std::string& variable,
+ const std::string& propertyName)
{
- if (this->Name.empty()) {
- this->SetError("not given name for TEST scope.");
+ if (name.empty()) {
+ status.SetError("not given name for TEST scope.");
return false;
}
// Loop over all tests looking for matching names.
- if (cmTest* test = this->Makefile->GetTest(this->Name)) {
- return this->StoreResult(test->GetProperty(this->PropertyName));
+ if (cmTest* test = status.GetMakefile().GetTest(name)) {
+ return StoreResult(infoType, status.GetMakefile(), variable,
+ test->GetProperty(propertyName));
}
// If not found it is an error.
- std::ostringstream e;
- e << "given TEST name that does not exist: " << this->Name;
- this->SetError(e.str());
+ status.SetError(cmStrCat("given TEST name that does not exist: ", name));
return false;
}
-bool cmGetPropertyCommand::HandleVariableMode()
+bool HandleVariableMode(cmExecutionStatus& status, const std::string& name,
+ OutType infoType, const std::string& variable,
+ const std::string& propertyName)
{
- if (!this->Name.empty()) {
- this->SetError("given name for VARIABLE scope.");
+ if (!name.empty()) {
+ status.SetError("given name for VARIABLE scope.");
return false;
}
- return this->StoreResult(this->Makefile->GetDefinition(this->PropertyName));
+ return StoreResult(infoType, status.GetMakefile(), variable,
+ status.GetMakefile().GetDefinition(propertyName));
}
-bool cmGetPropertyCommand::HandleCacheMode()
+bool HandleCacheMode(cmExecutionStatus& status, const std::string& name,
+ OutType infoType, const std::string& variable,
+ const std::string& propertyName)
{
- if (this->Name.empty()) {
- this->SetError("not given name for CACHE scope.");
+ if (name.empty()) {
+ status.SetError("not given name for CACHE scope.");
return false;
}
- const char* value = CM_NULLPTR;
- if (this->Makefile->GetState()->GetCacheEntryValue(this->Name)) {
- value = this->Makefile->GetState()->GetCacheEntryProperty(
- this->Name, this->PropertyName);
+ const char* value = nullptr;
+ if (status.GetMakefile().GetState()->GetCacheEntryValue(name)) {
+ value = status.GetMakefile().GetState()->GetCacheEntryProperty(
+ name, propertyName);
}
- this->StoreResult(value);
+ StoreResult(infoType, status.GetMakefile(), variable, value);
return true;
}
-bool cmGetPropertyCommand::HandleInstallMode()
+bool HandleInstallMode(cmExecutionStatus& status, const std::string& name,
+ OutType infoType, const std::string& variable,
+ const std::string& propertyName)
{
- if (this->Name.empty()) {
- this->SetError("not given name for INSTALL scope.");
+ if (name.empty()) {
+ status.SetError("not given name for INSTALL scope.");
return false;
}
// Get the installed file.
- cmake* cm = this->Makefile->GetCMakeInstance();
+ cmake* cm = status.GetMakefile().GetCMakeInstance();
if (cmInstalledFile* file =
- cm->GetOrCreateInstalledFile(this->Makefile, this->Name)) {
+ cm->GetOrCreateInstalledFile(&status.GetMakefile(), name)) {
std::string value;
- bool isSet = file->GetProperty(this->PropertyName, value);
+ bool isSet = file->GetProperty(propertyName, value);
- return this->StoreResult(isSet ? value.c_str() : CM_NULLPTR);
+ return StoreResult(infoType, status.GetMakefile(), variable,
+ isSet ? value.c_str() : nullptr);
}
- std::ostringstream e;
- e << "given INSTALL name that could not be found or created: " << this->Name;
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("given INSTALL name that could not be found or created: ", name));
return false;
}
+}
diff --git a/Source/cmGetPropertyCommand.h b/Source/cmGetPropertyCommand.h
index 649780168..cc600f4ee 100644
--- a/Source/cmGetPropertyCommand.h
+++ b/Source/cmGetPropertyCommand.h
@@ -3,55 +3,14 @@
#ifndef cmGetPropertyCommand_h
#define cmGetPropertyCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmGetPropertyCommand : public cmCommand
-{
-public:
- cmGetPropertyCommand();
-
- cmCommand* Clone() CM_OVERRIDE { return new cmGetPropertyCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the input file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- enum OutType
- {
- OutValue,
- OutDefined,
- OutBriefDoc,
- OutFullDoc,
- OutSet
- };
- std::string Variable;
- std::string Name;
- std::string PropertyName;
- OutType InfoType;
-
- // Implementation of result storage.
- bool StoreResult(const char* value);
-
- // Implementation of each property type.
- bool HandleGlobalMode();
- bool HandleDirectoryMode();
- bool HandleTargetMode();
- bool HandleSourceMode();
- bool HandleTestMode();
- bool HandleVariableMode();
- bool HandleCacheMode();
- bool HandleInstallMode();
-};
+bool cmGetPropertyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmGetSourceFilePropertyCommand.cxx b/Source/cmGetSourceFilePropertyCommand.cxx
index 1a5f08ef8..eefdc6ccb 100644
--- a/Source/cmGetSourceFilePropertyCommand.cxx
+++ b/Source/cmGetSourceFilePropertyCommand.cxx
@@ -2,42 +2,37 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGetSourceFilePropertyCommand.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
-class cmExecutionStatus;
-
-// cmSetSourceFilePropertyCommand
-bool cmGetSourceFilePropertyCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmGetSourceFilePropertyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() != 3) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
std::string const& var = args[0];
std::string const& file = args[1];
- cmSourceFile* sf = this->Makefile->GetSource(file);
+ cmMakefile& mf = status.GetMakefile();
+ cmSourceFile* sf = mf.GetSource(file);
// for the location we must create a source file first
if (!sf && args[2] == "LOCATION") {
- sf = this->Makefile->CreateSource(file);
+ sf = mf.CreateSource(file);
}
if (sf) {
- if (args[2] == "LANGUAGE") {
- this->Makefile->AddDefinition(var, sf->GetLanguage().c_str());
- return true;
- }
- const char* prop = CM_NULLPTR;
+ const char* prop = nullptr;
if (!args[2].empty()) {
prop = sf->GetPropertyForUser(args[2]);
}
if (prop) {
- this->Makefile->AddDefinition(var, prop);
+ mf.AddDefinition(var, prop);
return true;
}
}
- this->Makefile->AddDefinition(var, "NOTFOUND");
+ mf.AddDefinition(var, "NOTFOUND");
return true;
}
diff --git a/Source/cmGetSourceFilePropertyCommand.h b/Source/cmGetSourceFilePropertyCommand.h
index e96bb29ed..f0c319b0a 100644
--- a/Source/cmGetSourceFilePropertyCommand.h
+++ b/Source/cmGetSourceFilePropertyCommand.h
@@ -3,26 +3,14 @@
#ifndef cmGetSourceFilePropertyCommand_h
#define cmGetSourceFilePropertyCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmGetSourceFilePropertyCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE { return new cmGetSourceFilePropertyCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the input file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmGetSourceFilePropertyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx
index 0910a5324..7f5df9cfb 100644
--- a/Source/cmGetTargetPropertyCommand.cxx
+++ b/Source/cmGetTargetPropertyCommand.cxx
@@ -4,39 +4,39 @@
#include <sstream>
+#include "cmExecutionStatus.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmTarget.h"
#include "cmTargetPropertyComputer.h"
-#include "cmake.h"
-class cmExecutionStatus;
class cmMessenger;
-// cmSetTargetPropertyCommand
-bool cmGetTargetPropertyCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmGetTargetPropertyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() != 3) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
std::string const& var = args[0];
std::string const& targetName = args[1];
std::string prop;
bool prop_exists = false;
+ cmMakefile& mf = status.GetMakefile();
- if (cmTarget* tgt = this->Makefile->FindTargetToUse(targetName)) {
+ if (cmTarget* tgt = mf.FindTargetToUse(targetName)) {
if (args[2] == "ALIASED_TARGET") {
- if (this->Makefile->IsAlias(targetName)) {
+ if (mf.IsAlias(targetName)) {
prop = tgt->GetName();
prop_exists = true;
}
} else if (!args[2].empty()) {
- const char* prop_cstr = CM_NULLPTR;
- cmListFileBacktrace bt = this->Makefile->GetBacktrace();
- cmMessenger* messenger = this->Makefile->GetMessenger();
+ const char* prop_cstr = nullptr;
+ cmListFileBacktrace bt = mf.GetBacktrace();
+ cmMessenger* messenger = mf.GetMessenger();
if (cmTargetPropertyComputer::PassesWhitelist(tgt->GetType(), args[2],
messenger, bt)) {
prop_cstr = tgt->GetComputedProperty(args[2], messenger, bt);
@@ -52,8 +52,8 @@ bool cmGetTargetPropertyCommand::InitialPass(
} else {
bool issueMessage = false;
std::ostringstream e;
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0045)) {
+ MessageType messageType = MessageType::AUTHOR_WARNING;
+ switch (mf.GetPolicyStatus(cmPolicies::CMP0045)) {
case cmPolicies::WARN:
issueMessage = true;
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0045) << "\n";
@@ -63,21 +63,21 @@ bool cmGetTargetPropertyCommand::InitialPass(
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
issueMessage = true;
- messageType = cmake::FATAL_ERROR;
+ messageType = MessageType::FATAL_ERROR;
}
if (issueMessage) {
e << "get_target_property() called with non-existent target \""
<< targetName << "\".";
- this->Makefile->IssueMessage(messageType, e.str());
- if (messageType == cmake::FATAL_ERROR) {
+ mf.IssueMessage(messageType, e.str());
+ if (messageType == MessageType::FATAL_ERROR) {
return false;
}
}
}
if (prop_exists) {
- this->Makefile->AddDefinition(var, prop.c_str());
+ mf.AddDefinition(var, prop);
return true;
}
- this->Makefile->AddDefinition(var, (var + "-NOTFOUND").c_str());
+ mf.AddDefinition(var, var + "-NOTFOUND");
return true;
}
diff --git a/Source/cmGetTargetPropertyCommand.h b/Source/cmGetTargetPropertyCommand.h
index 5de322563..c13078f8c 100644
--- a/Source/cmGetTargetPropertyCommand.h
+++ b/Source/cmGetTargetPropertyCommand.h
@@ -3,26 +3,14 @@
#ifndef cmGetTargetPropertyCommand_h
#define cmGetTargetPropertyCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmGetTargetPropertyCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE { return new cmGetTargetPropertyCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the input file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmGetTargetPropertyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmGetTestPropertyCommand.cxx b/Source/cmGetTestPropertyCommand.cxx
index 6424515ec..cf8c1d5fa 100644
--- a/Source/cmGetTestPropertyCommand.cxx
+++ b/Source/cmGetTestPropertyCommand.cxx
@@ -2,33 +2,32 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGetTestPropertyCommand.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmTest.h"
-class cmExecutionStatus;
-
-// cmGetTestPropertyCommand
-bool cmGetTestPropertyCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmGetTestPropertyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 3) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
std::string const& testName = args[0];
std::string const& var = args[2];
- cmTest* test = this->Makefile->GetTest(testName);
+ cmMakefile& mf = status.GetMakefile();
+ cmTest* test = mf.GetTest(testName);
if (test) {
- const char* prop = CM_NULLPTR;
+ const char* prop = nullptr;
if (!args[1].empty()) {
prop = test->GetProperty(args[1]);
}
if (prop) {
- this->Makefile->AddDefinition(var, prop);
+ mf.AddDefinition(var, prop);
return true;
}
}
- this->Makefile->AddDefinition(var, "NOTFOUND");
+ mf.AddDefinition(var, "NOTFOUND");
return true;
}
diff --git a/Source/cmGetTestPropertyCommand.h b/Source/cmGetTestPropertyCommand.h
index b17e7a1cc..30beb8f0f 100644
--- a/Source/cmGetTestPropertyCommand.h
+++ b/Source/cmGetTestPropertyCommand.h
@@ -3,26 +3,14 @@
#ifndef cmGetTestPropertyCommand_h
#define cmGetTestPropertyCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmGetTestPropertyCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE { return new cmGetTestPropertyCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the input file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmGetTestPropertyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmGhsMultiGpj.cxx b/Source/cmGhsMultiGpj.cxx
index f58cfc1e5..da27971de 100644
--- a/Source/cmGhsMultiGpj.cxx
+++ b/Source/cmGhsMultiGpj.cxx
@@ -2,33 +2,38 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGhsMultiGpj.h"
-#include "cmGeneratedFileStream.h"
+#include <ostream>
-void GhsMultiGpj::WriteGpjTag(Types const gpjType,
- cmGeneratedFileStream* const filestream)
+static const char* GHS_TAG[] = { "[INTEGRITY Application]",
+ "[Library]",
+ "[Project]",
+ "[Program]",
+ "[Reference]",
+ "[Subproject]",
+ "[Custom Target]" };
+
+const char* GhsMultiGpj::GetGpjTag(Types gpjType)
{
char const* tag;
switch (gpjType) {
case INTERGRITY_APPLICATION:
- tag = "INTEGRITY Application";
- break;
case LIBRARY:
- tag = "Library";
- break;
case PROJECT:
- tag = "Project";
- break;
case PROGRAM:
- tag = "Program";
- break;
case REFERENCE:
- tag = "Reference";
- break;
case SUBPROJECT:
- tag = "Subproject";
+ case CUSTOM_TARGET:
+ tag = GHS_TAG[gpjType];
break;
default:
tag = "";
}
- *filestream << "[" << tag << "]" << std::endl;
+ return tag;
+}
+
+void GhsMultiGpj::WriteGpjTag(Types gpjType, std::ostream& fout)
+{
+ char const* tag;
+ tag = GhsMultiGpj::GetGpjTag(gpjType);
+ fout << tag << std::endl;
}
diff --git a/Source/cmGhsMultiGpj.h b/Source/cmGhsMultiGpj.h
index 7bc7bfc46..fbbef5d8f 100644
--- a/Source/cmGhsMultiGpj.h
+++ b/Source/cmGhsMultiGpj.h
@@ -3,9 +3,9 @@
#ifndef cmGhsMultiGpj_h
#define cmGhsMultiGpj_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-class cmGeneratedFileStream;
+#include <iosfwd>
class GhsMultiGpj
{
@@ -17,11 +17,13 @@ public:
PROJECT,
PROGRAM,
REFERENCE,
- SUBPROJECT
+ SUBPROJECT,
+ CUSTOM_TARGET
};
- static void WriteGpjTag(Types const gpjType,
- cmGeneratedFileStream* filestream);
+ static void WriteGpjTag(Types gpjType, std::ostream& fout);
+
+ static const char* GetGpjTag(Types gpjType);
};
#endif // ! cmGhsMultiGpjType_h
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index 7032cd582..8e4352e29 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -2,184 +2,149 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGhsMultiTargetGenerator.h"
+#include <algorithm>
+#include <memory>
+#include <ostream>
+#include <set>
+#include <utility>
+#include <vector>
+
+#include "cmCustomCommand.h"
+#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGhsMultiGenerator.h"
#include "cmLinkLineComputer.h"
+#include "cmLocalGenerator.h"
#include "cmLocalGhsMultiGenerator.h"
#include "cmMakefile.h"
+#include "cmOutputConverter.h"
#include "cmSourceFile.h"
+#include "cmSourceFileLocation.h"
+#include "cmSourceGroup.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
#include "cmTarget.h"
-#include <assert.h>
-
-std::string const cmGhsMultiTargetGenerator::DDOption("-dynamic");
cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmGeneratorTarget* target)
: GeneratorTarget(target)
, LocalGenerator(
static_cast<cmLocalGhsMultiGenerator*>(target->GetLocalGenerator()))
, Makefile(target->Target->GetMakefile())
- , TargetGroup(DetermineIfTargetGroup(target))
- , DynamicDownload(false)
-{
- this->RelBuildFilePath = this->GetRelBuildFilePath(target);
-
- this->RelOutputFileName = this->RelBuildFilePath + target->GetName() + ".a";
-
- this->RelBuildFileName = this->RelBuildFilePath;
- this->RelBuildFileName += this->GetBuildFileName(target);
-
- std::string absPathToRoot = this->GetAbsPathToRoot(target);
- absPathToRoot = this->AddSlashIfNeededToPath(absPathToRoot);
- this->AbsBuildFilePath = absPathToRoot + this->RelBuildFilePath;
- this->AbsBuildFileName = absPathToRoot + this->RelBuildFileName;
- this->AbsOutputFileName = absPathToRoot + this->RelOutputFileName;
-}
-
-cmGhsMultiTargetGenerator::~cmGhsMultiTargetGenerator()
-{
- cmDeleteAll(this->FolderBuildStreams);
-}
-
-std::string cmGhsMultiTargetGenerator::GetRelBuildFilePath(
- const cmGeneratorTarget* target)
-{
- std::string output = target->GetEffectiveFolderName();
- cmSystemTools::ConvertToUnixSlashes(output);
- if (!output.empty()) {
- output += "/";
+ , Name(target->GetName())
+#ifdef _WIN32
+ , CmdWindowsShell(true)
+#else
+ , CmdWindowsShell(false)
+#endif
+{
+ // Store the configuration name that is being used
+ if (const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) {
+ // Use the build type given by the user.
+ this->ConfigName = config;
+ } else {
+ // No configuration type given.
+ this->ConfigName.clear();
}
- output += target->GetName() + "/";
- return output;
-}
-
-std::string cmGhsMultiTargetGenerator::GetAbsPathToRoot(
- const cmGeneratorTarget* target)
-{
- return target->GetLocalGenerator()->GetBinaryDirectory();
-}
-
-std::string cmGhsMultiTargetGenerator::GetAbsBuildFilePath(
- const cmGeneratorTarget* target)
-{
- std::string output;
- output = cmGhsMultiTargetGenerator::GetAbsPathToRoot(target);
- output = cmGhsMultiTargetGenerator::AddSlashIfNeededToPath(output);
- output += cmGhsMultiTargetGenerator::GetRelBuildFilePath(target);
- return output;
}
-std::string cmGhsMultiTargetGenerator::GetRelBuildFileName(
- const cmGeneratorTarget* target)
-{
- std::string output;
- output = cmGhsMultiTargetGenerator::GetRelBuildFilePath(target);
- output = cmGhsMultiTargetGenerator::AddSlashIfNeededToPath(output);
- output += cmGhsMultiTargetGenerator::GetBuildFileName(target);
- return output;
-}
-
-std::string cmGhsMultiTargetGenerator::GetBuildFileName(
- const cmGeneratorTarget* target)
-{
- std::string output;
- output = target->GetName();
- output += cmGlobalGhsMultiGenerator::FILE_EXTENSION;
- return output;
-}
-
-std::string cmGhsMultiTargetGenerator::AddSlashIfNeededToPath(
- std::string const& input)
-{
- std::string output(input);
- if (!cmHasLiteralSuffix(output, "/")) {
- output += "/";
- }
- return output;
-}
+cmGhsMultiTargetGenerator::~cmGhsMultiTargetGenerator() = default;
void cmGhsMultiTargetGenerator::Generate()
{
- std::vector<cmSourceFile*> objectSources = this->GetSources();
- if (!objectSources.empty() && this->IncludeThisTarget()) {
- if (!cmSystemTools::FileExists(this->AbsBuildFilePath.c_str())) {
- cmSystemTools::MakeDirectory(this->AbsBuildFilePath.c_str());
+ // Determine type of target for this project
+ switch (this->GeneratorTarget->GetType()) {
+ case cmStateEnums::EXECUTABLE: {
+ // Get the name of the executable to generate.
+ this->TargetNameReal =
+ this->GeneratorTarget->GetExecutableNames(this->ConfigName).Real;
+ if (cmGhsMultiTargetGenerator::DetermineIfIntegrityApp()) {
+ this->TagType = GhsMultiGpj::INTERGRITY_APPLICATION;
+ } else {
+ this->TagType = GhsMultiGpj::PROGRAM;
+ }
+ break;
}
- cmGlobalGhsMultiGenerator::Open(std::string(""), this->AbsBuildFileName,
- &this->FolderBuildStreams);
- cmGlobalGhsMultiGenerator::OpenBuildFileStream(
- this->GetFolderBuildStreams());
- std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
- if (0 == config.length()) {
- config = "RELEASE";
+ case cmStateEnums::STATIC_LIBRARY: {
+ this->TargetNameReal =
+ this->GeneratorTarget->GetLibraryNames(this->ConfigName).Real;
+ this->TagType = GhsMultiGpj::LIBRARY;
+ break;
}
- const std::string language(
- this->GeneratorTarget->GetLinkerLanguage(config));
- config = cmSystemTools::UpperCase(config);
- this->DynamicDownload = this->DetermineIfDynamicDownload(config, language);
- if (this->DynamicDownload) {
- *this->GetFolderBuildStreams() << "#component integrity_dynamic_download"
- << std::endl;
+ case cmStateEnums::SHARED_LIBRARY: {
+ std::string msg =
+ cmStrCat("add_library(<name> SHARED ...) not supported: ", this->Name);
+ cmSystemTools::Message(msg);
+ return;
}
- GhsMultiGpj::WriteGpjTag(this->GetGpjTag(), this->GetFolderBuildStreams());
- cmGlobalGhsMultiGenerator::WriteDisclaimer(this->GetFolderBuildStreams());
-
- bool const notKernel = this->IsNotKernel(config, language);
- this->WriteTypeSpecifics(config, notKernel);
- this->SetCompilerFlags(config, language, notKernel);
- this->WriteCompilerFlags(config, language);
- this->WriteCompilerDefinitions(config, language);
- this->WriteIncludes(config, language);
- if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
- this->WriteTargetLinkLibraries(config, language);
+ case cmStateEnums::OBJECT_LIBRARY: {
+ this->TargetNameReal =
+ this->GeneratorTarget->GetLibraryNames(this->ConfigName).Real;
+ this->TagType = GhsMultiGpj::SUBPROJECT;
+ break;
}
- this->WriteCustomCommands();
-
- std::map<const cmSourceFile*, std::string> objectNames =
- cmGhsMultiTargetGenerator::GetObjectNames(
- &objectSources, this->LocalGenerator, this->GeneratorTarget);
-
- this->WriteSources(objectSources, objectNames);
+ case cmStateEnums::MODULE_LIBRARY: {
+ std::string msg =
+ cmStrCat("add_library(<name> MODULE ...) not supported: ", this->Name);
+ cmSystemTools::Message(msg);
+ return;
+ }
+ case cmStateEnums::UTILITY: {
+ this->TargetNameReal = this->GeneratorTarget->GetName();
+ this->TagType = GhsMultiGpj::CUSTOM_TARGET;
+ break;
+ }
+ case cmStateEnums::GLOBAL_TARGET: {
+ this->TargetNameReal = this->GeneratorTarget->GetName();
+ if (this->TargetNameReal ==
+ this->GetGlobalGenerator()->GetInstallTargetName()) {
+ this->TagType = GhsMultiGpj::CUSTOM_TARGET;
+ } else {
+ return;
+ }
+ break;
+ }
+ default:
+ return;
}
-}
-bool cmGhsMultiTargetGenerator::IncludeThisTarget()
-{
- bool output = true;
- char const* excludeFromAll =
- this->GeneratorTarget->GetProperty("EXCLUDE_FROM_ALL");
- if (NULL != excludeFromAll && '1' == excludeFromAll[0] &&
- '\0' == excludeFromAll[1]) {
- output = false;
- }
- return output;
-}
+ // Tell the global generator the name of the project file
+ this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME",
+ this->Name.c_str());
+ this->GeneratorTarget->Target->SetProperty(
+ "GENERATOR_FILE_NAME_EXT", GhsMultiGpj::GetGpjTag(this->TagType));
-std::vector<cmSourceFile*> cmGhsMultiTargetGenerator::GetSources() const
-{
- std::vector<cmSourceFile*> output;
- std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
- this->GeneratorTarget->GetSourceFiles(output, config);
- return output;
+ this->GenerateTarget();
}
-GhsMultiGpj::Types cmGhsMultiTargetGenerator::GetGpjTag() const
+void cmGhsMultiTargetGenerator::GenerateTarget()
{
- return cmGhsMultiTargetGenerator::GetGpjTag(this->GeneratorTarget);
-}
+ // Open the target file in copy-if-different mode.
+ std::string fproj =
+ cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+ this->Name, cmGlobalGhsMultiGenerator::FILE_EXTENSION);
+ cmGeneratedFileStream fout(fproj);
+ fout.SetCopyIfDifferent(true);
-GhsMultiGpj::Types cmGhsMultiTargetGenerator::GetGpjTag(
- const cmGeneratorTarget* target)
-{
- GhsMultiGpj::Types output;
- if (cmGhsMultiTargetGenerator::DetermineIfTargetGroup(target)) {
- output = GhsMultiGpj::INTERGRITY_APPLICATION;
- } else if (target->GetType() == cmStateEnums::STATIC_LIBRARY) {
- output = GhsMultiGpj::LIBRARY;
- } else {
- output = GhsMultiGpj::PROGRAM;
+ this->GetGlobalGenerator()->WriteFileHeader(fout);
+ GhsMultiGpj::WriteGpjTag(this->TagType, fout);
+
+ if (this->TagType != GhsMultiGpj::CUSTOM_TARGET) {
+ const std::string language(
+ this->GeneratorTarget->GetLinkerLanguage(this->ConfigName));
+ this->WriteTargetSpecifics(fout, this->ConfigName);
+ this->SetCompilerFlags(this->ConfigName, language);
+ this->WriteCompilerFlags(fout, this->ConfigName, language);
+ this->WriteCompilerDefinitions(fout, this->ConfigName, language);
+ this->WriteIncludes(fout, this->ConfigName, language);
+ this->WriteTargetLinkLine(fout, this->ConfigName);
+ this->WriteBuildEvents(fout);
}
- return output;
+ this->WriteSources(fout);
+ fout.Close();
}
cmGlobalGhsMultiGenerator* cmGhsMultiTargetGenerator::GetGlobalGenerator()
@@ -189,56 +154,37 @@ cmGlobalGhsMultiGenerator* cmGhsMultiTargetGenerator::GetGlobalGenerator()
this->LocalGenerator->GetGlobalGenerator());
}
-void cmGhsMultiTargetGenerator::WriteTypeSpecifics(const std::string& config,
- bool const notKernel)
+void cmGhsMultiTargetGenerator::WriteTargetSpecifics(std::ostream& fout,
+ const std::string& config)
{
- std::string outputDir(this->GetOutputDirectory(config));
- std::string outputFilename(this->GetOutputFilename(config));
-
- if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
- std::string const static_library_suffix =
- this->Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX");
- *this->GetFolderBuildStreams() << " -o \"" << outputDir
- << outputFilename << static_library_suffix
- << "\"" << std::endl;
- } else if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
- if (notKernel && !this->IsTargetGroup()) {
- *this->GetFolderBuildStreams() << " -relprog" << std::endl;
- }
- if (this->IsTargetGroup()) {
- *this->GetFolderBuildStreams()
- << " -o \"" << outputDir << outputFilename << ".elf\"" << std::endl;
- *this->GetFolderBuildStreams() << " :extraOutputFile=\"" << outputDir
- << outputFilename << ".elf.ael\""
- << std::endl;
- } else {
- std::string const executable_suffix =
- this->Makefile->GetSafeDefinition("CMAKE_EXECUTABLE_SUFFIX");
- *this->GetFolderBuildStreams() << " -o \"" << outputDir
- << outputFilename << executable_suffix
- << "\"" << std::endl;
- }
+ std::string outpath;
+ std::string rootpath = this->LocalGenerator->GetCurrentBinaryDirectory();
+
+ if (this->TagType != GhsMultiGpj::SUBPROJECT) {
+ // set target binary file destination
+ outpath = this->GeneratorTarget->GetDirectory(config);
+ outpath =
+ this->LocalGenerator->MaybeConvertToRelativePath(rootpath, outpath);
+ fout << " :binDirRelative=\"" << outpath << "\"" << std::endl;
+ fout << " -o \"" << this->TargetNameReal << "\"" << std::endl;
}
+
+ // set target object file destination
+ outpath = this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
+ fout << " :outputDirRelative=\"" << outpath << "\"" << std::endl;
}
void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config,
- const std::string& language,
- bool const notKernel)
+ const std::string& language)
{
- std::map<std::string, std::string>::iterator i =
- this->FlagsByLanguage.find(language);
+ auto i = this->FlagsByLanguage.find(language);
if (i == this->FlagsByLanguage.end()) {
std::string flags;
const char* lang = language.c_str();
- if (notKernel) {
- this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
- lang, config);
- } else {
- this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
- lang + std::string("_GHS_KERNEL"),
- config);
- }
+ this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, lang,
+ config);
+
this->LocalGenerator->AddCMP0018Flags(flags, this->GeneratorTarget, lang,
config);
this->LocalGenerator->AddVisibilityPresetFlags(
@@ -262,19 +208,13 @@ void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config,
std::string cmGhsMultiTargetGenerator::GetDefines(const std::string& language,
std::string const& config)
{
- std::map<std::string, std::string>::iterator i =
- this->DefinesByLanguage.find(language);
+ auto i = this->DefinesByLanguage.find(language);
if (i == this->DefinesByLanguage.end()) {
std::set<std::string> defines;
const char* lang = language.c_str();
- // Add the export symbol definition for shared library objects.
- if (const char* exportMacro = this->GeneratorTarget->GetExportMacro()) {
- this->LocalGenerator->AppendDefines(defines, exportMacro);
- }
-
// Add preprocessor definitions for this target and configuration.
- this->LocalGenerator->AddCompileDefinitions(defines, this->GeneratorTarget,
- config, language);
+ this->LocalGenerator->GetTargetDefines(this->GeneratorTarget, config,
+ language, defines);
std::string definesString;
this->LocalGenerator->JoinDefines(defines, definesString, lang);
@@ -286,376 +226,562 @@ std::string cmGhsMultiTargetGenerator::GetDefines(const std::string& language,
return i->second;
}
-void cmGhsMultiTargetGenerator::WriteCompilerFlags(std::string const&,
+void cmGhsMultiTargetGenerator::WriteCompilerFlags(std::ostream& fout,
+ std::string const&,
const std::string& language)
{
- std::map<std::string, std::string>::iterator flagsByLangI =
- this->FlagsByLanguage.find(language);
+ auto flagsByLangI = this->FlagsByLanguage.find(language);
if (flagsByLangI != this->FlagsByLanguage.end()) {
if (!flagsByLangI->second.empty()) {
- *this->GetFolderBuildStreams() << " " << flagsByLangI->second
- << std::endl;
+ std::vector<std::string> ghsCompFlags =
+ cmSystemTools::ParseArguments(flagsByLangI->second);
+ for (auto& f : ghsCompFlags) {
+ fout << " " << f << std::endl;
+ }
}
}
}
void cmGhsMultiTargetGenerator::WriteCompilerDefinitions(
- const std::string& config, const std::string& language)
+ std::ostream& fout, const std::string& config, const std::string& language)
{
std::vector<std::string> compileDefinitions;
this->GeneratorTarget->GetCompileDefinitions(compileDefinitions, config,
language);
- for (std::vector<std::string>::const_iterator cdI =
- compileDefinitions.begin();
- cdI != compileDefinitions.end(); ++cdI) {
- *this->GetFolderBuildStreams() << " -D" << (*cdI) << std::endl;
+ for (std::string const& compileDefinition : compileDefinitions) {
+ fout << " -D" << compileDefinition << std::endl;
}
}
-void cmGhsMultiTargetGenerator::WriteIncludes(const std::string& config,
+void cmGhsMultiTargetGenerator::WriteIncludes(std::ostream& fout,
+ const std::string& config,
const std::string& language)
{
std::vector<std::string> includes;
this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
language, config);
- for (std::vector<std::string>::const_iterator includes_i = includes.begin();
- includes_i != includes.end(); ++includes_i) {
- *this->GetFolderBuildStreams() << " -I\"" << *includes_i << "\""
- << std::endl;
+ for (std::string const& include : includes) {
+ fout << " -I\"" << include << "\"" << std::endl;
}
}
-void cmGhsMultiTargetGenerator::WriteTargetLinkLibraries(
- std::string const& config, std::string const& language)
+void cmGhsMultiTargetGenerator::WriteTargetLinkLine(std::ostream& fout,
+ std::string const& config)
{
- // library directories
- cmTargetDependSet tds =
- this->GetGlobalGenerator()->GetTargetDirectDepends(this->GeneratorTarget);
- for (cmTargetDependSet::iterator tdsI = tds.begin(); tdsI != tds.end();
- ++tdsI) {
- const cmGeneratorTarget* tg = *tdsI;
- *this->GetFolderBuildStreams() << " -L\"" << GetAbsBuildFilePath(tg)
- << "\"" << std::endl;
- }
- // library targets
- cmTarget::LinkLibraryVectorType llv =
- this->GeneratorTarget->Target->GetOriginalLinkLibraries();
- for (cmTarget::LinkLibraryVectorType::const_iterator llvI = llv.begin();
- llvI != llv.end(); ++llvI) {
- std::string libName = llvI->first;
- // if it is a user defined target get the full path to the lib
- cmTarget* tg(GetGlobalGenerator()->FindTarget(libName));
- if (NULL != tg) {
- libName = tg->GetName() + ".a";
- }
- *this->GetFolderBuildStreams() << " -l\"" << libName << "\""
- << std::endl;
+ if (this->TagType == GhsMultiGpj::INTERGRITY_APPLICATION) {
+ return;
}
- if (!this->TargetGroup) {
- std::string linkLibraries;
- std::string flags;
- std::string linkFlags;
- std::string frameworkPath;
- std::string linkPath;
- std::string createRule =
- this->GeneratorTarget->GetCreateRuleVariable(language, config);
- bool useWatcomQuote =
- this->Makefile->IsOn(createRule + "_USE_WATCOM_QUOTE");
- CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
- this->GetGlobalGenerator()->CreateLinkLineComputer(
- this->LocalGenerator,
- this->LocalGenerator->GetStateSnapshot().GetDirectory()));
- linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
-
- this->LocalGenerator->GetTargetFlags(
- linkLineComputer.get(), config, linkLibraries, flags, linkFlags,
- frameworkPath, linkPath, this->GeneratorTarget);
- linkFlags = cmSystemTools::TrimWhitespace(linkFlags);
-
- if (!linkPath.empty()) {
- linkPath = " " + linkPath.substr(0U, linkPath.size() - 1U);
- *this->GetFolderBuildStreams() << linkPath;
- }
+ std::string linkLibraries;
+ std::string flags;
+ std::string linkFlags;
+ std::string frameworkPath;
+ std::string linkPath;
+
+ std::unique_ptr<cmLinkLineComputer> linkLineComputer(
+ this->GetGlobalGenerator()->CreateLinkLineComputer(
+ this->LocalGenerator,
+ this->LocalGenerator->GetStateSnapshot().GetDirectory()));
+
+ this->LocalGenerator->GetTargetFlags(
+ linkLineComputer.get(), config, linkLibraries, flags, linkFlags,
+ frameworkPath, linkPath, this->GeneratorTarget);
+
+ // write out link options
+ std::vector<std::string> lopts = cmSystemTools::ParseArguments(linkFlags);
+ for (auto& l : lopts) {
+ fout << " " << l << std::endl;
+ }
- if (!linkFlags.empty()) {
- *this->GetFolderBuildStreams() << " " << linkFlags << std::endl;
- }
+ // write out link search paths
+ // must be quoted for paths that contain spaces
+ std::vector<std::string> lpath = cmSystemTools::ParseArguments(linkPath);
+ for (auto& l : lpath) {
+ fout << " -L\"" << l << "\"" << std::endl;
}
-}
-void cmGhsMultiTargetGenerator::WriteCustomCommands()
-{
- WriteCustomCommandsHelper(this->GeneratorTarget->GetPreBuildCommands(),
- cmTarget::PRE_BUILD);
- WriteCustomCommandsHelper(this->GeneratorTarget->GetPostBuildCommands(),
- cmTarget::POST_BUILD);
-}
+ // write out link libs
+ // must be quoted for filepaths that contains spaces
+ std::string cbd = this->LocalGenerator->GetCurrentBinaryDirectory();
-void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper(
- std::vector<cmCustomCommand> const& commandsSet,
- cmTarget::CustomCommandType const commandType)
-{
- for (std::vector<cmCustomCommand>::const_iterator commandsSetI =
- commandsSet.begin();
- commandsSetI != commandsSet.end(); ++commandsSetI) {
- cmCustomCommandLines const& commands = commandsSetI->GetCommandLines();
- for (cmCustomCommandLines::const_iterator commandI = commands.begin();
- commandI != commands.end(); ++commandI) {
- switch (commandType) {
- case cmTarget::PRE_BUILD:
- *this->GetFolderBuildStreams() << " :preexecShellSafe=";
- break;
- case cmTarget::POST_BUILD:
- *this->GetFolderBuildStreams() << " :postexecShellSafe=";
- break;
- default:
- assert("Only pre and post are supported");
- }
- cmCustomCommandLine const& command = *commandI;
- for (cmCustomCommandLine::const_iterator commandLineI = command.begin();
- commandLineI != command.end(); ++commandLineI) {
- std::string subCommandE =
- this->LocalGenerator->EscapeForShell(*commandLineI, true);
- if (!command.empty()) {
- *this->GetFolderBuildStreams()
- << (command.begin() == commandLineI ? "'" : " ");
- // Need to double escape backslashes
- cmSystemTools::ReplaceString(subCommandE, "\\", "\\\\");
- }
- *this->GetFolderBuildStreams() << subCommandE;
- }
- if (!command.empty()) {
- *this->GetFolderBuildStreams() << "'" << std::endl;
- }
+ std::vector<std::string> llibs =
+ cmSystemTools::ParseArguments(linkLibraries);
+ for (auto& l : llibs) {
+ if (l.compare(0, 2, "-l") == 0) {
+ fout << " \"" << l << "\"" << std::endl;
+ } else {
+ std::string rl = cmSystemTools::CollapseFullPath(l, cbd);
+ fout << " -l\"" << rl << "\"" << std::endl;
}
}
}
-std::map<const cmSourceFile*, std::string>
-cmGhsMultiTargetGenerator::GetObjectNames(
- std::vector<cmSourceFile*>* const objectSources,
- cmLocalGhsMultiGenerator* const localGhsMultiGenerator,
- cmGeneratorTarget* const generatorTarget)
+void cmGhsMultiTargetGenerator::WriteBuildEvents(std::ostream& fout)
{
- std::map<std::string, std::vector<cmSourceFile*> > filenameToSource;
- std::map<cmSourceFile*, std::string> sourceToFilename;
- for (std::vector<cmSourceFile*>::const_iterator sf = objectSources->begin();
- sf != objectSources->end(); ++sf) {
- const std::string filename =
- cmSystemTools::GetFilenameName((*sf)->GetFullPath());
- const std::string lower_filename = cmSystemTools::LowerCase(filename);
- filenameToSource[lower_filename].push_back(*sf);
- sourceToFilename[*sf] = lower_filename;
- }
-
- std::vector<cmSourceFile*> duplicateSources;
- for (std::map<std::string, std::vector<cmSourceFile*> >::const_iterator
- msvSourceI = filenameToSource.begin();
- msvSourceI != filenameToSource.end(); ++msvSourceI) {
- if (msvSourceI->second.size() > 1) {
- duplicateSources.insert(duplicateSources.end(),
- msvSourceI->second.begin(),
- msvSourceI->second.end());
- }
- }
-
- std::map<const cmSourceFile*, std::string> objectNamesCorrected;
+ this->WriteBuildEventsHelper(
+ fout, this->GeneratorTarget->GetPreBuildCommands(),
+ std::string("prebuild"), std::string("preexecShell"));
- for (std::vector<cmSourceFile*>::const_iterator sf =
- duplicateSources.begin();
- sf != duplicateSources.end(); ++sf) {
- std::string const longestObjectDirectory(
- cmGhsMultiTargetGenerator::ComputeLongestObjectDirectory(
- localGhsMultiGenerator, generatorTarget, *sf));
- std::string objFilenameName =
- localGhsMultiGenerator->GetObjectFileNameWithoutTarget(
- **sf, longestObjectDirectory);
- cmsys::SystemTools::ReplaceString(objFilenameName, "/", "_");
- objectNamesCorrected[*sf] = objFilenameName;
+ if (this->TagType != GhsMultiGpj::CUSTOM_TARGET) {
+ this->WriteBuildEventsHelper(
+ fout, this->GeneratorTarget->GetPreLinkCommands(),
+ std::string("prelink"), std::string("preexecShell"));
}
- return objectNamesCorrected;
+ this->WriteBuildEventsHelper(
+ fout, this->GeneratorTarget->GetPostBuildCommands(),
+ std::string("postbuild"), std::string("postexecShell"));
+}
+
+void cmGhsMultiTargetGenerator::WriteBuildEventsHelper(
+ std::ostream& fout, const std::vector<cmCustomCommand>& ccv,
+ std::string const& name, std::string const& cmd)
+{
+ int cmdcount = 0;
+
+ for (cmCustomCommand const& cc : ccv) {
+ cmCustomCommandGenerator ccg(cc, this->ConfigName, this->LocalGenerator);
+ // Open the filestream for this custom command
+ std::string fname =
+ cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget),
+ '/', this->Name, '_', name, cmdcount++,
+ this->CmdWindowsShell ? ".bat" : ".sh");
+ cmGeneratedFileStream f(fname);
+ f.SetCopyIfDifferent(true);
+ this->WriteCustomCommandsHelper(f, ccg);
+ f.Close();
+ if (this->TagType != GhsMultiGpj::CUSTOM_TARGET) {
+ fout << " :" << cmd << "=\"" << fname << "\"" << std::endl;
+ } else {
+ fout << fname << std::endl;
+ fout << " :outputName=\"" << fname << ".rule\"" << std::endl;
+ }
+ for (auto& byp : ccg.GetByproducts()) {
+ fout << " :extraOutputFile=\"" << byp << "\"" << std::endl;
+ }
+ }
}
-void cmGhsMultiTargetGenerator::WriteSources(
- std::vector<cmSourceFile*> const& objectSources,
- std::map<const cmSourceFile*, std::string> const& objectNames)
+void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper(
+ std::ostream& fout, cmCustomCommandGenerator const& ccg)
{
- 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();
- cmSourceGroup* sourceGroup =
- this->Makefile->FindSourceGroup(sourceFullPath, sourceGroups);
- std::string sgPath(sourceGroup->GetFullName());
- cmSystemTools::ConvertToUnixSlashes(sgPath);
- cmGlobalGhsMultiGenerator::AddFilesUpToPath(
- this->GetFolderBuildStreams(), &this->FolderBuildStreams,
- this->LocalGenerator->GetBinaryDirectory(), sgPath,
- GhsMultiGpj::SUBPROJECT, this->RelBuildFilePath);
-
- std::string fullSourcePath((*si)->GetFullPath());
- if ((*si)->GetExtension() == "int" || (*si)->GetExtension() == "bsp") {
- *this->FolderBuildStreams[sgPath] << fullSourcePath << std::endl;
- } else {
- // WORKAROUND: GHS MULTI needs the path to use backslashes without quotes
- // to open files in search as of version 6.1.6
- cmsys::SystemTools::ReplaceString(fullSourcePath, "/", "\\");
- *this->FolderBuildStreams[sgPath] << fullSourcePath << std::endl;
- }
+ std::vector<std::string> cmdLines;
- if ("ld" != (*si)->GetExtension() && "int" != (*si)->GetExtension() &&
- "bsp" != (*si)->GetExtension()) {
- this->WriteObjectLangOverride(this->FolderBuildStreams[sgPath], (*si));
- if (objectNames.end() != objectNames.find(*si)) {
- *this->FolderBuildStreams[sgPath]
- << " -o \"" << objectNames.find(*si)->second << "\"" << std::endl;
+ // if the command specified a working directory use it.
+ std::string dir = this->LocalGenerator->GetCurrentBinaryDirectory();
+ std::string currentBinDir = dir;
+ std::string workingDir = ccg.GetWorkingDirectory();
+ if (!workingDir.empty()) {
+ dir = workingDir;
+ }
+
+ // Line to check for error between commands.
+#ifdef _WIN32
+ std::string check_error = "if %errorlevel% neq 0 exit /b %errorlevel%";
+#else
+ std::string check_error = "if [[ $? -ne 0 ]]; then exit 1; fi";
+#endif
+
+#ifdef _WIN32
+ cmdLines.push_back("@echo off");
+#endif
+ // Echo the custom command's comment text.
+ const char* comment = ccg.GetComment();
+ if (comment && *comment) {
+ std::string echocmd = cmStrCat("echo ", comment);
+ cmdLines.push_back(std::move(echocmd));
+ }
+
+ // Switch to working directory
+ std::string cdCmd;
+#ifdef _WIN32
+ std::string cdStr = "cd /D ";
+#else
+ std::string cdStr = "cd ";
+#endif
+ cdCmd = cdStr +
+ this->LocalGenerator->ConvertToOutputFormat(dir, cmOutputConverter::SHELL);
+ cmdLines.push_back(std::move(cdCmd));
+
+ for (unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c) {
+ // Build the command line in a single string.
+ std::string cmd = ccg.GetCommand(c);
+ if (!cmd.empty()) {
+ // Use "call " before any invocations of .bat or .cmd files
+ // invoked as custom commands in the WindowsShell.
+ //
+ bool useCall = false;
+
+ if (this->CmdWindowsShell) {
+ std::string suffix;
+ if (cmd.size() > 4) {
+ suffix = cmSystemTools::LowerCase(cmd.substr(cmd.size() - 4));
+ if (suffix == ".bat" || suffix == ".cmd") {
+ useCall = true;
+ }
+ }
}
- this->WriteObjectDir(this->FolderBuildStreams[sgPath],
- this->AbsBuildFilePath + sgPath);
+ cmSystemTools::ReplaceString(cmd, "/./", "/");
+ // Convert the command to a relative path only if the current
+ // working directory will be the start-output directory.
+ bool had_slash = cmd.find('/') != std::string::npos;
+ if (workingDir.empty()) {
+ cmd =
+ this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, cmd);
+ }
+ bool has_slash = cmd.find('/') != std::string::npos;
+ if (had_slash && !has_slash) {
+ // This command was specified as a path to a file in the
+ // current directory. Add a leading "./" so it can run
+ // without the current directory being in the search path.
+ cmd = cmStrCat("./", cmd);
+ }
+ cmd = this->LocalGenerator->ConvertToOutputFormat(
+ cmd, cmOutputConverter::SHELL);
+ if (useCall) {
+ cmd = cmStrCat("call ", cmd);
+ }
+ ccg.AppendArguments(c, cmd);
+ cmdLines.push_back(std::move(cmd));
}
}
+
+ // push back the custom commands
+ for (auto const& c : cmdLines) {
+ fout << c << std::endl;
+ fout << check_error << std::endl;
+ }
}
-void cmGhsMultiTargetGenerator::WriteObjectLangOverride(
- cmGeneratedFileStream* fileStream, cmSourceFile* sourceFile)
+void cmGhsMultiTargetGenerator::WriteSourceProperty(
+ std::ostream& fout, const cmSourceFile* sf, std::string const& propName,
+ std::string const& propFlag)
{
- const char* rawLangProp = sourceFile->GetProperty("LANGUAGE");
- if (NULL != rawLangProp) {
- std::string sourceLangProp(rawLangProp);
- std::string extension(sourceFile->GetExtension());
- if ("CXX" == sourceLangProp && ("c" == extension || "C" == extension)) {
- *fileStream << " -dotciscxx" << std::endl;
+ const char* prop = sf->GetProperty(propName);
+ if (prop) {
+ std::vector<std::string> list = cmExpandedList(prop);
+ for (auto& p : list) {
+ fout << " " << propFlag << p << std::endl;
}
}
}
-void cmGhsMultiTargetGenerator::WriteObjectDir(
- cmGeneratedFileStream* fileStream, std::string const& dir)
+void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
{
- std::string workingDir(dir);
- cmSystemTools::ConvertToUnixSlashes(workingDir);
- if (!workingDir.empty()) {
- workingDir += "/";
+ /* vector of all sources for this target */
+ std::vector<cmSourceFile*> sources;
+ this->GeneratorTarget->GetSourceFiles(sources, this->ConfigName);
+
+ /* vector of all groups defined for this target
+ * -- but the vector is not expanded with sub groups or in any useful order
+ */
+ std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
+
+ /* for each source file assign it to its group */
+ std::map<std::string, std::vector<cmSourceFile*>> groupFiles;
+ std::set<std::string> groupNames;
+ for (auto& sf : sources) {
+ cmSourceGroup* sourceGroup =
+ this->Makefile->FindSourceGroup(sf->ResolveFullPath(), sourceGroups);
+ std::string gn = sourceGroup->GetFullName();
+ groupFiles[gn].push_back(sf);
+ groupNames.insert(std::move(gn));
}
- workingDir += "Objs";
- *fileStream << " -object_dir=\"" << workingDir << "\"" << std::endl;
-}
-std::string cmGhsMultiTargetGenerator::GetOutputDirectory(
- const std::string& config) const
-{
- std::string outputDir(AbsBuildFilePath);
+ /* list of known groups and the order they are displayed in a project file */
+ const std::vector<std::string> standardGroups = {
+ "CMake Rules", "Header Files", "Source Files",
+ "Object Files", "Object Libraries", "Resources"
+ };
+
+ /* list of groups in the order they are displayed in a project file*/
+ std::vector<std::string> groupFilesList(groupFiles.size());
+
+ /* put the groups in the order they should be listed
+ * - standard groups first, and then everything else
+ * in the order used by std::map.
+ */
+ int i = 0;
+ for (const std::string& gn : standardGroups) {
+ auto n = groupNames.find(gn);
+ if (n != groupNames.end()) {
+ groupFilesList[i] = *n;
+ i += 1;
+ groupNames.erase(gn);
+ } else if (this->TagType == GhsMultiGpj::CUSTOM_TARGET &&
+ gn == "CMake Rules") {
+ /* make sure that rules folder always exists in case of custom targets
+ * that have no custom commands except for pre or post build events.
+ */
+ groupFilesList.resize(groupFilesList.size() + 1);
+ groupFilesList[i] = gn;
+ i += 1;
+ }
+ }
- const char* runtimeOutputProp =
- this->GeneratorTarget->GetProperty("RUNTIME_OUTPUT_DIRECTORY");
- if (NULL != runtimeOutputProp) {
- outputDir = runtimeOutputProp;
+ { /* catch-all group - is last item */
+ std::string gn;
+ auto n = groupNames.find(gn);
+ if (n != groupNames.end()) {
+ groupFilesList.back() = *n;
+ groupNames.erase(gn);
+ }
}
- std::string configCapped(cmSystemTools::UpperCase(config));
- const char* runtimeOutputSProp = this->GeneratorTarget->GetProperty(
- "RUNTIME_OUTPUT_DIRECTORY_" + configCapped);
- if (NULL != runtimeOutputSProp) {
- outputDir = runtimeOutputSProp;
+ for (auto& n : groupNames) {
+ groupFilesList[i] = n;
+ i += 1;
}
- cmSystemTools::ConvertToUnixSlashes(outputDir);
- if (!outputDir.empty()) {
- outputDir += "/";
+ /* sort the files within each group */
+ for (auto& n : groupFilesList) {
+ std::sort(groupFiles[n].begin(), groupFiles[n].end(),
+ [](cmSourceFile* l, cmSourceFile* r) {
+ return l->ResolveFullPath() < r->ResolveFullPath();
+ });
}
- return outputDir;
-}
+ /* list of open project files */
+ std::vector<cmGeneratedFileStream*> gfiles;
+
+ /* write files into the proper project file
+ * -- groups go into main project file
+ * unless NO_SOURCE_GROUP_FILE property or variable is set.
+ */
+ for (auto& sg : groupFilesList) {
+ std::ostream* fout;
+ bool useProjectFile =
+ cmIsOn(this->GeneratorTarget->GetProperty("GHS_NO_SOURCE_GROUP_FILE")) ||
+ cmIsOn(this->Makefile->GetDefinition("CMAKE_GHS_NO_SOURCE_GROUP_FILE"));
+ if (useProjectFile || sg.empty()) {
+ fout = &fout_proj;
+ } else {
+ // Open the filestream in copy-if-different mode.
+ std::string gname = sg;
+ cmsys::SystemTools::ReplaceString(gname, "\\", "_");
+ std::string lpath = cmStrCat(
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), '/',
+ gname, cmGlobalGhsMultiGenerator::FILE_EXTENSION);
+ std::string fpath = cmStrCat(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), '/', lpath);
+ cmGeneratedFileStream* f = new cmGeneratedFileStream(fpath);
+ f->SetCopyIfDifferent(true);
+ gfiles.push_back(f);
+ fout = f;
+ this->GetGlobalGenerator()->WriteFileHeader(*f);
+ GhsMultiGpj::WriteGpjTag(GhsMultiGpj::SUBPROJECT, *f);
+ fout_proj << lpath << " ";
+ GhsMultiGpj::WriteGpjTag(GhsMultiGpj::SUBPROJECT, fout_proj);
+ }
-std::string cmGhsMultiTargetGenerator::GetOutputFilename(
- const std::string& config) const
-{
- std::string outputFilename(this->GeneratorTarget->GetName());
+ if (useProjectFile) {
+ if (sg.empty()) {
+ *fout << "{comment} Others" << std::endl;
+ } else {
+ *fout << "{comment} " << sg << std::endl;
+ }
+ } else if (sg.empty()) {
+ *fout << "{comment} Others" << std::endl;
+ }
- const char* outputNameProp =
- this->GeneratorTarget->GetProperty("OUTPUT_NAME");
- if (NULL != outputNameProp) {
- outputFilename = outputNameProp;
- }
+ if (sg != "CMake Rules") {
+ /* output rule for each source file */
+ for (const cmSourceFile* si : groupFiles[sg]) {
+ bool compile = true;
+ // Convert filename to native system
+ // WORKAROUND: GHS MULTI 6.1.4 and 6.1.6 are known to need backslash on
+ // windows when opening some files from the search window.
+ std::string fname(si->GetFullPath());
+ cmSystemTools::ConvertToOutputSlashes(fname);
+
+ /* For custom targets list any associated sources,
+ * comment out source code to prevent it from being
+ * compiled when processing this target.
+ * Otherwise, comment out any custom command (main) dependencies that
+ * are listed as source files to prevent them from being considered
+ * part of the build.
+ */
+ std::string comment;
+ if ((this->TagType == GhsMultiGpj::CUSTOM_TARGET &&
+ !si->GetLanguage().empty()) ||
+ si->GetCustomCommand()) {
+ comment = "{comment} ";
+ compile = false;
+ }
- std::string configCapped(cmSystemTools::UpperCase(config));
- const char* outputNameSProp =
- this->GeneratorTarget->GetProperty(configCapped + "_OUTPUT_NAME");
- if (NULL != outputNameSProp) {
- outputFilename = outputNameSProp;
+ *fout << comment << fname << std::endl;
+ if (compile) {
+ if ("ld" != si->GetExtension() && "int" != si->GetExtension() &&
+ "bsp" != si->GetExtension()) {
+ WriteObjectLangOverride(*fout, si);
+ }
+
+ this->WriteSourceProperty(*fout, si, "INCLUDE_DIRECTORIES", "-I");
+ this->WriteSourceProperty(*fout, si, "COMPILE_DEFINITIONS", "-D");
+ this->WriteSourceProperty(*fout, si, "COMPILE_OPTIONS", "");
+
+ /* to avoid clutter in the GUI only print out the objectName if it
+ * has been renamed */
+ std::string objectName = this->GeneratorTarget->GetObjectName(si);
+ if (!objectName.empty() &&
+ this->GeneratorTarget->HasExplicitObjectName(si)) {
+ *fout << " -o " << objectName << std::endl;
+ }
+ }
+ }
+ } else {
+ std::vector<cmSourceFile const*> customCommands;
+ if (ComputeCustomCommandOrder(customCommands)) {
+ std::string message = "The custom commands for target [" +
+ this->GeneratorTarget->GetName() + "] had a cycle.\n";
+ cmSystemTools::Error(message);
+ } else {
+ /* Custom targets do not have a dependency on SOURCES files.
+ * Therefore the dependency list may include SOURCES files after the
+ * custom target. Because nothing can depend on the custom target just
+ * move it to the last item.
+ */
+ for (auto sf = customCommands.begin(); sf != customCommands.end();
+ ++sf) {
+ if (((*sf)->GetLocation()).GetName() == this->Name + ".rule") {
+ std::rotate(sf, sf + 1, customCommands.end());
+ break;
+ }
+ }
+ int cmdcount = 0;
+ for (auto& sf : customCommands) {
+ const cmCustomCommand* cc = sf->GetCustomCommand();
+ cmCustomCommandGenerator ccg(*cc, this->ConfigName,
+ this->LocalGenerator);
+
+ // Open the filestream for this custom command
+ std::string fname = cmStrCat(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget),
+ '/', this->Name, "_cc", cmdcount++, '_',
+ (sf->GetLocation()).GetName(),
+ this->CmdWindowsShell ? ".bat" : ".sh");
+ cmGeneratedFileStream f(fname);
+ f.SetCopyIfDifferent(true);
+ this->WriteCustomCommandsHelper(f, ccg);
+ f.Close();
+ this->WriteCustomCommandLine(*fout, fname, ccg);
+ }
+ }
+ if (this->TagType == GhsMultiGpj::CUSTOM_TARGET) {
+ this->WriteBuildEvents(*fout);
+ }
+ }
}
- return outputFilename;
+ for (cmGeneratedFileStream* f : gfiles) {
+ f->Close();
+ }
}
-std::string cmGhsMultiTargetGenerator::ComputeLongestObjectDirectory(
- cmLocalGhsMultiGenerator const* localGhsMultiGenerator,
- cmGeneratorTarget* const generatorTarget, cmSourceFile* const sourceFile)
-{
- std::string dir_max;
- dir_max +=
- localGhsMultiGenerator->GetMakefile()->GetCurrentBinaryDirectory();
- dir_max += "/";
- dir_max += generatorTarget->Target->GetName();
- dir_max += "/";
- std::vector<cmSourceGroup> sourceGroups(
- localGhsMultiGenerator->GetMakefile()->GetSourceGroups());
- char const* const sourceFullPath = sourceFile->GetFullPath().c_str();
- cmSourceGroup* sourceGroup =
- localGhsMultiGenerator->GetMakefile()->FindSourceGroup(sourceFullPath,
- sourceGroups);
- std::string const sgPath(sourceGroup->GetFullName());
- dir_max += sgPath;
- dir_max += "/Objs/libs/";
- dir_max += generatorTarget->Target->GetName();
- dir_max += "/";
- return dir_max;
+void cmGhsMultiTargetGenerator::WriteCustomCommandLine(
+ std::ostream& fout, std::string& fname, cmCustomCommandGenerator const& ccg)
+{
+ /* NOTE: Customization Files are not well documented. Testing showed
+ * that ":outputName=file" can only be used once per script. The
+ * script will only run if ":outputName=file" is missing or just run
+ * once if ":outputName=file" is not specified. If there are
+ * multiple outputs then the script needs to be listed multiple times
+ * for each output. Otherwise it won't rerun the script if one of
+ * the outputs is manually deleted.
+ */
+ bool specifyExtra = true;
+ for (auto& out : ccg.GetOutputs()) {
+ fout << fname << std::endl;
+ fout << " :outputName=\"" << out << "\"" << std::endl;
+ if (specifyExtra) {
+ for (auto& byp : ccg.GetByproducts()) {
+ fout << " :extraOutputFile=\"" << byp << "\"" << std::endl;
+ }
+ for (auto& dep : ccg.GetDepends()) {
+ fout << " :depends=\"" << dep << "\"" << std::endl;
+ }
+ specifyExtra = false;
+ }
+ }
}
-bool cmGhsMultiTargetGenerator::IsNotKernel(std::string const& config,
- const std::string& language)
+void cmGhsMultiTargetGenerator::WriteObjectLangOverride(
+ std::ostream& fout, const cmSourceFile* sourceFile)
{
- bool output;
- std::vector<std::string> options;
- this->GeneratorTarget->GetCompileOptions(options, config, language);
- output =
- options.end() == std::find(options.begin(), options.end(), "-kernel");
- return output;
+ const char* rawLangProp = sourceFile->GetProperty("LANGUAGE");
+ if (nullptr != rawLangProp) {
+ std::string sourceLangProp(rawLangProp);
+ std::string const& extension = sourceFile->GetExtension();
+ if ("CXX" == sourceLangProp && ("c" == extension || "C" == extension)) {
+ fout << " -dotciscxx" << std::endl;
+ }
+ }
}
-bool cmGhsMultiTargetGenerator::DetermineIfTargetGroup(
- const cmGeneratorTarget* target)
+bool cmGhsMultiTargetGenerator::DetermineIfIntegrityApp()
{
- bool output = false;
+ const char* p = this->GeneratorTarget->GetProperty("ghs_integrity_app");
+ if (p) {
+ return cmIsOn(this->GeneratorTarget->GetProperty("ghs_integrity_app"));
+ }
std::vector<cmSourceFile*> sources;
- std::string config =
- target->Target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
- target->GetSourceFiles(sources, config);
- for (std::vector<cmSourceFile*>::const_iterator sources_i = sources.begin();
- sources.end() != sources_i; ++sources_i) {
- if ("int" == (*sources_i)->GetExtension()) {
- output = true;
+ this->GeneratorTarget->GetSourceFiles(sources, this->ConfigName);
+ for (auto& sf : sources) {
+ if ("int" == sf->GetExtension()) {
+ return true;
}
}
- return output;
+ return false;
}
-bool cmGhsMultiTargetGenerator::DetermineIfDynamicDownload(
- std::string const& config, const std::string& language)
+bool cmGhsMultiTargetGenerator::ComputeCustomCommandOrder(
+ std::vector<cmSourceFile const*>& order)
{
- std::vector<std::string> options;
- bool output = false;
- this->GeneratorTarget->GetCompileOptions(options, config, language);
- for (std::vector<std::string>::const_iterator options_i = options.begin();
- options_i != options.end(); ++options_i) {
- std::string option = *options_i;
- if (this->DDOption == option) {
- output = true;
+ std::set<cmSourceFile const*> temp;
+ std::set<cmSourceFile const*> perm;
+
+ // Collect all custom commands for this target
+ std::vector<cmSourceFile const*> customCommands;
+ this->GeneratorTarget->GetCustomCommands(customCommands, this->ConfigName);
+
+ for (cmSourceFile const* si : customCommands) {
+ bool r = VisitCustomCommand(temp, perm, order, si);
+ if (r) {
+ return r;
+ }
+ }
+ return false;
+}
+
+bool cmGhsMultiTargetGenerator::VisitCustomCommand(
+ std::set<cmSourceFile const*>& temp, std::set<cmSourceFile const*>& perm,
+ std::vector<cmSourceFile const*>& order, cmSourceFile const* si)
+{
+ /* check if permanent mark is set*/
+ if (perm.find(si) == perm.end()) {
+ /* set temporary mark; check if revisit*/
+ if (temp.insert(si).second) {
+ for (auto& di : si->GetCustomCommand()->GetDepends()) {
+ cmSourceFile const* sf = this->GeneratorTarget->GetLocalGenerator()
+ ->GetMakefile()
+ ->GetSourceFileWithOutput(di);
+ /* if sf exists then visit */
+ if (sf && this->VisitCustomCommand(temp, perm, order, sf)) {
+ return true;
+ }
+ }
+ /* mark as complete; insert into beginning of list*/
+ perm.insert(si);
+ order.push_back(si);
+ return false;
}
+ /* revisiting item - not a DAG */
+ return true;
}
- return output;
+ /* already complete */
+ return false;
}
diff --git a/Source/cmGhsMultiTargetGenerator.h b/Source/cmGhsMultiTargetGenerator.h
index 2cdf68e11..f03ca44a2 100644
--- a/Source/cmGhsMultiTargetGenerator.h
+++ b/Source/cmGhsMultiTargetGenerator.h
@@ -3,12 +3,16 @@
#ifndef cmGhsMultiTargetGenerator_h
#define cmGhsMultiTargetGenerator_h
-#include "cmGhsMultiGpj.h"
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
-#include "cmTarget.h"
+#include "cmGhsMultiGpj.h"
class cmCustomCommand;
-class cmGeneratedFileStream;
+class cmCustomCommandGenerator;
class cmGeneratorTarget;
class cmGlobalGhsMultiGenerator;
class cmLocalGhsMultiGenerator;
@@ -24,97 +28,59 @@ public:
virtual void Generate();
- bool IncludeThisTarget();
- std::vector<cmSourceFile*> GetSources() const;
- GhsMultiGpj::Types GetGpjTag() const;
- static GhsMultiGpj::Types GetGpjTag(const cmGeneratorTarget* target);
- const char* GetAbsBuildFilePath() const
- {
- return this->AbsBuildFilePath.c_str();
- }
- const char* GetRelBuildFileName() const
- {
- return this->RelBuildFileName.c_str();
- }
- const char* GetAbsBuildFileName() const
- {
- return this->AbsBuildFileName.c_str();
- }
- const char* GetAbsOutputFileName() const
- {
- return this->AbsOutputFileName.c_str();
- }
-
- static std::string GetRelBuildFilePath(const cmGeneratorTarget* target);
- static std::string GetAbsPathToRoot(const cmGeneratorTarget* target);
- static std::string GetAbsBuildFilePath(const cmGeneratorTarget* target);
- static std::string GetRelBuildFileName(const cmGeneratorTarget* target);
- static std::string GetBuildFileName(const cmGeneratorTarget* target);
- static std::string AddSlashIfNeededToPath(std::string const& input);
-
private:
cmGlobalGhsMultiGenerator* GetGlobalGenerator() const;
- cmGeneratedFileStream* GetFolderBuildStreams()
- {
- return this->FolderBuildStreams[""];
- };
- bool IsTargetGroup() const { return this->TargetGroup; }
-
- void WriteTypeSpecifics(const std::string& config, bool notKernel);
- void WriteCompilerFlags(const std::string& config,
+
+ void GenerateTarget();
+
+ void WriteTargetSpecifics(std::ostream& fout, const std::string& config);
+
+ void WriteCompilerFlags(std::ostream& fout, const std::string& config,
const std::string& language);
- void WriteCompilerDefinitions(const std::string& config,
+ void WriteCompilerDefinitions(std::ostream& fout, const std::string& config,
const std::string& language);
- void SetCompilerFlags(std::string const& config, const std::string& language,
- bool const notKernel);
+ void SetCompilerFlags(std::string const& config,
+ const std::string& language);
+
std::string GetDefines(const std::string& langugae,
std::string const& config);
- void WriteIncludes(const std::string& config, const std::string& language);
- void WriteTargetLinkLibraries(std::string const& config,
- std::string const& language);
- void WriteCustomCommands();
- void WriteCustomCommandsHelper(
- std::vector<cmCustomCommand> const& commandsSet,
- cmTarget::CustomCommandType commandType);
- void WriteSources(
- std::vector<cmSourceFile*> const& objectSources,
- std::map<const cmSourceFile*, std::string> const& objectNames);
- static std::map<const cmSourceFile*, std::string> GetObjectNames(
- std::vector<cmSourceFile*>* objectSources,
- cmLocalGhsMultiGenerator* localGhsMultiGenerator,
- cmGeneratorTarget* generatorTarget);
- static void WriteObjectLangOverride(cmGeneratedFileStream* fileStream,
- cmSourceFile* sourceFile);
- static void WriteObjectDir(cmGeneratedFileStream* fileStream,
- std::string const& dir);
- std::string GetOutputDirectory(const std::string& config) const;
- std::string GetOutputFilename(const std::string& config) const;
- static std::string ComputeLongestObjectDirectory(
- cmLocalGhsMultiGenerator const* localGhsMultiGenerator,
- cmGeneratorTarget* generatorTarget, cmSourceFile* const sourceFile);
-
- bool IsNotKernel(std::string const& config, const std::string& language);
- static bool DetermineIfTargetGroup(const cmGeneratorTarget* target);
- bool DetermineIfDynamicDownload(std::string const& config,
- const std::string& language);
+ void WriteIncludes(std::ostream& fout, const std::string& config,
+ const std::string& language);
+ void WriteTargetLinkLine(std::ostream& fout, std::string const& config);
+ void WriteBuildEvents(std::ostream& fout);
+ void WriteBuildEventsHelper(std::ostream& fout,
+ const std::vector<cmCustomCommand>& ccv,
+ std::string const& name, std::string const& cmd);
+ void WriteCustomCommandsHelper(std::ostream& fout,
+ cmCustomCommandGenerator const& ccg);
+ void WriteCustomCommandLine(std::ostream& fout, std::string& fname,
+ cmCustomCommandGenerator const& ccg);
+ bool ComputeCustomCommandOrder(std::vector<cmSourceFile const*>& order);
+ bool VisitCustomCommand(std::set<cmSourceFile const*>& temp,
+ std::set<cmSourceFile const*>& perm,
+ std::vector<cmSourceFile const*>& order,
+ cmSourceFile const* sf);
+ void WriteSources(std::ostream& fout_proj);
+ void WriteSourceProperty(std::ostream& fout, const cmSourceFile* sf,
+ std::string const& propName,
+ std::string const& propFlag);
+ static void WriteObjectLangOverride(std::ostream& fout,
+ const cmSourceFile* sourceFile);
+ bool DetermineIfIntegrityApp();
cmGeneratorTarget* GeneratorTarget;
cmLocalGhsMultiGenerator* LocalGenerator;
cmMakefile* Makefile;
- std::string AbsBuildFilePath;
- std::string RelBuildFilePath;
- std::string AbsBuildFileName;
- std::string RelBuildFileName;
- std::string RelOutputFileName;
- std::string AbsOutputFileName;
- std::map<std::string, cmGeneratedFileStream*> FolderBuildStreams;
- bool TargetGroup;
- bool DynamicDownload;
- static std::string const DDOption;
std::map<std::string, std::string> FlagsByLanguage;
std::map<std::string, std::string> DefinesByLanguage;
+
+ std::string TargetNameReal;
+ GhsMultiGpj::Types TagType;
+ std::string const Name;
+ std::string ConfigName; /* CMAKE_BUILD_TYPE */
+ bool const CmdWindowsShell; /* custom commands run in cmd.exe or /bin/sh */
};
#endif // ! cmGhsMultiTargetGenerator_h
diff --git a/Source/cmGlobVerificationManager.cxx b/Source/cmGlobVerificationManager.cxx
new file mode 100644
index 000000000..481777345
--- /dev/null
+++ b/Source/cmGlobVerificationManager.cxx
@@ -0,0 +1,179 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmGlobVerificationManager.h"
+
+#include <sstream>
+
+#include "cmsys/FStream.hxx"
+
+#include "cmGeneratedFileStream.h"
+#include "cmListFileCache.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmVersion.h"
+
+bool cmGlobVerificationManager::SaveVerificationScript(const std::string& path)
+{
+ if (this->Cache.empty()) {
+ return true;
+ }
+
+ std::string scriptFile = cmStrCat(path, "/CMakeFiles");
+ std::string stampFile = scriptFile;
+ cmSystemTools::MakeDirectory(scriptFile);
+ scriptFile += "/VerifyGlobs.cmake";
+ stampFile += "/cmake.verify_globs";
+ cmGeneratedFileStream verifyScriptFile(scriptFile);
+ verifyScriptFile.SetCopyIfDifferent(true);
+ if (!verifyScriptFile) {
+ cmSystemTools::Error("Unable to open verification script file for save. " +
+ scriptFile);
+ cmSystemTools::ReportLastSystemError("");
+ return false;
+ }
+
+ verifyScriptFile << std::boolalpha;
+ verifyScriptFile << "# CMAKE generated file: DO NOT EDIT!\n"
+ << "# Generated by CMake Version "
+ << cmVersion::GetMajorVersion() << "."
+ << cmVersion::GetMinorVersion() << "\n";
+
+ for (auto const& i : this->Cache) {
+ CacheEntryKey k = std::get<0>(i);
+ CacheEntryValue v = std::get<1>(i);
+
+ if (!v.Initialized) {
+ continue;
+ }
+
+ verifyScriptFile << "\n";
+
+ for (auto const& bt : v.Backtraces) {
+ verifyScriptFile << "# " << std::get<0>(bt);
+ std::get<1>(bt).PrintTitle(verifyScriptFile);
+ verifyScriptFile << "\n";
+ }
+
+ k.PrintGlobCommand(verifyScriptFile, "NEW_GLOB");
+ verifyScriptFile << "\n";
+
+ verifyScriptFile << "set(OLD_GLOB\n";
+ for (const std::string& file : v.Files) {
+ verifyScriptFile << " \"" << file << "\"\n";
+ }
+ verifyScriptFile << " )\n";
+
+ verifyScriptFile << "if(NOT \"${NEW_GLOB}\" STREQUAL \"${OLD_GLOB}\")\n"
+ << " message(\"-- GLOB mismatch!\")\n"
+ << " file(TOUCH_NOCREATE \"" << stampFile << "\")\n"
+ << "endif()\n";
+ }
+ verifyScriptFile.Close();
+
+ cmsys::ofstream verifyStampFile(stampFile.c_str());
+ if (!verifyStampFile) {
+ cmSystemTools::Error("Unable to open verification stamp file for write. " +
+ stampFile);
+ return false;
+ }
+ verifyStampFile << "# This file is generated by CMake for checking of the "
+ "VerifyGlobs.cmake file\n";
+ this->VerifyScript = scriptFile;
+ this->VerifyStamp = stampFile;
+ return true;
+}
+
+bool cmGlobVerificationManager::DoWriteVerifyTarget() const
+{
+ return !this->VerifyScript.empty() && !this->VerifyStamp.empty();
+}
+
+bool cmGlobVerificationManager::CacheEntryKey::operator<(
+ const CacheEntryKey& r) const
+{
+ if (this->Recurse < r.Recurse) {
+ return true;
+ }
+ if (this->Recurse > r.Recurse) {
+ return false;
+ }
+ if (this->ListDirectories < r.ListDirectories) {
+ return true;
+ }
+ if (this->ListDirectories > r.ListDirectories) {
+ return false;
+ }
+ if (this->FollowSymlinks < r.FollowSymlinks) {
+ return true;
+ }
+ if (this->FollowSymlinks > r.FollowSymlinks) {
+ return false;
+ }
+ if (this->Relative < r.Relative) {
+ return true;
+ }
+ if (this->Relative > r.Relative) {
+ return false;
+ }
+ if (this->Expression < r.Expression) {
+ return true;
+ }
+ if (this->Expression > r.Expression) {
+ return false;
+ }
+ return false;
+}
+
+void cmGlobVerificationManager::CacheEntryKey::PrintGlobCommand(
+ std::ostream& out, const std::string& cmdVar)
+{
+ out << "file(GLOB" << (this->Recurse ? "_RECURSE " : " ");
+ out << cmdVar << " ";
+ if (this->Recurse && this->FollowSymlinks) {
+ out << "FOLLOW_SYMLINKS ";
+ }
+ out << "LIST_DIRECTORIES " << this->ListDirectories << " ";
+ if (!this->Relative.empty()) {
+ out << "RELATIVE \"" << this->Relative << "\" ";
+ }
+ out << "\"" << this->Expression << "\")";
+}
+
+void cmGlobVerificationManager::AddCacheEntry(
+ const bool recurse, const bool listDirectories, const bool followSymlinks,
+ const std::string& relative, const std::string& expression,
+ const std::vector<std::string>& files, const std::string& variable,
+ const cmListFileBacktrace& backtrace)
+{
+ CacheEntryKey key = CacheEntryKey(recurse, listDirectories, followSymlinks,
+ relative, expression);
+ CacheEntryValue& value = this->Cache[key];
+ if (!value.Initialized) {
+ value.Files = files;
+ value.Initialized = true;
+ value.Backtraces.emplace_back(variable, backtrace);
+ } else if (value.Initialized && value.Files != files) {
+ std::ostringstream message;
+ message << std::boolalpha;
+ message << "The glob expression\n";
+ key.PrintGlobCommand(message, variable);
+ backtrace.PrintTitle(message);
+ message << "\nwas already present in the glob cache but the directory\n"
+ "contents have changed during the configuration run.\n";
+ message << "Matching glob expressions:";
+ for (auto const& bt : value.Backtraces) {
+ message << "\n " << std::get<0>(bt);
+ std::get<1>(bt).PrintTitle(message);
+ }
+ cmSystemTools::Error(message.str());
+ } else {
+ value.Backtraces.emplace_back(variable, backtrace);
+ }
+}
+
+void cmGlobVerificationManager::Reset()
+{
+ this->Cache.clear();
+ this->VerifyScript.clear();
+ this->VerifyStamp.clear();
+}
diff --git a/Source/cmGlobVerificationManager.h b/Source/cmGlobVerificationManager.h
new file mode 100644
index 000000000..2e7e1ca70
--- /dev/null
+++ b/Source/cmGlobVerificationManager.h
@@ -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. */
+#ifndef cmGlobVerificationManager_h
+#define cmGlobVerificationManager_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <iosfwd>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cmListFileCache.h"
+
+/** \class cmGlobVerificationManager
+ * \brief Class for expressing build-time dependencies on glob expressions.
+ *
+ * Generates a CMake script which verifies glob outputs during prebuild.
+ *
+ */
+class cmGlobVerificationManager
+{
+protected:
+ //! Save verification script for given makefile.
+ //! Saves to output <path>/<CMakeFilesDirectory>/VerifyGlobs.cmake
+ bool SaveVerificationScript(const std::string& path);
+
+ //! Add an entry into the glob cache
+ void AddCacheEntry(bool recurse, bool listDirectories, bool followSymlinks,
+ const std::string& relative,
+ const std::string& expression,
+ const std::vector<std::string>& files,
+ const std::string& variable,
+ const cmListFileBacktrace& bt);
+
+ //! Clear the glob cache for state reset.
+ void Reset();
+
+ //! Check targets should be written in generated build system.
+ bool DoWriteVerifyTarget() const;
+
+ //! Get the paths to the generated script and stamp files
+ std::string const& GetVerifyScript() const { return this->VerifyScript; }
+ std::string const& GetVerifyStamp() const { return this->VerifyStamp; }
+
+private:
+ struct CacheEntryKey
+ {
+ const bool Recurse;
+ const bool ListDirectories;
+ const bool FollowSymlinks;
+ const std::string Relative;
+ const std::string Expression;
+ CacheEntryKey(const bool rec, const bool l, const bool s, std::string rel,
+ std::string e)
+ : Recurse(rec)
+ , ListDirectories(l)
+ , FollowSymlinks(s)
+ , Relative(std::move(rel))
+ , Expression(std::move(e))
+ {
+ }
+ bool operator<(const CacheEntryKey& r) const;
+ void PrintGlobCommand(std::ostream& out, const std::string& cmdVar);
+ };
+
+ struct CacheEntryValue
+ {
+ bool Initialized = false;
+ std::vector<std::string> Files;
+ std::vector<std::pair<std::string, cmListFileBacktrace>> Backtraces;
+ };
+
+ using CacheEntryMap = std::map<CacheEntryKey, CacheEntryValue>;
+ CacheEntryMap Cache;
+ std::string VerifyScript;
+ std::string VerifyStamp;
+
+ // Only cmState should be able to add cache values.
+ // cmGlobVerificationManager should never be used directly.
+ friend class cmState; // allow access to add cache values
+};
+
+#endif
diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx
index d2372a766..51d681dee 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.cxx
+++ b/Source/cmGlobalBorlandMakefileGenerator.cxx
@@ -5,6 +5,7 @@
#include "cmDocumentationEntry.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmState.h"
#include "cmake.h"
@@ -33,7 +34,7 @@ void cmGlobalBorlandMakefileGenerator::EnableLanguage(
this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
}
-///! Create a local generator appropriate to this Global Generator
+//! Create a local generator appropriate to this Global Generator
cmLocalGenerator* cmGlobalBorlandMakefileGenerator::CreateLocalGenerator(
cmMakefile* mf)
{
@@ -51,3 +52,33 @@ void cmGlobalBorlandMakefileGenerator::GetDocumentation(
entry.Name = cmGlobalBorlandMakefileGenerator::GetActualName();
entry.Brief = "Generates Borland makefiles.";
}
+
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalBorlandMakefileGenerator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int /*jobs*/, bool verbose,
+ std::vector<std::string> const& makeOptions)
+{
+ return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
+ makeProgram, projectName, projectDir, targetNames, config, fast,
+ cmake::NO_BUILD_PARALLEL_LEVEL, verbose, makeOptions);
+}
+
+void cmGlobalBorlandMakefileGenerator::PrintBuildCommandAdvice(
+ std::ostream& os, int jobs) const
+{
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ // Borland's make does not support parallel builds
+ // see http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Make
+
+ /* clang-format off */
+ os <<
+ "Warning: Borland's make does not support parallel builds. "
+ "Ignoring parallel build command line option.\n";
+ /* clang-format on */
+ }
+
+ this->cmGlobalUnixMakefileGenerator3::PrintBuildCommandAdvice(
+ os, cmake::NO_BUILD_PARALLEL_LEVEL);
+}
diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h
index 5578d7646..da04743ac 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.h
+++ b/Source/cmGlobalBorlandMakefileGenerator.h
@@ -3,6 +3,8 @@
#ifndef cmGlobalBorlandMakefileGenerator_h
#define cmGlobalBorlandMakefileGenerator_h
+#include <iosfwd>
+
#include "cmGlobalNMakeMakefileGenerator.h"
/** \class cmGlobalBorlandMakefileGenerator
@@ -20,8 +22,8 @@ public:
cmGlobalBorlandMakefileGenerator>();
}
- ///! Get the name for the generator.
- virtual std::string GetName() const
+ //! Get the name for the generator.
+ std::string GetName() const override
{
return cmGlobalBorlandMakefileGenerator::GetActualName();
}
@@ -30,18 +32,28 @@ public:
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
- ///! Create a local generator appropriate to this Global Generator
- virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf);
+ //! Create a local generator appropriate to this Global Generator
+ 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);
+ void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
+ bool optional) override;
+
+ bool AllowNotParallel() const override { return false; }
+ bool AllowDeleteOnError() const override { return false; }
+
+protected:
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
- virtual bool AllowNotParallel() const { return false; }
- virtual bool AllowDeleteOnError() const { return false; }
+ void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override;
};
#endif
diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx
index 3b7de4b9c..9fa4467b2 100644
--- a/Source/cmGlobalCommonGenerator.cxx
+++ b/Source/cmGlobalCommonGenerator.cxx
@@ -2,6 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalCommonGenerator.h"
+#include <utility>
+
+#include "cmGeneratorTarget.h"
+#include "cmLocalGenerator.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+
class cmake;
cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm)
@@ -9,6 +18,61 @@ cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm)
{
}
-cmGlobalCommonGenerator::~cmGlobalCommonGenerator()
+cmGlobalCommonGenerator::~cmGlobalCommonGenerator() = default;
+
+std::map<std::string, cmGlobalCommonGenerator::DirectoryTarget>
+cmGlobalCommonGenerator::ComputeDirectoryTargets() const
{
+ std::map<std::string, DirectoryTarget> dirTargets;
+ for (cmLocalGenerator* lg : this->LocalGenerators) {
+ std::string const& currentBinaryDir(
+ lg->GetStateSnapshot().GetDirectory().GetCurrentBinary());
+ DirectoryTarget& dirTarget = dirTargets[currentBinaryDir];
+ dirTarget.LG = lg;
+
+ // The directory-level rule should depend on the target-level rules
+ // for all targets in the directory.
+ for (auto gt : lg->GetGeneratorTargets()) {
+ cmStateEnums::TargetType const type = gt->GetType();
+ if (type != cmStateEnums::EXECUTABLE &&
+ type != cmStateEnums::STATIC_LIBRARY &&
+ type != cmStateEnums::SHARED_LIBRARY &&
+ type != cmStateEnums::MODULE_LIBRARY &&
+ type != cmStateEnums::OBJECT_LIBRARY &&
+ type != cmStateEnums::UTILITY) {
+ continue;
+ }
+ DirectoryTarget::Target t;
+ t.GT = gt;
+ if (const char* exclude = gt->GetProperty("EXCLUDE_FROM_ALL")) {
+ if (cmIsOn(exclude)) {
+ // This target has been explicitly excluded.
+ t.ExcludeFromAll = true;
+ } else {
+ // This target has been explicitly un-excluded. The directory-level
+ // rule for every directory between this and the root should depend
+ // on the target-level rule for this target.
+ for (cmStateSnapshot dir =
+ lg->GetStateSnapshot().GetBuildsystemDirectoryParent();
+ dir.IsValid(); dir = dir.GetBuildsystemDirectoryParent()) {
+ std::string const& d = dir.GetDirectory().GetCurrentBinary();
+ dirTargets[d].Targets.emplace_back(t);
+ }
+ }
+ }
+ dirTarget.Targets.emplace_back(t);
+ }
+
+ // The directory-level rule should depend on the directory-level
+ // rules of the subdirectories.
+ for (cmStateSnapshot const& state : lg->GetStateSnapshot().GetChildren()) {
+ DirectoryTarget::Dir d;
+ d.Path = state.GetDirectory().GetCurrentBinary();
+ d.ExcludeFromAll =
+ state.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL");
+ dirTarget.Children.emplace_back(std::move(d));
+ }
+ }
+
+ return dirTargets;
}
diff --git a/Source/cmGlobalCommonGenerator.h b/Source/cmGlobalCommonGenerator.h
index f2ad059de..7d16daca2 100644
--- a/Source/cmGlobalCommonGenerator.h
+++ b/Source/cmGlobalCommonGenerator.h
@@ -3,11 +3,17 @@
#ifndef cmGlobalCommonGenerator_h
#define cmGlobalCommonGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <string>
+#include <vector>
#include "cmGlobalGenerator.h"
class cmake;
+class cmGeneratorTarget;
+class cmLocalGenerator;
/** \class cmGlobalCommonGenerator
* \brief Common infrastructure for Makefile and Ninja global generators.
@@ -16,7 +22,25 @@ class cmGlobalCommonGenerator : public cmGlobalGenerator
{
public:
cmGlobalCommonGenerator(cmake* cm);
- ~cmGlobalCommonGenerator() CM_OVERRIDE;
+ ~cmGlobalCommonGenerator() override;
+
+ struct DirectoryTarget
+ {
+ cmLocalGenerator* LG = nullptr;
+ struct Target
+ {
+ cmGeneratorTarget const* GT = nullptr;
+ bool ExcludeFromAll = false;
+ };
+ std::vector<Target> Targets;
+ struct Dir
+ {
+ std::string Path;
+ bool ExcludeFromAll = false;
+ };
+ std::vector<Dir> Children;
+ };
+ std::map<std::string, DirectoryTarget> ComputeDirectoryTargets() const;
};
#endif
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 099f705f4..09fb87dd7 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -2,18 +2,20 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalGenerator.h"
-#include "cmsys/Directory.hxx"
-#include "cmsys/FStream.hxx"
#include <algorithm>
-#include <assert.h>
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <initializer_list>
#include <iterator>
#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <windows.h>
+# include <windows.h>
#endif
#include "cmAlgorithms.h"
@@ -21,6 +23,7 @@
#include "cmComputeTargetDepends.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
+#include "cmDuration.h"
#include "cmExportBuildFileGenerator.h"
#include "cmExternalMakefileProjectGenerator.h"
#include "cmGeneratedFileStream.h"
@@ -31,9 +34,9 @@
#include "cmLocalGenerator.h"
#include "cmMSVC60LinkLineComputer.h"
#include "cmMakefile.h"
-#include "cmOutputConverter.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmQtAutoGeneratorInitializer.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateDirectory.h"
@@ -42,14 +45,16 @@
#include "cmWorkingDirectory.h"
#include "cmake.h"
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmCryptoHash.h"
-#include "cm_jsoncpp_value.h"
-#include "cm_jsoncpp_writer.h"
+#if !defined(CMAKE_BOOTSTRAP)
+# include "cm_jsoncpp_value.h"
+# include "cm_jsoncpp_writer.h"
+
+# include "cmCryptoHash.h"
+# include "cmQtAutoGenGlobalInitializer.h"
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1800
-#define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
#endif
const std::string kCMAKE_PLATFORM_INFO_INITIALIZED =
@@ -62,8 +67,8 @@ bool cmTarget::StrictTargetComparison::operator()(cmTarget const* t1,
{
int nameResult = strcmp(t1->GetName().c_str(), t2->GetName().c_str());
if (nameResult == 0) {
- return strcmp(t1->GetMakefile()->GetCurrentBinaryDirectory(),
- t2->GetMakefile()->GetCurrentBinaryDirectory()) < 0;
+ return strcmp(t1->GetMakefile()->GetCurrentBinaryDirectory().c_str(),
+ t2->GetMakefile()->GetCurrentBinaryDirectory().c_str()) < 0;
}
return nameResult < 0;
}
@@ -87,15 +92,16 @@ cmGlobalGenerator::cmGlobalGenerator(cmake* cm)
this->InstallTargetEnabled = false;
// how long to let try compiles run
- this->TryCompileTimeout = 0;
+ this->TryCompileTimeout = cmDuration::zero();
- this->ExtraGenerator = CM_NULLPTR;
- this->CurrentMakefile = CM_NULLPTR;
- this->TryCompileOuterMakefile = CM_NULLPTR;
+ this->CurrentConfigureMakefile = nullptr;
+ this->TryCompileOuterMakefile = nullptr;
this->ConfigureDoneCMP0026AndCMP0024 = false;
this->FirstTimeProgress = 0.0f;
+ this->RecursionDepth = 0;
+
cm->GetState()->SetIsGeneratorMultiConfig(false);
cm->GetState()->SetMinGWMake(false);
cm->GetState()->SetMSYSShell(false);
@@ -108,7 +114,35 @@ cmGlobalGenerator::cmGlobalGenerator(cmake* cm)
cmGlobalGenerator::~cmGlobalGenerator()
{
this->ClearGeneratorMembers();
- delete this->ExtraGenerator;
+}
+
+#if !defined(CMAKE_BOOTSTRAP)
+Json::Value cmGlobalGenerator::GetJson() const
+{
+ Json::Value generator = Json::objectValue;
+ generator["name"] = this->GetName();
+ return generator;
+}
+#endif
+
+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(MessageType::FATAL_ERROR, e.str());
+ return false;
}
bool cmGlobalGenerator::SetGeneratorPlatform(std::string const& p,
@@ -127,7 +161,7 @@ bool cmGlobalGenerator::SetGeneratorPlatform(std::string const& p,
" " << p << "\n"
"was specified.";
/* clang-format on */
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
@@ -146,7 +180,7 @@ bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts,
" " << ts << "\n"
"was specified.";
/* clang-format on */
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
@@ -154,15 +188,15 @@ std::string cmGlobalGenerator::SelectMakeProgram(
const std::string& inMakeProgram, const std::string& makeDefault) const
{
std::string makeProgram = inMakeProgram;
- if (cmSystemTools::IsOff(makeProgram.c_str())) {
+ if (cmIsOff(makeProgram)) {
const char* makeProgramCSTR =
this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
- if (cmSystemTools::IsOff(makeProgramCSTR)) {
+ if (cmIsOff(makeProgramCSTR)) {
makeProgram = makeDefault;
} else {
makeProgram = makeProgramCSTR;
}
- if (cmSystemTools::IsOff(makeProgram.c_str()) && !makeProgram.empty()) {
+ if (cmIsOff(makeProgram) && !makeProgram.empty()) {
makeProgram = "CMAKE_MAKE_PROGRAM-NOTFOUND";
}
}
@@ -173,17 +207,15 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang,
cmMakefile* mf,
bool optional) const
{
- std::string langComp = "CMAKE_";
- langComp += lang;
- langComp += "_COMPILER";
+ std::string langComp = cmStrCat("CMAKE_", lang, "_COMPILER");
if (!mf->GetDefinition(langComp)) {
if (!optional) {
- cmSystemTools::Error(langComp.c_str(), " not set, after EnableLanguage");
+ cmSystemTools::Error(langComp + " not set, after EnableLanguage");
}
return;
}
- const char* name = mf->GetRequiredDefinition(langComp);
+ std::string const& name = mf->GetRequiredDefinition(langComp);
std::string path;
if (!cmSystemTools::FileIsFullPath(name)) {
path = cmSystemTools::FindProgram(name);
@@ -193,15 +225,15 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang,
if (!optional && (path.empty() || !cmSystemTools::FileExists(path))) {
return;
}
- const char* cname =
+ const std::string* cname =
this->GetCMakeInstance()->GetState()->GetInitializedCacheValue(langComp);
std::string changeVars;
if (cname && !optional) {
std::string cnameString;
- if (!cmSystemTools::FileIsFullPath(cname)) {
- cnameString = cmSystemTools::FindProgram(cname);
+ if (!cmSystemTools::FileIsFullPath(*cname)) {
+ cnameString = cmSystemTools::FindProgram(*cname);
} else {
- cnameString = cname;
+ cnameString = *cname;
}
std::string pathString = path;
// get rid of potentially multiple slashes:
@@ -217,7 +249,7 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang,
}
changeVars += langComp;
changeVars += ";";
- changeVars += cname;
+ changeVars += *cname;
this->GetCMakeInstance()->GetState()->SetGlobalProperty(
"__CMAKE_DELETE_CACHE_CHANGE_VARS_", changeVars.c_str());
}
@@ -238,21 +270,18 @@ void cmGlobalGenerator::AddBuildExportExportSet(
bool cmGlobalGenerator::GenerateImportFile(const std::string& file)
{
- std::map<std::string, cmExportBuildFileGenerator*>::iterator it =
- this->BuildExportSets.find(file);
+ auto const it = this->BuildExportSets.find(file);
if (it != this->BuildExportSets.end()) {
bool result = it->second->GenerateImportFile();
if (!this->ConfigureDoneCMP0026AndCMP0024) {
- for (std::vector<cmMakefile*>::const_iterator mit =
- this->Makefiles.begin();
- mit != this->Makefiles.end(); ++mit) {
- (*mit)->RemoveExportBuildFileGeneratorCMP0024(it->second);
+ for (cmMakefile* m : this->Makefiles) {
+ m->RemoveExportBuildFileGeneratorCMP0024(it->second);
}
}
delete it->second;
- it->second = CM_NULLPTR;
+ it->second = nullptr;
this->BuildExportSets.erase(it);
return result;
}
@@ -263,16 +292,115 @@ void cmGlobalGenerator::ForceLinkerLanguages()
{
}
+bool cmGlobalGenerator::CheckTargetsForMissingSources() const
+{
+ bool failed = false;
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ for (cmGeneratorTarget* target : localGen->GetGeneratorTargets()) {
+ if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET ||
+ target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY ||
+ target->GetType() == cmStateEnums::TargetType::UTILITY ||
+ cmIsOn(target->GetProperty("ghs_integrity_app"))) {
+ continue;
+ }
+
+ std::vector<std::string> configs;
+ target->Makefile->GetConfigurations(configs);
+ std::vector<cmSourceFile*> srcs;
+ if (configs.empty()) {
+ target->GetSourceFiles(srcs, "");
+ } else {
+ for (std::string const& config : configs) {
+ target->GetSourceFiles(srcs, config);
+ if (srcs.empty()) {
+ break;
+ }
+ }
+ }
+ if (srcs.empty()) {
+ std::ostringstream e;
+ e << "No SOURCES given to target: " << target->GetName();
+ this->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR, e.str(), target->GetBacktrace());
+ failed = true;
+ }
+ }
+ }
+ return failed;
+}
+
+bool cmGlobalGenerator::CheckTargetsForType() const
+{
+ if (!this->GetLanguageEnabled("Swift")) {
+ return false;
+ }
+ bool failed = false;
+ for (cmLocalGenerator* generator : this->LocalGenerators) {
+ for (cmGeneratorTarget* target : generator->GetGeneratorTargets()) {
+ if (target->GetType() == cmStateEnums::EXECUTABLE &&
+ target->GetPropertyAsBool("WIN32_EXECUTABLE")) {
+ std::vector<std::string> const& configs =
+ target->Makefile->GetGeneratorConfigs();
+ for (std::string const& config : configs) {
+ if (target->GetLinkerLanguage(config) == "Swift") {
+ this->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "WIN32_EXECUTABLE property is not supported on Swift "
+ "executables",
+ target->GetBacktrace());
+ failed = true;
+ }
+ }
+ }
+ }
+ }
+ return failed;
+}
+
+bool cmGlobalGenerator::CheckTargetsForPchCompilePdb() const
+{
+ if (!this->GetLanguageEnabled("C") && !this->GetLanguageEnabled("CXX")) {
+ return false;
+ }
+ bool failed = false;
+ for (cmLocalGenerator* generator : this->LocalGenerators) {
+ for (cmGeneratorTarget* target : generator->GetGeneratorTargets()) {
+ if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET ||
+ target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY ||
+ target->GetType() == cmStateEnums::TargetType::UTILITY ||
+ cmIsOn(target->GetProperty("ghs_integrity_app"))) {
+ continue;
+ }
+
+ const std::string reuseFrom =
+ target->GetSafeProperty("PRECOMPILE_HEADERS_REUSE_FROM");
+ const std::string compilePdb =
+ target->GetSafeProperty("COMPILE_PDB_NAME");
+
+ if (!reuseFrom.empty() && reuseFrom != compilePdb) {
+ const std::string e = cmStrCat(
+ "PRECOMPILE_HEADERS_REUSE_FROM property is set on target (\"",
+ target->GetName(),
+ "\"). Reusable precompile headers requires the COMPILE_PDB_NAME"
+ " property to have the value \"",
+ reuseFrom, "\"\n");
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e,
+ target->GetBacktrace());
+ failed = true;
+ }
+ }
+ }
+ return failed;
+}
+
bool cmGlobalGenerator::IsExportedTargetsFile(
const std::string& filename) const
{
- const std::map<std::string, cmExportBuildFileGenerator*>::const_iterator it =
- this->BuildExportSets.find(filename);
+ auto const it = this->BuildExportSets.find(filename);
if (it == this->BuildExportSets.end()) {
return false;
}
- return this->BuildExportExportSets.find(filename) ==
- this->BuildExportExportSets.end();
+ return !cmContains(this->BuildExportExportSets, filename);
}
// Find the make program for the generator, required for try compiles
@@ -285,20 +413,19 @@ bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
return false;
}
if (!mf->GetDefinition("CMAKE_MAKE_PROGRAM") ||
- cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
- std::string setMakeProgram =
- mf->GetModulesFile(this->FindMakeProgramFile.c_str());
+ cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
+ std::string setMakeProgram = mf->GetModulesFile(this->FindMakeProgramFile);
if (!setMakeProgram.empty()) {
- mf->ReadListFile(setMakeProgram.c_str());
+ mf->ReadListFile(setMakeProgram);
}
}
if (!mf->GetDefinition("CMAKE_MAKE_PROGRAM") ||
- cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
+ cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
std::ostringstream err;
err << "CMake was unable to find a build program corresponding to \""
<< this->GetName() << "\". CMAKE_MAKE_PROGRAM is not set. You "
<< "probably need to select a different build tool.";
- cmSystemTools::Error(err.str().c_str());
+ cmSystemTools::Error(err.str());
cmSystemTools::SetFatalErrorOccured();
return false;
}
@@ -313,9 +440,7 @@ bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
std::string saveFile = file;
cmSystemTools::GetShortPath(makeProgram, makeProgram);
cmSystemTools::SplitProgramPath(makeProgram, dir, file);
- makeProgram = dir;
- makeProgram += "/";
- makeProgram += saveFile;
+ makeProgram = cmStrCat(dir, '/', saveFile);
mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram.c_str(),
"make program", cmStateEnums::FILEPATH);
}
@@ -383,13 +508,13 @@ void cmGlobalGenerator::EnableLanguage(
}
std::set<std::string> cur_languages(languages.begin(), languages.end());
- for (std::set<std::string>::iterator li = cur_languages.begin();
- li != cur_languages.end(); ++li) {
- if (!this->LanguagesInProgress.insert(*li).second) {
+ for (std::string const& li : cur_languages) {
+ if (!this->LanguagesInProgress.insert(li).second) {
std::ostringstream e;
- e << "Language '" << *li << "' is currently being enabled. "
- "Recursive call not allowed.";
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ e << "Language '" << li
+ << "' is currently being enabled. "
+ "Recursive call not allowed.";
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
cmSystemTools::SetFatalErrorOccured();
return;
}
@@ -397,17 +522,15 @@ void cmGlobalGenerator::EnableLanguage(
if (this->TryCompileOuterMakefile) {
// In a try-compile we can only enable languages provided by caller.
- for (std::vector<std::string>::const_iterator li = languages.begin();
- li != languages.end(); ++li) {
- if (*li == "NONE") {
+ for (std::string const& lang : languages) {
+ if (lang == "NONE") {
this->SetLanguageEnabled("NONE", mf);
} else {
- const char* lang = li->c_str();
- if (this->LanguagesReady.find(lang) == this->LanguagesReady.end()) {
+ if (!cmContains(this->LanguagesReady, lang)) {
std::ostringstream e;
e << "The test project needs language " << lang
<< " which is not enabled.";
- this->TryCompileOuterMakefile->IssueMessage(cmake::FATAL_ERROR,
+ this->TryCompileOuterMakefile->IssueMessage(MessageType::FATAL_ERROR,
e.str());
cmSystemTools::SetFatalErrorOccured();
return;
@@ -418,9 +541,9 @@ void cmGlobalGenerator::EnableLanguage(
bool fatalError = false;
- mf->AddDefinition("RUN_CONFIGURE", true);
- std::string rootBin = this->CMakeInstance->GetHomeOutputDirectory();
- rootBin += cmake::GetCMakeFilesDirectory();
+ mf->AddDefinitionBool("RUN_CONFIGURE", true);
+ std::string rootBin =
+ cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(), "/CMakeFiles");
// If the configuration files path has been set,
// then we are in a try compile and need to copy the enable language
@@ -428,11 +551,11 @@ void cmGlobalGenerator::EnableLanguage(
if (!this->ConfiguredFilesPath.empty()) {
rootBin = this->ConfiguredFilesPath;
}
- rootBin += "/";
+ rootBin += '/';
rootBin += cmVersion::GetCMakeVersion();
// set the dir for parent files so they can be used by modules
- mf->AddDefinition("CMAKE_PLATFORM_INFO_DIR", rootBin.c_str());
+ mf->AddDefinition("CMAKE_PLATFORM_INFO_DIR", rootBin);
if (!this->CMakeInstance->GetIsInTryCompile()) {
// Keep a mark in the cache to indicate that we've initialized the
@@ -451,22 +574,13 @@ void cmGlobalGenerator::EnableLanguage(
"Platform information initialized", cmStateEnums::INTERNAL);
}
- // find and make sure CMAKE_MAKE_PROGRAM is defined
- if (!this->FindMakeProgram(mf)) {
- return;
- }
-
- if (!this->CheckLanguages(languages, mf)) {
- return;
- }
-
// try and load the CMakeSystem.cmake if it is there
std::string fpath = rootBin;
bool const readCMakeSystem = !mf->GetDefinition("CMAKE_SYSTEM_LOADED");
if (readCMakeSystem) {
fpath += "/CMakeSystem.cmake";
- if (cmSystemTools::FileExists(fpath.c_str())) {
- mf->ReadListFile(fpath.c_str());
+ if (cmSystemTools::FileExists(fpath)) {
+ mf->ReadListFile(fpath);
}
}
// Load the CMakeDetermineSystem.cmake file and find out
@@ -478,33 +592,48 @@ void cmGlobalGenerator::EnableLanguage(
ZeroMemory(&osviex, sizeof(osviex));
osviex.dwOSVersionInfoSize = sizeof(osviex);
-#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(push)
-#pragma warning(disable : 4996)
-#endif
+# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# pragma warning(push)
+# ifdef __INTEL_COMPILER
+# pragma warning(disable : 1478)
+# elif defined __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated-declarations"
+# else
+# pragma warning(disable : 4996)
+# endif
+# endif
GetVersionExW((OSVERSIONINFOW*)&osviex);
-#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(pop)
-#endif
+# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# ifdef __clang__
+# pragma clang diagnostic pop
+# else
+# pragma warning(pop)
+# endif
+# endif
std::ostringstream windowsVersionString;
windowsVersionString << osviex.dwMajorVersion << "."
<< osviex.dwMinorVersion << "."
<< osviex.dwBuildNumber;
- windowsVersionString.str();
- mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION",
- windowsVersionString.str().c_str());
+ mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION", windowsVersionString.str());
#endif
// Read the DetermineSystem file
std::string systemFile = mf->GetModulesFile("CMakeDetermineSystem.cmake");
- mf->ReadListFile(systemFile.c_str());
+ mf->ReadListFile(systemFile);
// load the CMakeSystem.cmake from the binary directory
// this file is configured by the CMakeDetermineSystem.cmake file
- fpath = rootBin;
- fpath += "/CMakeSystem.cmake";
- mf->ReadListFile(fpath.c_str());
+ fpath = cmStrCat(rootBin, "/CMakeSystem.cmake");
+ mf->ReadListFile(fpath);
}
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;
+ }
+
// Tell the generator about the target system.
std::string system = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME");
if (!this->SetSystemName(system, mf)) {
@@ -525,12 +654,23 @@ void cmGlobalGenerator::EnableLanguage(
cmSystemTools::SetFatalErrorOccured();
return;
}
+
+ // Find the native build tool for this generator.
+ if (!this->FindMakeProgram(mf)) {
+ return;
+ }
+ }
+
+ // Check that the languages are supported by the generator and its
+ // native build tool found above.
+ if (!this->CheckLanguages(languages, mf)) {
+ return;
}
// **** Load the system specific initialization if not yet loaded
if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INITIALIZE_LOADED")) {
fpath = mf->GetModulesFile("CMakeSystemSpecificInitialize.cmake");
- if (!mf->ReadListFile(fpath.c_str())) {
+ if (!mf->ReadListFile(fpath)) {
cmSystemTools::Error("Could not find cmake module file: "
"CMakeSystemSpecificInitialize.cmake");
}
@@ -542,30 +682,22 @@ void cmGlobalGenerator::EnableLanguage(
// load the CMakeDetermine(LANG)Compiler.cmake file to find
// the compiler
- for (std::vector<std::string>::const_iterator l = languages.begin();
- l != languages.end(); ++l) {
- const char* lang = l->c_str();
+ for (std::string const& lang : languages) {
needSetLanguageEnabledMaps[lang] = false;
- if (*l == "NONE") {
+ if (lang == "NONE") {
this->SetLanguageEnabled("NONE", mf);
continue;
}
- std::string loadedLang = "CMAKE_";
- loadedLang += lang;
- loadedLang += "_COMPILER_LOADED";
+ std::string loadedLang = cmStrCat("CMAKE_", lang, "_COMPILER_LOADED");
if (!mf->GetDefinition(loadedLang)) {
- fpath = rootBin;
- fpath += "/CMake";
- fpath += lang;
- fpath += "Compiler.cmake";
+ fpath = cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake");
// 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 (!mf->ReadListFile(fpath.c_str())) {
- cmSystemTools::Error("Could not find cmake module file: ",
- fpath.c_str());
+ if (cmSystemTools::FileExists(fpath)) {
+ if (!mf->ReadListFile(fpath)) {
+ cmSystemTools::Error("Could not find cmake module file: " + fpath);
}
// if this file was found then the language was already determined
// to be working
@@ -585,14 +717,12 @@ void cmGlobalGenerator::EnableLanguage(
}
// if the CMake(LANG)Compiler.cmake file was not found then
// load CMakeDetermine(LANG)Compiler.cmake
- std::string determineCompiler = "CMakeDetermine";
- determineCompiler += lang;
- determineCompiler += "Compiler.cmake";
- std::string determineFile =
- mf->GetModulesFile(determineCompiler.c_str());
- if (!mf->ReadListFile(determineFile.c_str())) {
- cmSystemTools::Error("Could not find cmake module file: ",
- determineCompiler.c_str());
+ std::string determineCompiler =
+ cmStrCat("CMakeDetermine", lang, "Compiler.cmake");
+ std::string determineFile = mf->GetModulesFile(determineCompiler);
+ if (!mf->ReadListFile(determineFile)) {
+ cmSystemTools::Error("Could not find cmake module file: " +
+ determineCompiler);
}
if (cmSystemTools::GetFatalErrorOccured()) {
return;
@@ -604,29 +734,21 @@ void cmGlobalGenerator::EnableLanguage(
// put ${CMake_(LANG)_COMPILER_ENV_VAR}=${CMAKE_(LANG)_COMPILER
// into the environment, in case user scripts want to run
// configure, or sub cmakes
- std::string compilerName = "CMAKE_";
- compilerName += lang;
- compilerName += "_COMPILER";
- std::string compilerEnv = "CMAKE_";
- compilerEnv += lang;
- compilerEnv += "_COMPILER_ENV_VAR";
- std::string envVar = mf->GetRequiredDefinition(compilerEnv);
- std::string envVarValue = mf->GetRequiredDefinition(compilerName);
- std::string env = envVar;
- env += "=";
- env += envVarValue;
+ std::string compilerName = cmStrCat("CMAKE_", lang, "_COMPILER");
+ std::string compilerEnv =
+ cmStrCat("CMAKE_", lang, "_COMPILER_ENV_VAR");
+ const std::string& envVar = mf->GetRequiredDefinition(compilerEnv);
+ const std::string& envVarValue =
+ mf->GetRequiredDefinition(compilerName);
+ std::string env = cmStrCat(envVar, '=', envVarValue);
cmSystemTools::PutEnv(env);
}
// if determineLanguage was called then load the file it
// configures CMake(LANG)Compiler.cmake
- fpath = rootBin;
- fpath += "/CMake";
- fpath += lang;
- fpath += "Compiler.cmake";
- if (!mf->ReadListFile(fpath.c_str())) {
- cmSystemTools::Error("Could not find cmake module file: ",
- fpath.c_str());
+ fpath = cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake");
+ if (!mf->ReadListFile(fpath)) {
+ cmSystemTools::Error("Could not find cmake module file: " + fpath);
}
this->SetLanguageEnabledFlag(lang, mf);
needSetLanguageEnabledMaps[lang] = true;
@@ -641,38 +763,31 @@ void cmGlobalGenerator::EnableLanguage(
// **** Load the system specific information if not yet loaded
if (!mf->GetDefinition("CMAKE_SYSTEM_SPECIFIC_INFORMATION_LOADED")) {
fpath = mf->GetModulesFile("CMakeSystemSpecificInformation.cmake");
- if (!mf->ReadListFile(fpath.c_str())) {
+ if (!mf->ReadListFile(fpath)) {
cmSystemTools::Error("Could not find cmake module file: "
"CMakeSystemSpecificInformation.cmake");
}
}
// loop over languages again loading CMake(LANG)Information.cmake
//
- for (std::vector<std::string>::const_iterator l = languages.begin();
- l != languages.end(); ++l) {
- const char* lang = l->c_str();
- if (*l == "NONE") {
+ for (std::string const& lang : languages) {
+ if (lang == "NONE") {
this->SetLanguageEnabled("NONE", mf);
continue;
}
// Check that the compiler was found.
- std::string compilerName = "CMAKE_";
- compilerName += lang;
- compilerName += "_COMPILER";
- std::string compilerEnv = "CMAKE_";
- compilerEnv += lang;
- compilerEnv += "_COMPILER_ENV_VAR";
+ std::string compilerName = cmStrCat("CMAKE_", lang, "_COMPILER");
+ std::string compilerEnv = cmStrCat("CMAKE_", lang, "_COMPILER_ENV_VAR");
std::ostringstream noCompiler;
const char* compilerFile = mf->GetDefinition(compilerName);
- if (!compilerFile || !*compilerFile ||
- cmSystemTools::IsNOTFOUND(compilerFile)) {
+ if (!compilerFile || !*compilerFile || cmIsNOTFOUND(compilerFile)) {
/* clang-format off */
noCompiler <<
"No " << compilerName << " could be found.\n"
;
/* clang-format on */
- } else if (strcmp(lang, "RC") != 0 && strcmp(lang, "ASM_MASM") != 0) {
+ } else if ((lang != "RC") && (lang != "ASM_MASM")) {
if (!cmSystemTools::FileIsFullPath(compilerFile)) {
/* clang-format off */
noCompiler <<
@@ -697,34 +812,28 @@ void cmGlobalGenerator::EnableLanguage(
if (!optional) {
// The compiler was not found and it is not optional. Remove
// CMake(LANG)Compiler.cmake so we try again next time CMake runs.
- std::string compilerLangFile = rootBin;
- compilerLangFile += "/CMake";
- compilerLangFile += lang;
- compilerLangFile += "Compiler.cmake";
+ std::string compilerLangFile =
+ cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake");
cmSystemTools::RemoveFile(compilerLangFile);
if (!this->CMakeInstance->GetIsInTryCompile()) {
this->PrintCompilerAdvice(noCompiler, lang,
mf->GetDefinition(compilerEnv));
- mf->IssueMessage(cmake::FATAL_ERROR, noCompiler.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, noCompiler.str());
fatalError = true;
}
}
}
- std::string langLoadedVar = "CMAKE_";
- langLoadedVar += lang;
- langLoadedVar += "_INFORMATION_LOADED";
+ std::string langLoadedVar =
+ cmStrCat("CMAKE_", lang, "_INFORMATION_LOADED");
if (!mf->GetDefinition(langLoadedVar)) {
- fpath = "CMake";
- fpath += lang;
- fpath += "Information.cmake";
- std::string informationFile = mf->GetModulesFile(fpath.c_str());
+ fpath = cmStrCat("CMake", lang, "Information.cmake");
+ std::string informationFile = mf->GetModulesFile(fpath);
if (informationFile.empty()) {
- cmSystemTools::Error("Could not find cmake module file: ",
- fpath.c_str());
- } else if (!mf->ReadListFile(informationFile.c_str())) {
- cmSystemTools::Error("Could not process cmake module file: ",
- informationFile.c_str());
+ cmSystemTools::Error("Could not find cmake module file: " + fpath);
+ } else if (!mf->ReadListFile(informationFile)) {
+ cmSystemTools::Error("Could not process cmake module file: " +
+ informationFile);
}
}
if (needSetLanguageEnabledMaps[lang]) {
@@ -739,37 +848,29 @@ void cmGlobalGenerator::EnableLanguage(
// If the language is untested then test it now with a try compile.
if (needTestLanguage[lang]) {
if (!this->CMakeInstance->GetIsInTryCompile()) {
- std::string testLang = "CMakeTest";
- testLang += lang;
- testLang += "Compiler.cmake";
- std::string ifpath = mf->GetModulesFile(testLang.c_str());
- if (!mf->ReadListFile(ifpath.c_str())) {
- cmSystemTools::Error("Could not find cmake module file: ",
- testLang.c_str());
+ std::string testLang = cmStrCat("CMakeTest", lang, "Compiler.cmake");
+ std::string ifpath = mf->GetModulesFile(testLang);
+ if (!mf->ReadListFile(ifpath)) {
+ cmSystemTools::Error("Could not find cmake module file: " +
+ testLang);
}
- std::string compilerWorks = "CMAKE_";
- compilerWorks += lang;
- compilerWorks += "_COMPILER_WORKS";
+ std::string compilerWorks =
+ cmStrCat("CMAKE_", lang, "_COMPILER_WORKS");
// if the compiler did not work, then remove the
// CMake(LANG)Compiler.cmake file so that it will get tested the
// next time cmake is run
if (!mf->IsOn(compilerWorks)) {
- std::string compilerLangFile = rootBin;
- compilerLangFile += "/CMake";
- compilerLangFile += lang;
- compilerLangFile += "Compiler.cmake";
+ std::string compilerLangFile =
+ cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake");
cmSystemTools::RemoveFile(compilerLangFile);
}
} // end if in try compile
} // end need test language
// Store the shared library flags so that we can satisfy CMP0018
- std::string sharedLibFlagsVar = "CMAKE_SHARED_LIBRARY_";
- sharedLibFlagsVar += lang;
- sharedLibFlagsVar += "_FLAGS";
- const char* sharedLibFlags = mf->GetSafeDefinition(sharedLibFlagsVar);
- if (sharedLibFlags) {
- this->LanguageToOriginalSharedLibFlags[lang] = sharedLibFlags;
- }
+ std::string sharedLibFlagsVar =
+ cmStrCat("CMAKE_SHARED_LIBRARY_", lang, "_FLAGS");
+ this->LanguageToOriginalSharedLibFlags[lang] =
+ mf->GetSafeDefinition(sharedLibFlagsVar);
// Translate compiler ids for compatibility.
this->CheckCompilerIdCompatibility(mf, lang);
@@ -778,12 +879,11 @@ void cmGlobalGenerator::EnableLanguage(
// Now load files that can override any settings on the platform or for
// the project First load the project compatibility file if it is in
// cmake
- std::string projectCompatibility = cmSystemTools::GetCMakeRoot();
- projectCompatibility += "/Modules/";
- projectCompatibility += mf->GetSafeDefinition("PROJECT_NAME");
- projectCompatibility += "Compatibility.cmake";
- if (cmSystemTools::FileExists(projectCompatibility.c_str())) {
- mf->ReadListFile(projectCompatibility.c_str());
+ std::string projectCompatibility =
+ cmStrCat(cmSystemTools::GetCMakeRoot(), "/Modules/",
+ mf->GetSafeDefinition("PROJECT_NAME"), "Compatibility.cmake");
+ if (cmSystemTools::FileExists(projectCompatibility)) {
+ mf->ReadListFile(projectCompatibility);
}
// Inform any extra generator of the new language.
if (this->ExtraGenerator) {
@@ -794,9 +894,8 @@ void cmGlobalGenerator::EnableLanguage(
cmSystemTools::SetFatalErrorOccured();
}
- for (std::set<std::string>::iterator li = cur_languages.begin();
- li != cur_languages.end(); ++li) {
- this->LanguagesInProgress.erase(*li);
+ for (std::string const& lang : cur_languages) {
+ this->LanguagesInProgress.erase(lang);
}
}
@@ -819,12 +918,9 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
cmMakefile* mf, std::string const& lang) const
{
std::string compilerIdVar = "CMAKE_" + lang + "_COMPILER_ID";
- const char* compilerId = mf->GetDefinition(compilerIdVar);
- if (!compilerId) {
- return;
- }
+ std::string const compilerId = mf->GetSafeDefinition(compilerIdVar);
- if (strcmp(compilerId, "AppleClang") == 0) {
+ if (compilerId == "AppleClang") {
switch (mf->GetPolicyStatus(cmPolicies::CMP0025)) {
case cmPolicies::WARN:
if (!this->CMakeInstance->GetIsInTryCompile() &&
@@ -833,10 +929,10 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
/* clang-format off */
w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0025) << "\n"
"Converting " << lang <<
- " compiler id \"AppleClang\" to \"Clang\" for compatibility."
+ R"( compiler id "AppleClang" to "Clang" for compatibility.)"
;
/* clang-format on */
- mf->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ mf->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
}
CM_FALLTHROUGH;
case cmPolicies::OLD:
@@ -846,7 +942,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
mf->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0025));
case cmPolicies::NEW:
// NEW behavior is to keep AppleClang.
@@ -854,7 +950,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
}
}
- if (strcmp(compilerId, "QCC") == 0) {
+ if (compilerId == "QCC") {
switch (mf->GetPolicyStatus(cmPolicies::CMP0047)) {
case cmPolicies::WARN:
if (!this->CMakeInstance->GetIsInTryCompile() &&
@@ -863,10 +959,10 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
/* clang-format off */
w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0047) << "\n"
"Converting " << lang <<
- " compiler id \"QCC\" to \"GNU\" for compatibility."
+ R"( compiler id "QCC" to "GNU" for compatibility.)"
;
/* clang-format on */
- mf->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ mf->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
}
CM_FALLTHROUGH;
case cmPolicies::OLD:
@@ -881,7 +977,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
mf->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0047));
CM_FALLTHROUGH;
case cmPolicies::NEW:
@@ -889,6 +985,36 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
break;
}
}
+
+ if (compilerId == "XLClang") {
+ switch (mf->GetPolicyStatus(cmPolicies::CMP0089)) {
+ case cmPolicies::WARN:
+ if (!this->CMakeInstance->GetIsInTryCompile() &&
+ mf->PolicyOptionalWarningEnabled("CMAKE_POLICY_WARNING_CMP0089")) {
+ std::ostringstream w;
+ /* clang-format off */
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0089) << "\n"
+ "Converting " << lang <<
+ R"( compiler id "XLClang" to "XL" for compatibility.)"
+ ;
+ /* clang-format on */
+ mf->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
+ }
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // OLD behavior is to convert XLClang to XL.
+ mf->AddDefinition(compilerIdVar, "XL");
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ mf->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0089));
+ case cmPolicies::NEW:
+ // NEW behavior is to keep AppleClang.
+ break;
+ }
+ }
}
std::string cmGlobalGenerator::GetLanguageOutputExtension(
@@ -896,15 +1022,13 @@ std::string cmGlobalGenerator::GetLanguageOutputExtension(
{
const std::string& lang = source.GetLanguage();
if (!lang.empty()) {
- std::map<std::string, std::string>::const_iterator it =
- this->LanguageToOutputExtension.find(lang);
-
+ auto const it = this->LanguageToOutputExtension.find(lang);
if (it != this->LanguageToOutputExtension.end()) {
return it->second;
}
} 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()) {
@@ -923,8 +1047,7 @@ std::string cmGlobalGenerator::GetLanguageFromExtension(const char* ext) const
if (ext && *ext == '.') {
++ext;
}
- std::map<std::string, std::string>::const_iterator it =
- this->ExtensionToLanguage.find(ext);
+ auto const it = this->ExtensionToLanguage.find(ext);
if (it != this->ExtensionToLanguage.end()) {
return it->second;
}
@@ -968,8 +1091,7 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l,
{
// use LanguageToLinkerPreference to detect whether this functions has
// run before
- if (this->LanguageToLinkerPreference.find(l) !=
- this->LanguageToLinkerPreference.end()) {
+ if (cmContains(this->LanguageToLinkerPreference, l)) {
return;
}
@@ -992,9 +1114,9 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l,
}
if (preference < 0) {
- std::string msg = linkerPrefVar;
- msg += " is negative, adjusting it to 0";
- cmSystemTools::Message(msg.c_str(), "Warning");
+ std::string msg =
+ cmStrCat(linkerPrefVar, " is negative, adjusting it to 0");
+ cmSystemTools::Message(msg, "Warning");
preference = 0;
}
@@ -1019,11 +1141,9 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l,
std::string ignoreExtensionsVar =
std::string("CMAKE_") + std::string(l) + std::string("_IGNORE_EXTENSIONS");
std::string ignoreExts = mf->GetSafeDefinition(ignoreExtensionsVar);
- std::vector<std::string> extensionList;
- cmSystemTools::ExpandListArgument(ignoreExts, extensionList);
- for (std::vector<std::string>::iterator i = extensionList.begin();
- i != extensionList.end(); ++i) {
- this->IgnoreExtensions[*i] = true;
+ std::vector<std::string> extensionList = cmExpandedList(ignoreExts);
+ for (std::string const& i : extensionList) {
+ this->IgnoreExtensions[i] = true;
}
}
@@ -1032,12 +1152,10 @@ void cmGlobalGenerator::FillExtensionToLanguageMap(const std::string& l,
{
std::string extensionsVar = std::string("CMAKE_") + std::string(l) +
std::string("_SOURCE_FILE_EXTENSIONS");
- std::string exts = mf->GetSafeDefinition(extensionsVar);
- std::vector<std::string> extensionList;
- cmSystemTools::ExpandListArgument(exts, extensionList);
- for (std::vector<std::string>::iterator i = extensionList.begin();
- i != extensionList.end(); ++i) {
- this->ExtensionToLanguage[*i] = l;
+ const std::string& exts = mf->GetSafeDefinition(extensionsVar);
+ std::vector<std::string> extensionList = cmExpandedList(exts);
+ for (std::string const& i : extensionList) {
+ this->ExtensionToLanguage[i] = l;
}
}
@@ -1053,7 +1171,7 @@ bool cmGlobalGenerator::GlobalSettingIsOn(std::string const& name) const
return this->Makefiles[0]->IsOn(name);
}
-const char* cmGlobalGenerator::GetSafeGlobalSetting(
+std::string cmGlobalGenerator::GetSafeGlobalSetting(
std::string const& name) const
{
assert(!this->Makefiles.empty());
@@ -1075,17 +1193,19 @@ bool cmGlobalGenerator::GetLanguageEnabled(const std::string& l) const
void cmGlobalGenerator::ClearEnabledLanguages()
{
- return this->CMakeInstance->GetState()->ClearEnabledLanguages();
+ this->CMakeInstance->GetState()->ClearEnabledLanguages();
}
void cmGlobalGenerator::CreateLocalGenerators()
{
+ this->LocalGeneratorSearchIndex.clear();
cmDeleteAll(this->LocalGenerators);
this->LocalGenerators.clear();
this->LocalGenerators.reserve(this->Makefiles.size());
- for (std::vector<cmMakefile*>::const_iterator it = this->Makefiles.begin();
- it != this->Makefiles.end(); ++it) {
- this->LocalGenerators.push_back(this->CreateLocalGenerator(*it));
+ for (cmMakefile* m : this->Makefiles) {
+ cmLocalGenerator* lg = this->CreateLocalGenerator(m);
+ this->LocalGenerators.push_back(lg);
+ this->IndexLocalGenerator(lg);
}
}
@@ -1102,6 +1222,7 @@ void cmGlobalGenerator::Configure()
this->CMakeInstance->GetHomeOutputDirectory());
cmMakefile* dirMf = new cmMakefile(this, snapshot);
+ dirMf->SetRecursionDepth(this->RecursionDepth);
this->Makefiles.push_back(dirMf);
this->IndexMakefile(dirMf);
@@ -1116,16 +1237,16 @@ void cmGlobalGenerator::Configure()
this->ConfigureDoneCMP0026AndCMP0024 = true;
// Put a copy of each global target in every directory.
- std::vector<GlobalTargetInfo> globalTargets;
- this->CreateDefaultGlobalTargets(globalTargets);
-
- for (unsigned int i = 0; i < this->Makefiles.size(); ++i) {
- cmMakefile* mf = this->Makefiles[i];
- cmTargets* targets = &(mf->GetTargets());
- for (std::vector<GlobalTargetInfo>::iterator gti = globalTargets.begin();
- gti != globalTargets.end(); ++gti) {
- targets->insert(
- cmTargets::value_type(gti->Name, this->CreateGlobalTarget(*gti, mf)));
+ {
+ std::vector<GlobalTargetInfo> globalTargets;
+ this->CreateDefaultGlobalTargets(globalTargets);
+
+ for (cmMakefile* mf : this->Makefiles) {
+ auto& targets = mf->GetTargets();
+ for (GlobalTargetInfo const& globalTarget : globalTargets) {
+ targets.emplace(globalTarget.Name,
+ this->CreateGlobalTarget(globalTarget, mf));
+ }
}
}
@@ -1145,20 +1266,18 @@ void cmGlobalGenerator::Configure()
std::ostringstream msg;
if (cmSystemTools::GetErrorOccuredFlag()) {
msg << "Configuring incomplete, errors occurred!";
- const char* logs[] = { "CMakeOutput.log", "CMakeError.log", CM_NULLPTR };
+ const char* logs[] = { "CMakeOutput.log", "CMakeError.log", nullptr };
for (const char** log = logs; *log; ++log) {
- std::string f = this->CMakeInstance->GetHomeOutputDirectory();
- f += this->CMakeInstance->GetCMakeFilesDirectory();
- f += "/";
- f += *log;
- if (cmSystemTools::FileExists(f.c_str())) {
+ std::string f = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(),
+ "/CMakeFiles/", *log);
+ if (cmSystemTools::FileExists(f)) {
msg << "\nSee also \"" << f << "\".";
}
}
} else {
msg << "Configuring done";
}
- this->CMakeInstance->UpdateProgress(msg.str().c_str(), -1);
+ this->CMakeInstance->UpdateProgress(msg.str(), -1);
}
}
@@ -1174,13 +1293,12 @@ void cmGlobalGenerator::CreateImportedGenerationObjects(
std::vector<const cmGeneratorTarget*>& exports)
{
this->CreateGenerationObjects(ImportedOnly);
- std::vector<cmMakefile*>::iterator mfit =
+ auto const mfit =
std::find(this->Makefiles.begin(), this->Makefiles.end(), mf);
cmLocalGenerator* lg =
this->LocalGenerators[std::distance(this->Makefiles.begin(), mfit)];
- for (std::vector<std::string>::const_iterator it = targets.begin();
- it != targets.end(); ++it) {
- cmGeneratorTarget* gt = lg->FindGeneratorTargetToUse(*it);
+ for (std::string const& t : targets) {
+ cmGeneratorTarget* gt = lg->FindGeneratorTargetToUse(t);
if (gt) {
exports.push_back(gt);
}
@@ -1190,9 +1308,8 @@ void cmGlobalGenerator::CreateImportedGenerationObjects(
cmExportBuildFileGenerator* cmGlobalGenerator::GetExportedTargetsFile(
const std::string& filename) const
{
- std::map<std::string, cmExportBuildFileGenerator*>::const_iterator it =
- this->BuildExportSets.find(filename);
- return it == this->BuildExportSets.end() ? CM_NULLPTR : it->second;
+ auto const it = this->BuildExportSets.find(filename);
+ return it == this->BuildExportSets.end() ? nullptr : it->second;
}
void cmGlobalGenerator::AddCMP0042WarnTarget(const std::string& target)
@@ -1221,7 +1338,7 @@ bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const
<< "duplicate custom targets. "
<< "Consider using a Makefiles generator or fix the project to not "
<< "use duplicate target names.";
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
return false;
}
@@ -1230,10 +1347,8 @@ void cmGlobalGenerator::ComputeBuildFileGenerators()
for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
std::vector<cmExportBuildFileGenerator*> gens =
this->Makefiles[i]->GetExportBuildFileGenerators();
- for (std::vector<cmExportBuildFileGenerator*>::const_iterator it =
- gens.begin();
- it != gens.end(); ++it) {
- (*it)->Compute(this->LocalGenerators[i]);
+ for (cmExportBuildFileGenerator* g : gens) {
+ g->Compute(this->LocalGenerators[i]);
}
}
}
@@ -1261,18 +1376,19 @@ bool cmGlobalGenerator::Compute()
// so create the map from project name to vector of local generators
this->FillProjectMap();
-#ifdef CMAKE_BUILD_WITH_CMAKE
- // Iterate through all targets and set up automoc for those which have
- // the AUTOMOC, AUTOUIC or AUTORCC property set
- std::vector<cmGeneratorTarget const*> autogenTargets =
- this->CreateQtAutoGeneratorsTargets();
-#endif
+ // Iterate through all targets and set up AUTOMOC, AUTOUIC and AUTORCC
+ if (!this->QtAutoGen()) {
+ return false;
+ }
- unsigned int i;
+ // Add automatically generated sources (e.g. unity build).
+ if (!this->AddAutomaticSources()) {
+ return false;
+ }
// Add generator specific helper commands
- for (i = 0; i < this->LocalGenerators.size(); ++i) {
- this->LocalGenerators[i]->AddHelperCommands();
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ localGen->AddHelperCommands();
}
// Finalize the set of compile features for each target.
@@ -1281,26 +1397,18 @@ bool cmGlobalGenerator::Compute()
// on the original cmTarget instance. It accumulates features
// across all configurations. Some refactoring is needed to
// compute a per-config resulta purely during generation.
- for (i = 0; i < this->LocalGenerators.size(); ++i) {
- if (!this->LocalGenerators[i]->ComputeTargetCompileFeatures()) {
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ if (!localGen->ComputeTargetCompileFeatures()) {
return false;
}
}
-#ifdef CMAKE_BUILD_WITH_CMAKE
- for (std::vector<cmGeneratorTarget const*>::iterator it =
- autogenTargets.begin();
- it != autogenTargets.end(); ++it) {
- cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(*it);
- }
-#endif
-
- for (i = 0; i < this->LocalGenerators.size(); ++i) {
- cmMakefile* mf = this->LocalGenerators[i]->GetMakefile();
- std::vector<cmInstallGenerator*>& gens = mf->GetInstallGenerators();
- for (std::vector<cmInstallGenerator*>::const_iterator git = gens.begin();
- git != gens.end(); ++git) {
- (*git)->Compute(this->LocalGenerators[i]);
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ cmMakefile* mf = localGen->GetMakefile();
+ for (cmInstallGenerator* g : mf->GetInstallGenerators()) {
+ if (!g->Compute(localGen)) {
+ return false;
+ }
}
}
@@ -1308,15 +1416,20 @@ bool cmGlobalGenerator::Compute()
// Trace the dependencies, after that no custom commands should be added
// because their dependencies might not be handled correctly
- for (i = 0; i < this->LocalGenerators.size(); ++i) {
- this->LocalGenerators[i]->TraceDependencies();
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ 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.
- for (i = 0; i < this->LocalGenerators.size(); ++i) {
- this->LocalGenerators[i]->ComputeTargetManifest();
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ localGen->ComputeTargetManifest();
}
// Compute the inter-target dependencies.
@@ -1324,8 +1437,16 @@ bool cmGlobalGenerator::Compute()
return false;
}
- for (i = 0; i < this->LocalGenerators.size(); ++i) {
- this->LocalGenerators[i]->ComputeHomeRelativeOutputPath();
+ if (this->CheckTargetsForType()) {
+ return false;
+ }
+
+ if (this->CheckTargetsForPchCompilePdb()) {
+ return false;
+ }
+
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ localGen->ComputeHomeRelativeOutputPath();
}
return true;
@@ -1349,22 +1470,21 @@ void cmGlobalGenerator::Generate()
}
this->LocalGenerators[i]->GenerateTestFiles();
this->CMakeInstance->UpdateProgress(
- "Generating", (static_cast<float>(i) + 1.0f) /
+ "Generating",
+ (static_cast<float>(i) + 1.0f) /
static_cast<float>(this->LocalGenerators.size()));
}
- this->SetCurrentMakefile(CM_NULLPTR);
+ this->SetCurrentMakefile(nullptr);
if (!this->GenerateCPackPropertiesFile()) {
this->GetCMakeInstance()->IssueMessage(
- cmake::FATAL_ERROR, "Could not write CPack properties file.");
+ MessageType::FATAL_ERROR, "Could not write CPack properties file.");
}
- for (std::map<std::string, cmExportBuildFileGenerator*>::iterator it =
- this->BuildExportSets.begin();
- it != this->BuildExportSets.end(); ++it) {
- if (!it->second->GenerateImportFile()) {
+ for (auto& buildExpSet : this->BuildExportSets) {
+ if (!buildExpSet.second->GenerateImportFile()) {
if (!cmSystemTools::GetErrorOccuredFlag()) {
- this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR,
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
"Could not write export file.");
}
return;
@@ -1375,7 +1495,7 @@ void cmGlobalGenerator::Generate()
this->WriteSummary();
- if (this->ExtraGenerator != CM_NULLPTR) {
+ if (this->ExtraGenerator) {
this->ExtraGenerator->Generate();
}
@@ -1384,12 +1504,11 @@ void cmGlobalGenerator::Generate()
w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0042) << "\n";
w << "MACOSX_RPATH is not specified for"
" the following targets:\n";
- for (std::set<std::string>::iterator iter =
- this->CMP0042WarnTargets.begin();
- iter != this->CMP0042WarnTargets.end(); ++iter) {
- w << " " << *iter << "\n";
+ for (std::string const& t : this->CMP0042WarnTargets) {
+ w << " " << t << "\n";
}
- this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING,
+ w.str());
}
if (!this->CMP0068WarnTargets.empty()) {
@@ -1402,12 +1521,11 @@ void cmGlobalGenerator::Generate()
"settings:\n"
;
/* clang-format on */
- for (std::set<std::string>::iterator iter =
- this->CMP0068WarnTargets.begin();
- iter != this->CMP0068WarnTargets.end(); ++iter) {
- w << " " << *iter << "\n";
+ for (std::string const& t : this->CMP0068WarnTargets) {
+ w << " " << t << "\n";
}
- this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING,
+ w.str());
}
this->CMakeInstance->UpdateProgress("Generating done", -1);
@@ -1419,69 +1537,46 @@ bool cmGlobalGenerator::ComputeTargetDepends()
if (!ctd.Compute()) {
return false;
}
- std::vector<cmGeneratorTarget const*> const& targets = ctd.GetTargets();
- for (std::vector<cmGeneratorTarget const*>::const_iterator ti =
- targets.begin();
- ti != targets.end(); ++ti) {
- ctd.GetTargetDirectDepends(*ti, this->TargetDependencies[*ti]);
+ for (cmGeneratorTarget const* target : ctd.GetTargets()) {
+ ctd.GetTargetDirectDepends(target, this->TargetDependencies[target]);
}
return true;
}
-std::vector<const cmGeneratorTarget*>
-cmGlobalGenerator::CreateQtAutoGeneratorsTargets()
+bool cmGlobalGenerator::QtAutoGen()
{
- std::vector<const cmGeneratorTarget*> autogenTargets;
+#ifndef CMAKE_BOOTSTRAP
+ cmQtAutoGenGlobalInitializer initializer(this->LocalGenerators);
+ return initializer.generate();
+#else
+ return true;
+#endif
+}
-#ifdef CMAKE_BUILD_WITH_CMAKE
- for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
- std::vector<cmGeneratorTarget*> targets =
- this->LocalGenerators[i]->GetGeneratorTargets();
- std::vector<cmGeneratorTarget*> filteredTargets;
- filteredTargets.reserve(targets.size());
- for (std::vector<cmGeneratorTarget*>::iterator ti = targets.begin();
- ti != targets.end(); ++ti) {
- if ((*ti)->GetType() == cmStateEnums::GLOBAL_TARGET) {
- continue;
- }
- if ((*ti)->GetType() != cmStateEnums::EXECUTABLE &&
- (*ti)->GetType() != cmStateEnums::STATIC_LIBRARY &&
- (*ti)->GetType() != cmStateEnums::SHARED_LIBRARY &&
- (*ti)->GetType() != cmStateEnums::MODULE_LIBRARY &&
- (*ti)->GetType() != cmStateEnums::OBJECT_LIBRARY) {
- continue;
- }
- if ((!(*ti)->GetPropertyAsBool("AUTOMOC") &&
- !(*ti)->GetPropertyAsBool("AUTOUIC") &&
- !(*ti)->GetPropertyAsBool("AUTORCC")) ||
- (*ti)->IsImported()) {
- continue;
- }
- // don't do anything if there is no Qt4 or Qt5Core (which contains moc):
- cmMakefile* mf = (*ti)->Target->GetMakefile();
- std::string qtMajorVersion = mf->GetSafeDefinition("QT_VERSION_MAJOR");
- if (qtMajorVersion == "") {
- qtMajorVersion = mf->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
- }
- if (qtMajorVersion != "4" && qtMajorVersion != "5") {
+bool cmGlobalGenerator::AddAutomaticSources()
+{
+ for (cmLocalGenerator* lg : this->LocalGenerators) {
+ lg->CreateEvaluationFileOutputs();
+ for (cmGeneratorTarget* gt : lg->GetGeneratorTargets()) {
+ if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ gt->GetType() == cmStateEnums::UTILITY ||
+ gt->GetType() == cmStateEnums::GLOBAL_TARGET) {
continue;
}
-
- cmGeneratorTarget* gt = *ti;
-
- cmQtAutoGeneratorInitializer::InitializeAutogenSources(gt);
- filteredTargets.push_back(gt);
+ lg->AddUnityBuild(gt);
+ lg->AddPchDependencies(gt);
}
- for (std::vector<cmGeneratorTarget*>::iterator ti =
- filteredTargets.begin();
- ti != filteredTargets.end(); ++ti) {
- cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
- this->LocalGenerators[i], *ti);
- autogenTargets.push_back(*ti);
+ }
+ // The above transformations may have changed the classification of sources.
+ // Clear the source list and classification cache (KindedSources) of all
+ // targets so that it will be recomputed correctly by the generators later
+ // now that the above transformations are done for all targets.
+ for (cmLocalGenerator* lg : this->LocalGenerators) {
+ for (cmGeneratorTarget* gt : lg->GetGeneratorTargets()) {
+ gt->ClearSourcesCache();
}
}
-#endif
- return autogenTargets;
+ return true;
}
cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer(
@@ -1502,17 +1597,14 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo()
this->CMakeInstance->GetState()->GetEnabledLanguages();
// Construct per-target generator information.
- for (unsigned int i = 0; i < this->Makefiles.size(); ++i) {
- cmMakefile* mf = this->Makefiles[i];
-
+ for (cmMakefile* mf : this->Makefiles) {
const cmStringRange noconfig_compile_definitions =
mf->GetCompileDefinitionsEntries();
const cmBacktraceRange noconfig_compile_definitions_bts =
mf->GetCompileDefinitionsBacktraces();
- cmTargets& targets = mf->GetTargets();
- for (cmTargets::iterator ti = targets.begin(); ti != targets.end(); ++ti) {
- cmTarget* t = &ti->second;
+ for (auto& target : mf->GetTargets()) {
+ cmTarget* t = &target.second;
if (t->GetType() == cmStateEnums::GLOBAL_TARGET) {
continue;
}
@@ -1523,12 +1615,12 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo()
continue;
}
- cmBacktraceRange::const_iterator btIt =
- noconfig_compile_definitions_bts.begin();
- for (cmStringRange::const_iterator
- it = noconfig_compile_definitions.begin();
- it != noconfig_compile_definitions.end(); ++it, ++btIt) {
- t->InsertCompileDefinition(*it, *btIt);
+ {
+ auto btIt = noconfig_compile_definitions_bts.begin();
+ auto it = noconfig_compile_definitions.begin();
+ for (; it != noconfig_compile_definitions.end(); ++it, ++btIt) {
+ t->InsertCompileDefinition(*it, *btIt);
+ }
}
cmPolicies::PolicyStatus polSt =
@@ -1537,10 +1629,9 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo()
std::vector<std::string> configs;
mf->GetConfigurations(configs);
- for (std::vector<std::string>::const_iterator ci = configs.begin();
- ci != configs.end(); ++ci) {
- std::string defPropName = "COMPILE_DEFINITIONS_";
- defPropName += cmSystemTools::UpperCase(*ci);
+ for (std::string const& c : configs) {
+ std::string defPropName =
+ cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(c));
t->AppendProperty(defPropName, mf->GetProperty(defPropName));
}
}
@@ -1549,15 +1640,13 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo()
// The standard include directories for each language
// should be treated as system include directories.
std::set<std::string> standardIncludesSet;
- for (std::vector<std::string>::const_iterator li = langs.begin();
- li != langs.end(); ++li) {
+ for (std::string const& li : langs) {
std::string const standardIncludesVar =
- "CMAKE_" + *li + "_STANDARD_INCLUDE_DIRECTORIES";
- std::string const standardIncludesStr =
+ "CMAKE_" + li + "_STANDARD_INCLUDE_DIRECTORIES";
+ std::string const& standardIncludesStr =
mf->GetSafeDefinition(standardIncludesVar);
- std::vector<std::string> standardIncludesVec;
- cmSystemTools::ExpandListArgument(standardIncludesStr,
- standardIncludesVec);
+ std::vector<std::string> standardIncludesVec =
+ cmExpandedList(standardIncludesStr);
standardIncludesSet.insert(standardIncludesVec.begin(),
standardIncludesVec.end());
}
@@ -1570,19 +1659,15 @@ void cmGlobalGenerator::CreateGeneratorTargets(
std::map<cmTarget*, cmGeneratorTarget*> const& importedMap)
{
if (targetTypes == AllTargets) {
- cmTargets& targets = mf->GetTargets();
- for (cmTargets::iterator ti = targets.begin(); ti != targets.end(); ++ti) {
- cmTarget* t = &ti->second;
+ for (auto& target : mf->GetTargets()) {
+ cmTarget* t = &target.second;
cmGeneratorTarget* gt = new cmGeneratorTarget(t, lg);
lg->AddGeneratorTarget(gt);
}
}
- std::vector<cmTarget*> itgts = mf->GetImportedTargets();
-
- for (std::vector<cmTarget*>::const_iterator j = itgts.begin();
- j != itgts.end(); ++j) {
- lg->AddImportedGeneratorTarget(importedMap.find(*j)->second);
+ for (cmTarget* t : mf->GetImportedTargets()) {
+ lg->AddImportedGeneratorTarget(importedMap.find(t)->second);
}
}
@@ -1591,13 +1676,11 @@ void cmGlobalGenerator::CreateGeneratorTargets(TargetTypes targetTypes)
std::map<cmTarget*, cmGeneratorTarget*> importedMap;
for (unsigned int i = 0; i < this->Makefiles.size(); ++i) {
cmMakefile* mf = this->Makefiles[i];
- for (std::vector<cmTarget*>::const_iterator j =
- mf->GetOwnedImportedTargets().begin();
- j != mf->GetOwnedImportedTargets().end(); ++j) {
+ for (cmTarget* ownedImpTgt : mf->GetOwnedImportedTargets()) {
cmLocalGenerator* lg = this->LocalGenerators[i];
- cmGeneratorTarget* gt = new cmGeneratorTarget(*j, lg);
+ cmGeneratorTarget* gt = new cmGeneratorTarget(ownedImpTgt, lg);
lg->AddOwnedImportedGeneratorTarget(gt);
- importedMap[*j] = gt;
+ importedMap[ownedImpTgt] = gt;
}
}
@@ -1619,11 +1702,13 @@ void cmGlobalGenerator::ClearGeneratorMembers()
cmDeleteAll(this->LocalGenerators);
this->LocalGenerators.clear();
+ this->AliasTargets.clear();
this->ExportSets.clear();
this->TargetDependencies.clear();
this->TargetSearchIndex.clear();
this->GeneratorTargetSearchIndex.clear();
this->MakefileSearchIndex.clear();
+ this->LocalGeneratorSearchIndex.clear();
this->ProjectMap.clear();
this->RuleHashes.clear();
this->DirectoryContentMap.clear();
@@ -1643,31 +1728,26 @@ void cmGlobalGenerator::CheckTargetProperties()
cmState* state = this->GetCMakeInstance()->GetState();
for (unsigned int i = 0; i < this->Makefiles.size(); ++i) {
this->Makefiles[i]->ConfigureFinalPass();
- cmTargets& targets = this->Makefiles[i]->GetTargets();
- for (cmTargets::iterator l = targets.begin(); l != targets.end(); l++) {
- if (l->second.GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ for (auto const& target : this->Makefiles[i]->GetTargets()) {
+ if (target.second.GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
- const cmTarget::LinkLibraryVectorType& libs =
- l->second.GetOriginalLinkLibraries();
- for (cmTarget::LinkLibraryVectorType::const_iterator lib = libs.begin();
- lib != libs.end(); ++lib) {
- if (lib->first.size() > 9 &&
- cmSystemTools::IsNOTFOUND(lib->first.c_str())) {
- std::string varName = lib->first.substr(0, lib->first.size() - 9);
+ for (auto const& lib : target.second.GetOriginalLinkLibraries()) {
+ if (lib.first.size() > 9 && cmIsNOTFOUND(lib.first)) {
+ std::string varName = lib.first.substr(0, lib.first.size() - 9);
if (state->GetCacheEntryPropertyAsBool(varName, "ADVANCED")) {
varName += " (ADVANCED)";
}
- std::string text = notFoundMap[varName];
- text += "\n linked by target \"";
- text += l->second.GetName();
- text += "\" in directory ";
- text += this->Makefiles[i]->GetCurrentSourceDirectory();
+ std::string text =
+ cmStrCat(notFoundMap[varName], "\n linked by target \"",
+ target.second.GetName(), "\" in directory ",
+ this->Makefiles[i]->GetCurrentSourceDirectory());
notFoundMap[varName] = text;
}
}
std::vector<std::string> incs;
- const char* incDirProp = l->second.GetProperty("INCLUDE_DIRECTORIES");
+ const char* incDirProp =
+ target.second.GetProperty("INCLUDE_DIRECTORIES");
if (!incDirProp) {
continue;
}
@@ -1675,46 +1755,45 @@ void cmGlobalGenerator::CheckTargetProperties()
std::string incDirs = cmGeneratorExpression::Preprocess(
incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions);
- cmSystemTools::ExpandListArgument(incDirs, incs);
+ cmExpandList(incDirs, incs);
- for (std::vector<std::string>::const_iterator incDir = incs.begin();
- incDir != incs.end(); ++incDir) {
- if (incDir->size() > 9 && cmSystemTools::IsNOTFOUND(incDir->c_str())) {
- std::string varName = incDir->substr(0, incDir->size() - 9);
+ for (std::string const& incDir : incs) {
+ if (incDir.size() > 9 && cmIsNOTFOUND(incDir)) {
+ std::string varName = incDir.substr(0, incDir.size() - 9);
if (state->GetCacheEntryPropertyAsBool(varName, "ADVANCED")) {
varName += " (ADVANCED)";
}
- std::string text = notFoundMap[varName];
- text += "\n used as include directory in directory ";
- text += this->Makefiles[i]->GetCurrentSourceDirectory();
+ std::string text =
+ cmStrCat(notFoundMap[varName],
+ "\n used as include directory in directory ",
+ this->Makefiles[i]->GetCurrentSourceDirectory());
notFoundMap[varName] = text;
}
}
}
this->CMakeInstance->UpdateProgress(
- "Configuring", 0.9f +
+ "Configuring",
+ 0.9f +
0.1f * (static_cast<float>(i) + 1.0f) /
static_cast<float>(this->Makefiles.size()));
}
if (!notFoundMap.empty()) {
std::string notFoundVars;
- for (std::map<std::string, std::string>::const_iterator ii =
- notFoundMap.begin();
- ii != notFoundMap.end(); ++ii) {
- notFoundVars += ii->first;
- notFoundVars += ii->second;
+ for (auto const& notFound : notFoundMap) {
+ notFoundVars += notFound.first;
+ notFoundVars += notFound.second;
notFoundVars += "\n";
}
cmSystemTools::Error("The following variables are used in this project, "
"but they are set to NOTFOUND.\n"
"Please set them or make sure they are set and "
- "tested correctly in the CMake files:\n",
- notFoundVars.c_str());
+ "tested correctly in the CMake files:\n" +
+ notFoundVars);
}
}
-int cmGlobalGenerator::TryCompile(const std::string& srcdir,
+int cmGlobalGenerator::TryCompile(int jobs, const std::string& srcdir,
const std::string& bindir,
const std::string& projectName,
const std::string& target, bool fast,
@@ -1738,47 +1817,45 @@ int cmGlobalGenerator::TryCompile(const std::string& srcdir,
this->FirstTimeProgress);
}
- std::string newTarget;
+ std::vector<std::string> newTarget = {};
if (!target.empty()) {
- newTarget += target;
-#if 0
-#if defined(_WIN32) || defined(__CYGWIN__)
- std::string tmp = target;
- // if the target does not already end in . something
- // then assume .exe
- if(tmp.size() < 4 || tmp[tmp.size()-4] != '.')
- {
- newTarget += ".exe";
- }
-#endif // WIN32
-#endif
+ newTarget = { target };
}
std::string config =
mf->GetSafeDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
- return this->Build(srcdir, bindir, projectName, newTarget, output, "",
+ return this->Build(jobs, srcdir, bindir, projectName, newTarget, output, "",
config, false, fast, false, this->TryCompileTimeout);
}
-void cmGlobalGenerator::GenerateBuildCommand(
- std::vector<std::string>& makeCommand, const std::string& /*unused*/,
- const std::string& /*unused*/, const std::string& /*unused*/,
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalGenerator::GenerateBuildCommand(
const std::string& /*unused*/, const std::string& /*unused*/,
- bool /*unused*/, bool /*unused*/, std::vector<std::string> const& /*unused*/)
+ const std::string& /*unused*/, std::vector<std::string> const& /*unused*/,
+ const std::string& /*unused*/, bool /*unused*/, int /*unused*/,
+ bool /*unused*/, std::vector<std::string> const& /*unused*/)
{
- makeCommand.push_back(
- "cmGlobalGenerator::GenerateBuildCommand not implemented");
+ GeneratedMakeCommand makeCommand;
+ makeCommand.Add("cmGlobalGenerator::GenerateBuildCommand not implemented");
+ return { std::move(makeCommand) };
}
-int cmGlobalGenerator::Build(const std::string& /*unused*/,
- const std::string& bindir,
- const std::string& projectName,
- const std::string& target, std::string& output,
- const std::string& makeCommandCSTR,
- const std::string& config, bool clean, bool fast,
- bool verbose, double timeout,
- cmSystemTools::OutputOption outputflag,
- std::vector<std::string> const& nativeOptions)
+void cmGlobalGenerator::PrintBuildCommandAdvice(std::ostream& /*os*/,
+ int /*jobs*/) const
{
+ // Subclasses override this method if they e.g want to give a warning that
+ // they do not support certain build command line options
+}
+
+int cmGlobalGenerator::Build(
+ int jobs, const std::string& /*unused*/, const std::string& bindir,
+ const std::string& projectName, const std::vector<std::string>& targets,
+ std::string& output, const std::string& makeCommandCSTR,
+ const std::string& config, bool clean, bool fast, bool verbose,
+ cmDuration timeout, cmSystemTools::OutputOption outputflag,
+ std::vector<std::string> const& nativeOptions)
+{
+ bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
+
/**
* Run an executable command and put the stdout in output.
*/
@@ -1786,37 +1863,49 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/,
output += "Change Dir: ";
output += bindir;
output += "\n";
+ if (workdir.Failed()) {
+ cmSystemTools::SetRunCommandHideConsole(hideconsole);
+ std::string err = cmStrCat("Failed to change directory: ",
+ std::strerror(workdir.GetLastResult()));
+ cmSystemTools::Error(err);
+ output += err;
+ output += "\n";
+ return 1;
+ }
- int retVal;
- bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
+ int retVal = 0;
cmSystemTools::SetRunCommandHideConsole(true);
std::string outputBuffer;
std::string* outputPtr = &outputBuffer;
- std::vector<std::string> makeCommand;
- this->GenerateBuildCommand(makeCommand, makeCommandCSTR, projectName, bindir,
- target, config, fast, verbose, nativeOptions);
+ std::vector<GeneratedMakeCommand> makeCommand =
+ this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir, targets,
+ config, fast, jobs, verbose, nativeOptions);
- // Workaround to convince VCExpress.exe to produce output.
+ // Workaround to convince some commands to produce output.
if (outputflag == cmSystemTools::OUTPUT_PASSTHROUGH &&
- !makeCommand.empty() &&
- cmSystemTools::LowerCase(
- cmSystemTools::GetFilenameName(makeCommand[0])) == "vcexpress.exe") {
+ makeCommand.back().RequiresOutputForward) {
outputflag = cmSystemTools::OUTPUT_FORWARD;
}
// should we do a clean first?
if (clean) {
- std::vector<std::string> cleanCommand;
- this->GenerateBuildCommand(cleanCommand, makeCommandCSTR, projectName,
- bindir, "clean", config, fast, verbose);
+ std::vector<GeneratedMakeCommand> cleanCommand =
+ this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir,
+ { "clean" }, config, fast, jobs, verbose);
output += "\nRun Clean Command:";
- output += cmSystemTools::PrintSingleCommand(cleanCommand);
+ output += cleanCommand.front().Printable();
output += "\n";
-
- if (!cmSystemTools::RunSingleCommand(cleanCommand, outputPtr, outputPtr,
- &retVal, CM_NULLPTR, outputflag,
- timeout)) {
+ if (cleanCommand.size() != 1) {
+ this->GetCMakeInstance()->IssueMessage(MessageType::INTERNAL_ERROR,
+ "The generator did not produce "
+ "exactly one command for the "
+ "'clean' target");
+ return 1;
+ }
+ if (!cmSystemTools::RunSingleCommand(cleanCommand.front().PrimaryCommand,
+ outputPtr, outputPtr, &retVal,
+ nullptr, outputflag, timeout)) {
cmSystemTools::SetRunCommandHideConsole(hideconsole);
cmSystemTools::Error("Generator: execution of make clean failed.");
output += *outputPtr;
@@ -1828,44 +1917,62 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/,
}
// now build
- std::string makeCommandStr = cmSystemTools::PrintSingleCommand(makeCommand);
- output += "\nRun Build Command:";
- output += makeCommandStr;
- output += "\n";
+ std::string makeCommandStr;
+ output += "\nRun Build Command(s):";
- if (!cmSystemTools::RunSingleCommand(makeCommand, outputPtr, outputPtr,
- &retVal, CM_NULLPTR, outputflag,
- timeout)) {
- cmSystemTools::SetRunCommandHideConsole(hideconsole);
- cmSystemTools::Error(
- "Generator: execution of make failed. Make command was: ",
- makeCommandStr.c_str());
- output += *outputPtr;
- output += "\nGenerator: execution of make failed. Make command was: " +
- makeCommandStr + "\n";
+ for (auto command = makeCommand.begin(); command != makeCommand.end();
+ ++command) {
+ makeCommandStr = command->Printable();
+ if (command != makeCommand.end()) {
+ makeCommandStr += " && ";
+ }
- return 1;
+ output += makeCommandStr;
+ if (!cmSystemTools::RunSingleCommand(command->PrimaryCommand, outputPtr,
+ outputPtr, &retVal, nullptr,
+ outputflag, timeout)) {
+ cmSystemTools::SetRunCommandHideConsole(hideconsole);
+ cmSystemTools::Error(
+ "Generator: execution of make failed. Make command was: " +
+ makeCommandStr);
+ output += *outputPtr;
+ output += "\nGenerator: execution of make failed. Make command was: " +
+ makeCommandStr + "\n";
+
+ return 1;
+ }
+ output += *outputPtr;
}
- output += *outputPtr;
+ output += "\n";
cmSystemTools::SetRunCommandHideConsole(hideconsole);
- // The SGI MipsPro 7.3 compiler does not return an error code when
- // the source has a #error in it! This is a work-around for such
- // compilers.
- if ((retVal == 0) && (output.find("#error") != std::string::npos)) {
+ // The OpenWatcom tools do not return an error code when a link
+ // library is not found!
+ if (this->CMakeInstance->GetState()->UseWatcomWMake() && retVal == 0 &&
+ output.find("W1008: cannot open") != std::string::npos) {
retVal = 1;
}
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 += " --build .";
+ makeCommand =
+ cmStrCat(cmSystemTools::ConvertToOutputPath(makeCommand), " --build .");
if (!config.empty()) {
makeCommand += " --config \"";
makeCommand += config;
@@ -1899,7 +2006,7 @@ void cmGlobalGenerator::AddMakefile(cmMakefile* mf)
// update progress
// estimate how many lg there will be
- const char* numGenC =
+ const std::string* numGenC =
this->CMakeInstance->GetState()->GetInitializedCacheValue(
"CMAKE_NUMBER_OF_MAKEFILES");
@@ -1917,7 +2024,7 @@ void cmGlobalGenerator::AddMakefile(cmMakefile* mf)
return;
}
- int numGen = atoi(numGenC);
+ int numGen = atoi(numGenC->c_str());
float prog = 0.9f * static_cast<float>(this->Makefiles.size()) /
static_cast<float>(numGen);
if (prog > 0.9f) {
@@ -1926,9 +2033,9 @@ void cmGlobalGenerator::AddMakefile(cmMakefile* mf)
this->CMakeInstance->UpdateProgress("Configuring", prog);
}
-void cmGlobalGenerator::AddInstallComponent(const char* component)
+void cmGlobalGenerator::AddInstallComponent(const std::string& component)
{
- if (component && *component) {
+ if (!component.empty()) {
this->InstallComponents.insert(component);
}
}
@@ -1968,8 +2075,8 @@ void cmGlobalGenerator::SetConfiguredFilesPath(cmGlobalGenerator* gen)
if (!gen->ConfiguredFilesPath.empty()) {
this->ConfiguredFilesPath = gen->ConfiguredFilesPath;
} else {
- this->ConfiguredFilesPath = gen->CMakeInstance->GetHomeOutputDirectory();
- this->ConfiguredFilesPath += cmake::GetCMakeFilesDirectory();
+ this->ConfiguredFilesPath =
+ cmStrCat(gen->CMakeInstance->GetHomeOutputDirectory(), "/CMakeFiles");
}
}
@@ -2006,11 +2113,12 @@ bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
cmGeneratorTarget* target) const
{
- if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
- target->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
- // This target is excluded from its directory.
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
return true;
}
+ if (const char* exclude = target->GetProperty("EXCLUDE_FROM_ALL")) {
+ return cmIsOn(exclude);
+ }
// This target is included in its directory. Check whether the
// directory is excluded.
return this->IsExcluded(root, target->GetLocalGenerator());
@@ -2024,8 +2132,7 @@ void cmGlobalGenerator::GetEnabledLanguages(
int cmGlobalGenerator::GetLinkerPreference(const std::string& lang) const
{
- std::map<std::string, int>::const_iterator it =
- this->LanguageToLinkerPreference.find(lang);
+ auto const it = this->LanguageToLinkerPreference.find(lang);
if (it != this->LanguageToLinkerPreference.end()) {
return it->second;
}
@@ -2035,16 +2142,15 @@ int cmGlobalGenerator::GetLinkerPreference(const std::string& lang) const
void cmGlobalGenerator::FillProjectMap()
{
this->ProjectMap.clear(); // make sure we start with a clean map
- unsigned int i;
- for (i = 0; i < this->LocalGenerators.size(); ++i) {
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
// for each local generator add all projects
- cmStateSnapshot snp = this->LocalGenerators[i]->GetStateSnapshot();
+ cmStateSnapshot snp = localGen->GetStateSnapshot();
std::string name;
do {
std::string snpProjName = snp.GetProjectName();
if (name != snpProjName) {
name = snpProjName;
- this->ProjectMap[name].push_back(this->LocalGenerators[i]);
+ this->ProjectMap[name].push_back(localGen);
}
snp = snp.GetBuildsystemDirectoryParent();
} while (snp.IsValid());
@@ -2053,26 +2159,21 @@ void cmGlobalGenerator::FillProjectMap()
cmMakefile* cmGlobalGenerator::FindMakefile(const std::string& start_dir) const
{
- MakefileMap::const_iterator i = this->MakefileSearchIndex.find(start_dir);
- if (i != this->MakefileSearchIndex.end()) {
- return i->second;
+ auto const it = this->MakefileSearchIndex.find(start_dir);
+ if (it != this->MakefileSearchIndex.end()) {
+ return it->second;
}
- return CM_NULLPTR;
+ return nullptr;
}
-///! Find a local generator by its startdirectory
cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(
- const std::string& start_dir) const
+ cmDirectoryId const& id) const
{
- for (std::vector<cmLocalGenerator*>::const_iterator it =
- this->LocalGenerators.begin();
- it != this->LocalGenerators.end(); ++it) {
- std::string sd = (*it)->GetCurrentSourceDirectory();
- if (sd == start_dir) {
- return *it;
- }
+ auto const it = this->LocalGeneratorSearchIndex.find(id.String);
+ if (it != this->LocalGeneratorSearchIndex.end()) {
+ return it->second;
}
- return CM_NULLPTR;
+ return nullptr;
}
void cmGlobalGenerator::AddAlias(const std::string& name,
@@ -2083,7 +2184,7 @@ void cmGlobalGenerator::AddAlias(const std::string& name,
bool cmGlobalGenerator::IsAlias(const std::string& name) const
{
- return this->AliasTargets.find(name) != this->AliasTargets.end();
+ return cmContains(this->AliasTargets, name);
}
void cmGlobalGenerator::IndexTarget(cmTarget* t)
@@ -2100,6 +2201,31 @@ void cmGlobalGenerator::IndexGeneratorTarget(cmGeneratorTarget* gt)
}
}
+static char const hexDigits[] = "0123456789abcdef";
+
+std::string cmGlobalGenerator::IndexGeneratorTargetUniquely(
+ cmGeneratorTarget const* gt)
+{
+ // Use the pointer value to uniquely identify the target instance.
+ // Use a ":" prefix to avoid conflict with project-defined targets.
+ // We must satisfy cmGeneratorExpression::IsValidTargetName so use no
+ // other special characters.
+ char buf[1 + sizeof(gt) * 2];
+ char* b = buf;
+ *b++ = ':';
+ for (size_t i = 0; i < sizeof(gt); ++i) {
+ unsigned char const c = reinterpret_cast<unsigned char const*>(&gt)[i];
+ *b++ = hexDigits[(c & 0xf0) >> 4];
+ *b++ = hexDigits[(c & 0x0f)];
+ }
+ std::string id(buf, sizeof(buf));
+ // We internally index pointers to non-const generator targets
+ // but our callers only have pointers to const generator targets.
+ // They will give up non-const privileges when looking up anyway.
+ this->GeneratorTargetSearchIndex[id] = const_cast<cmGeneratorTarget*>(gt);
+ return id;
+}
+
void cmGlobalGenerator::IndexMakefile(cmMakefile* mf)
{
// FIXME: add_subdirectory supports multiple build directories
@@ -2111,32 +2237,36 @@ void cmGlobalGenerator::IndexMakefile(cmMakefile* mf)
MakefileMap::value_type(mf->GetCurrentSourceDirectory(), mf));
}
+void cmGlobalGenerator::IndexLocalGenerator(cmLocalGenerator* lg)
+{
+ cmDirectoryId id = lg->GetMakefile()->GetDirectoryId();
+ this->LocalGeneratorSearchIndex[id.String] = lg;
+}
+
cmTarget* cmGlobalGenerator::FindTargetImpl(std::string const& name) const
{
- TargetMap::const_iterator i = this->TargetSearchIndex.find(name);
- if (i != this->TargetSearchIndex.end()) {
- return i->second;
+ auto const it = this->TargetSearchIndex.find(name);
+ if (it != this->TargetSearchIndex.end()) {
+ return it->second;
}
- return CM_NULLPTR;
+ return nullptr;
}
cmGeneratorTarget* cmGlobalGenerator::FindGeneratorTargetImpl(
std::string const& name) const
{
- GeneratorTargetMap::const_iterator i =
- this->GeneratorTargetSearchIndex.find(name);
- if (i != this->GeneratorTargetSearchIndex.end()) {
- return i->second;
+ auto const it = this->GeneratorTargetSearchIndex.find(name);
+ if (it != this->GeneratorTargetSearchIndex.end()) {
+ return it->second;
}
- return CM_NULLPTR;
+ return nullptr;
}
cmTarget* cmGlobalGenerator::FindTarget(const std::string& name,
bool excludeAliases) const
{
if (!excludeAliases) {
- std::map<std::string, std::string>::const_iterator ai =
- this->AliasTargets.find(name);
+ auto const ai = this->AliasTargets.find(name);
if (ai != this->AliasTargets.end()) {
return this->FindTargetImpl(ai->second);
}
@@ -2147,8 +2277,7 @@ cmTarget* cmGlobalGenerator::FindTarget(const std::string& name,
cmGeneratorTarget* cmGlobalGenerator::FindGeneratorTarget(
const std::string& name) const
{
- std::map<std::string, std::string>::const_iterator ai =
- this->AliasTargets.find(name);
+ auto const ai = this->AliasTargets.find(name);
if (ai != this->AliasTargets.end()) {
return this->FindGeneratorTargetImpl(ai->second);
}
@@ -2158,7 +2287,7 @@ cmGeneratorTarget* cmGlobalGenerator::FindGeneratorTarget(
bool cmGlobalGenerator::NameResolvesToFramework(
const std::string& libname) const
{
- if (cmSystemTools::IsPathToFramework(libname.c_str())) {
+ if (cmSystemTools::IsPathToFramework(libname)) {
return true;
}
@@ -2171,12 +2300,43 @@ bool cmGlobalGenerator::NameResolvesToFramework(
return false;
}
-inline std::string removeQuotes(const std::string& s)
+bool cmGlobalGenerator::CheckCMP0037(std::string const& targetName,
+ std::string const& reason) const
{
- if (s[0] == '\"' && s[s.size() - 1] == '\"') {
- return s.substr(1, s.size() - 2);
+ cmTarget* tgt = this->FindTarget(targetName);
+ if (!tgt) {
+ return true;
+ }
+ MessageType messageType = MessageType::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 = MessageType::FATAL_ERROR;
+ break;
+ }
+ if (issueMessage) {
+ e << "The target name \"" << targetName << "\" is reserved " << reason
+ << ".";
+ if (messageType == MessageType::AUTHOR_WARNING) {
+ e << " It may result in undefined behavior.";
+ }
+ this->GetCMakeInstance()->IssueMessage(messageType, e.str(),
+ tgt->GetBacktrace());
+ if (messageType == MessageType::FATAL_ERROR) {
+ return false;
+ }
}
- return s;
+ return true;
}
void cmGlobalGenerator::CreateDefaultGlobalTargets(
@@ -2194,6 +2354,19 @@ void cmGlobalGenerator::AddGlobalTarget_Package(
std::vector<GlobalTargetInfo>& targets)
{
cmMakefile* mf = this->Makefiles[0];
+ std::string configFile =
+ cmStrCat(mf->GetCurrentBinaryDirectory(), "/CPackConfig.cmake");
+ if (!cmSystemTools::FileExists(configFile)) {
+ return;
+ }
+
+ static const auto reservedTargets = { "package", "PACKAGE" };
+ for (auto const& target : reservedTargets) {
+ if (!this->CheckCMP0037(target, "when CPack packaging is enabled")) {
+ return;
+ }
+ }
+
const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
GlobalTargetInfo gti;
gti.Name = this->GetPackageTargetName();
@@ -2207,125 +2380,141 @@ 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());
+ gti.Depends.emplace_back(this->GetPreinstallTargetName());
} else {
const char* noPackageAll =
mf->GetDefinition("CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY");
- if (!noPackageAll || cmSystemTools::IsOff(noPackageAll)) {
- gti.Depends.push_back(this->GetAllTargetName());
+ if (!noPackageAll || cmIsOff(noPackageAll)) {
+ gti.Depends.emplace_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 =
+ cmStrCat(mf->GetCurrentBinaryDirectory(), "/CPackSourceConfig.cmake");
+ if (!cmSystemTools::FileExists(configFile)) {
+ return;
+ }
+
+ static const auto reservedTargets = { "package_source" };
+ for (auto const& target : reservedTargets) {
+ if (!this->CheckCMP0037(target,
+ "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;
+ }
+
+ static const auto reservedTargets = { "test", "RUN_TESTS" };
+ for (auto const& target : reservedTargets) {
+ if (!this->CheckCMP0037(target, "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("-S$(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("-S$(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(
@@ -2336,8 +2525,9 @@ void cmGlobalGenerator::AddGlobalTarget_Install(
bool skipInstallRules = mf->IsOn("CMAKE_SKIP_INSTALL_RULES");
if (this->InstallTargetEnabled && skipInstallRules) {
this->CMakeInstance->IssueMessage(
- cmake::WARNING, "CMAKE_SKIP_INSTALL_RULES was enabled even though "
- "installation rules have been specified",
+ MessageType::WARNING,
+ "CMAKE_SKIP_INSTALL_RULES was enabled even though "
+ "installation rules have been specified",
mf->GetBacktrace());
} else if (this->InstallTargetEnabled && !skipInstallRules) {
if (!cmakeCfgIntDir || !*cmakeCfgIntDir || cmakeCfgIntDir[0] == '.') {
@@ -2353,7 +2543,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;
@@ -2362,12 +2552,12 @@ void cmGlobalGenerator::AddGlobalTarget_Install(
gti.UsesTerminal = true;
cmCustomCommandLine singleLine;
if (this->GetPreinstallTargetName()) {
- gti.Depends.push_back(this->GetPreinstallTargetName());
+ gti.Depends.emplace_back(this->GetPreinstallTargetName());
} else {
const char* noall =
mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
- if (!noall || cmSystemTools::IsOff(noall)) {
- gti.Depends.push_back(this->GetAllTargetName());
+ if (!noall || cmIsOff(noall)) {
+ gti.Depends.emplace_back(this->GetAllTargetName());
}
}
if (mf->GetDefinition("CMake_BINARY_DIR") &&
@@ -2407,13 +2597,13 @@ 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);
}
// install_strip
const char* install_strip = this->GetInstallStripTargetName();
- if ((install_strip != CM_NULLPTR) && (mf->IsSet("CMAKE_STRIP"))) {
+ if ((install_strip != nullptr) && (mf->IsSet("CMAKE_STRIP"))) {
gti.Name = install_strip;
gti.Message = "Installing the project stripped...";
gti.UsesTerminal = true;
@@ -2423,7 +2613,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);
}
}
@@ -2449,7 +2639,7 @@ bool cmGlobalGenerator::UseFolderProperty() const
// If this property is defined, let the setter turn this on or off...
//
if (prop) {
- return cmSystemTools::IsOn(prop);
+ return cmIsOn(prop);
}
// By default, this feature is OFF, since it is not supported in the
@@ -2470,16 +2660,15 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
std::vector<std::string> no_byproducts;
std::vector<std::string> no_depends;
// Store the custom command in the target.
- cmCustomCommand cc(CM_NULLPTR, no_outputs, no_byproducts, no_depends,
- gti.CommandLines, CM_NULLPTR, gti.WorkingDir.c_str());
+ cmCustomCommand cc(nullptr, no_outputs, no_byproducts, no_depends,
+ gti.CommandLines, nullptr, gti.WorkingDir.c_str());
cc.SetUsesTerminal(gti.UsesTerminal);
- target.AddPostBuildCommand(cc);
+ target.AddPostBuildCommand(std::move(cc));
if (!gti.Message.empty()) {
target.SetProperty("EchoString", gti.Message.c_str());
}
- for (std::vector<std::string>::const_iterator dit = gti.Depends.begin();
- dit != gti.Depends.end(); ++dit) {
- target.AddUtility(*dit);
+ for (std::string const& d : gti.Depends) {
+ target.AddUtility(d);
}
// Organize in the "predefined targets" folder:
@@ -2494,26 +2683,23 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
std::string cmGlobalGenerator::GenerateRuleFile(
std::string const& output) const
{
- std::string ruleFile = output;
- ruleFile += ".rule";
+ std::string ruleFile = cmStrCat(output, ".rule");
const char* dir = this->GetCMakeCFGIntDir();
if (dir && dir[0] == '$') {
- cmSystemTools::ReplaceString(ruleFile, dir,
- cmake::GetCMakeFilesDirectory());
+ cmSystemTools::ReplaceString(ruleFile, dir, "/CMakeFiles");
}
return ruleFile;
}
bool cmGlobalGenerator::ShouldStripResourcePath(cmMakefile* mf) const
{
- return mf->PlatformIsAppleIos();
+ return mf->PlatformIsAppleEmbedded();
}
std::string cmGlobalGenerator::GetSharedLibFlagsForLanguage(
std::string const& l) const
{
- std::map<std::string, std::string>::const_iterator it =
- this->LanguageToOriginalSharedLibFlags.find(l);
+ auto const it = this->LanguageToOriginalSharedLibFlags.find(l);
if (it != this->LanguageToOriginalSharedLibFlags.end()) {
return it->second;
}
@@ -2542,21 +2728,19 @@ 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 cmContains(reservedTargets, name);
}
void cmGlobalGenerator::SetExternalMakefileProjectGenerator(
cmExternalMakefileProjectGenerator* extraGenerator)
{
- this->ExtraGenerator = extraGenerator;
- if (this->ExtraGenerator != CM_NULLPTR) {
+ this->ExtraGenerator.reset(extraGenerator);
+ if (this->ExtraGenerator) {
this->ExtraGenerator->SetGlobalGenerator(this);
}
}
@@ -2587,18 +2771,13 @@ void cmGlobalGenerator::GetTargetSets(TargetDependSet& projectTargets,
GeneratorVector const& generators)
{
// loop over all local generators
- for (std::vector<cmLocalGenerator*>::const_iterator i = generators.begin();
- i != generators.end(); ++i) {
+ for (cmLocalGenerator* generator : generators) {
// check to make sure generator is not excluded
- if (this->IsExcluded(root, *i)) {
+ if (this->IsExcluded(root, generator)) {
continue;
}
- // Get the targets in the makefile
- std::vector<cmGeneratorTarget*> tgts = (*i)->GetGeneratorTargets();
- // loop over all the targets
- for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin();
- l != tgts.end(); ++l) {
- cmGeneratorTarget* target = *l;
+ // loop over all the generator targets in the makefile
+ for (cmGeneratorTarget* target : generator->GetGeneratorTargets()) {
if (this->IsRootOnlyTarget(target) &&
target->GetLocalGenerator() != root) {
continue;
@@ -2624,9 +2803,8 @@ void cmGlobalGenerator::AddTargetDepends(cmGeneratorTarget const* target,
if (projectTargets.insert(target).second) {
// This is the first time we have encountered the target.
// Recursively follow its dependencies.
- TargetDependSet const& ts = this->GetTargetDirectDepends(target);
- for (TargetDependSet::const_iterator i = ts.begin(); i != ts.end(); ++i) {
- this->AddTargetDepends(*i, projectTargets);
+ for (auto const& t : this->GetTargetDirectDepends(target)) {
+ this->AddTargetDepends(t, projectTargets);
}
}
}
@@ -2671,7 +2849,7 @@ std::set<std::string> const& cmGlobalGenerator::GetDirectoryContent(
void cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs,
std::string const& content)
{
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
// Ignore if there are no outputs.
if (outputs.empty()) {
return;
@@ -2686,8 +2864,9 @@ void cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs,
}
// Shorten the output name (in expected use case).
- cmOutputConverter converter(this->GetMakefiles()[0]->GetStateSnapshot());
- std::string fname = converter.ConvertToRelativePath(
+ cmStateDirectory cmDir =
+ this->GetMakefiles()[0]->GetStateSnapshot().GetDirectory();
+ std::string fname = cmDir.ConvertToRelPathIfNotContained(
this->GetMakefiles()[0]->GetState()->GetBinaryDirectory(), outputs[0]);
// Associate the hash with this output.
@@ -2700,11 +2879,9 @@ void cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs,
void cmGlobalGenerator::CheckRuleHashes()
{
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
std::string home = this->GetCMakeInstance()->GetHomeOutputDirectory();
- std::string pfile = home;
- pfile += this->GetCMakeInstance()->GetCMakeFilesDirectory();
- pfile += "/CMakeRuleHashes.txt";
+ std::string pfile = cmStrCat(home, "/CMakeFiles/CMakeRuleHashes.txt");
this->CheckRuleHashes(pfile, home);
this->WriteRuleHashes(pfile);
#endif
@@ -2736,14 +2913,13 @@ void cmGlobalGenerator::CheckRuleHashes(std::string const& pfile,
fname = line.substr(33);
// Look for a hash for this file's rule.
- std::map<std::string, RuleHash>::const_iterator rhi =
- this->RuleHashes.find(fname);
+ auto const rhi = this->RuleHashes.find(fname);
if (rhi != this->RuleHashes.end()) {
// Compare the rule hash in the file to that we were given.
if (strncmp(line.c_str(), rhi->second.Data, 32) != 0) {
// The rule has changed. Delete the output so it will be
// built again.
- fname = cmSystemTools::CollapseFullPath(fname, home.c_str());
+ fname = cmSystemTools::CollapseFullPath(fname, home);
cmSystemTools::RemoveFile(fname);
}
} else {
@@ -2753,10 +2929,10 @@ void cmGlobalGenerator::CheckRuleHashes(std::string const& pfile,
// Instead, we keep the rule hash as long as the file exists so
// 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())) {
+ std::string fpath = cmSystemTools::CollapseFullPath(fname, home);
+ if (cmSystemTools::FileExists(fpath)) {
RuleHash hash;
- strncpy(hash.Data, line.c_str(), 32);
+ memcpy(hash.Data, line.c_str(), 32);
this->RuleHashes[fname] = hash;
}
}
@@ -2769,13 +2945,11 @@ void cmGlobalGenerator::WriteRuleHashes(std::string const& pfile)
if (this->RuleHashes.empty()) {
cmSystemTools::RemoveFile(pfile);
} else {
- cmGeneratedFileStream fout(pfile.c_str());
+ cmGeneratedFileStream fout(pfile);
fout << "# Hashes of file build rules.\n";
- for (std::map<std::string, RuleHash>::const_iterator rhi =
- this->RuleHashes.begin();
- rhi != this->RuleHashes.end(); ++rhi) {
- fout.write(rhi->second.Data, 32);
- fout << " " << rhi->first << "\n";
+ for (auto const& rh : this->RuleHashes) {
+ fout.write(rh.second.Data, 32);
+ fout << " " << rh.first << "\n";
}
}
}
@@ -2783,21 +2957,17 @@ void cmGlobalGenerator::WriteRuleHashes(std::string const& pfile)
void cmGlobalGenerator::WriteSummary()
{
// Record all target directories in a central location.
- std::string fname = this->CMakeInstance->GetHomeOutputDirectory();
- fname += cmake::GetCMakeFilesDirectory();
- fname += "/TargetDirectories.txt";
- cmGeneratedFileStream fout(fname.c_str());
+ std::string fname = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(),
+ "/CMakeFiles/TargetDirectories.txt");
+ cmGeneratedFileStream fout(fname);
- for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
- std::vector<cmGeneratorTarget*> tgts =
- this->LocalGenerators[i]->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator it = tgts.begin();
- it != tgts.end(); ++it) {
- if ((*it)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ for (cmLocalGenerator* lg : this->LocalGenerators) {
+ for (cmGeneratorTarget* tgt : lg->GetGeneratorTargets()) {
+ if (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
- this->WriteSummary(*it);
- fout << (*it)->GetSupportDirectory() << "\n";
+ this->WriteSummary(tgt);
+ fout << tgt->GetSupportDirectory() << "\n";
}
}
}
@@ -2806,68 +2976,92 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target)
{
// Place the labels file in a per-target support directory.
std::string dir = target->GetSupportDirectory();
- std::string file = dir;
- file += "/Labels.txt";
+ std::string file = cmStrCat(dir, "/Labels.txt");
std::string json_file = dir + "/Labels.json";
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
// Check whether labels are enabled for this target.
- if (const char* value = target->GetProperty("LABELS")) {
+ const char* targetLabels = target->GetProperty("LABELS");
+ const char* directoryLabels =
+ target->Target->GetMakefile()->GetProperty("LABELS");
+ const char* cmakeDirectoryLabels =
+ target->Target->GetMakefile()->GetDefinition("CMAKE_DIRECTORY_LABELS");
+ if (targetLabels || directoryLabels || cmakeDirectoryLabels) {
Json::Value lj_root(Json::objectValue);
Json::Value& lj_target = lj_root["target"] = Json::objectValue;
lj_target["name"] = target->GetName();
Json::Value& lj_target_labels = lj_target["labels"] = Json::arrayValue;
Json::Value& lj_sources = lj_root["sources"] = Json::arrayValue;
- cmSystemTools::MakeDirectory(dir.c_str());
- cmGeneratedFileStream fout(file.c_str());
+ cmSystemTools::MakeDirectory(dir);
+ cmGeneratedFileStream fout(file);
+
+ std::vector<std::string> labels;
// List the target-wide labels. All sources in the target get
// these labels.
- std::vector<std::string> labels;
- cmSystemTools::ExpandListArgument(value, labels);
- if (!labels.empty()) {
- fout << "# Target labels\n";
- for (std::vector<std::string>::const_iterator li = labels.begin();
- li != labels.end(); ++li) {
- fout << " " << *li << "\n";
- lj_target_labels.append(*li);
+ if (targetLabels) {
+ cmExpandList(targetLabels, labels);
+ if (!labels.empty()) {
+ fout << "# Target labels\n";
+ for (std::string const& l : labels) {
+ fout << " " << l << "\n";
+ lj_target_labels.append(l);
+ }
}
}
+ // List directory labels
+ std::vector<std::string> directoryLabelsList;
+ std::vector<std::string> cmakeDirectoryLabelsList;
+
+ if (directoryLabels) {
+ cmExpandList(directoryLabels, directoryLabelsList);
+ }
+
+ if (cmakeDirectoryLabels) {
+ cmExpandList(cmakeDirectoryLabels, cmakeDirectoryLabelsList);
+ }
+
+ if (!directoryLabelsList.empty() || !cmakeDirectoryLabelsList.empty()) {
+ fout << "# Directory labels\n";
+ }
+
+ for (std::string const& li : directoryLabelsList) {
+ fout << " " << li << "\n";
+ lj_target_labels.append(li);
+ }
+
+ for (std::string const& li : cmakeDirectoryLabelsList) {
+ fout << " " << li << "\n";
+ lj_target_labels.append(li);
+ }
+
// List the source files with any per-source labels.
fout << "# Source files and their labels\n";
std::vector<cmSourceFile*> sources;
- std::vector<std::string> configs;
- target->Target->GetMakefile()->GetConfigurations(configs);
- if (configs.empty()) {
- configs.push_back("");
- }
- for (std::vector<std::string>::const_iterator ci = configs.begin();
- ci != configs.end(); ++ci) {
- target->GetSourceFiles(sources, *ci);
- }
- std::vector<cmSourceFile*>::const_iterator sourcesEnd =
- cmRemoveDuplicates(sources);
- for (std::vector<cmSourceFile*>::const_iterator si = sources.begin();
- si != sourcesEnd; ++si) {
+ std::vector<std::string> const& configs =
+ target->Target->GetMakefile()->GetGeneratorConfigs();
+ for (std::string const& c : configs) {
+ target->GetSourceFiles(sources, c);
+ }
+ auto const sourcesEnd = cmRemoveDuplicates(sources);
+ for (cmSourceFile* sf : cmMakeRange(sources.cbegin(), sourcesEnd)) {
Json::Value& lj_source = lj_sources.append(Json::objectValue);
- cmSourceFile* sf = *si;
- std::string const& sfp = sf->GetFullPath();
+ std::string const& sfp = sf->ResolveFullPath();
fout << sfp << "\n";
lj_source["file"] = sfp;
if (const char* svalue = sf->GetProperty("LABELS")) {
labels.clear();
Json::Value& lj_source_labels = lj_source["labels"] = Json::arrayValue;
- cmSystemTools::ExpandListArgument(svalue, labels);
- for (std::vector<std::string>::const_iterator li = labels.begin();
- li != labels.end(); ++li) {
- fout << " " << *li << "\n";
- lj_source_labels.append(*li);
+ cmExpandList(svalue, labels);
+ for (std::string const& label : labels) {
+ fout << " " << label << "\n";
+ lj_source_labels.append(label);
}
}
}
- cmGeneratedFileStream json_fout(json_file.c_str());
+ cmGeneratedFileStream json_fout(json_file);
json_fout << lj_root;
} else
#endif
@@ -2881,11 +3075,23 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target)
std::string cmGlobalGenerator::EscapeJSON(const std::string& s)
{
std::string result;
- for (std::string::size_type i = 0; i < s.size(); ++i) {
- if (s[i] == '"' || s[i] == '\\') {
- result += '\\';
+ result.reserve(s.size());
+ for (char i : s) {
+ switch (i) {
+ case '"':
+ case '\\':
+ result += '\\';
+ result += i;
+ break;
+ case '\n':
+ result += "\\n";
+ break;
+ case '\t':
+ result += "\\t";
+ break;
+ default:
+ result += i;
}
- result += s[i];
}
return result;
}
@@ -2902,21 +3108,11 @@ cmGlobalGenerator::GetFilenameTargetDepends(cmSourceFile* sf) const
return this->FilenameTargetDepends[sf];
}
-void cmGlobalGenerator::CreateEvaluationSourceFiles(
- std::string const& config) const
-{
- unsigned int i;
- for (i = 0; i < this->LocalGenerators.size(); ++i) {
- this->LocalGenerators[i]->CreateEvaluationFileOutputs(config);
- }
-}
-
void cmGlobalGenerator::ProcessEvaluationFiles()
{
std::vector<std::string> generatedFiles;
- unsigned int i;
- for (i = 0; i < this->LocalGenerators.size(); ++i) {
- this->LocalGenerators[i]->ProcessEvaluationFiles(generatedFiles);
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ localGen->ProcessEvaluationFiles(generatedFiles);
}
}
@@ -2937,19 +3133,18 @@ bool cmGlobalGenerator::GenerateCPackPropertiesFile()
std::vector<std::string> configs;
std::string config = mf->GetConfigurations(configs, false);
- std::string path = this->CMakeInstance->GetHomeOutputDirectory();
- path += "/CPackProperties.cmake";
+ std::string path = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(),
+ "/CPackProperties.cmake");
- if (!cmSystemTools::FileExists(path.c_str()) && installedFiles.empty()) {
+ if (!cmSystemTools::FileExists(path) && installedFiles.empty()) {
return true;
}
- cmGeneratedFileStream file(path.c_str());
+ cmGeneratedFileStream file(path);
file << "# CPack properties\n";
- for (cmake::InstalledFilesMap::const_iterator i = installedFiles.begin();
- i != installedFiles.end(); ++i) {
- cmInstalledFile const& installedFile = i->second;
+ for (auto const& i : installedFiles) {
+ cmInstalledFile const& installedFile = i.second;
cmCPackPropertiesGenerator cpackPropertiesGenerator(lg, installedFile,
configs);
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 871178be1..f25ff7b77 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -3,28 +3,38 @@
#ifndef cmGlobalGenerator_h
#define cmGlobalGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <map>
+#include <memory>
#include <set>
#include <string>
+#include <unordered_map>
#include <utility>
#include <vector>
+#include "cm_codecvt.hxx"
+
+#include "cmAlgorithms.h"
#include "cmCustomCommandLines.h"
-#include "cmExportSetMap.h"
+#include "cmDuration.h"
+#include "cmExportSet.h"
#include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
-#include "cm_codecvt.hxx"
-#include "cm_unordered_map.hxx"
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmFileLockPool.h"
+#if !defined(CMAKE_BOOTSTRAP)
+# include "cm_jsoncpp_value.h"
+
+# include "cmFileLockPool.h"
#endif
+#define CMAKE_DIRECTORY_ID_SEP "::@"
+
+class cmDirectoryId;
class cmExportBuildFileGenerator;
class cmExternalMakefileProjectGenerator;
class cmGeneratorTarget;
@@ -36,6 +46,41 @@ class cmSourceFile;
class cmStateDirectory;
class cmake;
+namespace detail {
+inline void AppendStrs(std::vector<std::string>&)
+{
+}
+template <typename T, typename... Ts>
+inline void AppendStrs(std::vector<std::string>& command, T&& s, Ts&&... ts)
+{
+ command.emplace_back(std::forward<T>(s));
+ AppendStrs(command, std::forward<Ts>(ts)...);
+}
+
+struct GeneratedMakeCommand
+{
+ // Add each argument as a separate element to the vector
+ template <typename... T>
+ void Add(T&&... args)
+ {
+ // iterate the args and append each one
+ AppendStrs(PrimaryCommand, std::forward<T>(args)...);
+ }
+
+ // Add each value in the iterators as a separate element to the vector
+ void Add(std::vector<std::string>::const_iterator start,
+ std::vector<std::string>::const_iterator end)
+ {
+ cmAppend(PrimaryCommand, start, end);
+ }
+
+ std::string Printable() const { return cmJoin(PrimaryCommand, " "); }
+
+ std::vector<std::string> PrimaryCommand;
+ bool RequiresOutputForward = false;
+};
+}
+
/** \class cmGlobalGenerator
* \brief Responsible for overseeing the generation process for the entire tree
*
@@ -45,13 +90,13 @@ class cmake;
class cmGlobalGenerator
{
public:
- ///! Free any memory allocated with the GlobalGenerator
+ //! Free any memory allocated with the GlobalGenerator
cmGlobalGenerator(cmake* cm);
virtual ~cmGlobalGenerator();
virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf);
- ///! Get the name for this generator
+ //! Get the name for this generator
virtual std::string GetName() const { return "Generic"; }
/** Check whether the given name matches the current generator. */
@@ -66,9 +111,17 @@ public:
return codecvt::None;
}
+#if !defined(CMAKE_BOOTSTRAP)
+ /** Get a JSON object describing the generator. */
+ virtual Json::Value GetJson() const;
+#endif
+
/** 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);
@@ -142,9 +195,10 @@ public:
* Try running cmake and building a file. This is used for dynamically
* loaded commands, not as part of the usual build process.
*/
- int TryCompile(const std::string& srcdir, const std::string& bindir,
- const std::string& projectName, const std::string& targetName,
- bool fast, std::string& output, cmMakefile* mf);
+ int TryCompile(int jobs, const std::string& srcdir,
+ const std::string& bindir, const std::string& projectName,
+ const std::string& targetName, bool fast, std::string& output,
+ cmMakefile* mf);
/**
* Build a file given the following information. This is a more direct call
@@ -152,29 +206,41 @@ public:
* empty then all is assumed. clean indicates if a "make clean" should be
* done first.
*/
- int Build(const std::string& srcdir, const std::string& bindir,
- 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,
- std::vector<std::string> const& nativeOptions =
- std::vector<std::string>());
-
- 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,
+ int Build(
+ int jobs, const std::string& srcdir, const std::string& bindir,
+ const std::string& projectName,
+ std::vector<std::string> const& targetNames, std::string& output,
+ const std::string& makeProgram, const std::string& config, bool clean,
+ bool fast, bool verbose, 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);
+
+ struct GeneratedMakeCommand final : public detail::GeneratedMakeCommand
+ {
+ };
+
+ virtual std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
std::vector<std::string> const& makeOptions = std::vector<std::string>());
+ virtual void PrintBuildCommandAdvice(std::ostream& os, int jobs) const;
+
/** Generate a "cmake --build" call for a given target and config. */
std::string GenerateCMakeBuildCommand(const std::string& target,
const std::string& config,
const std::string& native,
bool ignoreErrors);
- ///! Get the CMake instance
+ //! Get the CMake instance
cmake* GetCMakeInstance() const { return this->CMakeInstance; }
void SetConfiguredFilesPath(cmGlobalGenerator* gen);
@@ -187,19 +253,25 @@ public:
return this->LocalGenerators;
}
- cmMakefile* GetCurrentMakefile() const { return this->CurrentMakefile; }
+ cmMakefile* GetCurrentMakefile() const
+ {
+ return this->CurrentConfigureMakefile;
+ }
- void SetCurrentMakefile(cmMakefile* mf) { this->CurrentMakefile = mf; }
+ void SetCurrentMakefile(cmMakefile* mf)
+ {
+ this->CurrentConfigureMakefile = mf;
+ }
void AddMakefile(cmMakefile* mf);
- ///! Set an generator for an "external makefile based project"
+ //! Set an generator for an "external makefile based project"
void SetExternalMakefileProjectGenerator(
cmExternalMakefileProjectGenerator* extraGenerator);
std::string GetExtraGeneratorName() const;
- void AddInstallComponent(const char* component);
+ void AddInstallComponent(const std::string& component);
const std::set<std::string>* GetInstallComponents() const
{
@@ -210,31 +282,31 @@ public:
const char* GetGlobalSetting(std::string const& name) const;
bool GlobalSettingIsOn(std::string const& name) const;
- const char* GetSafeGlobalSetting(std::string const& name) const;
+ std::string GetSafeGlobalSetting(std::string const& name) const;
/** Add a file to the manifest of generated targets for a configuration. */
void AddToManifest(std::string const& f);
void EnableInstallTarget();
- int TryCompileTimeout;
+ cmDuration TryCompileTimeout;
bool GetForceUnixPaths() const { return this->ForceUnixPaths; }
bool GetToolSupportsColor() const { return this->ToolSupportsColor; }
- ///! return the language for the given extension
+ //! return the language for the given extension
std::string GetLanguageFromExtension(const char* ext) const;
- ///! is an extension to be ignored
+ //! is an extension to be ignored
bool IgnoreFile(const char* ext) const;
- ///! What is the preference for linkers and this language (None or Preferred)
+ //! What is the preference for linkers and this language (None or Preferred)
int GetLinkerPreference(const std::string& lang) const;
- ///! What is the object file extension for a given source file?
+ //! What is the object file extension for a given source file?
std::string GetLanguageOutputExtension(cmSourceFile const&) const;
- ///! What is the configurations directory variable called?
+ //! What is the configurations directory variable called?
virtual const char* GetCMakeCFGIntDir() const { return "."; }
- ///! expand CFGIntDir for a configuration
+ //! expand CFGIntDir for a configuration
virtual std::string ExpandCFGIntDir(const std::string& str,
const std::string& config) const;
@@ -250,7 +322,7 @@ public:
*/
virtual bool FindMakeProgram(cmMakefile*);
- ///! Find a target by name by searching the local generators.
+ //! Find a target by name by searching the local generators.
cmTarget* FindTarget(const std::string& name,
bool excludeAliases = false) const;
@@ -264,8 +336,7 @@ public:
bool NameResolvesToFramework(const std::string& libname) const;
cmMakefile* FindMakefile(const std::string& start_dir) const;
- ///! Find a local generator by its startdirectory
- cmLocalGenerator* FindLocalGenerator(const std::string& start_dir) const;
+ cmLocalGenerator* FindLocalGenerator(cmDirectoryId const& id) const;
/** Append the subdirectory for the given configuration. If anything is
appended the given prefix and suffix will be appended around it, which
@@ -285,32 +356,36 @@ public:
void IndexTarget(cmTarget* t);
void IndexGeneratorTarget(cmGeneratorTarget* gt);
+ // Index the target using a name that is unique to that target
+ // even if other targets have the same name.
+ std::string IndexGeneratorTargetUniquely(cmGeneratorTarget const* gt);
+
static bool IsReservedTarget(std::string const& name);
virtual const char* GetAllTargetName() const { return "ALL_BUILD"; }
virtual const char* GetInstallTargetName() const { return "INSTALL"; }
- virtual const char* GetInstallLocalTargetName() const { return CM_NULLPTR; }
- virtual const char* GetInstallStripTargetName() const { return CM_NULLPTR; }
- virtual const char* GetPreinstallTargetName() const { return CM_NULLPTR; }
+ virtual const char* GetInstallLocalTargetName() const { return nullptr; }
+ virtual const char* GetInstallStripTargetName() const { return nullptr; }
+ virtual const char* GetPreinstallTargetName() const { return nullptr; }
virtual const char* GetTestTargetName() const { return "RUN_TESTS"; }
virtual const char* GetPackageTargetName() const { return "PACKAGE"; }
- virtual const char* GetPackageSourceTargetName() const { return CM_NULLPTR; }
- virtual const char* GetEditCacheTargetName() const { return CM_NULLPTR; }
- virtual const char* GetRebuildCacheTargetName() const { return CM_NULLPTR; }
- virtual const char* GetCleanTargetName() const { return CM_NULLPTR; }
+ virtual const char* GetPackageSourceTargetName() const { return nullptr; }
+ virtual const char* GetEditCacheTargetName() const { return nullptr; }
+ virtual const char* GetRebuildCacheTargetName() const { return nullptr; }
+ virtual const char* GetCleanTargetName() const { return nullptr; }
// Lookup edit_cache target command preferred by this generator.
virtual std::string GetEditCacheCommand() const { return ""; }
// Class to track a set of dependencies.
- typedef cmTargetDependSet TargetDependSet;
+ using TargetDependSet = cmTargetDependSet;
// what targets does the specified target depend on directly
// via a target_link_libraries or add_dependencies
TargetDependSet const& GetTargetDirectDepends(
const cmGeneratorTarget* target);
- const std::map<std::string, std::vector<cmLocalGenerator*> >& GetProjectMap()
+ const std::map<std::string, std::vector<cmLocalGenerator*>>& GetProjectMap()
const
{
return this->ProjectMap;
@@ -333,6 +408,8 @@ public:
i.e. "Can I build Debug and Release in the same tree?" */
virtual bool IsMultiConfig() const { return false; }
+ virtual bool IsXcode() const { return false; }
+
/** Return true if we know the exact location of object files.
If false, store the reason in the given string.
This is meaningful only after EnableLanguage has been called. */
@@ -342,6 +419,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; }
@@ -376,14 +457,12 @@ public:
bool GenerateCPackPropertiesFile();
- void CreateEvaluationSourceFiles(std::string const& config) const;
-
void SetFilenameTargetDepends(
cmSourceFile* sf, std::set<cmGeneratorTarget const*> const& tgts);
const std::set<const cmGeneratorTarget*>& GetFilenameTargetDepends(
cmSourceFile* sf) const;
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
cmFileLockPool& GetFileLockPool() { return FileLockPool; }
#endif
@@ -394,8 +473,10 @@ public:
std::string MakeSilentFlag;
+ int RecursionDepth;
+
protected:
- typedef std::vector<cmLocalGenerator*> GeneratorVector;
+ using GeneratorVector = std::vector<cmLocalGenerator*>;
// for a project collect all its targets by following depend
// information, and also collect all the targets
void GetTargetSets(TargetDependSet& projectTargets,
@@ -416,7 +497,11 @@ protected:
virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const;
- std::vector<const cmGeneratorTarget*> CreateQtAutoGeneratorsTargets();
+ /// @brief Qt AUTOMOC/UIC/RCC target generation
+ /// @return true on success
+ bool QtAutoGen();
+
+ bool AddAutomaticSources();
std::string SelectMakeProgram(const std::string& makeProgram,
const std::string& makeDefault = "") const;
@@ -438,11 +523,7 @@ protected:
cmCustomCommandLines CommandLines;
std::vector<std::string> Depends;
std::string WorkingDir;
- bool UsesTerminal;
- GlobalTargetInfo()
- : UsesTerminal(false)
- {
- }
+ bool UsesTerminal = false;
};
void CreateDefaultGlobalTargets(std::vector<GlobalTargetInfo>& targets);
@@ -460,9 +541,9 @@ protected:
cmake* CMakeInstance;
std::vector<cmMakefile*> Makefiles;
std::vector<cmLocalGenerator*> LocalGenerators;
- cmMakefile* CurrentMakefile;
+ cmMakefile* CurrentConfigureMakefile;
// map from project name to vector of local generators in that project
- std::map<std::string, std::vector<cmLocalGenerator*> > ProjectMap;
+ std::map<std::string, std::vector<cmLocalGenerator*>> ProjectMap;
// Set of named installation components requested by the project.
std::set<std::string> InstallComponents;
@@ -476,15 +557,15 @@ protected:
cmTarget* FindTargetImpl(std::string const& name) const;
cmGeneratorTarget* FindGeneratorTargetImpl(std::string const& name) const;
- cmGeneratorTarget* FindImportedGeneratorTargetImpl(
- std::string const& name) const;
const char* GetPredefinedTargetsFolder();
private:
- typedef CM_UNORDERED_MAP<std::string, cmTarget*> TargetMap;
- typedef CM_UNORDERED_MAP<std::string, cmGeneratorTarget*> GeneratorTargetMap;
- typedef CM_UNORDERED_MAP<std::string, cmMakefile*> MakefileMap;
+ using TargetMap = std::unordered_map<std::string, cmTarget*>;
+ using GeneratorTargetMap =
+ std::unordered_map<std::string, cmGeneratorTarget*>;
+ using MakefileMap = std::unordered_map<std::string, cmMakefile*>;
+ using LocalGeneratorMap = std::unordered_map<std::string, cmLocalGenerator*>;
// Map efficiently from target name to cmTarget instance.
// Do not use this structure for looping over all targets.
// It contains both normal and globally visible imported targets.
@@ -496,6 +577,11 @@ private:
// It may not contain all of them (see note in IndexMakefile method).
MakefileMap MakefileSearchIndex;
+ // Map efficiently from source directory path to cmLocalGenerator instance.
+ // Do not use this structure for looping over all directories.
+ // Its order is not deterministic.
+ LocalGeneratorMap LocalGeneratorSearchIndex;
+
cmMakefile* TryCompileOuterMakefile;
// If you add a new map here, make sure it is copied
// in EnableLanguagesFromGenerator
@@ -524,6 +610,10 @@ private:
virtual void ForceLinkerLanguages();
+ bool CheckTargetsForMissingSources() const;
+ bool CheckTargetsForType() const;
+ bool CheckTargetsForPchCompilePdb() const;
+
void CreateLocalGenerators();
void CheckCompilerIdCompatibility(cmMakefile* mf,
@@ -531,13 +621,13 @@ private:
void ComputeBuildFileGenerators();
- cmExternalMakefileProjectGenerator* ExtraGenerator;
+ std::unique_ptr<cmExternalMakefileProjectGenerator> ExtraGenerator;
// track files replaced during a Generate
std::vector<std::string> FilesReplacedDuringGenerate;
// Store computed inter-target dependencies.
- typedef std::map<cmGeneratorTarget const*, TargetDependSet> TargetDependMap;
+ using TargetDependMap = std::map<cmGeneratorTarget const*, TargetDependSet>;
TargetDependMap TargetDependencies;
friend class cmake;
@@ -548,20 +638,20 @@ private:
void ClearGeneratorMembers();
+ bool CheckCMP0037(std::string const& targetName,
+ std::string const& reason) const;
+
void IndexMakefile(cmMakefile* mf);
+ void IndexLocalGenerator(cmLocalGenerator* lg);
- virtual const char* GetBuildIgnoreErrorsFlag() const { return CM_NULLPTR; }
+ virtual const char* GetBuildIgnoreErrorsFlag() const { return nullptr; }
// Cache directory content and target files to be built.
struct DirectoryContent
{
- long LastDiskTime;
+ long LastDiskTime = -1;
std::set<std::string> All;
std::set<std::string> Generated;
- DirectoryContent()
- : LastDiskTime(-1)
- {
- }
};
std::map<std::string, DirectoryContent> DirectoryContentMap;
@@ -573,10 +663,10 @@ private:
// track targets to issue CMP0068 warning for.
std::set<std::string> CMP0068WarnTargets;
- mutable std::map<cmSourceFile*, std::set<cmGeneratorTarget const*> >
+ mutable std::map<cmSourceFile*, std::set<cmGeneratorTarget const*>>
FilenameTargetDepends;
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
// Pool of file locks
cmFileLockPool FileLockPool;
#endif
diff --git a/Source/cmGlobalGeneratorFactory.h b/Source/cmGlobalGeneratorFactory.h
index d5a6db06e..bb5f74cca 100644
--- a/Source/cmGlobalGeneratorFactory.h
+++ b/Source/cmGlobalGeneratorFactory.h
@@ -3,7 +3,7 @@
#ifndef cmGlobalGeneratorFactory_h
#define cmGlobalGeneratorFactory_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
@@ -20,7 +20,7 @@ struct cmDocumentationEntry;
class cmGlobalGeneratorFactory
{
public:
- virtual ~cmGlobalGeneratorFactory() {}
+ virtual ~cmGlobalGeneratorFactory() = default;
/** Create a GlobalGenerator */
virtual cmGlobalGenerator* CreateGlobalGenerator(const std::string& n,
@@ -30,13 +30,20 @@ public:
virtual void GetDocumentation(cmDocumentationEntry& entry) const = 0;
/** Get the names of the current registered generators */
- virtual void GetGenerators(std::vector<std::string>& names) const = 0;
+ virtual std::vector<std::string> GetGeneratorNames() const = 0;
+ virtual std::vector<std::string> GetGeneratorNamesWithPlatform() const = 0;
/** Determine whether or not this generator supports toolsets */
virtual bool SupportsToolset() const = 0;
/** Determine whether or not this generator supports platforms */
virtual bool SupportsPlatform() const = 0;
+
+ /** Get the list of supported platforms name for this generator */
+ virtual std::vector<std::string> GetKnownPlatforms() const = 0;
+
+ /** If the generator suports platforms, get its default. */
+ virtual std::string GetDefaultPlatformName() const = 0;
};
template <class T>
@@ -45,31 +52,46 @@ class cmGlobalGeneratorSimpleFactory : public cmGlobalGeneratorFactory
public:
/** Create a GlobalGenerator */
cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
- cmake* cm) const CM_OVERRIDE
+ cmake* cm) const override
{
if (name != T::GetActualName()) {
- return CM_NULLPTR;
+ return nullptr;
}
return new T(cm);
}
/** Get the documentation entry for this factory */
- void GetDocumentation(cmDocumentationEntry& entry) const CM_OVERRIDE
+ void GetDocumentation(cmDocumentationEntry& entry) const override
{
T::GetDocumentation(entry);
}
/** Get the names of the current registered generators */
- void GetGenerators(std::vector<std::string>& names) const CM_OVERRIDE
+ std::vector<std::string> GetGeneratorNames() const override
{
+ std::vector<std::string> names;
names.push_back(T::GetActualName());
+ return names;
+ }
+ std::vector<std::string> GetGeneratorNamesWithPlatform() const override
+ {
+ return std::vector<std::string>();
}
/** Determine whether or not this generator supports toolsets */
- bool SupportsToolset() const CM_OVERRIDE { return T::SupportsToolset(); }
+ bool SupportsToolset() const override { return T::SupportsToolset(); }
/** Determine whether or not this generator supports platforms */
- bool SupportsPlatform() const CM_OVERRIDE { return T::SupportsPlatform(); }
+ bool SupportsPlatform() const override { return T::SupportsPlatform(); }
+
+ /** Get the list of supported platforms name for this generator */
+ std::vector<std::string> GetKnownPlatforms() const override
+ {
+ // default is no platform supported
+ return std::vector<std::string>();
+ }
+
+ std::string GetDefaultPlatformName() const override { return std::string(); }
};
#endif
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 42ab4d98a..5a708abbc 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -2,31 +2,43 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalGhsMultiGenerator.h"
-#include "cmsys/SystemTools.hxx"
+#include <algorithm>
+#include <cstring>
+#include <map>
+#include <ostream>
+#include <utility>
#include "cmAlgorithms.h"
#include "cmDocumentationEntry.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
-#include "cmGhsMultiTargetGenerator.h"
+#include "cmGhsMultiGpj.h"
+#include "cmLocalGenerator.h"
#include "cmLocalGhsMultiGenerator.h"
#include "cmMakefile.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
#include "cmVersion.h"
+#include "cmake.h"
const char* cmGlobalGhsMultiGenerator::FILE_EXTENSION = ".gpj";
-const char* cmGlobalGhsMultiGenerator::DEFAULT_MAKE_PROGRAM = "gbuild";
+#ifdef __linux__
+const char* cmGlobalGhsMultiGenerator::DEFAULT_BUILD_PROGRAM = "gbuild";
+const char* cmGlobalGhsMultiGenerator::DEFAULT_TOOLSET_ROOT = "/usr/ghs";
+#elif defined(_WIN32)
+const char* cmGlobalGhsMultiGenerator::DEFAULT_BUILD_PROGRAM = "gbuild.exe";
+const char* cmGlobalGhsMultiGenerator::DEFAULT_TOOLSET_ROOT = "C:/ghs";
+#endif
cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator(cmake* cm)
: cmGlobalGenerator(cm)
- , OSDirRelative(false)
{
- this->GhsBuildCommandInitialized = false;
+ cm->GetState()->SetGhsMultiIDE(true);
}
-cmGlobalGhsMultiGenerator::~cmGlobalGhsMultiGenerator()
-{
- cmDeleteAll(TargetFolderBuildStreams);
-}
+cmGlobalGhsMultiGenerator::~cmGlobalGhsMultiGenerator() = default;
cmLocalGenerator* cmGlobalGhsMultiGenerator::CreateLocalGenerator(
cmMakefile* mf)
@@ -41,450 +53,686 @@ void cmGlobalGhsMultiGenerator::GetDocumentation(cmDocumentationEntry& entry)
"Generates Green Hills MULTI files (experimental, work-in-progress).";
}
-void cmGlobalGhsMultiGenerator::EnableLanguage(
- std::vector<std::string> const& l, cmMakefile* mf, bool optional)
+void cmGlobalGhsMultiGenerator::ComputeTargetObjectDirectory(
+ cmGeneratorTarget* gt) const
{
- mf->AddDefinition("CMAKE_SYSTEM_NAME", "GHS-MULTI");
- mf->AddDefinition("CMAKE_SYSTEM_PROCESSOR", "ARM");
-
- const std::string ghsCompRoot(GetCompRoot());
- mf->AddDefinition("GHS_COMP_ROOT", ghsCompRoot.c_str());
- std::string ghsCompRootStart =
- 0 == ghsCompRootStart.size() ? "" : ghsCompRoot + "/";
- mf->AddDefinition("CMAKE_C_COMPILER",
- std::string(ghsCompRootStart + "ccarm.exe").c_str());
- mf->AddDefinition("CMAKE_C_COMPILER_ID_RUN", "TRUE");
- mf->AddDefinition("CMAKE_C_COMPILER_ID", "GHS");
- mf->AddDefinition("CMAKE_C_COMPILER_FORCED", "TRUE");
-
- mf->AddDefinition("CMAKE_CXX_COMPILER",
- std::string(ghsCompRootStart + "cxarm.exe").c_str());
- mf->AddDefinition("CMAKE_CXX_COMPILER_ID_RUN", "TRUE");
- mf->AddDefinition("CMAKE_CXX_COMPILER_ID", "GHS");
- mf->AddDefinition("CMAKE_CXX_COMPILER_FORCED", "TRUE");
-
- if (!ghsCompRoot.empty()) {
- static const char* compPreFix = "comp_";
- std::string compFilename =
- cmsys::SystemTools::FindLastString(ghsCompRoot.c_str(), compPreFix);
- cmsys::SystemTools::ReplaceString(compFilename, compPreFix, "");
- mf->AddDefinition("CMAKE_SYSTEM_VERSION", compFilename.c_str());
- }
-
- mf->AddDefinition("GHSMULTI", "1"); // identifier for user CMake files
- this->cmGlobalGenerator::EnableLanguage(l, mf, optional);
+ // Compute full path to object file directory for this target.
+ std::string dir =
+ cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+ gt->LocalGenerator->GetTargetDirectory(gt), '/');
+ gt->ObjectDirectory = dir;
}
-bool cmGlobalGhsMultiGenerator::FindMakeProgram(cmMakefile* mf)
+bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts,
+ cmMakefile* mf)
{
- // The GHS generator knows how to lookup its build tool
- // directly instead of needing a helper module to do it, so we
- // do not actually need to put CMAKE_MAKE_PROGRAM into the cache.
- if (cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
- mf->AddDefinition("CMAKE_MAKE_PROGRAM",
- this->GetGhsBuildCommand().c_str());
+ std::string tsp; /* toolset path */
+
+ this->GetToolset(mf, tsp, ts);
+
+ /* no toolset was found */
+ if (tsp.empty()) {
+ return false;
+ }
+ if (ts.empty()) {
+ std::string message;
+ message = cmStrCat(
+ "Green Hills MULTI: -T <toolset> not specified; defaulting to \"", tsp,
+ '"');
+ cmSystemTools::Message(message);
+
+ /* store the full toolset for later use
+ * -- already done if -T<toolset> was specified
+ */
+ mf->AddCacheDefinition("CMAKE_GENERATOR_TOOLSET", tsp.c_str(),
+ "Location of generator toolset.",
+ cmStateEnums::INTERNAL);
+ }
+
+ /* set the build tool to use */
+ std::string gbuild(tsp + ((tsp.back() == '/') ? "" : "/") +
+ DEFAULT_BUILD_PROGRAM);
+ const char* prevTool = mf->GetDefinition("CMAKE_MAKE_PROGRAM");
+
+ /* check if the toolset changed from last generate */
+ if (prevTool != nullptr && (gbuild != prevTool)) {
+ std::string message =
+ cmStrCat("toolset build tool: ", gbuild,
+ "\nDoes not match the previously used build tool: ", prevTool,
+ "\nEither remove the CMakeCache.txt file and CMakeFiles "
+ "directory or choose a different binary directory.");
+ cmSystemTools::Error(message);
+ return false;
}
+
+ /* store the toolset that is being used for this build */
+ mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", gbuild.c_str(),
+ "build program to use", cmStateEnums::INTERNAL, true);
+
+ mf->AddDefinition("CMAKE_SYSTEM_VERSION", tsp);
+
return true;
}
-std::string const& cmGlobalGhsMultiGenerator::GetGhsBuildCommand()
+bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p,
+ cmMakefile* mf)
{
- if (!this->GhsBuildCommandInitialized) {
- this->GhsBuildCommandInitialized = true;
- this->GhsBuildCommand = this->FindGhsBuildCommand();
+ std::string arch;
+ if (p.empty()) {
+ cmSystemTools::Message(
+ "Green Hills MULTI: -A <arch> not specified; defaulting to \"arm\"");
+ arch = "arm";
+
+ /* store the platform name for later use
+ * -- already done if -A<arch> was specified
+ */
+ mf->AddCacheDefinition("CMAKE_GENERATOR_PLATFORM", arch.c_str(),
+ "Name of generator platform.",
+ cmStateEnums::INTERNAL);
+ } else {
+ arch = p;
}
- return this->GhsBuildCommand;
+
+ /* check if OS location has been updated by platform scripts */
+ std::string platform = mf->GetSafeDefinition("GHS_TARGET_PLATFORM");
+ std::string osdir = mf->GetSafeDefinition("GHS_OS_DIR");
+ if (cmIsOff(osdir) && platform.find("integrity") != std::string::npos) {
+ if (!this->CMakeInstance->GetIsInTryCompile()) {
+ /* required OS location is not found */
+ std::string m = cmStrCat(
+ "Green Hills MULTI: GHS_OS_DIR not specified; No OS found in \"",
+ mf->GetSafeDefinition("GHS_OS_ROOT"), '"');
+ cmSystemTools::Message(m);
+ }
+ osdir = "GHS_OS_DIR-NOT-SPECIFIED";
+ } else if (!this->CMakeInstance->GetIsInTryCompile() &&
+ cmIsOff(this->OsDir) && !cmIsOff(osdir)) {
+ /* OS location was updated by auto-selection */
+ std::string m = cmStrCat(
+ "Green Hills MULTI: GHS_OS_DIR not specified; found \"", osdir, '"');
+ cmSystemTools::Message(m);
+ }
+ this->OsDir = osdir;
+
+ // Determine GHS_BSP_NAME
+ std::string bspName = mf->GetSafeDefinition("GHS_BSP_NAME");
+
+ if (cmIsOff(bspName) && platform.find("integrity") != std::string::npos) {
+ bspName = "sim" + arch;
+ /* write back the calculate name for next time */
+ mf->AddCacheDefinition("GHS_BSP_NAME", bspName.c_str(),
+ "Name of GHS target platform.",
+ cmStateEnums::STRING, true);
+ std::string m = cmStrCat(
+ "Green Hills MULTI: GHS_BSP_NAME not specified; defaulting to \"",
+ bspName, '"');
+ cmSystemTools::Message(m);
+ }
+
+ return true;
}
-std::string cmGlobalGhsMultiGenerator::FindGhsBuildCommand()
+void cmGlobalGhsMultiGenerator::EnableLanguage(
+ std::vector<std::string> const& l, cmMakefile* mf, bool optional)
{
- std::vector<std::string> userPaths;
- userPaths.push_back(this->GetCompRoot());
- std::string makeProgram =
- cmSystemTools::FindProgram(DEFAULT_MAKE_PROGRAM, userPaths);
- if (makeProgram.empty()) {
- makeProgram = DEFAULT_MAKE_PROGRAM;
+ mf->AddDefinition("CMAKE_SYSTEM_NAME", "GHS-MULTI");
+
+ mf->AddDefinition("GHSMULTI", "1"); // identifier for user CMake files
+
+ const char* tgtPlatform = mf->GetDefinition("GHS_TARGET_PLATFORM");
+ if (!tgtPlatform) {
+ cmSystemTools::Message("Green Hills MULTI: GHS_TARGET_PLATFORM not "
+ "specified; defaulting to \"integrity\"");
+ tgtPlatform = "integrity";
}
- return makeProgram;
+
+ /* store the platform name for later use */
+ mf->AddCacheDefinition("GHS_TARGET_PLATFORM", tgtPlatform,
+ "Name of GHS target platform.", cmStateEnums::STRING);
+
+ /* store original OS location */
+ this->OsDir = mf->GetSafeDefinition("GHS_OS_DIR");
+
+ this->cmGlobalGenerator::EnableLanguage(l, mf, optional);
}
-std::string cmGlobalGhsMultiGenerator::GetCompRoot()
+bool cmGlobalGhsMultiGenerator::FindMakeProgram(cmMakefile* /*mf*/)
{
- std::string output;
-
- const std::vector<std::string> potentialDirsHardPaths(
- GetCompRootHardPaths());
- const std::vector<std::string> potentialDirsRegistry(GetCompRootRegistry());
-
- std::vector<std::string> potentialDirsComplete;
- potentialDirsComplete.insert(potentialDirsComplete.end(),
- potentialDirsHardPaths.begin(),
- potentialDirsHardPaths.end());
- potentialDirsComplete.insert(potentialDirsComplete.end(),
- potentialDirsRegistry.begin(),
- potentialDirsRegistry.end());
-
- // Use latest version
- std::string outputDirName;
- for (std::vector<std::string>::const_iterator potentialDirsCompleteIt =
- potentialDirsComplete.begin();
- potentialDirsCompleteIt != potentialDirsComplete.end();
- ++potentialDirsCompleteIt) {
- const std::string dirName(
- cmsys::SystemTools::GetFilenameName(*potentialDirsCompleteIt));
- if (dirName.compare(outputDirName) > 0) {
- output = *potentialDirsCompleteIt;
- outputDirName = dirName;
- }
- }
+ // The GHS generator only knows how to lookup its build tool
+ // during generation of the project files, but this
+ // can only be done after the toolset is specified.
- return output;
+ return true;
}
-std::vector<std::string> cmGlobalGhsMultiGenerator::GetCompRootHardPaths()
+void cmGlobalGhsMultiGenerator::GetToolset(cmMakefile* mf, std::string& tsd,
+ const std::string& ts)
{
- std::vector<std::string> output;
- cmSystemTools::Glob("C:/ghs", "comp_[^;]+", output);
- for (std::vector<std::string>::iterator outputIt = output.begin();
- outputIt != output.end(); ++outputIt) {
- *outputIt = "C:/ghs/" + *outputIt;
+ const char* ghsRoot = mf->GetDefinition("GHS_TOOLSET_ROOT");
+
+ if (!ghsRoot || ghsRoot[0] == '\0') {
+ ghsRoot = DEFAULT_TOOLSET_ROOT;
+ }
+ tsd = ghsRoot;
+
+ if (ts.empty()) {
+ std::vector<std::string> output;
+
+ // Use latest? version
+ if (tsd.back() != '/') {
+ tsd += "/";
+ }
+ cmSystemTools::Glob(tsd, "comp_[^;]+", output);
+
+ if (output.empty()) {
+ std::string msg =
+ "No GHS toolsets found in GHS_TOOLSET_ROOT \"" + tsd + "\".";
+ cmSystemTools::Error(msg);
+ tsd = "";
+ } else {
+ tsd += output.back();
+ }
+ } else {
+ std::string tryPath;
+ tryPath = cmSystemTools::CollapseFullPath(ts, tsd);
+ if (!cmSystemTools::FileExists(tryPath)) {
+ std::string msg = "GHS toolset \"" + tryPath + "\" not found.";
+ cmSystemTools::Error(msg);
+ tsd = "";
+ } else {
+ tsd = tryPath;
+ }
}
- return output;
}
-std::vector<std::string> cmGlobalGhsMultiGenerator::GetCompRootRegistry()
+void cmGlobalGhsMultiGenerator::WriteFileHeader(std::ostream& fout)
{
- std::vector<std::string> output(2);
- cmsys::SystemTools::ReadRegistryValue(
- "HKEY_LOCAL_"
- "MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\"
- "Windows\\CurrentVersion\\Uninstall\\"
- "GreenHillsSoftwared771f1b4;InstallLocation",
- output[0]);
- cmsys::SystemTools::ReadRegistryValue(
- "HKEY_LOCAL_"
- "MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\"
- "Windows\\CurrentVersion\\Uninstall\\"
- "GreenHillsSoftware9881cef6;InstallLocation",
- output[1]);
- return output;
+ fout << "#!gbuild" << std::endl;
+ fout << "#" << std::endl
+ << "# CMAKE generated file: DO NOT EDIT!" << std::endl
+ << "# Generated by \"" << GetActualName() << "\""
+ << " Generator, CMake Version " << cmVersion::GetMajorVersion() << "."
+ << cmVersion::GetMinorVersion() << std::endl
+ << "#" << std::endl
+ << std::endl;
}
-void cmGlobalGhsMultiGenerator::OpenBuildFileStream(
- std::string const& filepath, cmGeneratedFileStream** filestream)
+void cmGlobalGhsMultiGenerator::WriteCustomRuleBOD(std::ostream& fout)
{
- // Get a stream where to generate things.
- if (NULL == *filestream) {
- *filestream = new cmGeneratedFileStream(filepath.c_str());
- if (NULL != *filestream) {
- OpenBuildFileStream(*filestream);
- }
- }
+ fout << "Commands {\n"
+ " Custom_Rule_Command {\n"
+ " name = \"Custom Rule Command\"\n"
+ " exec = \"";
+#ifdef _WIN32
+ fout << "cmd.exe";
+#else
+ fout << "/bin/sh";
+#endif
+ fout << "\"\n"
+ " options = {\"SpecialOptions\"}\n"
+ " }\n"
+ "}\n";
+
+ fout << "\n\n";
+ fout << "FileTypes {\n"
+ " CmakeRule {\n"
+ " name = \"Custom Rule\"\n"
+ " action = \"&Run\"\n"
+ " extensions = {\"";
+#ifdef _WIN32
+ fout << "bat";
+#else
+ fout << "sh";
+#endif
+ fout << "\"}\n"
+ " grepable = false\n"
+ " command = \"Custom Rule Command\"\n"
+ " commandLine = \"$COMMAND ";
+#ifdef _WIN32
+ fout << "/c";
+#endif
+ fout << " $INPUTFILE\"\n"
+ " progress = \"Processing Custom Rule\"\n"
+ " promoteToFirstPass = true\n"
+ " outputType = \"None\"\n"
+ " color = \"#800080\"\n"
+ " }\n"
+ "}\n";
}
-void cmGlobalGhsMultiGenerator::OpenBuildFileStream(
- cmGeneratedFileStream* filestream)
+void cmGlobalGhsMultiGenerator::WriteCustomTargetBOD(std::ostream& fout)
{
- *filestream << "#!gbuild" << std::endl;
+ fout << "FileTypes {\n"
+ " CmakeTarget {\n"
+ " name = \"Custom Target\"\n"
+ " action = \"&Execute\"\n"
+ " grepable = false\n"
+ " outputType = \"None\"\n"
+ " color = \"#800080\"\n"
+ " }\n"
+ "}\n";
}
-void cmGlobalGhsMultiGenerator::OpenBuildFileStream()
+void cmGlobalGhsMultiGenerator::WriteTopLevelProject(std::ostream& fout,
+ cmLocalGenerator* root)
{
- // Compute GHS MULTI's build file path.
- std::string buildFilePath =
- this->GetCMakeInstance()->GetHomeOutputDirectory();
- buildFilePath += "/";
- buildFilePath += "default";
- buildFilePath += FILE_EXTENSION;
-
- this->Open(std::string(""), buildFilePath, &this->TargetFolderBuildStreams);
- OpenBuildFileStream(GetBuildFileStream());
-
- char const* osDir =
- this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR");
- if (NULL == osDir) {
- osDir = "";
- cmSystemTools::Error("GHS_OS_DIR cache variable must be set");
- } else {
- this->GetCMakeInstance()->MarkCliAsUsed("GHS_OS_DIR");
- }
- std::string fOSDir(this->trimQuotes(osDir));
- std::replace(fOSDir.begin(), fOSDir.end(), '\\', '/');
- if (!fOSDir.empty() && ('c' == fOSDir[0] || 'C' == fOSDir[0])) {
- this->OSDirRelative = false;
- } else {
- this->OSDirRelative = true;
- }
+ this->WriteFileHeader(fout);
+ this->WriteMacros(fout, root);
+ this->WriteHighLevelDirectives(root, fout);
+ GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fout);
+
+ fout << "# Top Level Project File" << std::endl;
- char const* bspName =
+ // Specify BSP option if supplied by user
+ const char* bspName =
this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME");
- if (NULL == bspName) {
- bspName = "";
- cmSystemTools::Error("GHS_BSP_NAME cache variable must be set");
- } else {
- this->GetCMakeInstance()->MarkCliAsUsed("GHS_BSP_NAME");
+ if (!cmIsOff(bspName)) {
+ fout << " -bsp " << bspName << std::endl;
}
- std::string fBspName(this->trimQuotes(bspName));
- std::replace(fBspName.begin(), fBspName.end(), '\\', '/');
- this->WriteMacros();
- this->WriteHighLevelDirectives();
-
- GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, this->GetBuildFileStream());
- this->WriteDisclaimer(this->GetBuildFileStream());
- *this->GetBuildFileStream() << "# Top Level Project File" << std::endl;
- if (!fBspName.empty()) {
- *this->GetBuildFileStream() << " -bsp " << fBspName << std::endl;
+
+ // Specify OS DIR if supplied by user
+ // -- not all platforms require this entry in the project file
+ if (!cmIsOff(this->OsDir)) {
+ const char* osDirOption =
+ this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR_OPTION");
+ std::replace(this->OsDir.begin(), this->OsDir.end(), '\\', '/');
+ fout << " ";
+ if (cmIsOff(osDirOption)) {
+ fout << "";
+ } else {
+ fout << osDirOption;
+ }
+ fout << "\"" << this->OsDir << "\"" << std::endl;
}
- this->WriteCompilerOptions(fOSDir);
}
-void cmGlobalGhsMultiGenerator::CloseBuildFileStream(
- cmGeneratedFileStream** filestream)
+void cmGlobalGhsMultiGenerator::WriteSubProjects(std::ostream& fout,
+ std::string& all_target)
{
- if (filestream) {
- delete *filestream;
- *filestream = NULL;
- } else {
- cmSystemTools::Error("Build file stream was not open.");
+ fout << "CMakeFiles/" << all_target << " [Project]" << std::endl;
+ // All known targets
+ for (cmGeneratorTarget const* target : this->ProjectTargets) {
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ target->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ target->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ (target->GetType() == cmStateEnums::GLOBAL_TARGET &&
+ target->GetName() != GetInstallTargetName())) {
+ continue;
+ }
+ fout << "CMakeFiles/" << target->GetName() + ".tgt" + FILE_EXTENSION
+ << " [Project]" << std::endl;
}
}
-void cmGlobalGhsMultiGenerator::Generate()
+void cmGlobalGhsMultiGenerator::WriteProjectLine(
+ std::ostream& fout, cmGeneratorTarget const* target, cmLocalGenerator* root,
+ std::string& rootBinaryDir)
{
- this->cmGlobalGenerator::Generate();
-
- if (!this->LocalGenerators.empty()) {
- this->OpenBuildFileStream();
-
- // Build all the folder build files
- for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
- cmLocalGhsMultiGenerator* lg =
- static_cast<cmLocalGhsMultiGenerator*>(this->LocalGenerators[i]);
- std::vector<cmGeneratorTarget*> tgts = lg->GetGeneratorTargets();
- this->UpdateBuildFiles(tgts);
+ const char* projName = target->GetProperty("GENERATOR_FILE_NAME");
+ const char* projType = target->GetProperty("GENERATOR_FILE_NAME_EXT");
+ if (projName && projType) {
+ cmLocalGenerator* lg = target->GetLocalGenerator();
+ std::string dir = lg->GetCurrentBinaryDirectory();
+ dir = root->MaybeConvertToRelativePath(rootBinaryDir, dir);
+ if (dir == ".") {
+ dir.clear();
+ } else {
+ if (dir.back() != '/') {
+ dir += "/";
+ }
}
- }
- cmDeleteAll(TargetFolderBuildStreams);
- this->TargetFolderBuildStreams.clear();
+ std::string projFile = dir + projName + FILE_EXTENSION;
+ fout << projFile;
+ fout << " " << projType << std::endl;
+ } else {
+ /* Should never happen */
+ std::string message =
+ "The project file for target [" + target->GetName() + "] is missing.\n";
+ cmSystemTools::Error(message);
+ fout << "{comment} " << target->GetName() << " [missing project file]\n";
+ }
}
-void cmGlobalGhsMultiGenerator::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)
+void cmGlobalGhsMultiGenerator::WriteTargets(cmLocalGenerator* root)
{
- makeCommand.push_back(
- this->SelectMakeProgram(makeProgram, this->GetGhsBuildCommand()));
-
- makeCommand.insert(makeCommand.end(), makeOptions.begin(),
- makeOptions.end());
- if (!targetName.empty()) {
- if (targetName == "clean") {
- makeCommand.push_back("-clean");
+ std::string rootBinaryDir =
+ cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeFiles");
+
+ // All known targets
+ for (cmGeneratorTarget const* target : this->ProjectTargets) {
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ target->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ target->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ (target->GetType() == cmStateEnums::GLOBAL_TARGET &&
+ target->GetName() != GetInstallTargetName())) {
+ continue;
+ }
+
+ // create target build file
+ std::string name = cmStrCat(target->GetName(), ".tgt", FILE_EXTENSION);
+ std::string fname = cmStrCat(rootBinaryDir, "/", name);
+ cmGeneratedFileStream fbld(fname);
+ fbld.SetCopyIfDifferent(true);
+ this->WriteFileHeader(fbld);
+ GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fbld);
+ std::vector<cmGeneratorTarget const*> build;
+ if (ComputeTargetBuildOrder(target, build)) {
+ cmSystemTools::Error(
+ cmStrCat("The inter-target dependency graph for target [",
+ target->GetName(), "] had a cycle.\n"));
} else {
- makeCommand.push_back(targetName);
+ for (auto& tgt : build) {
+ WriteProjectLine(fbld, tgt, root, rootBinaryDir);
+ }
}
+ fbld.Close();
}
}
-void cmGlobalGhsMultiGenerator::WriteMacros()
+void cmGlobalGhsMultiGenerator::WriteAllTarget(
+ cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators,
+ std::string& all_target)
{
- char const* ghsGpjMacros =
- this->GetCMakeInstance()->GetCacheDefinition("GHS_GPJ_MACROS");
- if (NULL != ghsGpjMacros) {
- std::vector<std::string> expandedList;
- cmSystemTools::ExpandListArgument(std::string(ghsGpjMacros), expandedList);
- for (std::vector<std::string>::const_iterator expandedListI =
- expandedList.begin();
- expandedListI != expandedList.end(); ++expandedListI) {
- *this->GetBuildFileStream() << "macro " << *expandedListI << std::endl;
+ this->ProjectTargets.clear();
+
+ // create target build file
+ all_target = root->GetProjectName() + "." + this->GetAllTargetName() +
+ ".tgt" + FILE_EXTENSION;
+ std::string fname =
+ root->GetCurrentBinaryDirectory() + "/CMakeFiles/" + all_target;
+ cmGeneratedFileStream fbld(fname);
+ fbld.SetCopyIfDifferent(true);
+ this->WriteFileHeader(fbld);
+ GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fbld);
+
+ // Collect all targets under this root generator and the transitive
+ // closure of their dependencies.
+ TargetDependSet projectTargets;
+ TargetDependSet originalTargets;
+ this->GetTargetSets(projectTargets, originalTargets, root, generators);
+ OrderedTargetDependSet sortedProjectTargets(projectTargets, "");
+ std::vector<cmGeneratorTarget const*> defaultTargets;
+ for (cmGeneratorTarget const* t : sortedProjectTargets) {
+ /* save list of all targets in sorted order */
+ this->ProjectTargets.push_back(t);
+ }
+ for (cmGeneratorTarget const* t : sortedProjectTargets) {
+ if (t->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
+ }
+ if (!cmIsOn(t->GetProperty("EXCLUDE_FROM_ALL"))) {
+ defaultTargets.push_back(t);
}
}
+ std::vector<cmGeneratorTarget const*> build;
+ if (ComputeTargetBuildOrder(defaultTargets, build)) {
+ std::string message = "The inter-target dependency graph for project [" +
+ root->GetProjectName() + "] had a cycle.\n";
+ cmSystemTools::Error(message);
+ } else {
+ // determine the targets for ALL target
+ std::string rootBinaryDir =
+ cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeFiles");
+ for (cmGeneratorTarget const* target : build) {
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ target->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ target->GetType() == cmStateEnums::SHARED_LIBRARY) {
+ continue;
+ }
+ this->WriteProjectLine(fbld, target, root, rootBinaryDir);
+ }
+ }
+ fbld.Close();
}
-void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives()
+void cmGlobalGhsMultiGenerator::Generate()
{
- *this->GetBuildFileStream() << "primaryTarget=arm_integrity.tgt"
- << std::endl;
- char const* const customization =
- this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION");
- if (NULL != customization && strlen(customization) > 0) {
- *this->GetBuildFileStream()
- << "customization=" << trimQuotes(customization) << std::endl;
- this->GetCMakeInstance()->MarkCliAsUsed("GHS_CUSTOMIZATION");
+ std::string fname;
+
+ // first do the superclass method
+ this->cmGlobalGenerator::Generate();
+
+ // output top-level projects
+ for (auto& it : this->ProjectMap) {
+ this->OutputTopLevelProject(it.second[0], it.second);
}
-}
-void cmGlobalGhsMultiGenerator::WriteCompilerOptions(std::string const& fOSDir)
-{
- *this->GetBuildFileStream() << " -os_dir=\"" << fOSDir << "\""
- << std::endl;
+ // create custom rule BOD file
+ fname = this->GetCMakeInstance()->GetHomeOutputDirectory() +
+ "/CMakeFiles/custom_rule.bod";
+ cmGeneratedFileStream frule(fname);
+ frule.SetCopyIfDifferent(true);
+ this->WriteFileHeader(frule);
+ this->WriteCustomRuleBOD(frule);
+ frule.Close();
+
+ // create custom target BOD file
+ fname = this->GetCMakeInstance()->GetHomeOutputDirectory() +
+ "/CMakeFiles/custom_target.bod";
+ cmGeneratedFileStream ftarget(fname);
+ ftarget.SetCopyIfDifferent(true);
+ this->WriteFileHeader(ftarget);
+ this->WriteCustomTargetBOD(ftarget);
+ ftarget.Close();
}
-void cmGlobalGhsMultiGenerator::WriteDisclaimer(std::ostream* os)
+void cmGlobalGhsMultiGenerator::OutputTopLevelProject(
+ cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators)
{
- (*os) << "#" << std::endl
- << "# CMAKE generated file: DO NOT EDIT!" << std::endl
- << "# Generated by \"" << GetActualName() << "\""
- << " Generator, CMake Version " << cmVersion::GetMajorVersion() << "."
- << cmVersion::GetMinorVersion() << std::endl
- << "#" << std::endl;
+ std::string fname;
+ std::string all_target;
+
+ if (generators.empty()) {
+ return;
+ }
+
+ /* Name top-level projects as filename.top.gpj to avoid name clashes
+ * with target projects. This avoid the issue where the project has
+ * the same name as the executable target.
+ */
+ fname = cmStrCat(root->GetCurrentBinaryDirectory(), '/',
+ root->GetProjectName(), ".top", FILE_EXTENSION);
+
+ cmGeneratedFileStream top(fname);
+ top.SetCopyIfDifferent(true);
+ this->WriteTopLevelProject(top, root);
+
+ this->WriteAllTarget(root, generators, all_target);
+ this->WriteTargets(root);
+
+ this->WriteSubProjects(top, all_target);
+ top.Close();
}
-void cmGlobalGhsMultiGenerator::AddFilesUpToPath(
- cmGeneratedFileStream* mainBuildFile,
- std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams,
- char const* homeOutputDirectory, std::string const& path,
- GhsMultiGpj::Types projType, std::string const& relPath)
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalGhsMultiGenerator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& /*config*/, bool /*fast*/, int jobs, bool /*verbose*/,
+ std::vector<std::string> const& makeOptions)
{
- std::string workingPath(path);
- cmSystemTools::ConvertToUnixSlashes(workingPath);
- std::vector<cmsys::String> splitPath =
- cmSystemTools::SplitString(workingPath);
- std::string workingRelPath(relPath);
- cmSystemTools::ConvertToUnixSlashes(workingRelPath);
- if (!workingRelPath.empty()) {
- workingRelPath += "/";
+ GeneratedMakeCommand makeCommand = {};
+ std::string gbuild;
+ if (const char* gbuildCached =
+ this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM")) {
+ gbuild = gbuildCached;
+ }
+ makeCommand.Add(this->SelectMakeProgram(makeProgram, gbuild));
+
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ makeCommand.Add("-parallel");
+ if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ makeCommand.Add(std::to_string(jobs));
+ }
}
- std::string pathUpTo;
- for (std::vector<cmsys::String>::const_iterator splitPathI =
- splitPath.begin();
- splitPath.end() != splitPathI; ++splitPathI) {
- pathUpTo += *splitPathI;
- if (targetFolderBuildStreams->end() ==
- targetFolderBuildStreams->find(pathUpTo)) {
- AddFilesUpToPathNewBuildFile(
- mainBuildFile, targetFolderBuildStreams, homeOutputDirectory, pathUpTo,
- splitPath.begin() == splitPathI, workingRelPath, projType);
+
+ makeCommand.Add(makeOptions.begin(), makeOptions.end());
+
+ /* determine which top-project file to use */
+ std::string proj = projectName + ".top" + FILE_EXTENSION;
+ std::vector<std::string> files;
+ cmSystemTools::Glob(projectDir, ".*\\.top\\.gpj", files);
+ if (!files.empty()) {
+ /* if multiple top-projects are found in build directory
+ * then prefer projectName top-project.
+ */
+ if (!cmContains(files, proj)) {
+ proj = files.at(0);
+ }
+ }
+
+ makeCommand.Add("-top", proj);
+ if (!targetNames.empty()) {
+ if (cmContains(targetNames, "clean")) {
+ makeCommand.Add("-clean");
+ } else {
+ for (const auto& tname : targetNames) {
+ if (!tname.empty()) {
+ makeCommand.Add(tname + ".tgt.gpj");
+ }
+ }
}
- AddFilesUpToPathAppendNextFile(targetFolderBuildStreams, pathUpTo,
- splitPathI, splitPath.end(), projType);
- pathUpTo += "/";
+ } else {
+ /* transform name to default build */;
+ std::string all = proj;
+ all.replace(all.end() - 7, all.end(),
+ std::string(this->GetAllTargetName()) + ".tgt.gpj");
+ makeCommand.Add(all);
}
+ return { makeCommand };
}
-void cmGlobalGhsMultiGenerator::Open(
- std::string const& mapKeyName, std::string const& fileName,
- std::map<std::string, cmGeneratedFileStream*>* fileMap)
+void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout,
+ cmLocalGenerator* root)
{
- if (fileMap->end() == fileMap->find(fileName)) {
- cmGeneratedFileStream* temp(new cmGeneratedFileStream);
- temp->open(fileName.c_str());
- (*fileMap)[mapKeyName] = temp;
+ fout << "macro PROJ_NAME=" << root->GetProjectName() << std::endl;
+ char const* ghsGpjMacros =
+ this->GetCMakeInstance()->GetCacheDefinition("GHS_GPJ_MACROS");
+ if (nullptr != ghsGpjMacros) {
+ std::vector<std::string> expandedList =
+ cmExpandedList(std::string(ghsGpjMacros));
+ for (std::string const& arg : expandedList) {
+ fout << "macro " << arg << std::endl;
+ }
}
}
-void cmGlobalGhsMultiGenerator::AddFilesUpToPathNewBuildFile(
- cmGeneratedFileStream* mainBuildFile,
- std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams,
- char const* homeOutputDirectory, std::string const& pathUpTo,
- bool const isFirst, std::string const& relPath,
- GhsMultiGpj::Types const projType)
+void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(
+ cmLocalGenerator* root, std::ostream& fout)
{
- // create folders up to file path
- std::string absPath = std::string(homeOutputDirectory) + "/" + relPath;
- std::string newPath = absPath + pathUpTo;
- if (!cmSystemTools::FileExists(newPath.c_str())) {
- cmSystemTools::MakeDirectory(newPath.c_str());
+ /* set primary target */
+ std::string tgt;
+ const char* t =
+ this->GetCMakeInstance()->GetCacheDefinition("GHS_PRIMARY_TARGET");
+ if (t && *t != '\0') {
+ tgt = t;
+ this->GetCMakeInstance()->MarkCliAsUsed("GHS_PRIMARY_TARGET");
+ } else {
+ const char* a =
+ this->GetCMakeInstance()->GetCacheDefinition("CMAKE_GENERATOR_PLATFORM");
+ const char* p =
+ this->GetCMakeInstance()->GetCacheDefinition("GHS_TARGET_PLATFORM");
+ tgt = cmStrCat((a ? a : ""), '_', (p ? p : ""), ".tgt");
}
- // Write out to filename for first time
- std::string relFilename(GetFileNameFromPath(pathUpTo));
- std::string absFilename = absPath + relFilename;
- Open(pathUpTo, absFilename, targetFolderBuildStreams);
- OpenBuildFileStream((*targetFolderBuildStreams)[pathUpTo]);
- GhsMultiGpj::WriteGpjTag(projType, (*targetFolderBuildStreams)[pathUpTo]);
- WriteDisclaimer((*targetFolderBuildStreams)[pathUpTo]);
-
- // Add to main build file
- if (isFirst) {
- *mainBuildFile << relFilename << " ";
- GhsMultiGpj::WriteGpjTag(projType, mainBuildFile);
+ fout << "primaryTarget=" << tgt << std::endl;
+ fout << "customization=" << root->GetBinaryDirectory()
+ << "/CMakeFiles/custom_rule.bod" << std::endl;
+ fout << "customization=" << root->GetBinaryDirectory()
+ << "/CMakeFiles/custom_target.bod" << std::endl;
+
+ char const* const customization =
+ this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION");
+ if (nullptr != customization && strlen(customization) > 0) {
+ fout << "customization=" << this->TrimQuotes(customization) << std::endl;
+ this->GetCMakeInstance()->MarkCliAsUsed("GHS_CUSTOMIZATION");
}
}
-void cmGlobalGhsMultiGenerator::AddFilesUpToPathAppendNextFile(
- std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams,
- std::string const& pathUpTo,
- std::vector<cmsys::String>::const_iterator splitPathI,
- std::vector<cmsys::String>::const_iterator end,
- GhsMultiGpj::Types const projType)
+std::string cmGlobalGhsMultiGenerator::TrimQuotes(std::string const& str)
{
- std::vector<cmsys::String>::const_iterator splitPathNextI = splitPathI + 1;
- if (end != splitPathNextI &&
- targetFolderBuildStreams->end() ==
- targetFolderBuildStreams->find(pathUpTo + "/" + *splitPathNextI)) {
- std::string nextFilename(*splitPathNextI);
- nextFilename = GetFileNameFromPath(nextFilename);
- *(*targetFolderBuildStreams)[pathUpTo] << nextFilename << " ";
- GhsMultiGpj::WriteGpjTag(projType, (*targetFolderBuildStreams)[pathUpTo]);
+ std::string result;
+ result.reserve(str.size());
+ for (const char* ch = str.c_str(); *ch != '\0'; ++ch) {
+ if (*ch != '"') {
+ result += *ch;
+ }
}
+ return result;
}
-std::string cmGlobalGhsMultiGenerator::GetFileNameFromPath(
- std::string const& path)
+bool cmGlobalGhsMultiGenerator::TargetCompare::operator()(
+ cmGeneratorTarget const* l, cmGeneratorTarget const* r) const
{
- std::string output(path);
- if (!path.empty()) {
- cmSystemTools::ConvertToUnixSlashes(output);
- std::vector<cmsys::String> splitPath = cmSystemTools::SplitString(output);
- output += "/" + splitPath.back() + FILE_EXTENSION;
+ // Make sure a given named target is ordered first,
+ // e.g. to set ALL_BUILD as the default active project.
+ // When the empty string is named this is a no-op.
+ if (r->GetName() == this->First) {
+ return false;
+ }
+ if (l->GetName() == this->First) {
+ return true;
}
- return output;
+ return l->GetName() < r->GetName();
}
-void cmGlobalGhsMultiGenerator::UpdateBuildFiles(
- std::vector<cmGeneratorTarget*> tgts)
+cmGlobalGhsMultiGenerator::OrderedTargetDependSet::OrderedTargetDependSet(
+ TargetDependSet const& targets, std::string const& first)
+ : derived(TargetCompare(first))
{
- for (std::vector<cmGeneratorTarget*>::iterator tgtsI = tgts.begin();
- tgtsI != tgts.end(); ++tgtsI) {
- const cmGeneratorTarget* tgt = *tgtsI;
- if (IsTgtForBuild(tgt)) {
- std::string folderName = tgt->GetEffectiveFolderName();
- if (this->TargetFolderBuildStreams.end() ==
- this->TargetFolderBuildStreams.find(folderName)) {
- this->AddFilesUpToPath(
- GetBuildFileStream(), &this->TargetFolderBuildStreams,
- this->GetCMakeInstance()->GetHomeOutputDirectory(), folderName,
- GhsMultiGpj::PROJECT);
- }
- std::vector<cmsys::String> splitPath = cmSystemTools::SplitString(
- cmGhsMultiTargetGenerator::GetRelBuildFileName(tgt));
- std::string foldNameRelBuildFile(*(splitPath.end() - 2) + "/" +
- splitPath.back());
- *this->TargetFolderBuildStreams[folderName] << foldNameRelBuildFile
- << " ";
- GhsMultiGpj::WriteGpjTag(cmGhsMultiTargetGenerator::GetGpjTag(tgt),
- this->TargetFolderBuildStreams[folderName]);
- }
- }
+ this->insert(targets.begin(), targets.end());
}
-bool cmGlobalGhsMultiGenerator::IsTgtForBuild(const cmGeneratorTarget* tgt)
+bool cmGlobalGhsMultiGenerator::ComputeTargetBuildOrder(
+ cmGeneratorTarget const* tgt, std::vector<cmGeneratorTarget const*>& build)
{
- const std::string config =
- tgt->Target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
- std::vector<cmSourceFile*> tgtSources;
- tgt->GetSourceFiles(tgtSources, config);
- bool tgtInBuild = true;
- char const* excludeFromAll = tgt->GetProperty("EXCLUDE_FROM_ALL");
- if (NULL != excludeFromAll && '1' == excludeFromAll[0] &&
- '\0' == excludeFromAll[1]) {
- tgtInBuild = false;
+ std::vector<cmGeneratorTarget const*> t{ tgt };
+ return ComputeTargetBuildOrder(t, build);
+}
+
+bool cmGlobalGhsMultiGenerator::ComputeTargetBuildOrder(
+ std::vector<cmGeneratorTarget const*>& tgt,
+ std::vector<cmGeneratorTarget const*>& build)
+{
+ std::set<cmGeneratorTarget const*> temp;
+ std::set<cmGeneratorTarget const*> perm;
+
+ for (auto ti : tgt) {
+ bool r = VisitTarget(temp, perm, build, ti);
+ if (r) {
+ return r;
+ }
}
- return !tgtSources.empty() && tgtInBuild;
+ return false;
}
-std::string cmGlobalGhsMultiGenerator::trimQuotes(std::string const& str)
+bool cmGlobalGhsMultiGenerator::VisitTarget(
+ std::set<cmGeneratorTarget const*>& temp,
+ std::set<cmGeneratorTarget const*>& perm,
+ std::vector<cmGeneratorTarget const*>& order, cmGeneratorTarget const* ti)
{
- std::string result;
- result.reserve(str.size());
- for (const char* ch = str.c_str(); *ch != '\0'; ++ch) {
- if (*ch != '"') {
- result += *ch;
+ /* check if permanent mark is set*/
+ if (perm.find(ti) == perm.end()) {
+ /* set temporary mark; check if revisit*/
+ if (temp.insert(ti).second) {
+ /* sort targets lexicographically to ensure that nodes are always visited
+ * in the same order */
+ OrderedTargetDependSet sortedTargets(this->GetTargetDirectDepends(ti),
+ "");
+ for (auto& di : sortedTargets) {
+ if (this->VisitTarget(temp, perm, order, di)) {
+ return true;
+ }
+ }
+ /* mark as complete; insert into beginning of list*/
+ perm.insert(ti);
+ order.push_back(ti);
+ return false;
}
+ /* revisiting item - not a DAG */
+ return true;
}
- return result;
+ /* already complete */
+ return false;
}
diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h
index 7b3eebbdf..ccfe07382 100644
--- a/Source/cmGlobalGhsMultiGenerator.h
+++ b/Source/cmGlobalGhsMultiGenerator.h
@@ -3,35 +3,44 @@
#ifndef cmGhsMultiGenerator_h
#define cmGhsMultiGenerator_h
-#include "cmGlobalGenerator.h"
+#include <iosfwd>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
-#include "cmGhsMultiGpj.h"
+#include "cmGlobalGenerator.h"
#include "cmGlobalGeneratorFactory.h"
+#include "cmTargetDepend.h"
-class cmGeneratedFileStream;
+class cmGeneratorTarget;
+class cmLocalGenerator;
+class cmMakefile;
+class cmake;
+struct cmDocumentationEntry;
class cmGlobalGhsMultiGenerator : public cmGlobalGenerator
{
public:
- /// The default name of GHS MULTI's build file. Typically: monolith.gpj.
+ // The default filename extension of GHS MULTI's build files.
static const char* FILE_EXTENSION;
cmGlobalGhsMultiGenerator(cmake* cm);
- ~cmGlobalGhsMultiGenerator();
+ ~cmGlobalGhsMultiGenerator() override;
static cmGlobalGeneratorFactory* NewFactory()
{
return new cmGlobalGeneratorSimpleFactory<cmGlobalGhsMultiGenerator>();
}
- ///! create the correct local generator
- virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf);
+ //! create the correct local generator
+ cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
/// @return the name of this generator.
static std::string GetActualName() { return "Green Hills MULTI"; }
- ///! Get the name for this generator
- virtual std::string GetName() const { return this->GetActualName(); }
+ //! Get the name for this generator
+ std::string GetName() const override { return GetActualName(); }
/// Overloaded methods. @see cmGlobalGenerator::GetDocumentation()
static void GetDocumentation(cmDocumentationEntry& entry);
@@ -40,94 +49,110 @@ public:
* Utilized by the generator factory to determine if this generator
* supports toolsets.
*/
- static bool SupportsToolset() { return false; }
+ static bool SupportsToolset() { return true; }
/**
* Utilized by the generator factory to determine if this generator
* supports platforms.
*/
- static bool SupportsPlatform() { return false; }
+ static bool SupportsPlatform() { return true; }
+
+ // Toolset / Platform Support
+ bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override;
+ bool SetGeneratorPlatform(std::string const& p, 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);
+ * Try to determine system information such as shared library
+ * extension, pthreads, byte order etc.
+ */
+ void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
+ bool optional) override;
/*
- * Determine what program to use for building the project.
- */
- bool FindMakeProgram(cmMakefile* mf) CM_OVERRIDE;
+ * Determine what program to use for building the project.
+ */
+ bool FindMakeProgram(cmMakefile* mf) override;
- cmGeneratedFileStream* GetBuildFileStream()
- {
- return this->TargetFolderBuildStreams[""];
- }
+ void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override;
+
+ // Write the common disclaimer text at the top of each build file.
+ void WriteFileHeader(std::ostream& fout);
- static void OpenBuildFileStream(std::string const& filepath,
- cmGeneratedFileStream** filestream);
- static void OpenBuildFileStream(cmGeneratedFileStream* filestream);
- static void CloseBuildFileStream(cmGeneratedFileStream** filestream);
- /// Write the common disclaimer text at the top of each build file.
- static void WriteDisclaimer(std::ostream* os);
- std::vector<std::string> GetLibDirs() { return this->LibDirs; }
-
- static void AddFilesUpToPath(
- cmGeneratedFileStream* mainBuildFile,
- std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams,
- char const* homeOutputDirectory, std::string const& path,
- GhsMultiGpj::Types projType, std::string const& relPath = "");
- static void Open(std::string const& mapKeyName, std::string const& fileName,
- std::map<std::string, cmGeneratedFileStream*>* fileMap);
-
- static std::string trimQuotes(std::string const& str);
- inline bool IsOSDirRelative() { return this->OSDirRelative; }
+ const char* GetInstallTargetName() const override { return "install"; }
protected:
- virtual void Generate();
- 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 Generate() override;
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
private:
- std::string const& GetGhsBuildCommand();
- std::string FindGhsBuildCommand();
- std::string GetCompRoot();
- std::vector<std::string> GetCompRootHardPaths();
- std::vector<std::string> GetCompRootRegistry();
- void OpenBuildFileStream();
-
- void WriteMacros();
- void WriteHighLevelDirectives();
- void WriteCompilerOptions(std::string const& fOSDir);
-
- static void AddFilesUpToPathNewBuildFile(
- cmGeneratedFileStream* mainBuildFile,
- std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams,
- char const* homeOutputDirectory, std::string const& pathUpTo, bool isFirst,
- std::string const& relPath, GhsMultiGpj::Types projType);
- static void AddFilesUpToPathAppendNextFile(
- std::map<std::string, cmGeneratedFileStream*>* targetFolderBuildStreams,
- std::string const& pathUpTo,
- std::vector<cmsys::String>::const_iterator splitPathI,
- std::vector<cmsys::String>::const_iterator end,
- GhsMultiGpj::Types projType);
- static std::string GetFileNameFromPath(std::string const& path);
- void UpdateBuildFiles(std::vector<cmGeneratorTarget*> tgts);
- bool IsTgtForBuild(const cmGeneratorTarget* tgt);
-
- std::vector<cmGeneratedFileStream*> TargetSubProjects;
- std::map<std::string, cmGeneratedFileStream*> TargetFolderBuildStreams;
-
- std::vector<std::string> LibDirs;
-
- bool OSDirRelative;
- bool GhsBuildCommandInitialized;
- std::string GhsBuildCommand;
- static const char* DEFAULT_MAKE_PROGRAM;
+ void GetToolset(cmMakefile* mf, std::string& tsd, const std::string& ts);
+
+ /* top-level project */
+ void OutputTopLevelProject(cmLocalGenerator* root,
+ std::vector<cmLocalGenerator*>& generators);
+ void WriteTopLevelProject(std::ostream& fout, cmLocalGenerator* root);
+ void WriteMacros(std::ostream& fout, cmLocalGenerator* root);
+ void WriteHighLevelDirectives(cmLocalGenerator* root, std::ostream& fout);
+ void WriteSubProjects(std::ostream& fout, std::string& all_target);
+ void WriteTargets(cmLocalGenerator* root);
+ void WriteProjectLine(std::ostream& fout, cmGeneratorTarget const* target,
+ cmLocalGenerator* root, std::string& rootBinaryDir);
+ void WriteCustomRuleBOD(std::ostream& fout);
+ void WriteCustomTargetBOD(std::ostream& fout);
+ void WriteAllTarget(cmLocalGenerator* root,
+ std::vector<cmLocalGenerator*>& generators,
+ std::string& all_target);
+
+ std::string TrimQuotes(std::string const& str);
+
+ std::string OsDir;
+ static const char* DEFAULT_BUILD_PROGRAM;
+ static const char* DEFAULT_TOOLSET_ROOT;
+
+ bool ComputeTargetBuildOrder(cmGeneratorTarget const* tgt,
+ std::vector<cmGeneratorTarget const*>& build);
+ bool ComputeTargetBuildOrder(std::vector<cmGeneratorTarget const*>& tgt,
+ std::vector<cmGeneratorTarget const*>& build);
+ bool VisitTarget(std::set<cmGeneratorTarget const*>& temp,
+ std::set<cmGeneratorTarget const*>& perm,
+ std::vector<cmGeneratorTarget const*>& order,
+ cmGeneratorTarget const* ti);
+
+ std::vector<cmGeneratorTarget const*> ProjectTargets;
+
+ // Target sorting
+ class TargetSet : public std::set<cmGeneratorTarget const*>
+ {
+ };
+ class TargetCompare
+ {
+ std::string First;
+
+ public:
+ TargetCompare(std::string first)
+ : First(std::move(first))
+ {
+ }
+ bool operator()(cmGeneratorTarget const* l,
+ cmGeneratorTarget const* r) const;
+ };
+ class OrderedTargetDependSet;
+};
+
+class cmGlobalGhsMultiGenerator::OrderedTargetDependSet
+ : public std::multiset<cmTargetDepend,
+ cmGlobalGhsMultiGenerator::TargetCompare>
+{
+ using derived =
+ std::multiset<cmTargetDepend, cmGlobalGhsMultiGenerator::TargetCompare>;
+
+public:
+ using TargetDependSet = cmGlobalGenerator::TargetDependSet;
+ OrderedTargetDependSet(TargetDependSet const&, std::string const& first);
};
#endif
diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx
index 18c45e0d8..ff5428868 100644
--- a/Source/cmGlobalJOMMakefileGenerator.cxx
+++ b/Source/cmGlobalJOMMakefileGenerator.cxx
@@ -6,6 +6,7 @@
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmState.h"
+#include "cmake.h"
cmGlobalJOMMakefileGenerator::cmGlobalJOMMakefileGenerator(cmake* cm)
: cmGlobalUnixMakefileGenerator3(cm)
@@ -52,3 +53,29 @@ void cmGlobalJOMMakefileGenerator::PrintCompilerAdvice(
}
this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar);
}
+
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalJOMMakefileGenerator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions)
+{
+ std::vector<std::string> jomMakeOptions;
+
+ // Since we have full control over the invocation of JOM, let us
+ // make it quiet.
+ jomMakeOptions.push_back(this->MakeSilentFlag);
+ cmAppend(jomMakeOptions, makeOptions);
+
+ // JOM does parallel builds by default, the -j is only needed if a specific
+ // number is given
+ // see https://github.com/qt-labs/jom/blob/v1.1.2/src/jomlib/options.cpp
+ if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ jobs = cmake::NO_BUILD_PARALLEL_LEVEL;
+ }
+
+ return cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
+ makeProgram, projectName, projectDir, targetNames, config, fast, jobs,
+ verbose, jomMakeOptions);
+}
diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h
index 2e8ee2939..fc39ddf42 100644
--- a/Source/cmGlobalJOMMakefileGenerator.h
+++ b/Source/cmGlobalJOMMakefileGenerator.h
@@ -3,6 +3,8 @@
#ifndef cmGlobalJOMMakefileGenerator_h
#define cmGlobalJOMMakefileGenerator_h
+#include <iosfwd>
+
#include "cmGlobalUnixMakefileGenerator3.h"
/** \class cmGlobalJOMMakefileGenerator
@@ -18,8 +20,8 @@ public:
{
return new cmGlobalGeneratorSimpleFactory<cmGlobalJOMMakefileGenerator>();
}
- ///! Get the name for the generator.
- virtual std::string GetName() const
+ //! Get the name for the generator.
+ std::string GetName() const override
{
return cmGlobalJOMMakefileGenerator::GetActualName();
}
@@ -34,12 +36,20 @@ 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;
+
+protected:
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
private:
void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
- const char* envVar) const;
+ const char* envVar) const override;
};
#endif
diff --git a/Source/cmGlobalKdevelopGenerator.cxx b/Source/cmGlobalKdevelopGenerator.cxx
deleted file mode 100644
index e72c6e384..000000000
--- a/Source/cmGlobalKdevelopGenerator.cxx
+++ /dev/null
@@ -1,606 +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 <map>
-#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 (std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator
- it = this->GlobalGenerator->GetProjectMap().begin();
- it != this->GlobalGenerator->GetProjectMap().end(); ++it) {
- 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 (std::vector<cmLocalGenerator*>::const_iterator lg = lgs.begin();
- lg != lgs.end(); lg++) {
- std::vector<cmGeneratorTarget*> const& targets =
- (*lg)->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::const_iterator ti =
- targets.begin();
- ti != targets.end(); ti++) {
- if ((*ti)->GetType() == cmStateEnums::EXECUTABLE) {
- executable = (*ti)->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 (std::vector<cmLocalGenerator*>::const_iterator it = lgs.begin();
- it != lgs.end(); it++) {
- cmMakefile* makefile = (*it)->GetMakefile();
- const std::vector<std::string>& listFiles = makefile->GetListFiles();
- for (std::vector<std::string>::const_iterator lt = listFiles.begin();
- lt != listFiles.end(); lt++) {
- tmp = *lt;
- 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()) ==
- CM_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") == CM_NULLPTR)) {
- cmakeFilePattern += tmp + ";";
- }
- }
- }
-
- // get all sources
- std::vector<cmGeneratorTarget*> targets = (*it)->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator ti = targets.begin();
- ti != targets.end(); ti++) {
- std::vector<cmSourceFile*> sources;
- cmGeneratorTarget* gt = *ti;
- gt->GetSourceFiles(sources, gt->Target->GetMakefile()->GetSafeDefinition(
- "CMAKE_BUILD_TYPE"));
- for (std::vector<cmSourceFile*>::const_iterator si = sources.begin();
- si != sources.end(); si++) {
- tmp = (*si)->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()) ==
- CM_NULLPTR) &&
- (cmSystemTools::GetFilenameExtension(tmp) != ".moc")) {
- files.insert(tmp);
-
- // check if there's a matching header around
- for (std::vector<std::string>::const_iterator ext = hdrExts.begin();
- ext != hdrExts.end(); ++ext) {
- std::string hname = headerBasename;
- hname += ".";
- hname += *ext;
- if (cmSystemTools::FileExists(hname.c_str())) {
- cmSystemTools::ReplaceString(hname, projectDir.c_str(), "");
- files.insert(hname);
- break;
- }
- }
- }
- }
- for (std::vector<std::string>::const_iterator lt = listFiles.begin();
- lt != listFiles.end(); lt++) {
- tmp = *lt;
- cmSystemTools::ReplaceString(tmp, projectDir.c_str(), "");
- if ((tmp[0] != '/') &&
- (strstr(tmp.c_str(), cmake::GetCMakeFilesDirectoryPostSlash()) ==
- CM_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::set<std::string>::const_iterator it = files.begin();
- it != files.end(); it++) {
- // get the full path to the file
- tmp = cmSystemTools::CollapseFullPath(*it, 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::vector<std::string>::const_iterator it = lines.begin();
- it != lines.end(); it++) {
- const char* line = (*it).c_str();
- // skip these tags as they are always replaced
- if ((strstr(line, "<projectdirectory>") != CM_NULLPTR) ||
- (strstr(line, "<projectmanagement>") != CM_NULLPTR) ||
- (strstr(line, "<absoluteprojectpath>") != CM_NULLPTR) ||
- (strstr(line, "<filelistdirectory>") != CM_NULLPTR) ||
- (strstr(line, "<buildtool>") != CM_NULLPTR) ||
- (strstr(line, "<builddir>") != CM_NULLPTR)) {
- continue;
- }
-
- // output the line from the file if it is not one of the above tags
- fout << *it << "\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::vector<std::string>::const_iterator dirIt =
- this->Blacklist.begin();
- dirIt != this->Blacklist.end(); ++dirIt) {
- xml.Element("path", *dirIt);
- }
- 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 bdcf8a190..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"
-
-#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() CM_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/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx
index 3f223824a..ae9d5a768 100644
--- a/Source/cmGlobalMSYSMakefileGenerator.cxx
+++ b/Source/cmGlobalMSYSMakefileGenerator.cxx
@@ -7,6 +7,7 @@
#include "cmDocumentationEntry.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmState.h"
#include "cmake.h"
@@ -23,8 +24,7 @@ cmGlobalMSYSMakefileGenerator::cmGlobalMSYSMakefileGenerator(cmake* cm)
std::string cmGlobalMSYSMakefileGenerator::FindMinGW(
std::string const& makeloc)
{
- std::string fstab = makeloc;
- fstab += "/../etc/fstab";
+ std::string fstab = cmStrCat(makeloc, "/../etc/fstab");
cmsys::ifstream fin(fstab.c_str());
std::string path;
std::string mount;
@@ -33,8 +33,7 @@ std::string cmGlobalMSYSMakefileGenerator::FindMinGW(
fin >> path;
fin >> mount;
if (mount == "/mingw") {
- mingwBin = path;
- mingwBin += "/bin";
+ mingwBin = cmStrCat(path, "/bin");
}
}
return mingwBin;
@@ -44,9 +43,10 @@ void cmGlobalMSYSMakefileGenerator::EnableLanguage(
std::vector<std::string> const& l, cmMakefile* mf, bool optional)
{
this->FindMakeProgram(mf);
- std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+ const std::string& makeProgram =
+ mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
std::vector<std::string> locations;
- std::string makeloc = cmSystemTools::GetProgramPath(makeProgram.c_str());
+ std::string makeloc = cmSystemTools::GetProgramPath(makeProgram);
locations.push_back(this->FindMinGW(makeloc));
locations.push_back(makeloc);
locations.push_back("/mingw/bin");
@@ -67,16 +67,16 @@ void cmGlobalMSYSMakefileGenerator::EnableLanguage(
rc = trc;
}
mf->AddDefinition("MSYS", "1");
- mf->AddDefinition("CMAKE_GENERATOR_CC", gcc.c_str());
- mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx.c_str());
- mf->AddDefinition("CMAKE_GENERATOR_RC", rc.c_str());
+ mf->AddDefinition("CMAKE_GENERATOR_CC", gcc);
+ mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx);
+ mf->AddDefinition("CMAKE_GENERATOR_RC", rc);
this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
if (!mf->IsSet("CMAKE_AR") && !this->CMakeInstance->GetIsInTryCompile() &&
!(1 == l.size() && l[0] == "NONE")) {
cmSystemTools::Error(
- "CMAKE_AR was not found, please set to archive program. ",
- mf->GetDefinition("CMAKE_AR"));
+ "CMAKE_AR was not found, please set to archive program. " +
+ mf->GetSafeDefinition("CMAKE_AR"));
}
}
diff --git a/Source/cmGlobalMSYSMakefileGenerator.h b/Source/cmGlobalMSYSMakefileGenerator.h
index 23dbc5e31..d6e4847fe 100644
--- a/Source/cmGlobalMSYSMakefileGenerator.h
+++ b/Source/cmGlobalMSYSMakefileGenerator.h
@@ -19,7 +19,7 @@ public:
return new cmGlobalGeneratorSimpleFactory<cmGlobalMSYSMakefileGenerator>();
}
- ///! Get the name for the generator.
+ //! Get the name for the generator.
virtual std::string GetName() const
{
return cmGlobalMSYSMakefileGenerator::GetActualName();
diff --git a/Source/cmGlobalMinGWMakefileGenerator.cxx b/Source/cmGlobalMinGWMakefileGenerator.cxx
index 3c3a5d1dc..d9fc50530 100644
--- a/Source/cmGlobalMinGWMakefileGenerator.cxx
+++ b/Source/cmGlobalMinGWMakefileGenerator.cxx
@@ -6,6 +6,7 @@
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmState.h"
+#include "cmake.h"
cmGlobalMinGWMakefileGenerator::cmGlobalMinGWMakefileGenerator(cmake* cm)
: cmGlobalUnixMakefileGenerator3(cm)
@@ -22,7 +23,8 @@ void cmGlobalMinGWMakefileGenerator::EnableLanguage(
std::vector<std::string> const& l, cmMakefile* mf, bool optional)
{
this->FindMakeProgram(mf);
- std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+ const std::string& makeProgram =
+ mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
std::vector<std::string> locations;
locations.push_back(cmSystemTools::GetProgramPath(makeProgram));
locations.push_back("/mingw/bin");
@@ -42,9 +44,9 @@ void cmGlobalMinGWMakefileGenerator::EnableLanguage(
if (!trc.empty()) {
rc = trc;
}
- mf->AddDefinition("CMAKE_GENERATOR_CC", gcc.c_str());
- mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx.c_str());
- mf->AddDefinition("CMAKE_GENERATOR_RC", rc.c_str());
+ mf->AddDefinition("CMAKE_GENERATOR_CC", gcc);
+ mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx);
+ mf->AddDefinition("CMAKE_GENERATOR_RC", rc);
this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
}
diff --git a/Source/cmGlobalMinGWMakefileGenerator.h b/Source/cmGlobalMinGWMakefileGenerator.h
index a994c9295..15297e3c7 100644
--- a/Source/cmGlobalMinGWMakefileGenerator.h
+++ b/Source/cmGlobalMinGWMakefileGenerator.h
@@ -19,7 +19,7 @@ public:
return new cmGlobalGeneratorSimpleFactory<
cmGlobalMinGWMakefileGenerator>();
}
- ///! Get the name for the generator.
+ //! Get the name for the generator.
virtual std::string GetName() const
{
return cmGlobalMinGWMakefileGenerator::GetActualName();
diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx
index da683fb39..2273c00ac 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.cxx
+++ b/Source/cmGlobalNMakeMakefileGenerator.cxx
@@ -6,6 +6,7 @@
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmState.h"
+#include "cmake.h"
cmGlobalNMakeMakefileGenerator::cmGlobalNMakeMakefileGenerator(cmake* cm)
: cmGlobalUnixMakefileGenerator3(cm)
@@ -52,3 +53,40 @@ void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice(
}
this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar);
}
+
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalNMakeMakefileGenerator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int /*jobs*/, bool verbose,
+ std::vector<std::string> const& makeOptions)
+{
+ std::vector<std::string> nmakeMakeOptions;
+
+ // Since we have full control over the invocation of nmake, let us
+ // make it quiet.
+ nmakeMakeOptions.push_back(this->MakeSilentFlag);
+ cmAppend(nmakeMakeOptions, makeOptions);
+
+ return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
+ makeProgram, projectName, projectDir, targetNames, config, fast,
+ cmake::NO_BUILD_PARALLEL_LEVEL, verbose, nmakeMakeOptions);
+}
+
+void cmGlobalNMakeMakefileGenerator::PrintBuildCommandAdvice(std::ostream& os,
+ int jobs) const
+{
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ // nmake does not support parallel build level
+ // see https://msdn.microsoft.com/en-us/library/afyyse50.aspx
+
+ /* clang-format off */
+ os <<
+ "Warning: NMake does not support parallel builds. "
+ "Ignoring parallel build command line option.\n";
+ /* clang-format on */
+ }
+
+ this->cmGlobalUnixMakefileGenerator3::PrintBuildCommandAdvice(
+ os, cmake::NO_BUILD_PARALLEL_LEVEL);
+}
diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h
index 6eb21249d..4586b77b1 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.h
+++ b/Source/cmGlobalNMakeMakefileGenerator.h
@@ -3,6 +3,8 @@
#ifndef cmGlobalNMakeMakefileGenerator_h
#define cmGlobalNMakeMakefileGenerator_h
+#include <iosfwd>
+
#include "cmGlobalUnixMakefileGenerator3.h"
/** \class cmGlobalNMakeMakefileGenerator
@@ -19,15 +21,15 @@ public:
return new cmGlobalGeneratorSimpleFactory<
cmGlobalNMakeMakefileGenerator>();
}
- ///! Get the name for the generator.
- virtual std::string GetName() const
+ //! Get the name for the generator.
+ std::string GetName() const override
{
return cmGlobalNMakeMakefileGenerator::GetActualName();
}
static std::string GetActualName() { return "NMake Makefiles"; }
/** Get encoding used by generator for makefile files */
- codecvt::Encoding GetMakefileEncoding() const CM_OVERRIDE
+ codecvt::Encoding GetMakefileEncoding() const override
{
return codecvt::ANSI;
}
@@ -39,12 +41,22 @@ 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;
+
+protected:
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
+
+ void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override;
private:
void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
- const char* envVar) const;
+ const char* envVar) const override;
};
#endif
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 2eef9e492..da21d6c2a 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -2,16 +2,19 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalNinjaGenerator.h"
-#include "cm_jsoncpp_reader.h"
-#include "cm_jsoncpp_value.h"
-#include "cm_jsoncpp_writer.h"
-#include "cmsys/FStream.hxx"
#include <algorithm>
-#include <ctype.h>
-#include <functional>
+#include <cctype>
+#include <cstdio>
#include <iterator>
#include <sstream>
-#include <stdio.h>
+
+#include <cm/memory>
+
+#include "cmsys/FStream.hxx"
+
+#include "cm_jsoncpp_reader.h"
+#include "cm_jsoncpp_value.h"
+#include "cm_jsoncpp_writer.h"
#include "cmAlgorithms.h"
#include "cmDocumentationEntry.h"
@@ -19,20 +22,24 @@
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpressionEvaluationFile.h"
#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmNinjaLinkLineComputer.h"
#include "cmOutputConverter.h"
+#include "cmRange.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
#include "cmVersion.h"
-#include "cm_auto_ptr.hxx"
#include "cmake.h"
class cmLinkLineComputer;
@@ -90,43 +97,18 @@ std::string cmGlobalNinjaGenerator::EncodeRuleName(std::string const& name)
// Ninja rule names must match "[a-zA-Z0-9_.-]+". Use ".xx" to encode
// "." and all invalid characters as hexadecimal.
std::string encoded;
- for (std::string::const_iterator i = name.begin(); i != name.end(); ++i) {
- if (isalnum(*i) || *i == '_' || *i == '-') {
- encoded += *i;
+ for (char i : name) {
+ if (isalnum(i) || i == '_' || i == '-') {
+ encoded += i;
} else {
char buf[16];
- sprintf(buf, ".%02x", static_cast<unsigned int>(*i));
+ sprintf(buf, ".%02x", static_cast<unsigned int>(i));
encoded += buf;
}
}
return encoded;
}
-static bool IsIdentChar(char c)
-{
- return ('a' <= c && c <= 'z') ||
- ('+' <= c && c <= '9') || // +,-./ and numbers
- ('A' <= c && c <= 'Z') || (c == '_') || (c == '$') || (c == '\\') ||
- (c == ' ') || (c == ':');
-}
-
-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()) {
- static unsigned VarNum = 0;
- std::ostringstream names;
- names << "ident" << VarNum++;
- vars << names.str() << " = " << ident << "\n";
- return "$" + names.str();
- }
- std::string result = ident;
- cmSystemTools::ReplaceString(result, " ", "$ ");
- cmSystemTools::ReplaceString(result, ":", "$:");
- return result;
-}
-
std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string& lit)
{
std::string result = lit;
@@ -137,293 +119,256 @@ std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string& lit)
std::string cmGlobalNinjaGenerator::EncodePath(const std::string& path)
{
- std::string result = path; // NOLINT(clang-tidy)
+ std::string result = path;
#ifdef _WIN32
if (this->IsGCCOnWindows())
std::replace(result.begin(), result.end(), '\\', '/');
else
std::replace(result.begin(), result.end(), '/', '\\');
#endif
- return EncodeLiteral(result);
+ result = EncodeLiteral(result);
+ cmSystemTools::ReplaceString(result, " ", "$ ");
+ cmSystemTools::ReplaceString(result, ":", "$:");
+ return result;
}
-void cmGlobalNinjaGenerator::WriteBuild(
- std::ostream& os, const std::string& comment, const std::string& rule,
- const cmNinjaDeps& outputs, const cmNinjaDeps& implicitOuts,
- const cmNinjaDeps& explicitDeps, const cmNinjaDeps& implicitDeps,
- const cmNinjaDeps& orderOnlyDeps, const cmNinjaVars& variables,
- const std::string& rspfile, int cmdLineLimit, bool* usedResponseFile)
+void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
+ cmNinjaBuild const& build,
+ int cmdLineLimit,
+ bool* usedResponseFile)
{
// Make sure there is a rule.
- if (rule.empty()) {
- cmSystemTools::Error("No rule for WriteBuildStatement! called "
- "with comment: ",
- comment.c_str());
+ if (build.Rule.empty()) {
+ cmSystemTools::Error("No rule for WriteBuild! called with comment: " +
+ build.Comment);
return;
}
// Make sure there is at least one output file.
- if (outputs.empty()) {
- cmSystemTools::Error("No output files for WriteBuildStatement! called "
- "with comment: ",
- comment.c_str());
+ if (build.Outputs.empty()) {
+ cmSystemTools::Error(
+ "No output files for WriteBuild! called with comment: " + build.Comment);
return;
}
- cmGlobalNinjaGenerator::WriteComment(os, comment);
-
- std::string arguments;
-
- // TODO: Better formatting for when there are multiple input/output files.
+ cmGlobalNinjaGenerator::WriteComment(os, build.Comment);
- // Write explicit dependencies.
- for (cmNinjaDeps::const_iterator i = explicitDeps.begin();
- i != explicitDeps.end(); ++i) {
- arguments += " " + EncodeIdent(EncodePath(*i), os);
- }
-
- // Write implicit dependencies.
- if (!implicitDeps.empty()) {
- arguments += " |";
- for (cmNinjaDeps::const_iterator i = implicitDeps.begin();
- i != implicitDeps.end(); ++i) {
- arguments += " " + EncodeIdent(EncodePath(*i), os);
+ // Write output files.
+ std::string buildStr("build");
+ {
+ // Write explicit outputs
+ for (std::string const& output : build.Outputs) {
+ buildStr += " " + EncodePath(output);
+ if (this->ComputingUnknownDependencies) {
+ this->CombinedBuildOutputs.insert(output);
+ }
}
- }
-
- // Write order-only dependencies.
- if (!orderOnlyDeps.empty()) {
- arguments += " ||";
- for (cmNinjaDeps::const_iterator i = orderOnlyDeps.begin();
- i != orderOnlyDeps.end(); ++i) {
- arguments += " " + EncodeIdent(EncodePath(*i), os);
+ // Write implicit outputs
+ if (!build.ImplicitOuts.empty()) {
+ buildStr += " |";
+ for (std::string const& implicitOut : build.ImplicitOuts) {
+ buildStr += " " + EncodePath(implicitOut);
+ }
}
+ buildStr += ":";
+
+ // Write the rule.
+ buildStr += " ";
+ buildStr += build.Rule;
}
- arguments += "\n";
+ std::string arguments;
+ {
+ // TODO: Better formatting for when there are multiple input/output files.
- std::string build;
+ // Write explicit dependencies.
+ for (std::string const& explicitDep : build.ExplicitDeps) {
+ arguments += " " + EncodePath(explicitDep);
+ }
- // Write outputs files.
- build += "build";
- for (cmNinjaDeps::const_iterator i = outputs.begin(); i != outputs.end();
- ++i) {
- build += " " + EncodeIdent(EncodePath(*i), os);
- if (this->ComputingUnknownDependencies) {
- this->CombinedBuildOutputs.insert(*i);
+ // Write implicit dependencies.
+ if (!build.ImplicitDeps.empty()) {
+ arguments += " |";
+ for (std::string const& implicitDep : build.ImplicitDeps) {
+ arguments += " " + EncodePath(implicitDep);
+ }
}
- }
- if (!implicitOuts.empty()) {
- build += " |";
- for (cmNinjaDeps::const_iterator i = implicitOuts.begin();
- i != implicitOuts.end(); ++i) {
- build += " " + EncodeIdent(EncodePath(*i), os);
+
+ // Write order-only dependencies.
+ if (!build.OrderOnlyDeps.empty()) {
+ arguments += " ||";
+ for (std::string const& orderOnlyDep : build.OrderOnlyDeps) {
+ arguments += " " + EncodePath(orderOnlyDep);
+ }
}
- }
- build += ":";
- // Write the rule.
- build += " " + rule;
+ arguments += "\n";
+ }
// Write the variables bound to this build statement.
- std::ostringstream variable_assignments;
- for (cmNinjaVars::const_iterator i = variables.begin(); i != variables.end();
- ++i) {
- cmGlobalNinjaGenerator::WriteVariable(variable_assignments, i->first,
- i->second, "", 1);
- }
+ std::string assignments;
+ {
+ std::ostringstream variable_assignments;
+ for (auto const& variable : build.Variables) {
+ cmGlobalNinjaGenerator::WriteVariable(
+ variable_assignments, variable.first, variable.second, "", 1);
+ }
- // check if a response file rule should be used
- std::string buildstr = build;
- std::string assignments = variable_assignments.str();
- const std::string& args = arguments;
- bool useResponseFile = false;
- if (cmdLineLimit < 0 ||
- (cmdLineLimit > 0 &&
- (args.size() + buildstr.size() + assignments.size() + 1000) >
- static_cast<size_t>(cmdLineLimit))) {
- variable_assignments.str(std::string());
- cmGlobalNinjaGenerator::WriteVariable(variable_assignments, "RSP_FILE",
- rspfile, "", 1);
- assignments += variable_assignments.str();
- useResponseFile = true;
- }
- if (usedResponseFile) {
- *usedResponseFile = useResponseFile;
+ // check if a response file rule should be used
+ assignments = variable_assignments.str();
+ bool useResponseFile = false;
+ if (cmdLineLimit < 0 ||
+ (cmdLineLimit > 0 &&
+ (arguments.size() + buildStr.size() + assignments.size() + 1000) >
+ static_cast<size_t>(cmdLineLimit))) {
+ variable_assignments.str(std::string());
+ cmGlobalNinjaGenerator::WriteVariable(variable_assignments, "RSP_FILE",
+ build.RspFile, "", 1);
+ assignments += variable_assignments.str();
+ useResponseFile = true;
+ }
+ if (usedResponseFile) {
+ *usedResponseFile = useResponseFile;
+ }
}
- os << buildstr << args << assignments;
-}
-
-void cmGlobalNinjaGenerator::WritePhonyBuild(
- std::ostream& os, const std::string& comment, const cmNinjaDeps& outputs,
- const cmNinjaDeps& explicitDeps, const cmNinjaDeps& implicitDeps,
- const cmNinjaDeps& orderOnlyDeps, const cmNinjaVars& variables)
-{
- this->WriteBuild(os, comment, "phony", outputs,
- /*implicitOuts=*/cmNinjaDeps(), explicitDeps, implicitDeps,
- orderOnlyDeps, variables);
+ os << buildStr << arguments << assignments << "\n";
}
void cmGlobalNinjaGenerator::AddCustomCommandRule()
{
- this->AddRule("CUSTOM_COMMAND", "$COMMAND", "$DESC",
- "Rule for running custom commands.",
- /*depfile*/ "",
- /*deptype*/ "",
- /*rspfile*/ "",
- /*rspcontent*/ "",
- /*restat*/ "", // bound on each build statement as needed
- /*generator*/ false);
+ cmNinjaRule rule("CUSTOM_COMMAND");
+ rule.Command = "$COMMAND";
+ rule.Description = "$DESC";
+ rule.Comment = "Rule for running custom commands.";
+ this->AddRule(rule);
}
void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
const std::string& command, const std::string& description,
- const std::string& comment, const std::string& depfile, bool uses_terminal,
- bool restat, const cmNinjaDeps& outputs, const cmNinjaDeps& deps,
- const cmNinjaDeps& orderOnly)
+ const std::string& comment, const std::string& depfile,
+ const std::string& job_pool, bool uses_terminal, bool restat,
+ const cmNinjaDeps& outputs, const cmNinjaDeps& explicitDeps,
+ const cmNinjaDeps& orderOnlyDeps)
{
- std::string cmd = command; // NOLINT(clang-tidy)
-#ifdef _WIN32
- if (cmd.empty())
- // TODO Shouldn't an empty command be handled by ninja?
- cmd = "cmd.exe /c";
-#endif
-
this->AddCustomCommandRule();
- cmNinjaVars vars;
- vars["COMMAND"] = cmd;
- vars["DESC"] = EncodeLiteral(description);
- if (restat) {
- vars["restat"] = "1";
- }
- if (uses_terminal && SupportsConsolePool()) {
- vars["pool"] = "console";
- }
- if (!depfile.empty()) {
- vars["depfile"] = depfile;
+ {
+ cmNinjaBuild build("CUSTOM_COMMAND");
+ build.Comment = comment;
+ build.Outputs = outputs;
+ build.ExplicitDeps = explicitDeps;
+ build.OrderOnlyDeps = orderOnlyDeps;
+
+ cmNinjaVars& vars = build.Variables;
+ {
+ std::string cmd = command; // NOLINT(*)
+#ifdef _WIN32
+ if (cmd.empty())
+ // TODO Shouldn't an empty command be handled by ninja?
+ cmd = "cmd.exe /c";
+#endif
+ vars["COMMAND"] = std::move(cmd);
+ }
+ vars["DESC"] = EncodeLiteral(description);
+ if (restat) {
+ vars["restat"] = "1";
+ }
+ if (uses_terminal && SupportsConsolePool()) {
+ vars["pool"] = "console";
+ } else if (!job_pool.empty()) {
+ vars["pool"] = job_pool;
+ }
+ if (!depfile.empty()) {
+ vars["depfile"] = depfile;
+ }
+ this->WriteBuild(*this->BuildFileStream, build);
}
- this->WriteBuild(*this->BuildFileStream, comment, "CUSTOM_COMMAND", outputs,
- /*implicitOuts=*/cmNinjaDeps(), deps, cmNinjaDeps(),
- orderOnly, vars);
if (this->ComputingUnknownDependencies) {
// we need to track every dependency that comes in, since we are trying
// to find dependencies that are side effects of build commands
- for (cmNinjaDeps::const_iterator i = deps.begin(); i != deps.end(); ++i) {
- this->CombinedCustomCommandExplicitDependencies.insert(*i);
+ for (std::string const& dep : explicitDeps) {
+ this->CombinedCustomCommandExplicitDependencies.insert(dep);
}
}
}
void cmGlobalNinjaGenerator::AddMacOSXContentRule()
{
- cmLocalGenerator* lg = this->LocalGenerators[0];
-
- std::ostringstream cmd;
- cmd << lg->ConvertToOutputFormat(cmSystemTools::GetCMakeCommand(),
- cmOutputConverter::SHELL)
- << " -E copy $in $out";
-
- this->AddRule("COPY_OSX_CONTENT", cmd.str(), "Copying OS X Content $out",
- "Rule for copying OS X bundle content file.",
- /*depfile*/ "",
- /*deptype*/ "",
- /*rspfile*/ "",
- /*rspcontent*/ "",
- /*restat*/ "",
- /*generator*/ false);
+ cmNinjaRule rule("COPY_OSX_CONTENT");
+ rule.Command = CMakeCmd() + " -E copy $in $out";
+ rule.Description = "Copying OS X Content $out";
+ rule.Comment = "Rule for copying OS X bundle content file.";
+ this->AddRule(rule);
}
-void cmGlobalNinjaGenerator::WriteMacOSXContentBuild(const std::string& input,
- const std::string& output)
+void cmGlobalNinjaGenerator::WriteMacOSXContentBuild(std::string input,
+ std::string output)
{
this->AddMacOSXContentRule();
-
- cmNinjaDeps outputs;
- outputs.push_back(output);
- cmNinjaDeps deps;
- deps.push_back(input);
- cmNinjaVars vars;
-
- this->WriteBuild(*this->BuildFileStream, "", "COPY_OSX_CONTENT", outputs,
- /*implicitOuts=*/cmNinjaDeps(), deps, cmNinjaDeps(),
- cmNinjaDeps(), cmNinjaVars());
+ {
+ cmNinjaBuild build("COPY_OSX_CONTENT");
+ build.Outputs.push_back(std::move(output));
+ build.ExplicitDeps.push_back(std::move(input));
+ this->WriteBuild(*this->BuildFileStream, build);
+ }
}
-void cmGlobalNinjaGenerator::WriteRule(
- std::ostream& os, const std::string& name, const std::string& command,
- const std::string& description, const std::string& comment,
- const std::string& depfile, const std::string& deptype,
- const std::string& rspfile, const std::string& rspcontent,
- const std::string& restat, bool generator)
+void cmGlobalNinjaGenerator::WriteRule(std::ostream& os,
+ cmNinjaRule const& rule)
{
+ // -- Parameter checks
// Make sure the rule has a name.
- if (name.empty()) {
- cmSystemTools::Error("No name given for WriteRuleStatement! called "
- "with comment: ",
- comment.c_str());
+ if (rule.Name.empty()) {
+ cmSystemTools::Error("No name given for WriteRule! called with comment: " +
+ rule.Comment);
return;
}
// Make sure a command is given.
- if (command.empty()) {
- cmSystemTools::Error("No command given for WriteRuleStatement! called "
- "with comment: ",
- comment.c_str());
+ if (rule.Command.empty()) {
+ cmSystemTools::Error(
+ "No command given for WriteRule! called with comment: " + rule.Comment);
return;
}
- cmGlobalNinjaGenerator::WriteComment(os, comment);
-
- // Write the rule.
- os << "rule " << name << "\n";
-
- // Write the depfile if any.
- if (!depfile.empty()) {
- cmGlobalNinjaGenerator::Indent(os, 1);
- os << "depfile = " << depfile << "\n";
- }
-
- // Write the deptype if any.
- if (!deptype.empty()) {
- cmGlobalNinjaGenerator::Indent(os, 1);
- os << "deps = " << deptype << "\n";
+ // Make sure response file content is given
+ if (!rule.RspFile.empty() && rule.RspContent.empty()) {
+ cmSystemTools::Error("rspfile but no rspfile_content given for WriteRule! "
+ "called with comment: " +
+ rule.Comment);
+ return;
}
- // Write the command.
- cmGlobalNinjaGenerator::Indent(os, 1);
- os << "command = " << command << "\n";
+ // -- Write rule
+ // Write rule intro
+ cmGlobalNinjaGenerator::WriteComment(os, rule.Comment);
+ os << "rule " << rule.Name << '\n';
- // Write the description if any.
- if (!description.empty()) {
- cmGlobalNinjaGenerator::Indent(os, 1);
- os << "description = " << description << "\n";
- }
-
- if (!rspfile.empty()) {
- if (rspcontent.empty()) {
- cmSystemTools::Error("No rspfile_content given!", comment.c_str());
- return;
+ // Write rule key/value pairs
+ auto writeKV = [&os](const char* key, std::string const& value) {
+ if (!value.empty()) {
+ cmGlobalNinjaGenerator::Indent(os, 1);
+ os << key << " = " << value << '\n';
}
- cmGlobalNinjaGenerator::Indent(os, 1);
- os << "rspfile = " << rspfile << "\n";
- cmGlobalNinjaGenerator::Indent(os, 1);
- os << "rspfile_content = " << rspcontent << "\n";
- }
+ };
- if (!restat.empty()) {
- cmGlobalNinjaGenerator::Indent(os, 1);
- os << "restat = " << restat << "\n";
+ writeKV("depfile", rule.DepFile);
+ writeKV("deps", rule.DepType);
+ writeKV("command", rule.Command);
+ writeKV("description", rule.Description);
+ if (!rule.RspFile.empty()) {
+ writeKV("rspfile", rule.RspFile);
+ writeKV("rspfile_content", rule.RspContent);
}
-
- if (generator) {
- cmGlobalNinjaGenerator::Indent(os, 1);
- os << "generator = 1\n";
+ writeKV("restat", rule.Restat);
+ if (rule.Generator) {
+ writeKV("generator", "1");
}
- os << "\n";
+ // Finish rule
+ os << '\n';
}
void cmGlobalNinjaGenerator::WriteVariable(std::ostream& os,
@@ -435,13 +380,13 @@ void cmGlobalNinjaGenerator::WriteVariable(std::ostream& os,
// Make sure we have a name.
if (name.empty()) {
cmSystemTools::Error("No name given for WriteVariable! called "
- "with comment: ",
- comment.c_str());
+ "with comment: " +
+ comment);
return;
}
// Do not add a variable if the value is empty.
- std::string val = cmSystemTools::TrimWhitespace(value);
+ std::string val = cmTrimWhitespace(value);
if (val.empty()) {
return;
}
@@ -465,26 +410,14 @@ void cmGlobalNinjaGenerator::WriteDefault(std::ostream& os,
{
cmGlobalNinjaGenerator::WriteComment(os, comment);
os << "default";
- for (cmNinjaDeps::const_iterator i = targets.begin(); i != targets.end();
- ++i) {
- os << " " << *i;
+ for (std::string const& target : targets) {
+ os << " " << target;
}
os << "\n";
}
cmGlobalNinjaGenerator::cmGlobalNinjaGenerator(cmake* cm)
: cmGlobalCommonGenerator(cm)
- , BuildFileStream(CM_NULLPTR)
- , RulesFileStream(CM_NULLPTR)
- , CompileCommandsStream(CM_NULLPTR)
- , Rules()
- , AllDependencies()
- , UsingGCCOnWindows(false)
- , ComputingUnknownDependencies(false)
- , PolicyCMP0058(cmPolicies::WARN)
- , NinjaSupportsConsolePool(false)
- , NinjaSupportsImplicitOuts(false)
- , NinjaSupportsDyndeps(0)
{
#ifdef _WIN32
cm->GetState()->SetWindowsShell(true);
@@ -532,12 +465,17 @@ void cmGlobalNinjaGenerator::Generate()
std::ostringstream msg;
msg << "The detected version of Ninja (" << this->NinjaVersion;
msg << ") is less than the version of Ninja required by CMake (";
- msg << this->RequiredNinjaVersion() << ").";
- this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, msg.str());
+ msg << cmGlobalNinjaGenerator::RequiredNinjaVersion() << ").";
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
+ msg.str());
+ return;
+ }
+ if (!this->OpenBuildFileStream()) {
+ return;
+ }
+ if (!this->OpenRulesFileStream()) {
return;
}
- this->OpenBuildFileStream();
- this->OpenRulesFileStream();
this->TargetDependsClosures.clear();
@@ -579,20 +517,21 @@ bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf)
this->NinjaCommand = ninjaCommand;
std::vector<std::string> command;
command.push_back(this->NinjaCommand);
- command.push_back("--version");
+ command.emplace_back("--version");
std::string version;
std::string error;
- if (!cmSystemTools::RunSingleCommand(command, &version, &error, CM_NULLPTR,
- CM_NULLPTR,
+ if (!cmSystemTools::RunSingleCommand(command, &version, &error, nullptr,
+ nullptr,
cmSystemTools::OUTPUT_NONE)) {
- mf->IssueMessage(cmake::FATAL_ERROR, "Running\n '" +
- cmJoin(command, "' '") + "'\n"
- "failed with:\n " +
+ mf->IssueMessage(MessageType::FATAL_ERROR,
+ "Running\n '" + cmJoin(command, "' '") +
+ "'\n"
+ "failed with:\n " +
error);
cmSystemTools::SetFatalErrorOccured();
return false;
}
- this->NinjaVersion = cmSystemTools::TrimWhitespace(version);
+ this->NinjaVersion = cmTrimWhitespace(version);
this->CheckNinjaFeatures();
}
return true;
@@ -605,15 +544,29 @@ void cmGlobalNinjaGenerator::CheckNinjaFeatures()
RequiredNinjaVersionForConsolePool().c_str());
this->NinjaSupportsImplicitOuts = !cmSystemTools::VersionCompare(
cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
- this->RequiredNinjaVersionForImplicitOuts().c_str());
- {
+ cmGlobalNinjaGenerator::RequiredNinjaVersionForImplicitOuts().c_str());
+ this->NinjaSupportsManifestRestat = !cmSystemTools::VersionCompare(
+ cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
+ RequiredNinjaVersionForManifestRestat().c_str());
+ this->NinjaSupportsMultilineDepfile = !cmSystemTools::VersionCompare(
+ cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
+ RequiredNinjaVersionForMultilineDepfile().c_str());
+ this->NinjaSupportsDyndeps = !cmSystemTools::VersionCompare(
+ cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
+ RequiredNinjaVersionForDyndeps().c_str());
+ if (!this->NinjaSupportsDyndeps) {
+ // The ninja version number is not new enough to have upstream support.
// Our ninja branch adds ".dyndep-#" to its version number,
// where '#' is a feature-specific version number. Extract it.
static std::string const k_DYNDEP_ = ".dyndep-";
std::string::size_type pos = this->NinjaVersion.find(k_DYNDEP_);
if (pos != std::string::npos) {
- const char* fv = this->NinjaVersion.c_str() + pos + k_DYNDEP_.size();
- cmSystemTools::StringToULong(fv, &this->NinjaSupportsDyndeps);
+ const char* fv = &this->NinjaVersion[pos + k_DYNDEP_.size()];
+ unsigned long dyndep = 0;
+ cmStrToULong(fv, &dyndep);
+ if (dyndep == 1) {
+ this->NinjaSupportsDyndeps = true;
+ }
}
}
}
@@ -621,8 +574,7 @@ void cmGlobalNinjaGenerator::CheckNinjaFeatures()
bool cmGlobalNinjaGenerator::CheckLanguages(
std::vector<std::string> const& languages, cmMakefile* mf) const
{
- if (std::find(languages.begin(), languages.end(), "Fortran") !=
- languages.end()) {
+ if (cmContains(languages, "Fortran")) {
return this->CheckFortran(mf);
}
return true;
@@ -630,38 +582,26 @@ bool cmGlobalNinjaGenerator::CheckLanguages(
bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const
{
- if (this->NinjaSupportsDyndeps == 1) {
+ if (this->NinjaSupportsDyndeps) {
return true;
}
std::ostringstream e;
- if (this->NinjaSupportsDyndeps == 0) {
- /* clang-format off */
- e <<
- "The Ninja generator does not support Fortran using Ninja version\n"
- " " + this->NinjaVersion + "\n"
- "due to lack of required features. "
- "Kitware has implemented the required features but as of this version "
- "of CMake they have not been integrated to upstream ninja. "
- "Pending integration, Kitware maintains a branch at:\n"
- " https://github.com/Kitware/ninja/tree/features-for-fortran#readme\n"
- "with the required features. "
- "One may build ninja from that branch to get support for Fortran."
- ;
- /* clang-format on */
- } else {
- /* clang-format off */
- e <<
- "The Ninja generator in this version of CMake does not support Fortran "
- "using Ninja version\n"
- " " + this->NinjaVersion + "\n"
- "because its 'dyndep' feature version is " <<
- this->NinjaSupportsDyndeps << ". "
- "This version of CMake is aware only of 'dyndep' feature version 1."
- ;
- /* clang-format on */
- }
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ /* clang-format off */
+ e <<
+ "The Ninja generator does not support Fortran using Ninja version\n"
+ " " + this->NinjaVersion + "\n"
+ "due to lack of required features. "
+ "Kitware has implemented the required features and they have been "
+ "merged to upstream ninja for inclusion in Ninja 1.10 and higher. "
+ "As of this version of CMake, Ninja 1.10 has not been released. "
+ "Meanwhile, Kitware maintains a branch of Ninja at:\n"
+ " https://github.com/Kitware/ninja/tree/features-for-fortran#readme\n"
+ "with the required features. "
+ "One may build ninja from that branch to get support for Fortran."
+ ;
+ /* clang-format on */
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
cmSystemTools::SetFatalErrorOccured();
return false;
}
@@ -670,21 +610,29 @@ void cmGlobalNinjaGenerator::EnableLanguage(
std::vector<std::string> const& langs, cmMakefile* mf, bool optional)
{
this->cmGlobalGenerator::EnableLanguage(langs, mf, optional);
- for (std::vector<std::string>::const_iterator l = langs.begin();
- l != langs.end(); ++l) {
- if (*l == "NONE") {
+ for (std::string const& l : langs) {
+ if (l == "NONE") {
continue;
}
- this->ResolveLanguageCompiler(*l, mf, optional);
+ this->ResolveLanguageCompiler(l, mf, optional);
}
#ifdef _WIN32
- if (strcmp(mf->GetSafeDefinition("CMAKE_C_SIMULATE_ID"), "MSVC") != 0 &&
- strcmp(mf->GetSafeDefinition("CMAKE_CXX_SIMULATE_ID"), "MSVC") != 0 &&
- (mf->IsOn("CMAKE_COMPILER_IS_MINGW") ||
- strcmp(mf->GetSafeDefinition("CMAKE_C_COMPILER_ID"), "GNU") == 0 ||
- strcmp(mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID"), "GNU") == 0 ||
- strcmp(mf->GetSafeDefinition("CMAKE_C_COMPILER_ID"), "Clang") == 0 ||
- strcmp(mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID"), "Clang") == 0)) {
+ const bool clangGnuMode =
+ ((mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "Clang") &&
+ (mf->GetSafeDefinition("CMAKE_C_COMPILER_FRONTEND_VARIANT") == "GNU")) ||
+ ((mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "Clang") &&
+ (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_FRONTEND_VARIANT") == "GNU"));
+
+ if (clangGnuMode ||
+ ((mf->GetSafeDefinition("CMAKE_C_SIMULATE_ID") != "MSVC") &&
+ (mf->GetSafeDefinition("CMAKE_CXX_SIMULATE_ID") != "MSVC") &&
+ (mf->IsOn("CMAKE_COMPILER_IS_MINGW") ||
+ (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "GNU") ||
+ (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "GNU") ||
+ (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "Clang") ||
+ (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "Clang") ||
+ (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "QCC") ||
+ (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "QCC")))) {
this->UsingGCCOnWindows = true;
}
#endif
@@ -698,56 +646,52 @@ void cmGlobalNinjaGenerator::EnableLanguage(
// cmGlobalXCodeGenerator
// Called by:
// cmGlobalGenerator::Build()
-void cmGlobalNinjaGenerator::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<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalNinjaGenerator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& /*projectName*/,
+ const std::string& /*projectDir*/,
+ std::vector<std::string> const& targetNames, const std::string& /*config*/,
+ bool /*fast*/, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions)
{
- makeCommand.push_back(this->SelectMakeProgram(makeProgram));
+ GeneratedMakeCommand makeCommand;
+ makeCommand.Add(this->SelectMakeProgram(makeProgram));
if (verbose) {
- makeCommand.push_back("-v");
+ makeCommand.Add("-v");
}
- makeCommand.insert(makeCommand.end(), makeOptions.begin(),
- makeOptions.end());
- if (!targetName.empty()) {
- if (targetName == "clean") {
- makeCommand.push_back("-t");
- makeCommand.push_back("clean");
- } else {
- makeCommand.push_back(targetName);
+ if ((jobs != cmake::NO_BUILD_PARALLEL_LEVEL) &&
+ (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL)) {
+ makeCommand.Add("-j", std::to_string(jobs));
+ }
+
+ makeCommand.Add(makeOptions.begin(), makeOptions.end());
+ for (const auto& tname : targetNames) {
+ if (!tname.empty()) {
+ makeCommand.Add(tname);
}
}
+ return { std::move(makeCommand) };
}
// Non-virtual public methods.
-void cmGlobalNinjaGenerator::AddRule(
- const std::string& name, const std::string& command,
- const std::string& description, const std::string& comment,
- const std::string& depfile, const std::string& deptype,
- const std::string& rspfile, const std::string& rspcontent,
- const std::string& restat, bool generator)
+void cmGlobalNinjaGenerator::AddRule(cmNinjaRule const& rule)
{
// Do not add the same rule twice.
- if (this->HasRule(name)) {
+ if (!this->Rules.insert(rule.Name).second) {
return;
}
-
- this->Rules.insert(name);
- cmGlobalNinjaGenerator::WriteRule(*this->RulesFileStream, name, command,
- description, comment, depfile, deptype,
- rspfile, rspcontent, restat, generator);
-
- this->RuleCmdLength[name] = (int)command.size();
+ // Store command length
+ this->RuleCmdLength[rule.Name] = static_cast<int>(rule.Command.size());
+ // Write rule
+ cmGlobalNinjaGenerator::WriteRule(*this->RulesFileStream, rule);
}
bool cmGlobalNinjaGenerator::HasRule(const std::string& name)
{
- RulesSetType::const_iterator rule = this->Rules.find(name);
- return (rule != this->Rules.end());
+ return (this->Rules.find(name) != this->Rules.end());
}
// Private virtual overrides
@@ -763,32 +707,29 @@ void cmGlobalNinjaGenerator::ComputeTargetObjectDirectory(
cmGeneratorTarget* gt) const
{
// Compute full path to object file directory for this target.
- std::string dir;
- dir += gt->LocalGenerator->GetCurrentBinaryDirectory();
- dir += "/";
- dir += gt->LocalGenerator->GetTargetDirectory(gt);
- dir += "/";
+ std::string dir =
+ cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+ gt->LocalGenerator->GetTargetDirectory(gt), '/');
gt->ObjectDirectory = dir;
}
// Private methods
-void cmGlobalNinjaGenerator::OpenBuildFileStream()
+bool cmGlobalNinjaGenerator::OpenBuildFileStream()
{
// Compute Ninja's build file path.
std::string buildFilePath =
- this->GetCMakeInstance()->GetHomeOutputDirectory();
- buildFilePath += "/";
- buildFilePath += cmGlobalNinjaGenerator::NINJA_BUILD_FILE;
+ cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/',
+ cmGlobalNinjaGenerator::NINJA_BUILD_FILE);
// Get a stream where to generate things.
if (!this->BuildFileStream) {
- this->BuildFileStream = new cmGeneratedFileStream(
- buildFilePath.c_str(), false, this->GetMakefileEncoding());
- if (!this->BuildFileStream) {
+ this->BuildFileStream = cm::make_unique<cmGeneratedFileStream>(
+ buildFilePath, false, this->GetMakefileEncoding());
+ if (!(*this->BuildFileStream)) {
// An error message is generated by the constructor if it cannot
// open the file.
- return;
+ return false;
}
}
@@ -799,34 +740,34 @@ void cmGlobalNinjaGenerator::OpenBuildFileStream()
*this->BuildFileStream
<< "# This file contains all the build statements describing the\n"
<< "# compilation DAG.\n\n";
+
+ return true;
}
void cmGlobalNinjaGenerator::CloseBuildFileStream()
{
if (this->BuildFileStream) {
- delete this->BuildFileStream;
- this->BuildFileStream = CM_NULLPTR;
+ this->BuildFileStream.reset();
} else {
cmSystemTools::Error("Build file stream was not open.");
}
}
-void cmGlobalNinjaGenerator::OpenRulesFileStream()
+bool cmGlobalNinjaGenerator::OpenRulesFileStream()
{
// Compute Ninja's build file path.
std::string rulesFilePath =
- this->GetCMakeInstance()->GetHomeOutputDirectory();
- rulesFilePath += "/";
- rulesFilePath += cmGlobalNinjaGenerator::NINJA_RULES_FILE;
+ cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/',
+ cmGlobalNinjaGenerator::NINJA_RULES_FILE);
// Get a stream where to generate things.
if (!this->RulesFileStream) {
- this->RulesFileStream = new cmGeneratedFileStream(
- rulesFilePath.c_str(), false, this->GetMakefileEncoding());
- if (!this->RulesFileStream) {
+ this->RulesFileStream = cm::make_unique<cmGeneratedFileStream>(
+ rulesFilePath, false, this->GetMakefileEncoding());
+ if (!(*this->RulesFileStream)) {
// An error message is generated by the constructor if it cannot
// open the file.
- return;
+ return false;
}
}
@@ -841,13 +782,13 @@ void cmGlobalNinjaGenerator::OpenRulesFileStream()
<< "# It is included in the main '" << NINJA_BUILD_FILE << "'.\n\n"
;
/* clang-format on */
+ return true;
}
void cmGlobalNinjaGenerator::CloseRulesFileStream()
{
if (this->RulesFileStream) {
- delete this->RulesFileStream;
- this->RulesFileStream = CM_NULLPTR;
+ this->RulesFileStream.reset();
} else {
cmSystemTools::Error("Rules file stream was not open.");
}
@@ -858,7 +799,7 @@ static void EnsureTrailingSlash(std::string& path)
if (path.empty()) {
return;
}
- std::string::value_type last = path[path.size() - 1];
+ std::string::value_type last = path.back();
#ifdef _WIN32
if (last != '\\') {
path += '\\';
@@ -870,18 +811,29 @@ static void EnsureTrailingSlash(std::string& path)
#endif
}
-std::string cmGlobalNinjaGenerator::ConvertToNinjaPath(
+std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath(
const std::string& path) const
{
+ auto const f = ConvertToNinjaPathCache.find(path);
+ if (f != ConvertToNinjaPathCache.end()) {
+ return f->second;
+ }
+
cmLocalNinjaGenerator* ng =
static_cast<cmLocalNinjaGenerator*>(this->LocalGenerators[0]);
- std::string convPath = ng->ConvertToRelativePath(
- this->LocalGenerators[0]->GetState()->GetBinaryDirectory(), path);
+ std::string const& bin_dir = ng->GetState()->GetBinaryDirectory();
+ std::string convPath = ng->MaybeConvertToRelativePath(bin_dir, path);
convPath = this->NinjaOutputPath(convPath);
#ifdef _WIN32
std::replace(convPath.begin(), convPath.end(), '/', '\\');
#endif
- return convPath;
+ return ConvertToNinjaPathCache.emplace(path, std::move(convPath))
+ .first->second;
+}
+
+void cmGlobalNinjaGenerator::AddAdditionalCleanFile(std::string fileName)
+{
+ this->AdditionalCleanFiles.emplace(std::move(fileName));
}
void cmGlobalNinjaGenerator::AddCXXCompileCommand(
@@ -899,25 +851,25 @@ void cmGlobalNinjaGenerator::AddCXXCompileCommand(
// Get a stream where to generate things.
this->CompileCommandsStream =
- new cmGeneratedFileStream(buildFilePath.c_str());
+ cm::make_unique<cmGeneratedFileStream>(buildFilePath);
*this->CompileCommandsStream << "[";
} else {
*this->CompileCommandsStream << "," << std::endl;
}
std::string sourceFileName = sourceFile;
- if (!cmSystemTools::FileIsFullPath(sourceFileName.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(sourceFileName)) {
sourceFileName = cmSystemTools::CollapseFullPath(
sourceFileName, this->GetCMakeInstance()->GetHomeOutputDirectory());
}
/* clang-format off */
*this->CompileCommandsStream << "\n{\n"
- << " \"directory\": \""
+ << R"( "directory": ")"
<< cmGlobalGenerator::EscapeJSON(buildFileDir) << "\",\n"
- << " \"command\": \""
+ << R"( "command": ")"
<< cmGlobalGenerator::EscapeJSON(commandLine) << "\",\n"
- << " \"file\": \""
+ << R"( "file": ")"
<< cmGlobalGenerator::EscapeJSON(sourceFileName) << "\"\n"
<< "}";
/* clang-format on */
@@ -927,8 +879,7 @@ void cmGlobalNinjaGenerator::CloseCompileCommandsStream()
{
if (this->CompileCommandsStream) {
*this->CompileCommandsStream << "\n]";
- delete this->CompileCommandsStream;
- this->CompileCommandsStream = CM_NULLPTR;
+ this->CompileCommandsStream.reset();
}
}
@@ -940,27 +891,18 @@ void cmGlobalNinjaGenerator::WriteDisclaimer(std::ostream& os)
<< cmVersion::GetMinorVersion() << "\n\n";
}
-void cmGlobalNinjaGenerator::AddDependencyToAll(cmGeneratorTarget* target)
-{
- this->AppendTargetOutputs(target, this->AllDependencies);
-}
-
-void cmGlobalNinjaGenerator::AddDependencyToAll(const std::string& input)
-{
- this->AllDependencies.push_back(input);
-}
-
void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
{
- for (std::map<std::string, std::set<std::string> >::iterator i =
- this->AssumedSourceDependencies.begin();
- i != this->AssumedSourceDependencies.end(); ++i) {
- cmNinjaDeps deps;
- std::copy(i->second.begin(), i->second.end(), std::back_inserter(deps));
+ for (auto const& asd : this->AssumedSourceDependencies) {
+ cmNinjaDeps orderOnlyDeps;
+ std::copy(asd.second.begin(), asd.second.end(),
+ std::back_inserter(orderOnlyDeps));
WriteCustomCommandBuild(/*command=*/"", /*description=*/"",
"Assume dependencies for generated source file.",
- /*depfile*/ "", /*uses_terminal*/ false,
- /*restat*/ true, cmNinjaDeps(1, i->first), deps);
+ /*depfile*/ "", /*job_pool*/ "",
+ /*uses_terminal*/ false,
+ /*restat*/ true, cmNinjaDeps(1, asd.first),
+ cmNinjaDeps(), orderOnlyDeps);
}
}
@@ -1024,63 +966,72 @@ void cmGlobalNinjaGenerator::AppendTargetDepends(
{
if (target->GetType() == cmStateEnums::GLOBAL_TARGET) {
// These depend only on other CMake-provided targets, e.g. "all".
- std::set<std::string> const& utils = target->GetUtilities();
- for (std::set<std::string>::const_iterator i = utils.begin();
- i != utils.end(); ++i) {
+ for (BT<std::string> const& util : target->GetUtilities()) {
std::string d =
- target->GetLocalGenerator()->GetCurrentBinaryDirectory() +
- std::string("/") + *i;
+ target->GetLocalGenerator()->GetCurrentBinaryDirectory() + "/" +
+ util.Value;
outputs.push_back(this->ConvertToNinjaPath(d));
}
} else {
cmNinjaDeps outs;
- cmTargetDependSet const& targetDeps = this->GetTargetDirectDepends(target);
- for (cmTargetDependSet::const_iterator i = targetDeps.begin();
- i != targetDeps.end(); ++i) {
- if ((*i)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ for (cmTargetDepend const& targetDep :
+ this->GetTargetDirectDepends(target)) {
+ if (targetDep->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
- this->AppendTargetOutputs(*i, outs, depends);
+ this->AppendTargetOutputs(targetDep, outs, depends);
}
std::sort(outs.begin(), outs.end());
- outputs.insert(outputs.end(), outs.begin(), outs.end());
+ cmAppend(outputs, outs);
}
}
void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
cmGeneratorTarget const* target, cmNinjaDeps& outputs)
{
- TargetDependsClosureMap::iterator i =
- this->TargetDependsClosures.find(target);
- if (i == this->TargetDependsClosures.end()) {
- TargetDependsClosureMap::value_type e(
- target, std::set<cmGeneratorTarget const*>());
- i = this->TargetDependsClosures.insert(e).first;
- this->ComputeTargetDependsClosure(target, i->second);
- }
- std::set<cmGeneratorTarget const*> const& targets = i->second;
- cmNinjaDeps outs;
- for (std::set<cmGeneratorTarget const*>::const_iterator ti = targets.begin();
- ti != targets.end(); ++ti) {
- this->AppendTargetOutputs(*ti, outs);
- }
- std::sort(outs.begin(), outs.end());
- outputs.insert(outputs.end(), outs.begin(), outs.end());
+ cmNinjaOuts outs;
+ this->AppendTargetDependsClosure(target, outs, true);
+ cmAppend(outputs, outs);
}
-void cmGlobalNinjaGenerator::ComputeTargetDependsClosure(
- cmGeneratorTarget const* target, std::set<cmGeneratorTarget const*>& depends)
+void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
+ cmGeneratorTarget const* target, cmNinjaOuts& outputs, bool omit_self)
{
- cmTargetDependSet const& targetDeps = this->GetTargetDirectDepends(target);
- for (cmTargetDependSet::const_iterator i = targetDeps.begin();
- i != targetDeps.end(); ++i) {
- if ((*i)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
- continue;
- }
- if (depends.insert(*i).second) {
- this->ComputeTargetDependsClosure(*i, depends);
+
+ // try to locate the target in the cache
+ auto find = this->TargetDependsClosures.lower_bound(target);
+
+ if (find == this->TargetDependsClosures.end() || find->first != target) {
+ // We now calculate the closure outputs by inspecting the dependent
+ // targets recursively.
+ // For that we have to distinguish between a local result set that is only
+ // relevant for filling the cache entries properly isolated and a global
+ // result set that is relevant for the result of the top level call to
+ // AppendTargetDependsClosure.
+ cmNinjaOuts this_outs; // this will be the new cache entry
+
+ for (auto const& dep_target : this->GetTargetDirectDepends(target)) {
+ if (dep_target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ continue;
+ }
+
+ // Collect the dependent targets for _this_ target
+ this->AppendTargetDependsClosure(dep_target, this_outs, false);
}
+ find = this->TargetDependsClosures.emplace_hint(find, target,
+ std::move(this_outs));
+ }
+
+ // now fill the outputs of the final result from the newly generated cache
+ // entry
+ outputs.insert(find->second.begin(), find->second.end());
+
+ // finally generate the outputs of the target itself, if applicable
+ cmNinjaDeps outs;
+ if (!omit_self) {
+ this->AppendTargetOutputs(target, outs);
}
+ outputs.insert(outs.begin(), outs.end());
}
void cmGlobalNinjaGenerator::AddTargetAlias(const std::string& alias,
@@ -1091,8 +1042,8 @@ void cmGlobalNinjaGenerator::AddTargetAlias(const std::string& alias,
this->AppendTargetOutputs(target, outputs);
// Mark the target's outputs as ambiguous to ensure that no other target uses
// the output as an alias.
- for (cmNinjaDeps::iterator i = outputs.begin(); i != outputs.end(); ++i) {
- TargetAliases[*i] = CM_NULLPTR;
+ for (std::string const& output : outputs) {
+ TargetAliases[output] = nullptr;
}
// Insert the alias into the map. If the alias was already present in the
@@ -1100,7 +1051,7 @@ void cmGlobalNinjaGenerator::AddTargetAlias(const std::string& alias,
std::pair<TargetAliasMap::iterator, bool> newAlias =
TargetAliases.insert(std::make_pair(buildAlias, target));
if (newAlias.second && newAlias.first->second != target) {
- newAlias.first->second = CM_NULLPTR;
+ newAlias.first->second = nullptr;
}
}
@@ -1109,17 +1060,27 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os)
cmGlobalNinjaGenerator::WriteDivider(os);
os << "# Target aliases.\n\n";
- for (TargetAliasMap::const_iterator i = TargetAliases.begin();
- i != TargetAliases.end(); ++i) {
+ cmNinjaBuild build("phony");
+ build.Outputs.emplace_back("");
+ for (auto const& ta : TargetAliases) {
// Don't write ambiguous aliases.
- if (!i->second) {
+ if (!ta.second) {
continue;
}
- cmNinjaDeps deps;
- this->AppendTargetOutputs(i->second, deps);
+ // Don't write alias if there is a already a custom command with
+ // matching output
+ if (this->HasCustomCommandOutput(ta.first)) {
+ continue;
+ }
- this->WritePhonyBuild(os, "", cmNinjaDeps(1, i->first), deps);
+ // Outputs
+ build.Outputs[0] = ta.first;
+ // Explicit depdendencies
+ build.ExplicitDeps.clear();
+ this->AppendTargetOutputs(ta.second, build.ExplicitDeps);
+ // Write
+ this->WriteBuild(os, build);
}
}
@@ -1128,65 +1089,32 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os)
cmGlobalNinjaGenerator::WriteDivider(os);
os << "# Folder targets.\n\n";
- std::map<std::string, cmNinjaDeps> targetsPerFolder;
- for (std::vector<cmLocalGenerator*>::const_iterator lgi =
- this->LocalGenerators.begin();
- lgi != this->LocalGenerators.end(); ++lgi) {
- cmLocalGenerator const* lg = *lgi;
- const std::string currentBinaryFolder(
- lg->GetStateSnapshot().GetDirectory().GetCurrentBinary());
- // The directory-level rule should depend on the target-level rules
- // for all targets in the directory.
- targetsPerFolder[currentBinaryFolder] = cmNinjaDeps();
- for (std::vector<cmGeneratorTarget*>::const_iterator ti =
- lg->GetGeneratorTargets().begin();
- ti != lg->GetGeneratorTargets().end(); ++ti) {
- cmGeneratorTarget const* gt = *ti;
- cmStateEnums::TargetType const type = gt->GetType();
- if ((type == cmStateEnums::EXECUTABLE ||
- type == cmStateEnums::STATIC_LIBRARY ||
- type == cmStateEnums::SHARED_LIBRARY ||
- type == cmStateEnums::MODULE_LIBRARY ||
- type == cmStateEnums::OBJECT_LIBRARY ||
- type == cmStateEnums::UTILITY) &&
- !gt->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
- targetsPerFolder[currentBinaryFolder].push_back(gt->GetName());
- }
- }
+ std::map<std::string, DirectoryTarget> dirTargets =
+ this->ComputeDirectoryTargets();
- // The directory-level rule should depend on the directory-level
- // rules of the subdirectories.
- std::vector<cmStateSnapshot> const& children =
- lg->GetStateSnapshot().GetChildren();
- for (std::vector<cmStateSnapshot>::const_iterator stateIt =
- children.begin();
- stateIt != children.end(); ++stateIt) {
- std::string const currentBinaryDir =
- stateIt->GetDirectory().GetCurrentBinary();
-
- targetsPerFolder[currentBinaryFolder].push_back(
- this->ConvertToNinjaPath(currentBinaryDir + "/all"));
- }
- }
-
- std::string const rootBinaryDir =
- this->LocalGenerators[0]->GetBinaryDirectory();
- for (std::map<std::string, cmNinjaDeps>::const_iterator it =
- targetsPerFolder.begin();
- it != targetsPerFolder.end(); ++it) {
+ for (auto const& it : dirTargets) {
+ cmNinjaBuild build("phony");
cmGlobalNinjaGenerator::WriteDivider(os);
- std::string const& currentBinaryDir = it->first;
-
- // Do not generate a rule for the root binary dir.
- if (rootBinaryDir.length() >= currentBinaryDir.length()) {
- continue;
+ std::string const& currentBinaryDir = it.first;
+ DirectoryTarget const& dt = it.second;
+
+ // Setup target
+ build.Comment = "Folder: " + currentBinaryDir;
+ build.Outputs.emplace_back(
+ this->ConvertToNinjaPath(currentBinaryDir + "/all"));
+ for (DirectoryTarget::Target const& t : dt.Targets) {
+ if (!t.ExcludeFromAll) {
+ this->AppendTargetOutputs(t.GT, build.ExplicitDeps);
+ }
}
-
- std::string const comment = "Folder: " + currentBinaryDir;
- cmNinjaDeps output(1);
- output.push_back(this->ConvertToNinjaPath(currentBinaryDir + "/all"));
-
- this->WritePhonyBuild(os, comment, output, it->second);
+ for (DirectoryTarget::Dir const& d : dt.Children) {
+ if (!d.ExcludeFromAll) {
+ build.ExplicitDeps.emplace_back(
+ this->ConvertToNinjaPath(d.Path + "/all"));
+ }
+ }
+ // Write target
+ this->WriteBuild(os, build);
}
}
@@ -1220,50 +1148,37 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os)
// get the list of files that cmake itself has generated as a
// product of configuration.
- for (std::vector<cmLocalGenerator*>::const_iterator i =
- this->LocalGenerators.begin();
- i != this->LocalGenerators.end(); ++i) {
+ for (cmLocalGenerator* lg : this->LocalGenerators) {
// get the vector of files created by this makefile and convert them
// to ninja paths, which are all relative in respect to the build directory
- const std::vector<std::string>& files =
- (*i)->GetMakefile()->GetOutputFiles();
- typedef std::vector<std::string>::const_iterator vect_it;
- for (vect_it j = files.begin(); j != files.end(); ++j) {
- knownDependencies.insert(this->ConvertToNinjaPath(*j));
+ for (std::string const& file : lg->GetMakefile()->GetOutputFiles()) {
+ knownDependencies.insert(this->ConvertToNinjaPath(file));
}
- // get list files which are implicit dependencies as well and will be phony
- // for rebuild manifest
- std::vector<std::string> const& lf = (*i)->GetMakefile()->GetListFiles();
- typedef std::vector<std::string>::const_iterator vect_it;
- for (vect_it j = lf.begin(); j != lf.end(); ++j) {
- knownDependencies.insert(this->ConvertToNinjaPath(*j));
+ if (!this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ // get list files which are implicit dependencies as well and will be
+ // phony for rebuild manifest
+ for (std::string const& j : lg->GetMakefile()->GetListFiles()) {
+ knownDependencies.insert(this->ConvertToNinjaPath(j));
+ }
}
- std::vector<cmGeneratorExpressionEvaluationFile*> const& ef =
- (*i)->GetMakefile()->GetEvaluationFiles();
- for (std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator li =
- ef.begin();
- li != ef.end(); ++li) {
+ for (cmGeneratorExpressionEvaluationFile* li :
+ lg->GetMakefile()->GetEvaluationFiles()) {
// get all the files created by generator expressions and convert them
// to ninja paths
- std::vector<std::string> evaluationFiles = (*li)->GetFiles();
- for (vect_it j = evaluationFiles.begin(); j != evaluationFiles.end();
- ++j) {
- knownDependencies.insert(this->ConvertToNinjaPath(*j));
+ for (std::string const& evaluationFile : li->GetFiles()) {
+ knownDependencies.insert(this->ConvertToNinjaPath(evaluationFile));
}
}
}
knownDependencies.insert(this->CMakeCacheFile);
- for (TargetAliasMap::const_iterator i = this->TargetAliases.begin();
- i != this->TargetAliases.end(); ++i) {
- knownDependencies.insert(this->ConvertToNinjaPath(i->first));
+ for (auto const& ta : this->TargetAliases) {
+ knownDependencies.insert(this->ConvertToNinjaPath(ta.first));
}
// remove all source files we know will exist.
- typedef std::map<std::string, std::set<std::string> >::const_iterator map_it;
- for (map_it i = this->AssumedSourceDependencies.begin();
- i != this->AssumedSourceDependencies.end(); ++i) {
- knownDependencies.insert(this->ConvertToNinjaPath(i->first));
+ for (auto const& i : this->AssumedSourceDependencies) {
+ knownDependencies.insert(this->ConvertToNinjaPath(i.first));
}
// now we difference with CombinedCustomCommandExplicitDependencies to find
@@ -1280,25 +1195,26 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os)
knownDependencies.begin(), knownDependencies.end(),
std::back_inserter(unknownExplicitDepends));
- std::string const rootBuildDirectory =
- this->GetCMakeInstance()->GetHomeOutputDirectory();
- bool const inSourceBuild =
- (rootBuildDirectory == this->GetCMakeInstance()->GetHomeDirectory());
std::vector<std::string> warnExplicitDepends;
- for (std::vector<std::string>::const_iterator i =
- unknownExplicitDepends.begin();
- i != unknownExplicitDepends.end(); ++i) {
- // verify the file is in the build directory
- std::string const absDepPath =
- cmSystemTools::CollapseFullPath(*i, rootBuildDirectory.c_str());
- bool const inBuildDir =
- cmSystemTools::IsSubDirectory(absDepPath, rootBuildDirectory);
- if (inBuildDir) {
- cmNinjaDeps deps(1, *i);
- this->WritePhonyBuild(os, "", deps, cmNinjaDeps());
- if (this->PolicyCMP0058 == cmPolicies::WARN && !inSourceBuild &&
- warnExplicitDepends.size() < 10) {
- warnExplicitDepends.push_back(*i);
+ if (!unknownExplicitDepends.empty()) {
+ cmake* cmk = this->GetCMakeInstance();
+ std::string const& buildRoot = cmk->GetHomeOutputDirectory();
+ bool const inSource = (buildRoot == cmk->GetHomeDirectory());
+ bool const warn = (!inSource && (this->PolicyCMP0058 == cmPolicies::WARN));
+ cmNinjaBuild build("phony");
+ build.Outputs.emplace_back("");
+ for (std::string const& ued : unknownExplicitDepends) {
+ // verify the file is in the build directory
+ std::string const absDepPath =
+ cmSystemTools::CollapseFullPath(ued, buildRoot);
+ if (cmSystemTools::IsSubDirectory(absDepPath, buildRoot)) {
+ // Generate phony build statement
+ build.Outputs[0] = ued;
+ this->WriteBuild(os, build);
+ // Add to warning on demand
+ if (warn && warnExplicitDepends.size() < 10) {
+ warnExplicitDepends.push_back(ued);
+ }
}
}
}
@@ -1320,7 +1236,8 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os)
"options to the custom commands that produce these files."
;
/* clang-format on */
- this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING,
+ w.str());
}
}
@@ -1330,87 +1247,144 @@ void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os)
cmGlobalNinjaGenerator::WriteDivider(os);
os << "# Built-in targets\n\n";
- this->WriteTargetAll(os);
+ this->WriteTargetDefault(os);
this->WriteTargetRebuildManifest(os);
this->WriteTargetClean(os);
this->WriteTargetHelp(os);
}
-void cmGlobalNinjaGenerator::WriteTargetAll(std::ostream& os)
+void cmGlobalNinjaGenerator::WriteTargetDefault(std::ostream& os)
{
- cmNinjaDeps outputs;
- outputs.push_back(this->TargetAll);
-
- this->WritePhonyBuild(os, "The main all target.", outputs,
- this->AllDependencies);
-
if (!this->HasOutputPathPrefix()) {
- cmGlobalNinjaGenerator::WriteDefault(os, outputs,
+ cmNinjaDeps all;
+ all.push_back(this->TargetAll);
+ cmGlobalNinjaGenerator::WriteDefault(os, all,
"Make the all target the default.");
}
}
void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
{
+ if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ return;
+ }
cmLocalGenerator* lg = this->LocalGenerators[0];
- std::ostringstream cmd;
- cmd << lg->ConvertToOutputFormat(cmSystemTools::GetCMakeCommand(),
- cmOutputConverter::SHELL)
- << " -H"
- << lg->ConvertToOutputFormat(lg->GetSourceDirectory(),
- cmOutputConverter::SHELL)
- << " -B"
- << lg->ConvertToOutputFormat(lg->GetBinaryDirectory(),
- cmOutputConverter::SHELL);
- WriteRule(*this->RulesFileStream, "RERUN_CMAKE", cmd.str(),
- "Re-running CMake...", "Rule for re-running cmake.",
- /*depfile=*/"",
- /*deptype=*/"",
- /*rspfile=*/"",
- /*rspcontent*/ "",
- /*restat=*/"",
- /*generator=*/true);
-
- cmNinjaDeps implicitDeps;
- for (std::vector<cmLocalGenerator*>::const_iterator i =
- this->LocalGenerators.begin();
- i != this->LocalGenerators.end(); ++i) {
- std::vector<std::string> const& lf = (*i)->GetMakefile()->GetListFiles();
- for (std::vector<std::string>::const_iterator fi = lf.begin();
- fi != lf.end(); ++fi) {
- implicitDeps.push_back(this->ConvertToNinjaPath(*fi));
+ {
+ cmNinjaRule rule("RERUN_CMAKE");
+ rule.Command =
+ cmStrCat(CMakeCmd(), " -S",
+ lg->ConvertToOutputFormat(lg->GetSourceDirectory(),
+ cmOutputConverter::SHELL),
+ " -B",
+ lg->ConvertToOutputFormat(lg->GetBinaryDirectory(),
+ cmOutputConverter::SHELL));
+ rule.Description = "Re-running CMake...";
+ rule.Comment = "Rule for re-running cmake.";
+ rule.Generator = true;
+ WriteRule(*this->RulesFileStream, rule);
+ }
+
+ cmNinjaBuild reBuild("RERUN_CMAKE");
+ reBuild.Comment = "Re-run CMake if any of its inputs changed.";
+ reBuild.Outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE));
+
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ for (std::string const& fi : localGen->GetMakefile()->GetListFiles()) {
+ reBuild.ImplicitDeps.push_back(this->ConvertToNinjaPath(fi));
}
}
- implicitDeps.push_back(this->CMakeCacheFile);
-
- std::sort(implicitDeps.begin(), implicitDeps.end());
- implicitDeps.erase(std::unique(implicitDeps.begin(), implicitDeps.end()),
- implicitDeps.end());
+ reBuild.ImplicitDeps.push_back(this->CMakeCacheFile);
- cmNinjaVars variables;
// Use 'console' pool to get non buffered output of the CMake re-run call
// Available since Ninja 1.5
if (SupportsConsolePool()) {
- variables["pool"] = "console";
+ reBuild.Variables["pool"] = "console";
}
- std::string const ninjaBuildFile = this->NinjaOutputPath(NINJA_BUILD_FILE);
- this->WriteBuild(os, "Re-run CMake if any of its inputs changed.",
- "RERUN_CMAKE",
- /*outputs=*/cmNinjaDeps(1, ninjaBuildFile),
- /*implicitOuts=*/cmNinjaDeps(),
- /*explicitDeps=*/cmNinjaDeps(), implicitDeps,
- /*orderOnlyDeps=*/cmNinjaDeps(), variables);
+ cmake* cm = this->GetCMakeInstance();
+ if (this->SupportsManifestRestat() && cm->DoWriteGlobVerifyTarget()) {
+ {
+ cmNinjaRule rule("VERIFY_GLOBS");
+ rule.Command =
+ cmStrCat(CMakeCmd(), " -P ",
+ lg->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
+ cmOutputConverter::SHELL));
+ rule.Description = "Re-checking globbed directories...";
+ rule.Comment = "Rule for re-checking globbed directories.";
+ rule.Generator = true;
+ this->WriteRule(*this->RulesFileStream, rule);
+ }
+
+ cmNinjaBuild phonyBuild("phony");
+ phonyBuild.Comment = "Phony target to force glob verification run.";
+ phonyBuild.Outputs.push_back(cm->GetGlobVerifyScript() + "_force");
+ this->WriteBuild(os, phonyBuild);
+
+ reBuild.Variables["restat"] = "1";
+ std::string const verifyScriptFile =
+ this->NinjaOutputPath(cm->GetGlobVerifyScript());
+ std::string const verifyStampFile =
+ this->NinjaOutputPath(cm->GetGlobVerifyStamp());
+ {
+ cmNinjaBuild vgBuild("VERIFY_GLOBS");
+ vgBuild.Comment =
+ "Re-run CMake to check if globbed directories changed.";
+ vgBuild.Outputs.push_back(verifyStampFile);
+ vgBuild.ImplicitDeps = phonyBuild.Outputs;
+ vgBuild.Variables = reBuild.Variables;
+ this->WriteBuild(os, vgBuild);
+ }
+ reBuild.Variables.erase("restat");
+ reBuild.ImplicitDeps.push_back(verifyScriptFile);
+ reBuild.ExplicitDeps.push_back(verifyStampFile);
+ } else if (!this->SupportsManifestRestat() &&
+ cm->DoWriteGlobVerifyTarget()) {
+ std::ostringstream msg;
+ msg << "The detected version of Ninja:\n"
+ << " " << this->NinjaVersion << "\n"
+ << "is less than the version of Ninja required by CMake for adding "
+ "restat dependencies to the build.ninja manifest regeneration "
+ "target:\n"
+ << " "
+ << cmGlobalNinjaGenerator::RequiredNinjaVersionForManifestRestat()
+ << "\n";
+ msg << "Any pre-check scripts, such as those generated for file(GLOB "
+ "CONFIGURE_DEPENDS), will not be run by Ninja.";
+ this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING,
+ msg.str());
+ }
+
+ std::sort(reBuild.ImplicitDeps.begin(), reBuild.ImplicitDeps.end());
+ reBuild.ImplicitDeps.erase(
+ std::unique(reBuild.ImplicitDeps.begin(), reBuild.ImplicitDeps.end()),
+ reBuild.ImplicitDeps.end());
+
+ this->WriteBuild(os, reBuild);
- this->WritePhonyBuild(os, "A missing CMake input file is not an error.",
- implicitDeps, cmNinjaDeps());
+ {
+ cmNinjaBuild build("phony");
+ build.Comment = "A missing CMake input file is not an error.";
+ std::set_difference(std::make_move_iterator(reBuild.ImplicitDeps.begin()),
+ std::make_move_iterator(reBuild.ImplicitDeps.end()),
+ CustomCommandOutputs.begin(),
+ CustomCommandOutputs.end(),
+ std::back_inserter(build.Outputs));
+ this->WriteBuild(os, build);
+ }
+}
+
+std::string cmGlobalNinjaGenerator::CMakeCmd() const
+{
+ cmLocalGenerator* lgen = this->LocalGenerators.at(0);
+ return lgen->ConvertToOutputFormat(cmSystemTools::GetCMakeCommand(),
+ cmOutputConverter::SHELL);
}
-std::string cmGlobalNinjaGenerator::ninjaCmd() const
+std::string cmGlobalNinjaGenerator::NinjaCmd() const
{
cmLocalGenerator* lgen = this->LocalGenerators[0];
- if (lgen) {
+ if (lgen != nullptr) {
return lgen->ConvertToOutputFormat(this->NinjaCommand,
cmOutputConverter::SHELL);
}
@@ -1427,44 +1401,115 @@ bool cmGlobalNinjaGenerator::SupportsImplicitOuts() const
return this->NinjaSupportsImplicitOuts;
}
+bool cmGlobalNinjaGenerator::SupportsManifestRestat() const
+{
+ return this->NinjaSupportsManifestRestat;
+}
+
+bool cmGlobalNinjaGenerator::SupportsMultilineDepfile() const
+{
+ return this->NinjaSupportsMultilineDepfile;
+}
+
+bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os)
+{
+ cmLocalGenerator* lgr = this->LocalGenerators.at(0);
+ std::string cleanScriptRel = "CMakeFiles/clean_additional.cmake";
+ std::string cleanScriptAbs =
+ cmStrCat(lgr->GetBinaryDirectory(), '/', cleanScriptRel);
+
+ // Check if there are additional files to clean
+ if (this->AdditionalCleanFiles.empty()) {
+ // Remove cmake clean script file if it exists
+ cmSystemTools::RemoveFile(cleanScriptAbs);
+ return false;
+ }
+
+ // Write cmake clean script file
+ {
+ cmGeneratedFileStream fout(cleanScriptAbs);
+ if (!fout) {
+ return false;
+ }
+ fout << "# Additional clean files\n\n";
+ fout << "file(REMOVE_RECURSE\n";
+ for (std::string const& acf : this->AdditionalCleanFiles) {
+ fout << " "
+ << cmOutputConverter::EscapeForCMake(ConvertToNinjaPath(acf))
+ << '\n';
+ }
+ fout << ")\n";
+ }
+ // Register clean script file
+ lgr->GetMakefile()->AddCMakeOutputFile(cleanScriptAbs);
+
+ // Write rule
+ {
+ cmNinjaRule rule("CLEAN_ADDITIONAL");
+ rule.Command = cmStrCat(
+ CMakeCmd(), " -P ",
+ lgr->ConvertToOutputFormat(this->NinjaOutputPath(cleanScriptRel),
+ cmOutputConverter::SHELL));
+ rule.Description = "Cleaning additional files...";
+ rule.Comment = "Rule for cleaning additional files.";
+ WriteRule(*this->RulesFileStream, rule);
+ }
+
+ // Write build
+ {
+ cmNinjaBuild build("CLEAN_ADDITIONAL");
+ build.Comment = "Clean additional files.";
+ build.Outputs.push_back(
+ this->NinjaOutputPath(this->GetAdditionalCleanTargetName()));
+ WriteBuild(os, build);
+ }
+ // Return success
+ return true;
+}
+
void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
{
- WriteRule(*this->RulesFileStream, "CLEAN", ninjaCmd() + " -t clean",
- "Cleaning all built files...",
- "Rule for cleaning all built files.",
- /*depfile=*/"",
- /*deptype=*/"",
- /*rspfile=*/"",
- /*rspcontent*/ "",
- /*restat=*/"",
- /*generator=*/false);
- WriteBuild(os, "Clean all the built files.", "CLEAN",
- /*outputs=*/cmNinjaDeps(1, this->NinjaOutputPath("clean")),
- /*implicitOuts=*/cmNinjaDeps(),
- /*explicitDeps=*/cmNinjaDeps(),
- /*implicitDeps=*/cmNinjaDeps(),
- /*orderOnlyDeps=*/cmNinjaDeps(),
- /*variables=*/cmNinjaVars());
+ // -- Additional clean target
+ bool additionalFiles = WriteTargetCleanAdditional(os);
+
+ // -- Default clean target
+ // Write rule
+ {
+ cmNinjaRule rule("CLEAN");
+ rule.Command = NinjaCmd() + " -t clean";
+ rule.Description = "Cleaning all built files...";
+ rule.Comment = "Rule for cleaning all built files.";
+ WriteRule(*this->RulesFileStream, rule);
+ }
+
+ // Write build
+ {
+ cmNinjaBuild build("CLEAN");
+ build.Comment = "Clean all the built files.";
+ build.Outputs.push_back(this->NinjaOutputPath(this->GetCleanTargetName()));
+ if (additionalFiles) {
+ build.ExplicitDeps.push_back(
+ this->NinjaOutputPath(this->GetAdditionalCleanTargetName()));
+ }
+ WriteBuild(os, build);
+ }
}
void cmGlobalNinjaGenerator::WriteTargetHelp(std::ostream& os)
{
- WriteRule(*this->RulesFileStream, "HELP", ninjaCmd() + " -t targets",
- "All primary targets available:",
- "Rule for printing all primary targets available.",
- /*depfile=*/"",
- /*deptype=*/"",
- /*rspfile=*/"",
- /*rspcontent*/ "",
- /*restat=*/"",
- /*generator=*/false);
- WriteBuild(os, "Print all primary targets available.", "HELP",
- /*outputs=*/cmNinjaDeps(1, this->NinjaOutputPath("help")),
- /*implicitOuts=*/cmNinjaDeps(),
- /*explicitDeps=*/cmNinjaDeps(),
- /*implicitDeps=*/cmNinjaDeps(),
- /*orderOnlyDeps=*/cmNinjaDeps(),
- /*variables=*/cmNinjaVars());
+ {
+ cmNinjaRule rule("HELP");
+ rule.Command = NinjaCmd() + " -t targets";
+ rule.Description = "All primary targets available:";
+ rule.Comment = "Rule for printing all primary targets available.";
+ WriteRule(*this->RulesFileStream, rule);
+ }
+ {
+ cmNinjaBuild build("HELP");
+ build.Comment = "Print all primary targets available.";
+ build.Outputs.push_back(this->NinjaOutputPath("help"));
+ WriteBuild(os, build);
+ }
}
void cmGlobalNinjaGenerator::InitOutputPathPrefix()
@@ -1513,12 +1558,13 @@ Compilation of source files within a target is split into the following steps:
command = gfortran -cpp $DEFINES $INCLUDES $FLAGS -E $in -o $out &&
cmake -E cmake_ninja_depends \
--tdi=FortranDependInfo.json --pp=$out --dep=$DEP_FILE \
- --obj=$OBJ_FILE --ddi=$DYNDEP_INTERMEDIATE_FILE
+ --obj=$OBJ_FILE --ddi=$DYNDEP_INTERMEDIATE_FILE \
+ --lang=Fortran
- build src.f90-pp.f90 | src.f90-pp.f90.ddi: Fortran_PREPROCESS src.f90
+ build src.f90-pp.f90 | src.f90.o.ddi: Fortran_PREPROCESS src.f90
OBJ_FILE = src.f90.o
- DEP_FILE = src.f90-pp.f90.d
- DYNDEP_INTERMEDIATE_FILE = src.f90-pp.f90.ddi
+ DEP_FILE = src.f90.o.d
+ DYNDEP_INTERMEDIATE_FILE = src.f90.o.ddi
The ``cmake -E cmake_ninja_depends`` tool reads the preprocessed output
and generates the ninja depfile for preprocessor dependencies. It also
@@ -1532,9 +1578,9 @@ Compilation of source files within a target is split into the following steps:
rule Fortran_DYNDEP
command = cmake -E cmake_ninja_dyndep \
- --tdi=FortranDependInfo.json --dd=$out $in
+ --tdi=FortranDependInfo.json --lang=Fortran --dd=$out $in
- build Fortran.dd: Fortran_DYNDEP src1.f90-pp.f90.ddi src2.f90-pp.f90.ddi
+ build Fortran.dd: Fortran_DYNDEP src1.f90.o.ddi src2.f90.o.ddi
The ``cmake -E cmake_ninja_dyndep`` tool reads the "ddi" files from all
sources in the target and the ``FortranModules.json`` files from targets
@@ -1572,6 +1618,19 @@ Compilation of source files within a target is split into the following steps:
(because the latter consumes the module).
*/
+struct cmSourceInfo
+{
+ // Set of provided and required modules.
+ std::set<std::string> Provides;
+ std::set<std::string> Requires;
+
+ // Set of files included in the translation unit.
+ std::set<std::string> Includes;
+};
+
+static std::unique_ptr<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
+ std::string const& arg_tdi, std::string const& arg_pp);
+
int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
std::vector<std::string>::const_iterator argEnd)
{
@@ -1580,8 +1639,8 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
std::string arg_dep;
std::string arg_obj;
std::string arg_ddi;
- for (std::vector<std::string>::const_iterator a = argBeg; a != argEnd; ++a) {
- std::string const& arg = *a;
+ std::string arg_lang;
+ for (std::string const& arg : cmMakeRange(argBeg, argEnd)) {
if (cmHasLiteralPrefix(arg, "--tdi=")) {
arg_tdi = arg.substr(6);
} else if (cmHasLiteralPrefix(arg, "--pp=")) {
@@ -1592,9 +1651,10 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
arg_obj = arg.substr(6);
} else if (cmHasLiteralPrefix(arg, "--ddi=")) {
arg_ddi = arg.substr(6);
+ } else if (cmHasLiteralPrefix(arg, "--lang=")) {
+ arg_lang = arg.substr(7);
} else {
- cmSystemTools::Error("-E cmake_ninja_depends unknown argument: ",
- arg.c_str());
+ cmSystemTools::Error("-E cmake_ninja_depends unknown argument: " + arg);
return 1;
}
}
@@ -1618,50 +1678,31 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
cmSystemTools::Error("-E cmake_ninja_depends requires value for --ddi=");
return 1;
}
-
- std::vector<std::string> includes;
- {
- Json::Value tdio;
- Json::Value const& tdi = tdio;
- {
- cmsys::ifstream tdif(arg_tdi.c_str(), std::ios::in | std::ios::binary);
- Json::Reader reader;
- if (!reader.parse(tdif, tdio, false)) {
- cmSystemTools::Error("-E cmake_ninja_depends failed to parse ",
- arg_tdi.c_str(),
- reader.getFormattedErrorMessages().c_str());
- return 1;
- }
- }
-
- Json::Value const& tdi_include_dirs = tdi["include-dirs"];
- if (tdi_include_dirs.isArray()) {
- for (Json::Value::const_iterator i = tdi_include_dirs.begin();
- i != tdi_include_dirs.end(); ++i) {
- includes.push_back(i->asString());
- }
- }
+ if (arg_lang.empty()) {
+ cmSystemTools::Error("-E cmake_ninja_depends requires value for --lang=");
+ return 1;
}
- cmFortranSourceInfo info;
- std::set<std::string> defines;
- cmFortranParser parser(includes, defines, info);
- if (!cmFortranParser_FilePush(&parser, arg_pp.c_str())) {
- cmSystemTools::Error("-E cmake_ninja_depends failed to open ",
- arg_pp.c_str());
+ std::unique_ptr<cmSourceInfo> info;
+ if (arg_lang == "Fortran") {
+ info = cmcmd_cmake_ninja_depends_fortran(arg_tdi, arg_pp);
+ } else {
+ cmSystemTools::Error(
+ cmStrCat("-E cmake_ninja_depends does not understand the ", arg_lang,
+ " language"));
return 1;
}
- if (cmFortran_yyparse(parser.Scanner) != 0) {
- // Failed to parse the file.
+
+ if (!info) {
+ // The error message is already expected to have been output.
return 1;
}
{
- cmGeneratedFileStream depfile(arg_dep.c_str());
+ cmGeneratedFileStream depfile(arg_dep);
depfile << cmSystemTools::ConvertToUnixOutputPath(arg_pp) << ":";
- for (std::set<std::string>::iterator i = info.Includes.begin();
- i != info.Includes.end(); ++i) {
- depfile << " \\\n " << cmSystemTools::ConvertToUnixOutputPath(*i);
+ for (std::string const& include : info->Includes) {
+ depfile << " \\\n " << cmSystemTools::ConvertToUnixOutputPath(include);
}
depfile << "\n";
}
@@ -1670,30 +1711,82 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
ddi["object"] = arg_obj;
Json::Value& ddi_provides = ddi["provides"] = Json::arrayValue;
- for (std::set<std::string>::iterator i = info.Provides.begin();
- i != info.Provides.end(); ++i) {
- ddi_provides.append(*i);
+ for (std::string const& provide : info->Provides) {
+ ddi_provides.append(provide);
}
Json::Value& ddi_requires = ddi["requires"] = Json::arrayValue;
- for (std::set<std::string>::iterator i = info.Requires.begin();
- i != info.Requires.end(); ++i) {
+ for (std::string const& r : info->Requires) {
// Require modules not provided in the same source.
- if (!info.Provides.count(*i)) {
- ddi_requires.append(*i);
+ if (!info->Provides.count(r)) {
+ ddi_requires.append(r);
}
}
- cmGeneratedFileStream ddif(arg_ddi.c_str());
+ cmGeneratedFileStream ddif(arg_ddi);
ddif << ddi;
if (!ddif) {
- cmSystemTools::Error("-E cmake_ninja_depends failed to write ",
- arg_ddi.c_str());
+ cmSystemTools::Error("-E cmake_ninja_depends failed to write " + arg_ddi);
return 1;
}
return 0;
}
-struct cmFortranObjectInfo
+std::unique_ptr<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
+ std::string const& arg_tdi, std::string const& arg_pp)
+{
+ cmFortranCompiler fc;
+ std::vector<std::string> includes;
+ {
+ Json::Value tdio;
+ Json::Value const& tdi = tdio;
+ {
+ cmsys::ifstream tdif(arg_tdi.c_str(), std::ios::in | std::ios::binary);
+ Json::Reader reader;
+ if (!reader.parse(tdif, tdio, false)) {
+ cmSystemTools::Error(
+ cmStrCat("-E cmake_ninja_depends failed to parse ", arg_tdi,
+ reader.getFormattedErrorMessages()));
+ return nullptr;
+ }
+ }
+
+ Json::Value const& tdi_include_dirs = tdi["include-dirs"];
+ if (tdi_include_dirs.isArray()) {
+ for (auto const& tdi_include_dir : tdi_include_dirs) {
+ includes.push_back(tdi_include_dir.asString());
+ }
+ }
+
+ Json::Value const& tdi_compiler_id = tdi["compiler-id"];
+ fc.Id = tdi_compiler_id.asString();
+
+ Json::Value const& tdi_submodule_sep = tdi["submodule-sep"];
+ fc.SModSep = tdi_submodule_sep.asString();
+
+ Json::Value const& tdi_submodule_ext = tdi["submodule-ext"];
+ fc.SModExt = tdi_submodule_ext.asString();
+ }
+
+ cmFortranSourceInfo finfo;
+ std::set<std::string> defines;
+ cmFortranParser parser(fc, includes, defines, finfo);
+ if (!cmFortranParser_FilePush(&parser, arg_pp.c_str())) {
+ cmSystemTools::Error("-E cmake_ninja_depends failed to open " + arg_pp);
+ return nullptr;
+ }
+ if (cmFortran_yyparse(parser.Scanner) != 0) {
+ // Failed to parse the file.
+ return nullptr;
+ }
+
+ auto info = cm::make_unique<cmSourceInfo>();
+ info->Provides = finfo.Provides;
+ info->Requires = finfo.Requires;
+ info->Includes = finfo.Includes;
+ return info;
+}
+
+struct cmDyndepObjectInfo
{
std::string Object;
std::vector<std::string> Provides;
@@ -1705,7 +1798,8 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
std::string const& dir_cur_src, std::string const& dir_cur_bld,
std::string const& arg_dd, std::vector<std::string> const& arg_ddis,
std::string const& module_dir,
- std::vector<std::string> const& linked_target_dirs)
+ std::vector<std::string> const& linked_target_dirs,
+ std::string const& arg_lang)
{
// Setup path conversions.
{
@@ -1714,62 +1808,59 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
snapshot.GetDirectory().SetCurrentBinary(dir_cur_bld);
snapshot.GetDirectory().SetRelativePathTopSource(dir_top_src.c_str());
snapshot.GetDirectory().SetRelativePathTopBinary(dir_top_bld.c_str());
- CM_AUTO_PTR<cmMakefile> mfd(new cmMakefile(this, snapshot));
- CM_AUTO_PTR<cmLocalNinjaGenerator> lgd(static_cast<cmLocalNinjaGenerator*>(
- this->CreateLocalGenerator(mfd.get())));
+ auto mfd = cm::make_unique<cmMakefile>(this, snapshot);
+ std::unique_ptr<cmLocalNinjaGenerator> lgd(
+ static_cast<cmLocalNinjaGenerator*>(
+ this->CreateLocalGenerator(mfd.get())));
this->Makefiles.push_back(mfd.release());
this->LocalGenerators.push_back(lgd.release());
}
- std::vector<cmFortranObjectInfo> objects;
- for (std::vector<std::string>::const_iterator ddii = arg_ddis.begin();
- ddii != arg_ddis.end(); ++ddii) {
+ std::vector<cmDyndepObjectInfo> objects;
+ for (std::string const& arg_ddi : arg_ddis) {
// Load the ddi file and compute the module file paths it provides.
Json::Value ddio;
Json::Value const& ddi = ddio;
- cmsys::ifstream ddif(ddii->c_str(), std::ios::in | std::ios::binary);
+ cmsys::ifstream ddif(arg_ddi.c_str(), std::ios::in | std::ios::binary);
Json::Reader reader;
if (!reader.parse(ddif, ddio, false)) {
- cmSystemTools::Error("-E cmake_ninja_dyndep failed to parse ",
- ddii->c_str(),
- reader.getFormattedErrorMessages().c_str());
+ cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
+ arg_ddi,
+ reader.getFormattedErrorMessages()));
return false;
}
- cmFortranObjectInfo info;
+ cmDyndepObjectInfo info;
info.Object = ddi["object"].asString();
Json::Value const& ddi_provides = ddi["provides"];
if (ddi_provides.isArray()) {
- for (Json::Value::const_iterator i = ddi_provides.begin();
- i != ddi_provides.end(); ++i) {
- info.Provides.push_back(i->asString());
+ for (auto const& ddi_provide : ddi_provides) {
+ info.Provides.push_back(ddi_provide.asString());
}
}
Json::Value const& ddi_requires = ddi["requires"];
if (ddi_requires.isArray()) {
- for (Json::Value::const_iterator i = ddi_requires.begin();
- i != ddi_requires.end(); ++i) {
- info.Requires.push_back(i->asString());
+ for (auto const& ddi_require : ddi_requires) {
+ 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.
std::map<std::string, std::string> mod_files;
// Populate the module map with those provided by linked targets first.
- for (std::vector<std::string>::const_iterator di =
- linked_target_dirs.begin();
- di != linked_target_dirs.end(); ++di) {
- std::string const ltmn = *di + "/FortranModules.json";
+ for (std::string const& linked_target_dir : linked_target_dirs) {
+ std::string const ltmn =
+ cmStrCat(linked_target_dir, "/", arg_lang, "Modules.json");
Json::Value ltm;
cmsys::ifstream ltmf(ltmn.c_str(), std::ios::in | std::ios::binary);
Json::Reader reader;
if (ltmf && !reader.parse(ltmf, ltm, false)) {
- cmSystemTools::Error("-E cmake_ninja_dyndep failed to parse ",
- di->c_str(),
- reader.getFormattedErrorMessages().c_str());
+ cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
+ linked_target_dir,
+ reader.getFormattedErrorMessages()));
return false;
}
if (ltm.isObject()) {
@@ -1783,55 +1874,47 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
// We do this after loading the modules provided by linked targets
// in case we have one of the same name that must be preferred.
Json::Value tm = Json::objectValue;
- for (std::vector<cmFortranObjectInfo>::iterator oi = objects.begin();
- oi != objects.end(); ++oi) {
- for (std::vector<std::string>::iterator i = oi->Provides.begin();
- i != oi->Provides.end(); ++i) {
- std::string const mod = module_dir + *i + ".mod";
- mod_files[*i] = mod;
- tm[*i] = mod;
+ for (cmDyndepObjectInfo const& object : objects) {
+ for (std::string const& p : object.Provides) {
+ std::string const mod = module_dir + p;
+ mod_files[p] = mod;
+ tm[p] = mod;
}
}
- cmGeneratedFileStream ddf(arg_dd.c_str());
+ cmGeneratedFileStream ddf(arg_dd);
ddf << "ninja_dyndep_version = 1.0\n";
- for (std::vector<cmFortranObjectInfo>::iterator oi = objects.begin();
- oi != objects.end(); ++oi) {
- std::string const ddComment;
- std::string const ddRule = "dyndep";
- cmNinjaDeps ddOutputs;
- cmNinjaDeps ddImplicitOuts;
- cmNinjaDeps ddExplicitDeps;
- cmNinjaDeps ddImplicitDeps;
- cmNinjaDeps ddOrderOnlyDeps;
- cmNinjaVars ddVars;
-
- ddOutputs.push_back(oi->Object);
- for (std::vector<std::string>::iterator i = oi->Provides.begin();
- i != oi->Provides.end(); ++i) {
- ddImplicitOuts.push_back(this->ConvertToNinjaPath(mod_files[*i]));
- }
- for (std::vector<std::string>::iterator i = oi->Requires.begin();
- i != oi->Requires.end(); ++i) {
- std::map<std::string, std::string>::iterator m = mod_files.find(*i);
- if (m != mod_files.end()) {
- ddImplicitDeps.push_back(this->ConvertToNinjaPath(m->second));
+ {
+ cmNinjaBuild build("dyndep");
+ build.Outputs.emplace_back("");
+ for (cmDyndepObjectInfo const& object : objects) {
+ build.Outputs[0] = object.Object;
+ build.ImplicitOuts.clear();
+ for (std::string const& p : object.Provides) {
+ build.ImplicitOuts.push_back(this->ConvertToNinjaPath(mod_files[p]));
+ }
+ build.ImplicitDeps.clear();
+ for (std::string const& r : object.Requires) {
+ auto mit = mod_files.find(r);
+ if (mit != mod_files.end()) {
+ build.ImplicitDeps.push_back(this->ConvertToNinjaPath(mit->second));
+ }
+ }
+ build.Variables.clear();
+ if (!object.Provides.empty()) {
+ build.Variables.emplace("restat", "1");
}
- }
- if (!oi->Provides.empty()) {
- ddVars["restat"] = "1";
- }
- this->WriteBuild(ddf, ddComment, ddRule, ddOutputs, ddImplicitOuts,
- ddExplicitDeps, ddImplicitDeps, ddOrderOnlyDeps, ddVars);
+ this->WriteBuild(ddf, build);
+ }
}
// Store the map of modules provided by this target in a file for
// use by dependents that reference this target in linked-target-dirs.
std::string const target_mods_file =
- cmSystemTools::GetFilenamePath(arg_dd) + "/FortranModules.json";
- cmGeneratedFileStream tmf(target_mods_file.c_str());
+ cmSystemTools::GetFilenamePath(arg_dd) + "/" + arg_lang + "Modules.json";
+ cmGeneratedFileStream tmf(target_mods_file);
tmf << tm;
return true;
@@ -1844,21 +1927,21 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
cmSystemTools::HandleResponseFile(argBeg, argEnd);
std::string arg_dd;
+ std::string arg_lang;
std::string arg_tdi;
std::vector<std::string> arg_ddis;
- for (std::vector<std::string>::const_iterator a = arg_full.begin();
- a != arg_full.end(); ++a) {
- std::string const& arg = *a;
+ for (std::string const& arg : arg_full) {
if (cmHasLiteralPrefix(arg, "--tdi=")) {
arg_tdi = arg.substr(6);
+ } else if (cmHasLiteralPrefix(arg, "--lang=")) {
+ arg_lang = arg.substr(7);
} else if (cmHasLiteralPrefix(arg, "--dd=")) {
arg_dd = arg.substr(5);
} else if (!cmHasLiteralPrefix(arg, "--") &&
cmHasLiteralSuffix(arg, ".ddi")) {
arg_ddis.push_back(arg);
} else {
- cmSystemTools::Error("-E cmake_ninja_dyndep unknown argument: ",
- arg.c_str());
+ cmSystemTools::Error("-E cmake_ninja_dyndep unknown argument: " + arg);
return 1;
}
}
@@ -1866,6 +1949,10 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
cmSystemTools::Error("-E cmake_ninja_dyndep requires value for --tdi=");
return 1;
}
+ if (arg_lang.empty()) {
+ cmSystemTools::Error("-E cmake_ninja_dyndep requires value for --lang=");
+ return 1;
+ }
if (arg_dd.empty()) {
cmSystemTools::Error("-E cmake_ninja_dyndep requires value for --dd=");
return 1;
@@ -1877,9 +1964,9 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
cmsys::ifstream tdif(arg_tdi.c_str(), std::ios::in | std::ios::binary);
Json::Reader reader;
if (!reader.parse(tdif, tdio, false)) {
- cmSystemTools::Error("-E cmake_ninja_dyndep failed to parse ",
- arg_tdi.c_str(),
- reader.getFormattedErrorMessages().c_str());
+ cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
+ arg_tdi,
+ reader.getFormattedErrorMessages()));
return 1;
}
}
@@ -1889,27 +1976,26 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
std::string const dir_top_bld = tdi["dir-top-bld"].asString();
std::string const dir_top_src = tdi["dir-top-src"].asString();
std::string module_dir = tdi["module-dir"].asString();
- if (!module_dir.empty()) {
+ if (!module_dir.empty() && !cmHasLiteralSuffix(module_dir, "/")) {
module_dir += "/";
}
std::vector<std::string> linked_target_dirs;
Json::Value const& tdi_linked_target_dirs = tdi["linked-target-dirs"];
if (tdi_linked_target_dirs.isArray()) {
- for (Json::Value::const_iterator i = tdi_linked_target_dirs.begin();
- i != tdi_linked_target_dirs.end(); ++i) {
- linked_target_dirs.push_back(i->asString());
+ for (auto const& tdi_linked_target_dir : tdi_linked_target_dirs) {
+ linked_target_dirs.push_back(tdi_linked_target_dir.asString());
}
}
- cmake cm(cmake::RoleInternal);
+ cmake cm(cmake::RoleInternal, cmState::Unknown);
cm.SetHomeDirectory(dir_top_src);
cm.SetHomeOutputDirectory(dir_top_bld);
- CM_AUTO_PTR<cmGlobalNinjaGenerator> ggd(
+ std::unique_ptr<cmGlobalNinjaGenerator> ggd(
static_cast<cmGlobalNinjaGenerator*>(cm.CreateGlobalGenerator("Ninja")));
- if (!ggd.get() ||
+ if (!ggd ||
!ggd->WriteDyndepFile(dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld,
- arg_dd, arg_ddis, module_dir,
- linked_target_dirs)) {
+ arg_dd, arg_ddis, module_dir, linked_target_dirs,
+ arg_lang)) {
return 1;
}
return 0;
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index b0008f74a..244e9fd38 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -3,24 +3,27 @@
#ifndef cmGlobalNinjaGenerator_h
#define cmGlobalNinjaGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <map>
+#include <memory>
#include <set>
#include <string>
+#include <unordered_map>
+#include <unordered_set>
#include <utility>
#include <vector>
+#include "cm_codecvt.hxx"
+
+#include "cmGeneratedFileStream.h"
#include "cmGlobalCommonGenerator.h"
-#include "cmGlobalGenerator.h"
#include "cmGlobalGeneratorFactory.h"
#include "cmNinjaTypes.h"
#include "cmPolicies.h"
-#include "cm_codecvt.hxx"
class cmCustomCommand;
-class cmGeneratedFileStream;
class cmGeneratorTarget;
class cmLinkLineComputer;
class cmLocalGenerator;
@@ -40,8 +43,6 @@ struct cmDocumentationEntry;
* it is handle by Ninja's -v option.
* - We don't care about computing any progress status since Ninja manages
* it itself.
- * - We don't care about generating a clean target since Ninja already have
- * a clean tool.
* - We generate one build.ninja and one rules.ninja per project.
* - We try to minimize the number of generated rules: one per target and
* language.
@@ -72,13 +73,12 @@ public:
static void WriteDivider(std::ostream& os);
static std::string EncodeRuleName(std::string const& name);
- static std::string EncodeIdent(const std::string& ident, std::ostream& vars);
static std::string EncodeLiteral(const std::string& lit);
std::string EncodePath(const std::string& path);
cmLinkLineComputer* CreateLinkLineComputer(
cmOutputConverter* outputConverter,
- cmStateDirectory const& stateDir) const CM_OVERRIDE;
+ cmStateDirectory const& stateDir) const override;
/**
* Write the given @a comment to the output stream @a os. It
@@ -98,57 +98,30 @@ public:
*/
static bool SupportsPlatform() { return false; }
- bool IsIPOSupported() const CM_OVERRIDE { return true; }
+ bool IsIPOSupported() const override { return true; }
/**
- * Write a build statement to @a os with the @a comment using
- * the @a rule the list of @a outputs files and inputs.
- * It also writes the variables bound to this build statement.
+ * Write a build statement @a build to @a os.
* @warning no escaping of any kind is done here.
*/
- void WriteBuild(std::ostream& os, const std::string& comment,
- const std::string& rule, const cmNinjaDeps& outputs,
- const cmNinjaDeps& implicitOuts,
- const cmNinjaDeps& explicitDeps,
- const cmNinjaDeps& implicitDeps,
- const cmNinjaDeps& orderOnlyDeps,
- const cmNinjaVars& variables,
- const std::string& rspfile = std::string(),
- int cmdLineLimit = 0, bool* usedResponseFile = CM_NULLPTR);
+ void WriteBuild(std::ostream& os, cmNinjaBuild const& build,
+ int cmdLineLimit = 0, bool* usedResponseFile = nullptr);
- /**
- * Helper to write a build statement with the special 'phony' rule.
- */
- void WritePhonyBuild(std::ostream& os, const std::string& comment,
- const cmNinjaDeps& outputs,
- const cmNinjaDeps& explicitDeps,
- const cmNinjaDeps& implicitDeps = cmNinjaDeps(),
- const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps(),
- const cmNinjaVars& variables = cmNinjaVars());
-
- void WriteCustomCommandBuild(const std::string& command,
- const std::string& description,
- const std::string& comment,
- const std::string& depfile, bool uses_terminal,
- bool restat, const cmNinjaDeps& outputs,
- const cmNinjaDeps& deps = cmNinjaDeps(),
- const cmNinjaDeps& orderOnly = cmNinjaDeps());
- void WriteMacOSXContentBuild(const std::string& input,
- const std::string& output);
+ void WriteCustomCommandBuild(
+ const std::string& command, const std::string& description,
+ const std::string& comment, const std::string& depfile,
+ const std::string& pool, bool uses_terminal, bool restat,
+ const cmNinjaDeps& outputs,
+ const cmNinjaDeps& explicitDeps = cmNinjaDeps(),
+ const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps());
+
+ void WriteMacOSXContentBuild(std::string input, std::string output);
/**
- * Write a rule statement named @a name to @a os with the @a comment,
- * the mandatory @a command, the @a depfile and the @a description.
- * It also writes the variables bound to this rule statement.
+ * Write a rule statement to @a os.
* @warning no escaping of any kind is done here.
*/
- static void WriteRule(std::ostream& os, const std::string& name,
- const std::string& command,
- const std::string& description,
- const std::string& comment, const std::string& depfile,
- const std::string& deptype, const std::string& rspfile,
- const std::string& rspcontent,
- const std::string& restat, bool generator);
+ static void WriteRule(std::ostream& os, cmNinjaRule const& rule);
/**
* Write a variable named @a name to @a os with value @a value and an
@@ -183,11 +156,9 @@ public:
return new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>();
}
- ~cmGlobalNinjaGenerator() CM_OVERRIDE {}
+ cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
- cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) CM_OVERRIDE;
-
- std::string GetName() const CM_OVERRIDE
+ std::string GetName() const override
{
return cmGlobalNinjaGenerator::GetActualName();
}
@@ -195,60 +166,55 @@ public:
static std::string GetActualName() { return "Ninja"; }
/** Get encoding used by generator for ninja files */
- codecvt::Encoding GetMakefileEncoding() const CM_OVERRIDE;
+ codecvt::Encoding GetMakefileEncoding() const override;
static void GetDocumentation(cmDocumentationEntry& entry);
void EnableLanguage(std::vector<std::string> const& languages,
- cmMakefile* mf, bool optional) CM_OVERRIDE;
+ cmMakefile* mf, bool optional) override;
- 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>()) CM_OVERRIDE;
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
// Setup target names
- const char* GetAllTargetName() const CM_OVERRIDE { return "all"; }
- const char* GetInstallTargetName() const CM_OVERRIDE { return "install"; }
- const char* GetInstallLocalTargetName() const CM_OVERRIDE
+ const char* GetAllTargetName() const override { return "all"; }
+ const char* GetInstallTargetName() const override { return "install"; }
+ const char* GetInstallLocalTargetName() const override
{
return "install/local";
}
- const char* GetInstallStripTargetName() const CM_OVERRIDE
+ const char* GetInstallStripTargetName() const override
{
return "install/strip";
}
- const char* GetTestTargetName() const CM_OVERRIDE { return "test"; }
- const char* GetPackageTargetName() const CM_OVERRIDE { return "package"; }
- const char* GetPackageSourceTargetName() const CM_OVERRIDE
+ const char* GetTestTargetName() const override { return "test"; }
+ const char* GetPackageTargetName() const override { return "package"; }
+ const char* GetPackageSourceTargetName() const override
{
return "package_source";
}
- const char* GetEditCacheTargetName() const CM_OVERRIDE
- {
- return "edit_cache";
- }
- const char* GetRebuildCacheTargetName() const CM_OVERRIDE
+ const char* GetEditCacheTargetName() const override { return "edit_cache"; }
+ const char* GetRebuildCacheTargetName() const override
{
return "rebuild_cache";
}
- const char* GetCleanTargetName() const CM_OVERRIDE { return "clean"; }
+ const char* GetCleanTargetName() const override { return "clean"; }
cmGeneratedFileStream* GetBuildFileStream() const
{
- return this->BuildFileStream;
+ return this->BuildFileStream.get();
}
cmGeneratedFileStream* GetRulesFileStream() const
{
- return this->RulesFileStream;
+ return this->RulesFileStream.get();
}
- std::string ConvertToNinjaPath(const std::string& path) const;
+ std::string const& ConvertToNinjaPath(const std::string& path) const;
struct MapToNinjaPathImpl
{
@@ -262,7 +228,14 @@ public:
return this->GG->ConvertToNinjaPath(path);
}
};
- MapToNinjaPathImpl MapToNinjaPath() { return MapToNinjaPathImpl(this); }
+ MapToNinjaPathImpl MapToNinjaPath() { return { this }; }
+
+ // -- Additional clean files
+ void AddAdditionalCleanFile(std::string fileName);
+ const char* GetAdditionalCleanTargetName() const
+ {
+ return "CMakeFiles/clean.additional";
+ }
void AddCXXCompileCommand(const std::string& commandLine,
const std::string& sourceFile);
@@ -272,11 +245,7 @@ public:
* Call WriteRule() behind the scene but perform some check before like:
* - Do not add twice the same rule.
*/
- void AddRule(const std::string& name, const std::string& command,
- const std::string& description, const std::string& comment,
- const std::string& depfile, const std::string& deptype,
- const std::string& rspfile, const std::string& rspcontent,
- const std::string& restat, bool generator);
+ void AddRule(cmNinjaRule const& rule);
bool HasRule(const std::string& name);
@@ -323,31 +292,34 @@ public:
cmNinjaTargetDepends depends = DependOnTargetArtifact);
void AppendTargetDependsClosure(cmGeneratorTarget const* target,
cmNinjaDeps& outputs);
- void AddDependencyToAll(cmGeneratorTarget* target);
- void AddDependencyToAll(const std::string& input);
+ void AppendTargetDependsClosure(cmGeneratorTarget const* target,
+ cmNinjaOuts& outputs, bool omit_self);
const std::vector<cmLocalGenerator*>& GetLocalGenerators() const
{
return LocalGenerators;
}
- bool IsExcluded(cmLocalGenerator* root, cmGeneratorTarget* target)
- {
- return cmGlobalGenerator::IsExcluded(root, target);
- }
-
int GetRuleCmdLength(const std::string& name) { return RuleCmdLength[name]; }
void AddTargetAlias(const std::string& alias, cmGeneratorTarget* target);
- void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const CM_OVERRIDE;
+ void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override;
// Ninja generator uses 'deps' and 'msvc_deps_prefix' introduced in 1.3
static std::string RequiredNinjaVersion() { return "1.3"; }
static std::string RequiredNinjaVersionForConsolePool() { return "1.5"; }
static std::string RequiredNinjaVersionForImplicitOuts() { return "1.7"; }
+ static std::string RequiredNinjaVersionForManifestRestat() { return "1.8"; }
+ static std::string RequiredNinjaVersionForMultilineDepfile()
+ {
+ return "1.9";
+ }
+ static std::string RequiredNinjaVersionForDyndeps() { return "1.10"; }
bool SupportsConsolePool() const;
bool SupportsImplicitOuts() const;
+ bool SupportsManifestRestat() const;
+ bool SupportsMultilineDepfile() const;
std::string NinjaOutputPath(std::string const& path) const;
bool HasOutputPathPrefix() const { return !this->OutputPathPrefix.empty(); }
@@ -360,27 +332,28 @@ public:
std::string const& arg_dd,
std::vector<std::string> const& arg_ddis,
std::string const& module_dir,
- std::vector<std::string> const& linked_target_dirs);
+ std::vector<std::string> const& linked_target_dirs,
+ std::string const& arg_lang);
protected:
- void Generate() CM_OVERRIDE;
+ void Generate() override;
- bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const CM_OVERRIDE { return true; }
+ bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; }
private:
- std::string GetEditCacheCommand() const CM_OVERRIDE;
- bool FindMakeProgram(cmMakefile* mf) CM_OVERRIDE;
+ std::string GetEditCacheCommand() const override;
+ bool FindMakeProgram(cmMakefile* mf) override;
void CheckNinjaFeatures();
bool CheckLanguages(std::vector<std::string> const& languages,
- cmMakefile* mf) const CM_OVERRIDE;
+ cmMakefile* mf) const override;
bool CheckFortran(cmMakefile* mf) const;
- void OpenBuildFileStream();
+ bool OpenBuildFileStream();
void CloseBuildFileStream();
void CloseCompileCommandsStream();
- void OpenRulesFileStream();
+ bool OpenRulesFileStream();
void CloseRulesFileStream();
/// Write the common disclaimer text at the top of each build file.
@@ -393,8 +366,9 @@ private:
void WriteUnknownExplicitDependencies(std::ostream& os);
void WriteBuiltinTargets(std::ostream& os);
- void WriteTargetAll(std::ostream& os);
+ void WriteTargetDefault(std::ostream& os);
void WriteTargetRebuildManifest(std::ostream& os);
+ bool WriteTargetCleanAdditional(std::ostream& os);
void WriteTargetClean(std::ostream& os);
void WriteTargetHelp(std::ostream& os);
@@ -402,30 +376,24 @@ private:
cmGeneratorTarget const* target,
std::set<cmGeneratorTarget const*>& depends);
- std::string ninjaCmd() const;
+ std::string CMakeCmd() const;
+ std::string NinjaCmd() const;
/// The file containing the build statement. (the relationship of the
/// compilation DAG).
- cmGeneratedFileStream* BuildFileStream;
+ std::unique_ptr<cmGeneratedFileStream> BuildFileStream;
/// The file containing the rule statements. (The action attached to each
/// edge of the compilation DAG).
- cmGeneratedFileStream* RulesFileStream;
- cmGeneratedFileStream* CompileCommandsStream;
-
- /// The type used to store the set of rules added to the generated build
- /// system.
- typedef std::set<std::string> RulesSetType;
+ std::unique_ptr<cmGeneratedFileStream> RulesFileStream;
+ std::unique_ptr<cmGeneratedFileStream> CompileCommandsStream;
/// The set of rules added to the generated build system.
- RulesSetType Rules;
+ std::unordered_set<std::string> Rules;
/// Length of rule command, used by rsp file evaluation
- std::map<std::string, int> RuleCmdLength;
+ std::unordered_map<std::string, int> RuleCmdLength;
- /// The set of dependencies to add to the "all" target.
- cmNinjaDeps AllDependencies;
-
- bool UsingGCCOnWindows;
+ bool UsingGCCOnWindows = false;
/// The set of custom commands we have seen.
std::set<cmCustomCommand const*> CustomCommands;
@@ -435,8 +403,8 @@ private:
/// Whether we are collecting known build outputs and needed
/// dependencies to determine unknown dependencies.
- bool ComputingUnknownDependencies;
- cmPolicies::PolicyStatus PolicyCMP0058;
+ bool ComputingUnknownDependencies = false;
+ cmPolicies::PolicyStatus PolicyCMP0058 = cmPolicies::WARN;
/// The combined explicit dependencies of custom build commands
std::set<std::string> CombinedCustomCommandExplicitDependencies;
@@ -446,21 +414,23 @@ private:
std::set<std::string> CombinedBuildOutputs;
/// The mapping from source file to assumed dependencies.
- std::map<std::string, std::set<std::string> > AssumedSourceDependencies;
+ std::map<std::string, std::set<std::string>> AssumedSourceDependencies;
- typedef std::map<std::string, cmGeneratorTarget*> TargetAliasMap;
+ using TargetAliasMap = std::map<std::string, cmGeneratorTarget*>;
TargetAliasMap TargetAliases;
- typedef std::map<cmGeneratorTarget const*,
- std::set<cmGeneratorTarget const*> >
- TargetDependsClosureMap;
- TargetDependsClosureMap TargetDependsClosures;
+ std::map<cmGeneratorTarget const*, cmNinjaOuts> TargetDependsClosures;
+
+ /// the local cache for calls to ConvertToNinjaPath
+ mutable std::unordered_map<std::string, std::string> ConvertToNinjaPathCache;
std::string NinjaCommand;
std::string NinjaVersion;
- bool NinjaSupportsConsolePool;
- bool NinjaSupportsImplicitOuts;
- unsigned long NinjaSupportsDyndeps;
+ bool NinjaSupportsConsolePool = false;
+ bool NinjaSupportsImplicitOuts = false;
+ bool NinjaSupportsManifestRestat = false;
+ bool NinjaSupportsMultilineDepfile = false;
+ bool NinjaSupportsDyndeps = false;
private:
void InitOutputPathPrefix();
@@ -468,6 +438,7 @@ private:
std::string OutputPathPrefix;
std::string TargetAll;
std::string CMakeCacheFile;
+ std::set<std::string> AdditionalCleanFiles;
};
#endif // ! cmGlobalNinjaGenerator_h
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 23b3718dc..4c2d69f09 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -7,6 +7,8 @@
#include <sstream>
#include <utility>
+#include <cm/memory>
+
#include "cmAlgorithms.h"
#include "cmDocumentationEntry.h"
#include "cmGeneratedFileStream.h"
@@ -20,8 +22,8 @@
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmTarget.h"
#include "cmTargetDepend.h"
#include "cmake.h"
@@ -38,7 +40,7 @@ cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3(cmake* cm)
#else
this->UseLinkScript = true;
#endif
- this->CommandDatabase = CM_NULLPTR;
+ this->CommandDatabase = nullptr;
this->IncludeDirective = "include";
this->DefineWindowsNULL = false;
@@ -50,16 +52,15 @@ void cmGlobalUnixMakefileGenerator3::EnableLanguage(
std::vector<std::string> const& languages, cmMakefile* mf, bool optional)
{
this->cmGlobalGenerator::EnableLanguage(languages, mf, optional);
- for (std::vector<std::string>::const_iterator l = languages.begin();
- l != languages.end(); ++l) {
- if (*l == "NONE") {
+ for (std::string const& language : languages) {
+ if (language == "NONE") {
continue;
}
- this->ResolveLanguageCompiler(*l, mf, optional);
+ this->ResolveLanguageCompiler(language, mf, optional);
}
}
-///! Create a local generator appropriate to this Global Generator
+//! Create a local generator appropriate to this Global Generator
cmLocalGenerator* cmGlobalUnixMakefileGenerator3::CreateLocalGenerator(
cmMakefile* mf)
{
@@ -107,11 +108,9 @@ void cmGlobalUnixMakefileGenerator3::ComputeTargetObjectDirectory(
cmGeneratorTarget* gt) const
{
// Compute full path to object file directory for this target.
- std::string dir;
- dir += gt->LocalGenerator->GetCurrentBinaryDirectory();
- dir += "/";
- dir += gt->LocalGenerator->GetTargetDirectory(gt);
- dir += "/";
+ std::string dir =
+ cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+ gt->LocalGenerator->GetTargetDirectory(gt), '/');
gt->ObjectDirectory = dir;
}
@@ -130,9 +129,8 @@ void cmGlobalUnixMakefileGenerator3::Generate()
// initialize progress
unsigned long total = 0;
- for (ProgressMapType::const_iterator pmi = this->ProgressMap.begin();
- pmi != this->ProgressMap.end(); ++pmi) {
- total += pmi->second.NumberOfActions;
+ for (auto const& pmi : this->ProgressMap) {
+ total += pmi.second.NumberOfActions;
}
// write each target's progress.make this loop is done twice. Bascially the
@@ -143,17 +141,13 @@ void cmGlobalUnixMakefileGenerator3::Generate()
// well. This is because the all targets require more information that is
// computed in the first loop.
unsigned long current = 0;
- for (ProgressMapType::iterator pmi = this->ProgressMap.begin();
- pmi != this->ProgressMap.end(); ++pmi) {
- pmi->second.WriteProgressVariables(total, current);
- }
- for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
- cmLocalGenerator* lg = this->LocalGenerators[i];
- std::string markFileName = lg->GetCurrentBinaryDirectory();
- markFileName += "/";
- markFileName += cmake::GetCMakeFilesDirectory();
- markFileName += "/progress.marks";
- cmGeneratedFileStream markFile(markFileName.c_str());
+ for (auto& pmi : this->ProgressMap) {
+ pmi.second.WriteProgressVariables(total, current);
+ }
+ for (cmLocalGenerator* lg : this->LocalGenerators) {
+ std::string markFileName =
+ cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles/progress.marks");
+ cmGeneratedFileStream markFile(markFileName);
markFile << this->CountProgressMarksInAll(lg) << "\n";
}
@@ -161,10 +155,10 @@ void cmGlobalUnixMakefileGenerator3::Generate()
this->WriteMainMakefile2();
this->WriteMainCMakefile();
- if (this->CommandDatabase != CM_NULLPTR) {
+ if (this->CommandDatabase != nullptr) {
*this->CommandDatabase << std::endl << "]";
delete this->CommandDatabase;
- this->CommandDatabase = CM_NULLPTR;
+ this->CommandDatabase = nullptr;
}
}
@@ -172,24 +166,23 @@ void cmGlobalUnixMakefileGenerator3::AddCXXCompileCommand(
const std::string& sourceFile, const std::string& workingDirectory,
const std::string& compileCommand)
{
- if (this->CommandDatabase == CM_NULLPTR) {
+ if (this->CommandDatabase == nullptr) {
std::string commandDatabaseName =
- std::string(this->GetCMakeInstance()->GetHomeOutputDirectory()) +
+ this->GetCMakeInstance()->GetHomeOutputDirectory() +
"/compile_commands.json";
- this->CommandDatabase =
- new cmGeneratedFileStream(commandDatabaseName.c_str());
+ this->CommandDatabase = new cmGeneratedFileStream(commandDatabaseName);
*this->CommandDatabase << "[" << std::endl;
} else {
*this->CommandDatabase << "," << std::endl;
}
*this->CommandDatabase << "{" << std::endl
- << " \"directory\": \""
+ << R"( "directory": ")"
<< cmGlobalGenerator::EscapeJSON(workingDirectory)
<< "\"," << std::endl
- << " \"command\": \""
+ << R"( "command": ")"
<< cmGlobalGenerator::EscapeJSON(compileCommand)
<< "\"," << std::endl
- << " \"file\": \""
+ << R"( "file": ")"
<< cmGlobalGenerator::EscapeJSON(sourceFile) << "\""
<< std::endl
<< "}";
@@ -201,10 +194,9 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
// because the check-build-system step compares the makefile time to
// see if the build system must be regenerated.
std::string makefileName =
- this->GetCMakeInstance()->GetHomeOutputDirectory();
- makefileName += cmake::GetCMakeFilesDirectory();
- makefileName += "/Makefile2";
- cmGeneratedFileStream makefileStream(makefileName.c_str(), false,
+ cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
+ "/CMakeFiles/Makefile2");
+ cmGeneratedFileStream makefileStream(makefileName, false,
this->GetMakefileEncoding());
if (!makefileStream) {
return;
@@ -222,7 +214,7 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
// Just depend on the all target to drive the build.
std::vector<std::string> depends;
std::vector<std::string> no_commands;
- depends.push_back("all");
+ depends.emplace_back("all");
// Write the rule.
lg->WriteMakeRule(makefileStream,
@@ -234,49 +226,47 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
// The all and preinstall rules might never have any dependencies
// added to them.
- if (this->EmptyRuleHackDepends != "") {
+ if (!this->EmptyRuleHackDepends.empty()) {
depends.push_back(this->EmptyRuleHackDepends);
}
- // Write and empty all:
- lg->WriteMakeRule(makefileStream, "The main recursive all target", "all",
- depends, no_commands, true);
-
- // Write an empty preinstall:
- lg->WriteMakeRule(makefileStream, "The main recursive preinstall target",
- "preinstall", depends, no_commands, true);
-
// Write out the "special" stuff
lg->WriteSpecialTargetsTop(makefileStream);
- // write the target convenience rules
- unsigned int i;
- for (i = 0; i < this->LocalGenerators.size(); ++i) {
- lg = static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[i]);
- this->WriteConvenienceRules2(makefileStream, lg);
+ // Write the directory level rules.
+ for (auto const& it : this->ComputeDirectoryTargets()) {
+ this->WriteDirectoryRules2(makefileStream, it.second);
}
- lg = static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[0]);
+ // Write the target convenience rules
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ this->WriteConvenienceRules2(
+ makefileStream, static_cast<cmLocalUnixMakefileGenerator3*>(localGen));
+ }
+
+ // Write special bottom targets
lg->WriteSpecialTargetsBottom(makefileStream);
}
void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
{
+ if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ return;
+ }
+
// Open the output file. This should not be copy-if-different
// because the check-build-system step compares the makefile time to
// see if the build system must be regenerated.
std::string cmakefileName =
- this->GetCMakeInstance()->GetHomeOutputDirectory();
- cmakefileName += cmake::GetCMakeFilesDirectory();
- cmakefileName += "/Makefile.cmake";
- cmGeneratedFileStream cmakefileStream(cmakefileName.c_str());
+ cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
+ "/CMakeFiles/Makefile.cmake");
+ cmGeneratedFileStream cmakefileStream(cmakefileName);
if (!cmakefileStream) {
return;
}
std::string makefileName =
- this->GetCMakeInstance()->GetHomeOutputDirectory();
- makefileName += "/Makefile";
+ cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), "/Makefile");
// get a local generator for some useful methods
cmLocalUnixMakefileGenerator3* lg =
@@ -292,18 +282,21 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
// for each cmMakefile get its list of dependencies
std::vector<std::string> lfiles;
- for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
- lg = static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[i]);
-
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
// Get the list of files contributing to this generation step.
- lfiles.insert(lfiles.end(), lg->GetMakefile()->GetListFiles().begin(),
- lg->GetMakefile()->GetListFiles().end());
+ cmAppend(lfiles, localGen->GetMakefile()->GetListFiles());
+ }
+
+ cmake* cm = this->GetCMakeInstance();
+ if (cm->DoWriteGlobVerifyTarget()) {
+ lfiles.push_back(cm->GetGlobVerifyScript());
+ lfiles.push_back(cm->GetGlobVerifyStamp());
}
+
// Sort the list and remove duplicates.
std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
#if !defined(__VMS) // The Compaq STL on VMS crashes, so accept duplicates.
- std::vector<std::string>::iterator new_end =
- std::unique(lfiles.begin(), lfiles.end());
+ auto new_end = std::unique(lfiles.begin(), lfiles.end());
lfiles.erase(new_end, lfiles.end());
#endif
@@ -316,25 +309,27 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
<< "# The top level Makefile was generated from the following files:\n"
<< "set(CMAKE_MAKEFILE_DEPENDS\n"
<< " \"CMakeCache.txt\"\n";
- for (std::vector<std::string>::const_iterator i = lfiles.begin();
- i != lfiles.end(); ++i) {
- cmakefileStream << " \"" << lg->ConvertToRelativePath(currentBinDir, *i)
+ for (std::string const& f : lfiles) {
+ cmakefileStream << " \""
+ << lg->MaybeConvertToRelativePath(currentBinDir, f)
<< "\"\n";
}
cmakefileStream << " )\n\n";
// Build the path to the cache check file.
- std::string check = this->GetCMakeInstance()->GetHomeOutputDirectory();
- check += cmake::GetCMakeFilesDirectory();
- check += "/cmake.check_cache";
+ std::string check =
+ cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
+ "/CMakeFiles/cmake.check_cache");
// Set the corresponding makefile in the cmake file.
cmakefileStream << "# The corresponding makefile is:\n"
<< "set(CMAKE_MAKEFILE_OUTPUTS\n"
<< " \""
- << lg->ConvertToRelativePath(currentBinDir, makefileName)
+ << lg->MaybeConvertToRelativePath(currentBinDir,
+ makefileName)
<< "\"\n"
- << " \"" << lg->ConvertToRelativePath(currentBinDir, check)
+ << " \""
+ << lg->MaybeConvertToRelativePath(currentBinDir, check)
<< "\"\n";
cmakefileStream << " )\n\n";
@@ -344,23 +339,20 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
{
cmakefileStream << "# Byproducts of CMake generate step:\n"
<< "set(CMAKE_MAKEFILE_PRODUCTS\n";
- const std::vector<std::string>& outfiles =
- lg->GetMakefile()->GetOutputFiles();
- for (std::vector<std::string>::const_iterator k = outfiles.begin();
- k != outfiles.end(); ++k) {
- cmakefileStream << " \"" << lg->ConvertToRelativePath(binDir, *k)
+ for (std::string const& outfile : lg->GetMakefile()->GetOutputFiles()) {
+ cmakefileStream << " \""
+ << lg->MaybeConvertToRelativePath(binDir, outfile)
<< "\"\n";
}
// add in all the directory information files
std::string tmpStr;
- for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
- lg =
- static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[i]);
- tmpStr = lg->GetCurrentBinaryDirectory();
- tmpStr += cmake::GetCMakeFilesDirectory();
- tmpStr += "/CMakeDirectoryInformation.cmake";
- cmakefileStream << " \"" << lg->ConvertToRelativePath(binDir, tmpStr)
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ lg = static_cast<cmLocalUnixMakefileGenerator3*>(localGen);
+ tmpStr = cmStrCat(lg->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/CMakeDirectoryInformation.cmake");
+ cmakefileStream << " \""
+ << lg->MaybeConvertToRelativePath(binDir, tmpStr)
<< "\"\n";
}
cmakefileStream << " )\n\n";
@@ -379,21 +371,19 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefileLanguageRules(
// now list all the target info files
cmakefileStream << "# Dependency information for all targets:\n";
cmakefileStream << "set(CMAKE_DEPEND_INFO_FILES\n";
- for (unsigned int i = 0; i < lGenerators.size(); ++i) {
- lg = static_cast<cmLocalUnixMakefileGenerator3*>(lGenerators[i]);
+ for (cmLocalGenerator* lGenerator : lGenerators) {
+ lg = static_cast<cmLocalUnixMakefileGenerator3*>(lGenerator);
// for all of out targets
- std::vector<cmGeneratorTarget*> tgts = lg->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin();
- l != tgts.end(); l++) {
- if (((*l)->GetType() == cmStateEnums::EXECUTABLE) ||
- ((*l)->GetType() == cmStateEnums::STATIC_LIBRARY) ||
- ((*l)->GetType() == cmStateEnums::SHARED_LIBRARY) ||
- ((*l)->GetType() == cmStateEnums::MODULE_LIBRARY) ||
- ((*l)->GetType() == cmStateEnums::OBJECT_LIBRARY) ||
- ((*l)->GetType() == cmStateEnums::UTILITY)) {
- cmGeneratorTarget* gt = *l;
- std::string tname = lg->GetRelativeTargetDirectory(gt);
- tname += "/DependInfo.cmake";
+ for (cmGeneratorTarget* tgt : lg->GetGeneratorTargets()) {
+ if ((tgt->GetType() == cmStateEnums::EXECUTABLE) ||
+ (tgt->GetType() == cmStateEnums::STATIC_LIBRARY) ||
+ (tgt->GetType() == cmStateEnums::SHARED_LIBRARY) ||
+ (tgt->GetType() == cmStateEnums::MODULE_LIBRARY) ||
+ (tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) ||
+ (tgt->GetType() == cmStateEnums::UTILITY)) {
+ cmGeneratorTarget* gt = tgt;
+ std::string tname =
+ cmStrCat(lg->GetRelativeTargetDirectory(gt), "/DependInfo.cmake");
cmSystemTools::ConvertToUnixSlashes(tname);
cmakefileStream << " \"" << tname << "\"\n";
}
@@ -403,134 +393,144 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefileLanguageRules(
}
void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
- std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3* lg,
- const char* pass, bool check_all, bool check_relink)
+ std::ostream& ruleFileStream, DirectoryTarget const& dt, const char* pass,
+ bool check_all, bool check_relink, std::vector<std::string> const& commands)
{
- // Get the relative path to the subdirectory from the top.
- std::string makeTarget = lg->GetCurrentBinaryDirectory();
- makeTarget += "/";
- makeTarget += pass;
+ auto* lg = static_cast<cmLocalUnixMakefileGenerator3*>(dt.LG);
+ std::string makeTarget =
+ cmStrCat(lg->GetCurrentBinaryDirectory(), '/', pass);
// The directory-level rule should depend on the target-level rules
// for all targets in the directory.
std::vector<std::string> depends;
- std::vector<cmGeneratorTarget*> targets = lg->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator l = targets.begin();
- l != targets.end(); ++l) {
- cmGeneratorTarget* gtarget = *l;
- int type = gtarget->GetType();
- if ((type == cmStateEnums::EXECUTABLE) ||
- (type == cmStateEnums::STATIC_LIBRARY) ||
- (type == cmStateEnums::SHARED_LIBRARY) ||
- (type == cmStateEnums::MODULE_LIBRARY) ||
- (type == cmStateEnums::OBJECT_LIBRARY) ||
- (type == cmStateEnums::UTILITY)) {
- // Add this to the list of depends rules in this directory.
- if ((!check_all || !gtarget->GetPropertyAsBool("EXCLUDE_FROM_ALL")) &&
- (!check_relink ||
- gtarget->NeedRelinkBeforeInstall(lg->GetConfigName()))) {
- std::string tname = lg->GetRelativeTargetDirectory(gtarget);
- tname += "/";
- tname += pass;
- depends.push_back(tname);
- }
+ for (DirectoryTarget::Target const& t : dt.Targets) {
+ // Add this to the list of depends rules in this directory.
+ if ((!check_all || !t.ExcludeFromAll) &&
+ (!check_relink ||
+ t.GT->NeedRelinkBeforeInstall(lg->GetConfigName()))) {
+ // The target may be from a different directory; use its local gen.
+ auto const* tlg = static_cast<cmLocalUnixMakefileGenerator3 const*>(
+ t.GT->GetLocalGenerator());
+ std::string tname =
+ cmStrCat(tlg->GetRelativeTargetDirectory(t.GT), '/', pass);
+ depends.push_back(std::move(tname));
}
}
// The directory-level rule should depend on the directory-level
// rules of the subdirectories.
- std::vector<cmStateSnapshot> children = lg->GetStateSnapshot().GetChildren();
- for (std::vector<cmStateSnapshot>::const_iterator ci = children.begin();
- ci != children.end(); ++ci) {
- std::string subdir = ci->GetDirectory().GetCurrentBinary();
- subdir += "/";
- subdir += pass;
- depends.push_back(subdir);
+ for (DirectoryTarget::Dir const& d : dt.Children) {
+ if (check_all && d.ExcludeFromAll) {
+ continue;
+ }
+ std::string subdir = cmStrCat(d.Path, '/', pass);
+ depends.push_back(std::move(subdir));
}
// Work-around for makes that drop rules that have no dependencies
// or commands.
- if (depends.empty() && this->EmptyRuleHackDepends != "") {
+ if (depends.empty() && !this->EmptyRuleHackDepends.empty()) {
depends.push_back(this->EmptyRuleHackDepends);
}
// Write the rule.
- std::string doc = "Convenience name for \"";
- doc += pass;
- doc += "\" pass in the directory.";
- std::vector<std::string> no_commands;
- lg->WriteMakeRule(ruleFileStream, doc.c_str(), makeTarget, depends,
- no_commands, true);
+ std::string doc;
+ if (lg->IsRootMakefile()) {
+ doc = cmStrCat("The main recursive \"", pass, "\" target.");
+ } else {
+ doc = cmStrCat("Recursive \"", pass, "\" directory target.");
+ }
+ lg->WriteMakeRule(ruleFileStream, doc.c_str(), makeTarget, depends, commands,
+ true);
}
void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
- std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3* lg)
+ std::ostream& ruleFileStream, DirectoryTarget const& dt)
{
- // Only subdirectories need these rules.
- if (lg->IsRootMakefile()) {
- return;
- }
-
+ auto* lg = static_cast<cmLocalUnixMakefileGenerator3*>(dt.LG);
// Begin the directory-level rules section.
- std::string dir = cmSystemTools::ConvertToOutputPath(
- lg->ConvertToRelativePath(lg->GetBinaryDirectory(),
- lg->GetCurrentBinaryDirectory())
- .c_str());
- lg->WriteDivider(ruleFileStream);
- ruleFileStream << "# Directory level rules for directory " << dir << "\n\n";
+ {
+ std::string dir =
+ cmSystemTools::ConvertToOutputPath(lg->MaybeConvertToRelativePath(
+ lg->GetBinaryDirectory(), lg->GetCurrentBinaryDirectory()));
+ lg->WriteDivider(ruleFileStream);
+ if (lg->IsRootMakefile()) {
+ ruleFileStream << "# Directory level rules for the build root directory";
+ } else {
+ ruleFileStream << "# Directory level rules for directory " << dir;
+ }
+ ruleFileStream << "\n\n";
+ }
// Write directory-level rules for "all".
- this->WriteDirectoryRule2(ruleFileStream, lg, "all", true, false);
-
- // Write directory-level rules for "clean".
- this->WriteDirectoryRule2(ruleFileStream, lg, "clean", false, false);
+ this->WriteDirectoryRule2(ruleFileStream, dt, "all", true, false);
// Write directory-level rules for "preinstall".
- this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", true, true);
+ this->WriteDirectoryRule2(ruleFileStream, dt, "preinstall", true, true);
+
+ // Write directory-level rules for "clean".
+ {
+ std::vector<std::string> cmds;
+ lg->AppendDirectoryCleanCommand(cmds);
+ this->WriteDirectoryRule2(ruleFileStream, dt, "clean", false, false, cmds);
+ }
}
-void cmGlobalUnixMakefileGenerator3::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<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& /*projectName*/,
+ const std::string& /*projectDir*/,
+ std::vector<std::string> const& targetNames, const std::string& /*config*/,
+ bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions)
{
- makeCommand.push_back(this->SelectMakeProgram(makeProgram));
-
- // Since we have full control over the invocation of nmake, let us
- // make it quiet.
- if (cmHasLiteralPrefix(this->GetName(), "NMake Makefiles")) {
- makeCommand.push_back("/NOLOGO");
- }
- makeCommand.insert(makeCommand.end(), makeOptions.begin(),
- makeOptions.end());
- if (!targetName.empty()) {
- cmMakefile* mf;
- if (!this->Makefiles.empty()) {
- mf = this->Makefiles[0];
- } else {
- cmStateSnapshot snapshot = this->CMakeInstance->GetCurrentSnapshot();
- snapshot.GetDirectory().SetCurrentSource(
- this->CMakeInstance->GetHomeDirectory());
- snapshot.GetDirectory().SetCurrentBinary(
- this->CMakeInstance->GetHomeOutputDirectory());
- snapshot.SetDefaultDefinitions();
- mf = new cmMakefile(this, snapshot);
+ std::unique_ptr<cmMakefile> mfu;
+ cmMakefile* mf;
+ if (!this->Makefiles.empty()) {
+ mf = this->Makefiles[0];
+ } else {
+ cmStateSnapshot snapshot = this->CMakeInstance->GetCurrentSnapshot();
+ snapshot.GetDirectory().SetCurrentSource(
+ this->CMakeInstance->GetHomeDirectory());
+ snapshot.GetDirectory().SetCurrentBinary(
+ this->CMakeInstance->GetHomeOutputDirectory());
+ snapshot.SetDefaultDefinitions();
+ mfu = cm::make_unique<cmMakefile>(this, snapshot);
+ mf = mfu.get();
+ }
+
+ GeneratedMakeCommand makeCommand;
+
+ // Make it possible to set verbosity also from command line
+ if (verbose) {
+ makeCommand.Add(cmSystemTools::GetCMakeCommand());
+ makeCommand.Add("-E");
+ makeCommand.Add("env");
+ makeCommand.Add("VERBOSE=1");
+ }
+ makeCommand.Add(this->SelectMakeProgram(makeProgram));
+
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ makeCommand.Add("-j");
+ if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ makeCommand.Add(std::to_string(jobs));
}
+ }
- std::string tname = targetName;
- if (fast) {
- tname += "/fast";
- }
- cmOutputConverter conv(mf->GetStateSnapshot());
- tname =
- conv.ConvertToRelativePath(mf->GetState()->GetBinaryDirectory(), tname);
- cmSystemTools::ConvertToOutputSlashes(tname);
- makeCommand.push_back(tname);
- if (this->Makefiles.empty()) {
- delete mf;
+ makeCommand.Add(makeOptions.begin(), makeOptions.end());
+ for (auto tname : targetNames) {
+ if (!tname.empty()) {
+ if (fast) {
+ tname += "/fast";
+ }
+ tname =
+ mf->GetStateSnapshot().GetDirectory().ConvertToRelPathIfNotContained(
+ mf->GetState()->GetBinaryDirectory(), tname);
+ cmSystemTools::ConvertToOutputSlashes(tname);
+ makeCommand.Add(std::move(tname));
}
}
+ return { std::move(makeCommand) };
}
void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules(
@@ -539,18 +539,17 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules(
std::vector<std::string> depends;
std::vector<std::string> commands;
- depends.push_back("cmake_check_build_system");
+ bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
+ if (regenerate) {
+ depends.emplace_back("cmake_check_build_system");
+ }
// write the target convenience rules
- unsigned int i;
- cmLocalUnixMakefileGenerator3* lg;
- for (i = 0; i < this->LocalGenerators.size(); ++i) {
- lg = static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[i]);
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ cmLocalUnixMakefileGenerator3* lg =
+ static_cast<cmLocalUnixMakefileGenerator3*>(localGen);
// for each target Generate the rule files for each target.
- std::vector<cmGeneratorTarget*> targets = lg->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator t = targets.begin();
- t != targets.end(); ++t) {
- cmGeneratorTarget* gtarget = *t;
+ for (cmGeneratorTarget* gtarget : lg->GetGeneratorTargets()) {
// Don't emit the same rule twice (e.g. two targets with the same
// simple name)
int type = gtarget->GetType();
@@ -571,41 +570,38 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules(
// Write the rule.
commands.clear();
- std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
- tmp += "Makefile2";
- commands.push_back(lg->GetRecursiveMakeCall(tmp.c_str(), name));
+ std::string tmp = "CMakeFiles/Makefile2";
+ commands.push_back(lg->GetRecursiveMakeCall(tmp, name));
depends.clear();
- depends.push_back("cmake_check_build_system");
+ if (regenerate) {
+ depends.emplace_back("cmake_check_build_system");
+ }
lg->WriteMakeRule(ruleFileStream, "Build rule for target.", name,
depends, commands, true);
// Add a fast rule to build the target
std::string localName = lg->GetRelativeTargetDirectory(gtarget);
std::string makefileName;
- makefileName = localName;
- makefileName += "/build.make";
+ makefileName = cmStrCat(localName, "/build.make");
depends.clear();
commands.clear();
- std::string makeTargetName = localName;
- makeTargetName += "/build";
- localName = name;
- localName += "/fast";
+ std::string makeTargetName = cmStrCat(localName, "/build");
+ localName = cmStrCat(name, "/fast");
commands.push_back(
- lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName));
+ lg->GetRecursiveMakeCall(makefileName, makeTargetName));
lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
localName, depends, commands, true);
// Add a local name for the rule to relink the target before
// installation.
if (gtarget->NeedRelinkBeforeInstall(lg->GetConfigName())) {
- makeTargetName = lg->GetRelativeTargetDirectory(gtarget);
- makeTargetName += "/preinstall";
- localName = name;
- localName += "/preinstall";
+ makeTargetName =
+ cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/preinstall");
+ localName = cmStrCat(name, "/preinstall");
depends.clear();
commands.clear();
commands.push_back(
- lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName));
+ lg->GetRecursiveMakeCall(makefileName, makeTargetName));
lg->WriteMakeRule(ruleFileStream,
"Manual pre-install relink rule for target.",
localName, depends, commands, true);
@@ -623,68 +619,50 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
std::string localName;
std::string makeTargetName;
- // write the directory level rules for this local gen
- this->WriteDirectoryRules2(ruleFileStream, lg);
-
- depends.push_back("cmake_check_build_system");
+ bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
+ if (regenerate) {
+ depends.emplace_back("cmake_check_build_system");
+ }
// for each target Generate the rule files for each target.
- std::vector<cmGeneratorTarget*> targets = lg->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator t = targets.begin();
- t != targets.end(); ++t) {
- cmGeneratorTarget* gtarget = *t;
+ for (cmGeneratorTarget* gtarget : lg->GetGeneratorTargets()) {
int type = gtarget->GetType();
std::string name = gtarget->GetName();
- if (!name.empty() && ((type == cmStateEnums::EXECUTABLE) ||
- (type == cmStateEnums::STATIC_LIBRARY) ||
- (type == cmStateEnums::SHARED_LIBRARY) ||
- (type == cmStateEnums::MODULE_LIBRARY) ||
- (type == cmStateEnums::OBJECT_LIBRARY) ||
- (type == cmStateEnums::UTILITY))) {
+ if (!name.empty() &&
+ ((type == cmStateEnums::EXECUTABLE) ||
+ (type == cmStateEnums::STATIC_LIBRARY) ||
+ (type == cmStateEnums::SHARED_LIBRARY) ||
+ (type == cmStateEnums::MODULE_LIBRARY) ||
+ (type == cmStateEnums::OBJECT_LIBRARY) ||
+ (type == cmStateEnums::UTILITY))) {
std::string makefileName;
// Add a rule to build the target by name.
localName = lg->GetRelativeTargetDirectory(gtarget);
- makefileName = localName;
- makefileName += "/build.make";
-
- bool needRequiresStep = this->NeedRequiresStep(gtarget);
+ makefileName = cmStrCat(localName, "/build.make");
lg->WriteDivider(ruleFileStream);
ruleFileStream << "# Target rules for target " << localName << "\n\n";
commands.clear();
- makeTargetName = localName;
- makeTargetName += "/depend";
+ makeTargetName = cmStrCat(localName, "/depend");
commands.push_back(
- lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName));
+ lg->GetRecursiveMakeCall(makefileName, 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";
+ makeTargetName = cmStrCat(localName, "/build");
commands.push_back(
- lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName));
+ lg->GetRecursiveMakeCall(makefileName, makeTargetName));
// Write the rule.
localName += "/all";
depends.clear();
cmLocalUnixMakefileGenerator3::EchoProgress progress;
- progress.Dir = lg->GetBinaryDirectory();
- progress.Dir += cmake::GetCMakeFilesDirectory();
+ progress.Dir = cmStrCat(lg->GetBinaryDirectory(), "/CMakeFiles");
{
std::ostringstream progressArg;
const char* sep = "";
- std::vector<unsigned long>& progFiles =
- this->ProgressMap[gtarget].Marks;
- for (std::vector<unsigned long>::iterator i = progFiles.begin();
- i != progFiles.end(); ++i) {
- progressArg << sep << *i;
+ for (unsigned long progFile : this->ProgressMap[gtarget].Marks) {
+ progressArg << sep << progFile;
sep = ",";
}
progress.Arg = progressArg.str();
@@ -694,7 +672,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
if (const char* tgtMsg =
this->GetCMakeInstance()->GetState()->GetGlobalProperty(
"TARGET_MESSAGES")) {
- targetMessages = cmSystemTools::IsOn(tgtMsg);
+ targetMessages = cmIsOn(tgtMsg);
}
if (targetMessages) {
@@ -706,15 +684,6 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
localName, depends, commands, true);
- // add the all/all dependency
- if (!this->IsExcluded(this->LocalGenerators[0], gtarget)) {
- depends.clear();
- depends.push_back(localName);
- commands.clear();
- lg->WriteMakeRule(ruleFileStream, "Include target in all.", "all",
- depends, commands, true);
- }
-
// Write the rule.
commands.clear();
@@ -731,9 +700,8 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
progCmd << " " << this->CountProgressMarksInTarget(gtarget, emitted);
commands.push_back(progCmd.str());
}
- std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
- tmp += "Makefile2";
- commands.push_back(lg->GetRecursiveMakeCall(tmp.c_str(), localName));
+ std::string tmp = "CMakeFiles/Makefile2";
+ commands.push_back(lg->GetRecursiveMakeCall(tmp, localName));
{
std::ostringstream progCmd;
progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
@@ -744,9 +712,10 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
commands.push_back(progCmd.str());
}
depends.clear();
- depends.push_back("cmake_check_build_system");
- localName = lg->GetRelativeTargetDirectory(gtarget);
- localName += "/rule";
+ if (regenerate) {
+ depends.emplace_back("cmake_check_build_system");
+ }
+ localName = cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/rule");
lg->WriteMakeRule(ruleFileStream,
"Build rule for subdir invocation for target.",
localName, depends, commands, true);
@@ -760,58 +729,38 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
// Add rules to prepare the target for installation.
if (gtarget->NeedRelinkBeforeInstall(lg->GetConfigName())) {
- localName = lg->GetRelativeTargetDirectory(gtarget);
- localName += "/preinstall";
+ localName =
+ cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/preinstall");
depends.clear();
commands.clear();
- commands.push_back(
- lg->GetRecursiveMakeCall(makefileName.c_str(), localName));
+ commands.push_back(lg->GetRecursiveMakeCall(makefileName, localName));
lg->WriteMakeRule(ruleFileStream,
"Pre-install relink rule for target.", localName,
depends, commands, true);
-
- if (!this->IsExcluded(this->LocalGenerators[0], gtarget)) {
- depends.clear();
- depends.push_back(localName);
- commands.clear();
- lg->WriteMakeRule(ruleFileStream, "Prepare target for install.",
- "preinstall", depends, commands, true);
- }
}
// add the clean rule
localName = lg->GetRelativeTargetDirectory(gtarget);
- makeTargetName = localName;
- makeTargetName += "/clean";
+ makeTargetName = cmStrCat(localName, "/clean");
depends.clear();
commands.clear();
commands.push_back(
- lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName));
+ lg->GetRecursiveMakeCall(makefileName, makeTargetName));
lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
makeTargetName, depends, commands, true);
commands.clear();
- depends.push_back(makeTargetName);
- lg->WriteMakeRule(ruleFileStream, "clean rule for target.", "clean",
- depends, commands, true);
}
}
}
-// Build a map that contains a the set of targets used by each local
+// Build a map that contains the set of targets used by each local
// generator directory level.
void cmGlobalUnixMakefileGenerator3::InitializeProgressMarks()
{
this->DirectoryTargetsMap.clear();
// Loop over all targets in all local generators.
- for (std::vector<cmLocalGenerator*>::const_iterator lgi =
- this->LocalGenerators.begin();
- lgi != this->LocalGenerators.end(); ++lgi) {
- cmLocalGenerator* lg = *lgi;
- std::vector<cmGeneratorTarget*> targets = lg->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::const_iterator t = targets.begin();
- t != targets.end(); ++t) {
- cmGeneratorTarget* gt = *t;
-
+ for (cmLocalGenerator* lg : this->LocalGenerators) {
+ for (cmGeneratorTarget* gt : lg->GetGeneratorTargets()) {
cmLocalGenerator* tlg = gt->GetLocalGenerator();
if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
@@ -834,10 +783,8 @@ void cmGlobalUnixMakefileGenerator3::InitializeProgressMarks()
// Add dependencies of the included target. An excluded
// target may still be included if it is a dependency of a
// non-excluded target.
- TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(gt);
- for (TargetDependSet::const_iterator ti = tgtdeps.begin();
- ti != tgtdeps.end(); ++ti) {
- targetSet.insert(*ti);
+ for (cmTargetDepend const& tgtdep : this->GetTargetDirectDepends(gt)) {
+ targetSet.insert(tgtdep);
}
}
}
@@ -850,13 +797,11 @@ size_t cmGlobalUnixMakefileGenerator3::CountProgressMarksInTarget(
size_t count = 0;
if (emitted.insert(target).second) {
count = this->ProgressMap[target].Marks.size();
- TargetDependSet const& depends = this->GetTargetDirectDepends(target);
- for (TargetDependSet::const_iterator di = depends.begin();
- di != depends.end(); ++di) {
- if ((*di)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ for (cmTargetDepend const& depend : this->GetTargetDirectDepends(target)) {
+ if (depend->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
- count += this->CountProgressMarksInTarget(*di, emitted);
+ count += this->CountProgressMarksInTarget(depend, emitted);
}
}
return count;
@@ -867,11 +812,9 @@ size_t cmGlobalUnixMakefileGenerator3::CountProgressMarksInAll(
{
size_t count = 0;
std::set<cmGeneratorTarget const*> emitted;
- std::set<cmGeneratorTarget const*> const& targets =
- this->DirectoryTargetsMap[lg->GetStateSnapshot()];
- for (std::set<cmGeneratorTarget const*>::const_iterator t = targets.begin();
- t != targets.end(); ++t) {
- count += this->CountProgressMarksInTarget(*t, emitted);
+ for (cmGeneratorTarget const* target :
+ this->DirectoryTargetsMap[lg->GetStateSnapshot()]) {
+ count += this->CountProgressMarksInTarget(target, emitted);
}
return count;
}
@@ -887,7 +830,7 @@ void cmGlobalUnixMakefileGenerator3::RecordTargetProgress(
void cmGlobalUnixMakefileGenerator3::TargetProgress::WriteProgressVariables(
unsigned long total, unsigned long& current)
{
- cmGeneratedFileStream fout(this->VariableFile.c_str());
+ cmGeneratedFileStream fout(this->VariableFile);
for (unsigned long i = 1; i <= this->NumberOfActions; ++i) {
fout << "CMAKE_PROGRESS_" << i << " = ";
if (total <= 100) {
@@ -909,19 +852,17 @@ void cmGlobalUnixMakefileGenerator3::TargetProgress::WriteProgressVariables(
void cmGlobalUnixMakefileGenerator3::AppendGlobalTargetDepends(
std::vector<std::string>& depends, cmGeneratorTarget* target)
{
- TargetDependSet const& depends_set = this->GetTargetDirectDepends(target);
- for (TargetDependSet::const_iterator i = depends_set.begin();
- i != depends_set.end(); ++i) {
+ for (cmTargetDepend const& i : this->GetTargetDirectDepends(target)) {
// Create the target-level dependency.
- cmGeneratorTarget const* dep = *i;
+ cmGeneratorTarget const* dep = i;
if (dep->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
cmLocalUnixMakefileGenerator3* lg3 =
static_cast<cmLocalUnixMakefileGenerator3*>(dep->GetLocalGenerator());
- std::string tgtName =
- lg3->GetRelativeTargetDirectory(const_cast<cmGeneratorTarget*>(dep));
- tgtName += "/all";
+ std::string tgtName = cmStrCat(
+ lg3->GetRelativeTargetDirectory(const_cast<cmGeneratorTarget*>(dep)),
+ "/all");
depends.push_back(tgtName);
}
}
@@ -933,29 +874,27 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule(
std::string path;
std::vector<std::string> no_depends;
std::vector<std::string> commands;
- lg->AppendEcho(commands, "The following are some of the valid targets "
- "for this Makefile:");
+ lg->AppendEcho(commands,
+ "The following are some of the valid targets "
+ "for this Makefile:");
lg->AppendEcho(commands, "... all (the default if no target is provided)");
lg->AppendEcho(commands, "... clean");
- lg->AppendEcho(commands, "... depend");
+ if (!this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ lg->AppendEcho(commands, "... depend");
+ }
// Keep track of targets already listed.
std::set<std::string> emittedTargets;
// for each local generator
- unsigned int i;
- cmLocalUnixMakefileGenerator3* lg2;
- for (i = 0; i < this->LocalGenerators.size(); ++i) {
- lg2 =
- static_cast<cmLocalUnixMakefileGenerator3*>(this->LocalGenerators[i]);
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ cmLocalUnixMakefileGenerator3* lg2 =
+ static_cast<cmLocalUnixMakefileGenerator3*>(localGen);
// for the passed in makefile or if this is the top Makefile wripte out
// the targets
if (lg2 == lg || lg->IsRootMakefile()) {
// for each target Generate the rule files for each target.
- std::vector<cmGeneratorTarget*> targets = lg2->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator t = targets.begin();
- t != targets.end(); ++t) {
- cmGeneratorTarget* target = *t;
+ for (cmGeneratorTarget* target : lg2->GetGeneratorTargets()) {
cmStateEnums::TargetType type = target->GetType();
if ((type == cmStateEnums::EXECUTABLE) ||
(type == cmStateEnums::STATIC_LIBRARY) ||
@@ -966,41 +905,18 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule(
(type == cmStateEnums::UTILITY)) {
std::string const& name = target->GetName();
if (emittedTargets.insert(name).second) {
- path = "... ";
- path += name;
+ path = cmStrCat("... ", name);
lg->AppendEcho(commands, path);
}
}
}
}
}
- std::vector<std::string> const& localHelp = lg->GetLocalHelp();
- for (std::vector<std::string>::const_iterator o = localHelp.begin();
- o != localHelp.end(); ++o) {
- path = "... ";
- path += *o;
+ for (std::string const& o : lg->GetLocalHelp()) {
+ path = cmStrCat("... ", o);
lg->AppendEcho(commands, path);
}
lg->WriteMakeRule(ruleFileStream, "Help Target", "help", no_depends,
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::set<std::string>::const_iterator l = languages.begin();
- l != languages.end(); ++l) {
- 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 a656102fb..79db30ebd 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -3,12 +3,12 @@
#ifndef cmGlobalUnixMakefileGenerator3_h
#define cmGlobalUnixMakefileGenerator3_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <iosfwd>
#include <map>
#include <set>
-#include <stddef.h>
#include <string>
#include <vector>
@@ -67,8 +67,8 @@ public:
cmGlobalUnixMakefileGenerator3>();
}
- ///! Get the name for the generator.
- std::string GetName() const CM_OVERRIDE
+ //! Get the name for the generator.
+ std::string GetName() const override
{
return cmGlobalUnixMakefileGenerator3::GetActualName();
}
@@ -89,23 +89,23 @@ public:
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
- cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) CM_OVERRIDE;
+ cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
/**
* Try to determine system information such as shared library
* extension, pthreads, byte order etc.
*/
void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
- bool optional) CM_OVERRIDE;
+ bool optional) override;
- void Configure() CM_OVERRIDE;
+ void Configure() override;
/**
* Generate the all required files for building this project/tree. This
* basically creates a series of LocalGenerators for each directory and
* requests that they Generate.
*/
- void Generate() CM_OVERRIDE;
+ void Generate() override;
void WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
std::vector<cmLocalGenerator*>&);
@@ -127,14 +127,12 @@ public:
std::string GetEmptyRuleHackDepends() { return this->EmptyRuleHackDepends; }
// change the build command for speed
- 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>()) CM_OVERRIDE;
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
/** Record per-target progress information. */
void RecordTargetProgress(cmMakefileTargetGenerator* tg);
@@ -149,9 +147,9 @@ public:
/** Does the make tool tolerate .DELETE_ON_ERROR? */
virtual bool AllowDeleteOnError() const { return true; }
- bool IsIPOSupported() const CM_OVERRIDE { return true; }
+ bool IsIPOSupported() const override { return true; }
- void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const CM_OVERRIDE;
+ void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override;
std::string IncludeDirective;
bool DefineWindowsNULL;
@@ -166,49 +164,41 @@ protected:
cmLocalUnixMakefileGenerator3*);
void WriteDirectoryRule2(std::ostream& ruleFileStream,
- cmLocalUnixMakefileGenerator3* lg, const char* pass,
- bool check_all, bool check_relink);
+ DirectoryTarget const& dt, const char* pass,
+ bool check_all, bool check_relink,
+ std::vector<std::string> const& commands = {});
void WriteDirectoryRules2(std::ostream& ruleFileStream,
- cmLocalUnixMakefileGenerator3* lg);
+ DirectoryTarget const& dt);
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 CM_OVERRIDE { return "all"; }
- const char* GetInstallTargetName() const CM_OVERRIDE { return "install"; }
- const char* GetInstallLocalTargetName() const CM_OVERRIDE
+ const char* GetAllTargetName() const override { return "all"; }
+ const char* GetInstallTargetName() const override { return "install"; }
+ const char* GetInstallLocalTargetName() const override
{
return "install/local";
}
- const char* GetInstallStripTargetName() const CM_OVERRIDE
+ const char* GetInstallStripTargetName() const override
{
return "install/strip";
}
- const char* GetPreinstallTargetName() const CM_OVERRIDE
- {
- return "preinstall";
- }
- const char* GetTestTargetName() const CM_OVERRIDE { return "test"; }
- const char* GetPackageTargetName() const CM_OVERRIDE { return "package"; }
- const char* GetPackageSourceTargetName() const CM_OVERRIDE
+ const char* GetPreinstallTargetName() const override { return "preinstall"; }
+ const char* GetTestTargetName() const override { return "test"; }
+ const char* GetPackageTargetName() const override { return "package"; }
+ const char* GetPackageSourceTargetName() const override
{
return "package_source";
}
- const char* GetEditCacheTargetName() const CM_OVERRIDE
- {
- return "edit_cache";
- }
- const char* GetRebuildCacheTargetName() const CM_OVERRIDE
+ const char* GetEditCacheTargetName() const override { return "edit_cache"; }
+ const char* GetRebuildCacheTargetName() const override
{
return "rebuild_cache";
}
- const char* GetCleanTargetName() const CM_OVERRIDE { return "clean"; }
+ const char* GetCleanTargetName() const override { return "clean"; }
- bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const CM_OVERRIDE { return true; }
+ bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; }
// Some make programs (Borland) do not keep a rule if there are no
// dependencies or commands. This is a problem for creating rules
@@ -225,18 +215,13 @@ protected:
// Store per-target progress counters.
struct TargetProgress
{
- TargetProgress()
- : NumberOfActions(0)
- {
- }
- unsigned long NumberOfActions;
+ unsigned long NumberOfActions = 0;
std::string VariableFile;
std::vector<unsigned long> Marks;
void WriteProgressVariables(unsigned long total, unsigned long& current);
};
- typedef std::map<cmGeneratorTarget const*, TargetProgress,
- cmGeneratorTarget::StrictTargetComparison>
- ProgressMapType;
+ using ProgressMapType = std::map<cmGeneratorTarget const*, TargetProgress,
+ cmGeneratorTarget::StrictTargetComparison>;
ProgressMapType ProgressMap;
size_t CountProgressMarksInTarget(
@@ -247,13 +232,13 @@ protected:
cmGeneratedFileStream* CommandDatabase;
private:
- const char* GetBuildIgnoreErrorsFlag() const CM_OVERRIDE { return "-i"; }
- std::string GetEditCacheCommand() const CM_OVERRIDE;
+ const char* GetBuildIgnoreErrorsFlag() const override { return "-i"; }
+ std::string GetEditCacheCommand() const override;
std::map<cmStateSnapshot, std::set<cmGeneratorTarget const*>,
cmStateSnapshot::StrictWeakOrder>
DirectoryTargetsMap;
- void InitializeProgressMarks() CM_OVERRIDE;
+ void InitializeProgressMarks() override;
};
#endif
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 4fff11a9f..f6472ab06 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -2,34 +2,29 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio10Generator.h"
+#include <algorithm>
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/RegularExpression.hxx"
+
+#include "cm_jsoncpp_reader.h"
+
#include "cmAlgorithms.h"
#include "cmDocumentationEntry.h"
#include "cmGeneratorTarget.h"
#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmSourceFile.h"
-#include "cmVS10CLFlagTable.h"
-#include "cmVS10CSharpFlagTable.h"
-#include "cmVS10CudaFlagTable.h"
-#include "cmVS10CudaHostFlagTable.h"
-#include "cmVS10LibFlagTable.h"
-#include "cmVS10LinkFlagTable.h"
-#include "cmVS10MASMFlagTable.h"
-#include "cmVS10NASMFlagTable.h"
-#include "cmVS10RCFlagTable.h"
#include "cmVersion.h"
#include "cmVisualStudioSlnData.h"
#include "cmVisualStudioSlnParser.h"
#include "cmXMLWriter.h"
#include "cmake.h"
-#include "cmsys/FStream.hxx"
-#include "cmsys/Glob.hxx"
-#include "cmsys/RegularExpression.hxx"
-
-#include <algorithm>
-
static const char vs10generatorName[] = "Visual Studio 10 2010";
+static std::map<std::string, std::vector<cmIDEFlagTable>> loadedFlagJsonFiles;
// Map generator name without year to name with year.
static const char* cmVS10GenName(const std::string& name, std::string& genName)
@@ -51,7 +46,7 @@ class cmGlobalVisualStudio10Generator::Factory
{
public:
cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
- cmake* cm) const CM_OVERRIDE
+ cmake* cm) const override
{
std::string genName;
const char* p = cmVS10GenName(name, genName);
@@ -73,22 +68,41 @@ public:
return 0;
}
- void GetDocumentation(cmDocumentationEntry& entry) const CM_OVERRIDE
+ void GetDocumentation(cmDocumentationEntry& entry) const override
{
entry.Name = std::string(vs10generatorName) + " [arch]";
entry.Brief = "Generates Visual Studio 2010 project files. "
"Optional [arch] can be \"Win64\" or \"IA64\".";
}
- void GetGenerators(std::vector<std::string>& names) const CM_OVERRIDE
+ std::vector<std::string> GetGeneratorNames() const override
{
+ std::vector<std::string> names;
names.push_back(vs10generatorName);
+ return names;
+ }
+
+ std::vector<std::string> GetGeneratorNamesWithPlatform() const override
+ {
+ std::vector<std::string> names;
names.push_back(vs10generatorName + std::string(" IA64"));
names.push_back(vs10generatorName + std::string(" Win64"));
+ return names;
+ }
+
+ bool SupportsToolset() const override { return true; }
+ bool SupportsPlatform() const override { return true; }
+
+ std::vector<std::string> GetKnownPlatforms() const override
+ {
+ std::vector<std::string> platforms;
+ platforms.emplace_back("x64");
+ platforms.emplace_back("Win32");
+ platforms.emplace_back("Itanium");
+ return platforms;
}
- bool SupportsToolset() const CM_OVERRIDE { return true; }
- bool SupportsPlatform() const CM_OVERRIDE { return true; }
+ std::string GetDefaultPlatformName() const override { return "Win32"; }
};
cmGlobalGeneratorFactory* cmGlobalVisualStudio10Generator::NewFactory()
@@ -97,8 +111,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio10Generator::NewFactory()
}
cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(
- cmake* cm, const std::string& name, const std::string& platformName)
- : cmGlobalVisualStudio8Generator(cm, name, platformName)
+ cmake* cm, const std::string& name,
+ std::string const& platformInGeneratorName)
+ : cmGlobalVisualStudio8Generator(cm, name, platformInGeneratorName)
{
std::string vc10Express;
this->ExpressEdition = cmSystemTools::ReadRegistryValue(
@@ -120,15 +135,16 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(
this->DefaultPlatformToolset = "v100";
}
}
- this->DefaultClFlagTable = cmVS10CLFlagTable;
- this->DefaultCSharpFlagTable = cmVS10CSharpFlagTable;
- this->DefaultLibFlagTable = cmVS10LibFlagTable;
- this->DefaultLinkFlagTable = cmVS10LinkFlagTable;
- this->DefaultCudaFlagTable = cmVS10CudaFlagTable;
- this->DefaultCudaHostFlagTable = cmVS10CudaHostFlagTable;
- this->DefaultMasmFlagTable = cmVS10MASMFlagTable;
- this->DefaultNasmFlagTable = cmVS10NASMFlagTable;
- this->DefaultRcFlagTable = cmVS10RCFlagTable;
+ this->DefaultCLFlagTableName = "v10";
+ this->DefaultCSharpFlagTableName = "v10";
+ this->DefaultLibFlagTableName = "v10";
+ this->DefaultLinkFlagTableName = "v10";
+ this->DefaultCudaFlagTableName = "v10";
+ this->DefaultCudaHostFlagTableName = "v10";
+ this->DefaultMasmFlagTableName = "v10";
+ this->DefaultNasmFlagTableName = "v10";
+ this->DefaultRCFlagTableName = "v10";
+
this->Version = VS10;
this->PlatformToolsetNeedsDebugEnum = false;
}
@@ -184,7 +200,7 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
std::ostringstream e;
e << this->GetName() << " Windows CE version '" << this->SystemVersion
<< "' requires CMAKE_GENERATOR_TOOLSET to be set.";
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
@@ -214,10 +230,24 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
}
}
+ this->SupportsUnityBuilds =
+ this->Version >= cmGlobalVisualStudioGenerator::VS16 ||
+ (this->Version == cmGlobalVisualStudioGenerator::VS15 &&
+ cmSystemTools::PathExists(this->VCTargetsPath +
+ "/Microsoft.Cpp.Unity.targets"));
+
if (this->GeneratorToolsetCuda.empty()) {
// Find the highest available version of the CUDA tools.
std::vector<std::string> cudaTools;
- std::string const bcDir = this->VCTargetsPath + "/BuildCustomizations";
+ std::string bcDir;
+ if (this->GeneratorToolsetCudaCustomDir.empty()) {
+ bcDir = this->VCTargetsPath + "/BuildCustomizations";
+ } else {
+ bcDir = this->GetPlatformToolsetCudaCustomDirString() +
+ "CUDAVisualStudioIntegration\\extras\\"
+ "visual_studio_integration\\MSBuildExtensions";
+ cmSystemTools::ConvertToUnixSlashes(bcDir);
+ }
cmsys::Glob gl;
gl.SetRelative(bcDir.c_str());
if (gl.FindFiles(bcDir + "/CUDA *.props")) {
@@ -228,25 +258,110 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
std::sort(cudaTools.begin(), cudaTools.end(),
cmSystemTools::VersionCompareGreater);
this->GeneratorToolsetCuda = cudaTools.at(0);
+ } else if (!this->GeneratorToolsetCudaCustomDir.empty()) {
+ // Generate an error if Visual Studio integration files are not found
+ // inside of custom cuda toolset.
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "given toolset\n"
+ " cuda=" << this->GeneratorToolsetCudaCustomDir << "\n"
+ "cannot detect Visual Studio integration files in path\n"
+ " " << bcDir;
+
+ /* clang-format on */
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+
+ // Clear the configured tool-set
+ this->GeneratorToolsetCuda.clear();
+ }
+ }
+
+ if (!this->GeneratorToolsetVersion.empty() &&
+ this->GeneratorToolsetVersion != "Test Toolset Version") {
+ // If a specific minor version of the toolset was requested, verify that it
+ // is compatible to the major version and that is exists on disk.
+ // If not clear the value.
+ std::string version = this->GeneratorToolsetVersion;
+ cmsys::RegularExpression regex("[0-9][0-9]\\.[0-9][0-9]");
+ if (regex.find(version)) {
+ version = "v" + version.erase(2, 1);
+ } else {
+ // Version not recognized. Clear it.
+ version.clear();
+ }
+
+ if (version.find(this->GetPlatformToolsetString()) != 0) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "given toolset and version specification\n"
+ " " << this->GetPlatformToolsetString() << ",version=" <<
+ this->GeneratorToolsetVersion << "\n"
+ "contains an invalid version specification."
+ ;
+ /* clang-format on */
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+
+ // Clear the configured tool-set
+ this->GeneratorToolsetVersion.clear();
+ }
+
+ bool const isDefaultToolset =
+ this->IsDefaultToolset(this->GeneratorToolsetVersion);
+ if (isDefaultToolset) {
+ // If the given version is the default toolset, remove the setting
+ this->GeneratorToolsetVersion.clear();
+ } else {
+ std::string const toolsetPath = this->GetAuxiliaryToolset();
+ if (!toolsetPath.empty() && !cmSystemTools::FileExists(toolsetPath)) {
+
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "given toolset and version specification\n"
+ " " << this->GetPlatformToolsetString() << ",version=" <<
+ this->GeneratorToolsetVersion << "\n"
+ "does not seem to be installed at\n" <<
+ " " << toolsetPath;
+ ;
+ /* clang-format on */
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+
+ // Clear the configured tool-set
+ this->GeneratorToolsetVersion.clear();
+ }
}
}
if (const char* toolset = this->GetPlatformToolset()) {
mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET", toolset);
}
+ if (const char* version = this->GetPlatformToolsetVersion()) {
+ mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_VERSION", version);
+ }
if (const char* hostArch = this->GetPlatformToolsetHostArchitecture()) {
mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE", hostArch);
}
if (const char* cuda = this->GetPlatformToolsetCuda()) {
mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA", cuda);
}
+ if (const char* cudaDir = this->GetPlatformToolsetCudaCustomDir()) {
+ mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR", cudaDir);
+ }
return true;
}
bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset(
std::string const& ts, cmMakefile* mf)
{
- std::vector<std::string> const fields = cmSystemTools::tokenize(ts, ",");
+ std::vector<std::string> const fields = cmTokenize(ts, ",");
std::vector<std::string>::const_iterator fi = fields.begin();
if (fi == fields.end()) {
return true;
@@ -274,7 +389,7 @@ bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset(
"that contains a field after the first ',' with no '='."
;
/* clang-format on */
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
std::string const key = fi->substr(0, pos);
@@ -290,7 +405,7 @@ bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset(
"that contains duplicate field key '" << key << "'."
;
/* clang-format on */
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
if (!this->ProcessGeneratorToolsetField(key, value)) {
@@ -304,7 +419,7 @@ bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset(
"that contains invalid field '" << *fi << "'."
;
/* clang-format on */
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
}
@@ -316,7 +431,21 @@ bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField(
std::string const& key, std::string const& value)
{
if (key == "cuda") {
- this->GeneratorToolsetCuda = value;
+ /* test if cuda toolset is path to custom dir or cuda version */
+ auto pos = value.find_first_not_of("0123456789.");
+ if (pos != std::string::npos) {
+ this->GeneratorToolsetCudaCustomDir = value;
+ /* ensure trailing backslash for easy path joining */
+ if (this->GeneratorToolsetCudaCustomDir.back() != '\\') {
+ this->GeneratorToolsetCudaCustomDir.push_back('\\');
+ }
+ } else {
+ this->GeneratorToolsetCuda = value;
+ }
+ return true;
+ }
+ if (key == "version") {
+ this->GeneratorToolsetVersion = value;
return true;
}
return false;
@@ -344,16 +473,16 @@ bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf)
return false;
}
} else if (this->SystemName == "Android") {
- if (this->DefaultPlatformName != "Win32") {
+ if (this->PlatformInGeneratorName) {
std::ostringstream e;
e << "CMAKE_SYSTEM_NAME is 'Android' but CMAKE_GENERATOR "
<< "specifies a platform too: '" << this->GetName() << "'";
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
std::string v = this->GetInstalledNsightTegraVersion();
if (v.empty()) {
- mf->IssueMessage(cmake::FATAL_ERROR,
+ mf->IssueMessage(MessageType::FATAL_ERROR,
"CMAKE_SYSTEM_NAME is 'Android' but "
"'NVIDIA Nsight Tegra Visual Studio Edition' "
"is not installed.");
@@ -362,7 +491,7 @@ bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf)
this->DefaultPlatformName = "Tegra-Android";
this->DefaultPlatformToolset = "Default";
this->NsightTegraVersion = v;
- mf->AddDefinition("CMAKE_VS_NsightTegra_VERSION", v.c_str());
+ mf->AddDefinition("CMAKE_VS_NsightTegra_VERSION", v);
}
return true;
@@ -375,11 +504,11 @@ bool cmGlobalVisualStudio10Generator::InitializeWindows(cmMakefile*)
bool cmGlobalVisualStudio10Generator::InitializeWindowsCE(cmMakefile* mf)
{
- if (this->DefaultPlatformName != "Win32") {
+ if (this->PlatformInGeneratorName) {
std::ostringstream e;
e << "CMAKE_SYSTEM_NAME is 'WindowsCE' but CMAKE_GENERATOR "
<< "specifies a platform too: '" << this->GetName() << "'";
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
@@ -392,7 +521,7 @@ bool cmGlobalVisualStudio10Generator::InitializeWindowsPhone(cmMakefile* mf)
{
std::ostringstream e;
e << this->GetName() << " does not support Windows Phone.";
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
@@ -400,21 +529,21 @@ bool cmGlobalVisualStudio10Generator::InitializeWindowsStore(cmMakefile* mf)
{
std::ostringstream e;
e << this->GetName() << " does not support Windows Store.";
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
bool cmGlobalVisualStudio10Generator::SelectWindowsPhoneToolset(
std::string& toolset) const
{
- toolset = "";
+ toolset.clear();
return false;
}
bool cmGlobalVisualStudio10Generator::SelectWindowsStoreToolset(
std::string& toolset) const
{
- toolset = "";
+ toolset.clear();
return false;
}
@@ -426,17 +555,7 @@ std::string cmGlobalVisualStudio10Generator::SelectWindowsCEToolset() const
return "";
}
-void cmGlobalVisualStudio10Generator::WriteSLNHeader(std::ostream& fout)
-{
- fout << "Microsoft Visual Studio Solution File, Format Version 11.00\n";
- if (this->ExpressEdition) {
- fout << "# Visual C++ Express 2010\n";
- } else {
- fout << "# Visual Studio 2010\n";
- }
-}
-
-///! Create a local generator appropriate to this Global Generator
+//! Create a local generator appropriate to this Global Generator
cmLocalGenerator* cmGlobalVisualStudio10Generator::CreateLocalGenerator(
cmMakefile* mf)
{
@@ -471,19 +590,18 @@ void cmGlobalVisualStudio10Generator::Generate()
"To avoid this problem CMake must use a full path for this file "
"which then triggers the VS 10 property dialog bug.";
/* clang-format on */
- lg->IssueMessage(cmake::WARNING, e.str().c_str());
+ lg->IssueMessage(MessageType::WARNING, e.str().c_str());
}
}
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;
}
}
@@ -495,7 +613,7 @@ const char* cmGlobalVisualStudio10Generator::GetPlatformToolset() const
{
std::string const& toolset = this->GetPlatformToolsetString();
if (toolset.empty()) {
- return CM_NULLPTR;
+ return nullptr;
}
return toolset.c_str();
}
@@ -513,13 +631,48 @@ std::string const& cmGlobalVisualStudio10Generator::GetPlatformToolsetString()
return empty;
}
+const char* cmGlobalVisualStudio10Generator::GetPlatformToolsetVersion() const
+{
+ std::string const& version = this->GetPlatformToolsetVersionString();
+ if (version.empty()) {
+ return nullptr;
+ }
+ return version.c_str();
+}
+
+std::string const&
+cmGlobalVisualStudio10Generator::GetPlatformToolsetVersionString() const
+{
+ if (!this->GeneratorToolsetVersion.empty()) {
+ return this->GeneratorToolsetVersion;
+ }
+ static std::string const empty;
+ return empty;
+}
+
const char*
cmGlobalVisualStudio10Generator::GetPlatformToolsetHostArchitecture() const
{
+ std::string const& hostArch =
+ this->GetPlatformToolsetHostArchitectureString();
+ if (hostArch.empty()) {
+ return nullptr;
+ }
+ return hostArch.c_str();
+}
+
+std::string const&
+cmGlobalVisualStudio10Generator::GetPlatformToolsetHostArchitectureString()
+ const
+{
if (!this->GeneratorToolsetHostArchitecture.empty()) {
- return this->GeneratorToolsetHostArchitecture.c_str();
+ return this->GeneratorToolsetHostArchitecture;
+ }
+ if (!this->DefaultPlatformToolsetHostArchitecture.empty()) {
+ return this->DefaultPlatformToolsetHostArchitecture;
}
- return CM_NULLPTR;
+ static std::string const empty;
+ return empty;
}
const char* cmGlobalVisualStudio10Generator::GetPlatformToolsetCuda() const
@@ -527,7 +680,7 @@ const char* cmGlobalVisualStudio10Generator::GetPlatformToolsetCuda() const
if (!this->GeneratorToolsetCuda.empty()) {
return this->GeneratorToolsetCuda.c_str();
}
- return CM_NULLPTR;
+ return nullptr;
}
std::string const&
@@ -536,13 +689,38 @@ cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaString() const
return this->GeneratorToolsetCuda;
}
+const char* cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaCustomDir()
+ const
+{
+ if (!this->GeneratorToolsetCudaCustomDir.empty()) {
+ return this->GeneratorToolsetCudaCustomDir.c_str();
+ }
+ return nullptr;
+}
+
+std::string const&
+cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaCustomDirString() const
+{
+ return this->GeneratorToolsetCudaCustomDir;
+}
+
+bool cmGlobalVisualStudio10Generator::IsDefaultToolset(
+ const std::string&) const
+{
+ return true;
+}
+
+std::string cmGlobalVisualStudio10Generator::GetAuxiliaryToolset() const
+{
+ return {};
+}
+
bool cmGlobalVisualStudio10Generator::FindMakeProgram(cmMakefile* mf)
{
if (!this->cmGlobalVisualStudio8Generator::FindMakeProgram(mf)) {
return false;
}
- mf->AddDefinition("CMAKE_VS_MSBUILD_COMMAND",
- this->GetMSBuildCommand().c_str());
+ mf->AddDefinition("CMAKE_VS_MSBUILD_COMMAND", this->GetMSBuildCommand());
return true;
}
@@ -561,9 +739,9 @@ std::string cmGlobalVisualStudio10Generator::FindMSBuildCommand()
std::string mskey;
// Search in standard location.
- mskey = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\";
- mskey += this->GetToolsVersion();
- mskey += ";MSBuildToolsPath";
+ mskey = cmStrCat(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\",
+ this->GetToolsVersion(), ";MSBuildToolsPath");
if (cmSystemTools::ReadRegistryValue(mskey.c_str(), msbuild,
cmSystemTools::KeyWOW64_32)) {
cmSystemTools::ConvertToUnixSlashes(msbuild);
@@ -603,8 +781,8 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
// In a try-compile we are given the outer CMakeFiles directory.
wd = this->ConfiguredFilesPath;
} else {
- wd = this->GetCMakeInstance()->GetHomeOutputDirectory();
- wd += cmake::GetCMakeFilesDirectory();
+ wd = cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
+ "/CMakeFiles");
}
wd += "/";
wd += cmVersion::GetCMakeVersion();
@@ -625,7 +803,7 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
// Prepare the work directory.
if (!cmSystemTools::MakeDirectory(wd)) {
std::string e = "Failed to make directory:\n " + wd;
- mf->IssueMessage(cmake::FATAL_ERROR, e.c_str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.c_str());
cmSystemTools::SetFatalErrorOccured();
return false;
}
@@ -637,121 +815,88 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
cmsys::ofstream fout(vcxprojAbs.c_str());
cmXMLWriter xw(fout);
- /* clang-format off */
- xw.StartDocument();
- xw.StartElement("Project");
- xw.Attribute("DefaultTargets", "Build");
- xw.Attribute("ToolsVersion", "4.0");
- xw.Attribute("xmlns",
- "http://schemas.microsoft.com/developer/msbuild/2003");
- if (this->IsNsightTegra()) {
- xw.StartElement("PropertyGroup");
- xw.Attribute("Label", "NsightTegraProject");
- xw.StartElement("NsightTegraProjectRevisionNumber");
- xw.Content("6");
- xw.EndElement(); // NsightTegraProjectRevisionNumber
- xw.EndElement(); // PropertyGroup
- }
- xw.StartElement("ItemGroup");
- xw.Attribute("Label", "ProjectConfigurations");
- xw.StartElement("ProjectConfiguration");
- xw.Attribute("Include", "Debug|" + this->GetPlatformName());
- xw.StartElement("Configuration");
- xw.Content("Debug");
- xw.EndElement(); // Configuration
- xw.StartElement("Platform");
- xw.Content(this->GetPlatformName());
- xw.EndElement(); // Platform
- xw.EndElement(); // ProjectConfiguration
- xw.EndElement(); // ItemGroup
- xw.StartElement("PropertyGroup");
- xw.Attribute("Label", "Globals");
- xw.StartElement("ProjectGuid");
- xw.Content("{F3FC6D86-508D-3FB1-96D2-995F08B142EC}");
- xw.EndElement(); // ProjectGuid
- xw.StartElement("Keyword");
- xw.Content("Win32Proj");
- xw.EndElement(); // Keyword
- xw.StartElement("Platform");
- xw.Content(this->GetPlatformName());
- xw.EndElement(); // Platform
- if (this->GetSystemName() == "WindowsPhone") {
- xw.StartElement("ApplicationType");
- xw.Content("Windows Phone");
- xw.EndElement(); // ApplicationType
- xw.StartElement("ApplicationTypeRevision");
- xw.Content(this->GetSystemVersion());
- xw.EndElement(); // ApplicationTypeRevision
- } else if (this->GetSystemName() == "WindowsStore") {
- xw.StartElement("ApplicationType");
- xw.Content("Windows Store");
- xw.EndElement(); // ApplicationType
- xw.StartElement("ApplicationTypeRevision");
- xw.Content(this->GetSystemVersion());
- xw.EndElement(); // ApplicationTypeRevision
- }
- if (!this->WindowsTargetPlatformVersion.empty()) {
- xw.StartElement("WindowsTargetPlatformVersion");
- xw.Content(this->WindowsTargetPlatformVersion);
- xw.EndElement(); // WindowsTargetPlatformVersion
- }
- if (this->GetPlatformName() == "ARM") {
- xw.StartElement("WindowsSDKDesktopARMSupport");
- xw.Content("true");
- xw.EndElement(); // WindowsSDKDesktopARMSupport
- }
- xw.EndElement(); // PropertyGroup
- xw.StartElement("Import");
- xw.Attribute("Project",
- "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
- xw.EndElement(); // Import
- if (!this->GeneratorToolsetHostArchitecture.empty()) {
- xw.StartElement("PropertyGroup");
- xw.StartElement("PreferredToolArchitecture");
- xw.Content(this->GeneratorToolsetHostArchitecture);
- xw.EndElement(); // PreferredToolArchitecture
- xw.EndElement(); // PropertyGroup
+ cmXMLDocument doc(xw);
+ cmXMLElement eprj(doc, "Project");
+ eprj.Attribute("DefaultTargets", "Build");
+ eprj.Attribute("ToolsVersion", "4.0");
+ eprj.Attribute("xmlns",
+ "http://schemas.microsoft.com/developer/msbuild/2003");
+ if (this->IsNsightTegra()) {
+ cmXMLElement epg(eprj, "PropertyGroup");
+ epg.Attribute("Label", "NsightTegraProject");
+ cmXMLElement(epg, "NsightTegraProjectRevisionNumber").Content("6");
}
- xw.StartElement("PropertyGroup");
- xw.Attribute("Label", "Configuration");
- xw.StartElement("ConfigurationType");
+ {
+ cmXMLElement eig(eprj, "ItemGroup");
+ eig.Attribute("Label", "ProjectConfigurations");
+ cmXMLElement epc(eig, "ProjectConfiguration");
+ epc.Attribute("Include", "Debug|" + this->GetPlatformName());
+ cmXMLElement(epc, "Configuration").Content("Debug");
+ cmXMLElement(epc, "Platform").Content(this->GetPlatformName());
+ }
+ {
+ cmXMLElement epg(eprj, "PropertyGroup");
+ epg.Attribute("Label", "Globals");
+ cmXMLElement(epg, "ProjectGuid")
+ .Content("{F3FC6D86-508D-3FB1-96D2-995F08B142EC}");
+ cmXMLElement(epg, "Keyword").Content("Win32Proj");
+ cmXMLElement(epg, "Platform").Content(this->GetPlatformName());
+ if (this->GetSystemName() == "WindowsPhone") {
+ cmXMLElement(epg, "ApplicationType").Content("Windows Phone");
+ cmXMLElement(epg, "ApplicationTypeRevision")
+ .Content(this->GetApplicationTypeRevision());
+ } else if (this->GetSystemName() == "WindowsStore") {
+ cmXMLElement(epg, "ApplicationType").Content("Windows Store");
+ cmXMLElement(epg, "ApplicationTypeRevision")
+ .Content(this->GetApplicationTypeRevision());
+ }
+ if (!this->WindowsTargetPlatformVersion.empty()) {
+ cmXMLElement(epg, "WindowsTargetPlatformVersion")
+ .Content(this->WindowsTargetPlatformVersion);
+ }
+ if (this->GetPlatformName() == "ARM64") {
+ cmXMLElement(epg, "WindowsSDKDesktopARM64Support").Content("true");
+ } else if (this->GetPlatformName() == "ARM") {
+ cmXMLElement(epg, "WindowsSDKDesktopARMSupport").Content("true");
+ }
+ }
+ cmXMLElement(eprj, "Import")
+ .Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
+ if (const char* hostArch = this->GetPlatformToolsetHostArchitecture()) {
+ cmXMLElement epg(eprj, "PropertyGroup");
+ cmXMLElement(epg, "PreferredToolArchitecture").Content(hostArch);
+ }
+ {
+ cmXMLElement epg(eprj, "PropertyGroup");
+ epg.Attribute("Label", "Configuration");
+ {
+ cmXMLElement ect(epg, "ConfigurationType");
+ if (this->IsNsightTegra()) {
+ // Tegra-Android platform does not understand "Utility".
+ ect.Content("StaticLibrary");
+ } else {
+ ect.Content("Utility");
+ }
+ }
+ cmXMLElement(epg, "CharacterSet").Content("MultiByte");
if (this->IsNsightTegra()) {
- // Tegra-Android platform does not understand "Utility".
- xw.Content("StaticLibrary");
+ cmXMLElement(epg, "NdkToolchainVersion")
+ .Content(this->GetPlatformToolsetString());
} else {
- xw.Content("Utility");
+ cmXMLElement(epg, "PlatformToolset")
+ .Content(this->GetPlatformToolsetString());
}
- xw.EndElement(); // ConfigurationType
- xw.StartElement("CharacterSet");
- xw.Content("MultiByte");
- xw.EndElement(); // CharacterSet
- if (this->IsNsightTegra()) {
- xw.StartElement("NdkToolchainVersion");
- xw.Content(this->GetPlatformToolsetString());
- xw.EndElement(); // NdkToolchainVersion
- } else {
- xw.StartElement("PlatformToolset");
- xw.Content(this->GetPlatformToolsetString());
- xw.EndElement(); // PlatformToolset
- }
- xw.EndElement(); // PropertyGroup
- xw.StartElement("Import");
- xw.Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
- xw.EndElement(); // Import
- xw.StartElement("ItemDefinitionGroup");
- xw.StartElement("PostBuildEvent");
- xw.StartElement("Command");
- xw.Content("echo VCTargetsPath=$(VCTargetsPath)");
- xw.EndElement(); // Command
- xw.EndElement(); // PostBuildEvent
- xw.EndElement(); // ItemDefinitionGroup
- xw.StartElement("Import");
- xw.Attribute("Project",
- "$(VCTargetsPath)\\Microsoft.Cpp.targets");
- xw.EndElement(); // Import
- xw.EndElement(); // Project
- xw.EndDocument();
- /* clang-format on */
+ }
+ cmXMLElement(eprj, "Import")
+ .Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
+ {
+ cmXMLElement eidg(eprj, "ItemDefinitionGroup");
+ cmXMLElement epbe(eidg, "PostBuildEvent");
+ cmXMLElement(epbe, "Command")
+ .Content("echo VCTargetsPath=$(VCTargetsPath)");
+ }
+ cmXMLElement(eprj, "Import")
+ .Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets");
}
std::vector<std::string> cmd;
@@ -779,7 +924,7 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
if (ret != 0) {
e << "Exit code: " << ret << "\n";
}
- mf->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str().c_str());
cmSystemTools::SetFatalErrorOccured();
return false;
}
@@ -793,12 +938,14 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
return true;
}
-void cmGlobalVisualStudio10Generator::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<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalVisualStudio10Generator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions)
{
+ std::vector<GeneratedMakeCommand> makeCommands;
// Select the caller- or user-preferred make program, else MSBuild.
std::string makeProgramSelected =
this->SelectMakeProgram(makeProgram, this->GetMSBuildCommand());
@@ -809,14 +956,17 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
bool useDevEnv = (makeProgramLower.find("devenv") != std::string::npos ||
makeProgramLower.find("vcexpress") != std::string::npos);
+ // Workaround to convince VCExpress.exe to produce output.
+ const bool requiresOutputForward =
+ (makeProgramLower.find("vcexpress") != std::string::npos);
+
// MSBuild is preferred (and required for VS Express), but if the .sln has
// an Intel Fortran .vfproj then we have to use devenv. Parse it to find out.
cmSlnData slnData;
{
std::string slnFile;
if (!projectDir.empty()) {
- slnFile = projectDir;
- slnFile += "/";
+ slnFile = cmStrCat(projectDir, '/');
}
slnFile += projectName;
slnFile += ".sln";
@@ -824,9 +974,11 @@ 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) {
- std::string proj = i->GetRelativePath();
+ for (cmSlnProjectEntry const& project : slnProjects) {
+ if (useDevEnv) {
+ break;
+ }
+ std::string proj = project.GetRelativePath();
if (proj.size() > 7 && proj.substr(proj.size() - 7) == ".vfproj") {
useDevEnv = true;
}
@@ -835,46 +987,70 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
}
if (useDevEnv) {
// Use devenv to build solutions containing Intel Fortran projects.
- cmGlobalVisualStudio7Generator::GenerateBuildCommand(
- makeCommand, makeProgram, projectName, projectDir, targetName, config,
- fast, verbose, makeOptions);
- return;
+ return cmGlobalVisualStudio7Generator::GenerateBuildCommand(
+ makeProgram, projectName, projectDir, targetNames, config, fast, jobs,
+ verbose, makeOptions);
}
- makeCommand.push_back(makeProgramSelected);
-
- std::string realTarget = targetName;
- // msbuild.exe CxxOnly.sln /t:Build /p:Configuration=Debug /target:ALL_BUILD
- if (realTarget.empty()) {
- realTarget = "ALL_BUILD";
+ std::vector<std::string> realTargetNames = targetNames;
+ if (targetNames.empty() ||
+ ((targetNames.size() == 1) && targetNames.front().empty())) {
+ realTargetNames = { "ALL_BUILD" };
}
- if (realTarget == "clean") {
- makeCommand.push_back(std::string(projectName) + ".sln");
- makeCommand.push_back("/t:Clean");
- } else {
- std::string targetProject(realTarget);
- targetProject += ".vcxproj";
- if (targetProject.find('/') == std::string::npos) {
- // it might be in a subdir
- if (cmSlnProjectEntry const* proj =
- slnData.GetProjectByName(realTarget)) {
- targetProject = proj->GetRelativePath();
- cmSystemTools::ConvertToUnixSlashes(targetProject);
+ for (const auto& tname : realTargetNames) {
+ // msbuild.exe CxxOnly.sln /t:Build /p:Configuration=Debug
+ // /target:ALL_BUILD
+ // /m
+ if (tname.empty()) {
+ continue;
+ }
+
+ GeneratedMakeCommand makeCommand;
+ makeCommand.RequiresOutputForward = requiresOutputForward;
+ makeCommand.Add(makeProgramSelected);
+
+ if (tname == "clean") {
+ makeCommand.Add(std::string(projectName) + ".sln");
+ makeCommand.Add("/t:Clean");
+ } else {
+ std::string targetProject = cmStrCat(tname, ".vcxproj");
+ if (targetProject.find('/') == std::string::npos) {
+ // it might be in a subdir
+ if (cmSlnProjectEntry const* proj = slnData.GetProjectByName(tname)) {
+ targetProject = proj->GetRelativePath();
+ cmSystemTools::ConvertToUnixSlashes(targetProject);
+ }
}
+ makeCommand.Add(std::move(targetProject));
}
- makeCommand.push_back(targetProject);
- }
- std::string configArg = "/p:Configuration=";
- if (!config.empty()) {
- configArg += config;
- } else {
- configArg += "Debug";
+ std::string configArg = "/p:Configuration=";
+ if (!config.empty()) {
+ configArg += config;
+ } else {
+ configArg += "Debug";
+ }
+ makeCommand.Add(configArg);
+ makeCommand.Add(std::string("/p:Platform=") + this->GetPlatformName());
+ makeCommand.Add(std::string("/p:VisualStudioVersion=") +
+ this->GetIDEVersion());
+
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ makeCommand.Add("/m");
+ } else {
+ makeCommand.Add(std::string("/m:") + std::to_string(jobs));
+ }
+ // Having msbuild.exe and cl.exe using multiple jobs is discouraged
+ makeCommand.Add("/p:CL_MPCount=1");
+ }
+
+ // Respect the verbosity: 'n' normal will show build commands
+ // 'm' minimal only the build step's title
+ makeCommand.Add(std::string("/v:") + ((verbose) ? "n" : "m"));
+ makeCommand.Add(makeOptions.begin(), makeOptions.end());
+ makeCommands.emplace_back(std::move(makeCommand));
}
- makeCommand.push_back(configArg);
- makeCommand.push_back(std::string("/p:VisualStudioVersion=") +
- this->GetIDEVersion());
- makeCommand.insert(makeCommand.end(), makeOptions.begin(),
- makeOptions.end());
+ return makeCommands;
}
bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf)
@@ -899,7 +1075,7 @@ bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf)
winSDK_7_1)) {
std::ostringstream m;
m << "Found Windows SDK v7.1: " << winSDK_7_1;
- mf->DisplayStatus(m.str().c_str(), -1);
+ mf->DisplayStatus(m.str(), -1);
this->DefaultPlatformToolset = "Windows7.1SDK";
return true;
} else {
@@ -909,7 +1085,7 @@ bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf)
<< "Install the Microsoft Windows SDK v7.1 to get 64-bit tools:\n"
<< " http://msdn.microsoft.com/en-us/windows/bb980924.aspx";
/* clang-format on */
- mf->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str().c_str());
cmSystemTools::SetFatalErrorOccured();
return false;
}
@@ -920,14 +1096,12 @@ std::string cmGlobalVisualStudio10Generator::GenerateRuleFile(
{
// The VS 10 generator needs to create the .rule files on disk.
// Hide them away under the CMakeFiles directory.
- std::string ruleDir = this->GetCMakeInstance()->GetHomeOutputDirectory();
- ruleDir += cmake::GetCMakeFilesDirectory();
- ruleDir += "/";
- ruleDir += cmSystemTools::ComputeStringMD5(
- cmSystemTools::GetFilenamePath(output).c_str());
- std::string ruleFile = ruleDir + "/";
- ruleFile += cmSystemTools::GetFilenameName(output);
- ruleFile += ".rule";
+ std::string ruleDir = cmStrCat(
+ this->GetCMakeInstance()->GetHomeOutputDirectory(), "/CMakeFiles/",
+ cmSystemTools::ComputeStringMD5(
+ cmSystemTools::GetFilenamePath(output).c_str()));
+ std::string ruleFile =
+ cmStrCat(ruleDir, '/', cmSystemTools::GetFilenameName(output), ".rule");
return ruleFile;
}
@@ -936,7 +1110,7 @@ void cmGlobalVisualStudio10Generator::PathTooLong(cmGeneratorTarget* target,
std::string const& sfRel)
{
size_t len =
- (strlen(target->GetLocalGenerator()->GetCurrentBinaryDirectory()) + 1 +
+ (target->GetLocalGenerator()->GetCurrentBinaryDirectory().length() + 1 +
sfRel.length());
if (len > this->LongestSource.Length) {
this->LongestSource.Length = len;
@@ -946,6 +1120,34 @@ void cmGlobalVisualStudio10Generator::PathTooLong(cmGeneratorTarget* target,
}
}
+std::string cmGlobalVisualStudio10Generator::Encoding()
+{
+ return "utf-8";
+}
+
+const char* cmGlobalVisualStudio10Generator::GetToolsVersion() const
+{
+ switch (this->Version) {
+ case cmGlobalVisualStudioGenerator::VS9:
+ case cmGlobalVisualStudioGenerator::VS10:
+ case cmGlobalVisualStudioGenerator::VS11:
+ return "4.0";
+
+ // 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
+ case cmGlobalVisualStudioGenerator::VS12:
+ return "12.0";
+ case cmGlobalVisualStudioGenerator::VS14:
+ return "14.0";
+ case cmGlobalVisualStudioGenerator::VS15:
+ return "15.0";
+ case cmGlobalVisualStudioGenerator::VS16:
+ return "16.0";
+ }
+ return "";
+}
+
bool cmGlobalVisualStudio10Generator::IsNsightTegra() const
{
return !this->NsightTegraVersion.empty();
@@ -966,67 +1168,227 @@ std::string cmGlobalVisualStudio10Generator::GetInstalledNsightTegraVersion()
return version;
}
+std::string cmGlobalVisualStudio10Generator::GetApplicationTypeRevision() const
+{
+ // Return the first two '.'-separated components of the Windows version.
+ std::string::size_type end1 = this->SystemVersion.find('.');
+ std::string::size_type end2 =
+ end1 == std::string::npos ? end1 : this->SystemVersion.find('.', end1 + 1);
+ return this->SystemVersion.substr(0, end2);
+}
+
+static std::string cmLoadFlagTableString(Json::Value entry, const char* field)
+{
+ if (entry.isMember(field)) {
+ auto string = entry[field];
+ if (string.isConvertibleTo(Json::ValueType::stringValue)) {
+ return string.asString();
+ }
+ }
+ return "";
+}
+
+static unsigned int cmLoadFlagTableSpecial(Json::Value entry,
+ const char* field)
+{
+ unsigned int value = 0;
+ if (entry.isMember(field)) {
+ auto specials = entry[field];
+ if (specials.isArray()) {
+ for (auto const& special : specials) {
+ std::string s = special.asString();
+ if (s == "UserValue") {
+ value |= cmIDEFlagTable::UserValue;
+ } else if (s == "UserIgnored") {
+ value |= cmIDEFlagTable::UserIgnored;
+ } else if (s == "UserRequired") {
+ value |= cmIDEFlagTable::UserRequired;
+ } else if (s == "Continue") {
+ value |= cmIDEFlagTable::Continue;
+ } else if (s == "SemicolonAppendable") {
+ value |= cmIDEFlagTable::SemicolonAppendable;
+ } else if (s == "UserFollowing") {
+ value |= cmIDEFlagTable::UserFollowing;
+ } else if (s == "CaseInsensitive") {
+ value |= cmIDEFlagTable::CaseInsensitive;
+ } else if (s == "SpaceAppendable") {
+ value |= cmIDEFlagTable::SpaceAppendable;
+ } else if (s == "CommaAppendable") {
+ value |= cmIDEFlagTable::CommaAppendable;
+ }
+ }
+ }
+ }
+ return value;
+}
+
+static cmIDEFlagTable const* cmLoadFlagTableJson(
+ std::string const& flagJsonPath)
+{
+ cmIDEFlagTable* ret = nullptr;
+ auto savedFlagIterator = loadedFlagJsonFiles.find(flagJsonPath);
+ if (savedFlagIterator != loadedFlagJsonFiles.end()) {
+ ret = savedFlagIterator->second.data();
+ } else {
+ Json::Reader reader;
+ cmsys::ifstream stream;
+
+ stream.open(flagJsonPath.c_str(), std::ios_base::in);
+ if (stream) {
+ Json::Value flags;
+ if (reader.parse(stream, flags, false) && flags.isArray()) {
+ std::vector<cmIDEFlagTable> flagTable;
+ for (auto const& flag : flags) {
+ cmIDEFlagTable flagEntry;
+ flagEntry.IDEName = cmLoadFlagTableString(flag, "name");
+ flagEntry.commandFlag = cmLoadFlagTableString(flag, "switch");
+ flagEntry.comment = cmLoadFlagTableString(flag, "comment");
+ flagEntry.value = cmLoadFlagTableString(flag, "value");
+ flagEntry.special = cmLoadFlagTableSpecial(flag, "flags");
+ flagTable.push_back(flagEntry);
+ }
+ cmIDEFlagTable endFlag{ "", "", "", "", 0 };
+ flagTable.push_back(endFlag);
+
+ loadedFlagJsonFiles[flagJsonPath] = flagTable;
+ ret = loadedFlagJsonFiles[flagJsonPath].data();
+ }
+ }
+ }
+ return ret;
+}
+
+static std::string cmGetFlagTableName(std::string const& toolsetName,
+ std::string const& table)
+{
+ return cmSystemTools::GetCMakeRoot() + "/Templates/MSBuild/FlagTables/" +
+ toolsetName + "_" + table + ".json";
+}
+
+cmIDEFlagTable const* cmGlobalVisualStudio10Generator::LoadFlagTable(
+ std::string const& optionsName, std::string const& toolsetName,
+ std::string const& defaultName, std::string const& table) const
+{
+ cmIDEFlagTable const* ret = nullptr;
+
+ std::string filename;
+ if (!optionsName.empty()) {
+ filename = cmGetFlagTableName(optionsName, table);
+ ret = cmLoadFlagTableJson(filename);
+ } else {
+ filename = cmGetFlagTableName(toolsetName, table);
+ if (cmSystemTools::FileExists(filename)) {
+ ret = cmLoadFlagTableJson(filename);
+ } else {
+ filename = cmGetFlagTableName(defaultName, table);
+ ret = cmLoadFlagTableJson(filename);
+ }
+ }
+
+ if (!ret) {
+ cmMakefile* mf = this->GetCurrentMakefile();
+
+ std::ostringstream e;
+ /* clang-format off */
+ e << "JSON flag table \"" << filename <<
+ "\" could not be loaded.\n";
+ /* clang-format on */
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str().c_str());
+ }
+ return ret;
+}
+
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetClFlagTable() const
{
- cmIDEFlagTable const* table = this->ToolsetOptions.GetClFlagTable(
+ std::string optionsName = this->ToolsetOptions.GetClFlagTableName(
this->GetPlatformName(), this->GetPlatformToolsetString());
-
- return (table != CM_NULLPTR) ? table : this->DefaultClFlagTable;
+ std::string toolsetName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->GetPlatformToolsetString());
+ std::string defaultName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->DefaultCLFlagTableName);
+ return LoadFlagTable(optionsName, toolsetName, defaultName, "CL");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCSharpFlagTable()
const
{
- cmIDEFlagTable const* table = this->ToolsetOptions.GetCSharpFlagTable(
+ std::string optionsName = this->ToolsetOptions.GetCSharpFlagTableName(
this->GetPlatformName(), this->GetPlatformToolsetString());
-
- return (table != CM_NULLPTR) ? table : this->DefaultCSharpFlagTable;
+ std::string toolsetName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->GetPlatformToolsetString());
+ std::string defaultName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->DefaultCSharpFlagTableName);
+ return LoadFlagTable(optionsName, toolsetName, defaultName, "CSharp");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetRcFlagTable() const
{
- cmIDEFlagTable const* table = this->ToolsetOptions.GetRcFlagTable(
+ std::string optionsName = this->ToolsetOptions.GetRcFlagTableName(
this->GetPlatformName(), this->GetPlatformToolsetString());
-
- return (table != CM_NULLPTR) ? table : this->DefaultRcFlagTable;
+ std::string toolsetName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->GetPlatformToolsetString());
+ std::string defaultName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->DefaultRCFlagTableName);
+ return LoadFlagTable(optionsName, toolsetName, defaultName, "RC");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLibFlagTable() const
{
- cmIDEFlagTable const* table = this->ToolsetOptions.GetLibFlagTable(
+ std::string optionsName = this->ToolsetOptions.GetLibFlagTableName(
this->GetPlatformName(), this->GetPlatformToolsetString());
-
- return (table != CM_NULLPTR) ? table : this->DefaultLibFlagTable;
+ std::string toolsetName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->GetPlatformToolsetString());
+ std::string defaultName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->DefaultLibFlagTableName);
+ return LoadFlagTable(optionsName, toolsetName, defaultName, "LIB");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const
{
- cmIDEFlagTable const* table = this->ToolsetOptions.GetLinkFlagTable(
+ std::string optionsName = this->ToolsetOptions.GetLinkFlagTableName(
this->GetPlatformName(), this->GetPlatformToolsetString());
-
- return (table != CM_NULLPTR) ? table : this->DefaultLinkFlagTable;
+ std::string toolsetName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->GetPlatformToolsetString());
+ std::string defaultName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->DefaultLinkFlagTableName);
+ return LoadFlagTable(optionsName, toolsetName, defaultName, "Link");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const
{
- return this->DefaultCudaFlagTable;
+ std::string toolsetName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->GetPlatformToolsetString());
+ std::string defaultName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->DefaultCudaFlagTableName);
+ return LoadFlagTable("", toolsetName, defaultName, "Cuda");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable()
const
{
- return this->DefaultCudaHostFlagTable;
+ std::string toolsetName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->GetPlatformToolsetString());
+ std::string defaultName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->DefaultCudaHostFlagTableName);
+ return LoadFlagTable("", toolsetName, defaultName, "CudaHost");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const
{
- cmIDEFlagTable const* table = this->ToolsetOptions.GetMasmFlagTable(
+ std::string optionsName = this->ToolsetOptions.GetMasmFlagTableName(
this->GetPlatformName(), this->GetPlatformToolsetString());
-
- return (table != CM_NULLPTR) ? table : this->DefaultMasmFlagTable;
+ std::string toolsetName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->GetPlatformToolsetString());
+ std::string defaultName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->DefaultMasmFlagTableName);
+ return LoadFlagTable(optionsName, toolsetName, defaultName, "MASM");
}
cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const
{
- return this->DefaultNasmFlagTable;
+ std::string toolsetName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->GetPlatformToolsetString());
+ std::string defaultName = this->ToolsetOptions.GetToolsetName(
+ this->GetPlatformName(), this->DefaultNasmFlagTableName);
+ return LoadFlagTable("", toolsetName, defaultName, "NASM");
}
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 4a5c2454b..56f119363 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -14,33 +14,30 @@
class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator
{
public:
- cmGlobalVisualStudio10Generator(cmake* cm, const std::string& name,
- 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>());
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
- ///! create the correct local generator
- virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf);
+ //! create the correct local generator
+ 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;
bool IsCudaEnabled() const { return this->CudaEnabled; }
@@ -52,13 +49,22 @@ public:
const char* GetPlatformToolset() const;
std::string const& GetPlatformToolsetString() const;
+ /** The toolset version. */
+ const char* GetPlatformToolsetVersion() const;
+ std::string const& GetPlatformToolsetVersionString() const;
+
/** The toolset host architecture name (e.g. x64 for 64-bit host tools). */
const char* GetPlatformToolsetHostArchitecture() const;
+ std::string const& GetPlatformToolsetHostArchitectureString() const;
/** The cuda toolset version. */
const char* GetPlatformToolsetCuda() const;
std::string const& GetPlatformToolsetCudaString() const;
+ /** The custom cuda install directory */
+ const char* GetPlatformToolsetCudaCustomDir() const;
+ std::string const& GetPlatformToolsetCudaCustomDirString() const;
+
/** Return whether we need to use No/Debug instead of false/true
for GenerateDebugInformation. */
bool GetPlatformToolsetNeedsDebugEnum() const
@@ -79,7 +85,7 @@ public:
}
/** Return true if building for WindowsCE */
- bool TargetsWindowsCE() const { return this->SystemIsWindowsCE; }
+ bool TargetsWindowsCE() const override { return this->SystemIsWindowsCE; }
/** Return true if building for WindowsPhone */
bool TargetsWindowsPhone() const { return this->SystemIsWindowsPhone; }
@@ -87,21 +93,32 @@ 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);
- virtual const char* GetToolsVersion() { return "4.0"; }
+ std::string Encoding() override;
+ const char* GetToolsVersion() const;
+
+ virtual bool IsDefaultToolset(const std::string& version) const;
+ virtual std::string GetAuxiliaryToolset() const;
+
+ bool GetSupportsUnityBuilds() const { return this->SupportsUnityBuilds; }
+
+ bool FindMakeProgram(cmMakefile* mf) override;
- bool FindMakeProgram(cmMakefile* mf) CM_OVERRIDE;
+ bool IsIPOSupported() const override { return true; }
static std::string GetInstalledNsightTegraVersion();
+ /** Return the first two components of CMAKE_SYSTEM_VERSION. */
+ std::string GetApplicationTypeRevision() const;
+
cmIDEFlagTable const* GetClFlagTable() const;
cmIDEFlagTable const* GetCSharpFlagTable() const;
cmIDEFlagTable const* GetRcFlagTable() const;
@@ -113,7 +130,10 @@ public:
cmIDEFlagTable const* GetNasmFlagTable() const;
protected:
- virtual void Generate();
+ cmGlobalVisualStudio10Generator(cmake* cm, const std::string& name,
+ std::string const& platformInGeneratorName);
+
+ void Generate() override;
virtual bool InitializeSystem(cmMakefile* mf);
virtual bool InitializeWindows(cmMakefile* mf);
virtual bool InitializeWindowsCE(cmMakefile* mf);
@@ -127,33 +147,42 @@ protected:
virtual bool SelectWindowsPhoneToolset(std::string& toolset) const;
virtual bool SelectWindowsStoreToolset(std::string& toolset) const;
- virtual const char* GetIDEVersion() { return "10.0"; }
-
std::string const& GetMSBuildCommand();
+ cmIDEFlagTable const* LoadFlagTable(std::string const& optionsName,
+ std::string const& toolsetName,
+ std::string const& defaultName,
+ std::string const& table) const;
+
std::string GeneratorToolset;
+ std::string GeneratorToolsetVersion;
std::string GeneratorToolsetHostArchitecture;
std::string GeneratorToolsetCuda;
+ std::string GeneratorToolsetCudaCustomDir;
std::string DefaultPlatformToolset;
+ std::string DefaultPlatformToolsetHostArchitecture;
std::string WindowsTargetPlatformVersion;
std::string SystemName;
std::string SystemVersion;
std::string NsightTegraVersion;
- cmIDEFlagTable const* DefaultClFlagTable;
- cmIDEFlagTable const* DefaultCSharpFlagTable;
- cmIDEFlagTable const* DefaultLibFlagTable;
- cmIDEFlagTable const* DefaultLinkFlagTable;
- cmIDEFlagTable const* DefaultCudaFlagTable;
- cmIDEFlagTable const* DefaultCudaHostFlagTable;
- cmIDEFlagTable const* DefaultMasmFlagTable;
- cmIDEFlagTable const* DefaultNasmFlagTable;
- cmIDEFlagTable const* DefaultRcFlagTable;
+ std::string DefaultCLFlagTableName;
+ std::string DefaultCSharpFlagTableName;
+ std::string DefaultLibFlagTableName;
+ std::string DefaultLinkFlagTableName;
+ std::string DefaultCudaFlagTableName;
+ std::string DefaultCudaHostFlagTableName;
+ std::string DefaultMasmFlagTableName;
+ std::string DefaultNasmFlagTableName;
+ std::string DefaultRCFlagTableName;
+ bool SupportsUnityBuilds = false;
bool SystemIsWindowsCE;
bool SystemIsWindowsPhone;
bool SystemIsWindowsStore;
private:
class Factory;
+ friend class Factory;
+
struct LongestSourcePath
{
LongestSourcePath()
@@ -173,8 +202,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 +215,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 d37d4b095..4b74ef1b2 100644
--- a/Source/cmGlobalVisualStudio11Generator.cxx
+++ b/Source/cmGlobalVisualStudio11Generator.cxx
@@ -6,12 +6,6 @@
#include "cmDocumentationEntry.h"
#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.h"
-#include "cmVS11CLFlagTable.h"
-#include "cmVS11CSharpFlagTable.h"
-#include "cmVS11LibFlagTable.h"
-#include "cmVS11LinkFlagTable.h"
-#include "cmVS11MASMFlagTable.h"
-#include "cmVS11RCFlagTable.h"
static const char vs11generatorName[] = "Visual Studio 11 2012";
@@ -35,7 +29,7 @@ class cmGlobalVisualStudio11Generator::Factory
{
public:
cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
- cmake* cm) const CM_OVERRIDE
+ cmake* cm) const override
{
std::string genName;
const char* p = cmVS11GenName(name, genName);
@@ -68,29 +62,55 @@ public:
return ret;
}
- void GetDocumentation(cmDocumentationEntry& entry) const CM_OVERRIDE
+ void GetDocumentation(cmDocumentationEntry& entry) const override
{
entry.Name = std::string(vs11generatorName) + " [arch]";
entry.Brief = "Generates Visual Studio 2012 project files. "
"Optional [arch] can be \"Win64\" or \"ARM\".";
}
- void GetGenerators(std::vector<std::string>& names) const CM_OVERRIDE
+ std::vector<std::string> GetGeneratorNames() const override
{
+ std::vector<std::string> names;
names.push_back(vs11generatorName);
+ return names;
+ }
+
+ std::vector<std::string> GetGeneratorNamesWithPlatform() const override
+ {
+ std::vector<std::string> names;
names.push_back(vs11generatorName + std::string(" ARM"));
names.push_back(vs11generatorName + std::string(" Win64"));
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);
+ }
+
+ return names;
+ }
+
+ bool SupportsToolset() const override { return true; }
+ bool SupportsPlatform() const override { return true; }
+
+ std::vector<std::string> GetKnownPlatforms() const override
+ {
+ std::vector<std::string> platforms;
+ platforms.emplace_back("x64");
+ platforms.emplace_back("Win32");
+ platforms.emplace_back("ARM");
+
+ std::set<std::string> installedSDKs =
+ cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs();
+ for (std::string const& i : installedSDKs) {
+ platforms.emplace_back(i);
}
+
+ return platforms;
}
- bool SupportsToolset() const CM_OVERRIDE { return true; }
- bool SupportsPlatform() const CM_OVERRIDE { return true; }
+ std::string GetDefaultPlatformName() const override { return "Win32"; }
};
cmGlobalGeneratorFactory* cmGlobalVisualStudio11Generator::NewFactory()
@@ -99,8 +119,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio11Generator::NewFactory()
}
cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator(
- cmake* cm, const std::string& name, const std::string& platformName)
- : cmGlobalVisualStudio10Generator(cm, name, platformName)
+ cmake* cm, const std::string& name,
+ std::string const& platformInGeneratorName)
+ : cmGlobalVisualStudio10Generator(cm, name, platformInGeneratorName)
{
std::string vc11Express;
this->ExpressEdition = cmSystemTools::ReadRegistryValue(
@@ -108,12 +129,12 @@ cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator(
"ProductDir",
vc11Express, cmSystemTools::KeyWOW64_32);
this->DefaultPlatformToolset = "v110";
- this->DefaultClFlagTable = cmVS11CLFlagTable;
- this->DefaultCSharpFlagTable = cmVS11CSharpFlagTable;
- this->DefaultLibFlagTable = cmVS11LibFlagTable;
- this->DefaultLinkFlagTable = cmVS11LinkFlagTable;
- this->DefaultMasmFlagTable = cmVS11MASMFlagTable;
- this->DefaultRcFlagTable = cmVS11RCFlagTable;
+ this->DefaultCLFlagTableName = "v11";
+ this->DefaultCSharpFlagTableName = "v11";
+ this->DefaultLibFlagTableName = "v11";
+ this->DefaultLinkFlagTableName = "v11";
+ this->DefaultMasmFlagTableName = "v11";
+ this->DefaultRCFlagTableName = "v11";
this->Version = VS11;
}
@@ -139,7 +160,7 @@ bool cmGlobalVisualStudio11Generator::InitializeWindowsPhone(cmMakefile* mf)
<< "Desktop SDK as well as the Windows Phone '" << this->SystemVersion
<< "' SDK. Please make sure that you have both installed";
}
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
return true;
@@ -157,7 +178,7 @@ bool cmGlobalVisualStudio11Generator::InitializeWindowsStore(cmMakefile* mf)
<< "Desktop SDK as well as the Windows Store '" << this->SystemVersion
<< "' SDK. Please make sure that you have both installed";
}
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
return true;
@@ -195,17 +216,7 @@ bool cmGlobalVisualStudio11Generator::SelectWindowsStoreToolset(
toolset);
}
-void cmGlobalVisualStudio11Generator::WriteSLNHeader(std::ostream& fout)
-{
- fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
- if (this->ExpressEdition) {
- fout << "# Visual Studio Express 2012 for Windows Desktop\n";
- } else {
- fout << "# Visual Studio 2012\n";
- }
-}
-
-bool cmGlobalVisualStudio11Generator::UseFolderProperty()
+bool cmGlobalVisualStudio11Generator::UseFolderProperty() const
{
// Intentionally skip up to the top-level class implementation.
// Folders are not supported by the Express editions in VS10 and earlier,
@@ -224,33 +235,27 @@ 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);
}
}
return ret;
}
-bool cmGlobalVisualStudio11Generator::NeedsDeploy(
- cmStateEnums::TargetType type) const
+bool cmGlobalVisualStudio11Generator::TargetSystemSupportsDeployment() const
{
- if ((type == cmStateEnums::EXECUTABLE ||
- type == cmStateEnums::SHARED_LIBRARY) &&
- (this->SystemIsWindowsPhone || this->SystemIsWindowsStore)) {
- return true;
- }
- return cmGlobalVisualStudio10Generator::NeedsDeploy(type);
+ return this->SystemIsWindowsPhone || this->SystemIsWindowsStore ||
+ cmGlobalVisualStudio10Generator::TargetSystemSupportsDeployment();
}
bool cmGlobalVisualStudio11Generator::IsWindowsDesktopToolsetInstalled() const
diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h
index b4b327d8a..f8cce1898 100644
--- a/Source/cmGlobalVisualStudio11Generator.h
+++ b/Source/cmGlobalVisualStudio11Generator.h
@@ -3,7 +3,7 @@
#ifndef cmGlobalVisualStudio11Generator_h
#define cmGlobalVisualStudio11Generator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <set>
@@ -20,19 +20,18 @@ class cmake;
class cmGlobalVisualStudio11Generator : public cmGlobalVisualStudio10Generator
{
public:
- cmGlobalVisualStudio11Generator(cmake* cm, const std::string& name,
- const std::string& platformName);
static cmGlobalGeneratorFactory* NewFactory();
- virtual bool MatchesGeneratorName(const std::string& name) const;
-
- virtual void WriteSLNHeader(std::ostream& fout);
+ bool MatchesGeneratorName(const std::string& name) const 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;
+ cmGlobalVisualStudio11Generator(cmake* cm, const std::string& name,
+ std::string const& platformInGeneratorName);
+
+ 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 +42,11 @@ protected:
bool IsWindowsPhoneToolsetInstalled() const;
bool IsWindowsStoreToolsetInstalled() const;
- virtual const char* GetIDEVersion() { return "11.0"; }
- bool UseFolderProperty();
+ bool UseFolderProperty() const override;
static std::set<std::string> GetInstalledWindowsCESDKs();
- /** Return true if the configuration needs to be deployed */
- virtual bool NeedsDeploy(cmStateEnums::TargetType type) const;
+ /** Return true if target system supports debugging deployment. */
+ bool TargetSystemSupportsDeployment() const override;
private:
class Factory;
diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx
index de62ff0ac..d9702c9ee 100644
--- a/Source/cmGlobalVisualStudio12Generator.cxx
+++ b/Source/cmGlobalVisualStudio12Generator.cxx
@@ -6,12 +6,6 @@
#include "cmDocumentationEntry.h"
#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.h"
-#include "cmVS12CLFlagTable.h"
-#include "cmVS12CSharpFlagTable.h"
-#include "cmVS12LibFlagTable.h"
-#include "cmVS12LinkFlagTable.h"
-#include "cmVS12MASMFlagTable.h"
-#include "cmVS12RCFlagTable.h"
static const char vs12generatorName[] = "Visual Studio 12 2013";
@@ -35,7 +29,7 @@ class cmGlobalVisualStudio12Generator::Factory
{
public:
cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
- cmake* cm) const CM_OVERRIDE
+ cmake* cm) const override
{
std::string genName;
const char* p = cmVS12GenName(name, genName);
@@ -57,22 +51,41 @@ public:
return 0;
}
- void GetDocumentation(cmDocumentationEntry& entry) const CM_OVERRIDE
+ void GetDocumentation(cmDocumentationEntry& entry) const override
{
entry.Name = std::string(vs12generatorName) + " [arch]";
entry.Brief = "Generates Visual Studio 2013 project files. "
"Optional [arch] can be \"Win64\" or \"ARM\".";
}
- void GetGenerators(std::vector<std::string>& names) const CM_OVERRIDE
+ std::vector<std::string> GetGeneratorNames() const override
{
+ std::vector<std::string> names;
names.push_back(vs12generatorName);
+ return names;
+ }
+
+ std::vector<std::string> GetGeneratorNamesWithPlatform() const override
+ {
+ std::vector<std::string> names;
names.push_back(vs12generatorName + std::string(" ARM"));
names.push_back(vs12generatorName + std::string(" Win64"));
+ return names;
}
- bool SupportsToolset() const CM_OVERRIDE { return true; }
- bool SupportsPlatform() const CM_OVERRIDE { return true; }
+ bool SupportsToolset() const override { return true; }
+ bool SupportsPlatform() const override { return true; }
+
+ std::vector<std::string> GetKnownPlatforms() const override
+ {
+ std::vector<std::string> platforms;
+ platforms.emplace_back("x64");
+ platforms.emplace_back("Win32");
+ platforms.emplace_back("ARM");
+ return platforms;
+ }
+
+ std::string GetDefaultPlatformName() const override { return "Win32"; }
};
cmGlobalGeneratorFactory* cmGlobalVisualStudio12Generator::NewFactory()
@@ -81,8 +94,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio12Generator::NewFactory()
}
cmGlobalVisualStudio12Generator::cmGlobalVisualStudio12Generator(
- cmake* cm, const std::string& name, const std::string& platformName)
- : cmGlobalVisualStudio11Generator(cm, name, platformName)
+ cmake* cm, const std::string& name,
+ std::string const& platformInGeneratorName)
+ : cmGlobalVisualStudio11Generator(cm, name, platformInGeneratorName)
{
std::string vc12Express;
this->ExpressEdition = cmSystemTools::ReadRegistryValue(
@@ -90,12 +104,12 @@ cmGlobalVisualStudio12Generator::cmGlobalVisualStudio12Generator(
"ProductDir",
vc12Express, cmSystemTools::KeyWOW64_32);
this->DefaultPlatformToolset = "v120";
- this->DefaultClFlagTable = cmVS12CLFlagTable;
- this->DefaultCSharpFlagTable = cmVS12CSharpFlagTable;
- this->DefaultLibFlagTable = cmVS12LibFlagTable;
- this->DefaultLinkFlagTable = cmVS12LinkFlagTable;
- this->DefaultMasmFlagTable = cmVS12MASMFlagTable;
- this->DefaultRcFlagTable = cmVS12RCFlagTable;
+ this->DefaultCLFlagTableName = "v12";
+ this->DefaultCSharpFlagTableName = "v12";
+ this->DefaultLibFlagTableName = "v12";
+ this->DefaultLinkFlagTableName = "v12";
+ this->DefaultMasmFlagTableName = "v12";
+ this->DefaultRCFlagTableName = "v12";
this->Version = VS12;
}
@@ -112,8 +126,8 @@ bool cmGlobalVisualStudio12Generator::MatchesGeneratorName(
bool cmGlobalVisualStudio12Generator::ProcessGeneratorToolsetField(
std::string const& key, std::string const& value)
{
- if (key == "host" && value == "x64") {
- this->GeneratorToolsetHostArchitecture = "x64";
+ if (key == "host" && (value == "x64" || value == "x86")) {
+ this->GeneratorToolsetHostArchitecture = value;
return true;
}
return this->cmGlobalVisualStudio11Generator::ProcessGeneratorToolsetField(
@@ -125,15 +139,16 @@ bool cmGlobalVisualStudio12Generator::InitializeWindowsPhone(cmMakefile* mf)
if (!this->SelectWindowsPhoneToolset(this->DefaultPlatformToolset)) {
std::ostringstream e;
if (this->DefaultPlatformToolset.empty()) {
- e << this->GetName() << " supports Windows Phone '8.0' and '8.1', but "
- "not '"
+ e << this->GetName()
+ << " supports Windows Phone '8.0' and '8.1', but "
+ "not '"
<< this->SystemVersion << "'. Check CMAKE_SYSTEM_VERSION.";
} else {
e << "A Windows Phone component with CMake requires both the Windows "
<< "Desktop SDK as well as the Windows Phone '" << this->SystemVersion
<< "' SDK. Please make sure that you have both installed";
}
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
return true;
@@ -144,15 +159,16 @@ bool cmGlobalVisualStudio12Generator::InitializeWindowsStore(cmMakefile* mf)
if (!this->SelectWindowsStoreToolset(this->DefaultPlatformToolset)) {
std::ostringstream e;
if (this->DefaultPlatformToolset.empty()) {
- e << this->GetName() << " supports Windows Store '8.0' and '8.1', but "
- "not '"
+ e << this->GetName()
+ << " supports Windows Store '8.0' and '8.1', but "
+ "not '"
<< this->SystemVersion << "'. Check CMAKE_SYSTEM_VERSION.";
} else {
e << "A Windows Store component with CMake requires both the Windows "
<< "Desktop SDK as well as the Windows Store '" << this->SystemVersion
<< "' SDK. Please make sure that you have both installed";
}
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
return true;
@@ -190,16 +206,6 @@ bool cmGlobalVisualStudio12Generator::SelectWindowsStoreToolset(
toolset);
}
-void cmGlobalVisualStudio12Generator::WriteSLNHeader(std::ostream& fout)
-{
- fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
- if (this->ExpressEdition) {
- fout << "# Visual Studio Express 2013 for Windows Desktop\n";
- } else {
- fout << "# Visual Studio 2013\n";
- }
-}
-
bool cmGlobalVisualStudio12Generator::IsWindowsDesktopToolsetInstalled() const
{
const char desktop81Key[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h
index ebc95bb63..53b709157 100644
--- a/Source/cmGlobalVisualStudio12Generator.h
+++ b/Source/cmGlobalVisualStudio12Generator.h
@@ -3,7 +3,7 @@
#ifndef cmGlobalVisualStudio12Generator_h
#define cmGlobalVisualStudio12Generator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
@@ -18,37 +18,33 @@ class cmake;
class cmGlobalVisualStudio12Generator : public cmGlobalVisualStudio11Generator
{
public:
- cmGlobalVisualStudio12Generator(cmake* cm, const std::string& name,
- const std::string& platformName);
static cmGlobalGeneratorFactory* NewFactory();
- virtual bool MatchesGeneratorName(const std::string& name) const;
-
- virtual void WriteSLNHeader(std::ostream& fout);
+ bool MatchesGeneratorName(const std::string& name) const 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"; }
protected:
+ cmGlobalVisualStudio12Generator(cmake* cm, const std::string& name,
+ std::string const& platformInGeneratorName);
+
bool ProcessGeneratorToolsetField(std::string const& key,
- std::string const& value) CM_OVERRIDE;
+ 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"; }
+
private:
class Factory;
+ friend class Factory;
};
#endif
diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx
index c8cf02cdd..cd4847427 100644
--- a/Source/cmGlobalVisualStudio14Generator.cxx
+++ b/Source/cmGlobalVisualStudio14Generator.cxx
@@ -6,12 +6,6 @@
#include "cmDocumentationEntry.h"
#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.h"
-#include "cmVS140CLFlagTable.h"
-#include "cmVS140CSharpFlagTable.h"
-#include "cmVS140LinkFlagTable.h"
-#include "cmVS14LibFlagTable.h"
-#include "cmVS14MASMFlagTable.h"
-#include "cmVS14RCFlagTable.h"
static const char vs14generatorName[] = "Visual Studio 14 2015";
@@ -35,7 +29,7 @@ class cmGlobalVisualStudio14Generator::Factory
{
public:
cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
- cmake* cm) const CM_OVERRIDE
+ cmake* cm) const override
{
std::string genName;
const char* p = cmVS14GenName(name, genName);
@@ -57,22 +51,41 @@ public:
return 0;
}
- void GetDocumentation(cmDocumentationEntry& entry) const CM_OVERRIDE
+ void GetDocumentation(cmDocumentationEntry& entry) const override
{
entry.Name = std::string(vs14generatorName) + " [arch]";
entry.Brief = "Generates Visual Studio 2015 project files. "
"Optional [arch] can be \"Win64\" or \"ARM\".";
}
- void GetGenerators(std::vector<std::string>& names) const CM_OVERRIDE
+ std::vector<std::string> GetGeneratorNames() const override
{
+ std::vector<std::string> names;
names.push_back(vs14generatorName);
+ return names;
+ }
+
+ std::vector<std::string> GetGeneratorNamesWithPlatform() const override
+ {
+ std::vector<std::string> names;
names.push_back(vs14generatorName + std::string(" ARM"));
names.push_back(vs14generatorName + std::string(" Win64"));
+ return names;
}
- bool SupportsToolset() const CM_OVERRIDE { return true; }
- bool SupportsPlatform() const CM_OVERRIDE { return true; }
+ bool SupportsToolset() const override { return true; }
+ bool SupportsPlatform() const override { return true; }
+
+ std::vector<std::string> GetKnownPlatforms() const override
+ {
+ std::vector<std::string> platforms;
+ platforms.emplace_back("x64");
+ platforms.emplace_back("Win32");
+ platforms.emplace_back("ARM");
+ return platforms;
+ }
+
+ std::string GetDefaultPlatformName() const override { return "Win32"; }
};
cmGlobalGeneratorFactory* cmGlobalVisualStudio14Generator::NewFactory()
@@ -81,8 +94,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio14Generator::NewFactory()
}
cmGlobalVisualStudio14Generator::cmGlobalVisualStudio14Generator(
- cmake* cm, const std::string& name, const std::string& platformName)
- : cmGlobalVisualStudio12Generator(cm, name, platformName)
+ cmake* cm, const std::string& name,
+ std::string const& platformInGeneratorName)
+ : cmGlobalVisualStudio12Generator(cm, name, platformInGeneratorName)
{
std::string vc14Express;
this->ExpressEdition = cmSystemTools::ReadRegistryValue(
@@ -90,12 +104,12 @@ cmGlobalVisualStudio14Generator::cmGlobalVisualStudio14Generator(
"ProductDir",
vc14Express, cmSystemTools::KeyWOW64_32);
this->DefaultPlatformToolset = "v140";
- this->DefaultClFlagTable = cmVS140CLFlagTable;
- this->DefaultCSharpFlagTable = cmVS140CSharpFlagTable;
- this->DefaultLibFlagTable = cmVS14LibFlagTable;
- this->DefaultLinkFlagTable = cmVS140LinkFlagTable;
- this->DefaultMasmFlagTable = cmVS14MASMFlagTable;
- this->DefaultRcFlagTable = cmVS14RCFlagTable;
+ this->DefaultCLFlagTableName = "v140";
+ this->DefaultCSharpFlagTableName = "v140";
+ this->DefaultLibFlagTableName = "v14";
+ this->DefaultLinkFlagTableName = "v140";
+ this->DefaultMasmFlagTableName = "v14";
+ this->DefaultRCFlagTableName = "v14";
this->Version = VS14;
}
@@ -122,15 +136,16 @@ bool cmGlobalVisualStudio14Generator::InitializeWindowsStore(cmMakefile* mf)
std::ostringstream e;
if (!this->SelectWindowsStoreToolset(this->DefaultPlatformToolset)) {
if (this->DefaultPlatformToolset.empty()) {
- e << this->GetName() << " supports Windows Store '8.0', '8.1' and "
- "'10.0', but not '"
+ e << this->GetName()
+ << " supports Windows Store '8.0', '8.1' and "
+ "'10.0', but not '"
<< this->SystemVersion << "'. Check CMAKE_SYSTEM_VERSION.";
} else {
e << "A Windows Store component with CMake requires both the Windows "
<< "Desktop SDK as well as the Windows Store '" << this->SystemVersion
<< "' SDK. Please make sure that you have both installed";
}
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) {
@@ -143,19 +158,33 @@ bool cmGlobalVisualStudio14Generator::SelectWindows10SDK(cmMakefile* mf,
bool required)
{
// Find the default version of the Windows 10 SDK.
- this->WindowsTargetPlatformVersion = this->GetWindows10SDKVersion();
- if (required && this->WindowsTargetPlatformVersion.empty()) {
+ std::string const version = this->GetWindows10SDKVersion();
+ if (required && version.empty()) {
std::ostringstream e;
e << "Could not find an appropriate version of the Windows 10 SDK"
<< " installed on this machine";
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
- mf->AddDefinition("CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION",
- this->WindowsTargetPlatformVersion.c_str());
+ this->SetWindowsTargetPlatformVersion(version, mf);
return true;
}
+void cmGlobalVisualStudio14Generator::SetWindowsTargetPlatformVersion(
+ std::string const& version, cmMakefile* mf)
+{
+ this->WindowsTargetPlatformVersion = version;
+ if (!cmSystemTools::VersionCompareEqual(this->WindowsTargetPlatformVersion,
+ this->SystemVersion)) {
+ std::ostringstream e;
+ e << "Selecting Windows SDK version " << this->WindowsTargetPlatformVersion
+ << " to target Windows " << this->SystemVersion << ".";
+ mf->DisplayStatus(e.str(), -1);
+ }
+ mf->AddDefinition("CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION",
+ this->WindowsTargetPlatformVersion);
+}
+
bool cmGlobalVisualStudio14Generator::SelectWindowsStoreToolset(
std::string& toolset) const
{
@@ -172,17 +201,6 @@ bool cmGlobalVisualStudio14Generator::SelectWindowsStoreToolset(
toolset);
}
-void cmGlobalVisualStudio14Generator::WriteSLNHeader(std::ostream& fout)
-{
- // Visual Studio 14 writes .sln format 12.00
- fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
- if (this->ExpressEdition) {
- fout << "# Visual Studio Express 14 for Windows Desktop\n";
- } else {
- fout << "# Visual Studio 14\n";
- }
-}
-
bool cmGlobalVisualStudio14Generator::IsWindowsDesktopToolsetInstalled() const
{
const char desktop10Key[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
@@ -204,6 +222,16 @@ bool cmGlobalVisualStudio14Generator::IsWindowsStoreToolsetInstalled() const
cmSystemTools::KeyWOW64_32);
}
+std::string cmGlobalVisualStudio14Generator::GetWindows10SDKMaxVersion() const
+{
+ // The last Windows 10 SDK version that VS 2015 can target is 10.0.14393.0.
+ //
+ // "VS 2015 Users: The Windows 10 SDK (15063, 16299, 17134, 17763) is
+ // officially only supported for VS 2017." From:
+ // https://blogs.msdn.microsoft.com/chuckw/2018/10/02/windows-10-october-2018-update/
+ return "10.0.14393.0";
+}
+
#if defined(_WIN32) && !defined(__CYGWIN__)
struct NoWindowsH
{
@@ -212,6 +240,20 @@ struct NoWindowsH
return !cmSystemTools::FileExists(p + "/um/windows.h", true);
}
};
+class WindowsSDKTooRecent
+{
+ std::string const& MaxVersion;
+
+public:
+ WindowsSDKTooRecent(std::string const& maxVersion)
+ : MaxVersion(maxVersion)
+ {
+ }
+ bool operator()(std::string const& v)
+ {
+ return cmSystemTools::VersionCompareGreater(v, MaxVersion);
+ }
+};
#endif
std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion()
@@ -250,9 +292,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);
}
@@ -260,24 +301,28 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion()
// only the UCRT MSIs were installed for them.
cmEraseIf(sdks, NoWindowsH());
- 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);
- }
+ // Only use the filename, which will be the SDK version.
+ 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);
+ // Skip SDKs that cannot be used with our toolset.
+ std::string maxVersion = this->GetWindows10SDKMaxVersion();
+ if (!maxVersion.empty()) {
+ cmEraseIf(sdks, WindowsSDKTooRecent(maxVersion));
+ }
+
+ // 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;
- }
+ // Look for a SDK exactly matching the requested target version.
+ for (std::string const& i : sdks) {
+ if (cmSystemTools::VersionCompareEqual(i, this->SystemVersion)) {
+ return i;
}
+ }
+ if (!sdks.empty()) {
// Use the latest Windows 10 SDK since the exact version is not available.
return sdks.at(0);
}
diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h
index 0ce9a5641..6e12d3e2c 100644
--- a/Source/cmGlobalVisualStudio14Generator.h
+++ b/Source/cmGlobalVisualStudio14Generator.h
@@ -3,7 +3,7 @@
#ifndef cmGlobalVisualStudio14Generator_h
#define cmGlobalVisualStudio14Generator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
@@ -18,34 +18,39 @@ class cmake;
class cmGlobalVisualStudio14Generator : public cmGlobalVisualStudio12Generator
{
public:
- cmGlobalVisualStudio14Generator(cmake* cm, const std::string& name,
- const std::string& platformName);
static cmGlobalGeneratorFactory* NewFactory();
- virtual bool MatchesGeneratorName(const std::string& name) const;
-
- virtual void WriteSLNHeader(std::ostream& fout);
+ bool MatchesGeneratorName(const std::string& name) const override;
- virtual const char* GetToolsVersion() { return "14.0"; }
protected:
- virtual bool InitializeWindows(cmMakefile* mf);
- virtual bool InitializeWindowsStore(cmMakefile* mf);
- virtual bool SelectWindowsStoreToolset(std::string& toolset) const;
+ cmGlobalVisualStudio14Generator(cmake* cm, const std::string& name,
+ std::string const& platformInGeneratorName);
+
+ 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"; }
+ // Used to make sure that the Windows 10 SDK selected can work with the
+ // version of the toolset.
+ virtual std::string GetWindows10SDKMaxVersion() const;
+
virtual bool SelectWindows10SDK(cmMakefile* mf, bool required);
+ void SetWindowsTargetPlatformVersion(std::string const& version,
+ cmMakefile* mf);
+
// 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();
private:
class Factory;
+ friend class Factory;
};
#endif
diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx
deleted file mode 100644
index ce1ba007f..000000000
--- a/Source/cmGlobalVisualStudio15Generator.cxx
+++ /dev/null
@@ -1,206 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmGlobalVisualStudio15Generator.h"
-
-#include "cmAlgorithms.h"
-#include "cmDocumentationEntry.h"
-#include "cmLocalVisualStudio10Generator.h"
-#include "cmMakefile.h"
-#include "cmVS141CLFlagTable.h"
-#include "cmVS141CSharpFlagTable.h"
-#include "cmVS141LinkFlagTable.h"
-#include "cmVSSetupHelper.h"
-
-static const char vs15generatorName[] = "Visual Studio 15 2017";
-
-// Map generator name without year to name with year.
-static const char* cmVS15GenName(const std::string& name, std::string& genName)
-{
- if (strncmp(name.c_str(), vs15generatorName,
- sizeof(vs15generatorName) - 6) != 0) {
- return 0;
- }
- const char* p = name.c_str() + sizeof(vs15generatorName) - 6;
- if (cmHasLiteralPrefix(p, " 2017")) {
- p += 5;
- }
- genName = std::string(vs15generatorName) + p;
- return p;
-}
-
-class cmGlobalVisualStudio15Generator::Factory
- : public cmGlobalGeneratorFactory
-{
-public:
- virtual cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
- cmake* cm) const
- {
- std::string genName;
- const char* p = cmVS15GenName(name, genName);
- if (!p) {
- return 0;
- }
- if (!*p) {
- return new cmGlobalVisualStudio15Generator(cm, genName, "");
- }
- if (*p++ != ' ') {
- return 0;
- }
- if (strcmp(p, "Win64") == 0) {
- return new cmGlobalVisualStudio15Generator(cm, genName, "x64");
- }
- if (strcmp(p, "ARM") == 0) {
- return new cmGlobalVisualStudio15Generator(cm, genName, "ARM");
- }
- return 0;
- }
-
- virtual void GetDocumentation(cmDocumentationEntry& entry) const
- {
- entry.Name = std::string(vs15generatorName) + " [arch]";
- entry.Brief = "Generates Visual Studio 2017 project files. "
- "Optional [arch] can be \"Win64\" or \"ARM\".";
- }
-
- virtual void GetGenerators(std::vector<std::string>& names) const
- {
- names.push_back(vs15generatorName);
- names.push_back(vs15generatorName + std::string(" ARM"));
- names.push_back(vs15generatorName + std::string(" Win64"));
- }
-
- bool SupportsToolset() const CM_OVERRIDE { return true; }
- bool SupportsPlatform() const CM_OVERRIDE { return true; }
-};
-
-cmGlobalGeneratorFactory* cmGlobalVisualStudio15Generator::NewFactory()
-{
- return new Factory;
-}
-
-cmGlobalVisualStudio15Generator::cmGlobalVisualStudio15Generator(
- cmake* cm, const std::string& name, const std::string& platformName)
- : cmGlobalVisualStudio14Generator(cm, name, platformName)
-{
- this->ExpressEdition = false;
- this->DefaultPlatformToolset = "v141";
- this->DefaultClFlagTable = cmVS141CLFlagTable;
- this->DefaultCSharpFlagTable = cmVS141CSharpFlagTable;
- this->DefaultLinkFlagTable = cmVS141LinkFlagTable;
- this->Version = VS15;
-}
-
-bool cmGlobalVisualStudio15Generator::MatchesGeneratorName(
- const std::string& name) const
-{
- std::string genName;
- if (cmVS15GenName(name, genName)) {
- return genName == this->GetName();
- }
- return false;
-}
-
-void cmGlobalVisualStudio15Generator::WriteSLNHeader(std::ostream& fout)
-{
- // Visual Studio 15 writes .sln format 12.00
- fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
- if (this->ExpressEdition) {
- fout << "# Visual Studio Express 15 for Windows Desktop\n";
- } else {
- fout << "# Visual Studio 15\n";
- }
-}
-
-bool cmGlobalVisualStudio15Generator::InitializeWindows(cmMakefile* mf)
-{
- // If the Win 8.1 SDK is installed then we can select a SDK matching
- // the target Windows version.
- if (this->IsWin81SDKInstalled()) {
- return cmGlobalVisualStudio14Generator::InitializeWindows(mf);
- }
- // Otherwise we must choose a Win 10 SDK even if we are not targeting
- // Windows 10.
- return this->SelectWindows10SDK(mf, false);
-}
-
-bool cmGlobalVisualStudio15Generator::SelectWindowsStoreToolset(
- std::string& toolset) const
-{
- if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) {
- if (this->IsWindowsStoreToolsetInstalled() &&
- this->IsWindowsDesktopToolsetInstalled()) {
- toolset = "v141"; // VS 15 uses v141 toolset
- return true;
- } else {
- return false;
- }
- }
- return this->cmGlobalVisualStudio14Generator::SelectWindowsStoreToolset(
- toolset);
-}
-
-bool cmGlobalVisualStudio15Generator::IsWindowsDesktopToolsetInstalled() const
-{
- return vsSetupAPIHelper.IsVS2017Installed();
-}
-
-bool cmGlobalVisualStudio15Generator::IsWindowsStoreToolsetInstalled() const
-{
- return vsSetupAPIHelper.IsWin10SDKInstalled();
-}
-
-bool cmGlobalVisualStudio15Generator::IsWin81SDKInstalled() const
-{
- // Does the VS installer tool know about one?
- if (vsSetupAPIHelper.IsWin81SDKInstalled()) {
- return true;
- }
-
- // Does the registry know about one (e.g. from VS 2015)?
- std::string win81Root;
- if (cmSystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
- "Windows Kits\\Installed Roots;KitsRoot81",
- win81Root, cmSystemTools::KeyWOW64_32) ||
- cmSystemTools::ReadRegistryValue(
- "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\"
- "Windows Kits\\Installed Roots;KitsRoot81",
- win81Root, cmSystemTools::KeyWOW64_32)) {
- return cmSystemTools::FileExists(win81Root + "/um/windows.h", true);
- }
- return false;
-}
-
-std::string cmGlobalVisualStudio15Generator::FindMSBuildCommand()
-{
- std::string msbuild;
-
- // Ask Visual Studio Installer tool.
- std::string vs;
- if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) {
- msbuild = vs + "/MSBuild/15.0/Bin/MSBuild.exe";
- if (cmSystemTools::FileExists(msbuild)) {
- return msbuild;
- }
- }
-
- msbuild = "MSBuild.exe";
- return msbuild;
-}
-
-std::string cmGlobalVisualStudio15Generator::FindDevEnvCommand()
-{
- std::string devenv;
-
- // Ask Visual Studio Installer tool.
- std::string vs;
- if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) {
- devenv = vs + "/Common7/IDE/devenv.com";
- if (cmSystemTools::FileExists(devenv)) {
- return devenv;
- }
- }
-
- devenv = "devenv.com";
- return devenv;
-}
diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudio15Generator.h
deleted file mode 100644
index 4be88f44f..000000000
--- a/Source/cmGlobalVisualStudio15Generator.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmGlobalVisualStudio15Generator_h
-#define cmGlobalVisualStudio15Generator_h
-
-#include "cmConfigure.h"
-
-#include <iosfwd>
-#include <string>
-
-#include "cmGlobalVisualStudio14Generator.h"
-#include "cmVSSetupHelper.h"
-
-class cmGlobalGeneratorFactory;
-class cmake;
-
-/** \class cmGlobalVisualStudio15Generator */
-class cmGlobalVisualStudio15Generator : public cmGlobalVisualStudio14Generator
-{
-public:
- cmGlobalVisualStudio15Generator(cmake* cm, const std::string& name,
- const std::string& platformName);
- static cmGlobalGeneratorFactory* NewFactory();
-
- virtual bool MatchesGeneratorName(const std::string& name) const;
-
- virtual void WriteSLNHeader(std::ostream& fout);
-
- virtual const char* GetToolsVersion() { return "15.0"; }
-protected:
- bool InitializeWindows(cmMakefile* mf) CM_OVERRIDE;
- virtual bool SelectWindowsStoreToolset(std::string& toolset) const;
-
- virtual const char* GetIDEVersion() { return "15.0"; }
-
- // Used to verify that the Desktop toolset for the current generator is
- // installed on the machine.
- virtual bool IsWindowsDesktopToolsetInstalled() const;
-
- // These aren't virtual because we need to check if the selected version
- // of the toolset is installed
- bool IsWindowsStoreToolsetInstalled() const;
-
- // Check for a Win 8 SDK known to the registry or VS installer tool.
- bool IsWin81SDKInstalled() const;
-
- std::string FindMSBuildCommand() CM_OVERRIDE;
- std::string FindDevEnvCommand() CM_OVERRIDE;
-
-private:
- class Factory;
- mutable cmVSSetupAPIHelper vsSetupAPIHelper;
-};
-#endif
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index 3b45c902c..e8e9eced9 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -6,7 +6,7 @@
#include "cmGeneratorTarget.h"
#include "cmLocalVisualStudio7Generator.h"
#include "cmMakefile.h"
-#include "cmake.h"
+#include "cmMessageType.h"
cmGlobalVisualStudio71Generator::cmGlobalVisualStudio71Generator(
cmake* cm, const std::string& platformName)
@@ -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";
}
@@ -99,7 +98,7 @@ void cmGlobalVisualStudio71Generator::WriteProject(std::ostream& fout,
ext = ".vfproj";
project = "Project(\"{6989167D-11E4-40FE-8C1A-2192A86A7E90}\") = \"";
}
- if (this->TargetIsCSharpOnly(t)) {
+ if (t->IsCSharpOnly()) {
ext = ".csproj";
project = "Project(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"";
}
@@ -143,16 +142,12 @@ 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: ";
- m += target->GetName();
- m += " depends on unknown target: ";
- m += name;
- cmSystemTools::Error(m.c_str());
+ std::string m = cmStrCat("Target: ", target->GetName(),
+ " depends on unknown target: ", name);
+ cmSystemTools::Error(m);
}
fout << "\t\t{" << guid << "} = {" << guid << "}\n";
}
@@ -162,7 +157,7 @@ void cmGlobalVisualStudio71Generator::WriteProjectDepends(
// executables to the libraries it uses are also done here
void cmGlobalVisualStudio71Generator::WriteExternalProject(
std::ostream& fout, const std::string& name, const char* location,
- const char* typeGuid, const std::set<std::string>& depends)
+ const char* typeGuid, const std::set<BT<std::string>>& depends)
{
fout << "Project(\"{"
<< (typeGuid ? typeGuid : this->ExternalProjectType(location))
@@ -174,11 +169,11 @@ 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 (BT<std::string> const& it : depends) {
+ std::string const& dep = it.Value;
+ if (!dep.empty()) {
+ fout << "\t\t{" << this->GetGUID(dep) << "} = {" << this->GetGUID(dep)
+ << "}\n";
}
}
fout << "\tEndProjectSection\n";
@@ -198,32 +193,25 @@ 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::ExpandListArgument(m, mapConfig);
+ cmSystemTools::UpperCase(i))) {
+ cmExpandList(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
-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..85755af60 100644
--- a/Source/cmGlobalVisualStudio71Generator.h
+++ b/Source/cmGlobalVisualStudio71Generator.h
@@ -17,28 +17,26 @@ 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<BT<std::string>>& depends) override;
// Folders are not supported by VS 7.1.
- virtual bool UseFolderProperty() { return false; }
+ bool UseFolderProperty() const override { return false; }
std::string ProjectConfigurationSectionName;
};
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index b155f5b55..40b214c03 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -2,18 +2,26 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio7Generator.h"
+#include <vector>
+
+#include <cm/string_view>
+
+#include <windows.h>
+
+#include <assert.h>
+
+#include "cmsys/Encoding.hxx"
+
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmLocalVisualStudio7Generator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmState.h"
+#include "cmStringAlgorithms.h"
#include "cmUuid.h"
#include "cmake.h"
-#include "cmsys/Encoding.hxx"
-
-#include <assert.h>
-#include <vector>
-#include <windows.h>
static cmVS7FlagTable cmVS7ExtraFlagTable[] = {
// Precompiled header and related options. Note that the
@@ -37,43 +45,44 @@ static cmVS7FlagTable cmVS7ExtraFlagTable[] = {
// and have EHa passed on the command line by leaving out the table
// entry.
- { 0, 0, 0, 0, 0 }
+ { "", "", "", "", 0 }
};
+namespace {
+std::string GetSLNFile(cmLocalGenerator* root)
+{
+ return cmStrCat(root->GetCurrentBinaryDirectory(), '/',
+ root->GetProjectName(), ".sln");
+}
+}
+
cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator(
- cmake* cm, const std::string& platformName)
- : cmGlobalVisualStudioGenerator(cm)
+ cmake* cm, std::string const& platformInGeneratorName)
+ : cmGlobalVisualStudioGenerator(cm, platformInGeneratorName)
{
- this->IntelProjectVersion = 0;
this->DevEnvCommandInitialized = false;
this->MasmEnabled = false;
this->NasmEnabled = false;
-
- if (platformName.empty()) {
- this->DefaultPlatformName = "Win32";
- } else {
- this->DefaultPlatformName = platformName;
- }
this->ExtraFlagTable = cmVS7ExtraFlagTable;
}
cmGlobalVisualStudio7Generator::~cmGlobalVisualStudio7Generator()
{
- free(this->IntelProjectVersion);
}
// Package GUID of Intel Visual Fortran plugin to VS IDE
#define CM_INTEL_PLUGIN_GUID "{B68A201D-CB9B-47AF-A52F-7EEC72E217E4}"
-const char* cmGlobalVisualStudio7Generator::GetIntelProjectVersion()
+const std::string& cmGlobalVisualStudio7Generator::GetIntelProjectVersion()
{
- if (!this->IntelProjectVersion) {
+ if (this->IntelProjectVersion.empty()) {
// Compute the version of the Intel plugin to the VS IDE.
// If the key does not exist then use a default guess.
std::string intelVersion;
- std::string vskey = this->GetRegistryBase();
- vskey += "\\Packages\\" CM_INTEL_PLUGIN_GUID ";ProductVersion";
- cmSystemTools::ReadRegistryValue(vskey.c_str(), intelVersion,
+ std::string vskey =
+ cmStrCat(this->GetRegistryBase(),
+ "\\Packages\\" CM_INTEL_PLUGIN_GUID ";ProductVersion");
+ cmSystemTools::ReadRegistryValue(vskey, intelVersion,
cmSystemTools::KeyWOW64_32);
unsigned int intelVersionNumber = ~0u;
sscanf(intelVersion.c_str(), "%u", &intelVersionNumber);
@@ -86,7 +95,7 @@ const char* cmGlobalVisualStudio7Generator::GetIntelProjectVersion()
} else {
// Version <= 9: use ProductVersion from registry.
}
- this->IntelProjectVersion = strdup(intelVersion.c_str());
+ this->IntelProjectVersion = intelVersion;
}
return this->IntelProjectVersion;
}
@@ -106,7 +115,7 @@ void cmGlobalVisualStudio7Generator::EnableLanguage(
}
// Create list of configurations requested by user's cache, if any.
- this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
+ this->cmGlobalVisualStudioGenerator::EnableLanguage(lang, mf, optional);
// if this environment variable is set, then copy it to
// a static cache entry. It will be used by
@@ -128,8 +137,7 @@ bool cmGlobalVisualStudio7Generator::FindMakeProgram(cmMakefile* mf)
if (!this->cmGlobalVisualStudioGenerator::FindMakeProgram(mf)) {
return false;
}
- mf->AddDefinition("CMAKE_VS_DEVENV_COMMAND",
- this->GetDevEnvCommand().c_str());
+ mf->AddDefinition("CMAKE_VS_DEVENV_COMMAND", this->GetDevEnvCommand());
return true;
}
@@ -159,8 +167,9 @@ std::string cmGlobalVisualStudio7Generator::FindDevEnvCommand()
}
// Search where VS15Preview places it.
- vskey = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7;";
- vskey += this->GetIDEVersion();
+ vskey = cmStrCat(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7;",
+ this->GetIDEVersion());
if (cmSystemTools::ReadRegistryValue(vskey.c_str(), vscmd,
cmSystemTools::KeyWOW64_32)) {
cmSystemTools::ConvertToUnixSlashes(vscmd);
@@ -195,11 +204,14 @@ const char* cmGlobalVisualStudio7Generator::ExternalProjectType(
}
return "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942";
}
-void cmGlobalVisualStudio7Generator::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<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalVisualStudio7Generator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& /*projectDir*/,
+ std::vector<std::string> const& targetNames, const std::string& config,
+ bool /*fast*/, int /*jobs*/, bool /*verbose*/,
+ std::vector<std::string> const& makeOptions)
{
// Select the caller- or user-preferred make program, else devenv.
std::string makeProgramSelected =
@@ -214,38 +226,43 @@ void cmGlobalVisualStudio7Generator::GenerateBuildCommand(
makeProgramSelected = this->GetDevEnvCommand();
}
- makeCommand.push_back(makeProgramSelected);
+ // Workaround to convince VCExpress.exe to produce output.
+ const bool requiresOutputForward =
+ (makeProgramLower.find("vcexpress") != std::string::npos);
+ std::vector<GeneratedMakeCommand> makeCommands;
- makeCommand.push_back(std::string(projectName) + ".sln");
- std::string realTarget = targetName;
- bool clean = false;
- if (realTarget == "clean") {
- clean = true;
- realTarget = "ALL_BUILD";
- }
- if (clean) {
- makeCommand.push_back("/clean");
- } else {
- makeCommand.push_back("/build");
+ std::vector<std::string> realTargetNames = targetNames;
+ if (targetNames.empty() ||
+ ((targetNames.size() == 1) && targetNames.front().empty())) {
+ realTargetNames = { "ALL_BUILD" };
}
-
- if (!config.empty()) {
- makeCommand.push_back(config);
- } else {
- makeCommand.push_back("Debug");
- }
- makeCommand.push_back("/project");
-
- if (!realTarget.empty()) {
- makeCommand.push_back(realTarget);
- } else {
- makeCommand.push_back("ALL_BUILD");
- }
- makeCommand.insert(makeCommand.end(), makeOptions.begin(),
- makeOptions.end());
+ for (const auto& tname : realTargetNames) {
+ std::string realTarget;
+ if (!tname.empty()) {
+ realTarget = tname;
+ } else {
+ continue;
+ }
+ bool clean = false;
+ if (realTarget == "clean") {
+ clean = true;
+ realTarget = "ALL_BUILD";
+ }
+ GeneratedMakeCommand makeCommand;
+ makeCommand.RequiresOutputForward = requiresOutputForward;
+ makeCommand.Add(makeProgramSelected);
+ makeCommand.Add(projectName + ".sln");
+ makeCommand.Add((clean ? "/clean" : "/build"));
+ makeCommand.Add((config.empty() ? "Debug" : config));
+ makeCommand.Add("/project");
+ makeCommand.Add(realTarget);
+ makeCommand.Add(makeOptions.begin(), makeOptions.end());
+ makeCommands.emplace_back(std::move(makeCommand));
+ }
+ return makeCommands;
}
-///! Create a local generator appropriate to this Global Generator
+//! Create a local generator appropriate to this Global Generator
cmLocalGenerator* cmGlobalVisualStudio7Generator::CreateLocalGenerator(
cmMakefile* mf)
{
@@ -254,13 +271,14 @@ cmLocalGenerator* cmGlobalVisualStudio7Generator::CreateLocalGenerator(
return lg;
}
-std::string const& cmGlobalVisualStudio7Generator::GetPlatformName() const
+#if !defined(CMAKE_BOOTSTRAP)
+Json::Value cmGlobalVisualStudio7Generator::GetJson() const
{
- if (!this->GeneratorPlatform.empty()) {
- return this->GeneratorPlatform;
- }
- return this->DefaultPlatformName;
+ Json::Value generator = this->cmGlobalVisualStudioGenerator::GetJson();
+ generator["platform"] = this->GetPlatformName();
+ return generator;
}
+#endif
bool cmGlobalVisualStudio7Generator::SetSystemName(std::string const& s,
cmMakefile* mf)
@@ -270,18 +288,6 @@ bool cmGlobalVisualStudio7Generator::SetSystemName(std::string const& s,
return this->cmGlobalVisualStudioGenerator::SetSystemName(s, mf);
}
-bool cmGlobalVisualStudio7Generator::SetGeneratorPlatform(std::string const& p,
- cmMakefile* mf)
-{
- if (this->GetPlatformName() == "x64") {
- mf->AddDefinition("CMAKE_FORCE_WIN64", "TRUE");
- } else if (this->GetPlatformName() == "Itanium") {
- mf->AddDefinition("CMAKE_FORCE_IA64", "TRUE");
- }
- mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName().c_str());
- return this->cmGlobalVisualStudioGenerator::SetGeneratorPlatform(p, mf);
-}
-
void cmGlobalVisualStudio7Generator::Generate()
{
// first do the superclass method
@@ -291,21 +297,10 @@ void cmGlobalVisualStudio7Generator::Generate()
this->OutputSLNFile();
// If any solution or project files changed during the generation,
// tell Visual Studio to reload them...
- if (!cmSystemTools::GetErrorOccuredFlag()) {
- this->CallVisualStudioMacro(MacroReload);
- }
-
- if (this->Version == VS8 && !this->CMakeInstance->GetIsInTryCompile()) {
- const char* cmakeWarnVS8 =
- this->CMakeInstance->GetState()->GetCacheEntryValue("CMAKE_WARN_VS8");
- if (!cmakeWarnVS8 || !cmSystemTools::IsOff(cmakeWarnVS8)) {
- this->CMakeInstance->IssueMessage(
- cmake::WARNING,
- "The \"Visual Studio 8 2005\" generator is deprecated "
- "and will be removed in a future version of CMake."
- "\n"
- "Add CMAKE_WARN_VS8=OFF to the cache to disable this warning.");
- }
+ if (!cmSystemTools::GetErrorOccuredFlag() &&
+ !this->LocalGenerators.empty()) {
+ this->CallVisualStudioMacro(MacroReload,
+ GetSLNFile(this->LocalGenerators[0]));
}
}
@@ -316,10 +311,7 @@ void cmGlobalVisualStudio7Generator::OutputSLNFile(
return;
}
this->CurrentProject = root->GetProjectName();
- std::string fname = root->GetCurrentBinaryDirectory();
- fname += "/";
- fname += root->GetProjectName();
- fname += ".sln";
+ std::string fname = GetSLNFile(root);
cmGeneratedFileStream fout(fname.c_str());
fout.SetCopyIfDifferent(true);
if (!fout) {
@@ -334,9 +326,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 +337,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 +367,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;
}
@@ -401,9 +388,9 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
if (vcprojName) {
cmLocalGenerator* lg = target->GetLocalGenerator();
std::string dir = lg->GetCurrentBinaryDirectory();
- dir = root->ConvertToRelativePath(rootBinaryDir, dir.c_str());
+ dir = root->MaybeConvertToRelativePath(rootBinaryDir, dir.c_str());
if (dir == ".") {
- dir = ""; // msbuild cannot handle ".\" prefix
+ dir.clear(); // msbuild cannot handle ".\" prefix
}
this->WriteProject(fout, vcprojName, dir.c_str(), target);
written = true;
@@ -415,24 +402,23 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
if (written && this->UseFolderProperty()) {
const std::string targetFolder = target->GetEffectiveFolderName();
if (!targetFolder.empty()) {
- std::vector<cmsys::String> tokens =
+ std::vector<std::string> tokens =
cmSystemTools::SplitString(targetFolder, '/', false);
- std::string cumulativePath = "";
+ std::string cumulativePath;
- for (std::vector<cmsys::String>::iterator iter = tokens.begin();
- iter != tokens.end(); ++iter) {
- if (!iter->size()) {
+ for (std::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 +433,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;
}
@@ -464,18 +448,15 @@ void cmGlobalVisualStudio7Generator::WriteTargetDepends(
void cmGlobalVisualStudio7Generator::WriteFolders(std::ostream& fout)
{
- const char* prefix = "CMAKE_FOLDER_GUID_";
- const std::string::size_type skip_prefix = strlen(prefix);
+ cm::string_view const prefix = "CMAKE_FOLDER_GUID_";
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)) {
- fullName = fullName.substr(skip_prefix);
+ if (cmHasPrefix(fullName, prefix)) {
+ fullName = fullName.substr(prefix.size());
}
std::string nameOnly = cmSystemTools::GetFilenameName(fullName);
@@ -487,16 +468,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 +503,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";
@@ -548,18 +525,15 @@ void cmGlobalVisualStudio7Generator::WriteSLNGlobalSections(
extensibilityAddInsOverridden = true;
}
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('=');
+ std::vector<std::string> keyValuePairs =
+ cmExpandedList(root->GetMakefile()->GetProperty(it));
+ 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));
+ cmTrimWhitespace(itPair.substr(0, posEqual));
const std::string value =
- cmSystemTools::TrimWhitespace(itPair->substr(posEqual + 1));
+ cmTrimWhitespace(itPair.substr(posEqual + 1));
fout << "\t\t" << key << " = " << value << "\n";
if (key == "SolutionGuid") {
addGuid = false;
@@ -594,12 +568,10 @@ std::string cmGlobalVisualStudio7Generator::WriteUtilityDepend(
{
std::vector<std::string> configs;
target->Target->GetMakefile()->GetConfigurations(configs);
- std::string pname = target->GetName();
- pname += "_UTILITY";
- std::string fname = target->GetLocalGenerator()->GetCurrentBinaryDirectory();
- fname += "/";
- fname += pname;
- fname += ".vcproj";
+ std::string pname = cmStrCat(target->GetName(), "_UTILITY");
+ std::string fname =
+ cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/',
+ pname, ".vcproj");
cmGeneratedFileStream fout(fname.c_str());
fout.SetCopyIfDifferent(true);
std::string guid = this->GetGUID(pname.c_str());
@@ -618,14 +590,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"
@@ -653,13 +624,12 @@ std::string cmGlobalVisualStudio7Generator::GetGUID(std::string const& name)
{
std::string const& guidStoreName = name + "_GUID_CMAKE";
if (const char* storedGUID =
- this->CMakeInstance->GetCacheDefinition(guidStoreName.c_str())) {
+ this->CMakeInstance->GetCacheDefinition(guidStoreName)) {
return std::string(storedGUID);
}
// Compute a GUID that is deterministic but unique to the build tree.
- std::string input = this->CMakeInstance->GetState()->GetBinaryDirectory();
- input += "|";
- input += name;
+ std::string input =
+ cmStrCat(this->CMakeInstance->GetState()->GetBinaryDirectory(), '|', name);
cmUuid uuidGenerator;
@@ -696,23 +666,18 @@ 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;
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge =
- ge.Parse(propertyValue);
- if (cmSystemTools::IsOn(
- cge->Evaluate(target->GetLocalGenerator(), *i))) {
- activeConfigs.insert(*i);
+ if (cmIsOn(cmGeneratorExpression::Evaluate(
+ propertyValue, target->GetLocalGenerator(), i))) {
+ activeConfigs.insert(i);
}
}
}
@@ -724,12 +689,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());
- if (cmSystemTools::IsOff(propertyValue)) {
- activeConfigs.insert(*i);
+ target->GetFeature("EXCLUDE_FROM_DEFAULT_BUILD", i);
+ if (cmIsOff(propertyValue)) {
+ activeConfigs.insert(i);
}
}
return activeConfigs;
@@ -738,9 +702,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 32a8d6056..7a9fcefa2 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -3,9 +3,8 @@
#ifndef cmGlobalVisualStudio7Generator_h
#define cmGlobalVisualStudio7Generator_h
-#include "cmGlobalVisualStudioGenerator.h"
-
#include "cmGlobalGeneratorFactory.h"
+#include "cmGlobalVisualStudioGenerator.h"
class cmTarget;
struct cmIDEFlagTable;
@@ -18,19 +17,16 @@ struct cmIDEFlagTable;
class cmGlobalVisualStudio7Generator : public cmGlobalVisualStudioGenerator
{
public:
- cmGlobalVisualStudio7Generator(cmake* cm,
- const std::string& platformName = "");
~cmGlobalVisualStudio7Generator();
- ///! Get the name for the platform.
- std::string const& GetPlatformName() const;
+ //! Create a local generator appropriate to this Global Generator
+ cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
- ///! Create a local generator appropriate to this Global Generator
- virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf);
-
- virtual bool SetSystemName(std::string const& s, cmMakefile* mf);
+#if !defined(CMAKE_BOOTSTRAP)
+ Json::Value GetJson() const override;
+#endif
- virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf);
+ bool SetSystemName(std::string const& s, cmMakefile* mf) override;
/**
* Utilized by the generator factory to determine if this generator
@@ -48,36 +44,36 @@ 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>());
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
/**
* Generate the DSW workspace file.
*/
virtual void OutputSLNFile();
- ///! Lookup a stored GUID or compute one deterministically.
+ //! Lookup a stored GUID or compute one deterministically.
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
+ //! What is the configurations directory variable called?
+ const char* GetCMakeCFGIntDir() const override
{
return "$(ConfigurationName)";
}
@@ -89,9 +85,9 @@ public:
return false;
}
- const char* GetIntelProjectVersion();
+ const std::string& GetIntelProjectVersion();
- bool FindMakeProgram(cmMakefile* mf) CM_OVERRIDE;
+ bool FindMakeProgram(cmMakefile* mf) override;
/** Is the Microsoft Assembler enabled? */
bool IsMasmEnabled() const { return this->MasmEnabled; }
@@ -103,8 +99,10 @@ public:
cmIDEFlagTable const* ExtraFlagTable;
protected:
- virtual void Generate();
- virtual const char* GetIDEVersion() = 0;
+ cmGlobalVisualStudio7Generator(cmake* cm,
+ std::string const& platformInGeneratorName);
+
+ void Generate() override;
std::string const& GetDevEnvCommand();
virtual std::string FindDevEnvCommand();
@@ -128,8 +126,7 @@ protected:
virtual void WriteSLNGlobalSections(std::ostream& fout,
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,
@@ -142,7 +139,7 @@ protected:
virtual void WriteExternalProject(
std::ostream& fout, const std::string& name, const char* path,
- const char* typeGuid, const std::set<std::string>& dependencies) = 0;
+ const char* typeGuid, const std::set<BT<std::string>>& dependencies) = 0;
std::string ConvertToSolutionPath(const char* path);
@@ -156,21 +153,19 @@ protected:
virtual void WriteFolders(std::ostream& fout);
virtual void WriteFoldersContent(std::ostream& fout);
- std::map<std::string, std::set<std::string> > VisualStudioFolders;
+ std::map<std::string, std::set<std::string>> VisualStudioFolders;
// Set during OutputSLNFile with the name of the current project.
// There is one SLN file per project.
std::string CurrentProject;
- std::string GeneratorPlatform;
- std::string DefaultPlatformName;
bool MasmEnabled;
bool NasmEnabled;
private:
- char* IntelProjectVersion;
+ std::string 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 f06a8a1c6..8e6125b8a 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -2,108 +2,36 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudio8Generator.h"
+#include "cmCustomCommand.h"
+#include "cmCustomCommandLines.h"
#include "cmDocumentationEntry.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmLocalVisualStudio7Generator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmSourceFile.h"
#include "cmVisualStudioWCEPlatformParser.h"
#include "cmake.h"
-static const char vs8generatorName[] = "Visual Studio 8 2005";
-
-class cmGlobalVisualStudio8Generator::Factory : public cmGlobalGeneratorFactory
-{
-public:
- cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
- cmake* cm) const CM_OVERRIDE
- {
- if (strncmp(name.c_str(), vs8generatorName,
- sizeof(vs8generatorName) - 1) != 0) {
- return 0;
- }
-
- const char* p = name.c_str() + sizeof(vs8generatorName) - 1;
- if (p[0] == '\0') {
- return new cmGlobalVisualStudio8Generator(cm, name, "");
- }
-
- if (p[0] != ' ') {
- return 0;
- }
-
- ++p;
-
- if (!strcmp(p, "Win64")) {
- return new cmGlobalVisualStudio8Generator(cm, name, "x64");
- }
-
- cmVisualStudioWCEPlatformParser parser(p);
- parser.ParseVersion("8.0");
- if (!parser.Found()) {
- return 0;
- }
-
- cmGlobalVisualStudio8Generator* ret =
- new cmGlobalVisualStudio8Generator(cm, name, p);
- ret->WindowsCEVersion = parser.GetOSVersion();
- return ret;
- }
-
- void GetDocumentation(cmDocumentationEntry& entry) const CM_OVERRIDE
- {
- entry.Name = std::string(vs8generatorName) + " [arch]";
- entry.Brief = "Deprecated. Generates Visual Studio 2005 project files. "
- "Optional [arch] can be \"Win64\".";
- }
-
- void GetGenerators(std::vector<std::string>& names) const CM_OVERRIDE
- {
- names.push_back(vs8generatorName);
- names.push_back(vs8generatorName + std::string(" Win64"));
- cmVisualStudioWCEPlatformParser parser;
- 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);
- }
- }
-
- bool SupportsToolset() const CM_OVERRIDE { return false; }
- bool SupportsPlatform() const CM_OVERRIDE { return true; }
-};
-
-cmGlobalGeneratorFactory* cmGlobalVisualStudio8Generator::NewFactory()
-{
- return new Factory;
-}
-
cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator(
- cmake* cm, const std::string& name, const std::string& platformName)
- : cmGlobalVisualStudio71Generator(cm, platformName)
+ cmake* cm, const std::string& name,
+ std::string const& platformInGeneratorName)
+ : cmGlobalVisualStudio71Generator(cm, platformInGeneratorName)
{
this->ProjectConfigurationSectionName = "ProjectConfigurationPlatforms";
this->Name = name;
this->ExtraFlagTable = this->GetExtraFlagTableVS8();
- this->Version = VS8;
- std::string vc8Express;
- this->ExpressEdition = cmSystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\8.0\\Setup\\VC;"
- "ProductDir",
- vc8Express, cmSystemTools::KeyWOW64_32);
}
std::string cmGlobalVisualStudio8Generator::FindDevEnvCommand()
{
// First look for VCExpress.
std::string vsxcmd;
- std::string vsxkey = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\";
- vsxkey += this->GetIDEVersion();
- vsxkey += ";InstallDir";
+ std::string vsxkey =
+ cmStrCat("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\",
+ this->GetIDEVersion(), ";InstallDir");
if (cmSystemTools::ReadRegistryValue(vsxkey.c_str(), vsxcmd,
cmSystemTools::KeyWOW64_32)) {
cmSystemTools::ConvertToUnixSlashes(vsxcmd);
@@ -117,9 +45,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;
}
}
@@ -130,15 +57,14 @@ void cmGlobalVisualStudio8Generator::EnableLanguage(
void cmGlobalVisualStudio8Generator::AddPlatformDefinitions(cmMakefile* mf)
{
if (this->TargetsWindowsCE()) {
- mf->AddDefinition("CMAKE_VS_WINCE_VERSION",
- this->WindowsCEVersion.c_str());
+ mf->AddDefinition("CMAKE_VS_WINCE_VERSION", this->WindowsCEVersion);
}
}
bool cmGlobalVisualStudio8Generator::SetGeneratorPlatform(std::string const& p,
cmMakefile* mf)
{
- if (this->DefaultPlatformName == "Win32") {
+ if (!this->PlatformInGeneratorName) {
this->GeneratorPlatform = p;
return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform("", mf);
} else {
@@ -146,13 +72,6 @@ bool cmGlobalVisualStudio8Generator::SetGeneratorPlatform(std::string const& p,
}
}
-// ouput standard header for dsw file
-void cmGlobalVisualStudio8Generator::WriteSLNHeader(std::ostream& fout)
-{
- fout << "Microsoft Visual Studio Solution File, Format Version 9.00\n";
- fout << "# Visual Studio 2005\n";
-}
-
std::string cmGlobalVisualStudio8Generator::GetGenerateStampList()
{
return "generate.stamp.list";
@@ -163,71 +82,32 @@ void cmGlobalVisualStudio8Generator::Configure()
this->cmGlobalVisualStudio7Generator::Configure();
}
-bool cmGlobalVisualStudio8Generator::UseFolderProperty()
+bool cmGlobalVisualStudio8Generator::UseFolderProperty() const
{
return IsExpressEdition() ? false : cmGlobalGenerator::UseFolderProperty();
}
-std::string cmGlobalVisualStudio8Generator::GetUserMacrosDirectory()
-{
- // Some VS8 sp0 versions cannot run macros.
- // See http://support.microsoft.com/kb/928209
- const char* vc8sp1Registry =
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0\\"
- "InstalledProducts\\KB926601;";
- const char* vc8exSP1Registry =
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0\\"
- "InstalledProducts\\KB926748;";
- std::string vc8sp1;
- if (!cmSystemTools::ReadRegistryValue(vc8sp1Registry, vc8sp1) &&
- !cmSystemTools::ReadRegistryValue(vc8exSP1Registry, vc8sp1)) {
- return "";
- }
-
- std::string base;
- std::string path;
-
- // base begins with the VisualStudioProjectsLocation reg value...
- if (cmSystemTools::ReadRegistryValue(
- "HKEY_CURRENT_USER\\Software\\Microsoft\\VisualStudio\\8.0;"
- "VisualStudioProjectsLocation",
- base)) {
- cmSystemTools::ConvertToUnixSlashes(base);
-
- // 8.0 macros folder:
- path = base + "/VSMacros80";
- }
-
- // path is (correctly) still empty if we did not read the base value from
- // the Registry value
- return path;
-}
-
-std::string cmGlobalVisualStudio8Generator::GetUserMacrosRegKeyBase()
-{
- return "Software\\Microsoft\\VisualStudio\\8.0\\vsmacros";
-}
-
bool cmGlobalVisualStudio8Generator::AddCheckTarget()
{
// Add a special target on which all other targets depend that
// checks the build system and optionally re-runs CMake.
- const char* no_working_directory = 0;
- std::vector<std::string> no_depends;
+ // Skip the target if no regeneration is to be done.
+ if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ return false;
+ }
+
std::vector<cmLocalGenerator*> const& generators = this->LocalGenerators;
cmLocalVisualStudio7Generator* lg =
static_cast<cmLocalVisualStudio7Generator*>(generators[0]);
cmMakefile* mf = lg->GetMakefile();
- // Skip the target if no regeneration is to be done.
- if (mf->IsOn("CMAKE_SUPPRESS_REGENERATION")) {
- return false;
- }
-
- cmCustomCommandLines noCommandLines;
- cmTarget* tgt =
- mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false,
- no_working_directory, no_depends, noCommandLines);
+ const char* no_working_directory = nullptr;
+ std::vector<std::string> no_byproducts;
+ std::vector<std::string> no_depends;
+ cmCustomCommandLines no_commands;
+ cmTarget* tgt = mf->AddUtilityCommand(
+ CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmCommandOrigin::Generator, false,
+ no_working_directory, no_byproducts, no_depends, no_commands);
cmGeneratorTarget* gt = new cmGeneratorTarget(tgt, lg);
lg->AddGeneratorTarget(gt);
@@ -240,22 +120,17 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
// Create a list of all stamp files for this project.
std::vector<std::string> stamps;
- std::string stampList = cmake::GetCMakeFilesDirectoryPostSlash();
- stampList += cmGlobalVisualStudio8Generator::GetGenerateStampList();
+ std::string stampList = cmStrCat(
+ "CMakeFiles/", cmGlobalVisualStudio8Generator::GetGenerateStampList());
{
std::string stampListFile =
- generators[0]->GetMakefile()->GetCurrentBinaryDirectory();
- stampListFile += "/";
- stampListFile += stampList;
+ cmStrCat(generators[0]->GetMakefile()->GetCurrentBinaryDirectory(), '/',
+ 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();
- stampFile += "/";
- stampFile += cmake::GetCMakeFilesDirectoryPostSlash();
- stampFile += "generate.stamp";
+ for (cmLocalGenerator const* gi : generators) {
+ stampFile = cmStrCat(gi->GetMakefile()->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/generate.stamp");
fout << stampFile << "\n";
stamps.push_back(stampFile);
}
@@ -266,11 +141,29 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
// Collect the input files used to generate all targets in this
// project.
std::vector<std::string> listFiles;
- for (unsigned int j = 0; j < generators.size(); ++j) {
- cmMakefile* lmf = generators[j]->GetMakefile();
- listFiles.insert(listFiles.end(), lmf->GetListFiles().begin(),
- lmf->GetListFiles().end());
+ for (cmLocalGenerator* gen : generators) {
+ cmAppend(listFiles, gen->GetMakefile()->GetListFiles());
+ }
+
+ // Add a custom prebuild target to run the VerifyGlobs script.
+ cmake* cm = this->GetCMakeInstance();
+ if (cm->DoWriteGlobVerifyTarget()) {
+ cmCustomCommandLines verifyCommandLines = cmMakeSingleCommandLine(
+ { cmSystemTools::GetCMakeCommand(), "-P", cm->GetGlobVerifyScript() });
+ std::vector<std::string> byproducts;
+ byproducts.push_back(cm->GetGlobVerifyStamp());
+
+ mf->AddCustomCommandToTarget(
+ CMAKE_CHECK_BUILD_SYSTEM_TARGET, byproducts, no_depends,
+ verifyCommandLines, cmCustomCommandType::PRE_BUILD,
+ "Checking File Globs", no_working_directory, false);
+
+ // Ensure ZERO_CHECK always runs in Visual Studio using MSBuild,
+ // otherwise the prebuild command will not be run.
+ tgt->SetProperty("VS_GLOBAL_DisableFastUpToDateCheck", "true");
+ listFiles.push_back(cm->GetGlobVerifyStamp());
}
+
// Sort the list of input files and remove duplicates.
std::sort(listFiles.begin(), listFiles.end(), std::less<std::string>());
std::vector<std::string>::iterator new_end =
@@ -278,37 +171,27 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
listFiles.erase(new_end, listFiles.end());
// Create a rule to re-run CMake.
- std::string stampName = cmake::GetCMakeFilesDirectoryPostSlash();
- stampName += "generate.stamp";
- cmCustomCommandLine commandLine;
- commandLine.push_back(cmSystemTools::GetCMakeCommand());
- std::string argH = "-H";
- argH += lg->GetSourceDirectory();
- commandLine.push_back(argH);
- std::string argB = "-B";
- argB += lg->GetBinaryDirectory();
- commandLine.push_back(argB);
- commandLine.push_back("--check-stamp-list");
- commandLine.push_back(stampList.c_str());
- commandLine.push_back("--vs-solution-file");
- std::string const sln = std::string(lg->GetBinaryDirectory()) + "/" +
- lg->GetProjectName() + ".sln";
- commandLine.push_back(sln);
- cmCustomCommandLines commandLines;
- commandLines.push_back(commandLine);
+ std::string argS = cmStrCat("-S", lg->GetSourceDirectory());
+ std::string argB = cmStrCat("-B", lg->GetBinaryDirectory());
+ std::string const sln =
+ lg->GetBinaryDirectory() + "/" + lg->GetProjectName() + ".sln";
+ cmCustomCommandLines commandLines = cmMakeSingleCommandLine(
+ { cmSystemTools::GetCMakeCommand(), argS, argB, "--check-stamp-list",
+ stampList, "--vs-solution-file", sln });
// Add the rule. Note that we cannot use the CMakeLists.txt
// file as the main dependency because it would get
// overwritten by the CreateVCProjBuildRule.
// (this could be avoided with per-target source files)
- std::string no_main_dependency = "";
- std::vector<std::string> no_byproducts;
+ std::string no_main_dependency;
+ cmImplicitDependsList no_implicit_depends;
if (cmSourceFile* file = mf->AddCustomCommandToOutput(
- stamps, no_byproducts, listFiles, no_main_dependency, commandLines,
- "Checking Build System", no_working_directory, true, false)) {
- gt->AddSource(file->GetFullPath());
+ stamps, no_byproducts, listFiles, no_main_dependency,
+ no_implicit_depends, commandLines, "Checking Build System",
+ no_working_directory, true, false)) {
+ gt->AddSource(file->ResolveFullPath());
} else {
- cmSystemTools::Error("Error adding rule for ", stamps[0].c_str());
+ cmSystemTools::Error("Error adding rule for " + stamps[0]);
}
}
@@ -320,13 +203,12 @@ void cmGlobalVisualStudio8Generator::AddExtraIDETargets()
cmGlobalVisualStudio7Generator::AddExtraIDETargets();
if (this->AddCheckTarget()) {
for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
- std::vector<cmGeneratorTarget*> tgts =
+ const std::vector<cmGeneratorTarget*>& tgts =
this->LocalGenerators[i]->GetGeneratorTargets();
// All targets depend on the build-system check target.
- for (std::vector<cmGeneratorTarget*>::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 +219,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 +233,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::ExpandListArgument(m, mapConfig);
+ cmSystemTools::UpperCase(i))) {
+ cmExpandList(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()
+ if (this->NeedsDeploy(target, dstConfig)) {
+ fout << "\t\t{" << guid << "}." << i << "|" << this->GetPlatformName()
<< ".Deploy.0 = " << dstConfig << "|"
<< (!platformMapping.empty() ? platformMapping
: this->GetPlatformName())
@@ -390,11 +270,30 @@ void cmGlobalVisualStudio8Generator::WriteProjectConfigurations(
}
bool cmGlobalVisualStudio8Generator::NeedsDeploy(
- cmStateEnums::TargetType type) const
+ cmGeneratorTarget const& target, const char* config) const
+{
+ cmStateEnums::TargetType type = target.GetType();
+ bool noDeploy = DeployInhibited(target, config);
+ return !noDeploy &&
+ (type == cmStateEnums::EXECUTABLE ||
+ type == cmStateEnums::SHARED_LIBRARY) &&
+ this->TargetSystemSupportsDeployment();
+}
+
+bool cmGlobalVisualStudio8Generator::DeployInhibited(
+ cmGeneratorTarget const& target, const char* config) const
+{
+ bool rVal = false;
+ if (const char* prop = target.GetProperty("VS_NO_SOLUTION_DEPLOY")) {
+ rVal = cmIsOn(
+ cmGeneratorExpression::Evaluate(prop, target.LocalGenerator, config));
+ }
+ return rVal;
+}
+
+bool cmGlobalVisualStudio8Generator::TargetSystemSupportsDeployment() const
{
- bool needsDeploy =
- (type == cmStateEnums::EXECUTABLE || type == cmStateEnums::SHARED_LIBRARY);
- return this->TargetsWindowsCE() && needsDeploy;
+ return this->TargetsWindowsCE();
}
bool cmGlobalVisualStudio8Generator::ComputeTargetDepends()
@@ -410,12 +309,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 +322,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 (BT<std::string> const& ui : target->GetUtilities()) {
if (cmGeneratorTarget* depTarget =
- target->GetLocalGenerator()->FindGeneratorTargetToUse(ui->c_str())) {
+ target->GetLocalGenerator()->FindGeneratorTargetToUse(ui.Value)) {
if (depTarget->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
depTarget->GetProperty("EXTERNAL_MSPROJECT")) {
// This utility dependency names an external .vcproj target.
@@ -473,7 +369,7 @@ static cmVS7FlagTable cmVS8ExtraFlagTable[] = {
{ "TreatWChar_tAsBuiltInType", "Zc:wchar_t-",
"wchar_t is not a built-in type", "false", 0 },
- { 0, 0, 0, 0, 0 }
+ { "", "", "", "", 0 }
};
cmIDEFlagTable const* cmGlobalVisualStudio8Generator::GetExtraFlagTableVS8()
{
diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h
index 4723b83ba..352bc3c2b 100644
--- a/Source/cmGlobalVisualStudio8Generator.h
+++ b/Source/cmGlobalVisualStudio8Generator.h
@@ -13,89 +13,73 @@
class cmGlobalVisualStudio8Generator : public cmGlobalVisualStudio71Generator
{
public:
- cmGlobalVisualStudio8Generator(cmake* cm, const std::string& name,
- const std::string& platformName);
- static cmGlobalGeneratorFactory* NewFactory();
-
- ///! Get the name for the generator.
- virtual std::string GetName() const { return this->Name; }
+ //! Get the name for the generator.
+ 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();
-
- /**
- * 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();
-
- /**
- * What is the reg key path to "vsmacros" for this version of Visual
- * Studio?
- */
- virtual std::string GetUserMacrosRegKeyBase();
+ void Configure() 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();
}
- /** Is the installed VS an Express edition? */
- bool IsExpressEdition() const { return this->ExpressEdition; }
-
protected:
- virtual void AddExtraIDETargets();
- virtual const char* GetIDEVersion() { return "8.0"; }
+ cmGlobalVisualStudio8Generator(cmake* cm, const std::string& name,
+ std::string const& platformInGeneratorName);
+
+ void AddExtraIDETargets() override;
- virtual std::string FindDevEnvCommand();
+ std::string FindDevEnvCommand() override;
- virtual bool VSLinksDependencies() const { return false; }
+ bool VSLinksDependencies() const override { return false; }
bool AddCheckTarget();
/** Return true if the configuration needs to be deployed */
- virtual bool NeedsDeploy(cmStateEnums::TargetType type) const;
+ virtual bool NeedsDeploy(cmGeneratorTarget const& target,
+ const char* config) const;
+
+ /** Returns true if deployment has been disabled in cmake file. */
+ bool DeployInhibited(cmGeneratorTarget const& target,
+ const char* config) const;
+
+ /** Returns true if the target system support debugging deployment. */
+ virtual bool TargetSystemSupportsDeployment() 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 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();
+ bool UseFolderProperty() const override;
std::string Name;
std::string WindowsCEVersion;
- bool ExpressEdition;
-
-private:
- class Factory;
- friend class Factory;
};
#endif
diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx
index b1634e2ca..6e61d2681 100644
--- a/Source/cmGlobalVisualStudio9Generator.cxx
+++ b/Source/cmGlobalVisualStudio9Generator.cxx
@@ -5,8 +5,8 @@
#include "cmDocumentationEntry.h"
#include "cmLocalVisualStudio7Generator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmVisualStudioWCEPlatformParser.h"
-#include "cmake.h"
static const char vs9generatorName[] = "Visual Studio 9 2008";
@@ -14,7 +14,7 @@ class cmGlobalVisualStudio9Generator::Factory : public cmGlobalGeneratorFactory
{
public:
cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
- cmake* cm) const CM_OVERRIDE
+ cmake* cm) const override
{
if (strncmp(name.c_str(), vs9generatorName,
sizeof(vs9generatorName) - 1) != 0) {
@@ -52,31 +52,55 @@ public:
return ret;
}
- void GetDocumentation(cmDocumentationEntry& entry) const CM_OVERRIDE
+ void GetDocumentation(cmDocumentationEntry& entry) const override
{
entry.Name = std::string(vs9generatorName) + " [arch]";
entry.Brief = "Generates Visual Studio 2008 project files. "
"Optional [arch] can be \"Win64\" or \"IA64\".";
}
- void GetGenerators(std::vector<std::string>& names) const CM_OVERRIDE
+ std::vector<std::string> GetGeneratorNames() const override
{
+ std::vector<std::string> names;
names.push_back(vs9generatorName);
+ return names;
+ }
+
+ std::vector<std::string> GetGeneratorNamesWithPlatform() const override
+ {
+ std::vector<std::string> names;
names.push_back(vs9generatorName + std::string(" Win64"));
names.push_back(vs9generatorName + std::string(" IA64"));
cmVisualStudioWCEPlatformParser parser;
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);
}
+ return names;
}
- bool SupportsToolset() const CM_OVERRIDE { return false; }
- bool SupportsPlatform() const CM_OVERRIDE { return true; }
+ bool SupportsToolset() const override { return false; }
+ bool SupportsPlatform() const override { return true; }
+
+ std::vector<std::string> GetKnownPlatforms() const override
+ {
+ std::vector<std::string> platforms;
+ platforms.emplace_back("x64");
+ platforms.emplace_back("Win32");
+ platforms.emplace_back("Itanium");
+ cmVisualStudioWCEPlatformParser parser;
+ parser.ParseVersion("9.0");
+ const std::vector<std::string>& availablePlatforms =
+ parser.GetAvailablePlatforms();
+ for (std::string const& i : availablePlatforms) {
+ platforms.emplace_back(i);
+ }
+ return platforms;
+ }
+
+ std::string GetDefaultPlatformName() const override { return "Win32"; }
};
cmGlobalGeneratorFactory* cmGlobalVisualStudio9Generator::NewFactory()
@@ -85,8 +109,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio9Generator::NewFactory()
}
cmGlobalVisualStudio9Generator::cmGlobalVisualStudio9Generator(
- cmake* cm, const std::string& name, const std::string& platformName)
- : cmGlobalVisualStudio8Generator(cm, name, platformName)
+ cmake* cm, const std::string& name,
+ std::string const& platformInGeneratorName)
+ : cmGlobalVisualStudio8Generator(cm, name, platformInGeneratorName)
{
this->Version = VS9;
std::string vc9Express;
@@ -96,12 +121,6 @@ cmGlobalVisualStudio9Generator::cmGlobalVisualStudio9Generator(
vc9Express, cmSystemTools::KeyWOW64_32);
}
-void cmGlobalVisualStudio9Generator::WriteSLNHeader(std::ostream& fout)
-{
- fout << "Microsoft Visual Studio Solution File, Format Version 10.00\n";
- fout << "# Visual Studio 2008\n";
-}
-
std::string cmGlobalVisualStudio9Generator::GetUserMacrosDirectory()
{
std::string base;
diff --git a/Source/cmGlobalVisualStudio9Generator.h b/Source/cmGlobalVisualStudio9Generator.h
index fbc1f5d07..7bebfd65f 100644
--- a/Source/cmGlobalVisualStudio9Generator.h
+++ b/Source/cmGlobalVisualStudio9Generator.h
@@ -13,31 +13,25 @@
class cmGlobalVisualStudio9Generator : public cmGlobalVisualStudio8Generator
{
public:
- cmGlobalVisualStudio9Generator(cmake* cm, const std::string& name,
- const std::string& platformName);
static cmGlobalGeneratorFactory* NewFactory();
/**
- * Try to determine system information such as shared library
- * extension, pthreads, byte order etc.
- */
- virtual void WriteSLNHeader(std::ostream& fout);
-
- /**
* 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"; }
+ cmGlobalVisualStudio9Generator(cmake* cm, const std::string& name,
+ std::string const& platformInGeneratorName);
+
private:
class Factory;
friend class Factory;
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index bbff48eb6..ed0cba7dd 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -3,12 +3,21 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalVisualStudioGenerator.h"
-#include "cmsys/Encoding.hxx"
+#include <future>
#include <iostream>
+
+#include <cm/iterator>
+
#include <windows.h>
-#include "cmAlgorithms.h"
+#include <objbase.h>
+#include <shellapi.h>
+
+#include "cmsys/Encoding.hxx"
+
#include "cmCallVisualStudioMacro.h"
+#include "cmCustomCommand.h"
+#include "cmCustomCommandLines.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmLocalVisualStudioGenerator.h"
@@ -16,13 +25,22 @@
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmTarget.h"
+#include "cmake.h"
-cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator(cmake* cm)
+cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator(
+ cmake* cm, std::string const& platformInGeneratorName)
: cmGlobalGenerator(cm)
{
cm->GetState()->SetIsGeneratorMultiConfig(true);
cm->GetState()->SetWindowsShell(true);
cm->GetState()->SetWindowsVSIDE(true);
+
+ if (platformInGeneratorName.empty()) {
+ this->DefaultPlatformName = "Win32";
+ } else {
+ this->DefaultPlatformName = platformInGeneratorName;
+ this->PlatformInGeneratorName = true;
+ }
}
cmGlobalVisualStudioGenerator::~cmGlobalVisualStudioGenerator()
@@ -40,6 +58,119 @@ void cmGlobalVisualStudioGenerator::SetVersion(VSVersion v)
this->Version = v;
}
+void cmGlobalVisualStudioGenerator::EnableLanguage(
+ std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
+{
+ mf->AddDefinition("CMAKE_VS_PLATFORM_NAME_DEFAULT",
+ this->DefaultPlatformName);
+ this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
+}
+
+bool cmGlobalVisualStudioGenerator::SetGeneratorPlatform(std::string const& p,
+ cmMakefile* mf)
+{
+ if (this->GetPlatformName() == "x64") {
+ mf->AddDefinition("CMAKE_FORCE_WIN64", "TRUE");
+ } else if (this->GetPlatformName() == "Itanium") {
+ mf->AddDefinition("CMAKE_FORCE_IA64", "TRUE");
+ }
+ mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName());
+ return this->cmGlobalGenerator::SetGeneratorPlatform(p, mf);
+}
+
+std::string const& cmGlobalVisualStudioGenerator::GetPlatformName() const
+{
+ if (!this->GeneratorPlatform.empty()) {
+ return this->GeneratorPlatform;
+ }
+ return this->DefaultPlatformName;
+}
+
+const char* cmGlobalVisualStudioGenerator::GetIDEVersion() const
+{
+ switch (this->Version) {
+ case cmGlobalVisualStudioGenerator::VS9:
+ return "9.0";
+ case cmGlobalVisualStudioGenerator::VS10:
+ return "10.0";
+ case cmGlobalVisualStudioGenerator::VS11:
+ return "11.0";
+ case cmGlobalVisualStudioGenerator::VS12:
+ return "12.0";
+ case cmGlobalVisualStudioGenerator::VS14:
+ return "14.0";
+ case cmGlobalVisualStudioGenerator::VS15:
+ return "15.0";
+ case cmGlobalVisualStudioGenerator::VS16:
+ return "16.0";
+ }
+ return "";
+}
+
+void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout)
+{
+ char utf8bom[] = { char(0xEF), char(0xBB), char(0xBF) };
+ fout.write(utf8bom, 3);
+
+ switch (this->Version) {
+ case cmGlobalVisualStudioGenerator::VS9:
+ fout << "Microsoft Visual Studio Solution File, Format Version 10.00\n";
+ fout << "# Visual Studio 2008\n";
+ break;
+ case cmGlobalVisualStudioGenerator::VS10:
+ fout << "Microsoft Visual Studio Solution File, Format Version 11.00\n";
+ if (this->ExpressEdition) {
+ fout << "# Visual C++ Express 2010\n";
+ } else {
+ fout << "# Visual Studio 2010\n";
+ }
+ break;
+ case cmGlobalVisualStudioGenerator::VS11:
+ fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
+ if (this->ExpressEdition) {
+ fout << "# Visual Studio Express 2012 for Windows Desktop\n";
+ } else {
+ fout << "# Visual Studio 2012\n";
+ }
+ break;
+ case cmGlobalVisualStudioGenerator::VS12:
+ fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
+ if (this->ExpressEdition) {
+ fout << "# Visual Studio Express 2013 for Windows Desktop\n";
+ } else {
+ fout << "# Visual Studio 2013\n";
+ }
+ break;
+ case cmGlobalVisualStudioGenerator::VS14:
+ // Visual Studio 14 writes .sln format 12.00
+ fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
+ if (this->ExpressEdition) {
+ fout << "# Visual Studio Express 14 for Windows Desktop\n";
+ } else {
+ fout << "# Visual Studio 14\n";
+ }
+ break;
+ case cmGlobalVisualStudioGenerator::VS15:
+ // Visual Studio 15 writes .sln format 12.00
+ fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
+ if (this->ExpressEdition) {
+ fout << "# Visual Studio Express 15 for Windows Desktop\n";
+ } else {
+ fout << "# Visual Studio 15\n";
+ }
+ break;
+ case cmGlobalVisualStudioGenerator::VS16:
+ // Visual Studio 16 writes .sln format 12.00
+ fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
+ if (this->ExpressEdition) {
+ fout << "# Visual Studio Express 16 for Windows Desktop\n";
+ } else {
+ fout << "# Visual Studio 16\n";
+ }
+ break;
+ }
+}
+
std::string cmGlobalVisualStudioGenerator::GetRegistryBase()
{
return cmGlobalVisualStudioGenerator::GetRegistryBase(this->GetIDEVersion());
@@ -55,19 +186,19 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets()
{
// Add a special target that depends on ALL projects for easy build
// of one configuration only.
- const char* no_working_dir = 0;
+ const char* no_working_dir = nullptr;
+ std::vector<std::string> no_byproducts;
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", cmCommandOrigin::Generator, true, no_working_dir,
+ no_byproducts, no_depends, no_commands, false, "Build all projects");
cmGeneratorTarget* gt = new cmGeneratorTarget(allBuild, gen[0]);
gen[0]->AddGeneratorTarget(gt);
@@ -80,12 +211,8 @@ 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) {
- std::vector<cmGeneratorTarget*> targets = (*i)->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator t = targets.begin();
- t != targets.end(); ++t) {
- cmGeneratorTarget* tgt = *t;
+ for (cmLocalGenerator const* i : gen) {
+ for (cmGeneratorTarget* tgt : i->GetGeneratorTargets()) {
if (tgt->GetType() == cmStateEnums::GLOBAL_TARGET ||
tgt->IsImported()) {
continue;
@@ -101,22 +228,13 @@ 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(
cmGeneratorTarget* gt) const
{
- std::string dir = gt->LocalGenerator->GetCurrentBinaryDirectory();
- dir += "/";
+ std::string dir =
+ cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/');
std::string tgtDir = gt->LocalGenerator->GetTargetDirectory(gt);
if (!tgtDir.empty()) {
dir += tgtDir;
@@ -148,9 +266,9 @@ void cmGlobalVisualStudioGenerator::ConfigureCMakeVisualStudioMacros()
{
std::string dir = this->GetUserMacrosDirectory();
- if (dir != "") {
- std::string src = cmSystemTools::GetCMakeRoot();
- src += "/Templates/" CMAKE_VSMACROS_FILENAME;
+ if (!dir.empty()) {
+ std::string src = cmStrCat(cmSystemTools::GetCMakeRoot(),
+ "/Templates/" CMAKE_VSMACROS_FILENAME);
std::string dst = dir + "/CMakeMacros/" CMAKE_VSMACROS_FILENAME;
@@ -160,13 +278,12 @@ void cmGlobalVisualStudioGenerator::ConfigureCMakeVisualStudioMacros()
// purposes but newer versions distributed with CMake will replace
// older versions in user directories.
int res;
- if (!cmSystemTools::FileTimeCompare(src.c_str(), dst.c_str(), &res) ||
- res > 0) {
- if (!cmSystemTools::CopyFileAlways(src.c_str(), dst.c_str())) {
+ if (!cmSystemTools::FileTimeCompare(src, dst, &res) || res > 0) {
+ if (!cmSystemTools::CopyFileAlways(src, dst)) {
std::ostringstream oss;
oss << "Could not copy from: " << src << std::endl;
oss << " to: " << dst << std::endl;
- cmSystemTools::Message(oss.str().c_str(), "Warning");
+ cmSystemTools::Message(oss.str(), "Warning");
}
}
@@ -175,11 +292,10 @@ void cmGlobalVisualStudioGenerator::ConfigureCMakeVisualStudioMacros()
}
void cmGlobalVisualStudioGenerator::CallVisualStudioMacro(
- MacroName m, const char* vsSolutionFile)
+ MacroName m, const std::string& vsSolutionFile)
{
// If any solution or project files changed during the generation,
// tell Visual Studio to reload them...
- cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
std::string dir = this->GetUserMacrosDirectory();
// Only really try to call the macro if:
@@ -188,44 +304,24 @@ void cmGlobalVisualStudioGenerator::CallVisualStudioMacro(
// - the CMake vsmacros file is registered
// - there were .sln/.vcproj files changed during generation
//
- if (dir != "") {
+ if (!dir.empty()) {
std::string macrosFile = dir + "/CMakeMacros/" CMAKE_VSMACROS_FILENAME;
std::string nextSubkeyName;
if (cmSystemTools::FileExists(macrosFile.c_str()) &&
IsVisualStudioMacrosFileRegistered(
macrosFile, this->GetUserMacrosRegKeyBase(), nextSubkeyName)) {
- std::string topLevelSlnName;
- if (vsSolutionFile) {
- topLevelSlnName = vsSolutionFile;
- } else {
- topLevelSlnName = mf->GetCurrentBinaryDirectory();
- topLevelSlnName += "/";
- topLevelSlnName += this->LocalGenerators[0]->GetProjectName();
- topLevelSlnName += ".sln";
- }
-
if (m == MacroReload) {
std::vector<std::string> filenames;
this->GetFilesReplacedDuringGenerate(filenames);
if (!filenames.empty()) {
- // Convert vector to semi-colon delimited string of filenames:
- std::string projects;
- std::vector<std::string>::iterator it = filenames.begin();
- if (it != filenames.end()) {
- projects = *it;
- ++it;
- }
- for (; it != filenames.end(); ++it) {
- projects += ";";
- projects += *it;
- }
+ std::string projects = cmJoin(filenames, ";");
cmCallVisualStudioMacro::CallMacro(
- topLevelSlnName, CMAKE_VSMACROS_RELOAD_MACRONAME, projects,
+ vsSolutionFile, CMAKE_VSMACROS_RELOAD_MACRONAME, projects,
this->GetCMakeInstance()->GetDebugOutput());
}
} else if (m == MacroStop) {
cmCallVisualStudioMacro::CallMacro(
- topLevelSlnName, CMAKE_VSMACROS_STOP_MACRONAME, "",
+ vsSolutionFile, CMAKE_VSMACROS_STOP_MACRONAME, "",
this->GetCMakeInstance()->GetDebugOutput());
}
}
@@ -247,10 +343,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);
}
}
}
@@ -259,7 +354,7 @@ void cmGlobalVisualStudioGenerator::FillLinkClosure(
cmGlobalVisualStudioGenerator::TargetSet const&
cmGlobalVisualStudioGenerator::GetTargetLinkClosure(cmGeneratorTarget* target)
{
- TargetSetMap::iterator i = this->TargetLinkClosure.find(target);
+ auto i = this->TargetLinkClosure.find(target);
if (i == this->TargetLinkClosure.end()) {
TargetSetMap::value_type entry(target, TargetSet());
i = this->TargetLinkClosure.insert(entry).first;
@@ -279,10 +374,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);
}
}
}
@@ -293,15 +387,10 @@ 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) {
- std::vector<cmGeneratorTarget*> targets = (*i)->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator ti = targets.begin();
- ti != targets.end(); ++ti) {
- this->ComputeVSTargetDepends(*ti);
+ for (auto const& it : this->ProjectMap) {
+ for (const cmLocalGenerator* i : it.second) {
+ for (cmGeneratorTarget* ti : i->GetGeneratorTargets()) {
+ this->ComputeVSTargetDepends(ti);
}
}
}
@@ -351,22 +440,18 @@ 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;
- if (dep.IsLink()) {
- this->FollowLinkDepends(*di, linkDepends);
+ for (cmTargetDepend const& di : depends) {
+ if (di.IsLink()) {
+ 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;
- if (dep.IsUtil()) {
- this->FollowLinkDepends(*di, utilDepends);
+ for (cmTargetDepend const& di : depends) {
+ if (di.IsUtil()) {
+ this->FollowLinkDepends(di, utilDepends);
}
}
@@ -378,16 +463,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());
@@ -404,8 +485,8 @@ bool cmGlobalVisualStudioGenerator::FindMakeProgram(cmMakefile* mf)
// Visual Studio generators know how to lookup their build tool
// directly instead of needing a helper module to do it, so we
// do not actually need to put CMAKE_MAKE_PROGRAM into the cache.
- if (cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
- mf->AddDefinition("CMAKE_MAKE_PROGRAM", this->GetVSMakeProgram().c_str());
+ if (cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
+ mf->AddDefinition("CMAKE_MAKE_PROGRAM", this->GetVSMakeProgram());
}
return true;
}
@@ -413,7 +494,7 @@ bool cmGlobalVisualStudioGenerator::FindMakeProgram(cmMakefile* mf)
std::string cmGlobalVisualStudioGenerator::GetUtilityDepend(
cmGeneratorTarget const* target)
{
- UtilityDependsMap::iterator i = this->UtilityDepends.find(target);
+ auto i = this->UtilityDepends.find(target);
if (i == this->UtilityDepends.end()) {
std::string name = this->WriteUtilityDepend(target);
UtilityDependsMap::value_type entry(target, name);
@@ -432,7 +513,7 @@ std::string cmGlobalVisualStudioGenerator::GetStartupProjectName(
return startup;
} else {
root->GetMakefile()->IssueMessage(
- cmake::AUTHOR_WARNING,
+ MessageType::AUTHOR_WARNING,
"Directory property VS_STARTUP_PROJECT specifies target "
"'" +
startup + "' that does not exist. Ignoring.");
@@ -470,24 +551,24 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
if (ERROR_SUCCESS == result) {
// Iterate the subkeys and look for the values of interest in each subkey:
wchar_t subkeyname[256];
- DWORD cch_subkeyname = sizeof(subkeyname) * sizeof(subkeyname[0]);
+ DWORD cch_subkeyname = cm::size(subkeyname);
wchar_t keyclass[256];
- DWORD cch_keyclass = sizeof(keyclass) * sizeof(keyclass[0]);
+ DWORD cch_keyclass = cm::size(keyclass);
FILETIME lastWriteTime;
lastWriteTime.dwHighDateTime = 0;
lastWriteTime.dwLowDateTime = 0;
- while (ERROR_SUCCESS == RegEnumKeyExW(hkey, index, subkeyname,
- &cch_subkeyname, 0, keyclass,
- &cch_keyclass, &lastWriteTime)) {
+ while (ERROR_SUCCESS ==
+ RegEnumKeyExW(hkey, index, subkeyname, &cch_subkeyname, 0, keyclass,
+ &cch_keyclass, &lastWriteTime)) {
// Open the subkey and query the values of interest:
HKEY hsubkey = NULL;
result = RegOpenKeyExW(hkey, subkeyname, 0, KEY_READ, &hsubkey);
if (ERROR_SUCCESS == result) {
DWORD valueType = REG_SZ;
wchar_t data1[256];
- DWORD cch_data1 = sizeof(data1) * sizeof(data1[0]);
- RegQueryValueExW(hsubkey, L"Path", 0, &valueType, (LPBYTE)&data1[0],
+ DWORD cch_data1 = sizeof(data1);
+ RegQueryValueExW(hsubkey, L"Path", 0, &valueType, (LPBYTE)data1,
&cch_data1);
DWORD data2 = 0;
@@ -535,8 +616,8 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
}
++index;
- cch_subkeyname = sizeof(subkeyname) * sizeof(subkeyname[0]);
- cch_keyclass = sizeof(keyclass) * sizeof(keyclass[0]);
+ cch_subkeyname = cm::size(subkeyname);
+ cch_keyclass = cm::size(keyclass);
lastWriteTime.dwHighDateTime = 0;
lastWriteTime.dwLowDateTime = 0;
}
@@ -551,9 +632,7 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
// follow the expected naming scheme. Expected naming scheme is that
// the subkeys of OtherProjects7 is 0 to n-1, so it's ok to use "n"
// as the name of the next subkey.
- std::ostringstream ossNext;
- ossNext << index;
- nextAvailableSubKeyName = ossNext.str();
+ nextAvailableSubKeyName = std::to_string(index);
keyname = regKeyBase + "\\RecordingProject7";
hkey = NULL;
@@ -563,9 +642,8 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
if (ERROR_SUCCESS == result) {
DWORD valueType = REG_SZ;
wchar_t data1[256];
- DWORD cch_data1 = sizeof(data1) * sizeof(data1[0]);
- RegQueryValueExW(hkey, L"Path", 0, &valueType, (LPBYTE)&data1[0],
- &cch_data1);
+ DWORD cch_data1 = sizeof(data1);
+ RegQueryValueExW(hkey, L"Path", 0, &valueType, (LPBYTE)data1, &cch_data1);
DWORD data2 = 0;
DWORD cch_data2 = sizeof(data2);
@@ -691,7 +769,7 @@ void RegisterVisualStudioMacros(const std::string& macrosFile,
<< "CMake needs to register Visual Studio macros when its macros"
<< " file is updated or when it detects that its current macros file"
<< " is no longer registered with Visual Studio." << std::endl;
- cmSystemTools::Message(oss.str().c_str(), "Warning");
+ cmSystemTools::Message(oss.str(), "Warning");
// Count them again now that the warning is over. In the case of a GUI
// warning, the user may have gone to close Visual Studio and then come
@@ -722,7 +800,6 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(
cmGeneratorTarget const* gt)
{
// check to see if this is a fortran build
- std::set<std::string> languages;
{
// Issue diagnostic if the source files depend on the config.
std::vector<cmSourceFile*> sources;
@@ -730,65 +807,25 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(
return false;
}
}
+
// If there's only one source language, Fortran has to be used
// in order for the sources to compile.
- // Note: Via linker propagation, LINKER_LANGUAGE could become CXX in
- // this situation and mismatch from the actual language of the linker.
- gt->GetLanguages(languages, "");
- if (languages.size() == 1) {
- if (*languages.begin() == "Fortran") {
- return true;
- }
- }
-
- // In the case of mixed object files or sources mixed with objects,
- // decide the language based on the value of LINKER_LANGUAGE.
- // This will not make it possible to mix source files of different
- // languages, but object libraries will be linked together in the
- // same fashion as other generators do.
- if (gt->GetLinkerLanguage("") == "Fortran") {
- return true;
- }
-
- return false;
-}
-
-bool cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(
- cmGeneratorTarget const* gt)
-{
- // check to see if this is a C# build
std::set<std::string> languages;
- {
- // Issue diagnostic if the source files depend on the config.
- std::vector<cmSourceFile*> sources;
- if (!gt->GetConfigCommonSourceFiles(sources)) {
- return false;
- }
- // Only "real" targets are allowed to be C# targets.
- if (gt->Target->GetType() > cmStateEnums::OBJECT_LIBRARY) {
- return false;
- }
- }
gt->GetLanguages(languages, "");
- if (languages.size() == 1) {
- if (*languages.begin() == "CSharp") {
- return true;
- }
+ // Consider an explicit linker language property, but *not* the
+ // computed linker language that may depend on linked targets.
+ // This allows the project to control the language choice in
+ // a target with none of its own sources, e.g. when also using
+ // object libraries.
+ const char* linkLang = gt->GetProperty("LINKER_LANGUAGE");
+ if (linkLang && *linkLang) {
+ languages.insert(linkLang);
}
- return false;
-}
-bool cmGlobalVisualStudioGenerator::TargetCanBeReferenced(
- cmGeneratorTarget const* gt)
-{
- if (this->TargetIsCSharpOnly(gt)) {
- return true;
- }
- if (gt->GetType() != cmStateEnums::SHARED_LIBRARY &&
- gt->GetType() != cmStateEnums::EXECUTABLE) {
- return false;
- }
- return true;
+ // Intel Fortran .vfproj files do support the resource compiler.
+ languages.erase("RC");
+
+ return languages.size() == 1 && *languages.begin() == "Fortran";
}
bool cmGlobalVisualStudioGenerator::TargetCompare::operator()(
@@ -817,9 +854,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);
}
}
@@ -853,56 +889,41 @@ 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;
std::string cmakeCommand = cmSystemTools::GetCMakeCommand();
- cmSystemTools::ConvertToWindowsExtendedPath(cmakeCommand);
- cmCustomCommandLine cmdl;
- cmdl.push_back(cmakeCommand);
- cmdl.push_back("-E");
- cmdl.push_back("__create_def");
- cmdl.push_back(mdi->DefFile);
std::string obj_dir_expanded = obj_dir;
cmSystemTools::ReplaceString(obj_dir_expanded, this->GetCMakeCFGIntDir(),
configName.c_str());
cmSystemTools::MakeDirectory(obj_dir_expanded);
std::string const objs_file = obj_dir_expanded + "/objects.txt";
- cmdl.push_back(objs_file);
cmGeneratedFileStream fout(objs_file.c_str());
if (!fout) {
- cmSystemTools::Error("could not open ", objs_file.c_str());
+ cmSystemTools::Error("could not open " + objs_file);
return;
}
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);
// It must exist because we populated the mapping just above.
- assert(!map_it->second.empty());
- std::string objFile = obj_dir + map_it->second;
+ const auto& v = mapping[it];
+ assert(!v.empty());
+ std::string objFile = obj_dir + v;
objs.push_back(objFile);
}
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());
@@ -912,15 +933,44 @@ 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;
- commandLines.push_back(cmdl);
+ cmCustomCommandLines commandLines = cmMakeSingleCommandLine(
+ { cmakeCommand, "-E", "__create_def", mdi->DefFile, objs_file });
cmCustomCommand command(gt->Target->GetMakefile(), outputs, empty, empty,
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 sln = bindir + "/" + projectName + ".sln";
+
+ if (dryRun) {
+ return cmSystemTools::FileExists(sln, true);
+ }
+
+ sln = cmSystemTools::ConvertToOutputPath(sln);
+
+ return std::async(std::launch::async, OpenSolution, sln).get();
+}
diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h
index 3c43ccdd2..4f2007f75 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -3,7 +3,7 @@
#ifndef cmGlobalVisualStudioGenerator_h
#define cmGlobalVisualStudioGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <map>
@@ -32,22 +32,35 @@ public:
/** Known versions of Visual Studio. */
enum VSVersion
{
- VS8 = 80,
VS9 = 90,
VS10 = 100,
VS11 = 110,
VS12 = 120,
/* VS13 = 130 was skipped */
VS14 = 140,
- VS15 = 150
+ VS15 = 150,
+ VS16 = 160
};
- cmGlobalVisualStudioGenerator(cmake* cm);
virtual ~cmGlobalVisualStudioGenerator();
VSVersion GetVersion() const;
void SetVersion(VSVersion v);
+ /** Is the installed VS an Express edition? */
+ bool IsExpressEdition() const { return this->ExpressEdition; }
+
+ void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
+ bool optional) override;
+
+ bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override;
+
+ /**
+ * Get the name of the target platform (architecture) for which we generate.
+ * The names are as defined by VS, e.g. "Win32", "x64", "Itanium", "ARM".
+ */
+ std::string const& GetPlatformName() const;
+
/**
* Configure CMake's Visual Studio macros file into the user's Visual
* Studio macros directory.
@@ -77,17 +90,11 @@ public:
* Call the ReloadProjects macro if necessary based on
* GetFilesReplacedDuringGenerate results.
*/
- void CallVisualStudioMacro(MacroName m, const char* vsSolutionFile = 0);
+ void CallVisualStudioMacro(MacroName m, const std::string& vsSolutionFile);
// return true if target is fortran only
bool TargetIsFortranOnly(const cmGeneratorTarget* gt);
- // return true if target is C# only
- static bool TargetIsCSharpOnly(cmGeneratorTarget const* gt);
-
- // return true if target can be referenced by C# targets
- bool TargetCanBeReferenced(cmGeneratorTarget const* gt);
-
/** Get the top-level registry key for this VS version. */
std::string GetRegistryBase();
@@ -96,11 +103,20 @@ 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; }
+
+ /** Get encoding used by generator for generated source files
+ */
+ codecvt::Encoding GetMakefileEncoding() const override
+ {
+ return codecvt::ANSI;
+ }
+
class TargetSet : public std::set<cmGeneratorTarget const*>
{
};
@@ -118,12 +134,12 @@ public:
};
class OrderedTargetDependSet;
- bool FindMakeProgram(cmMakefile*) CM_OVERRIDE;
+ 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;
+ void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override;
std::string GetStartupProjectName(cmLocalGenerator const* root) const;
@@ -131,17 +147,25 @@ 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();
+ cmGlobalVisualStudioGenerator(cmake* cm,
+ std::string const& platformInGeneratorName);
+
+ 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
// below 8.
virtual bool VSLinksDependencies() const { return true; }
- virtual const char* GetIDEVersion() = 0;
+ const char* GetIDEVersion() const;
- virtual bool ComputeTargetDepends();
+ void WriteSLNHeader(std::ostream& fout);
+
+ bool ComputeTargetDepends() override;
class VSDependSet : public std::set<std::string>
{
};
@@ -156,16 +180,21 @@ protected:
const std::string&);
virtual std::string WriteUtilityDepend(cmGeneratorTarget const*) = 0;
std::string GetUtilityDepend(const cmGeneratorTarget* target);
- typedef std::map<cmGeneratorTarget const*, std::string> UtilityDependsMap;
+ using UtilityDependsMap = std::map<cmGeneratorTarget const*, std::string>;
UtilityDependsMap UtilityDepends;
protected:
VSVersion Version;
+ bool ExpressEdition;
+
+ std::string GeneratorPlatform;
+ std::string DefaultPlatformName;
+ bool PlatformInGeneratorName = false;
private:
virtual std::string GetVSMakeProgram() = 0;
void PrintCompilerAdvice(std::ostream&, std::string const&,
- const char*) const
+ const char*) const override
{
}
@@ -184,13 +213,12 @@ class cmGlobalVisualStudioGenerator::OrderedTargetDependSet
: public std::multiset<cmTargetDepend,
cmGlobalVisualStudioGenerator::TargetCompare>
{
- typedef std::multiset<cmTargetDepend,
- cmGlobalVisualStudioGenerator::TargetCompare>
- derived;
+ using derived = std::multiset<cmTargetDepend,
+ cmGlobalVisualStudioGenerator::TargetCompare>;
public:
- typedef cmGlobalGenerator::TargetDependSet TargetDependSet;
- typedef cmGlobalVisualStudioGenerator::TargetSet TargetSet;
+ using TargetDependSet = cmGlobalGenerator::TargetDependSet;
+ using TargetSet = cmGlobalVisualStudioGenerator::TargetSet;
OrderedTargetDependSet(TargetDependSet const&, std::string const& first);
OrderedTargetDependSet(TargetSet const&, std::string const& first);
};
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
new file mode 100644
index 000000000..a371633ed
--- /dev/null
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
@@ -0,0 +1,522 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmGlobalVisualStudioVersionedGenerator.h"
+
+#include "cmAlgorithms.h"
+#include "cmDocumentationEntry.h"
+#include "cmLocalVisualStudio10Generator.h"
+#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
+#include "cmVSSetupHelper.h"
+#include "cmake.h"
+
+#if defined(_M_ARM64)
+# define HOST_PLATFORM_NAME "ARM64"
+# define HOST_TOOLS_ARCH ""
+#elif defined(_M_ARM)
+# define HOST_PLATFORM_NAME "ARM"
+# define HOST_TOOLS_ARCH ""
+#elif defined(_M_IA64)
+# define HOST_PLATFORM_NAME "Itanium"
+# define HOST_TOOLS_ARCH ""
+#elif defined(_WIN64)
+# define HOST_PLATFORM_NAME "x64"
+# define HOST_TOOLS_ARCH "x64"
+#else
+static bool VSIsWow64()
+{
+ BOOL isWow64 = false;
+ return IsWow64Process(GetCurrentProcess(), &isWow64) && isWow64;
+}
+#endif
+
+static std::string VSHostPlatformName()
+{
+#ifdef HOST_PLATFORM_NAME
+ return HOST_PLATFORM_NAME;
+#else
+ if (VSIsWow64()) {
+ return "x64";
+ } else {
+ return "Win32";
+ }
+#endif
+}
+
+static std::string VSHostArchitecture()
+{
+#ifdef HOST_TOOLS_ARCH
+ return HOST_TOOLS_ARCH;
+#else
+ if (VSIsWow64()) {
+ return "x64";
+ } else {
+ return "x86";
+ }
+#endif
+}
+
+static unsigned int VSVersionToMajor(
+ cmGlobalVisualStudioGenerator::VSVersion v)
+{
+ switch (v) {
+ case cmGlobalVisualStudioGenerator::VS9:
+ return 9;
+ case cmGlobalVisualStudioGenerator::VS10:
+ return 10;
+ case cmGlobalVisualStudioGenerator::VS11:
+ return 11;
+ case cmGlobalVisualStudioGenerator::VS12:
+ return 12;
+ case cmGlobalVisualStudioGenerator::VS14:
+ return 14;
+ case cmGlobalVisualStudioGenerator::VS15:
+ return 15;
+ case cmGlobalVisualStudioGenerator::VS16:
+ return 16;
+ }
+ return 0;
+}
+
+static const char* VSVersionToToolset(
+ cmGlobalVisualStudioGenerator::VSVersion v)
+{
+ switch (v) {
+ case cmGlobalVisualStudioGenerator::VS9:
+ return "v90";
+ case cmGlobalVisualStudioGenerator::VS10:
+ return "v100";
+ case cmGlobalVisualStudioGenerator::VS11:
+ return "v110";
+ case cmGlobalVisualStudioGenerator::VS12:
+ return "v120";
+ case cmGlobalVisualStudioGenerator::VS14:
+ return "v140";
+ case cmGlobalVisualStudioGenerator::VS15:
+ return "v141";
+ case cmGlobalVisualStudioGenerator::VS16:
+ return "v142";
+ }
+ return "";
+}
+
+static const char vs15generatorName[] = "Visual Studio 15 2017";
+
+// Map generator name without year to name with year.
+static const char* cmVS15GenName(const std::string& name, std::string& genName)
+{
+ if (strncmp(name.c_str(), vs15generatorName,
+ sizeof(vs15generatorName) - 6) != 0) {
+ return 0;
+ }
+ const char* p = name.c_str() + sizeof(vs15generatorName) - 6;
+ if (cmHasLiteralPrefix(p, " 2017")) {
+ p += 5;
+ }
+ genName = std::string(vs15generatorName) + p;
+ return p;
+}
+
+class cmGlobalVisualStudioVersionedGenerator::Factory15
+ : public cmGlobalGeneratorFactory
+{
+public:
+ cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
+ cmake* cm) const override
+ {
+ std::string genName;
+ const char* p = cmVS15GenName(name, genName);
+ if (!p) {
+ return 0;
+ }
+ if (!*p) {
+ return new cmGlobalVisualStudioVersionedGenerator(
+ cmGlobalVisualStudioGenerator::VS15, cm, genName, "");
+ }
+ if (*p++ != ' ') {
+ return 0;
+ }
+ if (strcmp(p, "Win64") == 0) {
+ return new cmGlobalVisualStudioVersionedGenerator(
+ cmGlobalVisualStudioGenerator::VS15, cm, genName, "x64");
+ }
+ if (strcmp(p, "ARM") == 0) {
+ return new cmGlobalVisualStudioVersionedGenerator(
+ cmGlobalVisualStudioGenerator::VS15, cm, genName, "ARM");
+ }
+ return 0;
+ }
+
+ void GetDocumentation(cmDocumentationEntry& entry) const override
+ {
+ entry.Name = std::string(vs15generatorName) + " [arch]";
+ entry.Brief = "Generates Visual Studio 2017 project files. "
+ "Optional [arch] can be \"Win64\" or \"ARM\".";
+ }
+
+ std::vector<std::string> GetGeneratorNames() const override
+ {
+ std::vector<std::string> names;
+ names.push_back(vs15generatorName);
+ return names;
+ }
+
+ std::vector<std::string> GetGeneratorNamesWithPlatform() const override
+ {
+ std::vector<std::string> names;
+ names.push_back(vs15generatorName + std::string(" ARM"));
+ names.push_back(vs15generatorName + std::string(" Win64"));
+ return names;
+ }
+
+ bool SupportsToolset() const override { return true; }
+ bool SupportsPlatform() const override { return true; }
+
+ std::vector<std::string> GetKnownPlatforms() const override
+ {
+ std::vector<std::string> platforms;
+ platforms.emplace_back("x64");
+ platforms.emplace_back("Win32");
+ platforms.emplace_back("ARM");
+ platforms.emplace_back("ARM64");
+ return platforms;
+ }
+
+ std::string GetDefaultPlatformName() const override { return "Win32"; }
+};
+
+cmGlobalGeneratorFactory*
+cmGlobalVisualStudioVersionedGenerator::NewFactory15()
+{
+ return new Factory15;
+}
+
+static const char vs16generatorName[] = "Visual Studio 16 2019";
+
+// Map generator name without year to name with year.
+static const char* cmVS16GenName(const std::string& name, std::string& genName)
+{
+ if (strncmp(name.c_str(), vs16generatorName,
+ sizeof(vs16generatorName) - 6) != 0) {
+ return 0;
+ }
+ const char* p = name.c_str() + sizeof(vs16generatorName) - 6;
+ if (cmHasLiteralPrefix(p, " 2019")) {
+ p += 5;
+ }
+ genName = std::string(vs16generatorName) + p;
+ return p;
+}
+
+class cmGlobalVisualStudioVersionedGenerator::Factory16
+ : public cmGlobalGeneratorFactory
+{
+public:
+ cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
+ cmake* cm) const override
+ {
+ std::string genName;
+ const char* p = cmVS16GenName(name, genName);
+ if (!p) {
+ return 0;
+ }
+ if (!*p) {
+ return new cmGlobalVisualStudioVersionedGenerator(
+ cmGlobalVisualStudioGenerator::VS16, cm, genName, "");
+ }
+ return 0;
+ }
+
+ void GetDocumentation(cmDocumentationEntry& entry) const override
+ {
+ entry.Name = std::string(vs16generatorName);
+ entry.Brief = "Generates Visual Studio 2019 project files. "
+ "Use -A option to specify architecture.";
+ }
+
+ std::vector<std::string> GetGeneratorNames() const override
+ {
+ std::vector<std::string> names;
+ names.push_back(vs16generatorName);
+ return names;
+ }
+
+ std::vector<std::string> GetGeneratorNamesWithPlatform() const override
+ {
+ return std::vector<std::string>();
+ }
+
+ bool SupportsToolset() const override { return true; }
+ bool SupportsPlatform() const override { return true; }
+
+ std::vector<std::string> GetKnownPlatforms() const override
+ {
+ std::vector<std::string> platforms;
+ platforms.emplace_back("x64");
+ platforms.emplace_back("Win32");
+ platforms.emplace_back("ARM");
+ platforms.emplace_back("ARM64");
+ return platforms;
+ }
+
+ std::string GetDefaultPlatformName() const override
+ {
+ return VSHostPlatformName();
+ }
+};
+
+cmGlobalGeneratorFactory*
+cmGlobalVisualStudioVersionedGenerator::NewFactory16()
+{
+ return new Factory16;
+}
+
+cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator(
+ VSVersion version, cmake* cm, const std::string& name,
+ std::string const& platformInGeneratorName)
+ : cmGlobalVisualStudio14Generator(cm, name, platformInGeneratorName)
+ , vsSetupAPIHelper(VSVersionToMajor(version))
+{
+ this->Version = version;
+ this->ExpressEdition = false;
+ this->DefaultPlatformToolset = VSVersionToToolset(this->Version);
+ this->DefaultCLFlagTableName = VSVersionToToolset(this->Version);
+ this->DefaultCSharpFlagTableName = VSVersionToToolset(this->Version);
+ this->DefaultLinkFlagTableName = VSVersionToToolset(this->Version);
+ if (this->Version >= cmGlobalVisualStudioGenerator::VS16) {
+ this->DefaultPlatformName = VSHostPlatformName();
+ this->DefaultPlatformToolsetHostArchitecture = VSHostArchitecture();
+ }
+}
+
+bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName(
+ const std::string& name) const
+{
+ std::string genName;
+ switch (this->Version) {
+ case cmGlobalVisualStudioGenerator::VS9:
+ case cmGlobalVisualStudioGenerator::VS10:
+ case cmGlobalVisualStudioGenerator::VS11:
+ case cmGlobalVisualStudioGenerator::VS12:
+ case cmGlobalVisualStudioGenerator::VS14:
+ break;
+ case cmGlobalVisualStudioGenerator::VS15:
+ if (cmVS15GenName(name, genName)) {
+ return genName == this->GetName();
+ }
+ break;
+ case cmGlobalVisualStudioGenerator::VS16:
+ if (cmVS16GenName(name, genName)) {
+ return genName == this->GetName();
+ }
+ break;
+ }
+ return false;
+}
+
+bool cmGlobalVisualStudioVersionedGenerator::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(MessageType::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(MessageType::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 cmGlobalVisualStudioVersionedGenerator::GetVSInstance(
+ std::string& dir) const
+{
+ return vsSetupAPIHelper.GetVSInstanceInfo(dir);
+}
+
+bool cmGlobalVisualStudioVersionedGenerator::IsDefaultToolset(
+ const std::string& version) const
+{
+ if (version.empty()) {
+ return true;
+ }
+
+ std::string vcToolsetVersion;
+ if (this->vsSetupAPIHelper.GetVCToolsetVersion(vcToolsetVersion)) {
+
+ cmsys::RegularExpression regex("[0-9][0-9]\\.[0-9]+");
+ if (regex.find(version) && regex.find(vcToolsetVersion)) {
+ const auto majorMinorEnd = vcToolsetVersion.find('.', 3);
+ const auto majorMinor = vcToolsetVersion.substr(0, majorMinorEnd);
+ return version == majorMinor;
+ }
+ }
+
+ return false;
+}
+
+std::string cmGlobalVisualStudioVersionedGenerator::GetAuxiliaryToolset() const
+{
+ const char* version = this->GetPlatformToolsetVersion();
+ if (version) {
+ std::string instancePath;
+ GetVSInstance(instancePath);
+ std::string toolsetDir = instancePath + "/VC/Auxiliary/Build";
+ char sep = '/';
+ if (cmSystemTools::VersionCompareGreaterEq(version, "14.20")) {
+ std::string toolsetDot =
+ cmStrCat(toolsetDir, '.', version, "/Microsoft.VCToolsVersion.",
+ version, ".props");
+ if (cmSystemTools::PathExists(toolsetDot)) {
+ sep = '.';
+ }
+ }
+ std::string toolsetPath =
+ cmStrCat(toolsetDir, sep, version, "/Microsoft.VCToolsVersion.", version,
+ ".props");
+ cmSystemTools::ConvertToUnixSlashes(toolsetPath);
+ return toolsetPath;
+ }
+ return {};
+}
+
+bool cmGlobalVisualStudioVersionedGenerator::InitializeWindows(cmMakefile* mf)
+{
+ // If the Win 8.1 SDK is installed then we can select a SDK matching
+ // the target Windows version.
+ if (this->IsWin81SDKInstalled()) {
+ // VS 2019 does not default to 8.1 so specify it explicitly when needed.
+ if (this->Version >= cmGlobalVisualStudioGenerator::VS16 &&
+ !cmSystemTools::VersionCompareGreater(this->SystemVersion, "8.1")) {
+ this->SetWindowsTargetPlatformVersion("8.1", mf);
+ return true;
+ }
+ return cmGlobalVisualStudio14Generator::InitializeWindows(mf);
+ }
+ // Otherwise we must choose a Win 10 SDK even if we are not targeting
+ // Windows 10.
+ return this->SelectWindows10SDK(mf, false);
+}
+
+bool cmGlobalVisualStudioVersionedGenerator::SelectWindowsStoreToolset(
+ std::string& toolset) const
+{
+ if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) {
+ if (this->IsWindowsStoreToolsetInstalled() &&
+ this->IsWindowsDesktopToolsetInstalled()) {
+ toolset = VSVersionToToolset(this->Version);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return this->cmGlobalVisualStudio14Generator::SelectWindowsStoreToolset(
+ toolset);
+}
+
+bool cmGlobalVisualStudioVersionedGenerator::IsWindowsDesktopToolsetInstalled()
+ const
+{
+ return vsSetupAPIHelper.IsVSInstalled();
+}
+
+bool cmGlobalVisualStudioVersionedGenerator::IsWindowsStoreToolsetInstalled()
+ const
+{
+ return vsSetupAPIHelper.IsWin10SDKInstalled();
+}
+
+bool cmGlobalVisualStudioVersionedGenerator::IsWin81SDKInstalled() const
+{
+ // Does the VS installer tool know about one?
+ if (vsSetupAPIHelper.IsWin81SDKInstalled()) {
+ return true;
+ }
+
+ // Does the registry know about one (e.g. from VS 2015)?
+ std::string win81Root;
+ if (cmSystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
+ "Windows Kits\\Installed Roots;KitsRoot81",
+ win81Root, cmSystemTools::KeyWOW64_32) ||
+ cmSystemTools::ReadRegistryValue(
+ "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\"
+ "Windows Kits\\Installed Roots;KitsRoot81",
+ win81Root, cmSystemTools::KeyWOW64_32)) {
+ return cmSystemTools::FileExists(win81Root + "/include/um/windows.h",
+ true);
+ }
+ return false;
+}
+
+std::string cmGlobalVisualStudioVersionedGenerator::GetWindows10SDKMaxVersion()
+ const
+{
+ return std::string();
+}
+
+std::string cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommand()
+{
+ std::string msbuild;
+
+ // Ask Visual Studio Installer tool.
+ std::string vs;
+ if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) {
+ msbuild = vs + "/MSBuild/Current/Bin/MSBuild.exe";
+ if (cmSystemTools::FileExists(msbuild)) {
+ return msbuild;
+ }
+ msbuild = vs + "/MSBuild/15.0/Bin/MSBuild.exe";
+ if (cmSystemTools::FileExists(msbuild)) {
+ return msbuild;
+ }
+ }
+
+ msbuild = "MSBuild.exe";
+ return msbuild;
+}
+
+std::string cmGlobalVisualStudioVersionedGenerator::FindDevEnvCommand()
+{
+ std::string devenv;
+
+ // Ask Visual Studio Installer tool.
+ std::string vs;
+ if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) {
+ devenv = vs + "/Common7/IDE/devenv.com";
+ if (cmSystemTools::FileExists(devenv)) {
+ return devenv;
+ }
+ }
+
+ devenv = "devenv.com";
+ return devenv;
+}
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h
new file mode 100644
index 000000000..466816ba8
--- /dev/null
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.h
@@ -0,0 +1,65 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmGlobalVisualStudioVersionedGenerator_h
+#define cmGlobalVisualStudioVersionedGenerator_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <iosfwd>
+#include <string>
+
+#include "cmGlobalVisualStudio14Generator.h"
+#include "cmVSSetupHelper.h"
+
+class cmGlobalGeneratorFactory;
+class cmake;
+
+/** \class cmGlobalVisualStudioVersionedGenerator */
+class cmGlobalVisualStudioVersionedGenerator
+ : public cmGlobalVisualStudio14Generator
+{
+public:
+ static cmGlobalGeneratorFactory* NewFactory15();
+ static cmGlobalGeneratorFactory* NewFactory16();
+
+ bool MatchesGeneratorName(const std::string& name) const override;
+
+ bool SetGeneratorInstance(std::string const& i, cmMakefile* mf) override;
+
+ bool GetVSInstance(std::string& dir) const;
+
+ bool IsDefaultToolset(const std::string& version) const override;
+ std::string GetAuxiliaryToolset() const override;
+
+protected:
+ cmGlobalVisualStudioVersionedGenerator(
+ VSVersion version, cmake* cm, const std::string& name,
+ std::string const& platformInGeneratorName);
+
+ bool InitializeWindows(cmMakefile* mf) override;
+ bool SelectWindowsStoreToolset(std::string& toolset) const override;
+
+ // Used to verify that the Desktop toolset for the current generator is
+ // installed on the machine.
+ bool IsWindowsDesktopToolsetInstalled() const override;
+
+ // These aren't virtual because we need to check if the selected version
+ // of the toolset is installed
+ bool IsWindowsStoreToolsetInstalled() const;
+
+ // Check for a Win 8 SDK known to the registry or VS installer tool.
+ bool IsWin81SDKInstalled() const;
+
+ std::string GetWindows10SDKMaxVersion() const override;
+
+ std::string FindMSBuildCommand() override;
+ std::string FindDevEnvCommand() override;
+
+private:
+ class Factory15;
+ friend class Factory15;
+ class Factory16;
+ friend class Factory16;
+ mutable cmVSSetupAPIHelper vsSetupAPIHelper;
+};
+#endif
diff --git a/Source/cmGlobalWatcomWMakeGenerator.cxx b/Source/cmGlobalWatcomWMakeGenerator.cxx
index 94cdb3848..308ddda73 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.cxx
+++ b/Source/cmGlobalWatcomWMakeGenerator.cxx
@@ -2,7 +2,10 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalWatcomWMakeGenerator.h"
+#include <ostream>
+
#include "cmDocumentationEntry.h"
+#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmake.h"
@@ -47,3 +50,32 @@ void cmGlobalWatcomWMakeGenerator::GetDocumentation(
entry.Name = cmGlobalWatcomWMakeGenerator::GetActualName();
entry.Brief = "Generates Watcom WMake makefiles.";
}
+
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalWatcomWMakeGenerator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int /*jobs*/, bool verbose,
+ std::vector<std::string> const& makeOptions)
+{
+ return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
+ makeProgram, projectName, projectDir, targetNames, config, fast,
+ cmake::NO_BUILD_PARALLEL_LEVEL, verbose, makeOptions);
+}
+
+void cmGlobalWatcomWMakeGenerator::PrintBuildCommandAdvice(std::ostream& os,
+ int jobs) const
+{
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ // wmake does not support parallel build level
+
+ /* clang-format off */
+ os <<
+ "Warning: Watcom's WMake does not support parallel builds. "
+ "Ignoring parallel build command line option.\n";
+ /* clang-format on */
+ }
+
+ this->cmGlobalUnixMakefileGenerator3::PrintBuildCommandAdvice(
+ os, cmake::NO_BUILD_PARALLEL_LEVEL);
+}
diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h
index b2d6d5d71..64ace1359 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.h
+++ b/Source/cmGlobalWatcomWMakeGenerator.h
@@ -3,14 +3,15 @@
#ifndef cmGlobalWatcomWMakeGenerator_h
#define cmGlobalWatcomWMakeGenerator_h
-#include "cmConfigure.h"
-
-#include "cmGlobalGeneratorFactory.h"
-#include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+#include <iosfwd>
#include <string>
#include <vector>
+#include "cmGlobalGeneratorFactory.h"
+#include "cmGlobalUnixMakefileGenerator3.h"
+
class cmMakefile;
class cmake;
struct cmDocumentationEntry;
@@ -28,8 +29,8 @@ public:
{
return new cmGlobalGeneratorSimpleFactory<cmGlobalWatcomWMakeGenerator>();
}
- ///! Get the name for the generator.
- std::string GetName() const CM_OVERRIDE
+ //! Get the name for the generator.
+ std::string GetName() const override
{
return cmGlobalWatcomWMakeGenerator::GetActualName();
}
@@ -43,10 +44,20 @@ public:
* extension, pthreads, byte order etc.
*/
void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
- bool optional) CM_OVERRIDE;
+ bool optional) override;
+
+ bool AllowNotParallel() const override { return false; }
+ bool AllowDeleteOnError() const override { return false; }
+
+protected:
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
- bool AllowNotParallel() const CM_OVERRIDE { return false; }
- bool AllowDeleteOnError() const CM_OVERRIDE { return false; }
+ void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override;
};
#endif
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 903796123..3002b2a68 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -2,15 +2,21 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalXCodeGenerator.h"
-#include "cmsys/RegularExpression.hxx"
-#include <assert.h>
+#include <cassert>
+#include <cstdio>
+#include <cstring>
#include <iomanip>
#include <sstream>
-#include <stdio.h>
-#include <string.h>
+#include <cm/memory>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
+#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
+#include "cmCustomCommandLines.h"
#include "cmDocumentationEntry.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
@@ -19,6 +25,7 @@
#include "cmLocalGenerator.h"
#include "cmLocalXCodeGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmSourceFile.h"
#include "cmSourceGroup.h"
@@ -29,13 +36,17 @@
#include "cmXCode21Object.h"
#include "cmXCodeObject.h"
#include "cmXCodeScheme.h"
-#include "cm_auto_ptr.hxx"
#include "cmake.h"
struct cmLinkImplementation;
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmXMLParser.h"
+#if !defined(CMAKE_BOOTSTRAP) && defined(__APPLE__)
+# define HAVE_APPLICATION_SERVICES
+# include <ApplicationServices/ApplicationServices.h>
+#endif
+
+#if !defined(CMAKE_BOOTSTRAP)
+# include "cmXMLParser.h"
// parse the xml file storing the installed version of Xcode on
// the machine
@@ -46,8 +57,11 @@ public:
: Version("1.5")
{
}
- void StartElement(const std::string&, const char**) { this->Data = ""; }
- void EndElement(const std::string& name)
+ void StartElement(const std::string&, const char**) override
+ {
+ this->Data = "";
+ }
+ void EndElement(const std::string& name) override
{
if (name == "key") {
this->Key = this->Data;
@@ -57,7 +71,7 @@ public:
}
}
}
- void CharacterDataHandler(const char* data, int length)
+ void CharacterDataHandler(const char* data, int length) override
{
this->Data.append(data, length);
}
@@ -79,7 +93,7 @@ class cmGlobalXCodeGenerator::BuildObjectListOrString
public:
BuildObjectListOrString(cmGlobalXCodeGenerator* gen, bool buildObjectList)
: Generator(gen)
- , Group(0)
+ , Group(nullptr)
, Empty(true)
{
if (buildObjectList) {
@@ -107,9 +121,8 @@ public:
{
if (this->Group) {
return this->Group;
- } else {
- return this->Generator->CreateString(this->String);
}
+ return this->Generator->CreateString(this->String);
}
};
@@ -117,20 +130,34 @@ class cmGlobalXCodeGenerator::Factory : public cmGlobalGeneratorFactory
{
public:
cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
- cmake* cm) const CM_OVERRIDE;
+ cmake* cm) const override;
- void GetDocumentation(cmDocumentationEntry& entry) const CM_OVERRIDE
+ void GetDocumentation(cmDocumentationEntry& entry) const override
{
cmGlobalXCodeGenerator::GetDocumentation(entry);
}
- void GetGenerators(std::vector<std::string>& names) const CM_OVERRIDE
+ std::vector<std::string> GetGeneratorNames() const override
{
+ std::vector<std::string> names;
names.push_back(cmGlobalXCodeGenerator::GetActualName());
+ return names;
}
- bool SupportsToolset() const CM_OVERRIDE { return true; }
- bool SupportsPlatform() const CM_OVERRIDE { return false; }
+ std::vector<std::string> GetGeneratorNamesWithPlatform() const override
+ {
+ return std::vector<std::string>();
+ }
+
+ bool SupportsToolset() const override { return true; }
+ bool SupportsPlatform() const override { return false; }
+
+ std::vector<std::string> GetKnownPlatforms() const override
+ {
+ return std::vector<std::string>();
+ }
+
+ std::string GetDefaultPlatformName() const override { return std::string(); }
};
cmGlobalXCodeGenerator::cmGlobalXCodeGenerator(
@@ -140,10 +167,10 @@ cmGlobalXCodeGenerator::cmGlobalXCodeGenerator(
this->VersionString = version_string;
this->XcodeVersion = version_number;
- this->RootObject = 0;
- this->MainGroupChildren = 0;
- this->CurrentMakefile = 0;
- this->CurrentLocalGenerator = 0;
+ this->RootObject = nullptr;
+ this->MainGroupChildren = nullptr;
+ this->CurrentMakefile = nullptr;
+ this->CurrentLocalGenerator = nullptr;
this->XcodeBuildCommandInitialized = false;
this->ObjectDirArchDefault = "$(CURRENT_ARCH)";
@@ -160,21 +187,25 @@ cmGlobalGeneratorFactory* cmGlobalXCodeGenerator::NewFactory()
cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator(
const std::string& name, cmake* cm) const
{
- if (name != GetActualName())
- return 0;
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+ if (name != GetActualName()) {
+ return nullptr;
+ }
+#if !defined(CMAKE_BOOTSTRAP)
cmXcodeVersionParser parser;
std::string versionFile;
{
std::string out;
- std::string::size_type pos;
- if (cmSystemTools::RunSingleCommand("xcode-select --print-path", &out, 0,
- 0, 0, cmSystemTools::OUTPUT_NONE) &&
- (pos = out.find(".app/"), pos != std::string::npos)) {
- versionFile = out.substr(0, pos + 5) + "Contents/version.plist";
+ bool commandResult = cmSystemTools::RunSingleCommand(
+ "xcode-select --print-path", &out, nullptr, nullptr, nullptr,
+ cmSystemTools::OUTPUT_NONE);
+ if (commandResult) {
+ std::string::size_type pos = out.find(".app/");
+ if (pos != std::string::npos) {
+ versionFile = out.substr(0, pos + 5) + "Contents/version.plist";
+ }
}
}
- if (!versionFile.empty() && cmSystemTools::FileExists(versionFile.c_str())) {
+ if (!versionFile.empty() && cmSystemTools::FileExists(versionFile)) {
parser.ParseFile(versionFile.c_str());
} else if (cmSystemTools::FileExists(
"/Applications/Xcode.app/Contents/version.plist")) {
@@ -190,14 +221,14 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator(
sscanf(version_string.c_str(), "%u.%u", &v[0], &v[1]);
unsigned int version_number = 10 * v[0] + v[1];
- if (version_number < 30) {
- cm->IssueMessage(cmake::FATAL_ERROR,
+ if (version_number < 50) {
+ cm->IssueMessage(MessageType::FATAL_ERROR,
"Xcode " + version_string + " not supported.");
- return CM_NULLPTR;
+ return nullptr;
}
- CM_AUTO_PTR<cmGlobalXCodeGenerator> gg(
- new cmGlobalXCodeGenerator(cm, version_string, version_number));
+ auto gg = cm::make_unique<cmGlobalXCodeGenerator>(cm, version_string,
+ version_number);
return gg.release();
#else
std::cerr << "CMake should be built with cmake to use Xcode, "
@@ -211,9 +242,8 @@ bool cmGlobalXCodeGenerator::FindMakeProgram(cmMakefile* mf)
// The Xcode generator knows how to lookup its build tool
// directly instead of needing a helper module to do it, so we
// do not actually need to put CMAKE_MAKE_PROGRAM into the cache.
- if (cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
- mf->AddDefinition("CMAKE_MAKE_PROGRAM",
- this->GetXcodeBuildCommand().c_str());
+ if (cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
+ mf->AddDefinition("CMAKE_MAKE_PROGRAM", this->GetXcodeBuildCommand());
}
return true;
}
@@ -229,16 +259,11 @@ std::string const& cmGlobalXCodeGenerator::GetXcodeBuildCommand()
std::string cmGlobalXCodeGenerator::FindXcodeBuildCommand()
{
- if (this->XcodeVersion >= 40) {
- std::string makeProgram = cmSystemTools::FindProgram("xcodebuild");
- if (makeProgram.empty()) {
- makeProgram = "xcodebuild";
- }
- return makeProgram;
- } else {
- // Use cmakexbuild wrapper to suppress environment dump from output.
- return cmSystemTools::GetCMakeCommand() + "xbuild";
+ std::string makeProgram = cmSystemTools::FindProgram("xcodebuild");
+ if (makeProgram.empty()) {
+ makeProgram = "xcodebuild";
}
+ return makeProgram;
}
bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts,
@@ -254,13 +279,12 @@ bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts,
" " << ts << "\n"
"that was specified.";
/* clang-format on */
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
this->GeneratorToolset = ts;
if (!this->GeneratorToolset.empty()) {
- mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET",
- this->GeneratorToolset.c_str());
+ mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", this->GeneratorToolset);
}
return true;
}
@@ -269,7 +293,7 @@ void cmGlobalXCodeGenerator::EnableLanguage(
std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
{
mf->AddDefinition("XCODE", "1");
- mf->AddDefinition("XCODE_VERSION", this->VersionString.c_str());
+ mf->AddDefinition("XCODE_VERSION", this->VersionString);
if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) {
mf->AddCacheDefinition(
"CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo",
@@ -283,46 +307,87 @@ void cmGlobalXCodeGenerator::EnableLanguage(
this->ComputeArchitectures(mf);
}
-void cmGlobalXCodeGenerator::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)
+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;
+}
+
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalXCodeGenerator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& /*projectDir*/,
+ std::vector<std::string> const& targetNames, const std::string& config,
+ bool /*fast*/, int jobs, bool /*verbose*/,
+ std::vector<std::string> const& makeOptions)
{
+ GeneratedMakeCommand makeCommand;
// now build the test
- makeCommand.push_back(
+ makeCommand.Add(
this->SelectMakeProgram(makeProgram, this->GetXcodeBuildCommand()));
- makeCommand.push_back("-project");
- std::string projectArg = projectName;
- projectArg += ".xcode";
- projectArg += "proj";
- makeCommand.push_back(projectArg);
-
- bool clean = false;
- std::string realTarget = targetName;
- if (realTarget == "clean") {
- clean = true;
- realTarget = "ALL_BUILD";
+ if (!projectName.empty()) {
+ makeCommand.Add("-project");
+ std::string projectArg = cmStrCat(projectName, ".xcodeproj");
+ makeCommand.Add(projectArg);
}
- if (clean) {
- makeCommand.push_back("clean");
+ if (cmContains(targetNames, "clean")) {
+ makeCommand.Add("clean");
+ makeCommand.Add("-target", "ALL_BUILD");
} else {
- makeCommand.push_back("build");
+ makeCommand.Add("build");
+ if (targetNames.empty() ||
+ ((targetNames.size() == 1) && targetNames.front().empty())) {
+ makeCommand.Add("-target", "ALL_BUILD");
+ } else {
+ for (const auto& tname : targetNames) {
+ if (!tname.empty()) {
+ makeCommand.Add("-target", tname);
+ }
+ }
+ }
}
- makeCommand.push_back("-target");
- if (!realTarget.empty()) {
- makeCommand.push_back(realTarget);
- } else {
- makeCommand.push_back("ALL_BUILD");
+
+ makeCommand.Add("-configuration", (config.empty() ? "Debug" : config));
+
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ makeCommand.Add("-jobs");
+ if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ makeCommand.Add(std::to_string(jobs));
+ }
}
- makeCommand.push_back("-configuration");
- makeCommand.push_back(!config.empty() ? config : "Debug");
- makeCommand.insert(makeCommand.end(), makeOptions.begin(),
- makeOptions.end());
+
+ if (this->XcodeVersion >= 70) {
+ makeCommand.Add("-hideShellScriptEnvironment");
+ }
+ makeCommand.Add(makeOptions.begin(), makeOptions.end());
+ return { std::move(makeCommand) };
}
-///! Create a local generator appropriate to this Global Generator
+//! Create a local generator appropriate to this Global Generator
cmLocalGenerator* cmGlobalXCodeGenerator::CreateLocalGenerator(cmMakefile* mf)
{
return new cmLocalXCodeGenerator(this, mf);
@@ -330,15 +395,45 @@ 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);
+ }
+}
+
+void cmGlobalXCodeGenerator::ComputeTargetOrder()
+{
+ size_t index = 0;
+ auto const& lgens = this->GetLocalGenerators();
+ for (cmLocalGenerator* lgen : lgens) {
+ auto const& targets = lgen->GetGeneratorTargets();
+ for (cmGeneratorTarget const* gt : targets) {
+ this->ComputeTargetOrder(gt, index);
+ }
+ }
+ assert(index == this->TargetOrderIndex.size());
+}
+
+void cmGlobalXCodeGenerator::ComputeTargetOrder(cmGeneratorTarget const* gt,
+ size_t& index)
+{
+ std::map<cmGeneratorTarget const*, size_t>::value_type value(gt, 0);
+ auto insertion = this->TargetOrderIndex.insert(value);
+ if (!insertion.second) {
+ return;
+ }
+ auto entry = insertion.first;
+
+ auto& deps = this->GetTargetDirectDepends(gt);
+ for (auto& d : deps) {
+ this->ComputeTargetOrder(d, index);
}
+
+ entry->second = index++;
}
void cmGlobalXCodeGenerator::Generate()
@@ -347,12 +442,25 @@ 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];
+
+ this->ComputeTargetOrder();
+
+ 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);
}
}
@@ -367,9 +475,9 @@ void cmGlobalXCodeGenerator::SetGenerationRoot(cmLocalGenerator* root)
this->CurrentLocalGenerator->GetCurrentBinaryDirectory(),
this->ProjectOutputDirectoryComponents);
- this->CurrentXCodeHackMakefile = root->GetCurrentBinaryDirectory();
- this->CurrentXCodeHackMakefile += "/CMakeScripts";
- cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile.c_str());
+ this->CurrentXCodeHackMakefile =
+ cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeScripts");
+ cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile);
this->CurrentXCodeHackMakefile += "/XCODE_DEPEND_HELPER.make";
}
@@ -378,54 +486,52 @@ std::string cmGlobalXCodeGenerator::PostBuildMakeTarget(
{
std::string target = tName;
std::replace(target.begin(), target.end(), ' ', '_');
- std::string out = "PostBuild." + target;
- out += "." + configName;
+ std::string out = cmStrCat("PostBuild.", target, '.', configName);
return out;
}
#define CMAKE_CHECK_BUILD_SYSTEM_TARGET "ZERO_CHECK"
+#define OBJECT_LIBRARY_ARTIFACT_DIR std::string()
void cmGlobalXCodeGenerator::AddExtraTargets(
cmLocalGenerator* root, std::vector<cmLocalGenerator*>& gens)
{
cmMakefile* mf = root->GetMakefile();
- // Add ALL_BUILD
- const char* no_working_directory = 0;
+ const char* no_working_directory = nullptr;
+ std::vector<std::string> no_byproducts;
std::vector<std::string> no_depends;
- cmTarget* allbuild =
- mf->AddUtilityCommand("ALL_BUILD", true, no_depends, no_working_directory,
- "echo", "Build all projects");
+
+ // Add ALL_BUILD
+ cmTarget* allbuild = mf->AddUtilityCommand(
+ "ALL_BUILD", cmCommandOrigin::Generator, true, no_working_directory,
+ no_byproducts, no_depends,
+ cmMakeSingleCommandLine({ "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;
- makeHelper.push_back("make");
- makeHelper.push_back("-C");
- makeHelper.push_back(dir);
- makeHelper.push_back("-f");
- makeHelper.push_back(this->CurrentXCodeHackMakefile);
- makeHelper.push_back(""); // placeholder, see below
+ cmCustomCommandLines commandLines = cmMakeSingleCommandLine(
+ { "make", "-C", dir, "-f", this->CurrentXCodeHackMakefile,
+ "OBJDIR=$(OBJDIR)", /* placeholder, see below */ "" });
// Add ZERO_CHECK
- bool regenerate = !mf->IsOn("CMAKE_SUPPRESS_REGENERATION");
- if (regenerate) {
+ bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
+ 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());
+ this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile);
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, cmCommandOrigin::Generator, true,
+ no_working_directory, no_byproducts, no_depends,
+ cmMakeSingleCommandLine({ "make", "-f", file }));
cmGeneratorTarget* checkGt = new cmGeneratorTarget(check, root);
root->AddGeneratorTarget(checkGt);
@@ -433,25 +539,14 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
// now make the allbuild depend on all the non-utility targets
// in the project
- for (std::vector<cmLocalGenerator*>::iterator i = gens.begin();
- i != gens.end(); ++i) {
- cmLocalGenerator* lg = *i;
- if (this->IsExcluded(root, *i)) {
- continue;
- }
-
- std::vector<cmGeneratorTarget*> tgts = lg->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin();
- l != tgts.end(); l++) {
- cmGeneratorTarget* target = *l;
-
+ for (auto& gen : gens) {
+ for (auto target : gen->GetGeneratorTargets()) {
if (target->GetType() == cmStateEnums::GLOBAL_TARGET) {
continue;
}
- std::string targetName = target->GetName();
-
- if (regenerate && (targetName != CMAKE_CHECK_BUILD_SYSTEM_TARGET)) {
+ if (regenerate &&
+ (target->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET)) {
target->Target->AddUtility(CMAKE_CHECK_BUILD_SYSTEM_TARGET);
}
@@ -459,33 +554,19 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
// run the depend check makefile as a post build rule
// this will make sure that when the next target is built
// things are up-to-date
- if (target->GetType() == cmStateEnums::OBJECT_LIBRARY ||
- (this->XcodeVersion < 50 &&
- (target->GetType() == cmStateEnums::EXECUTABLE ||
- target->GetType() == cmStateEnums::STATIC_LIBRARY ||
- target->GetType() == cmStateEnums::SHARED_LIBRARY ||
- target->GetType() == cmStateEnums::MODULE_LIBRARY))) {
- makeHelper[makeHelper.size() - 1] = // fill placeholder
+ if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ commandLines.front().back() = // fill placeholder
this->PostBuildMakeTarget(target->GetName(), "$(CONFIGURATION)");
- cmCustomCommandLines commandLines;
- commandLines.push_back(makeHelper);
- std::vector<std::string> no_byproducts;
- lg->GetMakefile()->AddCustomCommandToTarget(
+ gen->GetMakefile()->AddCustomCommandToTarget(
target->GetName(), no_byproducts, no_depends, commandLines,
- cmTarget::POST_BUILD, "Depend check for xcode", dir.c_str(), true,
- false, "", false, cmMakefile::AcceptObjectLibraryCommands);
+ cmCustomCommandType::POST_BUILD, "Depend check for xcode",
+ dir.c_str(), true, false, "", "", false,
+ cmObjectLibraryCommands::Accept);
}
- if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
- !target->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+ if (!this->IsExcluded(gens[0], target)) {
allbuild->AddUtility(target->GetName());
}
-
- // Refer to the build configuration file for easy editing.
- listfile = lg->GetCurrentSourceDirectory();
- listfile += "/";
- listfile += "CMakeLists.txt";
- target->AddSource(listfile);
}
}
}
@@ -494,47 +575,60 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile(
cmLocalGenerator* root, std::vector<cmLocalGenerator*> const& gens)
{
std::vector<std::string> lfiles;
- for (std::vector<cmLocalGenerator*>::const_iterator gi = gens.begin();
- gi != gens.end(); ++gi) {
- std::vector<std::string> const& lf = (*gi)->GetMakefile()->GetListFiles();
- lfiles.insert(lfiles.end(), lf.begin(), lf.end());
+ for (auto gen : gens) {
+ cmAppend(lfiles, gen->GetMakefile()->GetListFiles());
}
// sort the array
- std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
- std::vector<std::string>::iterator new_end =
- std::unique(lfiles.begin(), lfiles.end());
- lfiles.erase(new_end, lfiles.end());
- this->CurrentReRunCMakeMakefile = root->GetCurrentBinaryDirectory();
- this->CurrentReRunCMakeMakefile += "/CMakeScripts";
- cmSystemTools::MakeDirectory(this->CurrentReRunCMakeMakefile.c_str());
+ std::sort(lfiles.begin(), lfiles.end());
+ lfiles.erase(std::unique(lfiles.begin(), lfiles.end()), lfiles.end());
+
+ cmake* cm = this->GetCMakeInstance();
+ if (cm->DoWriteGlobVerifyTarget()) {
+ lfiles.emplace_back(cm->GetGlobVerifyStamp());
+ }
+
+ this->CurrentReRunCMakeMakefile =
+ cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeScripts");
+ cmSystemTools::MakeDirectory(this->CurrentReRunCMakeMakefile);
this->CurrentReRunCMakeMakefile += "/ReRunCMake.make";
- cmGeneratedFileStream makefileStream(
- this->CurrentReRunCMakeMakefile.c_str());
+ cmGeneratedFileStream makefileStream(this->CurrentReRunCMakeMakefile);
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) << "))\n";
}
+ makefileStream << "\n";
- std::string checkCache = root->GetBinaryDirectory();
- checkCache += "/";
- checkCache += cmake::GetCMakeFilesDirectoryPostSlash();
- checkCache += "cmake.check_cache";
+ std::string checkCache =
+ cmStrCat(root->GetBinaryDirectory(), "/CMakeFiles/cmake.check_cache");
- makefileStream << "\n"
- << this->ConvertToRelativeForMake(checkCache.c_str())
+ if (cm->DoWriteGlobVerifyTarget()) {
+ makefileStream << ".NOTPARALLEL:\n\n";
+ makefileStream << ".PHONY: all VERIFY_GLOBS\n\n";
+ makefileStream << "all: VERIFY_GLOBS "
+ << this->ConvertToRelativeForMake(checkCache) << "\n\n";
+ makefileStream << "VERIFY_GLOBS:\n";
+ makefileStream << "\t"
+ << this->ConvertToRelativeForMake(
+ cmSystemTools::GetCMakeCommand())
+ << " -P "
+ << this->ConvertToRelativeForMake(cm->GetGlobVerifyScript())
+ << "\n\n";
+ }
+
+ makefileStream << this->ConvertToRelativeForMake(checkCache)
<< ": $(TARGETS)\n";
makefileStream << "\t"
<< this->ConvertToRelativeForMake(
- cmSystemTools::GetCMakeCommand().c_str())
+ cmSystemTools::GetCMakeCommand())
<< " -H"
<< this->ConvertToRelativeForMake(root->GetSourceDirectory())
<< " -B"
@@ -556,8 +650,8 @@ void cmGlobalXCodeGenerator::SortXCodeObjects()
void cmGlobalXCodeGenerator::ClearXCodeObjects()
{
this->TargetDoneSet.clear();
- for (unsigned int i = 0; i < this->XCodeObjects.size(); ++i) {
- delete this->XCodeObjects[i];
+ for (auto& obj : this->XCodeObjects) {
+ delete obj;
}
this->XCodeObjects.clear();
this->XCodeObjectIDs.clear();
@@ -571,7 +665,7 @@ void cmGlobalXCodeGenerator::ClearXCodeObjects()
void cmGlobalXCodeGenerator::addObject(cmXCodeObject* obj)
{
if (obj->GetType() == cmXCodeObject::OBJECT) {
- std::string id = obj->GetId();
+ const std::string& id = obj->GetId();
// If this is a duplicate id, it's an error:
//
@@ -649,9 +743,58 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath(
return buildFile;
}
+class XCodeGeneratorExpressionInterpreter
+ : public cmGeneratorExpressionInterpreter
+{
+public:
+ XCodeGeneratorExpressionInterpreter(cmSourceFile* sourceFile,
+ cmLocalGenerator* localGenerator,
+ cmGeneratorTarget* headTarget,
+ const std::string& lang)
+ : cmGeneratorExpressionInterpreter(
+ localGenerator, "NO-PER-CONFIG-SUPPORT-IN-XCODE", headTarget, lang)
+ , SourceFile(sourceFile)
+ {
+ }
+
+ XCodeGeneratorExpressionInterpreter(
+ XCodeGeneratorExpressionInterpreter const&) = delete;
+ XCodeGeneratorExpressionInterpreter& operator=(
+ XCodeGeneratorExpressionInterpreter const&) = delete;
+
+ using cmGeneratorExpressionInterpreter::Evaluate;
+
+ const std::string& Evaluate(const char* expression,
+ const std::string& property)
+ {
+ const std::string& processed =
+ this->cmGeneratorExpressionInterpreter::Evaluate(expression, property);
+ if (this->CompiledGeneratorExpression->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->ResolveFullPath() << "\n";
+ /* clang-format on */
+ this->LocalGenerator->IssueMessage(MessageType::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");
@@ -665,29 +808,30 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
default:
break;
}
- if (const char* cflags = sf->GetProperty("COMPILE_FLAGS")) {
- cmGeneratorExpression ge;
- std::string configName = "NO-PER-CONFIG-SUPPORT-IN-XCODE";
- CM_AUTO_PTR<cmCompiledGeneratorExpression> compiledExpr = ge.Parse(cflags);
- const char* processed = compiledExpr->Evaluate(lg, configName);
- 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).c_str(),
+ true);
+ }
+
+ if (sf->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) {
+ this->AppendDefines(flagsBuild, "CMAKE_SKIP_PRECOMPILE_HEADERS", true);
+ }
+
if (!flagsBuild.IsEmpty()) {
if (!flags.empty()) {
flags += ' ';
@@ -695,10 +839,18 @@ 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);
+ this->CreateXCodeSourceFileFromPath(sf->ResolveFullPath(), gtgt, lang, sf);
cmXCodeObject* settings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
settings->AddAttributeIfNotEmpty("COMPILER_FLAGS",
@@ -724,13 +876,11 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
const char* extraFileAttributes = sf->GetProperty("XCODE_FILE_ATTRIBUTES");
if (extraFileAttributes) {
// Expand the list of attributes.
- std::vector<std::string> attributes;
- cmSystemTools::ExpandListArgument(extraFileAttributes, attributes);
+ std::vector<std::string> attributes = cmExpandedList(extraFileAttributes);
// 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));
}
}
@@ -740,6 +890,19 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
return buildFile;
}
+void cmGlobalXCodeGenerator::AddXCodeProjBuildRule(
+ cmGeneratorTarget* target, std::vector<cmSourceFile*>& sources) const
+{
+ std::string listfile =
+ cmStrCat(target->GetLocalGenerator()->GetCurrentSourceDirectory(),
+ "/CMakeLists.txt");
+ cmSourceFile* srcCMakeLists = target->Makefile->GetOrCreateSource(
+ listfile, false, cmSourceFileLocationKind::Known);
+ if (!cmContains(sources, srcCMakeLists)) {
+ sources.push_back(srcCMakeLists);
+ }
+}
+
std::string GetSourcecodeValueFromFileExtension(const std::string& _ext,
const std::string& lang,
bool& keepLastKnownFileType)
@@ -779,6 +942,10 @@ std::string GetSourcecodeValueFromFileExtension(const std::string& _ext,
sourcecode += ".cpp.cpp";
} else if (lang == "C") {
sourcecode += ".c.c";
+ } else if (lang == "OBJCXX") {
+ sourcecode += ".cpp.objcpp";
+ } else if (lang == "OBJC") {
+ sourcecode += ".c.objc";
} else if (lang == "Fortran") {
sourcecode += ".fortran.f90";
} else if (lang == "ASM") {
@@ -852,11 +1019,10 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath(
this->CreateString(fileType));
// Store the file path relative to the top of the source tree.
- std::string path = this->RelativeToSource(fullpath.c_str());
+ std::string path = this->RelativeToSource(fullpath);
std::string name = cmSystemTools::GetFilenameName(path);
const char* sourceTree =
- (cmSystemTools::FileIsFullPath(path.c_str()) ? "<absolute>"
- : "SOURCE_ROOT");
+ cmSystemTools::FileIsFullPath(path) ? "<absolute>" : "SOURCE_ROOT";
fileRef->AddAttribute("name", this->CreateString(name));
fileRef->AddAttribute("path", this->CreateString(path));
fileRef->AddAttribute("sourceTree", this->CreateString(sourceTree));
@@ -868,7 +1034,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReference(
{
std::string lang = this->CurrentLocalGenerator->GetSourceFileLanguage(*sf);
- return this->CreateXCodeFileReferenceFromPath(sf->GetFullPath(), target,
+ return this->CreateXCodeFileReferenceFromPath(sf->ResolveFullPath(), target,
lang, sf);
}
@@ -895,7 +1061,7 @@ void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator* gen)
this->CurrentConfigurationTypes.clear();
this->CurrentMakefile->GetConfigurations(this->CurrentConfigurationTypes);
if (this->CurrentConfigurationTypes.empty()) {
- this->CurrentConfigurationTypes.push_back("");
+ this->CurrentConfigurationTypes.emplace_back();
}
}
@@ -903,21 +1069,23 @@ struct cmSourceFilePathCompare
{
bool operator()(cmSourceFile* l, cmSourceFile* r)
{
- return l->GetFullPath() < r->GetFullPath();
+ return l->ResolveFullPath() < r->ResolveFullPath();
}
};
struct cmCompareTargets
{
- bool operator()(std::string const& a, std::string const& b) const
+ bool operator()(cmXCodeObject* l, cmXCodeObject* r) const
{
+ std::string const& a = l->GetTarget()->GetName();
+ std::string const& b = r->GetTarget()->GetName();
if (a == "ALL_BUILD") {
return true;
}
if (b == "ALL_BUILD") {
return false;
}
- return strcmp(a.c_str(), b.c_str()) < 0;
+ return a < b;
}
};
@@ -925,298 +1093,282 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
cmLocalGenerator* gen, std::vector<cmXCodeObject*>& targets)
{
this->SetCurrentLocalGenerator(gen);
- std::vector<cmGeneratorTarget*> tgts =
+ std::vector<cmGeneratorTarget*> gts =
this->CurrentLocalGenerator->GetGeneratorTargets();
- typedef std::map<std::string, cmGeneratorTarget*, cmCompareTargets>
- cmSortedTargets;
- cmSortedTargets sortedTargets;
- for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin();
- l != tgts.end(); l++) {
- sortedTargets[(*l)->GetName()] = *l;
+ std::sort(gts.begin(), gts.end(),
+ [this](cmGeneratorTarget const* l, cmGeneratorTarget const* r) {
+ return this->TargetOrderIndex[l] < this->TargetOrderIndex[r];
+ });
+ for (auto gtgt : gts) {
+ if (!this->CreateXCodeTarget(gtgt, targets)) {
+ return false;
+ }
}
- for (cmSortedTargets::iterator l = sortedTargets.begin();
- l != sortedTargets.end(); l++) {
- cmGeneratorTarget* gtgt = l->second;
-
- std::string targetName = gtgt->GetName();
+ std::sort(targets.begin(), targets.end(), cmCompareTargets());
+ return true;
+}
- // make sure ALL_BUILD, INSTALL, etc are only done once
- if (this->SpecialTargetEmitted(targetName)) {
- continue;
- }
+bool cmGlobalXCodeGenerator::CreateXCodeTarget(
+ cmGeneratorTarget* gtgt, std::vector<cmXCodeObject*>& targets)
+{
+ std::string targetName = gtgt->GetName();
- if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
- continue;
- }
+ // make sure ALL_BUILD, INSTALL, etc are only done once
+ if (this->SpecialTargetEmitted(targetName)) {
+ return true;
+ }
- if (gtgt->GetType() == cmStateEnums::UTILITY ||
- gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) {
- cmXCodeObject* t = this->CreateUtilityTarget(gtgt);
- if (!t) {
- return false;
- }
- targets.push_back(t);
- continue;
- }
+ if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return true;
+ }
- // organize the sources
- std::vector<cmSourceFile*> classes;
- if (!gtgt->GetConfigCommonSourceFiles(classes)) {
+ if (gtgt->GetType() == cmStateEnums::UTILITY ||
+ gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) {
+ cmXCodeObject* t = this->CreateUtilityTarget(gtgt);
+ if (!t) {
return false;
}
- std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
+ targets.push_back(t);
+ return true;
+ }
- gtgt->ComputeObjectMapping();
+ // organize the sources
+ std::vector<cmSourceFile*> classes;
+ if (!gtgt->GetConfigCommonSourceFiles(classes)) {
+ return false;
+ }
- std::vector<cmXCodeObject*> externalObjFiles;
- 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);
- cmXCodeObject* fr = xsf->GetObject("fileRef");
- cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType");
+ // Add CMakeLists.txt file for user convenience.
+ this->AddXCodeProjBuildRule(gtgt, classes);
- cmGeneratorTarget::SourceFileFlags tsFlags =
- gtgt->GetTargetSourceFileFlags(*i);
+ // Add the Info.plist we are about to generate for an App Bundle.
+ if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) {
+ std::string plist = this->ComputeInfoPListLocation(gtgt);
+ cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(
+ plist, true, cmSourceFileLocationKind::Known);
+ classes.push_back(sf);
+ }
- if (filetype && filetype->GetString() == "compiled.mach-o.objfile") {
- if ((*i)->GetObjectLibrary().empty()) {
- externalObjFiles.push_back(xsf);
- }
- } else if (this->IsHeaderFile(*i) ||
- (tsFlags.Type ==
- cmGeneratorTarget::SourceFileTypePrivateHeader) ||
- (tsFlags.Type ==
- cmGeneratorTarget::SourceFileTypePublicHeader)) {
- headerFiles.push_back(xsf);
- } else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) {
- resourceFiles.push_back(xsf);
- } else if (!(*i)->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())) {
- sourceFiles.push_back(xsf);
- }
- }
- }
+ std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
- if (this->XcodeVersion < 50) {
- // Add object library contents as external objects. (Equivalent to
- // the externalObjFiles above, except each one is not a cmSourceFile
- // 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()) {
- continue;
- }
- std::string const& obj = (*oi)->GetFullPath();
- cmXCodeObject* xsf =
- this->CreateXCodeSourceFileFromPath(obj, gtgt, "", 0);
- externalObjFiles.push_back(xsf);
- }
- }
+ gtgt->ComputeObjectMapping();
- // some build phases only apply to bundles and/or frameworks
- bool isFrameworkTarget = gtgt->IsFrameworkOnApple();
- bool isBundleTarget = gtgt->GetPropertyAsBool("MACOSX_BUNDLE");
- bool isCFBundleTarget = gtgt->IsCFBundleOnApple();
+ std::vector<cmXCodeObject*> externalObjFiles;
+ std::vector<cmXCodeObject*> headerFiles;
+ std::vector<cmXCodeObject*> resourceFiles;
+ std::vector<cmXCodeObject*> sourceFiles;
+ for (auto sourceFile : classes) {
+ cmXCodeObject* xsf = this->CreateXCodeSourceFile(
+ this->CurrentLocalGenerator, sourceFile, gtgt);
+ cmXCodeObject* fr = xsf->GetObject("fileRef");
+ cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType");
- cmXCodeObject* buildFiles = 0;
+ cmGeneratorTarget::SourceFileFlags tsFlags =
+ gtgt->GetTargetSourceFileFlags(sourceFile);
- // create source build phase
- cmXCodeObject* sourceBuildPhase = 0;
- if (!sourceFiles.empty()) {
- sourceBuildPhase =
- this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase);
- sourceBuildPhase->SetComment("Sources");
- sourceBuildPhase->AddAttribute("buildActionMask",
- this->CreateString("2147483647"));
- buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- for (std::vector<cmXCodeObject*>::iterator i = sourceFiles.begin();
- i != sourceFiles.end(); ++i) {
- buildFiles->AddObject(*i);
+ if (filetype && filetype->GetString() == "compiled.mach-o.objfile") {
+ if (sourceFile->GetObjectLibrary().empty()) {
+ externalObjFiles.push_back(xsf);
+ }
+ } else if (this->IsHeaderFile(sourceFile) ||
+ (tsFlags.Type ==
+ cmGeneratorTarget::SourceFileTypePrivateHeader) ||
+ (tsFlags.Type ==
+ cmGeneratorTarget::SourceFileTypePublicHeader)) {
+ headerFiles.push_back(xsf);
+ } else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) {
+ resourceFiles.push_back(xsf);
+ } else if (!sourceFile->GetPropertyAsBool("HEADER_FILE_ONLY") &&
+ !gtgt->IsSourceFilePartOfUnityBatch(
+ sourceFile->ResolveFullPath())) {
+ // 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(*sourceFile)
+ .empty() &&
+ !this->IgnoreFile(sourceFile->GetExtension().c_str())) {
+ sourceFiles.push_back(xsf);
}
- sourceBuildPhase->AddAttribute("files", buildFiles);
- sourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
}
+ }
- // create header build phase - only for framework targets
- cmXCodeObject* headerBuildPhase = 0;
- if (!headerFiles.empty() && isFrameworkTarget) {
- headerBuildPhase =
- this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase);
- headerBuildPhase->SetComment("Headers");
- headerBuildPhase->AddAttribute("buildActionMask",
+ // some build phases only apply to bundles and/or frameworks
+ bool isFrameworkTarget = gtgt->IsFrameworkOnApple();
+ bool isBundleTarget = gtgt->GetPropertyAsBool("MACOSX_BUNDLE");
+ bool isCFBundleTarget = gtgt->IsCFBundleOnApple();
+
+ cmXCodeObject* buildFiles = nullptr;
+
+ // create source build phase
+ cmXCodeObject* sourceBuildPhase = nullptr;
+ if (!sourceFiles.empty()) {
+ sourceBuildPhase = this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase);
+ sourceBuildPhase->SetComment("Sources");
+ sourceBuildPhase->AddAttribute("buildActionMask",
+ this->CreateString("2147483647"));
+ buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ for (auto& sourceFile : sourceFiles) {
+ buildFiles->AddObject(sourceFile);
+ }
+ sourceBuildPhase->AddAttribute("files", buildFiles);
+ sourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+ this->CreateString("0"));
+ }
+
+ // create header build phase - only for framework targets
+ cmXCodeObject* headerBuildPhase = nullptr;
+ if (!headerFiles.empty() && isFrameworkTarget) {
+ headerBuildPhase = this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase);
+ headerBuildPhase->SetComment("Headers");
+ headerBuildPhase->AddAttribute("buildActionMask",
+ this->CreateString("2147483647"));
+ buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ for (auto& headerFile : headerFiles) {
+ buildFiles->AddObject(headerFile);
+ }
+ headerBuildPhase->AddAttribute("files", buildFiles);
+ headerBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+ this->CreateString("0"));
+ }
+
+ // create resource build phase - only for framework or bundle targets
+ cmXCodeObject* resourceBuildPhase = nullptr;
+ if (!resourceFiles.empty() &&
+ (isFrameworkTarget || isBundleTarget || isCFBundleTarget)) {
+ resourceBuildPhase =
+ this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase);
+ resourceBuildPhase->SetComment("Resources");
+ resourceBuildPhase->AddAttribute("buildActionMask",
this->CreateString("2147483647"));
- buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- for (std::vector<cmXCodeObject*>::iterator i = headerFiles.begin();
- i != headerFiles.end(); ++i) {
- buildFiles->AddObject(*i);
- }
- headerBuildPhase->AddAttribute("files", buildFiles);
- headerBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
+ buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ for (auto& resourceFile : resourceFiles) {
+ buildFiles->AddObject(resourceFile);
}
+ resourceBuildPhase->AddAttribute("files", buildFiles);
+ resourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+ this->CreateString("0"));
+ }
- // create resource build phase - only for framework or bundle targets
- cmXCodeObject* resourceBuildPhase = 0;
- if (!resourceFiles.empty() &&
- (isFrameworkTarget || isBundleTarget || isCFBundleTarget)) {
- resourceBuildPhase =
- this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase);
- resourceBuildPhase->SetComment("Resources");
- resourceBuildPhase->AddAttribute("buildActionMask",
- this->CreateString("2147483647"));
- buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- for (std::vector<cmXCodeObject*>::iterator i = resourceFiles.begin();
- i != resourceFiles.end(); ++i) {
- buildFiles->AddObject(*i);
+ // create vector of "non-resource content file" build phases - only for
+ // framework or bundle targets
+ std::vector<cmXCodeObject*> contentBuildPhases;
+ if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) {
+ using mapOfVectorOfSourceFiles =
+ std::map<std::string, std::vector<cmSourceFile*>>;
+ mapOfVectorOfSourceFiles bundleFiles;
+ for (auto sourceFile : classes) {
+ cmGeneratorTarget::SourceFileFlags tsFlags =
+ gtgt->GetTargetSourceFileFlags(sourceFile);
+ if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) {
+ bundleFiles[tsFlags.MacFolder].push_back(sourceFile);
}
- resourceBuildPhase->AddAttribute("files", buildFiles);
- resourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
- }
-
- // create vector of "non-resource content file" build phases - only for
- // framework or bundle targets
- std::vector<cmXCodeObject*> contentBuildPhases;
- if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) {
- typedef std::map<std::string, std::vector<cmSourceFile*> >
- mapOfVectorOfSourceFiles;
- mapOfVectorOfSourceFiles bundleFiles;
- for (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
- i != classes.end(); ++i) {
- cmGeneratorTarget::SourceFileFlags tsFlags =
- gtgt->GetTargetSourceFileFlags(*i);
- if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) {
- bundleFiles[tsFlags.MacFolder].push_back(*i);
+ }
+ for (auto const& keySources : bundleFiles) {
+ cmXCodeObject* copyFilesBuildPhase =
+ this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
+ copyFilesBuildPhase->SetComment("Copy files");
+ copyFilesBuildPhase->AddAttribute("buildActionMask",
+ this->CreateString("2147483647"));
+ copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
+ this->CreateString("6"));
+ std::ostringstream ostr;
+ if (gtgt->IsFrameworkOnApple()) {
+ // dstPath in frameworks is relative to Versions/<version>
+ 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 << "../" << keySources.first;
}
}
- mapOfVectorOfSourceFiles::iterator mit;
- for (mit = bundleFiles.begin(); mit != bundleFiles.end(); ++mit) {
- cmXCodeObject* copyFilesBuildPhase =
- this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
- copyFilesBuildPhase->SetComment("Copy files");
- copyFilesBuildPhase->AddAttribute("buildActionMask",
- this->CreateString("2147483647"));
- copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
- this->CreateString("6"));
- 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;
- } else {
- // dstPath in bundles is relative to Contents/MacOS
- ostr << "../" << mit->first;
- }
- }
- copyFilesBuildPhase->AddAttribute("dstPath",
- this->CreateString(ostr.str()));
- 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) {
- cmXCodeObject* xsf = this->CreateXCodeSourceFile(
- this->CurrentLocalGenerator, *sfIt, gtgt);
- buildFiles->AddObject(xsf);
- }
- contentBuildPhases.push_back(copyFilesBuildPhase);
+ copyFilesBuildPhase->AddAttribute("dstPath",
+ this->CreateString(ostr.str()));
+ copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+ this->CreateString("0"));
+ buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ copyFilesBuildPhase->AddAttribute("files", buildFiles);
+ for (auto sourceFile : keySources.second) {
+ cmXCodeObject* xsf = this->CreateXCodeSourceFile(
+ this->CurrentLocalGenerator, sourceFile, gtgt);
+ buildFiles->AddObject(xsf);
}
+ contentBuildPhases.push_back(copyFilesBuildPhase);
}
+ }
- // create vector of "resource content file" build phases - only for
- // framework or bundle targets
- if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) {
- typedef std::map<std::string, std::vector<cmSourceFile*> >
- mapOfVectorOfSourceFiles;
- mapOfVectorOfSourceFiles bundleFiles;
- for (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
- i != classes.end(); ++i) {
- cmGeneratorTarget::SourceFileFlags tsFlags =
- gtgt->GetTargetSourceFileFlags(*i);
- if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) {
- bundleFiles[tsFlags.MacFolder].push_back(*i);
- }
- }
- mapOfVectorOfSourceFiles::iterator mit;
- for (mit = bundleFiles.begin(); mit != bundleFiles.end(); ++mit) {
- cmXCodeObject* copyFilesBuildPhase =
- this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
- copyFilesBuildPhase->SetComment("Copy files");
- copyFilesBuildPhase->AddAttribute("buildActionMask",
- this->CreateString("2147483647"));
- copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
- this->CreateString("7"));
- copyFilesBuildPhase->AddAttribute("dstPath",
- this->CreateString(mit->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) {
- cmXCodeObject* xsf = this->CreateXCodeSourceFile(
- this->CurrentLocalGenerator, *sfIt, gtgt);
- buildFiles->AddObject(xsf);
- }
- contentBuildPhases.push_back(copyFilesBuildPhase);
+ // create vector of "resource content file" build phases - only for
+ // framework or bundle targets
+ if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) {
+ using mapOfVectorOfSourceFiles =
+ std::map<std::string, std::vector<cmSourceFile*>>;
+ mapOfVectorOfSourceFiles bundleFiles;
+ for (auto sourceFile : classes) {
+ cmGeneratorTarget::SourceFileFlags tsFlags =
+ gtgt->GetTargetSourceFileFlags(sourceFile);
+ if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) {
+ bundleFiles[tsFlags.MacFolder].push_back(sourceFile);
}
}
-
- // create framework build phase
- cmXCodeObject* frameworkBuildPhase = 0;
- if (!externalObjFiles.empty()) {
- frameworkBuildPhase =
- this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase);
- frameworkBuildPhase->SetComment("Frameworks");
- frameworkBuildPhase->AddAttribute("buildActionMask",
+ for (auto const& keySources : bundleFiles) {
+ cmXCodeObject* copyFilesBuildPhase =
+ this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
+ copyFilesBuildPhase->SetComment("Copy files");
+ copyFilesBuildPhase->AddAttribute("buildActionMask",
this->CreateString("2147483647"));
+ copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
+ this->CreateString("7"));
+ copyFilesBuildPhase->AddAttribute("dstPath",
+ this->CreateString(keySources.first));
+ copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+ this->CreateString("0"));
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- frameworkBuildPhase->AddAttribute("files", buildFiles);
- for (std::vector<cmXCodeObject*>::iterator i = externalObjFiles.begin();
- i != externalObjFiles.end(); ++i) {
- buildFiles->AddObject(*i);
+ copyFilesBuildPhase->AddAttribute("files", buildFiles);
+ for (auto sourceFile : keySources.second) {
+ cmXCodeObject* xsf = this->CreateXCodeSourceFile(
+ this->CurrentLocalGenerator, sourceFile, gtgt);
+ buildFiles->AddObject(xsf);
}
- frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
+ contentBuildPhases.push_back(copyFilesBuildPhase);
}
+ }
- // create list of build phases and create the Xcode target
- cmXCodeObject* buildPhases =
- this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ // create framework build phase
+ cmXCodeObject* frameworkBuildPhase = nullptr;
+ if (!externalObjFiles.empty()) {
+ frameworkBuildPhase =
+ this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase);
+ frameworkBuildPhase->SetComment("Frameworks");
+ frameworkBuildPhase->AddAttribute("buildActionMask",
+ this->CreateString("2147483647"));
+ buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ frameworkBuildPhase->AddAttribute("files", buildFiles);
+ for (auto& externalObjFile : externalObjFiles) {
+ buildFiles->AddObject(externalObjFile);
+ }
+ frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+ this->CreateString("0"));
+ }
- this->CreateCustomCommands(buildPhases, sourceBuildPhase, headerBuildPhase,
- resourceBuildPhase, contentBuildPhases,
- frameworkBuildPhase, gtgt);
+ // create list of build phases and create the Xcode target
+ cmXCodeObject* buildPhases = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- targets.push_back(this->CreateXCodeTarget(gtgt, buildPhases));
- }
+ this->CreateCustomCommands(buildPhases, sourceBuildPhase, headerBuildPhase,
+ resourceBuildPhase, contentBuildPhases,
+ frameworkBuildPhase, gtgt);
+
+ targets.push_back(this->CreateXCodeTarget(gtgt, buildPhases));
return true;
}
void cmGlobalXCodeGenerator::ForceLinkerLanguages()
{
- for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
- std::vector<cmGeneratorTarget*> tgts =
- this->LocalGenerators[i]->GetGeneratorTargets();
+ for (auto localGenerator : this->LocalGenerators) {
// All targets depend on the build-system check target.
- for (std::vector<cmGeneratorTarget*>::const_iterator ti = tgts.begin();
- ti != tgts.end(); ++ti) {
+ for (auto tgt : localGenerator->GetGeneratorTargets()) {
// This makes sure all targets link using the proper language.
- this->ForceLinkerLanguage(*ti);
+ this->ForceLinkerLanguage(tgt);
}
}
}
@@ -1236,10 +1388,9 @@ 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 (std::vector<std::string>::const_iterator li = impl->Languages.begin();
- li != impl->Languages.end(); ++li) {
- if (*li == llang) {
+ for (auto const& Language :
+ gtgt->GetLinkImplementation("NOCONFIG")->Languages) {
+ if (Language == llang) {
return;
}
}
@@ -1248,15 +1399,11 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt)
// linker language. This should convince Xcode to choose the proper
// language.
cmMakefile* mf = gtgt->Target->GetMakefile();
- std::string fname = gtgt->GetLocalGenerator()->GetCurrentBinaryDirectory();
- fname += cmake::GetCMakeFilesDirectory();
- fname += "/";
- fname += gtgt->GetName();
- fname += "-CMakeForceLinker";
- fname += ".";
- fname += cmSystemTools::LowerCase(llang);
+ std::string fname = cmStrCat(
+ gtgt->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/CMakeFiles/",
+ gtgt->GetName(), "-CMakeForceLinker.", cmSystemTools::LowerCase(llang));
{
- cmGeneratedFileStream fout(fname.c_str());
+ cmGeneratedFileStream fout(fname);
fout << "\n";
}
if (cmSourceFile* sf = mf->GetOrCreateSource(fname)) {
@@ -1267,18 +1414,16 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt)
bool cmGlobalXCodeGenerator::IsHeaderFile(cmSourceFile* sf)
{
- const std::vector<std::string>& hdrExts =
- this->CMakeInstance->GetHeaderExtensions();
- return (std::find(hdrExts.begin(), hdrExts.end(), sf->GetExtension()) !=
- hdrExts.end());
+ return cmContains(this->CMakeInstance->GetHeaderExtensions(),
+ sf->GetExtension());
}
cmXCodeObject* cmGlobalXCodeGenerator::CreateBuildPhase(
const char* name, const char* name2, cmGeneratorTarget* target,
const std::vector<cmCustomCommand>& commands)
{
- if (commands.size() == 0 && strcmp(name, "CMake ReRun") != 0) {
- return 0;
+ if (commands.empty() && strcmp(name, "CMake ReRun") != 0) {
+ return nullptr;
}
cmXCodeObject* buildPhase =
this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase);
@@ -1297,7 +1442,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateBuildPhase(
void cmGlobalXCodeGenerator::CreateCustomCommands(
cmXCodeObject* buildPhases, cmXCodeObject* sourceBuildPhase,
cmXCodeObject* headerBuildPhase, cmXCodeObject* resourceBuildPhase,
- std::vector<cmXCodeObject*> contentBuildPhases,
+ std::vector<cmXCodeObject*> const& contentBuildPhases,
cmXCodeObject* frameworkBuildPhase, cmGeneratorTarget* gtgt)
{
std::vector<cmCustomCommand> const& prebuild = gtgt->GetPreBuildCommands();
@@ -1306,23 +1451,14 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
if (gtgt->GetType() == cmStateEnums::SHARED_LIBRARY &&
!gtgt->IsFrameworkOnApple()) {
- cmCustomCommandLines cmd;
- cmd.resize(1);
- cmd[0].push_back(cmSystemTools::GetCMakeCommand());
- cmd[0].push_back("-E");
- cmd[0].push_back("cmake_symlink_library");
- std::string str_file = "$<TARGET_FILE:";
- str_file += gtgt->GetName();
- str_file += ">";
- std::string str_so_file = "$<TARGET_SONAME_FILE:";
- str_so_file += gtgt->GetName();
- str_so_file += ">";
- std::string str_link_file = "$<TARGET_LINKER_FILE:";
- str_link_file += gtgt->GetName();
- str_link_file += ">";
- cmd[0].push_back(str_file);
- cmd[0].push_back(str_so_file);
- cmd[0].push_back(str_link_file);
+ std::string str_file = cmStrCat("$<TARGET_FILE:", gtgt->GetName(), '>');
+ std::string str_so_file =
+ cmStrCat("$<TARGET_SONAME_FILE:", gtgt->GetName(), '>');
+ std::string str_link_file =
+ cmStrCat("$<TARGET_LINKER_FILE:", gtgt->GetName(), '>');
+ cmCustomCommandLines cmd = cmMakeSingleCommandLine(
+ { cmSystemTools::GetCMakeCommand(), "-E", "cmake_symlink_library",
+ str_file, str_so_file, str_link_file });
cmCustomCommand command(this->CurrentMakefile, std::vector<std::string>(),
std::vector<std::string>(),
@@ -1338,10 +1474,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
@@ -1373,10 +1508,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);
@@ -1438,7 +1571,7 @@ std::string cmGlobalXCodeGenerator::ExtractFlagRegex(const char* exp,
std::string::size_type offset = 0;
- while (regex.find(flags.c_str() + offset)) {
+ while (regex.find(&flags[offset])) {
const std::string::size_type startPos = offset + regex.start(matchIndex);
const std::string::size_type endPos = offset + regex.end(matchIndex);
const std::string::size_type size = endPos - startPos;
@@ -1465,7 +1598,7 @@ void cmGlobalXCodeGenerator::FilterConfigurationAttribute(
return;
}
- std::string::size_type endVariant = attribute.find("]", beginVariant + 9);
+ std::string::size_type endVariant = attribute.find(']', beginVariant + 9);
if (endVariant == std::string::npos) {
// There is no terminating bracket.
return;
@@ -1489,32 +1622,23 @@ void cmGlobalXCodeGenerator::AddCommandsToBuildPhase(
cmXCodeObject* buildphase, cmGeneratorTarget* target,
std::vector<cmCustomCommand> const& commands, const char* name)
{
- std::string dir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory();
- dir += "/CMakeScripts";
- cmSystemTools::MakeDirectory(dir.c_str());
- std::string makefile = dir;
- makefile += "/";
- makefile += target->GetName();
- makefile += "_";
- makefile += name;
- makefile += ".make";
-
- for (std::vector<std::string>::const_iterator currentConfig =
- this->CurrentConfigurationTypes.begin();
- currentConfig != this->CurrentConfigurationTypes.end();
- currentConfig++) {
+ std::string dir = cmStrCat(
+ this->CurrentLocalGenerator->GetCurrentBinaryDirectory(), "/CMakeScripts");
+ cmSystemTools::MakeDirectory(dir);
+ std::string makefile =
+ cmStrCat(dir, '/', target->GetName(), '_', name, ".make");
+
+ for (const auto& currentConfig : this->CurrentConfigurationTypes) {
this->CreateCustomRulesMakefile(makefile.c_str(), target, commands,
- *currentConfig);
+ currentConfig);
}
std::string cdir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory();
- cdir = this->ConvertToRelativeForMake(cdir.c_str());
- std::string makecmd = "make -C ";
- makecmd += cdir;
- makecmd += " -f ";
- makecmd +=
- this->ConvertToRelativeForMake((makefile + "$CONFIGURATION").c_str());
- makecmd += " all";
+ cdir = this->ConvertToRelativeForMake(cdir);
+ std::string makecmd =
+ cmStrCat("make -C ", cdir, " -f ",
+ this->ConvertToRelativeForMake((makefile + "$CONFIGURATION")),
+ " OBJDIR=$(basename \"$OBJECT_FILE_DIR_normal\") all");
buildphase->AddAttribute("shellScript", this->CreateString(makecmd));
buildphase->AddAttribute("showEnvVarsInLog", this->CreateString("0"));
}
@@ -1523,9 +1647,8 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
const char* makefileBasename, cmGeneratorTarget* target,
std::vector<cmCustomCommand> const& commands, const std::string& configName)
{
- std::string makefileName = makefileBasename;
- makefileName += configName;
- cmGeneratedFileStream makefileStream(makefileName.c_str());
+ std::string makefileName = cmStrCat(makefileBasename, configName);
+ cmGeneratedFileStream makefileStream(makefileName);
if (!makefileStream) {
return;
}
@@ -1541,38 +1664,35 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
makefileStream << "all: ";
std::map<const cmCustomCommand*, std::string> tname;
int count = 0;
- for (std::vector<cmCustomCommand>::const_iterator i = commands.begin();
- i != commands.end(); ++i) {
- cmCustomCommandGenerator ccg(*i, configName, this->CurrentLocalGenerator);
+ for (auto const& command : commands) {
+ cmCustomCommandGenerator ccg(command, configName,
+ this->CurrentLocalGenerator);
if (ccg.GetNumberOfCommands() > 0) {
const std::vector<std::string>& outputs = ccg.GetOutputs();
if (!outputs.empty()) {
- for (std::vector<std::string>::const_iterator o = outputs.begin();
- o != outputs.end(); ++o) {
- makefileStream << "\\\n\t"
- << this->ConvertToRelativeForMake(o->c_str());
+ for (auto const& output : outputs) {
+ makefileStream << "\\\n\t" << this->ConvertToRelativeForMake(output);
}
} else {
std::ostringstream str;
str << "_buildpart_" << count++;
- tname[&ccg.GetCC()] = std::string(target->GetName()) + str.str();
+ tname[&ccg.GetCC()] = target->GetName() + str.str();
makefileStream << "\\\n\t" << tname[&ccg.GetCC()];
}
}
}
makefileStream << "\n\n";
- for (std::vector<cmCustomCommand>::const_iterator i = commands.begin();
- i != commands.end(); ++i) {
- cmCustomCommandGenerator ccg(*i, configName, this->CurrentLocalGenerator);
+ for (auto const& command : commands) {
+ cmCustomCommandGenerator ccg(command, configName,
+ this->CurrentLocalGenerator);
if (ccg.GetNumberOfCommands() > 0) {
makefileStream << "\n";
const std::vector<std::string>& outputs = ccg.GetOutputs();
if (!outputs.empty()) {
// There is at least one output, start the rule for it
const char* sep = "";
- for (std::vector<std::string>::const_iterator oi = outputs.begin();
- oi != outputs.end(); ++oi) {
- makefileStream << sep << this->ConvertToRelativeForMake(oi->c_str());
+ for (auto const& output : outputs) {
+ makefileStream << sep << this->ConvertToRelativeForMake(output);
sep = " ";
}
makefileStream << ": ";
@@ -1580,22 +1700,20 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
// There are no outputs. Use the generated force rule name.
makefileStream << tname[&ccg.GetCC()] << ": ";
}
- for (std::vector<std::string>::const_iterator d =
- ccg.GetDepends().begin();
- d != ccg.GetDepends().end(); ++d) {
+ for (auto const& d : ccg.GetDepends()) {
std::string dep;
- if (this->CurrentLocalGenerator->GetRealDependency(*d, configName,
+ if (this->CurrentLocalGenerator->GetRealDependency(d, configName,
dep)) {
- makefileStream << "\\\n"
- << this->ConvertToRelativeForMake(dep.c_str());
+ makefileStream << "\\\n" << this->ConvertToRelativeForMake(dep);
}
}
makefileStream << "\n";
if (const char* comment = ccg.GetComment()) {
- std::string echo_cmd = "echo ";
- echo_cmd += (this->CurrentLocalGenerator->EscapeForShell(
- comment, ccg.GetCC().GetEscapeAllowMakeVars()));
+ std::string echo_cmd =
+ cmStrCat("echo ",
+ (this->CurrentLocalGenerator->EscapeForShell(
+ comment, ccg.GetCC().GetEscapeAllowMakeVars())));
makefileStream << "\t" << echo_cmd << "\n";
}
@@ -1604,12 +1722,12 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
// Build the command line in a single string.
std::string cmd2 = ccg.GetCommand(c);
cmSystemTools::ReplaceString(cmd2, "/./", "/");
- cmd2 = this->ConvertToRelativeForMake(cmd2.c_str());
+ cmd2 = this->ConvertToRelativeForMake(cmd2);
std::string cmd;
std::string wd = ccg.GetWorkingDirectory();
if (!wd.empty()) {
cmd += "cd ";
- cmd += this->ConvertToRelativeForMake(wd.c_str());
+ cmd += this->ConvertToRelativeForMake(wd);
cmd += " && ";
}
cmd += cmd2;
@@ -1620,6 +1738,25 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
}
}
+void cmGlobalXCodeGenerator::AddPositionIndependentLinkAttribute(
+ cmGeneratorTarget* target, cmXCodeObject* buildSettings,
+ const std::string& configName)
+{
+ // For now, only EXECUTABLE is concerned
+ if (target->GetType() != cmStateEnums::EXECUTABLE) {
+ return;
+ }
+
+ const char* PICValue = target->GetLinkPIEProperty(configName);
+ if (PICValue == nullptr) {
+ // POSITION_INDEPENDENT_CODE is not set
+ return;
+ }
+
+ buildSettings->AddAttribute(
+ "LD_NO_PIE", this->CreateString(cmIsOn(PICValue) ? "NO" : "YES"));
+}
+
void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
cmXCodeObject* buildSettings,
const std::string& configName)
@@ -1639,15 +1776,17 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
std::set<std::string> languages;
gtgt->GetLanguages(languages, configName);
std::map<std::string, std::string> cflags;
- for (std::set<std::string>::iterator li = languages.begin();
- li != languages.end(); ++li) {
- std::string const& lang = *li;
+ for (auto const& lang : languages) {
std::string& flags = cflags[lang];
// Add language-specific flags.
this->CurrentLocalGenerator->AddLanguageFlags(flags, gtgt, lang,
configName);
+ if (gtgt->IsIPOEnabled(lang, configName)) {
+ this->CurrentLocalGenerator->AppendFeatureOptions(flags, lang, "IPO");
+ }
+
// Add shared-library flags if needed.
this->CurrentLocalGenerator->AddCMP0018Flags(flags, gtgt, lang,
configName);
@@ -1661,10 +1800,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
std::string llang = gtgt->GetLinkerLanguage(configName);
if (binary && llang.empty()) {
cmSystemTools::Error(
- "CMake can not determine linker language for target: ",
- gtgt->GetName().c_str());
+ "CMake can not determine linker language for target: " +
+ gtgt->GetName());
return;
}
+ std::string const& langForPreprocessor = llang;
if (gtgt->IsIPOEnabled(llang, configName)) {
const char* ltoValue =
@@ -1672,6 +1812,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
buildSettings->AddAttribute("LLVM_LTO", this->CreateString(ltoValue));
}
+ // Handle PIE linker configuration
+ this->AddPositionIndependentLinkAttribute(gtgt, buildSettings, configName);
+
// Add define flags
this->CurrentLocalGenerator->AppendFlags(
defFlags, this->CurrentMakefile->GetDefineFlags());
@@ -1680,12 +1823,15 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
BuildObjectListOrString ppDefs(this, true);
this->AppendDefines(
ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"");
- if (const char* exportMacro = gtgt->GetExportMacro()) {
+ if (const std::string* exportMacro = gtgt->GetExportMacro()) {
// Add the export symbol definition for shared library objects.
- this->AppendDefines(ppDefs, exportMacro);
+ this->AppendDefines(ppDefs, exportMacro->c_str());
}
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());
@@ -1707,7 +1853,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY ||
gtgt->GetType() == cmStateEnums::STATIC_LIBRARY) {
this->CurrentLocalGenerator->GetStaticLibraryFlags(
- extraLinkOptions, cmSystemTools::UpperCase(configName), gtgt);
+ extraLinkOptions, cmSystemTools::UpperCase(configName), llang, gtgt);
} else {
const char* targetLinkFlags = gtgt->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
@@ -1715,12 +1861,16 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
targetLinkFlags);
}
if (!configName.empty()) {
- std::string linkFlagsVar = "LINK_FLAGS_";
- linkFlagsVar += cmSystemTools::UpperCase(configName);
+ std::string linkFlagsVar =
+ cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(configName));
if (const char* linkFlags = gtgt->GetProperty(linkFlagsVar)) {
this->CurrentLocalGenerator->AppendFlags(extraLinkOptions, linkFlags);
}
}
+ std::vector<std::string> opts;
+ gtgt->GetLinkOptions(opts, configName, llang);
+ // LINK_OPTIONS are escaped.
+ this->CurrentLocalGenerator->AppendCompileOptions(extraLinkOptions, opts);
}
// Set target-specific architectures.
@@ -1737,9 +1887,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
} else {
cmXCodeObject* archObjects =
this->CreateObject(cmXCodeObject::OBJECT_LIST);
- for (std::vector<std::string>::iterator i = archs.begin();
- i != archs.end(); i++) {
- archObjects->AddObject(this->CreateString(*i));
+ for (auto& arch : archs) {
+ archObjects->AddObject(this->CreateString(arch));
}
buildSettings->AddAttribute("ARCHS", archObjects);
}
@@ -1754,8 +1903,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
const char* version = gtgt->GetProperty("VERSION");
const char* soversion = gtgt->GetProperty("SOVERSION");
if (!gtgt->HasSOName(configName) || gtgt->IsFrameworkOnApple()) {
- version = 0;
- soversion = 0;
+ version = nullptr;
+ soversion = nullptr;
}
if (version && !soversion) {
soversion = version;
@@ -1799,8 +1948,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
pnbase = gtgt->GetName();
pnsuffix = ".a";
- std::string pncdir =
- this->GetObjectsNormalDirectory(this->CurrentProject, configName, gtgt);
+ std::string pncdir = this->GetObjectsDirectory(
+ this->CurrentProject, configName, gtgt, OBJECT_LIBRARY_ARTIFACT_DIR);
buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
this->CreateString(pncdir));
}
@@ -1827,7 +1976,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// so let it replace the framework name. This avoids creating
// a per-configuration Info.plist file.
this->CurrentLocalGenerator->GenerateFrameworkInfoPList(
- gtgt, "$(EXECUTABLE_NAME)", plist.c_str());
+ gtgt, "$(EXECUTABLE_NAME)", plist);
buildSettings->AddAttribute("INFOPLIST_FILE",
this->CreateString(plist));
buildSettings->AddAttribute("MACH_O_TYPE",
@@ -1868,7 +2017,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// a per-configuration Info.plist file. The cfbundle plist
// is very similar to the application bundle plist
this->CurrentLocalGenerator->GenerateAppleInfoPList(
- gtgt, "$(EXECUTABLE_NAME)", plist.c_str());
+ gtgt, "$(EXECUTABLE_NAME)", plist);
buildSettings->AddAttribute("INFOPLIST_FILE",
this->CreateString(plist));
} else {
@@ -1902,7 +2051,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// so let it replace the framework name. This avoids creating
// a per-configuration Info.plist file.
this->CurrentLocalGenerator->GenerateFrameworkInfoPList(
- gtgt, "$(EXECUTABLE_NAME)", plist.c_str());
+ gtgt, "$(EXECUTABLE_NAME)", plist);
buildSettings->AddAttribute("INFOPLIST_FILE",
this->CreateString(plist));
} else {
@@ -1940,7 +2089,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// so let it replace the executable name. This avoids creating
// a per-configuration Info.plist file.
this->CurrentLocalGenerator->GenerateAppleInfoPList(
- gtgt, "$(EXECUTABLE_NAME)", plist.c_str());
+ gtgt, "$(EXECUTABLE_NAME)", plist);
buildSettings->AddAttribute("INFOPLIST_FILE",
this->CreateString(plist));
}
@@ -1948,9 +2097,6 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
default:
break;
}
- if (this->XcodeVersion < 40) {
- buildSettings->AddAttribute("PREBINDING", this->CreateString("NO"));
- }
BuildObjectListOrString dirs(this, true);
BuildObjectListOrString fdirs(this, true);
@@ -1959,30 +2105,32 @@ 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");
- for (std::vector<std::string>::iterator i = includes.begin();
- i != includes.end(); ++i) {
- if (this->NameResolvesToFramework(*i)) {
- std::string frameworkDir = *i;
- frameworkDir += "/../";
+ for (auto& include : includes) {
+ if (this->NameResolvesToFramework(include)) {
+ std::string frameworkDir = cmStrCat(include, "/../");
frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir);
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);
}
}
} else {
- std::string incpath = this->XCodeEscapePath(*i);
+ std::string incpath = this->XCodeEscapePath(include);
if (emitSystemIncludes &&
- gtgt->IsSystemIncludeDirectory(*i, configName)) {
+ gtgt->IsSystemIncludeDirectory(include, configName,
+ langForPreprocessor)) {
sysdirs.Add(incpath);
} else {
dirs.Add(incpath);
@@ -1991,13 +2139,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 (std::vector<std::string>::const_iterator fdi = fwDirs.begin();
- fdi != fwDirs.end(); ++fdi) {
- if (emitted.insert(*fdi).second) {
- std::string incpath = this->XCodeEscapePath(*fdi);
+ for (auto const& fwDir : cli->GetFrameworkPaths()) {
+ if (emitted.insert(fwDir).second) {
+ std::string incpath = this->XCodeEscapePath(fwDir);
if (emitSystemIncludes &&
- gtgt->IsSystemIncludeDirectory(*fdi, configName)) {
+ gtgt->IsSystemIncludeDirectory(fwDir, configName,
+ langForPreprocessor)) {
sysfdirs.Add(incpath);
} else {
fdirs.Add(incpath);
@@ -2025,27 +2172,25 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// system include directory awareness. We need to also keep on setting
// HEADER_SEARCH_PATHS to work around a missing compile options flag for
// GNU assembly files (#16449)
- for (std::set<std::string>::iterator li = languages.begin();
- li != languages.end(); ++li) {
+ for (auto const& language : languages) {
std::string includeFlags = this->CurrentLocalGenerator->GetIncludeFlags(
- includes, gtgt, *li, true, false, configName);
+ includes, gtgt, language, true, false, configName);
if (!includeFlags.empty()) {
- cflags[*li] += " " + includeFlags;
+ cflags[language] += " " + includeFlags;
}
}
}
bool same_gflags = true;
std::map<std::string, std::string> gflags;
- std::string const* last_gflag = 0;
+ std::string const* last_gflag = nullptr;
std::string optLevel = "0";
// Minimal map of flags to build settings.
- for (std::set<std::string>::iterator li = languages.begin();
- li != languages.end(); ++li) {
- std::string& flags = cflags[*li];
- std::string& gflag = gflags[*li];
+ for (auto const& language : languages) {
+ std::string& flags = cflags[language];
+ std::string& gflag = gflags[language];
std::string oflag =
this->ExtractFlagRegex("(^| )(-Ofast|-Os|-O[0-9]*)( |$)", 2, flags);
if (oflag.size() == 2) {
@@ -2070,16 +2215,34 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
if (!same_gflags) {
// We can't set the Xcode flag differently depending on the language,
// so put them back in this case.
- for (std::set<std::string>::iterator li = languages.begin();
- li != languages.end(); ++li) {
- cflags[*li] += " ";
- cflags[*li] += gflags[*li];
+ for (auto const& language : languages) {
+ cflags[language] += " ";
+ cflags[language] += gflags[language];
}
debugStr = "NO";
} else if (last_gflag && (last_gflag->empty() || *last_gflag == "-g0")) {
debugStr = "NO";
}
+ // extract C++ stdlib
+ for (auto const& language : languages) {
+ if (language != "CXX" && language != "OBJCXX") {
+ continue;
+ }
+ std::string& flags = cflags[language];
+
+ auto stdlib =
+ this->ExtractFlagRegex("(^| )(-stdlib=[^ ]+)( |$)", 2, flags);
+ if (stdlib.size() > 8) {
+ const auto cxxLibrary = stdlib.substr(8);
+ if (language == "CXX" ||
+ !buildSettings->GetObject("CLANG_CXX_LIBRARY")) {
+ buildSettings->AddAttribute("CLANG_CXX_LIBRARY",
+ this->CreateString(cxxLibrary));
+ }
+ }
+ }
+
buildSettings->AddAttribute("COMBINE_HIDPI_IMAGES",
this->CreateString("YES"));
buildSettings->AddAttribute("GCC_GENERATE_DEBUGGING_SYMBOLS",
@@ -2090,25 +2253,30 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
this->CreateString("NO"));
buildSettings->AddAttribute("GCC_INLINES_ARE_PRIVATE_EXTERN",
this->CreateString("NO"));
- for (std::set<std::string>::iterator li = languages.begin();
- li != languages.end(); ++li) {
- std::string flags = cflags[*li] + " " + defFlags;
- if (*li == "CXX") {
- buildSettings->AddAttribute("OTHER_CPLUSPLUSFLAGS",
- this->CreateString(flags));
- } else if (*li == "Fortran") {
+
+ for (auto const& language : languages) {
+ std::string flags = cflags[language] + " " + defFlags;
+ if (language == "CXX" || language == "OBJCXX") {
+ if (language == "CXX" ||
+ !buildSettings->GetObject("OTHER_CPLUSPLUSFLAGS")) {
+ buildSettings->AddAttribute("OTHER_CPLUSPLUSFLAGS",
+ this->CreateString(flags));
+ }
+ } else if (language == "Fortran") {
buildSettings->AddAttribute("IFORT_OTHER_FLAGS",
this->CreateString(flags));
- } else if (*li == "C") {
- buildSettings->AddAttribute("OTHER_CFLAGS", this->CreateString(flags));
- } else if (*li == "Swift") {
+ } else if (language == "C" || language == "OBJC") {
+ if (language == "C" || !buildSettings->GetObject("OTHER_CFLAGS")) {
+ buildSettings->AddAttribute("OTHER_CFLAGS", this->CreateString(flags));
+ }
+ } else if (language == "Swift") {
buildSettings->AddAttribute("OTHER_SWIFT_FLAGS",
this->CreateString(flags));
}
}
// Add Fortran source format attribute if property is set.
- const char* format = 0;
+ const char* format = nullptr;
const char* tgtfmt = gtgt->GetProperty("Fortran_FORMAT");
switch (cmOutputConverter::GetFortranFormat(tgtfmt)) {
case cmOutputConverter::FortranFormatFixed:
@@ -2162,9 +2330,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()) {
@@ -2221,20 +2387,26 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
buildSettings->AddAttribute("DYLIB_COMPATIBILITY_VERSION",
this->CreateString(vso.str()));
}
+
+ // Precompile Headers
+ std::string pchHeader = gtgt->GetPchHeader(configName, llang);
+ if (!pchHeader.empty()) {
+ buildSettings->AddAttribute("GCC_PREFIX_HEADER",
+ this->CreateString(pchHeader));
+ buildSettings->AddAttribute("GCC_PRECOMPILE_PREFIX_HEADER",
+ this->CreateString("YES"));
+ }
+
// put this last so it can override existing settings
// Convert "XCODE_ATTRIBUTE_*" properties directly.
{
- std::vector<std::string> const& props = gtgt->GetPropertyKeys();
- for (std::vector<std::string>::const_iterator i = props.begin();
- i != props.end(); ++i) {
- if (i->find("XCODE_ATTRIBUTE_") == 0) {
- std::string attribute = i->substr(16);
+ for (auto const& prop : gtgt->GetPropertyKeys()) {
+ if (prop.find("XCODE_ATTRIBUTE_") == 0) {
+ std::string attribute = prop.substr(16);
this->FilterConfigurationAttribute(configName, attribute);
if (!attribute.empty()) {
- cmGeneratorExpression ge;
- std::string processed =
- ge.Parse(gtgt->GetProperty(*i))
- ->Evaluate(this->CurrentLocalGenerator, configName);
+ std::string processed = cmGeneratorExpression::Evaluate(
+ gtgt->GetProperty(prop), this->CurrentLocalGenerator, configName);
buildSettings->AddAttribute(attribute,
this->CreateString(processed));
}
@@ -2268,8 +2440,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget(
target->SetComment(gtgt->GetName());
cmXCodeObject* buildPhases = this->CreateObject(cmXCodeObject::OBJECT_LIST);
std::vector<cmXCodeObject*> emptyContentVector;
- this->CreateCustomCommands(buildPhases, 0, 0, 0, emptyContentVector, 0,
- gtgt);
+ this->CreateCustomCommands(buildPhases, nullptr, nullptr, nullptr,
+ emptyContentVector, nullptr, gtgt);
target->AddAttribute("buildPhases", buildPhases);
this->AddConfigurations(target, gtgt);
cmXCodeObject* dependencies = this->CreateObject(cmXCodeObject::OBJECT_LIST);
@@ -2280,16 +2452,19 @@ 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 0;
+ 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.
+ this->AddXCodeProjBuildRule(gtgt, sources);
+
+ for (auto sourceFile : sources) {
+ if (!sourceFile->GetIsGenerated()) {
+ this->CreateXCodeFileReference(sourceFile, gtgt);
}
}
}
@@ -2302,34 +2477,28 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget(
std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target,
cmGeneratorTarget* gtgt)
{
- std::string configTypes =
- this->CurrentMakefile->GetRequiredDefinition("CMAKE_CONFIGURATION_TYPES");
- std::vector<std::string> configVectorIn;
- std::vector<std::string> configVector;
- configVectorIn.push_back(configTypes);
- cmSystemTools::ExpandList(configVectorIn, configVector);
+ std::vector<std::string> const configVector = cmExpandedList(
+ this->CurrentMakefile->GetRequiredDefinition("CMAKE_CONFIGURATION_TYPES"));
cmXCodeObject* configlist =
this->CreateObject(cmXCodeObject::XCConfigurationList);
cmXCodeObject* buildConfigurations =
this->CreateObject(cmXCodeObject::OBJECT_LIST);
configlist->AddAttribute("buildConfigurations", buildConfigurations);
- std::string comment = "Build configuration list for ";
- comment += cmXCodeObject::PBXTypeNames[target->GetIsA()];
- comment += " \"";
- comment += gtgt->GetName();
- comment += "\"";
+ std::string comment = cmStrCat("Build configuration list for ",
+ cmXCodeObject::PBXTypeNames[target->GetIsA()],
+ " \"", gtgt->GetName(), '"');
configlist->SetComment(comment);
target->AddAttribute("buildConfigurationList",
this->CreateObjectReference(configlist));
- for (unsigned int i = 0; i < configVector.size(); ++i) {
+ for (auto const& i : configVector) {
cmXCodeObject* config =
this->CreateObject(cmXCodeObject::XCBuildConfiguration);
buildConfigurations->AddObject(config);
cmXCodeObject* buildSettings =
this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
- this->CreateBuildSettings(gtgt, buildSettings, configVector[i]);
- config->AddAttribute("name", this->CreateString(configVector[i]));
- config->SetComment(configVector[i]);
+ this->CreateBuildSettings(gtgt, buildSettings, i);
+ config->AddAttribute("name", this->CreateString(i));
+ config->SetComment(i);
config->AddAttribute("buildSettings", buildSettings);
}
if (!configVector.empty()) {
@@ -2349,9 +2518,8 @@ const char* cmGlobalXCodeGenerator::GetTargetLinkFlagsVar(
(target->GetType() == cmStateEnums::STATIC_LIBRARY ||
target->GetType() == cmStateEnums::OBJECT_LIBRARY)) {
return "OTHER_LIBTOOLFLAGS";
- } else {
- return "OTHER_LDFLAGS";
}
+ return "OTHER_LDFLAGS";
}
const char* cmGlobalXCodeGenerator::GetTargetFileType(
@@ -2368,12 +2536,13 @@ const char* cmGlobalXCodeGenerator::GetTargetFileType(
return (target->GetPropertyAsBool("FRAMEWORK") ? "wrapper.framework"
: "archive.ar");
case cmStateEnums::MODULE_LIBRARY:
- if (target->IsXCTestOnApple())
+ if (target->IsXCTestOnApple()) {
return "wrapper.cfbundle";
- else if (target->IsCFBundleOnApple())
+ }
+ if (target->IsCFBundleOnApple()) {
return "wrapper.plug-in";
- else
- return "compiled.mach-o.executable";
+ }
+ return "compiled.mach-o.executable";
case cmStateEnums::SHARED_LIBRARY:
return (target->GetPropertyAsBool("FRAMEWORK")
? "wrapper.framework"
@@ -2383,7 +2552,7 @@ const char* cmGlobalXCodeGenerator::GetTargetFileType(
default:
break;
}
- return 0;
+ return nullptr;
}
const char* cmGlobalXCodeGenerator::GetTargetProductType(
@@ -2401,12 +2570,13 @@ const char* cmGlobalXCodeGenerator::GetTargetProductType(
? "com.apple.product-type.framework"
: "com.apple.product-type.library.static");
case cmStateEnums::MODULE_LIBRARY:
- if (target->IsXCTestOnApple())
+ if (target->IsXCTestOnApple()) {
return "com.apple.product-type.bundle.unit-test";
- else if (target->IsCFBundleOnApple())
+ } else if (target->IsCFBundleOnApple()) {
return "com.apple.product-type.bundle";
- else
+ } else {
return "com.apple.product-type.tool";
+ }
case cmStateEnums::SHARED_LIBRARY:
return (target->GetPropertyAsBool("FRAMEWORK")
? "com.apple.product-type.framework"
@@ -2418,14 +2588,14 @@ const char* cmGlobalXCodeGenerator::GetTargetProductType(
default:
break;
}
- return 0;
+ return nullptr;
}
cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeTarget(
cmGeneratorTarget* gtgt, cmXCodeObject* buildPhases)
{
if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
- return 0;
+ return nullptr;
}
cmXCodeObject* target = this->CreateObject(cmXCodeObject::PBXNativeTarget);
target->AddAttribute("buildPhases", buildPhases);
@@ -2444,9 +2614,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeTarget(
}
std::string fullName;
if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- fullName = "lib";
- fullName += gtgt->GetName();
- fullName += ".a";
+ fullName = cmStrCat("lib", gtgt->GetName(), ".a");
} else {
fullName = gtgt->GetFullName(defConfig);
}
@@ -2469,13 +2637,12 @@ cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget(
cmGeneratorTarget const* t)
{
if (!t) {
- return 0;
+ return nullptr;
}
- std::map<cmGeneratorTarget const*, cmXCodeObject*>::const_iterator const i =
- this->XCodeObjectMap.find(t);
+ auto const i = this->XCodeObjectMap.find(t);
if (i == this->XCodeObjectMap.end()) {
- return 0;
+ return nullptr;
}
return i->second;
}
@@ -2483,8 +2650,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget(
std::string cmGlobalXCodeGenerator::GetOrCreateId(const std::string& name,
const std::string& id)
{
- std::string guidStoreName = name;
- guidStoreName += "_GUID_CMAKE";
+ std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE");
const char* storedGUID =
this->CMakeInstance->GetCacheDefinition(guidStoreName);
@@ -2539,9 +2705,7 @@ void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject* settings,
if (!attr) {
settings->AddAttribute(attribute, this->CreateString(value));
} else {
- std::string oldValue = attr->GetString();
- oldValue += " ";
- oldValue += value;
+ std::string oldValue = cmStrCat(attr->GetString(), ' ', value);
attr->SetString(oldValue);
}
}
@@ -2557,18 +2721,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 (std::vector<cmXCodeObject*>::iterator i = list.begin(); i != list.end();
- ++i) {
- 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);
}
}
@@ -2586,35 +2742,27 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
}
// Add dependencies on other CMake targets.
- TargetDependSet const& deps = this->GetTargetDirectDepends(gt);
- for (TargetDependSet::const_iterator i = deps.begin(); i != deps.end();
- ++i) {
- if (cmXCodeObject* dptarget = this->FindXCodeTarget(*i)) {
+ for (const auto& dep : this->GetTargetDirectDepends(gt)) {
+ if (cmXCodeObject* dptarget = this->FindXCodeTarget(dep)) {
this->AddDependTarget(target, dptarget);
}
}
// Loop over configuration types and set per-configuration info.
- for (std::vector<std::string>::iterator i =
- this->CurrentConfigurationTypes.begin();
- i != this->CurrentConfigurationTypes.end(); ++i) {
- // Get the current configuration name.
- std::string configName = *i;
-
- if (this->XcodeVersion >= 50) {
+ for (auto const& configName : this->CurrentConfigurationTypes) {
+ {
// Add object library contents as link flags.
std::string linkObjs;
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);
@@ -2634,28 +2782,22 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
cmComputeLinkInformation& cli = *pcli;
// Add dependencies directly on library files.
- {
- std::vector<std::string> const& libDeps = cli.GetDepends();
- for (std::vector<std::string>::const_iterator j = libDeps.begin();
- j != libDeps.end(); ++j) {
- target->AddDependLibrary(configName, *j);
- }
+ 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 (std::vector<std::string>::const_iterator libDir = libDirs.begin();
- libDir != libDirs.end(); ++libDir) {
- if (libDir->size() && *libDir != "/usr/lib") {
+ 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:
linkDirs += " ";
linkDirs += this->XCodeEscapePath(
- *libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)");
+ libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)");
linkDirs += " ";
- linkDirs += this->XCodeEscapePath(*libDir);
+ linkDirs += this->XCodeEscapePath(libDir);
}
}
this->AppendBuildSettingAttribute(target, "LIBRARY_SEARCH_PATHS",
@@ -2666,20 +2808,18 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
{
std::string linkLibs;
const char* sep = "";
- typedef cmComputeLinkInformation::ItemVector ItemVector;
- ItemVector const& libNames = cli.GetItems();
- for (ItemVector::const_iterator li = libNames.begin();
- li != libNames.end(); ++li) {
+ for (auto const& libName : cli.GetItems()) {
linkLibs += sep;
sep = " ";
- if (li->IsPath) {
- linkLibs += this->XCodeEscapePath(li->Value);
- } else if (!li->Target ||
- li->Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
- linkLibs += li->Value;
+ if (libName.IsPath) {
+ linkLibs += this->XCodeEscapePath(libName.Value);
+ } else if (!libName.Target ||
+ libName.Target->GetType() !=
+ cmStateEnums::INTERFACE_LIBRARY) {
+ linkLibs += libName.Value;
}
- if (li->Target && !li->Target->IsImported()) {
- target->AddDependTarget(configName, li->Target->GetName());
+ if (libName.Target && !libName.Target->IsImported()) {
+ target->AddDependTarget(configName, libName.Target->GetName());
}
}
this->AppendBuildSettingAttribute(
@@ -2691,17 +2831,12 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
bool cmGlobalXCodeGenerator::CreateGroups(
std::vector<cmLocalGenerator*>& generators)
{
- for (std::vector<cmLocalGenerator*>::iterator i = generators.begin();
- i != generators.end(); ++i) {
- cmMakefile* mf = (*i)->GetMakefile();
+ for (auto& generator : generators) {
+ cmMakefile* mf = generator->GetMakefile();
std::vector<cmSourceGroup> sourceGroups = mf->GetSourceGroups();
- std::vector<cmGeneratorTarget*> tgts = (*i)->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin();
- l != tgts.end(); l++) {
- cmGeneratorTarget* gtgt = *l;
-
+ 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) {
@@ -2710,34 +2845,44 @@ bool cmGlobalXCodeGenerator::CreateGroups(
if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
-
- // add the soon to be generated Info.plist file as a source for a
- // MACOSX_BUNDLE file
- if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) {
- std::string plist = this->ComputeInfoPListLocation(gtgt);
- mf->GetOrCreateSource(plist, true);
- gtgt->AddSource(plist);
+ if (gtgt->GetName() == CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
+ continue;
}
- std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
- gtgt->GetAllConfigSources();
+ auto addSourceToGroup = [this, mf, gtgt,
+ &sourceGroups](std::string const& source) {
+ cmSourceGroup* sourceGroup = mf->FindSourceGroup(source, sourceGroups);
+ cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup);
+ std::string key = GetGroupMapKeyFromPath(gtgt, source);
+ this->GroupMap[key] = pbxgroup;
+ };
// Put cmSourceFile instances in proper groups:
- for (std::vector<cmGeneratorTarget::AllConfigSource>::const_iterator si =
- sources.begin();
- si != sources.end(); ++si) {
- cmSourceFile const* sf = si->Source;
- if (this->XcodeVersion >= 50 && !sf->GetObjectLibrary().empty()) {
+ for (auto const& si : gtgt->GetAllConfigSources()) {
+ cmSourceFile const* sf = si.Source;
+ if (!sf->GetObjectLibrary().empty()) {
// Object library files go on the link line instead.
continue;
}
- // Add the file to the list of sources.
- 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;
+ addSourceToGroup(sf->GetFullPath());
+ }
+
+ // Add CMakeLists.txt file for user convenience.
+ {
+ std::string listfile =
+ cmStrCat(gtgt->GetLocalGenerator()->GetCurrentSourceDirectory(),
+ "/CMakeLists.txt");
+ cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(
+ listfile, false, cmSourceFileLocationKind::Known);
+ addSourceToGroup(sf->ResolveFullPath());
+ }
+
+ // Add the Info.plist we are about to generate for an App Bundle.
+ if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) {
+ std::string plist = this->ComputeInfoPListLocation(gtgt);
+ cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(
+ plist, true, cmSourceFileLocationKind::Known);
+ addSourceToGroup(sf->ResolveFullPath());
}
}
}
@@ -2745,19 +2890,21 @@ bool cmGlobalXCodeGenerator::CreateGroups(
}
cmXCodeObject* cmGlobalXCodeGenerator::CreatePBXGroup(cmXCodeObject* parent,
- std::string name)
+ const std::string& name)
{
- cmXCodeObject* parentChildren = NULL;
- if (parent)
+ cmXCodeObject* parentChildren = nullptr;
+ if (parent) {
parentChildren = parent->GetObject("children");
+ }
cmXCodeObject* group = this->CreateObject(cmXCodeObject::PBXGroup);
cmXCodeObject* groupChildren =
this->CreateObject(cmXCodeObject::OBJECT_LIST);
group->AddAttribute("name", this->CreateString(name));
group->AddAttribute("children", groupChildren);
group->AddAttribute("sourceTree", this->CreateString("<group>"));
- if (parentChildren)
+ if (parentChildren) {
parentChildren->AddObject(group);
+ }
return group;
}
@@ -2768,25 +2915,21 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup(
std::string target;
const std::string targetFolder = gtgt->GetEffectiveFolderName();
if (!targetFolder.empty()) {
- target = targetFolder;
- target += "/";
+ target = cmStrCat(targetFolder, '/');
}
target += gtgt->GetName();
- s = target + "/";
- s += sg->GetFullName();
- std::map<std::string, cmXCodeObject*>::iterator it =
- this->GroupNameMap.find(s);
+ s = cmStrCat(target, '/', sg->GetFullName());
+ auto it = this->GroupNameMap.find(s);
if (it != this->GroupNameMap.end()) {
return it->second;
}
it = this->TargetGroup.find(target);
- cmXCodeObject* tgroup = 0;
+ cmXCodeObject* tgroup = nullptr;
if (it != this->TargetGroup.end()) {
tgroup = it->second;
} else {
- std::vector<std::string> tgt_folders =
- cmSystemTools::tokenize(target, "/");
+ std::vector<std::string> tgt_folders = cmTokenize(target, "/");
std::string curr_tgt_folder;
for (std::vector<std::string>::size_type i = 0; i < tgt_folders.size();
i++) {
@@ -2811,30 +2954,26 @@ 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()) == "") {
+ 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(), "\\");
- std::string curr_folder = target;
- curr_folder += "/";
- for (std::vector<std::string>::size_type i = 0; i < folders.size(); i++) {
- curr_folder += folders[i];
- std::map<std::string, cmXCodeObject*>::iterator i_folder =
- this->GroupNameMap.find(curr_folder);
+ if (sg->GetFullName() != sg->GetName()) {
+ std::string curr_folder = cmStrCat(target, '/');
+ for (auto const& folder : cmTokenize(sg->GetFullName(), "\\")) {
+ curr_folder += folder;
+ auto const i_folder = this->GroupNameMap.find(curr_folder);
// Create new folder
if (i_folder == this->GroupNameMap.end()) {
- cmXCodeObject* group = this->CreatePBXGroup(tgroup, folders[i]);
+ cmXCodeObject* group = this->CreatePBXGroup(tgroup, folder);
this->GroupNameMap[curr_folder] = group;
tgroup = group;
} else {
tgroup = i_folder->second;
}
- curr_folder = curr_folder + "\\";
+ curr_folder += "\\";
}
return tgroup;
}
@@ -2847,15 +2986,16 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators)
{
this->ClearXCodeObjects();
- this->RootObject = 0;
- this->MainGroupChildren = 0;
+ this->RootObject = nullptr;
+ this->MainGroupChildren = nullptr;
cmXCodeObject* group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
group->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
cmXCodeObject* listObjs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) {
+ for (const std::string& CurrentConfigurationType :
+ this->CurrentConfigurationTypes) {
cmXCodeObject* buildStyle =
this->CreateObject(cmXCodeObject::PBXBuildStyle);
- const char* name = this->CurrentConfigurationTypes[i].c_str();
+ const std::string& name = CurrentConfigurationType;
buildStyle->AddAttribute("name", this->CreateString(name));
buildStyle->SetComment(name);
cmXCodeObject* sgroup = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
@@ -2885,10 +3025,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
this->RootObject = this->CreateObject(cmXCodeObject::PBXProject);
this->RootObject->SetComment("Project object");
- std::string project_id = "PROJECT_";
- project_id += root->GetProjectName();
+ std::string project_id = cmStrCat("PROJECT_", root->GetProjectName());
this->RootObject->SetId(
- this->GetOrCreateId(project_id.c_str(), this->RootObject->GetId()));
+ this->GetOrCreateId(project_id, this->RootObject->GetId()));
group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
this->RootObject->AddAttribute("mainGroup",
@@ -2904,15 +3043,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
v << std::setfill('0') << std::setw(4) << XcodeVersion * 10;
group->AddAttribute("LastUpgradeCheck", this->CreateString(v.str()));
this->RootObject->AddAttribute("attributes", group);
- if (this->XcodeVersion >= 32)
- this->RootObject->AddAttribute("compatibilityVersion",
- this->CreateString("Xcode 3.2"));
- else if (this->XcodeVersion >= 31)
- this->RootObject->AddAttribute("compatibilityVersion",
- this->CreateString("Xcode 3.1"));
- else
- this->RootObject->AddAttribute("compatibilityVersion",
- this->CreateString("Xcode 3.0"));
+ this->RootObject->AddAttribute("compatibilityVersion",
+ this->CreateString("Xcode 3.2"));
// Point Xcode at the top of the source tree.
{
std::string pdir =
@@ -2924,12 +3056,11 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
this->CreateObject(cmXCodeObject::XCConfigurationList);
cmXCodeObject* buildConfigurations =
this->CreateObject(cmXCodeObject::OBJECT_LIST);
- typedef std::vector<std::pair<std::string, cmXCodeObject*> > Configs;
+ using Configs = std::vector<std::pair<std::string, cmXCodeObject*>>;
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 =
@@ -2937,15 +3068,16 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
config->AddAttribute("name", this->CreateString(name));
configs.push_back(std::make_pair(name, config));
}
- for (Configs::iterator c = configs.begin(); c != configs.end(); ++c) {
- buildConfigurations->AddObject(c->second);
+ if (defaultConfigName.empty()) {
+ defaultConfigName = "Debug";
+ }
+ for (auto& config : configs) {
+ buildConfigurations->AddObject(config.second);
}
configlist->AddAttribute("buildConfigurations", buildConfigurations);
- std::string comment = "Build configuration list for PBXProject";
- comment += " \"";
- comment += this->CurrentProject;
- comment += "\"";
+ std::string comment = cmStrCat("Build configuration list for PBXProject \"",
+ this->CurrentProject, '"');
configlist->SetComment(comment);
configlist->AddAttribute("defaultConfigurationIsVisible",
this->CreateString("0"));
@@ -2971,7 +3103,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()) {
@@ -2983,6 +3115,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
if (const char* vers = this->CurrentMakefile->GetDefinition(
"CMAKE_Swift_LANGUAGE_VERSION")) {
swiftVersion = vers;
+ } else if (this->XcodeVersion >= 102) {
+ swiftVersion = "4.0";
} else if (this->XcodeVersion >= 83) {
swiftVersion = "3.0";
} else {
@@ -2992,57 +3126,48 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
this->CreateString(swiftVersion));
}
- std::string symroot = root->GetCurrentBinaryDirectory();
- symroot += "/build";
+ std::string symroot = cmStrCat(root->GetCurrentBinaryDirectory(), "/build");
buildSettings->AddAttribute("SYMROOT", this->CreateString(symroot));
- for (Configs::iterator i = configs.begin(); i != configs.end(); ++i) {
+ for (auto& config : configs) {
cmXCodeObject* buildSettingsForCfg = this->CreateFlatClone(buildSettings);
// 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);
- this->FilterConfigurationAttribute(i->first, attribute);
+ 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))
- ->Evaluate(this->CurrentLocalGenerator, i->first);
+ std::string processed = cmGeneratorExpression::Evaluate(
+ this->CurrentMakefile->GetDefinition(var),
+ this->CurrentLocalGenerator, config.first);
buildSettingsForCfg->AddAttribute(attribute,
this->CreateString(processed));
}
}
}
// store per-config buildSettings into configuration object
- i->second->AddAttribute("buildSettings", buildSettingsForCfg);
+ config.second->AddAttribute("buildSettings", buildSettingsForCfg);
}
this->RootObject->AddAttribute("buildConfigurationList",
this->CreateObjectReference(configlist));
std::vector<cmXCodeObject*> targets;
- for (std::vector<cmLocalGenerator*>::iterator i = generators.begin();
- i != generators.end(); ++i) {
- if (!this->CreateXCodeTargets(*i, targets)) {
+ for (auto& generator : generators) {
+ if (!this->CreateXCodeTargets(generator, targets)) {
return false;
}
}
// loop over all targets and add link and depend info
- for (std::vector<cmXCodeObject*>::iterator i = targets.begin();
- i != targets.end(); ++i) {
- cmXCodeObject* t = *i;
+ for (auto t : targets) {
this->AddDependAndLinkInformation(t);
}
this->CreateXCodeDependHackTarget(targets);
// now add all targets to the root object
cmXCodeObject* allTargets = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- for (std::vector<cmXCodeObject*>::iterator i = targets.begin();
- i != targets.end(); ++i) {
- cmXCodeObject* t = *i;
+ for (auto t : targets) {
allTargets->AddObject(t);
cmXCodeObject* productRef = t->GetObject("productReference");
if (productRef) {
@@ -3053,19 +3178,13 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
return true;
}
-std::string cmGlobalXCodeGenerator::GetObjectsNormalDirectory(
+std::string cmGlobalXCodeGenerator::GetObjectsDirectory(
const std::string& projName, const std::string& configName,
- const cmGeneratorTarget* t) const
+ const cmGeneratorTarget* t, const std::string& variant) const
{
- std::string dir = t->GetLocalGenerator()->GetCurrentBinaryDirectory();
- dir += "/";
- dir += projName;
- dir += ".build/";
- dir += configName;
- dir += "/";
- dir += t->GetName();
- dir += ".build/Objects-normal/";
-
+ std::string dir = cmStrCat(
+ t->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/', projName,
+ ".build/", configName, '/', t->GetName(), ".build/", variant);
return dir;
}
@@ -3075,15 +3194,19 @@ void cmGlobalXCodeGenerator::ComputeArchitectures(cmMakefile* mf)
const char* osxArch = mf->GetDefinition("CMAKE_OSX_ARCHITECTURES");
const char* sysroot = mf->GetDefinition("CMAKE_OSX_SYSROOT");
if (osxArch && sysroot) {
- cmSystemTools::ExpandListArgument(std::string(osxArch),
- this->Architectures);
+ cmExpandList(std::string(osxArch), this->Architectures);
}
if (this->Architectures.empty()) {
// With no ARCHS we use ONLY_ACTIVE_ARCH.
// Look up the arch that Xcode chooses in this case.
- if (const char* arch = mf->GetDefinition("CMAKE_XCODE_CURRENT_ARCH")) {
+ if (const char* arch = mf->GetDefinition("CMAKE_XCODE_ARCHS")) {
this->ObjectDirArchDefault = arch;
+ // We expect only one arch but choose the first just in case.
+ std::string::size_type pos = this->ObjectDirArchDefault.find(';');
+ if (pos != std::string::npos) {
+ this->ObjectDirArchDefault = this->ObjectDirArchDefault.substr(0, pos);
+ }
}
}
@@ -3104,10 +3227,9 @@ void cmGlobalXCodeGenerator::ComputeObjectDirArch(cmMakefile* mf)
void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
std::vector<cmXCodeObject*>& targets)
{
- cmGeneratedFileStream makefileStream(this->CurrentXCodeHackMakefile.c_str());
+ cmGeneratedFileStream makefileStream(this->CurrentXCodeHackMakefile);
if (!makefileStream) {
- cmSystemTools::Error("Could not create",
- this->CurrentXCodeHackMakefile.c_str());
+ cmSystemTools::Error("Could not create " + this->CurrentXCodeHackMakefile);
return;
}
makefileStream.SetCopyIfDifferent(true);
@@ -3131,13 +3253,8 @@ 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 (std::vector<cmXCodeObject*>::iterator i = targets.begin();
- i != targets.end(); ++i) {
- cmXCodeObject* target = *i;
+ for (const auto& configName : this->CurrentConfigurationTypes) {
+ for (auto target : targets) {
cmGeneratorTarget* gt = target->GetTarget();
if (gt->GetType() == cmStateEnums::EXECUTABLE ||
@@ -3146,7 +3263,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";
}
@@ -3155,26 +3272,22 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
gt->GetType() == cmStateEnums::MODULE_LIBRARY) {
std::string tfull = gt->GetFullPath(configName);
- std::string trel = this->ConvertToRelativeForMake(tfull.c_str());
+ std::string trel = this->ConvertToRelativeForMake(tfull);
// Add this target to the post-build phases of its dependencies.
- std::map<std::string, cmXCodeObject::StringVec>::const_iterator y =
- target->GetDependTargets().find(*ct);
+ auto const y = target->GetDependTargets().find(configName);
if (y != target->GetDependTargets().end()) {
- std::vector<std::string> const& deptgts = y->second;
- for (std::vector<std::string>::const_iterator d = deptgts.begin();
- d != deptgts.end(); ++d) {
- makefileStream << this->PostBuildMakeTarget(*d, *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";
}
@@ -3182,30 +3295,24 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
makefileStream << trel << ":";
// List dependencies if any exist.
- std::map<std::string, cmXCodeObject::StringVec>::const_iterator x =
- target->GetDependLibraries().find(*ct);
+ auto const x = target->GetDependLibraries().find(configName);
if (x != target->GetDependLibraries().end()) {
- std::vector<std::string> const& deplibs = x->second;
- for (std::vector<std::string>::const_iterator d = deplibs.begin();
- d != deplibs.end(); ++d) {
- std::string file = this->ConvertToRelativeForMake(d->c_str());
+ for (auto const& deplib : x->second) {
+ std::string file = this->ConvertToRelativeForMake(deplib);
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();
- std::string d = this->GetObjectsNormalDirectory(this->CurrentProject,
- configName, *it);
- d += "lib";
- d += objLibName;
- d += ".a";
+ const std::string objLibName = objLib->GetName();
+ std::string d = cmStrCat(
+ this->GetObjectsDirectory(this->CurrentProject, configName, objLib,
+ OBJECT_LIBRARY_ARTIFACT_DIR),
+ "lib", objLibName, ".a");
- std::string dependency = this->ConvertToRelativeForMake(d.c_str());
+ std::string dependency = this->ConvertToRelativeForMake(d);
makefileStream << "\\\n\t" << dependency;
dummyRules.insert(dependency);
}
@@ -3213,23 +3320,17 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
// Write the action to remove the target if it is out of date.
makefileStream << "\n";
makefileStream << "\t/bin/rm -f "
- << this->ConvertToRelativeForMake(tfull.c_str())
- << "\n";
+ << this->ConvertToRelativeForMake(tfull) << "\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 (std::vector<std::string>::iterator arch =
- this->Architectures.begin();
- arch != this->Architectures.end(); ++arch) {
- std::string universalFile = universal;
- universalFile += *arch;
- universalFile += "/";
- universalFile += gt->GetFullName(configName);
+ std::string universal = this->GetObjectsDirectory(
+ this->CurrentProject, configName, gt, "$(OBJDIR)/");
+ for (const auto& architecture : this->Architectures) {
+ std::string universalFile = cmStrCat(universal, architecture, '/',
+ gt->GetFullName(configName));
makefileStream << "\t/bin/rm -f "
- << this->ConvertToRelativeForMake(
- universalFile.c_str())
+ << this->ConvertToRelativeForMake(universalFile)
<< "\n";
}
}
@@ -3241,51 +3342,33 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
makefileStream << "\n\n"
<< "# For each target create a dummy rule"
<< "so the target does not have to exist\n";
- for (std::set<std::string>::const_iterator it = dummyRules.begin();
- it != dummyRules.end(); ++it) {
- makefileStream << *it << ":\n";
+ for (auto const& dummyRule : dummyRules) {
+ makefileStream << dummyRule << ":\n";
}
}
void cmGlobalXCodeGenerator::OutputXCodeProject(
cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators)
{
- if (generators.size() == 0) {
+ if (generators.empty()) {
return;
}
- // Skip local generators that are excluded from this project.
- for (std::vector<cmLocalGenerator*>::iterator g = generators.begin();
- g != generators.end(); ++g) {
- if (this->IsExcluded(root, *g)) {
- continue;
- }
- }
-
if (!this->CreateXCodeObjects(root, generators)) {
return;
}
- std::string xcodeDir = root->GetCurrentBinaryDirectory();
- xcodeDir += "/";
- xcodeDir += root->GetProjectName();
- xcodeDir += ".xcodeproj";
- cmSystemTools::MakeDirectory(xcodeDir.c_str());
+ std::string xcodeDir = cmStrCat(root->GetCurrentBinaryDirectory(), '/',
+ root->GetProjectName(), ".xcodeproj");
+ cmSystemTools::MakeDirectory(xcodeDir);
std::string xcodeProjFile = xcodeDir + "/project.pbxproj";
- cmGeneratedFileStream fout(xcodeProjFile.c_str());
+ cmGeneratedFileStream fout(xcodeProjFile);
fout.SetCopyIfDifferent(true);
if (!fout) {
return;
}
this->WriteXCodePBXProj(fout, root, generators);
- // Since the lowest available Xcode version for testing was 7.0,
- // I'm setting this as a limit then
- if (this->XcodeVersion >= 70) {
- if (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() ||
- root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_SCHEME")) {
- this->OutputXCodeSharedSchemes(xcodeDir);
- this->OutputXCodeWorkspaceSettings(xcodeDir);
- }
- }
+ bool hasGeneratedSchemes = this->OutputXCodeSharedSchemes(xcodeDir, root);
+ this->OutputXCodeWorkspaceSettings(xcodeDir, hasGeneratedSchemes);
this->ClearXCodeObjects();
@@ -3295,35 +3378,67 @@ void cmGlobalXCodeGenerator::OutputXCodeProject(
root->GetBinaryDirectory());
}
-void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes(
- const std::string& xcProjDir)
+bool cmGlobalXCodeGenerator::OutputXCodeSharedSchemes(
+ const std::string& xcProjDir, cmLocalGenerator* root)
{
- for (std::vector<cmXCodeObject*>::const_iterator i =
- this->XCodeObjects.begin();
- i != this->XCodeObjects.end(); ++i) {
- cmXCodeObject* obj = *i;
- if (obj->GetType() == cmXCodeObject::OBJECT &&
- (obj->GetIsA() == cmXCodeObject::PBXNativeTarget ||
- obj->GetIsA() == cmXCodeObject::PBXAggregateTarget)) {
- cmXCodeScheme schm(obj, this->CurrentConfigurationTypes,
- this->XcodeVersion);
- schm.WriteXCodeSharedScheme(xcProjDir,
- this->RelativeToSource(xcProjDir.c_str()));
+ // collect all tests for the targets
+ std::map<std::string, cmXCodeScheme::TestObjects> testables;
+
+ for (auto obj : this->XCodeObjects) {
+ if (obj->GetType() != cmXCodeObject::OBJECT ||
+ obj->GetIsA() != cmXCodeObject::PBXNativeTarget) {
+ continue;
+ }
+
+ if (!obj->GetTarget()->IsXCTestOnApple()) {
+ continue;
+ }
+
+ const char* testee = obj->GetTarget()->GetProperty("XCTEST_TESTEE");
+ if (!testee) {
+ continue;
+ }
+
+ testables[testee].push_back(obj);
+ }
+
+ // generate scheme
+ bool ret = false;
+
+ // Since the lowest available Xcode version for testing was 6.4,
+ // I'm setting this as a limit then
+ if (this->XcodeVersion >= 64) {
+ for (auto obj : this->XCodeObjects) {
+ if (obj->GetType() == cmXCodeObject::OBJECT &&
+ (obj->GetIsA() == cmXCodeObject::PBXNativeTarget ||
+ obj->GetIsA() == cmXCodeObject::PBXAggregateTarget) &&
+ (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() ||
+ obj->GetTarget()->GetPropertyAsBool("XCODE_GENERATE_SCHEME"))) {
+ const std::string& targetName = obj->GetTarget()->GetName();
+ cmXCodeScheme schm(obj, testables[targetName],
+ this->CurrentConfigurationTypes,
+ this->XcodeVersion);
+ schm.WriteXCodeSharedScheme(xcProjDir,
+ this->RelativeToSource(xcProjDir));
+ ret = true;
+ }
}
}
+
+ return ret;
}
void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings(
- const std::string& xcProjDir)
+ const std::string& xcProjDir, bool hasGeneratedSchemes)
{
- std::string xcodeSharedDataDir = xcProjDir;
- xcodeSharedDataDir += "/project.xcworkspace/xcshareddata";
+ std::string xcodeSharedDataDir =
+ cmStrCat(xcProjDir, "/project.xcworkspace/xcshareddata");
cmSystemTools::MakeDirectory(xcodeSharedDataDir);
- std::string workspaceSettingsFile = xcodeSharedDataDir;
- workspaceSettingsFile += "/WorkspaceSettings.xcsettings";
+ std::string workspaceSettingsFile =
+ cmStrCat(xcodeSharedDataDir, "/WorkspaceSettings.xcsettings");
- cmGeneratedFileStream fout(workspaceSettingsFile.c_str());
+ cmGeneratedFileStream fout(workspaceSettingsFile);
fout.SetCopyIfDifferent(true);
if (!fout) {
return;
@@ -3336,8 +3451,15 @@ void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings(
xout.StartElement("plist");
xout.Attribute("version", "1.0");
xout.StartElement("dict");
- xout.Element("key", "IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded");
- xout.Element("false");
+ if (this->XcodeVersion >= 100) {
+ xout.Element("key", "BuildSystemType");
+ xout.Element("string", "Original");
+ }
+ if (hasGeneratedSchemes) {
+ xout.Element("key",
+ "IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded");
+ xout.Element("false");
+ }
xout.EndElement(); // dict
xout.EndElement(); // plist
xout.EndDocument();
@@ -3358,12 +3480,7 @@ void cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout,
cmXCodeObject::Indent(1, fout);
fout << "};\n";
cmXCodeObject::Indent(1, fout);
- if (this->XcodeVersion >= 32)
- fout << "objectVersion = 46;\n";
- else if (this->XcodeVersion >= 31)
- fout << "objectVersion = 45;\n";
- else
- fout << "objectVersion = 44;\n";
+ fout << "objectVersion = 46;\n";
cmXCode21Object::PrintList(this->XCodeObjects, fout);
cmXCodeObject::Indent(1, fout);
fout << "rootObject = " << this->RootObject->GetId()
@@ -3402,31 +3519,30 @@ 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);
}
-std::string cmGlobalXCodeGenerator::RelativeToSource(const char* p)
+std::string cmGlobalXCodeGenerator::RelativeToSource(const std::string& p)
{
// We force conversion because Xcode breakpoints do not work unless
// they are in a file named relative to the source tree.
- return cmOutputConverter::ForceToRelativePath(
+ return cmSystemTools::ForceToRelativePath(
cmSystemTools::JoinPath(this->ProjectSourceDirectoryComponents), p);
}
-std::string cmGlobalXCodeGenerator::RelativeToBinary(const char* p)
+std::string cmGlobalXCodeGenerator::RelativeToBinary(const std::string& p)
{
- return this->CurrentLocalGenerator->ConvertToRelativePath(
+ return this->CurrentLocalGenerator->MaybeConvertToRelativePath(
cmSystemTools::JoinPath(this->ProjectOutputDirectoryComponents), p);
}
std::string cmGlobalXCodeGenerator::XCodeEscapePath(const std::string& p)
{
if (p.find(' ') != std::string::npos) {
- std::string t = "\"";
- t += p;
- t += "\"";
+ std::string t = cmStrCat('"', p, '"');
return t;
}
return p;
@@ -3448,9 +3564,7 @@ std::string cmGlobalXCodeGenerator::LookupFlags(
const std::string& varNameSuffix, const std::string& default_flags)
{
if (!varNameLang.empty()) {
- std::string varName = varNamePrefix;
- varName += varNameLang;
- varName += varNameSuffix;
+ std::string varName = cmStrCat(varNamePrefix, varNameLang, varNameSuffix);
if (const char* varValue = this->CurrentMakefile->GetDefinition(varName)) {
if (*varValue) {
return varValue;
@@ -3470,8 +3584,7 @@ void cmGlobalXCodeGenerator::AppendDefines(BuildObjectListOrString& defs,
}
// Expand the list of definitions.
- std::vector<std::string> defines;
- cmSystemTools::ExpandListArgument(defines_list, defines);
+ std::vector<std::string> defines = cmExpandedList(defines_list);
// Store the definitions in the string.
this->AppendDefines(defs, defines, dflag);
@@ -3483,11 +3596,9 @@ void cmGlobalXCodeGenerator::AppendDefines(
{
// GCC_PREPROCESSOR_DEFINITIONS is a space-separated list of definitions.
std::string def;
- for (std::vector<std::string>::const_iterator di = defines.begin();
- di != defines.end(); ++di) {
+ for (auto const& define : defines) {
// Start with -D if requested.
- def = dflag ? "-D" : "";
- def += *di;
+ def = cmStrCat(dflag ? "-D" : "", define);
// Append the flag with needed escapes.
std::string tmp;
@@ -3497,7 +3608,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()) {
@@ -3529,17 +3640,13 @@ void cmGlobalXCodeGenerator::AppendFlag(std::string& flags,
}
// Flag value with escaped quotes and backslashes.
- for (const char* c = flag.c_str(); *c; ++c) {
- if (*c == '\'') {
- if (this->XcodeVersion >= 40) {
- flags += "'\\''";
- } else {
- flags += "\\'";
- }
- } else if (*c == '\\') {
+ for (auto c : flag) {
+ if (c == '\'') {
+ flags += "'\\''";
+ } else if (c == '\\') {
flags += "\\\\";
} else {
- flags += *c;
+ flags += c;
}
}
@@ -3552,11 +3659,9 @@ void cmGlobalXCodeGenerator::AppendFlag(std::string& flags,
std::string cmGlobalXCodeGenerator::ComputeInfoPListLocation(
cmGeneratorTarget* target)
{
- std::string plist = target->GetLocalGenerator()->GetCurrentBinaryDirectory();
- plist += cmake::GetCMakeFilesDirectory();
- plist += "/";
- plist += target->GetName();
- plist += ".dir/Info.plist";
+ std::string plist =
+ cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/", target->GetName(), ".dir/Info.plist");
return plist;
}
@@ -3572,7 +3677,7 @@ bool cmGlobalXCodeGenerator::HasKnownObjectFileLocation(
std::string* reason) const
{
if (this->ObjectDirArch.find('$') != std::string::npos) {
- if (reason != CM_NULLPTR) {
+ if (reason != nullptr) {
*reason = " under Xcode with multiple architectures";
}
return false;
@@ -3587,10 +3692,10 @@ bool cmGlobalXCodeGenerator::UseEffectivePlatformName(cmMakefile* mf) const
"XCODE_EMIT_EFFECTIVE_PLATFORM_NAME");
if (!epnValue) {
- return mf->PlatformIsAppleIos();
+ return mf->PlatformIsAppleEmbedded();
}
- return cmSystemTools::IsOn(epnValue);
+ return cmIsOn(epnValue);
}
bool cmGlobalXCodeGenerator::ShouldStripResourcePath(cmMakefile*) const
@@ -3604,8 +3709,29 @@ void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory(
{
std::string configName = this->GetCMakeCFGIntDir();
std::string dir =
- this->GetObjectsNormalDirectory("$(PROJECT_NAME)", configName, gt);
- dir += this->ObjectDirArch;
- dir += "/";
+ cmStrCat(this->GetObjectsDirectory("$(PROJECT_NAME)", configName, gt,
+ "$(OBJECT_FILE_DIR_normal:base)/"),
+ this->ObjectDirArch, '/');
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 e69793bcc..af905d00c 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -3,7 +3,7 @@
#ifndef cmGlobalXCodeGenerator_h
#define cmGlobalXCodeGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <map>
@@ -36,8 +36,8 @@ public:
unsigned int version_number);
static cmGlobalGeneratorFactory* NewFactory();
- ///! Get the name for the generator.
- std::string GetName() const CM_OVERRIDE
+ //! Get the name for the generator.
+ std::string GetName() const override
{
return cmGlobalXCodeGenerator::GetActualName();
}
@@ -46,79 +46,87 @@ public:
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
- ///! Create a local generator appropriate to this Global Generator
- cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) CM_OVERRIDE;
+ //! Create a local generator appropriate to this Global Generator
+ cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
/**
* Try to determine system information such as shared library
* extension, pthreads, byte order etc.
*/
void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
- bool optional) CM_OVERRIDE;
+ 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.
*/
- 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>()) CM_OVERRIDE;
+ std::vector<GeneratedMakeCommand> GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& projectDir, std::vector<std::string> const& targetNames,
+ const std::string& config, bool fast, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
/** Append the subdirectory for the given configuration. */
void AppendDirectoryForConfig(const std::string& prefix,
const std::string& config,
const std::string& suffix,
- std::string& dir) CM_OVERRIDE;
+ std::string& dir) override;
- bool FindMakeProgram(cmMakefile*) CM_OVERRIDE;
+ bool FindMakeProgram(cmMakefile*) override;
- ///! What is the configurations directory variable called?
- const char* GetCMakeCFGIntDir() const CM_OVERRIDE;
- ///! expand CFGIntDir
+ //! What is the configurations directory variable called?
+ const char* GetCMakeCFGIntDir() const override;
+ //! expand CFGIntDir
std::string ExpandCFGIntDir(const std::string& str,
- const std::string& config) const CM_OVERRIDE;
+ const std::string& config) const override;
void SetCurrentLocalGenerator(cmLocalGenerator*);
/** Return true if the generated build tree may contain multiple builds.
i.e. "Can I build Debug and Release in the same tree?" */
- bool IsMultiConfig() const CM_OVERRIDE;
+ bool IsMultiConfig() const override;
+
+ bool IsXcode() const override { return true; }
- bool HasKnownObjectFileLocation(std::string* reason) const CM_OVERRIDE;
+ bool HasKnownObjectFileLocation(std::string* reason) const override;
- bool IsIPOSupported() const CM_OVERRIDE { return true; }
+ bool IsIPOSupported() const override { return true; }
- bool UseEffectivePlatformName(cmMakefile* mf) const CM_OVERRIDE;
+ bool UseEffectivePlatformName(cmMakefile* mf) const override;
- bool ShouldStripResourcePath(cmMakefile*) const CM_OVERRIDE;
+ bool ShouldStripResourcePath(cmMakefile*) const override;
- bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) CM_OVERRIDE;
- void AppendFlag(std::string& flags, std::string const& flag);
+ bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override;
+ void AppendFlag(std::string& flags, std::string const& flag) const;
protected:
- void AddExtraIDETargets() CM_OVERRIDE;
- void Generate() CM_OVERRIDE;
+ void AddExtraIDETargets() override;
+ void ComputeTargetOrder();
+ void ComputeTargetOrder(cmGeneratorTarget const* gt, size_t& index);
+ void Generate() override;
private:
cmXCodeObject* CreateOrGetPBXGroup(cmGeneratorTarget* gtgt,
cmSourceGroup* sg);
- cmXCodeObject* CreatePBXGroup(cmXCodeObject* parent, std::string name);
+ cmXCodeObject* CreatePBXGroup(cmXCodeObject* parent,
+ const std::string& name);
bool CreateGroups(std::vector<cmLocalGenerator*>& generators);
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);
- void CreateCustomCommands(cmXCodeObject* buildPhases,
- cmXCodeObject* sourceBuildPhase,
- cmXCodeObject* headerBuildPhase,
- cmXCodeObject* resourceBuildPhase,
- std::vector<cmXCodeObject*> contentBuildPhases,
- cmXCodeObject* frameworkBuildPhase,
- cmGeneratorTarget* gtgt);
+ std::string RelativeToSource(const std::string& p);
+ std::string RelativeToBinary(const std::string& p);
+ std::string ConvertToRelativeForMake(std::string const& p);
+ void CreateCustomCommands(
+ cmXCodeObject* buildPhases, cmXCodeObject* sourceBuildPhase,
+ cmXCodeObject* headerBuildPhase, cmXCodeObject* resourceBuildPhase,
+ std::vector<cmXCodeObject*> const& contentBuildPhases,
+ cmXCodeObject* frameworkBuildPhase, cmGeneratorTarget* gtgt);
std::string ComputeInfoPListLocation(cmGeneratorTarget* target);
@@ -144,7 +152,7 @@ private:
cmXCodeObject* CreateFlatClone(cmXCodeObject*);
cmXCodeObject* CreateXCodeTarget(cmGeneratorTarget* gtgt,
cmXCodeObject* buildPhases);
- void ForceLinkerLanguages() CM_OVERRIDE;
+ void ForceLinkerLanguages() override;
void ForceLinkerLanguage(cmGeneratorTarget* gtgt);
const char* GetTargetLinkFlagsVar(const cmGeneratorTarget* target) const;
const char* GetTargetFileType(cmGeneratorTarget* target);
@@ -158,6 +166,9 @@ private:
const std::string& configName);
cmXCodeObject* CreateUtilityTarget(cmGeneratorTarget* gtgt);
void AddDependAndLinkInformation(cmXCodeObject* target);
+ void AddPositionIndependentLinkAttribute(cmGeneratorTarget* target,
+ cmXCodeObject* buildSettings,
+ const std::string& configName);
void CreateBuildSettings(cmGeneratorTarget* gtgt,
cmXCodeObject* buildSettings,
const std::string& buildType);
@@ -174,8 +185,11 @@ private:
void OutputXCodeProject(cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators);
// Write shared scheme files for all the native targets
- void OutputXCodeSharedSchemes(const std::string& xcProjDir);
- void OutputXCodeWorkspaceSettings(const std::string& xcProjDir);
+ // return true if any were written
+ bool OutputXCodeSharedSchemes(const std::string& xcProjDir,
+ cmLocalGenerator* root);
+ void OutputXCodeWorkspaceSettings(const std::string& xcProjDir,
+ bool hasGeneratedSchemes);
void WriteXCodePBXProj(std::ostream& fout, cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators);
cmXCodeObject* CreateXCodeFileReferenceFromPath(const std::string& fullpath,
@@ -190,7 +204,11 @@ private:
cmGeneratorTarget* target);
cmXCodeObject* CreateXCodeSourceFile(cmLocalGenerator* gen, cmSourceFile* sf,
cmGeneratorTarget* gtgt);
+ void AddXCodeProjBuildRule(cmGeneratorTarget* target,
+ std::vector<cmSourceFile*>& sources) const;
bool CreateXCodeTargets(cmLocalGenerator* gen, std::vector<cmXCodeObject*>&);
+ bool CreateXCodeTarget(cmGeneratorTarget* gtgt,
+ std::vector<cmXCodeObject*>&);
bool IsHeaderFile(cmSourceFile*);
void AddDependTarget(cmXCodeObject* target, cmXCodeObject* dependTarget);
void CreateXCodeDependHackTarget(std::vector<cmXCodeObject*>& targets);
@@ -219,11 +237,11 @@ private:
std::vector<std::string> const& defines,
bool dflag = false);
- void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const CM_OVERRIDE;
+ void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override;
protected:
- const char* GetInstallTargetName() const CM_OVERRIDE { return "install"; }
- const char* GetPackageTargetName() const CM_OVERRIDE { return "package"; }
+ const char* GetInstallTargetName() const override { return "install"; }
+ const char* GetPackageTargetName() const override { return "package"; }
unsigned int XcodeVersion;
std::string VersionString;
@@ -238,13 +256,16 @@ private:
bool XcodeBuildCommandInitialized;
void PrintCompilerAdvice(std::ostream&, std::string const&,
- const char*) const CM_OVERRIDE
+ const char*) const override
{
}
- std::string GetObjectsNormalDirectory(const std::string& projName,
- const std::string& configName,
- const cmGeneratorTarget* t) const;
+ std::string GetObjectsDirectory(const std::string& projName,
+ const std::string& configName,
+ const cmGeneratorTarget* t,
+ const std::string& variant) const;
+
+ static std::string GetDeploymentPlatform(const cmMakefile* mf);
void ComputeArchitectures(cmMakefile* mf);
void ComputeObjectDirArch(cmMakefile* mf);
@@ -271,6 +292,7 @@ private:
std::string ObjectDirArchDefault;
std::string ObjectDirArch;
std::string GeneratorToolset;
+ std::map<cmGeneratorTarget const*, size_t> TargetOrderIndex;
};
#endif
diff --git a/Source/cmGraphAdjacencyList.h b/Source/cmGraphAdjacencyList.h
index 46cf87871..5ed6af461 100644
--- a/Source/cmGraphAdjacencyList.h
+++ b/Source/cmGraphAdjacencyList.h
@@ -5,8 +5,11 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <utility>
#include <vector>
+#include "cmListFileCache.h"
+
/**
* Graph edge representation. Most use cases just need the
* destination vertex, so we support conversion to/from an int. We
@@ -15,17 +18,22 @@
class cmGraphEdge
{
public:
- cmGraphEdge(int n = 0, bool s = true)
+ cmGraphEdge(int n, bool s, cmListFileBacktrace bt)
: Dest(n)
, Strong(s)
+ , Backtrace(std::move(bt))
{
}
operator int() const { return this->Dest; }
bool IsStrong() const { return this->Strong; }
+
+ cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; }
+
private:
int Dest;
bool Strong;
+ cmListFileBacktrace Backtrace;
};
struct cmGraphEdgeList : public std::vector<cmGraphEdge>
{
diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx
index 7e953cef1..e0d545d86 100644
--- a/Source/cmGraphVizWriter.cxx
+++ b/Source/cmGraphVizWriter.cxx
@@ -2,8 +2,9 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGraphVizWriter.h"
-#include "cmConfigure.h"
+#include <cstddef>
#include <iostream>
+#include <memory>
#include <sstream>
#include <utility>
@@ -12,13 +13,41 @@
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmState.h"
#include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
-#include "cm_auto_ptr.hxx"
#include "cmake.h"
-static const char* getShapeForTarget(const cmGeneratorTarget* target)
+namespace {
+enum LinkLibraryScopeType
+{
+ LLT_SCOPE_PUBLIC,
+ LLT_SCOPE_PRIVATE,
+ LLT_SCOPE_INTERFACE
+};
+
+const char* const GRAPHVIZ_PRIVATE_EDEGE_STYLE = "dashed";
+const char* const GRAPHVIZ_INTERFACE_EDEGE_STYLE = "dotted";
+
+std::string getLinkLibraryStyle(const LinkLibraryScopeType& type)
+{
+ std::string style;
+ switch (type) {
+ case LLT_SCOPE_PRIVATE:
+ style = "[style = " + std::string(GRAPHVIZ_PRIVATE_EDEGE_STYLE) + "]";
+ break;
+ case LLT_SCOPE_INTERFACE:
+ style = "[style = " + std::string(GRAPHVIZ_INTERFACE_EDEGE_STYLE) + "]";
+ break;
+ default:
+ break;
+ }
+ return style;
+}
+
+const char* getShapeForTarget(const cmGeneratorTarget* target)
{
if (!target) {
return "ellipse";
@@ -40,17 +69,102 @@ static const char* getShapeForTarget(const cmGeneratorTarget* target)
return "box";
}
-cmGraphVizWriter::cmGraphVizWriter(
- const std::vector<cmLocalGenerator*>& localGenerators)
+std::map<std::string, LinkLibraryScopeType> getScopedLinkLibrariesFromTarget(
+ cmTarget* Target, const cmGlobalGenerator* globalGenerator)
+{
+ char sep = ';';
+ std::map<std::string, LinkLibraryScopeType> tokens;
+ size_t start = 0;
+ size_t end = 0;
+
+ const char* pInterfaceLinkLibraries =
+ Target->GetProperty("INTERFACE_LINK_LIBRARIES");
+ const char* pLinkLibraries = Target->GetProperty("LINK_LIBRARIES");
+
+ if (!pInterfaceLinkLibraries && !pLinkLibraries) {
+ return tokens; // target is not linked against any other libraries
+ }
+
+ // make sure we don't touch a null-ptr
+ auto interfaceLinkLibraries =
+ std::string(pInterfaceLinkLibraries ? pInterfaceLinkLibraries : "");
+ auto linkLibraries = std::string(pLinkLibraries ? pLinkLibraries : "");
+
+ // first extract interfaceLinkLibraries
+ while (start < interfaceLinkLibraries.length()) {
+
+ if ((end = interfaceLinkLibraries.find(sep, start)) == std::string::npos) {
+ end = interfaceLinkLibraries.length();
+ }
+
+ std::string element = interfaceLinkLibraries.substr(start, end - start);
+ if (globalGenerator->IsAlias(element)) {
+ const auto tgt = globalGenerator->FindTarget(element);
+ if (tgt) {
+ element = tgt->GetName();
+ }
+ }
+
+ if (std::string::npos == element.find("$<LINK_ONLY:", 0)) {
+ // we assume first, that this library is an interface library.
+ // if we find it again in the linklibraries property, we promote it to an
+ // public library.
+ tokens[element] = LLT_SCOPE_INTERFACE;
+ } else {
+ // this is an private linked static library.
+ // we take care of this case in the second iterator.
+ }
+ start = end + 1;
+ }
+
+ // second extract linkLibraries
+ start = 0;
+ while (start < linkLibraries.length()) {
+
+ if ((end = linkLibraries.find(sep, start)) == std::string::npos) {
+ end = linkLibraries.length();
+ }
+
+ std::string element = linkLibraries.substr(start, end - start);
+ if (globalGenerator->IsAlias(element)) {
+ const auto tgt = globalGenerator->FindTarget(element);
+ if (tgt) {
+ element = tgt->GetName();
+ }
+ }
+
+ if (tokens.find(element) == tokens.end()) {
+ // this library is not found in interfaceLinkLibraries but in
+ // linkLibraries.
+ // this results in a private linked library.
+ tokens[element] = LLT_SCOPE_PRIVATE;
+ } else if (LLT_SCOPE_INTERFACE == tokens[element]) {
+ // this library is found in interfaceLinkLibraries and linkLibraries.
+ // this results in a public linked library.
+ tokens[element] = LLT_SCOPE_PUBLIC;
+ } else {
+ // private and public linked libraries should not be changed anymore.
+ }
+
+ start = end + 1;
+ }
+
+ return tokens;
+}
+}
+
+cmGraphVizWriter::cmGraphVizWriter(const cmGlobalGenerator* globalGenerator)
: GraphType("digraph")
, GraphName("GG")
, GraphHeader("node [\n fontsize = \"12\"\n];")
, GraphNodePrefix("node")
- , LocalGenerators(localGenerators)
+ , GlobalGenerator(globalGenerator)
+ , LocalGenerators(globalGenerator->GetLocalGenerators())
, GenerateForExecutables(true)
, GenerateForStaticLibs(true)
, GenerateForSharedLibs(true)
, GenerateForModuleLibs(true)
+ , GenerateForInterface(true)
, GenerateForExternals(true)
, GeneratePerTarget(true)
, GenerateDependers(true)
@@ -58,19 +172,19 @@ cmGraphVizWriter::cmGraphVizWriter(
{
}
-void cmGraphVizWriter::ReadSettings(const char* settingsFileName,
- const char* fallbackSettingsFileName)
+void cmGraphVizWriter::ReadSettings(
+ const std::string& settingsFileName,
+ const std::string& fallbackSettingsFileName)
{
- cmake cm(cmake::RoleScript);
+ cmake cm(cmake::RoleScript, cmState::Unknown);
cm.SetHomeDirectory("");
cm.SetHomeOutputDirectory("");
cm.GetCurrentSnapshot().SetDefaultDefinitions();
cmGlobalGenerator ggi(&cm);
- CM_AUTO_PTR<cmMakefile> mf(new cmMakefile(&ggi, cm.GetCurrentSnapshot()));
- CM_AUTO_PTR<cmLocalGenerator> lg(ggi.CreateLocalGenerator(mf.get()));
-
- const char* inFileName = settingsFileName;
+ cmMakefile mf(&ggi, cm.GetCurrentSnapshot());
+ std::unique_ptr<cmLocalGenerator> lg(ggi.CreateLocalGenerator(&mf));
+ std::string inFileName = settingsFileName;
if (!cmSystemTools::FileExists(inFileName)) {
inFileName = fallbackSettingsFileName;
if (!cmSystemTools::FileExists(inFileName)) {
@@ -78,8 +192,8 @@ void cmGraphVizWriter::ReadSettings(const char* settingsFileName,
}
}
- if (!mf->ReadListFile(inFileName)) {
- cmSystemTools::Error("Problem opening GraphViz options file: ",
+ if (!mf.ReadListFile(inFileName)) {
+ cmSystemTools::Error("Problem opening GraphViz options file: " +
inFileName);
return;
}
@@ -87,12 +201,12 @@ void cmGraphVizWriter::ReadSettings(const char* settingsFileName,
std::cout << "Reading GraphViz options file: " << inFileName << std::endl;
#define __set_if_set(var, cmakeDefinition) \
- { \
- const char* value = mf->GetDefinition(cmakeDefinition); \
+ do { \
+ const char* value = mf.GetDefinition(cmakeDefinition); \
if (value) { \
(var) = value; \
} \
- }
+ } while (false)
__set_if_set(this->GraphType, "GRAPHVIZ_GRAPH_TYPE");
__set_if_set(this->GraphName, "GRAPHVIZ_GRAPH_NAME");
@@ -100,17 +214,18 @@ void cmGraphVizWriter::ReadSettings(const char* settingsFileName,
__set_if_set(this->GraphNodePrefix, "GRAPHVIZ_NODE_PREFIX");
#define __set_bool_if_set(var, cmakeDefinition) \
- { \
- const char* value = mf->GetDefinition(cmakeDefinition); \
+ do { \
+ const char* value = mf.GetDefinition(cmakeDefinition); \
if (value) { \
- (var) = mf->IsOn(cmakeDefinition); \
+ (var) = mf.IsOn(cmakeDefinition); \
} \
- }
+ } while (false)
__set_bool_if_set(this->GenerateForExecutables, "GRAPHVIZ_EXECUTABLES");
__set_bool_if_set(this->GenerateForStaticLibs, "GRAPHVIZ_STATIC_LIBS");
__set_bool_if_set(this->GenerateForSharedLibs, "GRAPHVIZ_SHARED_LIBS");
__set_bool_if_set(this->GenerateForModuleLibs, "GRAPHVIZ_MODULE_LIBS");
+ __set_bool_if_set(this->GenerateForInterface, "GRAPHVIZ_INTERFACE");
__set_bool_if_set(this->GenerateForExternals, "GRAPHVIZ_EXTERNAL_LIBS");
__set_bool_if_set(this->GeneratePerTarget, "GRAPHVIZ_GENERATE_PER_TARGET");
__set_bool_if_set(this->GenerateDependers, "GRAPHVIZ_GENERATE_DEPENDERS");
@@ -120,26 +235,22 @@ void cmGraphVizWriter::ReadSettings(const char* settingsFileName,
this->TargetsToIgnoreRegex.clear();
if (!ignoreTargetsRegexes.empty()) {
- std::vector<std::string> ignoreTargetsRegExVector;
- cmSystemTools::ExpandListArgument(ignoreTargetsRegexes,
- ignoreTargetsRegExVector);
- for (std::vector<std::string>::const_iterator itvIt =
- ignoreTargetsRegExVector.begin();
- itvIt != ignoreTargetsRegExVector.end(); ++itvIt) {
- std::string currentRegexString(*itvIt);
+ std::vector<std::string> ignoreTargetsRegExVector =
+ cmExpandedList(ignoreTargetsRegexes);
+ 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));
}
}
}
// Iterate over all targets and write for each one a graph which shows
// which other targets depend on it.
-void cmGraphVizWriter::WriteTargetDependersFiles(const char* fileName)
+void cmGraphVizWriter::WriteTargetDependersFiles(const std::string& fileName)
{
if (!this->GenerateDependers) {
return;
@@ -147,23 +258,19 @@ void cmGraphVizWriter::WriteTargetDependersFiles(const char* fileName)
this->CollectTargetsAndLibs();
- for (std::map<std::string, const cmGeneratorTarget*>::const_iterator ptrIt =
- this->TargetPtrs.begin();
- ptrIt != this->TargetPtrs.end(); ++ptrIt) {
- if (ptrIt->second == CM_NULLPTR) {
+ for (auto const& ptr : this->TargetPtrs) {
+ if (ptr.second == nullptr) {
continue;
}
- if (!this->GenerateForTargetType(ptrIt->second->GetType())) {
+ if (!this->GenerateForTargetType(ptr.second->GetType())) {
continue;
}
- std::string currentFilename = fileName;
- currentFilename += ".";
- currentFilename += ptrIt->first;
- currentFilename += ".dependers";
+ std::string currentFilename =
+ cmStrCat(fileName, '.', ptr.first, ".dependers");
- cmGeneratedFileStream str(currentFilename.c_str());
+ cmGeneratedFileStream str(currentFilename);
if (!str) {
return;
}
@@ -174,7 +281,7 @@ void cmGraphVizWriter::WriteTargetDependersFiles(const char* fileName)
std::cout << "Writing " << currentFilename << "..." << std::endl;
this->WriteHeader(str);
- this->WriteDependerConnections(ptrIt->first, insertedNodes,
+ this->WriteDependerConnections(ptr.first, insertedNodes,
insertedConnections, str);
this->WriteFooter(str);
@@ -183,7 +290,7 @@ void cmGraphVizWriter::WriteTargetDependersFiles(const char* fileName)
// Iterate over all targets and write for each one a graph which shows
// on which targets it depends.
-void cmGraphVizWriter::WritePerTargetFiles(const char* fileName)
+void cmGraphVizWriter::WritePerTargetFiles(const std::string& fileName)
{
if (!this->GeneratePerTarget) {
return;
@@ -191,24 +298,20 @@ void cmGraphVizWriter::WritePerTargetFiles(const char* fileName)
this->CollectTargetsAndLibs();
- for (std::map<std::string, const cmGeneratorTarget*>::const_iterator ptrIt =
- this->TargetPtrs.begin();
- ptrIt != this->TargetPtrs.end(); ++ptrIt) {
- if (ptrIt->second == CM_NULLPTR) {
+ for (auto const& ptr : this->TargetPtrs) {
+ if (ptr.second == nullptr) {
continue;
}
- if (!this->GenerateForTargetType(ptrIt->second->GetType())) {
+ if (!this->GenerateForTargetType(ptr.second->GetType())) {
continue;
}
std::set<std::string> insertedConnections;
std::set<std::string> insertedNodes;
- std::string currentFilename = fileName;
- currentFilename += ".";
- currentFilename += ptrIt->first;
- cmGeneratedFileStream str(currentFilename.c_str());
+ std::string currentFilename = cmStrCat(fileName, '.', ptr.first);
+ cmGeneratedFileStream str(currentFilename);
if (!str) {
return;
}
@@ -216,13 +319,12 @@ void cmGraphVizWriter::WritePerTargetFiles(const char* fileName)
std::cout << "Writing " << currentFilename << "..." << std::endl;
this->WriteHeader(str);
- this->WriteConnections(ptrIt->first, insertedNodes, insertedConnections,
- str);
+ this->WriteConnections(ptr.first, insertedNodes, insertedConnections, str);
this->WriteFooter(str);
}
}
-void cmGraphVizWriter::WriteGlobalFile(const char* fileName)
+void cmGraphVizWriter::WriteGlobalFile(const std::string& fileName)
{
this->CollectTargetsAndLibs();
@@ -237,19 +339,16 @@ void cmGraphVizWriter::WriteGlobalFile(const char* fileName)
std::set<std::string> insertedConnections;
std::set<std::string> insertedNodes;
- for (std::map<std::string, const cmGeneratorTarget*>::const_iterator ptrIt =
- this->TargetPtrs.begin();
- ptrIt != this->TargetPtrs.end(); ++ptrIt) {
- if (ptrIt->second == CM_NULLPTR) {
+ for (auto const& ptr : this->TargetPtrs) {
+ if (ptr.second == nullptr) {
continue;
}
- if (!this->GenerateForTargetType(ptrIt->second->GetType())) {
+ if (!this->GenerateForTargetType(ptr.second->GetType())) {
continue;
}
- this->WriteConnections(ptrIt->first, insertedNodes, insertedConnections,
- str);
+ this->WriteConnections(ptr.first, insertedNodes, insertedConnections, str);
}
this->WriteFooter(str);
}
@@ -269,8 +368,7 @@ void cmGraphVizWriter::WriteConnections(
const std::string& targetName, std::set<std::string>& insertedNodes,
std::set<std::string>& insertedConnections, cmGeneratedFileStream& str) const
{
- std::map<std::string, const cmGeneratorTarget*>::const_iterator targetPtrIt =
- this->TargetPtrs.find(targetName);
+ auto targetPtrIt = this->TargetPtrs.find(targetName);
if (targetPtrIt == this->TargetPtrs.end()) // not found at all
{
@@ -279,30 +377,26 @@ void cmGraphVizWriter::WriteConnections(
this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str);
- if (targetPtrIt->second == CM_NULLPTR) // it's an external library
+ if (targetPtrIt->second == nullptr) // it's an external library
{
return;
}
std::string myNodeName = this->TargetNamesNodes.find(targetName)->second;
+ std::map<std::string, LinkLibraryScopeType> ll =
+ getScopedLinkLibrariesFromTarget(targetPtrIt->second->Target,
+ GlobalGenerator);
- const cmTarget::LinkLibraryVectorType* ll =
- &(targetPtrIt->second->Target->GetOriginalLinkLibraries());
-
- for (cmTarget::LinkLibraryVectorType::const_iterator llit = ll->begin();
- llit != ll->end(); ++llit) {
- const char* libName = llit->first.c_str();
- std::map<std::string, std::string>::const_iterator libNameIt =
- this->TargetNamesNodes.find(libName);
+ for (auto const& llit : ll) {
+ const std::string& libName = llit.first;
+ auto libNameIt = this->TargetNamesNodes.find(libName);
// can happen e.g. if GRAPHVIZ_TARGET_IGNORE_REGEX is used
if (libNameIt == this->TargetNamesNodes.end()) {
continue;
}
- std::string connectionName = myNodeName;
- connectionName += "-";
- connectionName += libNameIt->second;
+ std::string connectionName = cmStrCat(myNodeName, '-', libNameIt->second);
if (insertedConnections.find(connectionName) ==
insertedConnections.end()) {
insertedConnections.insert(connectionName);
@@ -310,6 +404,9 @@ void cmGraphVizWriter::WriteConnections(
insertedNodes, str);
str << " \"" << myNodeName << "\" -> \"" << libNameIt->second << "\"";
+
+ str << getLinkLibraryStyle(llit.second);
+
str << " // " << targetName << " -> " << libName << std::endl;
this->WriteConnections(libName, insertedNodes, insertedConnections, str);
}
@@ -320,8 +417,7 @@ void cmGraphVizWriter::WriteDependerConnections(
const std::string& targetName, std::set<std::string>& insertedNodes,
std::set<std::string>& insertedConnections, cmGeneratedFileStream& str) const
{
- std::map<std::string, const cmGeneratorTarget*>::const_iterator targetPtrIt =
- this->TargetPtrs.find(targetName);
+ auto targetPtrIt = this->TargetPtrs.find(targetName);
if (targetPtrIt == this->TargetPtrs.end()) // not found at all
{
@@ -330,7 +426,7 @@ void cmGraphVizWriter::WriteDependerConnections(
this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str);
- if (targetPtrIt->second == CM_NULLPTR) // it's an external library
+ if (targetPtrIt->second == nullptr) // it's an external library
{
return;
}
@@ -338,46 +434,39 @@ void cmGraphVizWriter::WriteDependerConnections(
std::string myNodeName = this->TargetNamesNodes.find(targetName)->second;
// now search who links against me
- for (std::map<std::string, const cmGeneratorTarget*>::const_iterator
- dependerIt = this->TargetPtrs.begin();
- dependerIt != this->TargetPtrs.end(); ++dependerIt) {
- if (dependerIt->second == CM_NULLPTR) {
+ for (auto const& tptr : this->TargetPtrs) {
+ if (tptr.second == nullptr) {
continue;
}
- if (!this->GenerateForTargetType(dependerIt->second->GetType())) {
+ if (!this->GenerateForTargetType(tptr.second->GetType())) {
continue;
}
// Now we have a target, check whether it links against targetName.
// If so, draw a connection, and then continue with dependers on that one.
- const cmTarget::LinkLibraryVectorType* ll =
- &(dependerIt->second->Target->GetOriginalLinkLibraries());
+ std::map<std::string, LinkLibraryScopeType> ll =
+ getScopedLinkLibrariesFromTarget(tptr.second->Target, GlobalGenerator);
- for (cmTarget::LinkLibraryVectorType::const_iterator llit = ll->begin();
- llit != ll->end(); ++llit) {
- std::string libName = llit->first;
- if (libName == targetName) {
+ for (auto const& llit : ll) {
+ if (llit.first == targetName) {
// So this target links against targetName.
- std::map<std::string, std::string>::const_iterator dependerNodeNameIt =
- this->TargetNamesNodes.find(dependerIt->first);
+ auto dependerNodeNameIt = this->TargetNamesNodes.find(tptr.first);
if (dependerNodeNameIt != this->TargetNamesNodes.end()) {
- std::string connectionName = dependerNodeNameIt->second;
- connectionName += "-";
- connectionName += myNodeName;
+ std::string connectionName =
+ cmStrCat(dependerNodeNameIt->second, '-', myNodeName);
if (insertedConnections.find(connectionName) ==
insertedConnections.end()) {
insertedConnections.insert(connectionName);
- this->WriteNode(dependerIt->first, dependerIt->second,
- insertedNodes, str);
+ this->WriteNode(tptr.first, tptr.second, insertedNodes, str);
str << " \"" << dependerNodeNameIt->second << "\" -> \""
<< myNodeName << "\"";
- str << " // " << targetName << " -> " << dependerIt->first
- << std::endl;
- this->WriteDependerConnections(dependerIt->first, insertedNodes,
+ str << " // " << targetName << " -> " << tptr.first << std::endl;
+ str << getLinkLibraryStyle(llit.second);
+ this->WriteDependerConnections(tptr.first, insertedNodes,
insertedConnections, str);
}
}
@@ -394,8 +483,7 @@ void cmGraphVizWriter::WriteNode(const std::string& targetName,
{
if (insertedNodes.find(targetName) == insertedNodes.end()) {
insertedNodes.insert(targetName);
- std::map<std::string, std::string>::const_iterator nameIt =
- this->TargetNamesNodes.find(targetName);
+ auto nameIt = this->TargetNamesNodes.find(targetName);
str << " \"" << nameIt->second << "\" [ label=\"" << targetName
<< "\" shape=\"" << getShapeForTarget(target) << "\"];" << std::endl;
@@ -417,13 +505,10 @@ int cmGraphVizWriter::CollectAllTargets()
{
int cnt = 0;
// First pass get the list of all cmake targets
- for (std::vector<cmLocalGenerator*>::const_iterator lit =
- this->LocalGenerators.begin();
- lit != this->LocalGenerators.end(); ++lit) {
- std::vector<cmGeneratorTarget*> targets = (*lit)->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::const_iterator it = targets.begin();
- it != targets.end(); ++it) {
- const char* realTargetName = (*it)->GetName().c_str();
+ for (cmLocalGenerator* lg : this->LocalGenerators) {
+ const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
+ for (cmGeneratorTarget* target : targets) {
+ const std::string& realTargetName = target->GetName();
if (this->IgnoreThisTarget(realTargetName)) {
// Skip ignored targets
continue;
@@ -432,7 +517,7 @@ int cmGraphVizWriter::CollectAllTargets()
std::ostringstream ostr;
ostr << this->GraphNodePrefix << cnt++;
this->TargetNamesNodes[realTargetName] = ostr.str();
- this->TargetPtrs[realTargetName] = *it;
+ this->TargetPtrs[realTargetName] = target;
}
}
@@ -442,34 +527,36 @@ int cmGraphVizWriter::CollectAllTargets()
int cmGraphVizWriter::CollectAllExternalLibs(int cnt)
{
// Ok, now find all the stuff we link to that is not in cmake
- for (std::vector<cmLocalGenerator*>::const_iterator lit =
- this->LocalGenerators.begin();
- lit != this->LocalGenerators.end(); ++lit) {
- std::vector<cmGeneratorTarget*> targets = (*lit)->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::const_iterator it = targets.begin();
- it != targets.end(); ++it) {
- const char* realTargetName = (*it)->GetName().c_str();
+ for (cmLocalGenerator* lg : this->LocalGenerators) {
+ const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
+ for (cmGeneratorTarget* target : targets) {
+ const std::string& realTargetName = target->GetName();
if (this->IgnoreThisTarget(realTargetName)) {
// Skip ignored targets
continue;
}
const cmTarget::LinkLibraryVectorType* ll =
- &((*it)->Target->GetOriginalLinkLibraries());
- for (cmTarget::LinkLibraryVectorType::const_iterator llit = ll->begin();
- llit != ll->end(); ++llit) {
- const char* libName = llit->first.c_str();
+ &(target->Target->GetOriginalLinkLibraries());
+ for (auto const& llit : *ll) {
+ std::string libName = llit.first;
if (this->IgnoreThisTarget(libName)) {
// Skip ignored targets
continue;
}
- std::map<std::string, const cmGeneratorTarget*>::const_iterator tarIt =
- this->TargetPtrs.find(libName);
+ if (GlobalGenerator->IsAlias(libName)) {
+ const auto tgt = GlobalGenerator->FindTarget(libName);
+ if (tgt) {
+ libName = tgt->GetName();
+ }
+ }
+
+ auto tarIt = this->TargetPtrs.find(libName);
if (tarIt == this->TargetPtrs.end()) {
std::ostringstream ostr;
ostr << this->GraphNodePrefix << cnt++;
this->TargetNamesNodes[libName] = ostr.str();
- this->TargetPtrs[libName] = CM_NULLPTR;
+ this->TargetPtrs[libName] = nullptr;
// str << " \"" << ostr << "\" [ label=\"" << libName
// << "\" shape=\"ellipse\"];" << std::endl;
}
@@ -481,10 +568,7 @@ int cmGraphVizWriter::CollectAllExternalLibs(int cnt)
bool cmGraphVizWriter::IgnoreThisTarget(const std::string& name)
{
- for (std::vector<cmsys::RegularExpression>::iterator itvIt =
- this->TargetsToIgnoreRegex.begin();
- itvIt != this->TargetsToIgnoreRegex.end(); ++itvIt) {
- cmsys::RegularExpression& regEx = *itvIt;
+ for (cmsys::RegularExpression& regEx : this->TargetsToIgnoreRegex) {
if (regEx.is_valid()) {
if (regEx.find(name)) {
return true;
@@ -507,6 +591,8 @@ bool cmGraphVizWriter::GenerateForTargetType(
return this->GenerateForSharedLibs;
case cmStateEnums::MODULE_LIBRARY:
return this->GenerateForModuleLibs;
+ case cmStateEnums::INTERFACE_LIBRARY:
+ return this->GenerateForInterface;
default:
break;
}
diff --git a/Source/cmGraphVizWriter.h b/Source/cmGraphVizWriter.h
index 824999b96..9c3051f2c 100644
--- a/Source/cmGraphVizWriter.h
+++ b/Source/cmGraphVizWriter.h
@@ -5,32 +5,34 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmStateTypes.h"
-
-#include "cmsys/RegularExpression.hxx"
#include <map>
#include <set>
#include <string>
#include <vector>
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmStateTypes.h"
+
class cmGeneratedFileStream;
class cmGeneratorTarget;
class cmLocalGenerator;
+class cmGlobalGenerator;
/** This class implements writing files for graphviz (dot) for graphs
* representing the dependencies between the targets in the project. */
class cmGraphVizWriter
{
public:
- cmGraphVizWriter(const std::vector<cmLocalGenerator*>& localGenerators);
+ cmGraphVizWriter(const cmGlobalGenerator* globalGenerator);
- void ReadSettings(const char* settingsFileName,
- const char* fallbackSettingsFileName);
+ void ReadSettings(const std::string& settingsFileName,
+ const std::string& fallbackSettingsFileName);
- void WritePerTargetFiles(const char* fileName);
- void WriteTargetDependersFiles(const char* fileName);
+ void WritePerTargetFiles(const std::string& fileName);
+ void WriteTargetDependersFiles(const std::string& fileName);
- void WriteGlobalFile(const char* fileName);
+ void WriteGlobalFile(const std::string& fileName);
protected:
void CollectTargetsAndLibs();
@@ -69,6 +71,7 @@ protected:
std::vector<cmsys::RegularExpression> TargetsToIgnoreRegex;
+ const cmGlobalGenerator* GlobalGenerator;
const std::vector<cmLocalGenerator*>& LocalGenerators;
std::map<std::string, const cmGeneratorTarget*> TargetPtrs;
@@ -79,6 +82,7 @@ protected:
bool GenerateForStaticLibs;
bool GenerateForSharedLibs;
bool GenerateForModuleLibs;
+ bool GenerateForInterface;
bool GenerateForExternals;
bool GeneratePerTarget;
bool GenerateDependers;
diff --git a/Source/cmHexFileConverter.cxx b/Source/cmHexFileConverter.cxx
index 78dceb794..2fa4b5505 100644
--- a/Source/cmHexFileConverter.cxx
+++ b/Source/cmHexFileConverter.cxx
@@ -2,9 +2,9 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmHexFileConverter.h"
-#include "cmConfigure.h"
-#include <stdio.h>
-#include <string.h>
+#include <cctype>
+#include <cstdio>
+#include <cstring>
#include "cmSystemTools.h"
@@ -13,16 +13,9 @@
#define MOTOROLA_SREC_MIN_LINE_LENGTH (2 + 2 + 4 + 2)
#define MOTOROLA_SREC_MAX_LINE_LENGTH (2 + 2 + 8 + (256 * 2) + 2)
-// might go to SystemTools ?
-static bool cm_IsHexChar(char c)
-{
- return (((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')) ||
- ((c >= 'A') && (c <= 'F')));
-}
-
static unsigned int ChompStrlen(const char* line)
{
- if (line == CM_NULLPTR) {
+ if (line == nullptr) {
return 0;
}
unsigned int length = static_cast<unsigned int>(strlen(line));
@@ -135,11 +128,11 @@ static bool ConvertIntelHexLine(const char* buf, FILE* outFile)
}
cmHexFileConverter::FileType cmHexFileConverter::DetermineFileType(
- const char* inFileName)
+ const std::string& inFileName)
{
char buf[1024];
FILE* inFile = cmsys::SystemTools::Fopen(inFileName, "rb");
- if (inFile == CM_NULLPTR) {
+ if (inFile == nullptr) {
return Binary;
}
@@ -170,15 +163,15 @@ cmHexFileConverter::FileType cmHexFileConverter::DetermineFileType(
}
for (unsigned int i = 1; i < slen; i++) {
- if (!cm_IsHexChar(buf[i])) {
+ if (!isxdigit(buf[i])) {
return Binary;
}
}
return type;
}
-bool cmHexFileConverter::TryConvert(const char* inFileName,
- const char* outFileName)
+bool cmHexFileConverter::TryConvert(const std::string& inFileName,
+ const std::string& outFileName)
{
FileType type = DetermineFileType(inFileName);
if (type == Binary) {
@@ -188,11 +181,11 @@ bool cmHexFileConverter::TryConvert(const char* inFileName,
// try to open the file
FILE* inFile = cmsys::SystemTools::Fopen(inFileName, "rb");
FILE* outFile = cmsys::SystemTools::Fopen(outFileName, "wb");
- if ((inFile == CM_NULLPTR) || (outFile == CM_NULLPTR)) {
- if (inFile != CM_NULLPTR) {
+ if ((inFile == nullptr) || (outFile == nullptr)) {
+ if (inFile != nullptr) {
fclose(inFile);
}
- if (outFile != CM_NULLPTR) {
+ if (outFile != nullptr) {
fclose(outFile);
}
return false;
@@ -201,7 +194,7 @@ bool cmHexFileConverter::TryConvert(const char* inFileName,
// convert them line by line
bool success = false;
char buf[1024];
- while (fgets(buf, 1024, inFile) != CM_NULLPTR) {
+ while (fgets(buf, 1024, inFile) != nullptr) {
if (type == MotorolaSrec) {
success = ConvertMotorolaSrecLine(buf, outFile);
} else if (type == IntelHex) {
diff --git a/Source/cmHexFileConverter.h b/Source/cmHexFileConverter.h
index 1050bc1b4..26f9ea8ba 100644
--- a/Source/cmHexFileConverter.h
+++ b/Source/cmHexFileConverter.h
@@ -3,6 +3,10 @@
#ifndef cmHexFileConverter_h
#define cmHexFileConverter_h
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+
/** \class cmHexFileConverter
* \brief Can detects Intel Hex and Motorola S-record files and convert them
* to binary files.
@@ -17,8 +21,9 @@ public:
IntelHex,
MotorolaSrec
};
- static FileType DetermineFileType(const char* inFileName);
- static bool TryConvert(const char* inFileName, const char* outFileName);
+ static FileType DetermineFileType(const std::string& inFileName);
+ static bool TryConvert(const std::string& inFileName,
+ const std::string& outFileName);
};
#endif
diff --git a/Source/cmIDEFlagTable.h b/Source/cmIDEFlagTable.h
index 152e293eb..ff93432cb 100644
--- a/Source/cmIDEFlagTable.h
+++ b/Source/cmIDEFlagTable.h
@@ -3,13 +3,15 @@
#ifndef cmIDEFlagTable_h
#define cmIDEFlagTable_h
+#include <string>
+
// This is a table mapping XML tag IDE names to command line options
struct cmIDEFlagTable
{
- const char* IDEName; // name used in the IDE xml file
- const char* commandFlag; // command line flag
- const char* comment; // comment
- const char* value; // string value
+ std::string IDEName; // name used in the IDE xml file
+ std::string commandFlag; // command line flag
+ std::string comment; // comment
+ std::string value; // string value
unsigned int special; // flags for special handling requests
enum
{
@@ -27,6 +29,9 @@ struct cmIDEFlagTable
SpaceAppendable = (1 << 7), // a flag that if specified multiple times
// should have its value appended to the
// old value with spaces
+ CommaAppendable = (1 << 8), // a flag that if specified multiple times
+ // should have its value appended to the
+ // old value with commas (e.g. C# /nowarn
UserValueIgnored = UserValue | UserIgnored,
UserValueRequired = UserValue | UserRequired
diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx
index 5e872d2ff..71326d23a 100644
--- a/Source/cmIDEOptions.cxx
+++ b/Source/cmIDEOptions.cxx
@@ -2,17 +2,21 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmIDEOptions.h"
-#include "cmsys/String.h"
#include <iterator>
+
#include <string.h>
+#include "cmsys/String.h"
+
+#include "cmAlgorithms.h"
#include "cmIDEFlagTable.h"
-#include "cmSystemTools.h"
+#include "cmStringAlgorithms.h"
cmIDEOptions::cmIDEOptions()
{
this->DoingDefine = false;
this->AllowDefine = true;
+ this->DoingInclude = false;
this->AllowSlash = false;
this->DoingFollowing = 0;
for (int i = 0; i < FlagTableCount; ++i) {
@@ -24,7 +28,7 @@ cmIDEOptions::~cmIDEOptions()
{
}
-void cmIDEOptions::HandleFlag(const char* flag)
+void cmIDEOptions::HandleFlag(std::string const& flag)
{
// If the last option was -D then this option is the definition.
if (this->DoingDefine) {
@@ -33,6 +37,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);
@@ -41,15 +52,27 @@ void cmIDEOptions::HandleFlag(const char* flag)
}
// Look for known arguments.
- if (flag[0] == '-' || (this->AllowSlash && flag[0] == '/')) {
+ size_t len = flag.length();
+ if (len > 0 && (flag[0] == '-' || (this->AllowSlash && flag[0] == '/'))) {
// Look for preprocessor definitions.
- if (this->AllowDefine && flag[1] == 'D') {
- if (flag[2] == '\0') {
+ if (this->AllowDefine && len > 1 && flag[1] == 'D') {
+ if (len <= 2) {
// The next argument will have the definition.
this->DoingDefine = true;
} else {
// Store this definition.
- this->Defines.push_back(flag + 2);
+ this->Defines.push_back(flag.substr(2));
+ }
+ return;
+ }
+ // Look for include directory.
+ if (this->AllowInclude && len > 1 && flag[1] == 'I') {
+ if (len <= 2) {
+ // The next argument will have the include directory.
+ this->DoingInclude = true;
+ } else {
+ // Store this include directory.
+ this->Includes.push_back(flag.substr(2));
}
return;
}
@@ -73,27 +96,28 @@ void cmIDEOptions::HandleFlag(const char* flag)
}
bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table,
- const char* flag, bool& flag_handled)
+ std::string const& flag, bool& flag_handled)
{
+ const char* pf = flag.c_str() + 1;
// Look for an entry in the flag table matching this flag.
- for (cmIDEFlagTable const* entry = table; entry->IDEName; ++entry) {
+ for (cmIDEFlagTable const* entry = table; !entry->IDEName.empty(); ++entry) {
bool entry_found = false;
if (entry->special & cmIDEFlagTable::UserValue) {
// This flag table entry accepts a user-specified value. If
// the entry specifies UserRequired we must match only if a
// non-empty value is given.
- int n = static_cast<int>(strlen(entry->commandFlag));
- if ((strncmp(flag + 1, entry->commandFlag, n) == 0 ||
+ int n = static_cast<int>(entry->commandFlag.length());
+ if ((strncmp(pf, entry->commandFlag.c_str(), n) == 0 ||
(entry->special & cmIDEFlagTable::CaseInsensitive &&
- cmsysString_strncasecmp(flag + 1, entry->commandFlag, n))) &&
+ cmsysString_strncasecmp(pf, entry->commandFlag.c_str(), n))) &&
(!(entry->special & cmIDEFlagTable::UserRequired) ||
- static_cast<int>(strlen(flag + 1)) > n)) {
- this->FlagMapUpdate(entry, flag + n + 1);
+ static_cast<int>(strlen(pf)) > n)) {
+ this->FlagMapUpdate(entry, std::string(pf + n));
entry_found = true;
}
- } else if (strcmp(flag + 1, entry->commandFlag) == 0 ||
+ } else if (strcmp(pf, entry->commandFlag.c_str()) == 0 ||
(entry->special & cmIDEFlagTable::CaseInsensitive &&
- cmsysString_strcasecmp(flag + 1, entry->commandFlag) == 0)) {
+ cmsysString_strcasecmp(pf, entry->commandFlag.c_str()) == 0)) {
if (entry->special & cmIDEFlagTable::UserFollowing) {
// This flag expects a value in the following argument.
this->DoingFollowing = entry;
@@ -118,7 +142,7 @@ bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table,
}
void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry,
- const char* new_value)
+ std::string const& new_value)
{
if (entry->special & cmIDEFlagTable::UserIgnored) {
// Ignore the user-specified value.
@@ -127,6 +151,8 @@ void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry,
this->FlagMap[entry->IDEName].push_back(new_value);
} else if (entry->special & cmIDEFlagTable::SpaceAppendable) {
this->FlagMap[entry->IDEName].append_with_space(new_value);
+ } else if (entry->special & cmIDEFlagTable::CommaAppendable) {
+ this->FlagMap[entry->IDEName].append_with_comma(new_value);
} else {
// Use the user-specified value.
this->FlagMap[entry->IDEName] = new_value;
@@ -138,16 +164,16 @@ void cmIDEOptions::AddDefine(const std::string& def)
this->Defines.push_back(def);
}
-void cmIDEOptions::AddDefines(const char* defines)
+void cmIDEOptions::AddDefines(std::string const& defines)
{
- if (defines) {
+ if (!defines.empty()) {
// Expand the list of definitions.
- cmSystemTools::ExpandListArgument(defines, this->Defines);
+ cmExpandList(defines, this->Defines);
}
}
void cmIDEOptions::AddDefines(const std::vector<std::string>& defines)
{
- this->Defines.insert(this->Defines.end(), defines.begin(), defines.end());
+ cmAppend(this->Defines, defines);
}
std::vector<std::string> const& cmIDEOptions::GetDefines() const
@@ -155,12 +181,34 @@ 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(std::string const& includes)
+{
+ if (!includes.empty()) {
+ // Expand the list of includes.
+ cmExpandList(includes, this->Includes);
+ }
+}
+void cmIDEOptions::AddIncludes(const std::vector<std::string>& includes)
+{
+ cmAppend(this->Includes, includes);
+}
+
+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 +233,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 +243,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 19e96bd44..f949ae3dd 100644
--- a/Source/cmIDEOptions.h
+++ b/Source/cmIDEOptions.h
@@ -3,7 +3,7 @@
#ifndef cmIDEOptions_h
#define cmIDEOptions_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
#include <string>
@@ -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(std::string const& 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(std::string const& 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
@@ -46,7 +51,7 @@ protected:
// and overwrite or add new values to this map
class FlagValue : public std::vector<std::string>
{
- typedef std::vector<std::string> derived;
+ using derived = std::vector<std::string>;
public:
FlagValue& operator=(std::string const& r)
@@ -60,12 +65,22 @@ protected:
this->derived::operator=(r);
return *this;
}
+ FlagValue& append_with_comma(std::string const& r)
+ {
+ return append_with_separator(r, ',');
+ }
FlagValue& append_with_space(std::string const& r)
{
+ return append_with_separator(r, ' ');
+ }
+
+ private:
+ FlagValue& append_with_separator(std::string const& r, char separator)
+ {
this->resize(1);
std::string& l = this->operator[](0);
if (!l.empty()) {
- l += " ";
+ l += separator;
}
l += r;
return *this;
@@ -76,8 +91,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
@@ -85,11 +105,12 @@ protected:
FlagTableCount = 16
};
cmIDEFlagTable const* FlagTable[FlagTableCount];
- void HandleFlag(const char* flag);
- bool CheckFlagTable(cmIDEFlagTable const* table, const char* flag,
+ void HandleFlag(std::string const& flag);
+ bool CheckFlagTable(cmIDEFlagTable const* table, std::string const& flag,
bool& flag_handled);
- void FlagMapUpdate(cmIDEFlagTable const* entry, const char* new_value);
- virtual void StoreUnknownFlag(const char* flag) = 0;
+ void FlagMapUpdate(cmIDEFlagTable const* entry,
+ std::string const& new_value);
+ virtual void StoreUnknownFlag(std::string const& flag) = 0;
};
#endif
diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx
index 0972664a2..290e064b4 100644
--- a/Source/cmIfCommand.cxx
+++ b/Source/cmIfCommand.cxx
@@ -2,218 +2,210 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmIfCommand.h"
+#include <string>
+#include <utility>
+
+#include <cm/memory>
+#include <cm/string_view>
+
+#include "cm_static_string_view.hxx"
+
#include "cmConditionEvaluator.h"
#include "cmExecutionStatus.h"
#include "cmExpandedCommandArgument.h"
+#include "cmFunctionBlocker.h"
+#include "cmListFileCache.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmOutputConverter.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cm_auto_ptr.hxx"
#include "cmake.h"
static std::string cmIfCommandError(
std::vector<cmExpandedCommandArgument> const& args)
{
std::string err = "given arguments:\n ";
- for (std::vector<cmExpandedCommandArgument>::const_iterator i = args.begin();
- i != args.end(); ++i) {
+ for (cmExpandedCommandArgument const& i : args) {
err += " ";
- err += cmOutputConverter::EscapeForCMake(i->GetValue());
+ err += cmOutputConverter::EscapeForCMake(i.GetValue());
}
err += "\n";
return err;
}
-//=========================================================================
-bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
- cmMakefile& mf,
- cmExecutionStatus& inStatus)
+class cmIfFunctionBlocker : public cmFunctionBlocker
+{
+public:
+ cm::string_view StartCommandName() const override { return "if"_s; }
+ cm::string_view EndCommandName() const override { return "endif"_s; }
+
+ bool ArgumentsMatch(cmListFileFunction const& lff,
+ cmMakefile&) const override;
+
+ bool Replay(std::vector<cmListFileFunction> functions,
+ cmExecutionStatus& inStatus) override;
+
+ std::vector<cmListFileArgument> Args;
+ bool IsBlocking;
+ bool HasRun = false;
+ bool ElseSeen = false;
+};
+
+bool cmIfFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
+ cmMakefile&) const
{
- // we start by recording all the functions
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "if")) {
- this->ScopeDepth++;
- } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endif")) {
- this->ScopeDepth--;
- // if this is the endif for this if statement, then start executing
- if (!this->ScopeDepth) {
- // Remove the function blocker for this scope or bail.
- CM_AUTO_PTR<cmFunctionBlocker> fb(mf.RemoveFunctionBlocker(this, lff));
- if (!fb.get()) {
- return false;
+ return lff.Arguments.empty() || lff.Arguments == this->Args;
+}
+
+bool cmIfFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,
+ cmExecutionStatus& inStatus)
+{
+ cmMakefile& mf = inStatus.GetMakefile();
+ // execute the functions for the true parts of the if statement
+ int scopeDepth = 0;
+ for (cmListFileFunction const& func : functions) {
+ // keep track of scope depth
+ if (func.Name.Lower == "if") {
+ scopeDepth++;
+ }
+ if (func.Name.Lower == "endif") {
+ scopeDepth--;
+ }
+ // watch for our state change
+ if (scopeDepth == 0 && func.Name.Lower == "else") {
+
+ if (this->ElseSeen) {
+ cmListFileBacktrace bt = mf.GetBacktrace(func);
+ mf.GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "A duplicate ELSE command was found inside an IF block.", bt);
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
}
- // execute the functions for the true parts of the if statement
- cmExecutionStatus status;
- int scopeDepth = 0;
- for (unsigned int c = 0; c < this->Functions.size(); ++c) {
- // keep track of scope depth
- if (!cmSystemTools::Strucmp(this->Functions[c].Name.c_str(), "if")) {
- scopeDepth++;
- }
- if (!cmSystemTools::Strucmp(this->Functions[c].Name.c_str(),
- "endif")) {
- scopeDepth--;
+ this->IsBlocking = this->HasRun;
+ this->HasRun = true;
+ this->ElseSeen = true;
+
+ // if trace is enabled, print a (trivially) evaluated "else"
+ // statement
+ if (!this->IsBlocking && mf.GetCMakeInstance()->GetTrace()) {
+ mf.PrintCommandTrace(func);
+ }
+ } else if (scopeDepth == 0 && func.Name.Lower == "elseif") {
+ if (this->ElseSeen) {
+ cmListFileBacktrace bt = mf.GetBacktrace(func);
+ mf.GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "An ELSEIF command was found after an ELSE command.", bt);
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+
+ if (this->HasRun) {
+ this->IsBlocking = true;
+ } else {
+ // if trace is enabled, print the evaluated "elseif" statement
+ if (mf.GetCMakeInstance()->GetTrace()) {
+ mf.PrintCommandTrace(func);
}
- // watch for our state change
- if (scopeDepth == 0 &&
- !cmSystemTools::Strucmp(this->Functions[c].Name.c_str(), "else")) {
-
- if (this->ElseSeen) {
- cmListFileBacktrace bt = mf.GetBacktrace(this->Functions[c]);
- mf.GetCMakeInstance()->IssueMessage(
- cmake::FATAL_ERROR,
- "A duplicate ELSE command was found inside an IF block.", bt);
- cmSystemTools::SetFatalErrorOccured();
- return true;
- }
- this->IsBlocking = this->HasRun;
- this->HasRun = true;
- this->ElseSeen = true;
+ std::string errorString;
- // if trace is enabled, print a (trivially) evaluated "else"
- // statement
- if (!this->IsBlocking && mf.GetCMakeInstance()->GetTrace()) {
- mf.PrintCommandTrace(this->Functions[c]);
- }
- } else if (scopeDepth == 0 &&
- !cmSystemTools::Strucmp(this->Functions[c].Name.c_str(),
- "elseif")) {
- if (this->ElseSeen) {
- cmListFileBacktrace bt = mf.GetBacktrace(this->Functions[c]);
- mf.GetCMakeInstance()->IssueMessage(
- cmake::FATAL_ERROR,
- "An ELSEIF command was found after an ELSE command.", bt);
+ std::vector<cmExpandedCommandArgument> expandedArguments;
+ mf.ExpandArguments(func.Arguments, expandedArguments);
+
+ MessageType messType;
+
+ cmListFileContext conditionContext =
+ cmListFileContext::FromCommandContext(
+ func, this->GetStartingContext().FilePath);
+
+ cmConditionEvaluator conditionEvaluator(mf, conditionContext,
+ mf.GetBacktrace(func));
+
+ bool isTrue =
+ conditionEvaluator.IsTrue(expandedArguments, errorString, messType);
+
+ if (!errorString.empty()) {
+ std::string err =
+ cmStrCat(cmIfCommandError(expandedArguments), errorString);
+ cmListFileBacktrace bt = mf.GetBacktrace(func);
+ mf.GetCMakeInstance()->IssueMessage(messType, err, bt);
+ if (messType == MessageType::FATAL_ERROR) {
cmSystemTools::SetFatalErrorOccured();
return true;
}
-
- if (this->HasRun) {
- this->IsBlocking = true;
- } else {
- // if trace is enabled, print the evaluated "elseif" statement
- if (mf.GetCMakeInstance()->GetTrace()) {
- mf.PrintCommandTrace(this->Functions[c]);
- }
-
- std::string errorString;
-
- std::vector<cmExpandedCommandArgument> expandedArguments;
- mf.ExpandArguments(this->Functions[c].Arguments,
- expandedArguments);
-
- cmake::MessageType messType;
-
- cmListFileContext conditionContext =
- cmListFileContext::FromCommandContext(
- this->Functions[c], this->GetStartingContext().FilePath);
-
- cmConditionEvaluator conditionEvaluator(
- mf, conditionContext, mf.GetBacktrace(this->Functions[c]));
-
- bool isTrue = conditionEvaluator.IsTrue(expandedArguments,
- errorString, messType);
-
- if (!errorString.empty()) {
- std::string err = cmIfCommandError(expandedArguments);
- err += errorString;
- cmListFileBacktrace bt = mf.GetBacktrace(this->Functions[c]);
- mf.GetCMakeInstance()->IssueMessage(messType, err, bt);
- if (messType == cmake::FATAL_ERROR) {
- cmSystemTools::SetFatalErrorOccured();
- return true;
- }
- }
-
- if (isTrue) {
- this->IsBlocking = false;
- this->HasRun = true;
- }
- }
}
- // should we execute?
- else if (!this->IsBlocking) {
- status.Clear();
- mf.ExecuteCommand(this->Functions[c], status);
- if (status.GetReturnInvoked()) {
- inStatus.SetReturnInvoked();
- return true;
- }
- if (status.GetBreakInvoked()) {
- inStatus.SetBreakInvoked();
- return true;
- }
- if (status.GetContinueInvoked()) {
- inStatus.SetContinueInvoked();
- return true;
- }
+ if (isTrue) {
+ this->IsBlocking = false;
+ this->HasRun = true;
}
}
- return true;
}
- }
- // record the command
- this->Functions.push_back(lff);
-
- // always return true
- return true;
-}
-
-//=========================================================================
-bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
- cmMakefile&)
-{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endif")) {
- // if the endif has arguments, then make sure
- // they match the arguments of the matching if
- if (lff.Arguments.empty() || lff.Arguments == this->Args) {
- return true;
+ // should we execute?
+ else if (!this->IsBlocking) {
+ cmExecutionStatus status(mf);
+ mf.ExecuteCommand(func, status);
+ if (status.GetReturnInvoked()) {
+ inStatus.SetReturnInvoked();
+ return true;
+ }
+ if (status.GetBreakInvoked()) {
+ inStatus.SetBreakInvoked();
+ return true;
+ }
+ if (status.GetContinueInvoked()) {
+ inStatus.SetContinueInvoked();
+ return true;
+ }
}
}
-
- return false;
+ return true;
}
//=========================================================================
-bool cmIfCommand::InvokeInitialPass(
- const std::vector<cmListFileArgument>& args, cmExecutionStatus&)
+bool cmIfCommand(std::vector<cmListFileArgument> const& args,
+ cmExecutionStatus& inStatus)
{
+ cmMakefile& makefile = inStatus.GetMakefile();
std::string errorString;
std::vector<cmExpandedCommandArgument> expandedArguments;
- this->Makefile->ExpandArguments(args, expandedArguments);
+ makefile.ExpandArguments(args, expandedArguments);
- cmake::MessageType status;
+ MessageType status;
cmConditionEvaluator conditionEvaluator(
- *(this->Makefile), this->Makefile->GetExecutionContext(),
- this->Makefile->GetBacktrace());
+ makefile, makefile.GetExecutionContext(), makefile.GetBacktrace());
bool isTrue =
conditionEvaluator.IsTrue(expandedArguments, errorString, status);
if (!errorString.empty()) {
- std::string err = "if " + cmIfCommandError(expandedArguments);
- err += errorString;
- if (status == cmake::FATAL_ERROR) {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, err);
+ std::string err =
+ cmStrCat("if ", cmIfCommandError(expandedArguments), errorString);
+ if (status == MessageType::FATAL_ERROR) {
+ makefile.IssueMessage(MessageType::FATAL_ERROR, err);
cmSystemTools::SetFatalErrorOccured();
return true;
}
- this->Makefile->IssueMessage(status, err);
+ makefile.IssueMessage(status, err);
}
- cmIfFunctionBlocker* f = new cmIfFunctionBlocker();
- // if is isn't true block the commands
- f->ScopeDepth = 1;
- f->IsBlocking = !isTrue;
- if (isTrue) {
- f->HasRun = true;
+ {
+ auto fb = cm::make_unique<cmIfFunctionBlocker>();
+ // if is isn't true block the commands
+ fb->IsBlocking = !isTrue;
+ if (isTrue) {
+ fb->HasRun = true;
+ }
+ fb->Args = args;
+ makefile.AddFunctionBlocker(std::move(fb));
}
- f->Args = args;
- this->Makefile->AddFunctionBlocker(f);
return true;
}
diff --git a/Source/cmIfCommand.h b/Source/cmIfCommand.h
index 5877a7d12..820ffa4c6 100644
--- a/Source/cmIfCommand.h
+++ b/Source/cmIfCommand.h
@@ -3,70 +3,15 @@
#ifndef cmIfCommand_h
#define cmIfCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include <string>
#include <vector>
-#include "cmCommand.h"
-#include "cmFunctionBlocker.h"
-#include "cmListFileCache.h"
-
class cmExecutionStatus;
-class cmExpandedCommandArgument;
-class cmMakefile;
-
-class cmIfFunctionBlocker : public cmFunctionBlocker
-{
-public:
- cmIfFunctionBlocker()
- {
- this->HasRun = false;
- this->ElseSeen = false;
- this->ScopeDepth = 0;
- }
- ~cmIfFunctionBlocker() CM_OVERRIDE {}
- bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
- cmExecutionStatus&) CM_OVERRIDE;
- bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) CM_OVERRIDE;
-
- std::vector<cmListFileArgument> Args;
- std::vector<cmListFileFunction> Functions;
- bool IsBlocking;
- bool HasRun;
- bool ElseSeen;
- unsigned int ScopeDepth;
-};
+struct cmListFileArgument;
/// Starts an if block
-class cmIfCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmIfCommand; }
-
- /**
- * This overrides the default InvokeInitialPass implementation.
- * It records the arguments before expansion.
- */
- bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
- cmExecutionStatus&) CM_OVERRIDE;
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const&,
- cmExecutionStatus&) CM_OVERRIDE
- {
- return false;
- }
-
- // Filter the given variable definition based on policy CMP0054.
- static const char* GetDefinitionIfUnquoted(
- const cmMakefile* mf, cmExpandedCommandArgument const& argument);
-};
+bool cmIfCommand(std::vector<cmListFileArgument> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx
index 12e0c9ab3..14264f487 100644
--- a/Source/cmIncludeCommand.cxx
+++ b/Source/cmIncludeCommand.cxx
@@ -4,21 +4,21 @@
#include <sstream>
+#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmake.h"
-
-class cmExecutionStatus;
// cmIncludeCommand
-bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmIncludeCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty() || args.size() > 4) {
- this->SetError("called with wrong number of arguments. "
- "include() only takes one file.");
+ status.SetError("called with wrong number of arguments. "
+ "include() only takes one file.");
return false;
}
bool optional = false;
@@ -29,20 +29,20 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args,
for (unsigned int i = 1; i < args.size(); i++) {
if (args[i] == "OPTIONAL") {
if (optional) {
- this->SetError("called with invalid arguments: OPTIONAL used twice");
+ status.SetError("called with invalid arguments: OPTIONAL used twice");
return false;
}
optional = true;
} else if (args[i] == "RESULT_VARIABLE") {
if (!resultVarName.empty()) {
- this->SetError("called with invalid arguments: "
- "only one result variable allowed");
+ status.SetError("called with invalid arguments: "
+ "only one result variable allowed");
return false;
}
if (++i < args.size()) {
resultVarName = args[i];
} else {
- this->SetError("called with no value for RESULT_VARIABLE.");
+ status.SetError("called with no value for RESULT_VARIABLE.");
return false;
}
} else if (args[i] == "NO_POLICY_SCOPE") {
@@ -50,39 +50,39 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args,
} else if (i > 1) // compat.: in previous cmake versions the second
// parameter was ignored if it wasn't "OPTIONAL"
{
- std::string errorText = "called with invalid argument: ";
- errorText += args[i];
- this->SetError(errorText);
+ std::string errorText =
+ cmStrCat("called with invalid argument: ", args[i]);
+ status.SetError(errorText);
return false;
}
}
if (fname.empty()) {
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING,
- "include() given empty file name (ignored).");
+ status.GetMakefile().IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ "include() given empty file name (ignored).");
return true;
}
- if (!cmSystemTools::FileIsFullPath(fname.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(fname)) {
// Not a path. Maybe module.
- std::string module = fname;
- module += ".cmake";
- std::string mfile = this->Makefile->GetModulesFile(module.c_str());
+ std::string module = cmStrCat(fname, ".cmake");
+ std::string mfile = status.GetMakefile().GetModulesFile(module);
if (!mfile.empty()) {
fname = mfile;
}
}
std::string fname_abs = cmSystemTools::CollapseFullPath(
- fname, this->Makefile->GetCurrentSourceDirectory());
+ fname, status.GetMakefile().GetCurrentSourceDirectory());
- cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
+ cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator();
if (gg->IsExportedTargetsFile(fname_abs)) {
- const char* modal = CM_NULLPTR;
+ const char* modal = nullptr;
std::ostringstream e;
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ MessageType messageType = MessageType::AUTHOR_WARNING;
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0024)) {
+ switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0024)) {
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0024) << "\n";
modal = "should";
@@ -92,17 +92,18 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args,
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
modal = "may";
- messageType = cmake::FATAL_ERROR;
+ messageType = MessageType::FATAL_ERROR;
}
if (modal) {
- e << "The file\n " << fname_abs << "\nwas generated by the export() "
- "command. It "
+ e << "The file\n " << fname_abs
+ << "\nwas generated by the export() "
+ "command. It "
<< modal
<< " not be used as the argument to the "
"include() command. Use ALIAS targets instead to refer to targets "
"by alternative names.\n";
- this->Makefile->IssueMessage(messageType, e.str());
- if (messageType == cmake::FATAL_ERROR) {
+ status.GetMakefile().IssueMessage(messageType, e.str());
+ if (messageType == MessageType::FATAL_ERROR) {
return false;
}
}
@@ -111,28 +112,28 @@ 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())) {
+ fname, status.GetMakefile().GetCurrentSourceDirectory());
+ if (optional && !cmSystemTools::FileExists(listFile)) {
if (!resultVarName.empty()) {
- this->Makefile->AddDefinition(resultVarName, "NOTFOUND");
+ status.GetMakefile().AddDefinition(resultVarName, "NOTFOUND");
}
return true;
}
bool readit =
- this->Makefile->ReadDependentFile(listFile.c_str(), noPolicyScope);
+ status.GetMakefile().ReadDependentFile(listFile, noPolicyScope);
// add the location of the included file if a result variable was given
if (!resultVarName.empty()) {
- this->Makefile->AddDefinition(resultVarName,
- readit ? fname_abs.c_str() : "NOTFOUND");
+ status.GetMakefile().AddDefinition(
+ resultVarName, readit ? fname_abs.c_str() : "NOTFOUND");
}
if (!optional && !readit && !cmSystemTools::GetFatalErrorOccured()) {
- std::string m = "could not find load file:\n"
- " ";
- m += fname;
- this->SetError(m);
+ std::string m = cmStrCat("could not find load file:\n"
+ " ",
+ fname);
+ status.SetError(m);
return false;
}
return true;
diff --git a/Source/cmIncludeCommand.h b/Source/cmIncludeCommand.h
index 16dda0ef5..b0dd77956 100644
--- a/Source/cmIncludeCommand.h
+++ b/Source/cmIncludeCommand.h
@@ -3,35 +3,20 @@
#ifndef cmIncludeCommand_h
#define cmIncludeCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmIncludeCommand
+/**
* \brief cmIncludeCommand defines a list of distant
* files that can be "included" in the current list file.
* In almost every sense, this is identical to a C/C++
* #include command. Arguments are first expended as usual.
*/
-class cmIncludeCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmIncludeCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmIncludeCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx
index b81f7cb2d..170aea125 100644
--- a/Source/cmIncludeDirectoryCommand.cxx
+++ b/Source/cmIncludeDirectoryCommand.cxx
@@ -4,23 +4,31 @@
#include <algorithm>
#include <set>
+#include <utility>
+#include "cmAlgorithms.h"
+#include "cmExecutionStatus.h"
+#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
+static void GetIncludes(cmMakefile& mf, const std::string& arg,
+ std::vector<std::string>& incs);
+static void NormalizeInclude(cmMakefile& mf, std::string& inc);
-// cmIncludeDirectoryCommand
-bool cmIncludeDirectoryCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmIncludeDirectoryCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
return true;
}
- std::vector<std::string>::const_iterator i = args.begin();
+ cmMakefile& mf = status.GetMakefile();
- bool before = this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_BEFORE");
+ auto i = args.begin();
+
+ bool before = mf.IsOn("CMAKE_INCLUDE_DIRECTORIES_BEFORE");
bool system = false;
if ((*i) == "BEFORE") {
@@ -41,20 +49,18 @@ bool cmIncludeDirectoryCommand::InitialPass(
continue;
}
if (i->empty()) {
- this->SetError("given empty-string as include directory.");
+ status.SetError("given empty-string as include directory.");
return false;
}
std::vector<std::string> includes;
- this->GetIncludes(*i, includes);
+ GetIncludes(mf, *i, includes);
if (before) {
- beforeIncludes.insert(beforeIncludes.end(), includes.begin(),
- includes.end());
+ cmAppend(beforeIncludes, includes);
} else {
- afterIncludes.insert(afterIncludes.end(), includes.begin(),
- includes.end());
+ cmAppend(afterIncludes, includes);
}
if (system) {
systemIncludes.insert(includes.begin(), includes.end());
@@ -62,22 +68,17 @@ bool cmIncludeDirectoryCommand::InitialPass(
}
std::reverse(beforeIncludes.begin(), beforeIncludes.end());
- this->Makefile->AddIncludeDirectories(afterIncludes);
- this->Makefile->AddIncludeDirectories(beforeIncludes, before);
- this->Makefile->AddSystemIncludeDirectories(systemIncludes);
+ mf.AddIncludeDirectories(afterIncludes);
+ mf.AddIncludeDirectories(beforeIncludes, before);
+ mf.AddSystemIncludeDirectories(systemIncludes);
return true;
}
-static bool StartsWithGeneratorExpression(const std::string& input)
-{
- return input[0] == '$' && input[1] == '<';
-}
-
// 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 "
@@ -86,8 +87,8 @@ static bool StartsWithGeneratorExpression(const std::string& input)
// output from a program and passing it into a command the cleanup doesn't
// always happen
//
-void cmIncludeDirectoryCommand::GetIncludes(const std::string& arg,
- std::vector<std::string>& incs)
+static void GetIncludes(cmMakefile& mf, const std::string& arg,
+ std::vector<std::string>& incs)
{
// break apart any line feed arguments
std::string::size_type pos = 0;
@@ -95,41 +96,36 @@ void cmIncludeDirectoryCommand::GetIncludes(const std::string& arg,
while ((pos = arg.find('\n', lastPos)) != std::string::npos) {
if (pos) {
std::string inc = arg.substr(lastPos, pos);
- this->NormalizeInclude(inc);
+ NormalizeInclude(mf, inc);
if (!inc.empty()) {
- incs.push_back(inc);
+ incs.push_back(std::move(inc));
}
}
lastPos = pos + 1;
}
std::string inc = arg.substr(lastPos);
- this->NormalizeInclude(inc);
+ NormalizeInclude(mf, inc);
if (!inc.empty()) {
- incs.push_back(inc);
+ incs.push_back(std::move(inc));
}
}
-void cmIncludeDirectoryCommand::NormalizeInclude(std::string& inc)
+static void NormalizeInclude(cmMakefile& mf, std::string& inc)
{
std::string::size_type b = inc.find_first_not_of(" \r");
std::string::size_type e = inc.find_last_not_of(" \r");
if ((b != std::string::npos) && (e != std::string::npos)) {
inc.assign(inc, b, 1 + e - b); // copy the remaining substring
} else {
- inc = "";
+ inc.clear();
return;
}
- if (!cmSystemTools::IsOff(inc.c_str())) {
+ if (!cmIsOff(inc)) {
cmSystemTools::ConvertToUnixSlashes(inc);
-
- if (!cmSystemTools::FileIsFullPath(inc.c_str())) {
- if (!StartsWithGeneratorExpression(inc)) {
- std::string tmp = this->Makefile->GetCurrentSourceDirectory();
- tmp += "/";
- tmp += inc;
- inc = tmp;
- }
+ if (!cmSystemTools::FileIsFullPath(inc) &&
+ !cmGeneratorExpression::StartsWithGeneratorExpression(inc)) {
+ inc = cmStrCat(mf.GetCurrentSourceDirectory(), '/', inc);
}
}
}
diff --git a/Source/cmIncludeDirectoryCommand.h b/Source/cmIncludeDirectoryCommand.h
index 12de698cb..66caff721 100644
--- a/Source/cmIncludeDirectoryCommand.h
+++ b/Source/cmIncludeDirectoryCommand.h
@@ -3,40 +3,14 @@
#ifndef cmIncludeDirectoryCommand_h
#define cmIncludeDirectoryCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmIncludeDirectoryCommand
- * \brief Add include directories to the build.
- *
- * cmIncludeDirectoryCommand is used to specify directory locations
- * to search for included files.
- */
-class cmIncludeDirectoryCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmIncludeDirectoryCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-protected:
- // used internally
- void GetIncludes(const std::string& arg, std::vector<std::string>& incs);
- void NormalizeInclude(std::string& inc);
-};
+bool cmIncludeDirectoryCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmIncludeExternalMSProjectCommand.cxx b/Source/cmIncludeExternalMSProjectCommand.cxx
index 03388c7e9..fa1e8bcf9 100644
--- a/Source/cmIncludeExternalMSProjectCommand.cxx
+++ b/Source/cmIncludeExternalMSProjectCommand.cxx
@@ -2,27 +2,31 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmIncludeExternalMSProjectCommand.h"
+#include "cmExecutionStatus.h"
+
#ifdef _WIN32
-#include "cmMakefile.h"
-#include "cmStateTypes.h"
-#include "cmSystemTools.h"
-#include "cmTarget.h"
+# include "cmGlobalGenerator.h"
+# include "cmMakefile.h"
+# include "cmStateTypes.h"
+# include "cmSystemTools.h"
+# include "cmTarget.h"
+# include "cmake.h"
#endif
-class cmExecutionStatus;
-
-// cmIncludeExternalMSProjectCommand
-bool cmIncludeExternalMSProjectCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmIncludeExternalMSProjectCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("INCLUDE_EXTERNAL_MSPROJECT called with incorrect "
- "number of arguments");
+ status.SetError("INCLUDE_EXTERNAL_MSPROJECT called with incorrect "
+ "number of arguments");
return false;
}
+
// only compile this for win32 to avoid coverage errors
#ifdef _WIN32
- if (this->Makefile->GetDefinition("WIN32")) {
+ cmMakefile& mf = status.GetMakefile();
+ if (mf.GetDefinition("WIN32") ||
+ mf.GetGlobalGenerator()->IsIncludeExternalMSProjectSupported()) {
enum Doing
{
DoingNone,
@@ -73,27 +77,28 @@ bool cmIncludeExternalMSProjectCommand::InitialPass(
if (!customGuid.empty()) {
std::string guidVariable = utility_name + "_GUID_CMAKE";
- this->Makefile->GetCMakeInstance()->AddCacheEntry(
- guidVariable.c_str(), customGuid.c_str(), "Stored GUID",
- cmStateEnums::INTERNAL);
+ mf.GetCMakeInstance()->AddCacheEntry(guidVariable.c_str(),
+ customGuid.c_str(), "Stored GUID",
+ cmStateEnums::INTERNAL);
}
// Create a target instance for this utility.
- cmTarget* target = this->Makefile->AddNewTarget(cmStateEnums::UTILITY,
- utility_name.c_str());
+ cmTarget* target =
+ mf.AddNewTarget(cmStateEnums::UTILITY, utility_name.c_str());
+ if (mf.GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+ target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
+ }
target->SetProperty("GENERATOR_FILE_NAME", utility_name.c_str());
target->SetProperty("EXTERNAL_MSPROJECT", path.c_str());
- target->SetProperty("EXCLUDE_FROM_ALL", "FALSE");
if (!customType.empty())
target->SetProperty("VS_PROJECT_TYPE", customType.c_str());
if (!platformMapping.empty())
target->SetProperty("VS_PLATFORM_MAPPING", platformMapping.c_str());
- for (std::vector<std::string>::const_iterator it = depends.begin();
- it != depends.end(); ++it) {
- target->AddUtility(it->c_str());
+ for (std::string const& d : depends) {
+ target->AddUtility(d.c_str());
}
}
#endif
diff --git a/Source/cmIncludeExternalMSProjectCommand.h b/Source/cmIncludeExternalMSProjectCommand.h
index 375646fa6..1013c4435 100644
--- a/Source/cmIncludeExternalMSProjectCommand.h
+++ b/Source/cmIncludeExternalMSProjectCommand.h
@@ -3,39 +3,14 @@
#ifndef cmIncludeExternalMSProjectCommand_h
#define cmIncludeExternalMSProjectCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmIncludeExternalMSProjectCommand
- * \brief Specify an external MS project file for inclusion in the workspace.
- *
- * cmIncludeExternalMSProjectCommand is used to specify an externally
- * generated Microsoft project file for inclusion in the default workspace
- * generated by CMake.
- */
-class cmIncludeExternalMSProjectCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE
- {
- return new cmIncludeExternalMSProjectCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmIncludeExternalMSProjectCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmIncludeGuardCommand.cxx b/Source/cmIncludeGuardCommand.cxx
new file mode 100644
index 000000000..ccb4496e6
--- /dev/null
+++ b/Source/cmIncludeGuardCommand.cxx
@@ -0,0 +1,108 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmIncludeGuardCommand.h"
+
+#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+namespace {
+
+enum IncludeGuardScope
+{
+ VARIABLE,
+ DIRECTORY,
+ GLOBAL
+};
+
+std::string GetIncludeGuardVariableName(std::string const& filePath)
+{
+ std::string result = "__INCGUARD_";
+#ifndef CMAKE_BOOTSTRAP
+ result += cmSystemTools::ComputeStringMD5(filePath);
+#else
+ result += cmSystemTools::MakeCidentifier(filePath);
+#endif
+ result += "__";
+ return result;
+}
+
+bool CheckIncludeGuardIsSet(cmMakefile* mf, std::string const& includeGuardVar)
+{
+ if (mf->GetProperty(includeGuardVar)) {
+ return true;
+ }
+ cmStateSnapshot dirSnapshot =
+ mf->GetStateSnapshot().GetBuildsystemDirectoryParent();
+ while (dirSnapshot.GetState()) {
+ cmStateDirectory stateDir = dirSnapshot.GetDirectory();
+ if (stateDir.GetProperty(includeGuardVar)) {
+ return true;
+ }
+ dirSnapshot = dirSnapshot.GetBuildsystemDirectoryParent();
+ }
+ return false;
+}
+
+} // anonymous namespace
+
+// cmIncludeGuardCommand
+bool cmIncludeGuardCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.size() > 1) {
+ status.SetError(
+ "given an invalid number of arguments. The command takes at "
+ "most 1 argument.");
+ return false;
+ }
+
+ IncludeGuardScope scope = VARIABLE;
+
+ if (!args.empty()) {
+ std::string const& arg = args[0];
+ if (arg == "DIRECTORY") {
+ scope = DIRECTORY;
+ } else if (arg == "GLOBAL") {
+ scope = GLOBAL;
+ } else {
+ status.SetError("given an invalid scope: " + arg);
+ return false;
+ }
+ }
+
+ std::string includeGuardVar = GetIncludeGuardVariableName(
+ status.GetMakefile().GetDefinition("CMAKE_CURRENT_LIST_FILE"));
+
+ cmMakefile* const mf = &status.GetMakefile();
+
+ switch (scope) {
+ case VARIABLE:
+ if (mf->IsDefinitionSet(includeGuardVar)) {
+ status.SetReturnInvoked();
+ return true;
+ }
+ mf->AddDefinitionBool(includeGuardVar, true);
+ break;
+ case DIRECTORY:
+ if (CheckIncludeGuardIsSet(mf, includeGuardVar)) {
+ status.SetReturnInvoked();
+ return true;
+ }
+ mf->SetProperty(includeGuardVar, "TRUE");
+ break;
+ case GLOBAL:
+ cmake* const cm = mf->GetCMakeInstance();
+ if (cm->GetProperty(includeGuardVar)) {
+ status.SetReturnInvoked();
+ return true;
+ }
+ cm->SetProperty(includeGuardVar, "TRUE");
+ break;
+ }
+
+ return true;
+}
diff --git a/Source/cmIncludeGuardCommand.h b/Source/cmIncludeGuardCommand.h
new file mode 100644
index 000000000..b86b76015
--- /dev/null
+++ b/Source/cmIncludeGuardCommand.h
@@ -0,0 +1,22 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmIncludeGuardCommand_h
+#define cmIncludeGuardCommand_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+class cmExecutionStatus;
+
+/**
+ * \brief cmIncludeGuardCommand identical to C++ #pragma_once command
+ * Can work in 3 modes: GLOBAL (works on global properties),
+ * DIRECTORY(use directory property), VARIABLE(unnamed overload without
+ * arguments) define an ordinary variable to be used as include guard checker
+ */
+bool cmIncludeGuardCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+
+#endif
diff --git a/Source/cmIncludeRegularExpressionCommand.cxx b/Source/cmIncludeRegularExpressionCommand.cxx
index 073c95f7d..655ebd6e4 100644
--- a/Source/cmIncludeRegularExpressionCommand.cxx
+++ b/Source/cmIncludeRegularExpressionCommand.cxx
@@ -2,22 +2,22 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmIncludeRegularExpressionCommand.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-class cmExecutionStatus;
-
-// cmIncludeRegularExpressionCommand
-bool cmIncludeRegularExpressionCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmIncludeRegularExpressionCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- if ((args.empty()) || (args.size() > 2)) {
- this->SetError("called with incorrect number of arguments");
+ if (args.empty() || args.size() > 2) {
+ status.SetError("called with incorrect number of arguments");
return false;
}
- this->Makefile->SetIncludeRegularExpression(args[0].c_str());
+
+ cmMakefile& mf = status.GetMakefile();
+ mf.SetIncludeRegularExpression(args[0].c_str());
if (args.size() > 1) {
- this->Makefile->SetComplainRegularExpression(args[1]);
+ mf.SetComplainRegularExpression(args[1]);
}
return true;
diff --git a/Source/cmIncludeRegularExpressionCommand.h b/Source/cmIncludeRegularExpressionCommand.h
index bac4b8fc3..ca152b046 100644
--- a/Source/cmIncludeRegularExpressionCommand.h
+++ b/Source/cmIncludeRegularExpressionCommand.h
@@ -3,38 +3,14 @@
#ifndef cmIncludeRegularExpressionCommand_h
#define cmIncludeRegularExpressionCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmIncludeRegularExpressionCommand
- * \brief Set the regular expression for following #includes.
- *
- * cmIncludeRegularExpressionCommand is used to specify the regular expression
- * that determines whether to follow a #include file in dependency checking.
- */
-class cmIncludeRegularExpressionCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE
- {
- return new cmIncludeRegularExpressionCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmIncludeRegularExpressionCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 294fb178d..0c52cc5b7 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -2,14 +2,20 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallCommand.h"
-#include "cmsys/Glob.hxx"
+#include <cstddef>
+#include <set>
#include <sstream>
-#include <stddef.h>
+#include <utility>
+
+#include <cm/memory>
+
+#include "cmsys/Glob.hxx"
+
+#include "cm_static_string_view.hxx"
-#include "cmAlgorithms.h"
-#include "cmCommandArgumentsHelper.h"
+#include "cmArgumentParser.h"
+#include "cmExecutionStatus.h"
#include "cmExportSet.h"
-#include "cmExportSetMap.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmInstallCommandArguments.h"
@@ -19,100 +25,128 @@
#include "cmInstallGenerator.h"
#include "cmInstallScriptGenerator.h"
#include "cmInstallTargetGenerator.h"
+#include "cmListFileCache.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSubcommandTable.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetExport.h"
-#include "cmake.h"
-class cmExecutionStatus;
+namespace {
+
+class Helper
+{
+public:
+ Helper(cmExecutionStatus& status)
+ : Status(status)
+ , Makefile(&status.GetMakefile())
+ {
+ this->DefaultComponentName = this->Makefile->GetSafeDefinition(
+ "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
+ if (this->DefaultComponentName.empty()) {
+ this->DefaultComponentName = "Unspecified";
+ }
+ }
-static cmInstallTargetGenerator* CreateInstallTargetGenerator(
+ void SetError(std::string const& err) { this->Status.SetError(err); }
+
+ bool MakeFilesFullPath(const char* modeName,
+ const std::vector<std::string>& relFiles,
+ std::vector<std::string>& absFiles);
+ bool CheckCMP0006(bool& failure);
+
+ std::string GetDestination(const cmInstallCommandArguments* args,
+ const std::string& varName,
+ const std::string& guess);
+ std::string GetRuntimeDestination(const cmInstallCommandArguments* args);
+ std::string GetSbinDestination(const cmInstallCommandArguments* args);
+ std::string GetArchiveDestination(const cmInstallCommandArguments* args);
+ std::string GetLibraryDestination(const cmInstallCommandArguments* args);
+ std::string GetIncludeDestination(const cmInstallCommandArguments* args);
+ std::string GetSysconfDestination(const cmInstallCommandArguments* args);
+ std::string GetSharedStateDestination(const cmInstallCommandArguments* args);
+ std::string GetLocalStateDestination(const cmInstallCommandArguments* args);
+ std::string GetRunStateDestination(const cmInstallCommandArguments* args);
+ std::string GetDataRootDestination(const cmInstallCommandArguments* args);
+ std::string GetDataDestination(const cmInstallCommandArguments* args);
+ std::string GetInfoDestination(const cmInstallCommandArguments* args);
+ std::string GetLocaleDestination(const cmInstallCommandArguments* args);
+ std::string GetManDestination(const cmInstallCommandArguments* args);
+ std::string GetDocDestination(const cmInstallCommandArguments* args);
+ std::string GetDestinationForType(const cmInstallCommandArguments* args,
+ const std::string& type);
+
+ cmExecutionStatus& Status;
+ cmMakefile* Makefile;
+ std::string DefaultComponentName;
+};
+
+cmInstallTargetGenerator* CreateInstallTargetGenerator(
cmTarget& target, const cmInstallCommandArguments& args, bool impLib,
- bool forceOpt = false)
+ cmListFileBacktrace const& backtrace, const std::string& destination,
+ bool forceOpt = false, bool namelink = false)
{
cmInstallGenerator::MessageLevel message =
cmInstallGenerator::SelectMessageLevel(target.GetMakefile());
target.SetHaveInstallRule(true);
- return new cmInstallTargetGenerator(
- target.GetName(), args.GetDestination().c_str(), impLib,
- args.GetPermissions().c_str(), args.GetConfigurations(),
- args.GetComponent().c_str(), message, args.GetExcludeFromAll(),
- args.GetOptional() || forceOpt);
+ const char* component = namelink ? args.GetNamelinkComponent().c_str()
+ : args.GetComponent().c_str();
+ auto g = new cmInstallTargetGenerator(
+ target.GetName(), destination.c_str(), impLib,
+ args.GetPermissions().c_str(), args.GetConfigurations(), component,
+ message, args.GetExcludeFromAll(), args.GetOptional() || forceOpt,
+ backtrace);
+ target.AddInstallGenerator(g);
+ return g;
+}
+
+cmInstallTargetGenerator* CreateInstallTargetGenerator(
+ cmTarget& target, const cmInstallCommandArguments& args, bool impLib,
+ cmListFileBacktrace const& backtrace, bool forceOpt = false,
+ bool namelink = false)
+{
+ return CreateInstallTargetGenerator(target, args, impLib, backtrace,
+ args.GetDestination(), forceOpt,
+ namelink);
}
-static cmInstallFilesGenerator* CreateInstallFilesGenerator(
+cmInstallFilesGenerator* CreateInstallFilesGenerator(
cmMakefile* mf, const std::vector<std::string>& absFiles,
- const cmInstallCommandArguments& args, bool programs)
+ const cmInstallCommandArguments& args, bool programs,
+ const std::string& destination)
{
cmInstallGenerator::MessageLevel message =
cmInstallGenerator::SelectMessageLevel(mf);
return new cmInstallFilesGenerator(
- absFiles, args.GetDestination().c_str(), programs,
- args.GetPermissions().c_str(), args.GetConfigurations(),
- args.GetComponent().c_str(), message, args.GetExcludeFromAll(),
- args.GetRename().c_str(), args.GetOptional());
+ absFiles, destination.c_str(), programs, args.GetPermissions().c_str(),
+ args.GetConfigurations(), args.GetComponent().c_str(), message,
+ args.GetExcludeFromAll(), args.GetRename().c_str(), args.GetOptional());
}
-// cmInstallCommand
-bool cmInstallCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+cmInstallFilesGenerator* CreateInstallFilesGenerator(
+ cmMakefile* mf, const std::vector<std::string>& absFiles,
+ const cmInstallCommandArguments& args, bool programs)
{
- // Allow calling with no arguments so that arguments may be built up
- // using a variable that may be left empty.
- if (args.empty()) {
- return true;
- }
-
- // Enable the install target.
- this->Makefile->GetGlobalGenerator()->EnableInstallTarget();
-
- this->DefaultComponentName =
- this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
- if (this->DefaultComponentName.empty()) {
- this->DefaultComponentName = "Unspecified";
- }
-
- std::string const& mode = args[0];
-
- // Switch among the command modes.
- if (mode == "SCRIPT") {
- return this->HandleScriptMode(args);
- }
- if (mode == "CODE") {
- return this->HandleScriptMode(args);
- }
- if (mode == "TARGETS") {
- return this->HandleTargetsMode(args);
- }
- if (mode == "FILES") {
- return this->HandleFilesMode(args);
- }
- if (mode == "PROGRAMS") {
- return this->HandleFilesMode(args);
- }
- if (mode == "DIRECTORY") {
- return this->HandleDirectoryMode(args);
- }
- if (mode == "EXPORT") {
- return this->HandleExportMode(args);
- }
- if (mode == "EXPORT_ANDROID_MK") {
- return this->HandleExportAndroidMKMode(args);
- }
-
- // Unknown mode.
- std::string e = "called with unknown mode ";
- e += args[0];
- this->SetError(e);
- return false;
+ return CreateInstallFilesGenerator(mf, absFiles, args, programs,
+ args.GetDestination());
}
-bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args)
+std::set<std::string> const allowedTypes{
+ "BIN", "SBIN", "LIB", "INCLUDE", "SYSCONF",
+ "SHAREDSTATE", "LOCALSTATE", "RUNSTATE", "DATA", "INFO",
+ "LOCALE", "MAN", "DOC",
+};
+
+bool HandleScriptMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- std::string component = this->DefaultComponentName;
+ Helper helper(status);
+
+ std::string component = helper.DefaultComponentName;
int componentCount = 0;
bool doing_script = false;
bool doing_code = false;
@@ -132,137 +166,140 @@ bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args)
}
if (componentCount > 1) {
- this->SetError("given more than one COMPONENT for the SCRIPT or CODE "
- "signature of the INSTALL command. "
- "Use multiple INSTALL commands with one COMPONENT each.");
+ status.SetError("given more than one COMPONENT for the SCRIPT or CODE "
+ "signature of the INSTALL command. "
+ "Use multiple INSTALL commands with one COMPONENT each.");
return false;
}
// Scan the args again, this time adding install generators each time we
// encounter a SCRIPT or CODE arg:
//
- for (size_t i = 0; i < args.size(); ++i) {
- if (args[i] == "SCRIPT") {
+ for (std::string const& arg : args) {
+ if (arg == "SCRIPT") {
doing_script = true;
doing_code = false;
- } else if (args[i] == "CODE") {
+ } else if (arg == "CODE") {
doing_script = false;
doing_code = true;
- } else if (args[i] == "COMPONENT") {
+ } else if (arg == "COMPONENT") {
doing_script = false;
doing_code = false;
} else if (doing_script) {
doing_script = false;
- std::string script = args[i];
- if (!cmSystemTools::FileIsFullPath(script.c_str())) {
- script = this->Makefile->GetCurrentSourceDirectory();
- script += "/";
- script += args[i];
+ std::string script = arg;
+ if (!cmSystemTools::FileIsFullPath(script)) {
+ script =
+ cmStrCat(helper.Makefile->GetCurrentSourceDirectory(), '/', arg);
}
if (cmSystemTools::FileIsDirectory(script)) {
- this->SetError("given a directory as value of SCRIPT argument.");
+ status.SetError("given a directory as value of SCRIPT argument.");
return false;
}
- this->Makefile->AddInstallGenerator(new cmInstallScriptGenerator(
+ helper.Makefile->AddInstallGenerator(new cmInstallScriptGenerator(
script.c_str(), false, component.c_str(), exclude_from_all));
} else if (doing_code) {
doing_code = false;
- std::string const& code = args[i];
- this->Makefile->AddInstallGenerator(new cmInstallScriptGenerator(
+ std::string const& code = arg;
+ helper.Makefile->AddInstallGenerator(new cmInstallScriptGenerator(
code.c_str(), true, component.c_str(), exclude_from_all));
}
}
if (doing_script) {
- this->SetError("given no value for SCRIPT argument.");
+ status.SetError("given no value for SCRIPT argument.");
return false;
}
if (doing_code) {
- this->SetError("given no value for CODE argument.");
+ status.SetError("given no value for CODE argument.");
return false;
}
// Tell the global generator about any installation component names
// specified.
- this->Makefile->GetGlobalGenerator()->AddInstallComponent(component.c_str());
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(component);
return true;
}
-/*struct InstallPart
+bool HandleTargetsMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- InstallPart(cmCommandArgumentsHelper* helper, const char* key,
- cmCommandArgumentGroup* group);
- cmCAStringVector argVector;
- cmInstallCommandArguments args;
-};*/
+ Helper helper(status);
-bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
-{
// This is the TARGETS mode.
std::vector<cmTarget*> targets;
- cmCommandArgumentsHelper argHelper;
- cmCommandArgumentGroup group;
- cmCAStringVector genericArgVector(&argHelper, CM_NULLPTR);
- cmCAStringVector archiveArgVector(&argHelper, "ARCHIVE", &group);
- cmCAStringVector libraryArgVector(&argHelper, "LIBRARY", &group);
- cmCAStringVector runtimeArgVector(&argHelper, "RUNTIME", &group);
- cmCAStringVector objectArgVector(&argHelper, "OBJECTS", &group);
- cmCAStringVector frameworkArgVector(&argHelper, "FRAMEWORK", &group);
- cmCAStringVector bundleArgVector(&argHelper, "BUNDLE", &group);
- cmCAStringVector includesArgVector(&argHelper, "INCLUDES", &group);
- cmCAStringVector privateHeaderArgVector(&argHelper, "PRIVATE_HEADER",
- &group);
- cmCAStringVector publicHeaderArgVector(&argHelper, "PUBLIC_HEADER", &group);
- cmCAStringVector resourceArgVector(&argHelper, "RESOURCE", &group);
- genericArgVector.Follows(CM_NULLPTR);
- group.Follows(&genericArgVector);
-
- argHelper.Parse(&args, CM_NULLPTR);
+ struct ArgVectors
+ {
+ std::vector<std::string> Archive;
+ std::vector<std::string> Library;
+ std::vector<std::string> Runtime;
+ std::vector<std::string> Object;
+ std::vector<std::string> Framework;
+ std::vector<std::string> Bundle;
+ std::vector<std::string> Includes;
+ std::vector<std::string> PrivateHeader;
+ std::vector<std::string> PublicHeader;
+ std::vector<std::string> Resource;
+ };
+
+ static auto const argHelper =
+ cmArgumentParser<ArgVectors>{}
+ .Bind("ARCHIVE"_s, &ArgVectors::Archive)
+ .Bind("LIBRARY"_s, &ArgVectors::Library)
+ .Bind("RUNTIME"_s, &ArgVectors::Runtime)
+ .Bind("OBJECTS"_s, &ArgVectors::Object)
+ .Bind("FRAMEWORK"_s, &ArgVectors::Framework)
+ .Bind("BUNDLE"_s, &ArgVectors::Bundle)
+ .Bind("INCLUDES"_s, &ArgVectors::Includes)
+ .Bind("PRIVATE_HEADER"_s, &ArgVectors::PrivateHeader)
+ .Bind("PUBLIC_HEADER"_s, &ArgVectors::PublicHeader)
+ .Bind("RESOURCE"_s, &ArgVectors::Resource);
+
+ std::vector<std::string> genericArgVector;
+ ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector);
// now parse the generic args (i.e. the ones not specialized on LIBRARY/
// ARCHIVE, RUNTIME etc. (see above)
// These generic args also contain the targets and the export stuff
+ std::vector<std::string> targetList;
+ std::string exports;
std::vector<std::string> unknownArgs;
- cmInstallCommandArguments genericArgs(this->DefaultComponentName);
- cmCAStringVector targetList(&genericArgs.Parser, "TARGETS");
- cmCAString exports(&genericArgs.Parser, "EXPORT",
- &genericArgs.ArgumentGroup);
- targetList.Follows(CM_NULLPTR);
- genericArgs.ArgumentGroup.Follows(&targetList);
- genericArgs.Parse(&genericArgVector.GetVector(), &unknownArgs);
+ cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
+ genericArgs.Bind("TARGETS"_s, targetList);
+ genericArgs.Bind("EXPORT"_s, exports);
+ genericArgs.Parse(genericArgVector, &unknownArgs);
bool success = genericArgs.Finalize();
- cmInstallCommandArguments archiveArgs(this->DefaultComponentName);
- cmInstallCommandArguments libraryArgs(this->DefaultComponentName);
- cmInstallCommandArguments runtimeArgs(this->DefaultComponentName);
- cmInstallCommandArguments objectArgs(this->DefaultComponentName);
- cmInstallCommandArguments frameworkArgs(this->DefaultComponentName);
- cmInstallCommandArguments bundleArgs(this->DefaultComponentName);
- cmInstallCommandArguments privateHeaderArgs(this->DefaultComponentName);
- cmInstallCommandArguments publicHeaderArgs(this->DefaultComponentName);
- cmInstallCommandArguments resourceArgs(this->DefaultComponentName);
+ cmInstallCommandArguments archiveArgs(helper.DefaultComponentName);
+ cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
+ cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName);
+ cmInstallCommandArguments objectArgs(helper.DefaultComponentName);
+ cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName);
+ cmInstallCommandArguments bundleArgs(helper.DefaultComponentName);
+ cmInstallCommandArguments privateHeaderArgs(helper.DefaultComponentName);
+ cmInstallCommandArguments publicHeaderArgs(helper.DefaultComponentName);
+ cmInstallCommandArguments resourceArgs(helper.DefaultComponentName);
cmInstallCommandIncludesArgument includesArgs;
// now parse the args for specific parts of the target (e.g. LIBRARY,
// RUNTIME, ARCHIVE etc.
- archiveArgs.Parse(&archiveArgVector.GetVector(), &unknownArgs);
- libraryArgs.Parse(&libraryArgVector.GetVector(), &unknownArgs);
- runtimeArgs.Parse(&runtimeArgVector.GetVector(), &unknownArgs);
- objectArgs.Parse(&objectArgVector.GetVector(), &unknownArgs);
- frameworkArgs.Parse(&frameworkArgVector.GetVector(), &unknownArgs);
- bundleArgs.Parse(&bundleArgVector.GetVector(), &unknownArgs);
- privateHeaderArgs.Parse(&privateHeaderArgVector.GetVector(), &unknownArgs);
- publicHeaderArgs.Parse(&publicHeaderArgVector.GetVector(), &unknownArgs);
- resourceArgs.Parse(&resourceArgVector.GetVector(), &unknownArgs);
- includesArgs.Parse(&includesArgVector.GetVector(), &unknownArgs);
+ archiveArgs.Parse(argVectors.Archive, &unknownArgs);
+ libraryArgs.Parse(argVectors.Library, &unknownArgs);
+ runtimeArgs.Parse(argVectors.Runtime, &unknownArgs);
+ objectArgs.Parse(argVectors.Object, &unknownArgs);
+ frameworkArgs.Parse(argVectors.Framework, &unknownArgs);
+ bundleArgs.Parse(argVectors.Bundle, &unknownArgs);
+ privateHeaderArgs.Parse(argVectors.PrivateHeader, &unknownArgs);
+ publicHeaderArgs.Parse(argVectors.PublicHeader, &unknownArgs);
+ resourceArgs.Parse(argVectors.Resource, &unknownArgs);
+ includesArgs.Parse(&argVectors.Includes, &unknownArgs);
if (!unknownArgs.empty()) {
// Unknown argument.
- std::ostringstream e;
- e << "TARGETS given unknown argument \"" << unknownArgs[0] << "\".";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("TARGETS given unknown argument \"", unknownArgs[0], "\"."));
return false;
}
@@ -297,7 +334,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
objectArgs.GetNamelinkOnly() || frameworkArgs.GetNamelinkOnly() ||
bundleArgs.GetNamelinkOnly() || privateHeaderArgs.GetNamelinkOnly() ||
publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly()) {
- this->SetError(
+ status.SetError(
"TARGETS given NAMELINK_ONLY option not in LIBRARY group. "
"The NAMELINK_ONLY option may be specified only following LIBRARY.");
return false;
@@ -306,14 +343,38 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
objectArgs.GetNamelinkSkip() || frameworkArgs.GetNamelinkSkip() ||
bundleArgs.GetNamelinkSkip() || privateHeaderArgs.GetNamelinkSkip() ||
publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip()) {
- this->SetError(
+ status.SetError(
"TARGETS given NAMELINK_SKIP option not in LIBRARY group. "
"The NAMELINK_SKIP option may be specified only following LIBRARY.");
return false;
}
+ if (archiveArgs.HasNamelinkComponent() ||
+ runtimeArgs.HasNamelinkComponent() ||
+ objectArgs.HasNamelinkComponent() ||
+ frameworkArgs.HasNamelinkComponent() ||
+ bundleArgs.HasNamelinkComponent() ||
+ privateHeaderArgs.HasNamelinkComponent() ||
+ publicHeaderArgs.HasNamelinkComponent() ||
+ resourceArgs.HasNamelinkComponent()) {
+ status.SetError(
+ "TARGETS given NAMELINK_COMPONENT option not in LIBRARY group. "
+ "The NAMELINK_COMPONENT option may be specified only following "
+ "LIBRARY.");
+ return false;
+ }
if (libraryArgs.GetNamelinkOnly() && libraryArgs.GetNamelinkSkip()) {
- this->SetError("TARGETS given NAMELINK_ONLY and NAMELINK_SKIP. "
- "At most one of these two options may be specified.");
+ status.SetError("TARGETS given NAMELINK_ONLY and NAMELINK_SKIP. "
+ "At most one of these two options may be specified.");
+ return false;
+ }
+ if (!genericArgs.GetType().empty() || !archiveArgs.GetType().empty() ||
+ !libraryArgs.GetType().empty() || !runtimeArgs.GetType().empty() ||
+ !objectArgs.GetType().empty() || !frameworkArgs.GetType().empty() ||
+ !bundleArgs.GetType().empty() || !privateHeaderArgs.GetType().empty() ||
+ !publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty()) {
+ status.SetError(
+ "TARGETS given TYPE option. The TYPE option may only be specified in "
+ " install(FILES) and install(DIRECTORIES).");
return false;
}
@@ -327,28 +388,28 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
}
// Check if there is something to do.
- if (targetList.GetVector().empty()) {
+ if (targetList.empty()) {
return true;
}
- // Check whether this is a DLL platform.
- bool dll_platform =
- (this->Makefile->IsOn("WIN32") || this->Makefile->IsOn("CYGWIN") ||
- this->Makefile->IsOn("MINGW"));
-
- for (std::vector<std::string>::const_iterator targetIt =
- targetList.GetVector().begin();
- targetIt != targetList.GetVector().end(); ++targetIt) {
+ for (std::string const& tgt : targetList) {
- if (this->Makefile->IsAlias(*targetIt)) {
- std::ostringstream e;
- e << "TARGETS given target \"" << (*targetIt) << "\" which is an alias.";
- this->SetError(e.str());
+ if (helper.Makefile->IsAlias(tgt)) {
+ status.SetError(
+ cmStrCat("TARGETS given target \"", tgt, "\" which is an alias."));
return false;
}
// Lookup this target in the current directory.
- if (cmTarget* target =
- this->Makefile->FindLocalNonAliasTarget(*targetIt)) {
+ cmTarget* target = helper.Makefile->FindLocalNonAliasTarget(tgt);
+ if (!target) {
+ // If no local target has been found, find it in the global scope.
+ cmTarget* const global_target =
+ helper.Makefile->GetGlobalGenerator()->FindTarget(tgt, true);
+ if (global_target && !global_target->IsImported()) {
+ target = global_target;
+ }
+ }
+ if (target) {
// Found the target. Check its type.
if (target->GetType() != cmStateEnums::EXECUTABLE &&
target->GetType() != cmStateEnums::STATIC_LIBRARY &&
@@ -356,31 +417,17 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
target->GetType() != cmStateEnums::MODULE_LIBRARY &&
target->GetType() != cmStateEnums::OBJECT_LIBRARY &&
target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
- std::ostringstream e;
- e << "TARGETS given target \"" << (*targetIt)
- << "\" which is not an executable, library, or module.";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("TARGETS given target \"", tgt,
+ "\" which is not an executable, library, or module."));
return false;
}
- if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::string reason;
- if (!this->Makefile->GetGlobalGenerator()->HasKnownObjectFileLocation(
- &reason)) {
- std::ostringstream e;
- e << "TARGETS given OBJECT library \"" << (*targetIt)
- << "\" which may not be installed" << reason << ".";
- this->SetError(e.str());
- return false;
- }
- }
// Store the target in the list to be installed.
targets.push_back(target);
} else {
// Did not find the target.
- std::ostringstream e;
- e << "TARGETS given target \"" << (*targetIt)
- << "\" which does not exist in this directory.";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("TARGETS given target \"", tgt, "\" which does not exist."));
return false;
}
}
@@ -389,6 +436,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// any files of the given type.
bool installsArchive = false;
bool installsLibrary = false;
+ bool installsNamelink = false;
bool installsRuntime = false;
bool installsObject = false;
bool installsFramework = false;
@@ -398,19 +446,19 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
bool installsResource = false;
// Generate install script code to install the given targets.
- for (std::vector<cmTarget*>::iterator ti = targets.begin();
- ti != targets.end(); ++ti) {
+ for (cmTarget* ti : targets) {
// Handle each target type.
- cmTarget& target = *(*ti);
- cmInstallTargetGenerator* archiveGenerator = CM_NULLPTR;
- cmInstallTargetGenerator* libraryGenerator = CM_NULLPTR;
- cmInstallTargetGenerator* runtimeGenerator = CM_NULLPTR;
- cmInstallTargetGenerator* objectGenerator = CM_NULLPTR;
- cmInstallTargetGenerator* frameworkGenerator = CM_NULLPTR;
- cmInstallTargetGenerator* bundleGenerator = CM_NULLPTR;
- cmInstallFilesGenerator* privateHeaderGenerator = CM_NULLPTR;
- cmInstallFilesGenerator* publicHeaderGenerator = CM_NULLPTR;
- cmInstallFilesGenerator* resourceGenerator = CM_NULLPTR;
+ cmTarget& target = *ti;
+ cmInstallTargetGenerator* archiveGenerator = nullptr;
+ cmInstallTargetGenerator* libraryGenerator = nullptr;
+ cmInstallTargetGenerator* namelinkGenerator = nullptr;
+ cmInstallTargetGenerator* runtimeGenerator = nullptr;
+ cmInstallTargetGenerator* objectGenerator = nullptr;
+ cmInstallTargetGenerator* frameworkGenerator = nullptr;
+ cmInstallTargetGenerator* bundleGenerator = nullptr;
+ cmInstallFilesGenerator* privateHeaderGenerator = nullptr;
+ cmInstallFilesGenerator* publicHeaderGenerator = nullptr;
+ cmInstallFilesGenerator* resourceGenerator = nullptr;
// Track whether this is a namelink-only rule.
bool namelinkOnly = false;
@@ -420,7 +468,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// Shared libraries are handled differently on DLL and non-DLL
// platforms. All windows platforms are DLL platforms including
// cygwin. Currently no other platform is a DLL platform.
- if (dll_platform) {
+ if (target.IsDLLPlatform()) {
// When in namelink only mode skip all libraries on Windows.
if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
continue;
@@ -429,18 +477,21 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// This is a DLL platform.
if (!archiveArgs.GetDestination().empty()) {
// The import library uses the ARCHIVE properties.
- archiveGenerator =
- CreateInstallTargetGenerator(target, archiveArgs, true);
+ archiveGenerator = CreateInstallTargetGenerator(
+ target, archiveArgs, true, helper.Makefile->GetBacktrace());
}
if (!runtimeArgs.GetDestination().empty()) {
// The DLL uses the RUNTIME properties.
- runtimeGenerator =
- CreateInstallTargetGenerator(target, runtimeArgs, false);
+ runtimeGenerator = CreateInstallTargetGenerator(
+ target, runtimeArgs, false, helper.Makefile->GetBacktrace());
}
- if ((archiveGenerator == CM_NULLPTR) &&
- (runtimeGenerator == CM_NULLPTR)) {
- this->SetError("Library TARGETS given no DESTINATION!");
- return false;
+ if ((archiveGenerator == nullptr) && (runtimeGenerator == nullptr)) {
+ archiveGenerator = CreateInstallTargetGenerator(
+ target, archiveArgs, true, helper.Makefile->GetBacktrace(),
+ helper.GetArchiveDestination(nullptr));
+ runtimeGenerator = CreateInstallTargetGenerator(
+ target, runtimeArgs, false, helper.Makefile->GetBacktrace(),
+ helper.GetRuntimeDestination(nullptr));
}
} else {
// This is a non-DLL platform.
@@ -454,32 +505,33 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// Use the FRAMEWORK properties.
if (!frameworkArgs.GetDestination().empty()) {
- frameworkGenerator =
- CreateInstallTargetGenerator(target, frameworkArgs, false);
+ frameworkGenerator = CreateInstallTargetGenerator(
+ target, frameworkArgs, false, helper.Makefile->GetBacktrace());
} else {
- std::ostringstream e;
- e << "TARGETS given no FRAMEWORK DESTINATION for shared library "
- "FRAMEWORK target \""
- << target.GetName() << "\".";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("TARGETS given no FRAMEWORK DESTINATION for shared "
+ "library FRAMEWORK target \"",
+ target.GetName(), "\"."));
return false;
}
} else {
// The shared library uses the LIBRARY properties.
- if (!libraryArgs.GetDestination().empty()) {
- libraryGenerator =
- CreateInstallTargetGenerator(target, libraryArgs, false);
- libraryGenerator->SetNamelinkMode(namelinkMode);
- namelinkOnly =
- (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
- } else {
- std::ostringstream e;
- e << "TARGETS given no LIBRARY DESTINATION for shared library "
- "target \""
- << target.GetName() << "\".";
- this->SetError(e.str());
- return false;
+ if (namelinkMode != cmInstallTargetGenerator::NamelinkModeOnly) {
+ libraryGenerator = CreateInstallTargetGenerator(
+ target, libraryArgs, false, helper.Makefile->GetBacktrace(),
+ helper.GetLibraryDestination(&libraryArgs));
+ libraryGenerator->SetNamelinkMode(
+ cmInstallTargetGenerator::NamelinkModeSkip);
+ }
+ if (namelinkMode != cmInstallTargetGenerator::NamelinkModeSkip) {
+ namelinkGenerator = CreateInstallTargetGenerator(
+ target, libraryArgs, false, helper.Makefile->GetBacktrace(),
+ helper.GetLibraryDestination(&libraryArgs), false, true);
+ namelinkGenerator->SetNamelinkMode(
+ cmInstallTargetGenerator::NamelinkModeOnly);
}
+ namelinkOnly =
+ (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
}
}
} break;
@@ -494,109 +546,98 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// Use the FRAMEWORK properties.
if (!frameworkArgs.GetDestination().empty()) {
- frameworkGenerator =
- CreateInstallTargetGenerator(target, frameworkArgs, false);
+ frameworkGenerator = CreateInstallTargetGenerator(
+ target, frameworkArgs, false, helper.Makefile->GetBacktrace());
} else {
- std::ostringstream e;
- e << "TARGETS given no FRAMEWORK DESTINATION for static library "
- "FRAMEWORK target \""
- << target.GetName() << "\".";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("TARGETS given no FRAMEWORK DESTINATION for static "
+ "library FRAMEWORK target \"",
+ target.GetName(), "\"."));
return false;
}
} else {
// Static libraries use ARCHIVE properties.
- if (!archiveArgs.GetDestination().empty()) {
- archiveGenerator =
- CreateInstallTargetGenerator(target, archiveArgs, false);
- } else {
- std::ostringstream e;
- e << "TARGETS given no ARCHIVE DESTINATION for static library "
- "target \""
- << target.GetName() << "\".";
- this->SetError(e.str());
- return false;
- }
+ archiveGenerator = CreateInstallTargetGenerator(
+ target, archiveArgs, false, helper.Makefile->GetBacktrace(),
+ helper.GetArchiveDestination(&archiveArgs));
}
} break;
case cmStateEnums::MODULE_LIBRARY: {
// Modules use LIBRARY properties.
if (!libraryArgs.GetDestination().empty()) {
- libraryGenerator =
- CreateInstallTargetGenerator(target, libraryArgs, false);
+ libraryGenerator = CreateInstallTargetGenerator(
+ target, libraryArgs, false, helper.Makefile->GetBacktrace());
libraryGenerator->SetNamelinkMode(namelinkMode);
namelinkOnly =
(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
} else {
- std::ostringstream e;
- e << "TARGETS given no LIBRARY DESTINATION for module target \""
- << target.GetName() << "\".";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat("TARGETS given no LIBRARY DESTINATION for module "
+ "target \"",
+ target.GetName(), "\"."));
return false;
}
} break;
case cmStateEnums::OBJECT_LIBRARY: {
// Objects use OBJECT properties.
if (!objectArgs.GetDestination().empty()) {
- objectGenerator =
- CreateInstallTargetGenerator(target, objectArgs, false);
+ // Verify that we know where the objects are to install them.
+ std::string reason;
+ if (!helper.Makefile->GetGlobalGenerator()
+ ->HasKnownObjectFileLocation(&reason)) {
+ status.SetError(
+ cmStrCat("TARGETS given OBJECT library \"", target.GetName(),
+ "\" whose objects may not be installed", reason, "."));
+ return false;
+ }
+
+ objectGenerator = CreateInstallTargetGenerator(
+ target, objectArgs, false, helper.Makefile->GetBacktrace());
} else {
- std::ostringstream e;
- e << "TARGETS given no OBJECTS DESTINATION for object library "
- "target \""
- << target.GetName() << "\".";
- this->SetError(e.str());
- return false;
+ // Installing an OBJECT library without a destination transforms
+ // it to an INTERFACE library. It installs no files but can be
+ // exported.
}
} break;
case cmStateEnums::EXECUTABLE: {
if (target.IsAppBundleOnApple()) {
// Application bundles use the BUNDLE properties.
if (!bundleArgs.GetDestination().empty()) {
- bundleGenerator =
- CreateInstallTargetGenerator(target, bundleArgs, false);
+ bundleGenerator = CreateInstallTargetGenerator(
+ target, bundleArgs, false, helper.Makefile->GetBacktrace());
} else if (!runtimeArgs.GetDestination().empty()) {
bool failure = false;
- if (this->CheckCMP0006(failure)) {
+ if (helper.CheckCMP0006(failure)) {
// For CMake 2.4 compatibility fallback to the RUNTIME
// properties.
- bundleGenerator =
- CreateInstallTargetGenerator(target, runtimeArgs, false);
+ bundleGenerator = CreateInstallTargetGenerator(
+ target, runtimeArgs, false, helper.Makefile->GetBacktrace());
} else if (failure) {
return false;
}
}
if (!bundleGenerator) {
- std::ostringstream e;
- e << "TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE "
- "executable target \""
- << target.GetName() << "\".";
- this->SetError(e.str());
+ status.SetError(cmStrCat("TARGETS given no BUNDLE DESTINATION for "
+ "MACOSX_BUNDLE executable target \"",
+ target.GetName(), "\"."));
return false;
}
} else {
// Executables use the RUNTIME properties.
- if (!runtimeArgs.GetDestination().empty()) {
- runtimeGenerator =
- CreateInstallTargetGenerator(target, runtimeArgs, false);
- } else {
- std::ostringstream e;
- e << "TARGETS given no RUNTIME DESTINATION for executable "
- "target \""
- << target.GetName() << "\".";
- this->SetError(e.str());
- return false;
- }
+ runtimeGenerator = CreateInstallTargetGenerator(
+ target, runtimeArgs, false, helper.Makefile->GetBacktrace(),
+ helper.GetRuntimeDestination(&runtimeArgs));
}
// On DLL platforms an executable may also have an import
// library. Install it to the archive destination if it
// exists.
- if (dll_platform && !archiveArgs.GetDestination().empty() &&
+ if ((target.IsDLLPlatform() || target.IsAIX()) &&
+ !archiveArgs.GetDestination().empty() &&
target.IsExecutableWithExports()) {
// The import library uses the ARCHIVE properties.
- archiveGenerator =
- CreateInstallTargetGenerator(target, archiveArgs, true, true);
+ archiveGenerator = CreateInstallTargetGenerator(
+ target, archiveArgs, true, helper.Makefile->GetBacktrace(), true);
}
} break;
case cmStateEnums::INTERFACE_LIBRARY:
@@ -617,103 +658,89 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// generators for them.
bool createInstallGeneratorsForTargetFileSets = true;
- if (target.IsFrameworkOnApple() ||
- target.GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (target.IsFrameworkOnApple()) {
createInstallGeneratorsForTargetFileSets = false;
}
if (createInstallGeneratorsForTargetFileSets && !namelinkOnly) {
const char* files = target.GetProperty("PRIVATE_HEADER");
if ((files) && (*files)) {
- std::vector<std::string> relFiles;
- cmSystemTools::ExpandListArgument(files, relFiles);
+ std::vector<std::string> relFiles = cmExpandedList(files);
std::vector<std::string> absFiles;
- if (!this->MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles)) {
+ if (!helper.MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles)) {
return false;
}
// Create the files install generator.
- if (!privateHeaderArgs.GetDestination().empty()) {
- privateHeaderGenerator = CreateInstallFilesGenerator(
- this->Makefile, absFiles, privateHeaderArgs, false);
- } else {
- std::ostringstream e;
- e << "INSTALL TARGETS - target " << target.GetName() << " has "
- << "PRIVATE_HEADER files but no PRIVATE_HEADER DESTINATION.";
- cmSystemTools::Message(e.str().c_str(), "Warning");
- }
+ privateHeaderGenerator = CreateInstallFilesGenerator(
+ helper.Makefile, absFiles, privateHeaderArgs, false,
+ helper.GetIncludeDestination(&privateHeaderArgs));
}
files = target.GetProperty("PUBLIC_HEADER");
if ((files) && (*files)) {
- std::vector<std::string> relFiles;
- cmSystemTools::ExpandListArgument(files, relFiles);
+ std::vector<std::string> relFiles = cmExpandedList(files);
std::vector<std::string> absFiles;
- if (!this->MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles)) {
+ if (!helper.MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles)) {
return false;
}
// Create the files install generator.
- if (!publicHeaderArgs.GetDestination().empty()) {
- publicHeaderGenerator = CreateInstallFilesGenerator(
- this->Makefile, absFiles, publicHeaderArgs, false);
- } else {
- std::ostringstream e;
- e << "INSTALL TARGETS - target " << target.GetName() << " has "
- << "PUBLIC_HEADER files but no PUBLIC_HEADER DESTINATION.";
- cmSystemTools::Message(e.str().c_str(), "Warning");
- }
+ publicHeaderGenerator = CreateInstallFilesGenerator(
+ helper.Makefile, absFiles, publicHeaderArgs, false,
+ helper.GetIncludeDestination(&publicHeaderArgs));
}
files = target.GetProperty("RESOURCE");
if ((files) && (*files)) {
- std::vector<std::string> relFiles;
- cmSystemTools::ExpandListArgument(files, relFiles);
+ std::vector<std::string> relFiles = cmExpandedList(files);
std::vector<std::string> absFiles;
- if (!this->MakeFilesFullPath("RESOURCE", relFiles, absFiles)) {
+ if (!helper.MakeFilesFullPath("RESOURCE", relFiles, absFiles)) {
return false;
}
// Create the files install generator.
if (!resourceArgs.GetDestination().empty()) {
resourceGenerator = CreateInstallFilesGenerator(
- this->Makefile, absFiles, resourceArgs, false);
+ helper.Makefile, absFiles, resourceArgs, false);
} else {
- std::ostringstream e;
- e << "INSTALL TARGETS - target " << target.GetName() << " has "
- << "RESOURCE files but no RESOURCE DESTINATION.";
- cmSystemTools::Message(e.str().c_str(), "Warning");
+ cmSystemTools::Message(
+ cmStrCat("INSTALL TARGETS - target ", target.GetName(),
+ " has RESOURCE files but no RESOURCE DESTINATION."),
+ "Warning");
}
}
}
// Keep track of whether we're installing anything in each category
- installsArchive = installsArchive || archiveGenerator != CM_NULLPTR;
- installsLibrary = installsLibrary || libraryGenerator != CM_NULLPTR;
- installsRuntime = installsRuntime || runtimeGenerator != CM_NULLPTR;
- installsObject = installsObject || objectGenerator != CM_NULLPTR;
- installsFramework = installsFramework || frameworkGenerator != CM_NULLPTR;
- installsBundle = installsBundle || bundleGenerator != CM_NULLPTR;
+ installsArchive = installsArchive || archiveGenerator != nullptr;
+ installsLibrary = installsLibrary || libraryGenerator != nullptr;
+ installsNamelink = installsNamelink || namelinkGenerator != nullptr;
+ installsRuntime = installsRuntime || runtimeGenerator != nullptr;
+ installsObject = installsObject || objectGenerator != nullptr;
+ installsFramework = installsFramework || frameworkGenerator != nullptr;
+ installsBundle = installsBundle || bundleGenerator != nullptr;
installsPrivateHeader =
- installsPrivateHeader || privateHeaderGenerator != CM_NULLPTR;
+ installsPrivateHeader || privateHeaderGenerator != nullptr;
installsPublicHeader =
- installsPublicHeader || publicHeaderGenerator != CM_NULLPTR;
+ installsPublicHeader || publicHeaderGenerator != nullptr;
installsResource = installsResource || resourceGenerator;
- this->Makefile->AddInstallGenerator(archiveGenerator);
- this->Makefile->AddInstallGenerator(libraryGenerator);
- this->Makefile->AddInstallGenerator(runtimeGenerator);
- this->Makefile->AddInstallGenerator(objectGenerator);
- this->Makefile->AddInstallGenerator(frameworkGenerator);
- this->Makefile->AddInstallGenerator(bundleGenerator);
- this->Makefile->AddInstallGenerator(privateHeaderGenerator);
- this->Makefile->AddInstallGenerator(publicHeaderGenerator);
- this->Makefile->AddInstallGenerator(resourceGenerator);
+ helper.Makefile->AddInstallGenerator(archiveGenerator);
+ helper.Makefile->AddInstallGenerator(libraryGenerator);
+ helper.Makefile->AddInstallGenerator(namelinkGenerator);
+ helper.Makefile->AddInstallGenerator(runtimeGenerator);
+ helper.Makefile->AddInstallGenerator(objectGenerator);
+ helper.Makefile->AddInstallGenerator(frameworkGenerator);
+ helper.Makefile->AddInstallGenerator(bundleGenerator);
+ helper.Makefile->AddInstallGenerator(privateHeaderGenerator);
+ helper.Makefile->AddInstallGenerator(publicHeaderGenerator);
+ helper.Makefile->AddInstallGenerator(resourceGenerator);
// Add this install rule to an export if one was specified and
// this is not a namelink-only rule.
- if (!exports.GetString().empty() && !namelinkOnly) {
- cmTargetExport* te = new cmTargetExport;
+ if (!exports.empty() && !namelinkOnly) {
+ auto te = cm::make_unique<cmTargetExport>();
te->TargetName = target.GetName();
te->ArchiveGenerator = archiveGenerator;
te->BundleGenerator = bundleGenerator;
@@ -722,77 +749,89 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
te->LibraryGenerator = libraryGenerator;
te->RuntimeGenerator = runtimeGenerator;
te->ObjectsGenerator = objectGenerator;
- this->Makefile->GetGlobalGenerator()
- ->GetExportSets()[exports.GetString()]
- ->AddTargetExport(te);
-
te->InterfaceIncludeDirectories =
cmJoin(includesArgs.GetIncludeDirs(), ";");
+
+ helper.Makefile->GetGlobalGenerator()
+ ->GetExportSets()[exports]
+ .AddTargetExport(std::move(te));
}
}
// Tell the global generator about any installation component names
// specified
if (installsArchive) {
- this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- archiveArgs.GetComponent().c_str());
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ archiveArgs.GetComponent());
}
if (installsLibrary) {
- this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- libraryArgs.GetComponent().c_str());
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ libraryArgs.GetComponent());
+ }
+ if (installsNamelink) {
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ libraryArgs.GetNamelinkComponent());
}
if (installsRuntime) {
- this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- runtimeArgs.GetComponent().c_str());
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ runtimeArgs.GetComponent());
}
if (installsObject) {
- this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- objectArgs.GetComponent().c_str());
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ objectArgs.GetComponent());
}
if (installsFramework) {
- this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- frameworkArgs.GetComponent().c_str());
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ frameworkArgs.GetComponent());
}
if (installsBundle) {
- this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- bundleArgs.GetComponent().c_str());
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ bundleArgs.GetComponent());
}
if (installsPrivateHeader) {
- this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- privateHeaderArgs.GetComponent().c_str());
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ privateHeaderArgs.GetComponent());
}
if (installsPublicHeader) {
- this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- publicHeaderArgs.GetComponent().c_str());
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ publicHeaderArgs.GetComponent());
}
if (installsResource) {
- this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- resourceArgs.GetComponent().c_str());
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ resourceArgs.GetComponent());
}
return true;
}
-bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
+bool HandleFilesMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
+ Helper helper(status);
+
// This is the FILES mode.
bool programs = (args[0] == "PROGRAMS");
- cmInstallCommandArguments ica(this->DefaultComponentName);
- cmCAStringVector files(&ica.Parser, programs ? "PROGRAMS" : "FILES");
- files.Follows(CM_NULLPTR);
- ica.ArgumentGroup.Follows(&files);
+ cmInstallCommandArguments ica(helper.DefaultComponentName);
+ std::vector<std::string> files;
+ ica.Bind(programs ? "PROGRAMS"_s : "FILES"_s, files);
std::vector<std::string> unknownArgs;
- ica.Parse(&args, &unknownArgs);
+ ica.Parse(args, &unknownArgs);
if (!unknownArgs.empty()) {
// Unknown argument.
- std::ostringstream e;
- e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\".";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat(args[0], " given unknown argument \"", unknownArgs[0], "\"."));
+ return false;
+ }
+
+ std::string type = ica.GetType();
+ if (!type.empty() && allowedTypes.count(type) == 0) {
+ status.SetError(
+ cmStrCat(args[0], " given non-type \"", type, "\" with TYPE argument."));
return false;
}
- const std::vector<std::string>& filesVector = files.GetVector();
+ const std::vector<std::string>& filesVector = files;
// Check if there is something to do.
if (filesVector.empty()) {
@@ -801,29 +840,27 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
if (!ica.GetRename().empty() && filesVector.size() > 1) {
// The rename option works only with one file.
- std::ostringstream e;
- e << args[0] << " given RENAME option with more than one file.";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat(args[0], " given RENAME option with more than one file."));
return false;
}
std::vector<std::string> absFiles;
- if (!this->MakeFilesFullPath(args[0].c_str(), filesVector, absFiles)) {
+ if (!helper.MakeFilesFullPath(args[0].c_str(), filesVector, absFiles)) {
return false;
}
- cmPolicies::PolicyStatus status =
- this->Makefile->GetPolicyStatus(cmPolicies::CMP0062);
+ cmPolicies::PolicyStatus policyStatus =
+ helper.Makefile->GetPolicyStatus(cmPolicies::CMP0062);
- cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
- for (std::vector<std::string>::const_iterator fileIt = filesVector.begin();
- fileIt != filesVector.end(); ++fileIt) {
- if (gg->IsExportedTargetsFile(*fileIt)) {
- const char* modal = CM_NULLPTR;
+ cmGlobalGenerator* gg = helper.Makefile->GetGlobalGenerator();
+ for (std::string const& file : filesVector) {
+ if (gg->IsExportedTargetsFile(file)) {
+ const char* modal = nullptr;
std::ostringstream e;
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ MessageType messageType = MessageType::AUTHOR_WARNING;
- switch (status) {
+ switch (policyStatus) {
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0062) << "\n";
modal = "should";
@@ -833,16 +870,18 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
modal = "may";
- messageType = cmake::FATAL_ERROR;
+ messageType = MessageType::FATAL_ERROR;
}
if (modal) {
- e << "The file\n " << *fileIt << "\nwas generated by the export() "
- "command. It "
- << modal << " not be installed with the "
- "install() command. Use the install(EXPORT) mechanism "
- "instead. See the cmake-packages(7) manual for more.\n";
- this->Makefile->IssueMessage(messageType, e.str());
- if (messageType == cmake::FATAL_ERROR) {
+ e << "The file\n " << file
+ << "\nwas generated by the export() "
+ "command. It "
+ << modal
+ << " not be installed with the "
+ "install() command. Use the install(EXPORT) mechanism "
+ "instead. See the cmake-packages(7) manual for more.\n";
+ helper.Makefile->IssueMessage(messageType, e.str());
+ if (messageType == MessageType::FATAL_ERROR) {
return false;
}
}
@@ -853,29 +892,37 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
return false;
}
- if (ica.GetDestination().empty()) {
+ if (!type.empty() && !ica.GetDestination().empty()) {
+ status.SetError(cmStrCat(args[0],
+ " given both TYPE and DESTINATION arguments. "
+ "You may only specify one."));
+ return false;
+ }
+
+ std::string destination = helper.GetDestinationForType(&ica, type);
+ if (destination.empty()) {
// A destination is required.
- std::ostringstream e;
- e << args[0] << " given no DESTINATION!";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " given no DESTINATION!"));
return false;
}
// Create the files install generator.
- this->Makefile->AddInstallGenerator(
- CreateInstallFilesGenerator(this->Makefile, absFiles, ica, programs));
+ helper.Makefile->AddInstallGenerator(CreateInstallFilesGenerator(
+ helper.Makefile, absFiles, ica, programs, destination));
// Tell the global generator about any installation component names
// specified.
- this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- ica.GetComponent().c_str());
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ ica.GetComponent());
return true;
}
-bool cmInstallCommand::HandleDirectoryMode(
- std::vector<std::string> const& args)
+bool HandleDirectoryMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
+ Helper helper(status);
+
enum Doing
{
DoingNone,
@@ -887,7 +934,8 @@ bool cmInstallCommand::HandleDirectoryMode(
DoingPermsDir,
DoingPermsMatch,
DoingConfigurations,
- DoingComponent
+ DoingComponent,
+ DoingType
};
Doing doing = DoingDirs;
bool in_match_mode = false;
@@ -895,30 +943,36 @@ bool cmInstallCommand::HandleDirectoryMode(
bool exclude_from_all = false;
bool message_never = false;
std::vector<std::string> dirs;
- const char* destination = CM_NULLPTR;
+ const char* destination = nullptr;
std::string permissions_file;
std::string permissions_dir;
std::vector<std::string> configurations;
- std::string component = this->DefaultComponentName;
+ std::string component = helper.DefaultComponentName;
std::string literal_args;
+ std::string type;
for (unsigned int i = 1; i < args.size(); ++i) {
if (args[i] == "DESTINATION") {
if (in_match_mode) {
- std::ostringstream e;
- e << args[0] << " does not allow \"" << args[i]
- << "\" after PATTERN or REGEX.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
+ "\" after PATTERN or REGEX."));
return false;
}
// Switch to setting the destination property.
doing = DoingDestination;
+ } else if (args[i] == "TYPE") {
+ if (in_match_mode) {
+ status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
+ "\" after PATTERN or REGEX."));
+ return false;
+ }
+
+ // Switch to setting the type.
+ doing = DoingType;
} else if (args[i] == "OPTIONAL") {
if (in_match_mode) {
- std::ostringstream e;
- e << args[0] << " does not allow \"" << args[i]
- << "\" after PATTERN or REGEX.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
+ "\" after PATTERN or REGEX."));
return false;
}
@@ -927,10 +981,8 @@ bool cmInstallCommand::HandleDirectoryMode(
doing = DoingNone;
} else if (args[i] == "MESSAGE_NEVER") {
if (in_match_mode) {
- std::ostringstream e;
- e << args[0] << " does not allow \"" << args[i]
- << "\" after PATTERN or REGEX.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
+ "\" after PATTERN or REGEX."));
return false;
}
@@ -948,20 +1000,16 @@ bool cmInstallCommand::HandleDirectoryMode(
} else if (args[i] == "EXCLUDE") {
// Add this property to the current match rule.
if (!in_match_mode || doing == DoingPattern || doing == DoingRegex) {
- std::ostringstream e;
- e << args[0] << " does not allow \"" << args[i]
- << "\" before a PATTERN or REGEX is given.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
+ "\" before a PATTERN or REGEX is given."));
return false;
}
literal_args += " EXCLUDE";
doing = DoingNone;
} else if (args[i] == "PERMISSIONS") {
if (!in_match_mode) {
- std::ostringstream e;
- e << args[0] << " does not allow \"" << args[i]
- << "\" before a PATTERN or REGEX is given.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
+ "\" before a PATTERN or REGEX is given."));
return false;
}
@@ -970,10 +1018,8 @@ bool cmInstallCommand::HandleDirectoryMode(
doing = DoingPermsMatch;
} else if (args[i] == "FILE_PERMISSIONS") {
if (in_match_mode) {
- std::ostringstream e;
- e << args[0] << " does not allow \"" << args[i]
- << "\" after PATTERN or REGEX.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
+ "\" after PATTERN or REGEX."));
return false;
}
@@ -981,10 +1027,8 @@ bool cmInstallCommand::HandleDirectoryMode(
doing = DoingPermsFile;
} else if (args[i] == "DIRECTORY_PERMISSIONS") {
if (in_match_mode) {
- std::ostringstream e;
- e << args[0] << " does not allow \"" << args[i]
- << "\" after PATTERN or REGEX.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
+ "\" after PATTERN or REGEX."));
return false;
}
@@ -992,10 +1036,8 @@ bool cmInstallCommand::HandleDirectoryMode(
doing = DoingPermsDir;
} else if (args[i] == "USE_SOURCE_PERMISSIONS") {
if (in_match_mode) {
- std::ostringstream e;
- e << args[0] << " does not allow \"" << args[i]
- << "\" after PATTERN or REGEX.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
+ "\" after PATTERN or REGEX."));
return false;
}
@@ -1004,10 +1046,8 @@ bool cmInstallCommand::HandleDirectoryMode(
doing = DoingNone;
} else if (args[i] == "FILES_MATCHING") {
if (in_match_mode) {
- std::ostringstream e;
- e << args[0] << " does not allow \"" << args[i]
- << "\" after PATTERN or REGEX.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
+ "\" after PATTERN or REGEX."));
return false;
}
@@ -1016,10 +1056,8 @@ bool cmInstallCommand::HandleDirectoryMode(
doing = DoingNone;
} else if (args[i] == "CONFIGURATIONS") {
if (in_match_mode) {
- std::ostringstream e;
- e << args[0] << " does not allow \"" << args[i]
- << "\" after PATTERN or REGEX.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
+ "\" after PATTERN or REGEX."));
return false;
}
@@ -1027,10 +1065,8 @@ bool cmInstallCommand::HandleDirectoryMode(
doing = DoingConfigurations;
} else if (args[i] == "COMPONENT") {
if (in_match_mode) {
- std::ostringstream e;
- e << args[0] << " does not allow \"" << args[i]
- << "\" after PATTERN or REGEX.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
+ "\" after PATTERN or REGEX."));
return false;
}
@@ -1038,10 +1074,8 @@ bool cmInstallCommand::HandleDirectoryMode(
doing = DoingComponent;
} else if (args[i] == "EXCLUDE_FROM_ALL") {
if (in_match_mode) {
- std::ostringstream e;
- e << args[0] << " does not allow \"" << args[i]
- << "\" after PATTERN or REGEX.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " does not allow \"", args[i],
+ "\" after PATTERN or REGEX."));
return false;
}
exclude_from_all = true;
@@ -1050,29 +1084,35 @@ 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())) {
- dir = this->Makefile->GetCurrentSourceDirectory();
- dir += "/";
- dir += args[i];
+ if (gpos != 0 && !cmSystemTools::FileIsFullPath(dir)) {
+ dir =
+ cmStrCat(helper.Makefile->GetCurrentSourceDirectory(), '/', 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]
- << "\" to install.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " given non-directory \"", args[i],
+ "\" to install."));
return false;
}
// 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) {
destination = args[i].c_str();
doing = DoingNone;
+ } else if (doing == DoingType) {
+ if (allowedTypes.count(args[i]) == 0) {
+ status.SetError(cmStrCat(args[0], " given non-type \"", args[i],
+ "\" with TYPE argument."));
+ return false;
+ }
+
+ type = args[i];
+ doing = DoingNone;
} else if (doing == DoingPattern) {
// Convert the pattern to a regular expression. Require a
// leading slash and trailing end-of-string in the matched
@@ -1103,95 +1143,101 @@ bool cmInstallCommand::HandleDirectoryMode(
// Check the requested permission.
if (!cmInstallCommandArguments::CheckPermissions(args[i],
permissions_file)) {
- std::ostringstream e;
- e << args[0] << " given invalid file permission \"" << args[i]
- << "\".";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " given invalid file permission \"",
+ args[i], "\"."));
return false;
}
} else if (doing == DoingPermsDir) {
// Check the requested permission.
if (!cmInstallCommandArguments::CheckPermissions(args[i],
permissions_dir)) {
- std::ostringstream e;
- e << args[0] << " given invalid directory permission \"" << args[i]
- << "\".";
- this->SetError(e.str());
+ status.SetError(cmStrCat(
+ args[0], " given invalid directory permission \"", args[i], "\"."));
return false;
}
} else if (doing == DoingPermsMatch) {
// Check the requested permission.
if (!cmInstallCommandArguments::CheckPermissions(args[i],
literal_args)) {
- std::ostringstream e;
- e << args[0] << " given invalid permission \"" << args[i] << "\".";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat(args[0], " given invalid permission \"", args[i], "\"."));
return false;
}
} else {
// Unknown argument.
- std::ostringstream e;
- e << args[0] << " given unknown argument \"" << args[i] << "\".";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat(args[0], " given unknown argument \"", args[i], "\"."));
return false;
}
}
// Support installing an empty directory.
if (dirs.empty() && destination) {
- dirs.push_back("");
+ dirs.emplace_back();
}
// Check if there is something to do.
if (dirs.empty()) {
return true;
}
+ std::string destinationStr;
if (!destination) {
- // A destination is required.
- std::ostringstream e;
- e << args[0] << " given no DESTINATION!";
- this->SetError(e.str());
+ if (type.empty()) {
+ // A destination is required.
+ status.SetError(cmStrCat(args[0], " given no DESTINATION!"));
+ return false;
+ }
+ destinationStr = helper.GetDestinationForType(nullptr, type);
+ destination = destinationStr.c_str();
+ } else if (!type.empty()) {
+ status.SetError(cmStrCat(args[0],
+ " given both TYPE and DESTINATION "
+ "arguments. You may only specify one."));
return false;
}
cmInstallGenerator::MessageLevel message =
- cmInstallGenerator::SelectMessageLevel(this->Makefile, message_never);
+ cmInstallGenerator::SelectMessageLevel(helper.Makefile, message_never);
// Create the directory install generator.
- this->Makefile->AddInstallGenerator(new cmInstallDirectoryGenerator(
+ helper.Makefile->AddInstallGenerator(new cmInstallDirectoryGenerator(
dirs, destination, permissions_file.c_str(), permissions_dir.c_str(),
configurations, component.c_str(), message, exclude_from_all,
literal_args.c_str(), optional));
// Tell the global generator about any installation component names
// specified.
- this->Makefile->GetGlobalGenerator()->AddInstallComponent(component.c_str());
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(component);
return true;
}
-bool cmInstallCommand::HandleExportAndroidMKMode(
- std::vector<std::string> const& args)
+bool HandleExportAndroidMKMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
+ Helper helper(status);
+
// This is the EXPORT mode.
- cmInstallCommandArguments ica(this->DefaultComponentName);
- cmCAString exp(&ica.Parser, "EXPORT_ANDROID_MK");
- cmCAString name_space(&ica.Parser, "NAMESPACE", &ica.ArgumentGroup);
- cmCAEnabler exportOld(&ica.Parser, "EXPORT_LINK_INTERFACE_LIBRARIES",
- &ica.ArgumentGroup);
- cmCAString filename(&ica.Parser, "FILE", &ica.ArgumentGroup);
- exp.Follows(CM_NULLPTR);
-
- ica.ArgumentGroup.Follows(&exp);
+ cmInstallCommandArguments ica(helper.DefaultComponentName);
+
+ std::string exp;
+ std::string name_space;
+ bool exportOld = false;
+ std::string filename;
+
+ ica.Bind("EXPORT_ANDROID_MK"_s, exp);
+ ica.Bind("NAMESPACE"_s, name_space);
+ ica.Bind("EXPORT_LINK_INTERFACE_LIBRARIES"_s, exportOld);
+ ica.Bind("FILE"_s, filename);
+
std::vector<std::string> unknownArgs;
- ica.Parse(&args, &unknownArgs);
+ ica.Parse(args, &unknownArgs);
if (!unknownArgs.empty()) {
// Unknown argument.
- std::ostringstream e;
- e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\".";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat(args[0], " given unknown argument \"", unknownArgs[0], "\"."));
return false;
}
@@ -1202,39 +1248,35 @@ bool cmInstallCommand::HandleExportAndroidMKMode(
// Make sure there is a destination.
if (ica.GetDestination().empty()) {
// A destination is required.
- std::ostringstream e;
- e << args[0] << " given no DESTINATION!";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " given no DESTINATION!"));
return false;
}
// Check the file name.
- std::string fname = filename.GetString();
+ std::string fname = filename;
if (fname.find_first_of(":/\\") != std::string::npos) {
- std::ostringstream e;
- e << args[0] << " given invalid export file name \"" << fname << "\". "
- << "The FILE argument may not contain a path. "
- << "Specify the path in the DESTINATION argument.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " given invalid export file name \"",
+ fname,
+ "\". The FILE argument may not contain a path. "
+ "Specify the path in the DESTINATION argument."));
return false;
}
// Check the file extension.
if (!fname.empty() &&
cmSystemTools::GetFilenameLastExtension(fname) != ".mk") {
- std::ostringstream e;
- e << args[0] << " given invalid export file name \"" << fname << "\". "
- << "The FILE argument must specify a name ending in \".mk\".";
- this->SetError(e.str());
+ status.SetError(cmStrCat(
+ args[0], " given invalid export file name \"", fname,
+ R"(". The FILE argument must specify a name ending in ".mk".)"));
return false;
}
if (fname.find_first_of(":/\\") != std::string::npos) {
- std::ostringstream e;
- e << args[0] << " given export name \"" << exp.GetString() << "\". "
- << "This name cannot be safely converted to a file name. "
- << "Specify a different export name or use the FILE option to set "
- << "a file name explicitly.";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat(args[0], " given export name \"", exp,
+ "\". "
+ "This name cannot be safely converted to a file name. "
+ "Specify a different export name or use the FILE option to set "
+ "a file name explicitly."));
return false;
}
// Use the default name
@@ -1242,48 +1284,53 @@ bool cmInstallCommand::HandleExportAndroidMKMode(
fname = "Android.mk";
}
- cmExportSet* exportSet =
- this->Makefile->GetGlobalGenerator()->GetExportSets()[exp.GetString()];
+ cmExportSet& exportSet =
+ helper.Makefile->GetGlobalGenerator()->GetExportSets()[exp];
cmInstallGenerator::MessageLevel message =
- cmInstallGenerator::SelectMessageLevel(this->Makefile);
+ cmInstallGenerator::SelectMessageLevel(helper.Makefile);
// Create the export install generator.
cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator(
- exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
+ &exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
ica.GetConfigurations(), ica.GetComponent().c_str(), message,
- ica.GetExcludeFromAll(), fname.c_str(), name_space.GetCString(),
- exportOld.IsEnabled(), true);
- this->Makefile->AddInstallGenerator(exportGenerator);
+ ica.GetExcludeFromAll(), fname.c_str(), name_space.c_str(), exportOld,
+ true);
+ helper.Makefile->AddInstallGenerator(exportGenerator);
return true;
#else
static_cast<void>(args);
- this->SetError("EXPORT_ANDROID_MK not supported in bootstrap cmake");
+ status.SetError("EXPORT_ANDROID_MK not supported in bootstrap cmake");
return false;
#endif
}
-bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
+bool HandleExportMode(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
+ Helper helper(status);
+
// This is the EXPORT mode.
- cmInstallCommandArguments ica(this->DefaultComponentName);
- cmCAString exp(&ica.Parser, "EXPORT");
- cmCAString name_space(&ica.Parser, "NAMESPACE", &ica.ArgumentGroup);
- cmCAEnabler exportOld(&ica.Parser, "EXPORT_LINK_INTERFACE_LIBRARIES",
- &ica.ArgumentGroup);
- cmCAString filename(&ica.Parser, "FILE", &ica.ArgumentGroup);
- exp.Follows(CM_NULLPTR);
-
- ica.ArgumentGroup.Follows(&exp);
+ cmInstallCommandArguments ica(helper.DefaultComponentName);
+
+ std::string exp;
+ std::string name_space;
+ bool exportOld = false;
+ std::string filename;
+
+ ica.Bind("EXPORT"_s, exp);
+ ica.Bind("NAMESPACE"_s, name_space);
+ ica.Bind("EXPORT_LINK_INTERFACE_LIBRARIES"_s, exportOld);
+ ica.Bind("FILE"_s, filename);
+
std::vector<std::string> unknownArgs;
- ica.Parse(&args, &unknownArgs);
+ ica.Parse(args, &unknownArgs);
if (!unknownArgs.empty()) {
// Unknown argument.
- std::ostringstream e;
- e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\".";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat(args[0], " given unknown argument \"", unknownArgs[0], "\"."));
return false;
}
@@ -1294,121 +1341,110 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
// Make sure there is a destination.
if (ica.GetDestination().empty()) {
// A destination is required.
- std::ostringstream e;
- e << args[0] << " given no DESTINATION!";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " given no DESTINATION!"));
return false;
}
// Check the file name.
- std::string fname = filename.GetString();
+ std::string fname = filename;
if (fname.find_first_of(":/\\") != std::string::npos) {
- std::ostringstream e;
- e << args[0] << " given invalid export file name \"" << fname << "\". "
- << "The FILE argument may not contain a path. "
- << "Specify the path in the DESTINATION argument.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(args[0], " given invalid export file name \"",
+ fname,
+ "\". "
+ "The FILE argument may not contain a path. "
+ "Specify the path in the DESTINATION argument."));
return false;
}
// Check the file extension.
if (!fname.empty() &&
cmSystemTools::GetFilenameLastExtension(fname) != ".cmake") {
- std::ostringstream e;
- e << args[0] << " given invalid export file name \"" << fname << "\". "
- << "The FILE argument must specify a name ending in \".cmake\".";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat(args[0], " given invalid export file name \"", fname,
+ "\". "
+ "The FILE argument must specify a name ending in \".cmake\"."));
return false;
}
// Construct the file name.
if (fname.empty()) {
- fname = exp.GetString();
- fname += ".cmake";
+ fname = cmStrCat(exp, ".cmake");
if (fname.find_first_of(":/\\") != std::string::npos) {
- std::ostringstream e;
- e << args[0] << " given export name \"" << exp.GetString() << "\". "
- << "This name cannot be safely converted to a file name. "
- << "Specify a different export name or use the FILE option to set "
- << "a file name explicitly.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(
+ args[0], " given export name \"", exp,
+ "\". "
+ "This name cannot be safely converted to a file name. "
+ "Specify a different export name or use the FILE option to set "
+ "a file name explicitly."));
return false;
}
}
- cmExportSet* exportSet =
- this->Makefile->GetGlobalGenerator()->GetExportSets()[exp.GetString()];
- if (exportOld.IsEnabled()) {
- for (std::vector<cmTargetExport*>::const_iterator tei =
- exportSet->GetTargetExports()->begin();
- tei != exportSet->GetTargetExports()->end(); ++tei) {
- cmTargetExport const* te = *tei;
+ cmExportSet& exportSet =
+ helper.Makefile->GetGlobalGenerator()->GetExportSets()[exp];
+ if (exportOld) {
+ for (auto const& te : exportSet.GetTargetExports()) {
cmTarget* tgt =
- this->Makefile->GetGlobalGenerator()->FindTarget(te->TargetName);
+ helper.Makefile->GetGlobalGenerator()->FindTarget(te->TargetName);
const bool newCMP0022Behavior =
(tgt && tgt->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
tgt->GetPolicyStatusCMP0022() != cmPolicies::OLD);
if (!newCMP0022Behavior) {
- std::ostringstream e;
- e << "INSTALL(EXPORT) given keyword \""
- << "EXPORT_LINK_INTERFACE_LIBRARIES"
- << "\", but target \"" << te->TargetName
- << "\" does not have policy CMP0022 set to NEW.";
- this->SetError(e.str());
+ status.SetError(cmStrCat(
+ "INSTALL(EXPORT) given keyword \""
+ "EXPORT_LINK_INTERFACE_LIBRARIES\", but target \"",
+ te->TargetName, "\" does not have policy CMP0022 set to NEW."));
return false;
}
}
}
cmInstallGenerator::MessageLevel message =
- cmInstallGenerator::SelectMessageLevel(this->Makefile);
+ cmInstallGenerator::SelectMessageLevel(helper.Makefile);
// Create the export install generator.
cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator(
- exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
+ &exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
ica.GetConfigurations(), ica.GetComponent().c_str(), message,
- ica.GetExcludeFromAll(), fname.c_str(), name_space.GetCString(),
- exportOld.IsEnabled(), false);
- this->Makefile->AddInstallGenerator(exportGenerator);
+ ica.GetExcludeFromAll(), fname.c_str(), name_space.c_str(), exportOld,
+ false);
+ helper.Makefile->AddInstallGenerator(exportGenerator);
return true;
}
-bool cmInstallCommand::MakeFilesFullPath(
- const char* modeName, const std::vector<std::string>& relFiles,
- std::vector<std::string>& absFiles)
+bool Helper::MakeFilesFullPath(const char* modeName,
+ const std::vector<std::string>& relFiles,
+ std::vector<std::string>& absFiles)
{
- for (std::vector<std::string>::const_iterator fileIt = relFiles.begin();
- fileIt != relFiles.end(); ++fileIt) {
- std::string file = (*fileIt);
+ 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())) {
- file = this->Makefile->GetCurrentSourceDirectory();
- file += "/";
- file += *fileIt;
+ if (gpos != 0 && !cmSystemTools::FileIsFullPath(file)) {
+ file =
+ cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', relFile);
}
// Make sure the file is not a directory.
if (gpos == std::string::npos && cmSystemTools::FileIsDirectory(file)) {
- std::ostringstream e;
- e << modeName << " given directory \"" << (*fileIt) << "\" to install.";
- this->SetError(e.str());
+ this->SetError(
+ cmStrCat(modeName, " given directory \"", relFile, "\" to install."));
return false;
}
// Store the file for installation.
- absFiles.push_back(file);
+ absFiles.push_back(std::move(file));
}
return true;
}
-bool cmInstallCommand::CheckCMP0006(bool& failure)
+bool Helper::CheckCMP0006(bool& failure)
{
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0006)) {
case cmPolicies::WARN:
this->Makefile->IssueMessage(
- cmake::AUTHOR_WARNING,
+ MessageType::AUTHOR_WARNING,
cmPolicies::GetPolicyWarning(cmPolicies::CMP0006));
CM_FALLTHROUGH;
case cmPolicies::OLD:
@@ -1421,9 +1457,191 @@ bool cmInstallCommand::CheckCMP0006(bool& failure)
case cmPolicies::REQUIRED_ALWAYS:
failure = true;
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0006));
break;
}
return false;
}
+
+std::string Helper::GetDestination(const cmInstallCommandArguments* args,
+ const std::string& varName,
+ const std::string& guess)
+{
+ if (args && !args->GetDestination().empty()) {
+ return args->GetDestination();
+ }
+ std::string val = this->Makefile->GetSafeDefinition(varName);
+ if (!val.empty()) {
+ return val;
+ }
+ return guess;
+}
+
+std::string Helper::GetRuntimeDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_BINDIR", "bin");
+}
+
+std::string Helper::GetSbinDestination(const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_SBINDIR", "sbin");
+}
+
+std::string Helper::GetArchiveDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib");
+}
+
+std::string Helper::GetLibraryDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib");
+}
+
+std::string Helper::GetIncludeDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_INCLUDEDIR", "include");
+}
+
+std::string Helper::GetSysconfDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_SYSCONFDIR", "etc");
+}
+
+std::string Helper::GetSharedStateDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_SHAREDSTATEDIR", "com");
+}
+
+std::string Helper::GetLocalStateDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_LOCALSTATEDIR", "var");
+}
+
+std::string Helper::GetRunStateDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_RUNSTATEDIR",
+ this->GetLocalStateDestination(nullptr) +
+ "/run");
+}
+
+std::string Helper::GetDataRootDestination(
+ const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_DATAROOTDIR", "share");
+}
+
+std::string Helper::GetDataDestination(const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_DATADIR",
+ this->GetDataRootDestination(nullptr));
+}
+
+std::string Helper::GetInfoDestination(const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_INFODIR",
+ this->GetDataRootDestination(nullptr) + "/info");
+}
+
+std::string Helper::GetLocaleDestination(const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_LOCALEDIR",
+ this->GetDataRootDestination(nullptr) +
+ "/locale");
+}
+
+std::string Helper::GetManDestination(const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_MANDIR",
+ this->GetDataRootDestination(nullptr) + "/man");
+}
+
+std::string Helper::GetDocDestination(const cmInstallCommandArguments* args)
+{
+ return this->GetDestination(args, "CMAKE_INSTALL_DOCDIR",
+ this->GetDataRootDestination(nullptr) + "/doc");
+}
+
+std::string Helper::GetDestinationForType(
+ const cmInstallCommandArguments* args, const std::string& type)
+{
+ if (args && !args->GetDestination().empty()) {
+ return args->GetDestination();
+ }
+ if (type == "BIN") {
+ return this->GetRuntimeDestination(nullptr);
+ }
+ if (type == "SBIN") {
+ return this->GetSbinDestination(nullptr);
+ }
+ if (type == "SYSCONF") {
+ return this->GetSysconfDestination(nullptr);
+ }
+ if (type == "SHAREDSTATE") {
+ return this->GetSharedStateDestination(nullptr);
+ }
+ if (type == "LOCALSTATE") {
+ return this->GetLocalStateDestination(nullptr);
+ }
+ if (type == "RUNSTATE") {
+ return this->GetRunStateDestination(nullptr);
+ }
+ if (type == "LIB") {
+ return this->GetLibraryDestination(nullptr);
+ }
+ if (type == "INCLUDE") {
+ return this->GetIncludeDestination(nullptr);
+ }
+ if (type == "DATA") {
+ return this->GetDataDestination(nullptr);
+ }
+ if (type == "INFO") {
+ return this->GetInfoDestination(nullptr);
+ }
+ if (type == "LOCALE") {
+ return this->GetLocaleDestination(nullptr);
+ }
+ if (type == "MAN") {
+ return this->GetManDestination(nullptr);
+ }
+ if (type == "DOC") {
+ return this->GetDocDestination(nullptr);
+ }
+ return "";
+}
+
+} // namespace
+
+bool cmInstallCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ // Allow calling with no arguments so that arguments may be built up
+ // using a variable that may be left empty.
+ if (args.empty()) {
+ return true;
+ }
+
+ // Enable the install target.
+ status.GetMakefile().GetGlobalGenerator()->EnableInstallTarget();
+
+ static cmSubcommandTable const subcommand{
+ { "SCRIPT"_s, HandleScriptMode },
+ { "CODE"_s, HandleScriptMode },
+ { "TARGETS"_s, HandleTargetsMode },
+ { "FILES"_s, HandleFilesMode },
+ { "PROGRAMS"_s, HandleFilesMode },
+ { "DIRECTORY"_s, HandleDirectoryMode },
+ { "EXPORT"_s, HandleExportMode },
+ { "EXPORT_ANDROID_MK"_s, HandleExportAndroidMKMode },
+ };
+
+ return subcommand(args[0], args, status);
+}
diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h
index f5d1f9265..32f00ce49 100644
--- a/Source/cmInstallCommand.h
+++ b/Source/cmInstallCommand.h
@@ -3,49 +3,14 @@
#ifndef cmInstallCommand_h
#define cmInstallCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmInstallCommand
- * \brief Specifies where to install some files
- *
- * cmInstallCommand is a general-purpose interface command for
- * specifying install rules.
- */
-class cmInstallCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmInstallCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- bool HandleScriptMode(std::vector<std::string> const& args);
- bool HandleTargetsMode(std::vector<std::string> const& args);
- bool HandleFilesMode(std::vector<std::string> const& args);
- bool HandleDirectoryMode(std::vector<std::string> const& args);
- bool HandleExportMode(std::vector<std::string> const& args);
- bool HandleExportAndroidMKMode(std::vector<std::string> const& args);
- bool MakeFilesFullPath(const char* modeName,
- const std::vector<std::string>& relFiles,
- std::vector<std::string>& absFiles);
- bool CheckCMP0006(bool& failure);
-
- std::string DefaultComponentName;
-};
+bool cmInstallCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx
index b73414dd0..31ba63f2c 100644
--- a/Source/cmInstallCommandArguments.cxx
+++ b/Source/cmInstallCommandArguments.cxx
@@ -2,35 +2,37 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallCommandArguments.h"
-#include "cmConfigure.h"
+#include <utility>
+#include "cm_static_string_view.hxx"
+
+#include "cmRange.h"
#include "cmSystemTools.h"
// Table of valid permissions.
const char* cmInstallCommandArguments::PermissionsTable[] = {
"OWNER_READ", "OWNER_WRITE", "OWNER_EXECUTE", "GROUP_READ",
"GROUP_WRITE", "GROUP_EXECUTE", "WORLD_READ", "WORLD_WRITE",
- "WORLD_EXECUTE", "SETUID", "SETGID", CM_NULLPTR
+ "WORLD_EXECUTE", "SETUID", "SETGID", nullptr
};
const std::string cmInstallCommandArguments::EmptyString;
cmInstallCommandArguments::cmInstallCommandArguments(
- const std::string& defaultComponent)
- : Parser()
- , ArgumentGroup()
- , Destination(&Parser, "DESTINATION", &ArgumentGroup)
- , Component(&Parser, "COMPONENT", &ArgumentGroup)
- , ExcludeFromAll(&Parser, "EXCLUDE_FROM_ALL", &ArgumentGroup)
- , Rename(&Parser, "RENAME", &ArgumentGroup)
- , Permissions(&Parser, "PERMISSIONS", &ArgumentGroup)
- , Configurations(&Parser, "CONFIGURATIONS", &ArgumentGroup)
- , Optional(&Parser, "OPTIONAL", &ArgumentGroup)
- , NamelinkOnly(&Parser, "NAMELINK_ONLY", &ArgumentGroup)
- , NamelinkSkip(&Parser, "NAMELINK_SKIP", &ArgumentGroup)
- , GenericArguments(CM_NULLPTR)
- , DefaultComponentName(defaultComponent)
-{
+ std::string defaultComponent)
+ : DefaultComponentName(std::move(defaultComponent))
+{
+ this->Bind("DESTINATION"_s, this->Destination);
+ this->Bind("COMPONENT"_s, this->Component);
+ this->Bind("NAMELINK_COMPONENT"_s, this->NamelinkComponent);
+ this->Bind("EXCLUDE_FROM_ALL"_s, this->ExcludeFromAll);
+ this->Bind("RENAME"_s, this->Rename);
+ this->Bind("PERMISSIONS"_s, this->Permissions);
+ this->Bind("CONFIGURATIONS"_s, this->Configurations);
+ this->Bind("OPTIONAL"_s, this->Optional);
+ this->Bind("NAMELINK_ONLY"_s, this->NamelinkOnly);
+ this->Bind("NAMELINK_SKIP"_s, this->NamelinkSkip);
+ this->Bind("TYPE"_s, this->Type);
}
const std::string& cmInstallCommandArguments::GetDestination() const
@@ -38,18 +40,18 @@ const std::string& cmInstallCommandArguments::GetDestination() const
if (!this->DestinationString.empty()) {
return this->DestinationString;
}
- if (this->GenericArguments != CM_NULLPTR) {
+ if (this->GenericArguments != nullptr) {
return this->GenericArguments->GetDestination();
}
- return this->EmptyString;
+ return EmptyString;
}
const std::string& cmInstallCommandArguments::GetComponent() const
{
- if (!this->Component.GetString().empty()) {
- return this->Component.GetString();
+ if (!this->Component.empty()) {
+ return this->Component;
}
- if (this->GenericArguments != CM_NULLPTR) {
+ if (this->GenericArguments != nullptr) {
return this->GenericArguments->GetComponent();
}
if (!this->DefaultComponentName.empty()) {
@@ -59,15 +61,23 @@ const std::string& cmInstallCommandArguments::GetComponent() const
return unspecifiedComponent;
}
+const std::string& cmInstallCommandArguments::GetNamelinkComponent() const
+{
+ if (!this->NamelinkComponent.empty()) {
+ return this->NamelinkComponent;
+ }
+ return this->GetComponent();
+}
+
const std::string& cmInstallCommandArguments::GetRename() const
{
- if (!this->Rename.GetString().empty()) {
- return this->Rename.GetString();
+ if (!this->Rename.empty()) {
+ return this->Rename;
}
- if (this->GenericArguments != CM_NULLPTR) {
+ if (this->GenericArguments != nullptr) {
return this->GenericArguments->GetRename();
}
- return this->EmptyString;
+ return EmptyString;
}
const std::string& cmInstallCommandArguments::GetPermissions() const
@@ -75,18 +85,18 @@ const std::string& cmInstallCommandArguments::GetPermissions() const
if (!this->PermissionsString.empty()) {
return this->PermissionsString;
}
- if (this->GenericArguments != CM_NULLPTR) {
+ if (this->GenericArguments != nullptr) {
return this->GenericArguments->GetPermissions();
}
- return this->EmptyString;
+ return EmptyString;
}
bool cmInstallCommandArguments::GetOptional() const
{
- if (this->Optional.IsEnabled()) {
+ if (this->Optional) {
return true;
}
- if (this->GenericArguments != CM_NULLPTR) {
+ if (this->GenericArguments != nullptr) {
return this->GenericArguments->GetOptional();
}
return false;
@@ -94,10 +104,10 @@ bool cmInstallCommandArguments::GetOptional() const
bool cmInstallCommandArguments::GetExcludeFromAll() const
{
- if (this->ExcludeFromAll.IsEnabled()) {
+ if (this->ExcludeFromAll) {
return true;
}
- if (this->GenericArguments != CM_NULLPTR) {
+ if (this->GenericArguments != nullptr) {
return this->GenericArguments->GetExcludeFromAll();
}
return false;
@@ -105,10 +115,10 @@ bool cmInstallCommandArguments::GetExcludeFromAll() const
bool cmInstallCommandArguments::GetNamelinkOnly() const
{
- if (this->NamelinkOnly.IsEnabled()) {
+ if (this->NamelinkOnly) {
return true;
}
- if (this->GenericArguments != CM_NULLPTR) {
+ if (this->GenericArguments != nullptr) {
return this->GenericArguments->GetNamelinkOnly();
}
return false;
@@ -116,25 +126,41 @@ bool cmInstallCommandArguments::GetNamelinkOnly() const
bool cmInstallCommandArguments::GetNamelinkSkip() const
{
- if (this->NamelinkSkip.IsEnabled()) {
+ if (this->NamelinkSkip) {
return true;
}
- if (this->GenericArguments != CM_NULLPTR) {
+ if (this->GenericArguments != nullptr) {
return this->GenericArguments->GetNamelinkSkip();
}
return false;
}
+bool cmInstallCommandArguments::HasNamelinkComponent() const
+{
+ if (!this->NamelinkComponent.empty()) {
+ return true;
+ }
+ if (this->GenericArguments != nullptr) {
+ return this->GenericArguments->HasNamelinkComponent();
+ }
+ return false;
+}
+
+const std::string& cmInstallCommandArguments::GetType() const
+{
+ return this->Type;
+}
+
const std::vector<std::string>& cmInstallCommandArguments::GetConfigurations()
const
{
- if (!this->Configurations.GetVector().empty()) {
- return this->Configurations.GetVector();
+ if (!this->Configurations.empty()) {
+ return this->Configurations;
}
- if (this->GenericArguments != CM_NULLPTR) {
+ if (this->GenericArguments != nullptr) {
return this->GenericArguments->GetConfigurations();
}
- return this->Configurations.GetVector();
+ return this->Configurations;
}
bool cmInstallCommandArguments::Finalize()
@@ -142,24 +168,17 @@ bool cmInstallCommandArguments::Finalize()
if (!this->CheckPermissions()) {
return false;
}
- this->DestinationString = this->Destination.GetString();
+ this->DestinationString = this->Destination;
cmSystemTools::ConvertToUnixSlashes(this->DestinationString);
return true;
}
-void cmInstallCommandArguments::Parse(const std::vector<std::string>* args,
- std::vector<std::string>* unconsumedArgs)
-{
- this->Parser.Parse(args, unconsumedArgs);
-}
-
bool cmInstallCommandArguments::CheckPermissions()
{
- this->PermissionsString = "";
- for (std::vector<std::string>::const_iterator permIt =
- this->Permissions.GetVector().begin();
- permIt != this->Permissions.GetVector().end(); ++permIt) {
- if (!this->CheckPermissions(*permIt, this->PermissionsString)) {
+ this->PermissionsString.clear();
+ for (std::string const& perm : this->Permissions) {
+ if (!cmInstallCommandArguments::CheckPermissions(
+ perm, this->PermissionsString)) {
return false;
}
}
@@ -183,9 +202,7 @@ bool cmInstallCommandArguments::CheckPermissions(
return false;
}
-cmInstallCommandIncludesArgument::cmInstallCommandIncludesArgument()
-{
-}
+cmInstallCommandIncludesArgument::cmInstallCommandIncludesArgument() = default;
const std::vector<std::string>&
cmInstallCommandIncludesArgument::GetIncludeDirs() const
@@ -199,11 +216,8 @@ void cmInstallCommandIncludesArgument::Parse(
if (args->empty()) {
return;
}
- std::vector<std::string>::const_iterator it = args->begin();
- ++it;
- for (; it != args->end(); ++it) {
- std::string dir = *it;
+ for (std::string dir : cmMakeRange(*args).advance(1)) {
cmSystemTools::ConvertToUnixSlashes(dir);
- this->IncludeDirs.push_back(dir);
+ this->IncludeDirs.push_back(std::move(dir));
}
}
diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h
index a576e7202..5d2ee0ab4 100644
--- a/Source/cmInstallCommandArguments.h
+++ b/Source/cmInstallCommandArguments.h
@@ -8,24 +8,23 @@
#include <string>
#include <vector>
-#include "cmCommandArgumentsHelper.h"
+#include "cmArgumentParser.h"
-class cmInstallCommandArguments
+class cmInstallCommandArguments : public cmArgumentParser<void>
{
public:
- cmInstallCommandArguments(const std::string& defaultComponent);
+ cmInstallCommandArguments(std::string defaultComponent);
void SetGenericArguments(cmInstallCommandArguments* args)
{
this->GenericArguments = args;
}
- void Parse(const std::vector<std::string>* args,
- std::vector<std::string>* unconsumedArgs);
// Compute destination path.and check permissions
bool Finalize();
const std::string& GetDestination() const;
const std::string& GetComponent() const;
+ const std::string& GetNamelinkComponent() const;
bool GetExcludeFromAll() const;
const std::string& GetRename() const;
const std::string& GetPermissions() const;
@@ -33,30 +32,28 @@ public:
bool GetOptional() const;
bool GetNamelinkOnly() const;
bool GetNamelinkSkip() const;
+ bool HasNamelinkComponent() const;
+ const std::string& GetType() const;
- // once HandleDirectoryMode() is also switched to using
- // cmInstallCommandArguments then these two functions can become non-static
- // private member functions without arguments
static bool CheckPermissions(const std::string& onePerm, std::string& perm);
- cmCommandArgumentsHelper Parser;
- cmCommandArgumentGroup ArgumentGroup;
private:
- cmInstallCommandArguments(); // disabled
- cmCAString Destination;
- cmCAString Component;
- cmCAEnabler ExcludeFromAll;
- cmCAString Rename;
- cmCAStringVector Permissions;
- cmCAStringVector Configurations;
- cmCAEnabler Optional;
- cmCAEnabler NamelinkOnly;
- cmCAEnabler NamelinkSkip;
+ std::string Destination;
+ std::string Component;
+ std::string NamelinkComponent;
+ bool ExcludeFromAll = false;
+ std::string Rename;
+ std::vector<std::string> Permissions;
+ std::vector<std::string> Configurations;
+ bool Optional = false;
+ bool NamelinkOnly = false;
+ bool NamelinkSkip = false;
+ std::string Type;
std::string DestinationString;
std::string PermissionsString;
- cmInstallCommandArguments* GenericArguments;
+ cmInstallCommandArguments* GenericArguments = nullptr;
static const char* PermissionsTable[];
static const std::string EmptyString;
std::string DefaultComponentName;
diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx
index 54ad85c3b..259c7f76d 100644
--- a/Source/cmInstallDirectoryGenerator.cxx
+++ b/Source/cmInstallDirectoryGenerator.cxx
@@ -6,8 +6,8 @@
#include "cmInstallType.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cm_auto_ptr.hxx"
cmInstallDirectoryGenerator::cmInstallDirectoryGenerator(
std::vector<std::string> const& dirs, const char* dest,
@@ -17,7 +17,7 @@ cmInstallDirectoryGenerator::cmInstallDirectoryGenerator(
bool optional)
: cmInstallGenerator(dest, configurations, component, message,
exclude_from_all)
- , LocalGenerator(CM_NULLPTR)
+ , LocalGenerator(nullptr)
, Directories(dirs)
, FilePermissions(file_permissions)
, DirPermissions(dir_permissions)
@@ -30,21 +30,22 @@ cmInstallDirectoryGenerator::cmInstallDirectoryGenerator(
}
// We need per-config actions if any directories have generator expressions.
- for (std::vector<std::string>::const_iterator i = dirs.begin();
- !this->ActionsPerConfig && i != dirs.end(); ++i) {
- if (cmGeneratorExpression::Find(*i) != std::string::npos) {
- this->ActionsPerConfig = true;
+ if (!this->ActionsPerConfig) {
+ for (std::string const& dir : dirs) {
+ if (cmGeneratorExpression::Find(dir) != std::string::npos) {
+ this->ActionsPerConfig = true;
+ break;
+ }
}
}
}
-cmInstallDirectoryGenerator::~cmInstallDirectoryGenerator()
-{
-}
+cmInstallDirectoryGenerator::~cmInstallDirectoryGenerator() = default;
-void cmInstallDirectoryGenerator::Compute(cmLocalGenerator* lg)
+bool cmInstallDirectoryGenerator::Compute(cmLocalGenerator* lg)
{
- LocalGenerator = lg;
+ this->LocalGenerator = lg;
+ return true;
}
void cmInstallDirectoryGenerator::GenerateScriptActions(std::ostream& os,
@@ -61,20 +62,16 @@ void cmInstallDirectoryGenerator::GenerateScriptForConfig(
std::ostream& os, const std::string& config, Indent indent)
{
std::vector<std::string> dirs;
- cmGeneratorExpression ge;
- for (std::vector<std::string>::const_iterator i = this->Directories.begin();
- i != this->Directories.end(); ++i) {
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(*i);
- cmSystemTools::ExpandListArgument(
- cge->Evaluate(this->LocalGenerator, config), dirs);
+ for (std::string const& d : this->Directories) {
+ cmExpandList(
+ cmGeneratorExpression::Evaluate(d, this->LocalGenerator, config), dirs);
}
// Make sure all dirs have absolute paths.
cmMakefile const& mf = *this->LocalGenerator->GetMakefile();
- for (std::vector<std::string>::iterator i = dirs.begin(); i != dirs.end();
- ++i) {
- if (!cmSystemTools::FileIsFullPath(i->c_str())) {
- *i = std::string(mf.GetCurrentSourceDirectory()) + "/" + *i;
+ for (std::string& d : dirs) {
+ if (!cmSystemTools::FileIsFullPath(d)) {
+ d = cmStrCat(mf.GetCurrentSourceDirectory(), "/", d);
}
}
@@ -86,7 +83,7 @@ void cmInstallDirectoryGenerator::AddDirectoryInstallRule(
std::vector<std::string> const& dirs)
{
// Write code to install the directories.
- const char* no_rename = CM_NULLPTR;
+ const char* no_rename = nullptr;
this->AddInstallRule(os, this->GetDestination(config),
cmInstallType_DIRECTORY, dirs, this->Optional,
this->FilePermissions.c_str(),
@@ -97,6 +94,6 @@ void cmInstallDirectoryGenerator::AddDirectoryInstallRule(
std::string cmInstallDirectoryGenerator::GetDestination(
std::string const& config) const
{
- cmGeneratorExpression ge;
- return ge.Parse(this->Destination)->Evaluate(this->LocalGenerator, config);
+ return cmGeneratorExpression::Evaluate(this->Destination,
+ this->LocalGenerator, config);
}
diff --git a/Source/cmInstallDirectoryGenerator.h b/Source/cmInstallDirectoryGenerator.h
index aa2cbc690..84c06948e 100644
--- a/Source/cmInstallDirectoryGenerator.h
+++ b/Source/cmInstallDirectoryGenerator.h
@@ -3,15 +3,15 @@
#ifndef cmInstallDirectoryGenerator_h
#define cmInstallDirectoryGenerator_h
-#include "cmInstallGenerator.h"
-#include "cmScriptGenerator.h"
-
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
#include <vector>
+#include "cmInstallGenerator.h"
+#include "cmScriptGenerator.h"
+
class cmLocalGenerator;
/** \class cmInstallDirectoryGenerator
@@ -27,16 +27,16 @@ public:
const char* component, MessageLevel message,
bool exclude_from_all, const char* literal_args,
bool optional = false);
- ~cmInstallDirectoryGenerator() CM_OVERRIDE;
+ ~cmInstallDirectoryGenerator() override;
- void Compute(cmLocalGenerator* lg) CM_OVERRIDE;
+ bool Compute(cmLocalGenerator* lg) override;
std::string GetDestination(std::string const& config) const;
protected:
- void GenerateScriptActions(std::ostream& os, Indent indent) CM_OVERRIDE;
+ void GenerateScriptActions(std::ostream& os, Indent indent) override;
void GenerateScriptForConfig(std::ostream& os, const std::string& config,
- Indent indent) CM_OVERRIDE;
+ Indent indent) override;
void AddDirectoryInstallRule(std::ostream& os, const std::string& config,
Indent indent,
std::vector<std::string> const& dirs);
diff --git a/Source/cmInstallExportAndroidMKGenerator.cxx b/Source/cmInstallExportAndroidMKGenerator.cxx
deleted file mode 100644
index 8eeaa9c7c..000000000
--- a/Source/cmInstallExportAndroidMKGenerator.cxx
+++ /dev/null
@@ -1,140 +0,0 @@
-
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmInstallExportAndroidMKGenerator.h"
-
-#include <stdio.h>
-
-#include "cmExportInstallFileGenerator.h"
-#include "cmExportSet.h"
-#include "cmGeneratedFileStream.h"
-#include "cmGlobalGenerator.h"
-#include "cmInstallFilesGenerator.h"
-#include "cmInstallTargetGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmMakefile.h"
-#include "cmake.h"
-
-cmInstallExportAndroidMKGenerator::cmInstallExportAndroidMKGenerator(
- cmExportSet* exportSet, const char* destination,
- const char* file_permissions, std::vector<std::string> const& configurations,
- const char* component, MessageLevel message, bool exclude_from_all,
- const char* filename, const char* name_space, bool exportOld)
- : cmInstallExportGenerator(exportSet, destination, file_permissions,
- configurations, component, message,
- exclude_from_all, filename, name_space, exportOld)
-{
-}
-
-cmInstallExportAndroidMKGenerator::~cmInstallExportAndroidMKGenerator()
-{
-}
-
-void cmInstallExportAndroidMKGenerator::Compute(cmLocalGenerator* lg)
-{
- this->LocalGenerator = lg;
- this->ExportSet->Compute(lg);
-}
-
-void cmInstallExportAndroidMKGenerator::GenerateScript(std::ostream& os)
-{
- // Skip empty sets.
- if (ExportSet->GetTargetExports()->empty()) {
- std::ostringstream e;
- e << "INSTALL(EXPORT) given unknown export \"" << ExportSet->GetName()
- << "\"";
- cmSystemTools::Error(e.str().c_str());
- return;
- }
-
- // Create the temporary directory in which to store the files.
- this->ComputeTempDir();
- cmSystemTools::MakeDirectory(this->TempDir.c_str());
-
- // Construct a temporary location for the file.
- this->MainImportFile = this->TempDir;
- this->MainImportFile += "/";
- this->MainImportFile += this->FileName;
-
- // Generate the import file for this export set.
- this->EFGen->SetExportFile(this->MainImportFile.c_str());
- this->EFGen->SetNamespace(this->Namespace);
- this->EFGen->SetExportOld(this->ExportOld);
- if (this->ConfigurationTypes->empty()) {
- if (!this->ConfigurationName.empty()) {
- this->EFGen->AddConfiguration(this->ConfigurationName);
- } else {
- this->EFGen->AddConfiguration("");
- }
- } else {
- for (std::vector<std::string>::const_iterator ci =
- this->ConfigurationTypes->begin();
- ci != this->ConfigurationTypes->end(); ++ci) {
- this->EFGen->AddConfiguration(*ci);
- }
- }
- this->EFGen->GenerateImportFile();
-
- // Perform the main install script generation.
- this->cmInstallGenerator::GenerateScript(os);
-}
-
-void cmInstallExportAndroidMKGenerator::GenerateScriptConfigs(
- std::ostream& os, Indent const& indent)
-{
- // Create the main install rules first.
- this->cmInstallGenerator::GenerateScriptConfigs(os, indent);
-
- // Now create a configuration-specific install rule for the import
- // file of each configuration.
- std::vector<std::string> files;
- for (std::map<std::string, std::string>::const_iterator i =
- this->EFGen->GetConfigImportFiles().begin();
- i != this->EFGen->GetConfigImportFiles().end(); ++i) {
- files.push_back(i->second);
- std::string config_test = this->CreateConfigTest(i->first);
- os << indent << "if(" << config_test << ")\n";
- this->AddInstallRule(os, this->Destination, cmInstallType_FILES, files,
- false, this->FilePermissions.c_str(), CM_NULLPTR,
- CM_NULLPTR, CM_NULLPTR, indent.Next());
- os << indent << "endif()\n";
- files.clear();
- }
-}
-
-void cmInstallExportAndroidMKGenerator::GenerateScriptActions(
- std::ostream& os, Indent const& indent)
-{
- // Remove old per-configuration export files if the main changes.
- std::string installedDir = "$ENV{DESTDIR}";
- installedDir += this->ConvertToAbsoluteDestination(this->Destination);
- installedDir += "/";
- std::string installedFile = installedDir;
- installedFile += this->FileName;
- os << indent << "if(EXISTS \"" << installedFile << "\")\n";
- Indent indentN = indent.Next();
- Indent indentNN = indentN.Next();
- Indent indentNNN = indentNN.Next();
- /* clang-format off */
- os << indentN << "file(DIFFERENT EXPORT_FILE_CHANGED FILES\n"
- << indentN << " \"" << installedFile << "\"\n"
- << indentN << " \"" << this->MainImportFile << "\")\n";
- os << indentN << "if(EXPORT_FILE_CHANGED)\n";
- os << indentNN << "file(GLOB OLD_CONFIG_FILES \"" << installedDir
- << this->EFGen->GetConfigImportFileGlob() << "\")\n";
- os << indentNN << "if(OLD_CONFIG_FILES)\n";
- os << indentNNN << "message(STATUS \"Old export file \\\"" << installedFile
- << "\\\" will be replaced. Removing files [${OLD_CONFIG_FILES}].\")\n";
- os << indentNNN << "file(REMOVE ${OLD_CONFIG_FILES})\n";
- os << indentNN << "endif()\n";
- os << indentN << "endif()\n";
- os << indent << "endif()\n";
- /* clang-format on */
-
- // Install the main export file.
- std::vector<std::string> files;
- files.push_back(this->MainImportFile);
- this->AddInstallRule(os, this->Destination, cmInstallType_FILES, files,
- false, this->FilePermissions.c_str(), CM_NULLPTR,
- CM_NULLPTR, CM_NULLPTR, indent);
-}
diff --git a/Source/cmInstallExportAndroidMKGenerator.h b/Source/cmInstallExportAndroidMKGenerator.h
deleted file mode 100644
index 189084a1a..000000000
--- a/Source/cmInstallExportAndroidMKGenerator.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmInstallExportAndroidMKGenerator_h
-#define cmInstallExportAndroidMKGenerator_h
-
-#include "cmInstallExportGenerator.h"
-
-class cmExportInstallFileGenerator;
-class cmInstallFilesGenerator;
-class cmInstallTargetGenerator;
-class cmExportSet;
-class cmMakefile;
-
-/** \class cmInstallExportAndroidMKGenerator
- * \brief Generate rules for creating an export files.
- */
-class cmInstallExportAndroidMKGenerator : public cmInstallExportGenerator
-{
-public:
- cmInstallExportAndroidMKGenerator(
- cmExportSet* exportSet, const char* dest, const char* file_permissions,
- const std::vector<std::string>& configurations, const char* component,
- MessageLevel message, bool exclude_from_all, const char* filename,
- const char* name_space, bool exportOld);
- ~cmInstallExportAndroidMKGenerator();
-
- void Compute(cmLocalGenerator* lg);
-
-protected:
- virtual void GenerateScript(std::ostream& os);
- virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent);
- virtual void GenerateScriptActions(std::ostream& os, Indent const& indent);
- void GenerateImportFile(cmExportSet const* exportSet);
- void GenerateImportFile(const char* config, cmExportSet const* exportSet);
-};
-
-#endif
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index b176e85c5..cba68bed4 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -7,15 +7,15 @@
#include <sstream>
#include <utility>
-#ifdef CMAKE_BUILD_WITH_CMAKE
-#include "cmExportInstallAndroidMKGenerator.h"
+#ifndef CMAKE_BOOTSTRAP
+# include "cmExportInstallAndroidMKGenerator.h"
#endif
#include "cmExportInstallFileGenerator.h"
#include "cmExportSet.h"
#include "cmInstallType.h"
#include "cmLocalGenerator.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmake.h"
cmInstallExportGenerator::cmInstallExportGenerator(
cmExportSet* exportSet, const char* destination,
@@ -29,10 +29,10 @@ cmInstallExportGenerator::cmInstallExportGenerator(
, FileName(filename)
, Namespace(name_space)
, ExportOld(exportOld)
- , LocalGenerator(CM_NULLPTR)
+ , LocalGenerator(nullptr)
{
if (android) {
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
this->EFGen = new cmExportInstallAndroidMKGenerator(this);
#endif
} else {
@@ -46,19 +46,19 @@ cmInstallExportGenerator::~cmInstallExportGenerator()
delete this->EFGen;
}
-void cmInstallExportGenerator::Compute(cmLocalGenerator* lg)
+bool cmInstallExportGenerator::Compute(cmLocalGenerator* lg)
{
this->LocalGenerator = lg;
this->ExportSet->Compute(lg);
+ return true;
}
void cmInstallExportGenerator::ComputeTempDir()
{
// Choose a temporary directory in which to generate the import
// files to be installed.
- this->TempDir = this->LocalGenerator->GetCurrentBinaryDirectory();
- this->TempDir += cmake::GetCMakeFilesDirectory();
- this->TempDir += "/Export";
+ this->TempDir = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/Export");
if (this->Destination.empty()) {
return;
}
@@ -111,11 +111,9 @@ size_t cmInstallExportGenerator::GetMaxConfigLength() const
len = this->ConfigurationName.size();
}
} else {
- for (std::vector<std::string>::const_iterator ci =
- this->ConfigurationTypes->begin();
- ci != this->ConfigurationTypes->end(); ++ci) {
- if (ci->size() > len) {
- len = ci->size();
+ for (std::string const& c : *this->ConfigurationTypes) {
+ if (c.size() > len) {
+ len = c.size();
}
}
}
@@ -125,22 +123,20 @@ size_t cmInstallExportGenerator::GetMaxConfigLength() const
void cmInstallExportGenerator::GenerateScript(std::ostream& os)
{
// Skip empty sets.
- if (ExportSet->GetTargetExports()->empty()) {
+ if (ExportSet->GetTargetExports().empty()) {
std::ostringstream e;
e << "INSTALL(EXPORT) given unknown export \"" << ExportSet->GetName()
<< "\"";
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
return;
}
// 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;
- this->MainImportFile += "/";
- this->MainImportFile += this->FileName;
+ this->MainImportFile = cmStrCat(this->TempDir, '/', this->FileName);
// Generate the import file for this export set.
this->EFGen->SetExportFile(this->MainImportFile.c_str());
@@ -153,10 +149,8 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os)
this->EFGen->AddConfiguration("");
}
} else {
- for (std::vector<std::string>::const_iterator ci =
- this->ConfigurationTypes->begin();
- ci != this->ConfigurationTypes->end(); ++ci) {
- this->EFGen->AddConfiguration(*ci);
+ for (std::string const& c : *this->ConfigurationTypes) {
+ this->EFGen->AddConfiguration(c);
}
}
this->EFGen->GenerateImportFile();
@@ -174,15 +168,13 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
// Now create a configuration-specific install rule for the import
// file of each configuration.
std::vector<std::string> files;
- for (std::map<std::string, std::string>::const_iterator i =
- this->EFGen->GetConfigImportFiles().begin();
- i != this->EFGen->GetConfigImportFiles().end(); ++i) {
- files.push_back(i->second);
- std::string config_test = this->CreateConfigTest(i->first);
+ for (auto const& i : this->EFGen->GetConfigImportFiles()) {
+ files.push_back(i.second);
+ std::string config_test = this->CreateConfigTest(i.first);
os << indent << "if(" << config_test << ")\n";
this->AddInstallRule(os, this->Destination, cmInstallType_FILES, files,
- false, this->FilePermissions.c_str(), CM_NULLPTR,
- CM_NULLPTR, CM_NULLPTR, indent.Next());
+ false, this->FilePermissions.c_str(), nullptr,
+ nullptr, nullptr, indent.Next());
os << indent << "endif()\n";
files.clear();
}
@@ -192,11 +184,10 @@ void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
Indent indent)
{
// Remove old per-configuration export files if the main changes.
- std::string installedDir = "$ENV{DESTDIR}";
- installedDir += this->ConvertToAbsoluteDestination(this->Destination);
- installedDir += "/";
- std::string installedFile = installedDir;
- installedFile += this->FileName;
+ std::string installedDir =
+ cmStrCat("$ENV{DESTDIR}",
+ this->ConvertToAbsoluteDestination(this->Destination), '/');
+ std::string installedFile = cmStrCat(installedDir, this->FileName);
os << indent << "if(EXISTS \"" << installedFile << "\")\n";
Indent indentN = indent.Next();
Indent indentNN = indentN.Next();
@@ -209,7 +200,7 @@ void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
os << indentNN << "file(GLOB OLD_CONFIG_FILES \"" << installedDir
<< this->EFGen->GetConfigImportFileGlob() << "\")\n";
os << indentNN << "if(OLD_CONFIG_FILES)\n";
- os << indentNNN << "message(STATUS \"Old export file \\\"" << installedFile
+ os << indentNNN << R"(message(STATUS "Old export file \")" << installedFile
<< "\\\" will be replaced. Removing files [${OLD_CONFIG_FILES}].\")\n";
os << indentNNN << "file(REMOVE ${OLD_CONFIG_FILES})\n";
os << indentNN << "endif()\n";
@@ -221,6 +212,11 @@ void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
std::vector<std::string> files;
files.push_back(this->MainImportFile);
this->AddInstallRule(os, this->Destination, cmInstallType_FILES, files,
- false, this->FilePermissions.c_str(), CM_NULLPTR,
- CM_NULLPTR, CM_NULLPTR, indent);
+ false, this->FilePermissions.c_str(), nullptr, nullptr,
+ nullptr, indent);
+}
+
+std::string cmInstallExportGenerator::GetDestinationFile() const
+{
+ return this->Destination + '/' + this->FileName;
}
diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h
index 047e6b3cd..f44127e3d 100644
--- a/Source/cmInstallExportGenerator.h
+++ b/Source/cmInstallExportGenerator.h
@@ -3,16 +3,16 @@
#ifndef cmInstallExportGenerator_h
#define cmInstallExportGenerator_h
-#include "cmConfigure.h"
-
-#include "cmInstallGenerator.h"
-#include "cmScriptGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <iosfwd>
-#include <stddef.h>
#include <string>
#include <vector>
+#include "cmInstallGenerator.h"
+#include "cmScriptGenerator.h"
+
class cmExportInstallFileGenerator;
class cmExportSet;
class cmLocalGenerator;
@@ -30,22 +30,23 @@ public:
bool exclude_from_all, const char* filename,
const char* name_space, bool exportOld,
bool android);
- ~cmInstallExportGenerator() CM_OVERRIDE;
+ ~cmInstallExportGenerator() override;
cmExportSet* GetExportSet() { return this->ExportSet; }
- void Compute(cmLocalGenerator* lg) CM_OVERRIDE;
+ bool Compute(cmLocalGenerator* lg) override;
cmLocalGenerator* GetLocalGenerator() const { return this->LocalGenerator; }
const std::string& GetNamespace() const { return this->Namespace; }
std::string const& GetDestination() const { return this->Destination; }
+ std::string GetDestinationFile() const;
protected:
- void GenerateScript(std::ostream& os) CM_OVERRIDE;
- void GenerateScriptConfigs(std::ostream& os, Indent indent) CM_OVERRIDE;
- void GenerateScriptActions(std::ostream& os, Indent indent) CM_OVERRIDE;
+ void GenerateScript(std::ostream& os) override;
+ void GenerateScriptConfigs(std::ostream& os, Indent indent) override;
+ void GenerateScriptActions(std::ostream& os, Indent indent) override;
void GenerateImportFile(cmExportSet const* exportSet);
void GenerateImportFile(const char* config, cmExportSet const* exportSet);
void ComputeTempDir();
diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx
index 4a3b620af..d62394311 100644
--- a/Source/cmInstallFilesCommand.cxx
+++ b/Source/cmInstallFilesCommand.cxx
@@ -2,67 +2,72 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallFilesCommand.h"
+#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmInstallFilesGenerator.h"
#include "cmInstallGenerator.h"
#include "cmMakefile.h"
+#include "cmRange.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
+static std::string FindInstallSource(cmMakefile& makefile, const char* name);
+static void CreateInstallGenerator(cmMakefile& makefile,
+ std::string const& dest,
+ std::vector<std::string> const& files);
+static void FinalAction(cmMakefile& makefile, std::string const& dest,
+ std::vector<std::string> const& args);
-// cmExecutableCommand
-bool cmInstallFilesCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmInstallFilesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
+ cmMakefile& mf = status.GetMakefile();
+
// Enable the install target.
- this->Makefile->GetGlobalGenerator()->EnableInstallTarget();
+ mf.GetGlobalGenerator()->EnableInstallTarget();
- this->Destination = args[0];
+ std::string const& dest = args[0];
if ((args.size() > 1) && (args[1] == "FILES")) {
- this->IsFilesForm = true;
- for (std::vector<std::string>::const_iterator s = args.begin() + 2;
- s != args.end(); ++s) {
+ std::vector<std::string> files;
+ for (std::string const& arg : cmMakeRange(args).advance(2)) {
// Find the source location for each file listed.
- std::string f = this->FindInstallSource(s->c_str());
- this->Files.push_back(f);
+ files.push_back(FindInstallSource(mf, arg.c_str()));
}
- this->CreateInstallGenerator();
+ CreateInstallGenerator(mf, dest, files);
} else {
- this->IsFilesForm = false;
- this->FinalArgs.insert(this->FinalArgs.end(), args.begin() + 1,
- args.end());
+ std::vector<std::string> finalArgs(args.begin() + 1, args.end());
+ mf.AddFinalAction([dest, finalArgs](cmMakefile& makefile) {
+ FinalAction(makefile, dest, finalArgs);
+ });
}
- this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"));
+ mf.GetGlobalGenerator()->AddInstallComponent(
+ mf.GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"));
return true;
}
-void cmInstallFilesCommand::FinalPass()
+static void FinalAction(cmMakefile& makefile, std::string const& dest,
+ std::vector<std::string> const& args)
{
- // No final pass for "FILES" form of arguments.
- if (this->IsFilesForm) {
- return;
- }
-
std::string testf;
- std::string const& ext = this->FinalArgs[0];
+ std::string const& ext = args[0];
+ std::vector<std::string> installFiles;
// two different options
- if (this->FinalArgs.size() > 1) {
+ if (args.size() > 1) {
// now put the files into the list
- std::vector<std::string>::iterator s = this->FinalArgs.begin();
+ auto s = args.begin();
++s;
// for each argument, get the files
- for (; s != this->FinalArgs.end(); ++s) {
+ for (; s != args.end(); ++s) {
// replace any variables
std::string const& temps = *s;
if (!cmSystemTools::GetFilenamePath(temps).empty()) {
@@ -73,30 +78,31 @@ void cmInstallFilesCommand::FinalPass()
}
// add to the result
- this->Files.push_back(this->FindInstallSource(testf.c_str()));
+ installFiles.push_back(FindInstallSource(makefile, testf.c_str()));
}
} else // reg exp list
{
std::vector<std::string> files;
- std::string const& regex = this->FinalArgs[0];
- cmSystemTools::Glob(this->Makefile->GetCurrentSourceDirectory(), regex,
- files);
+ std::string const& regex = args[0];
+ cmSystemTools::Glob(makefile.GetCurrentSourceDirectory(), regex, files);
- std::vector<std::string>::iterator s = files.begin();
+ auto s = files.begin();
// for each argument, get the files
for (; s != files.end(); ++s) {
- this->Files.push_back(this->FindInstallSource(s->c_str()));
+ installFiles.push_back(FindInstallSource(makefile, s->c_str()));
}
}
- this->CreateInstallGenerator();
+ CreateInstallGenerator(makefile, dest, installFiles);
}
-void cmInstallFilesCommand::CreateInstallGenerator() const
+static void CreateInstallGenerator(cmMakefile& makefile,
+ std::string const& dest,
+ std::vector<std::string> const& files)
{
// Construct the destination. This command always installs under
// the prefix. We skip the leading slash given by the user.
- std::string destination = this->Destination.substr(1);
+ std::string destination = dest.substr(1);
cmSystemTools::ConvertToUnixSlashes(destination);
if (destination.empty()) {
destination = ".";
@@ -107,12 +113,12 @@ void cmInstallFilesCommand::CreateInstallGenerator() const
const char* no_rename = "";
bool no_exclude_from_all = false;
std::string no_component =
- this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
+ makefile.GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
std::vector<std::string> no_configurations;
cmInstallGenerator::MessageLevel message =
- cmInstallGenerator::SelectMessageLevel(this->Makefile);
- this->Makefile->AddInstallGenerator(new cmInstallFilesGenerator(
- this->Files, destination.c_str(), false, no_permissions, no_configurations,
+ cmInstallGenerator::SelectMessageLevel(&makefile);
+ makefile.AddInstallGenerator(new cmInstallFilesGenerator(
+ files, destination.c_str(), false, no_permissions, no_configurations,
no_component.c_str(), message, no_exclude_from_all, no_rename));
}
@@ -122,7 +128,7 @@ void cmInstallFilesCommand::CreateInstallGenerator() const
* present in the build tree. If a full path is given, it is just
* returned.
*/
-std::string cmInstallFilesCommand::FindInstallSource(const char* name) const
+static std::string FindInstallSource(cmMakefile& makefile, const char* name)
{
if (cmSystemTools::FileIsFullPath(name) ||
cmGeneratorExpression::Find(name) == 0) {
@@ -131,18 +137,14 @@ std::string cmInstallFilesCommand::FindInstallSource(const char* name) const
}
// This is a relative path.
- std::string tb = this->Makefile->GetCurrentBinaryDirectory();
- tb += "/";
- tb += name;
- std::string ts = this->Makefile->GetCurrentSourceDirectory();
- ts += "/";
- ts += name;
-
- if (cmSystemTools::FileExists(tb.c_str())) {
+ std::string tb = cmStrCat(makefile.GetCurrentBinaryDirectory(), '/', name);
+ std::string ts = cmStrCat(makefile.GetCurrentSourceDirectory(), '/', name);
+
+ 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/cmInstallFilesCommand.h b/Source/cmInstallFilesCommand.h
index b3c27b827..f4ebbdec9 100644
--- a/Source/cmInstallFilesCommand.h
+++ b/Source/cmInstallFilesCommand.h
@@ -3,54 +3,14 @@
#ifndef cmInstallFilesCommand_h
#define cmInstallFilesCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmInstallFilesCommand
- * \brief Specifies where to install some files
- *
- * cmInstallFilesCommand specifies the relative path where a list of
- * files should be installed.
- */
-class cmInstallFilesCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmInstallFilesCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
- /**
- * This is called at the end after all the information
- * specified by the command is accumulated. Most commands do
- * not implement this method. At this point, reading and
- * writing to the cache can be done.
- */
- void FinalPass() CM_OVERRIDE;
- bool HasFinalPass() const CM_OVERRIDE { return !this->IsFilesForm; }
-
-protected:
- void CreateInstallGenerator() const;
- std::string FindInstallSource(const char* name) const;
-
-private:
- std::vector<std::string> FinalArgs;
- bool IsFilesForm;
- std::string Destination;
- std::vector<std::string> Files;
-};
+bool cmInstallFilesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx
index 6323a9189..f5b69a5d4 100644
--- a/Source/cmInstallFilesGenerator.cxx
+++ b/Source/cmInstallFilesGenerator.cxx
@@ -4,8 +4,7 @@
#include "cmGeneratorExpression.h"
#include "cmInstallType.h"
-#include "cmSystemTools.h"
-#include "cm_auto_ptr.hxx"
+#include "cmStringAlgorithms.h"
class cmLocalGenerator;
@@ -16,7 +15,7 @@ cmInstallFilesGenerator::cmInstallFilesGenerator(
const char* rename, bool optional)
: cmInstallGenerator(dest, configurations, component, message,
exclude_from_all)
- , LocalGenerator(CM_NULLPTR)
+ , LocalGenerator(nullptr)
, Files(files)
, FilePermissions(file_permissions)
, Rename(rename)
@@ -28,29 +27,30 @@ cmInstallFilesGenerator::cmInstallFilesGenerator(
this->ActionsPerConfig = true;
}
- // We need per-config actions if any files have generator expressions.
- for (std::vector<std::string>::const_iterator i = files.begin();
- !this->ActionsPerConfig && i != files.end(); ++i) {
- if (cmGeneratorExpression::Find(*i) != std::string::npos) {
- this->ActionsPerConfig = true;
+ // We need per-config actions if any directories have generator expressions.
+ if (!this->ActionsPerConfig) {
+ for (std::string const& file : files) {
+ if (cmGeneratorExpression::Find(file) != std::string::npos) {
+ this->ActionsPerConfig = true;
+ break;
+ }
}
}
}
-cmInstallFilesGenerator::~cmInstallFilesGenerator()
-{
-}
+cmInstallFilesGenerator::~cmInstallFilesGenerator() = default;
-void cmInstallFilesGenerator::Compute(cmLocalGenerator* lg)
+bool cmInstallFilesGenerator::Compute(cmLocalGenerator* lg)
{
this->LocalGenerator = lg;
+ return true;
}
std::string cmInstallFilesGenerator::GetDestination(
std::string const& config) const
{
- cmGeneratorExpression ge;
- return ge.Parse(this->Destination)->Evaluate(this->LocalGenerator, config);
+ return cmGeneratorExpression::Evaluate(this->Destination,
+ this->LocalGenerator, config);
}
void cmInstallFilesGenerator::AddFilesInstallRule(
@@ -58,12 +58,12 @@ void cmInstallFilesGenerator::AddFilesInstallRule(
std::vector<std::string> const& files)
{
// Write code to install the files.
- const char* no_dir_permissions = CM_NULLPTR;
+ const char* no_dir_permissions = nullptr;
this->AddInstallRule(
os, this->GetDestination(config),
(this->Programs ? cmInstallType_PROGRAMS : cmInstallType_FILES), files,
this->Optional, this->FilePermissions.c_str(), no_dir_permissions,
- this->Rename.c_str(), CM_NULLPTR, indent);
+ this->Rename.c_str(), nullptr, indent);
}
void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os,
@@ -80,12 +80,9 @@ void cmInstallFilesGenerator::GenerateScriptForConfig(
std::ostream& os, const std::string& config, Indent indent)
{
std::vector<std::string> files;
- cmGeneratorExpression ge;
- for (std::vector<std::string>::const_iterator i = this->Files.begin();
- i != this->Files.end(); ++i) {
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(*i);
- cmSystemTools::ExpandListArgument(
- cge->Evaluate(this->LocalGenerator, config), files);
+ for (std::string const& f : this->Files) {
+ cmExpandList(
+ cmGeneratorExpression::Evaluate(f, this->LocalGenerator, config), files);
}
this->AddFilesInstallRule(os, config, indent, files);
}
diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h
index 62b57f9c7..a6800375b 100644
--- a/Source/cmInstallFilesGenerator.h
+++ b/Source/cmInstallFilesGenerator.h
@@ -3,15 +3,15 @@
#ifndef cmInstallFilesGenerator_h
#define cmInstallFilesGenerator_h
-#include "cmConfigure.h"
-
-#include "cmInstallGenerator.h"
-#include "cmScriptGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
#include <vector>
+#include "cmInstallGenerator.h"
+#include "cmScriptGenerator.h"
+
class cmLocalGenerator;
/** \class cmInstallFilesGenerator
@@ -27,16 +27,16 @@ public:
const char* component, MessageLevel message,
bool exclude_from_all, const char* rename,
bool optional = false);
- ~cmInstallFilesGenerator() CM_OVERRIDE;
+ ~cmInstallFilesGenerator() override;
- void Compute(cmLocalGenerator* lg) CM_OVERRIDE;
+ bool Compute(cmLocalGenerator* lg) override;
std::string GetDestination(std::string const& config) const;
protected:
- void GenerateScriptActions(std::ostream& os, Indent indent) CM_OVERRIDE;
+ void GenerateScriptActions(std::ostream& os, Indent indent) override;
void GenerateScriptForConfig(std::ostream& os, const std::string& config,
- Indent indent) CM_OVERRIDE;
+ Indent indent) override;
void AddFilesInstallRule(std::ostream& os, std::string const& config,
Indent indent,
std::vector<std::string> const& files);
diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx
index 13b588efb..ec173619f 100644
--- a/Source/cmInstallGenerator.cxx
+++ b/Source/cmInstallGenerator.cxx
@@ -2,11 +2,11 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallGenerator.h"
+#include <ostream>
+
#include "cmMakefile.h"
#include "cmSystemTools.h"
-#include <ostream>
-
cmInstallGenerator::cmInstallGenerator(
const char* destination, std::vector<std::string> const& configurations,
const char* component, MessageLevel message, bool exclude_from_all)
@@ -18,8 +18,19 @@ cmInstallGenerator::cmInstallGenerator(
{
}
-cmInstallGenerator::~cmInstallGenerator()
+cmInstallGenerator::~cmInstallGenerator() = default;
+
+bool cmInstallGenerator::HaveInstall()
{
+ return true;
+}
+
+void cmInstallGenerator::CheckCMP0082(bool& haveSubdirectoryInstall,
+ bool& haveInstallAfterSubdirectory)
+{
+ if (haveSubdirectoryInstall) {
+ haveInstallAfterSubdirectory = true;
+ }
}
void cmInstallGenerator::AddInstallRule(
@@ -55,20 +66,21 @@ 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();
- fi != files.end(); ++fi) {
- if (fi != files.begin()) {
+ bool firstIteration = true;
+ for (std::string const& file : files) {
+ if (!firstIteration) {
os << ";";
}
os << dest << "/";
if (rename && *rename) {
os << rename;
} else {
- os << cmSystemTools::GetFilenameName(*fi);
+ os << cmSystemTools::GetFilenameName(file);
}
+ firstIteration = false;
}
os << "\")\n";
os << indent << "if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION)\n";
@@ -113,9 +125,8 @@ void cmInstallGenerator::AddInstallRule(
if (files.size() == 1) {
os << " \"" << files[0] << "\"";
} else {
- for (std::vector<std::string>::const_iterator fi = files.begin();
- fi != files.end(); ++fi) {
- os << "\n" << indent << " \"" << *fi << "\"";
+ for (std::string const& f : files) {
+ os << "\n" << indent << " \"" << f << "\"";
}
os << "\n" << indent << " ";
if (!(literal_args && *literal_args)) {
@@ -131,9 +142,9 @@ void cmInstallGenerator::AddInstallRule(
std::string cmInstallGenerator::CreateComponentTest(const char* component,
bool exclude_from_all)
{
- std::string result = "\"${CMAKE_INSTALL_COMPONENT}\" STREQUAL \"";
+ std::string result = R"("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "x)";
result += component;
- result += "\"";
+ result += "x\"";
if (!exclude_from_all) {
result += " OR NOT CMAKE_INSTALL_COMPONENT";
}
@@ -166,7 +177,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/cmInstallGenerator.h b/Source/cmInstallGenerator.h
index 8f8701f1a..024027d4d 100644
--- a/Source/cmInstallGenerator.h
+++ b/Source/cmInstallGenerator.h
@@ -3,15 +3,15 @@
#ifndef cmInstallGenerator_h
#define cmInstallGenerator_h
-#include "cmConfigure.h"
-
-#include "cmInstallType.h"
-#include "cmScriptGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
#include <vector>
+#include "cmInstallType.h"
+#include "cmScriptGenerator.h"
+
class cmLocalGenerator;
class cmMakefile;
@@ -21,8 +21,6 @@ class cmMakefile;
*/
class cmInstallGenerator : public cmScriptGenerator
{
- CM_DISABLE_COPY(cmInstallGenerator)
-
public:
enum MessageLevel
{
@@ -36,14 +34,21 @@ public:
std::vector<std::string> const& configurations,
const char* component, MessageLevel message,
bool exclude_from_all);
- ~cmInstallGenerator() CM_OVERRIDE;
+ ~cmInstallGenerator() override;
+
+ cmInstallGenerator(cmInstallGenerator const&) = delete;
+ cmInstallGenerator& operator=(cmInstallGenerator const&) = delete;
+
+ virtual bool HaveInstall();
+ virtual void CheckCMP0082(bool& haveSubdirectoryInstall,
+ bool& haveInstallAfterSubdirectory);
void AddInstallRule(
std::ostream& os, std::string const& dest, cmInstallType type,
std::vector<std::string> const& files, bool optional = false,
- const char* permissions_file = CM_NULLPTR,
- const char* permissions_dir = CM_NULLPTR, const char* rename = CM_NULLPTR,
- const char* literal_args = CM_NULLPTR, Indent indent = Indent());
+ const char* permissions_file = nullptr,
+ const char* permissions_dir = nullptr, const char* rename = nullptr,
+ const char* literal_args = nullptr, Indent indent = Indent());
/** Get the install destination as it should appear in the
installation script. */
@@ -55,10 +60,10 @@ public:
/** Select message level from CMAKE_INSTALL_MESSAGE or 'never'. */
static MessageLevel SelectMessageLevel(cmMakefile* mf, bool never = false);
- virtual void Compute(cmLocalGenerator*) {}
+ virtual bool Compute(cmLocalGenerator*) { return true; }
protected:
- void GenerateScript(std::ostream& os) CM_OVERRIDE;
+ void GenerateScript(std::ostream& os) override;
std::string CreateComponentTest(const char* component,
bool exclude_from_all);
diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx
index 5ee81fbf6..6bb4409d5 100644
--- a/Source/cmInstallProgramsCommand.cxx
+++ b/Source/cmInstallProgramsCommand.cxx
@@ -2,72 +2,81 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallProgramsCommand.h"
+#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmInstallFilesGenerator.h"
#include "cmInstallGenerator.h"
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
+static void FinalAction(cmMakefile& makefile, std::string const& dest,
+ std::vector<std::string> const& args);
+static std::string FindInstallSource(cmMakefile& makefile, const char* name);
-// cmExecutableCommand
-bool cmInstallProgramsCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmInstallProgramsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
- // Enable the install target.
- this->Makefile->GetGlobalGenerator()->EnableInstallTarget();
-
- this->Destination = args[0];
+ cmMakefile& mf = status.GetMakefile();
- this->FinalArgs.insert(this->FinalArgs.end(), args.begin() + 1, args.end());
+ // Enable the install target.
+ mf.GetGlobalGenerator()->EnableInstallTarget();
- this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"));
+ mf.GetGlobalGenerator()->AddInstallComponent(
+ mf.GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"));
+ std::string const& dest = args[0];
+ std::vector<std::string> const finalArgs(args.begin() + 1, args.end());
+ mf.AddFinalAction([dest, finalArgs](cmMakefile& makefile) {
+ FinalAction(makefile, dest, finalArgs);
+ });
return true;
}
-void cmInstallProgramsCommand::FinalPass()
+static void FinalAction(cmMakefile& makefile, std::string const& dest,
+ std::vector<std::string> const& args)
{
bool files_mode = false;
- if (!this->FinalArgs.empty() && this->FinalArgs[0] == "FILES") {
+ if (!args.empty() && args[0] == "FILES") {
files_mode = true;
}
+ std::vector<std::string> files;
+
// two different options
- if (this->FinalArgs.size() > 1 || files_mode) {
+ if (args.size() > 1 || files_mode) {
// for each argument, get the programs
- std::vector<std::string>::iterator s = this->FinalArgs.begin();
+ auto s = args.begin();
if (files_mode) {
// Skip the FILES argument in files mode.
++s;
}
- for (; s != this->FinalArgs.end(); ++s) {
+ for (; s != args.end(); ++s) {
// add to the result
- this->Files.push_back(this->FindInstallSource(s->c_str()));
+ files.push_back(FindInstallSource(makefile, s->c_str()));
}
} else // reg exp list
{
std::vector<std::string> programs;
- cmSystemTools::Glob(this->Makefile->GetCurrentSourceDirectory(),
- this->FinalArgs[0], programs);
+ cmSystemTools::Glob(makefile.GetCurrentSourceDirectory(), args[0],
+ programs);
- std::vector<std::string>::iterator s = programs.begin();
+ auto s = programs.begin();
// for each argument, get the programs
for (; s != programs.end(); ++s) {
- this->Files.push_back(this->FindInstallSource(s->c_str()));
+ files.push_back(FindInstallSource(makefile, s->c_str()));
}
}
// Construct the destination. This command always installs under
// the prefix. We skip the leading slash given by the user.
- std::string destination = this->Destination.substr(1);
+ std::string destination = dest.substr(1);
cmSystemTools::ConvertToUnixSlashes(destination);
if (destination.empty()) {
destination = ".";
@@ -78,12 +87,12 @@ void cmInstallProgramsCommand::FinalPass()
const char* no_rename = "";
bool no_exclude_from_all = false;
std::string no_component =
- this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
+ makefile.GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
std::vector<std::string> no_configurations;
cmInstallGenerator::MessageLevel message =
- cmInstallGenerator::SelectMessageLevel(this->Makefile);
- this->Makefile->AddInstallGenerator(new cmInstallFilesGenerator(
- this->Files, destination.c_str(), true, no_permissions, no_configurations,
+ cmInstallGenerator::SelectMessageLevel(&makefile);
+ makefile.AddInstallGenerator(new cmInstallFilesGenerator(
+ files, destination.c_str(), true, no_permissions, no_configurations,
no_component.c_str(), message, no_exclude_from_all, no_rename));
}
@@ -93,7 +102,7 @@ void cmInstallProgramsCommand::FinalPass()
* present in the build tree. If a full path is given, it is just
* returned.
*/
-std::string cmInstallProgramsCommand::FindInstallSource(const char* name) const
+static std::string FindInstallSource(cmMakefile& makefile, const char* name)
{
if (cmSystemTools::FileIsFullPath(name) ||
cmGeneratorExpression::Find(name) == 0) {
@@ -102,18 +111,14 @@ std::string cmInstallProgramsCommand::FindInstallSource(const char* name) const
}
// This is a relative path.
- std::string tb = this->Makefile->GetCurrentBinaryDirectory();
- tb += "/";
- tb += name;
- std::string ts = this->Makefile->GetCurrentSourceDirectory();
- ts += "/";
- ts += name;
-
- if (cmSystemTools::FileExists(tb.c_str())) {
+ std::string tb = cmStrCat(makefile.GetCurrentBinaryDirectory(), '/', name);
+ std::string ts = cmStrCat(makefile.GetCurrentSourceDirectory(), '/', name);
+
+ 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/cmInstallProgramsCommand.h b/Source/cmInstallProgramsCommand.h
index 242fb953d..c567f3bac 100644
--- a/Source/cmInstallProgramsCommand.h
+++ b/Source/cmInstallProgramsCommand.h
@@ -3,53 +3,14 @@
#ifndef cmInstallProgramsCommand_h
#define cmInstallProgramsCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmInstallProgramsCommand
- * \brief Specifies where to install some programs
- *
- * cmInstallProgramsCommand specifies the relative path where a list of
- * programs should be installed.
- */
-class cmInstallProgramsCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmInstallProgramsCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
- /**
- * This is called at the end after all the information
- * specified by the command is accumulated. Most commands do
- * not implement this method. At this point, reading and
- * writing to the cache can be done.
- */
- void FinalPass() CM_OVERRIDE;
-
- bool HasFinalPass() const CM_OVERRIDE { return true; }
-
-protected:
- std::string FindInstallSource(const char* name) const;
-
-private:
- std::vector<std::string> FinalArgs;
- std::string Destination;
- std::vector<std::string> Files;
-};
+bool cmInstallProgramsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmInstallScriptGenerator.cxx b/Source/cmInstallScriptGenerator.cxx
index b39a622f5..ea294556b 100644
--- a/Source/cmInstallScriptGenerator.cxx
+++ b/Source/cmInstallScriptGenerator.cxx
@@ -2,38 +2,86 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallScriptGenerator.h"
-#include "cmScriptGenerator.h"
-
#include <ostream>
#include <vector>
+#include "cmGeneratorExpression.h"
+#include "cmLocalGenerator.h"
+#include "cmMessageType.h"
+#include "cmPolicies.h"
+#include "cmScriptGenerator.h"
+
cmInstallScriptGenerator::cmInstallScriptGenerator(const char* script,
bool code,
const char* component,
bool exclude_from_all)
- : cmInstallGenerator(CM_NULLPTR, std::vector<std::string>(), component,
+ : cmInstallGenerator(nullptr, std::vector<std::string>(), component,
MessageDefault, exclude_from_all)
, Script(script)
, Code(code)
+ , AllowGenex(false)
{
+ // We need per-config actions if the script has generator expressions.
+ if (cmGeneratorExpression::Find(Script) != std::string::npos) {
+ this->ActionsPerConfig = true;
+ }
}
-cmInstallScriptGenerator::~cmInstallScriptGenerator()
+cmInstallScriptGenerator::~cmInstallScriptGenerator() = default;
+
+bool cmInstallScriptGenerator::Compute(cmLocalGenerator* lg)
{
+ this->LocalGenerator = lg;
+
+ if (this->ActionsPerConfig) {
+ switch (this->LocalGenerator->GetPolicyStatus(cmPolicies::CMP0087)) {
+ case cmPolicies::WARN:
+ this->LocalGenerator->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0087));
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::NEW:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ this->AllowGenex = true;
+ break;
+ }
+ }
+
+ return true;
}
-void cmInstallScriptGenerator::GenerateScript(std::ostream& os)
+void cmInstallScriptGenerator::AddScriptInstallRule(std::ostream& os,
+ Indent indent,
+ std::string const& script)
{
- Indent indent;
- std::string component_test =
- this->CreateComponentTest(this->Component.c_str(), this->ExcludeFromAll);
- os << indent << "if(" << component_test << ")\n";
-
if (this->Code) {
- os << indent.Next() << this->Script << "\n";
+ os << indent << script << "\n";
} else {
- os << indent.Next() << "include(\"" << this->Script << "\")\n";
+ os << indent << "include(\"" << script << "\")\n";
}
+}
- os << indent << "endif()\n\n";
+void cmInstallScriptGenerator::GenerateScriptActions(std::ostream& os,
+ Indent indent)
+{
+ if (this->AllowGenex && this->ActionsPerConfig) {
+ this->cmInstallGenerator::GenerateScriptActions(os, indent);
+ } else {
+ this->AddScriptInstallRule(os, indent, this->Script);
+ }
+}
+
+void cmInstallScriptGenerator::GenerateScriptForConfig(
+ std::ostream& os, const std::string& config, Indent indent)
+{
+ if (this->AllowGenex) {
+ this->AddScriptInstallRule(os, indent,
+ cmGeneratorExpression::Evaluate(
+ this->Script, this->LocalGenerator, config));
+ } else {
+ this->AddScriptInstallRule(os, indent, this->Script);
+ }
}
diff --git a/Source/cmInstallScriptGenerator.h b/Source/cmInstallScriptGenerator.h
index e183999d0..7efa32169 100644
--- a/Source/cmInstallScriptGenerator.h
+++ b/Source/cmInstallScriptGenerator.h
@@ -3,13 +3,16 @@
#ifndef cmInstallScriptGenerator_h
#define cmInstallScriptGenerator_h
-#include "cmConfigure.h"
-
-#include "cmInstallGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
+#include "cmInstallGenerator.h"
+#include "cmScriptGenerator.h"
+
+class cmLocalGenerator;
+
/** \class cmInstallScriptGenerator
* \brief Generate target installation rules.
*/
@@ -18,12 +21,21 @@ class cmInstallScriptGenerator : public cmInstallGenerator
public:
cmInstallScriptGenerator(const char* script, bool code,
const char* component, bool exclude_from_all);
- ~cmInstallScriptGenerator() CM_OVERRIDE;
+ ~cmInstallScriptGenerator() override;
+
+ bool Compute(cmLocalGenerator* lg) override;
protected:
- void GenerateScript(std::ostream& os) CM_OVERRIDE;
+ void GenerateScriptActions(std::ostream& os, Indent indent) override;
+ void GenerateScriptForConfig(std::ostream& os, const std::string& config,
+ Indent indent) override;
+ void AddScriptInstallRule(std::ostream& os, Indent indent,
+ std::string const& script);
+
std::string Script;
bool Code;
+ cmLocalGenerator* LocalGenerator;
+ bool AllowGenex;
};
#endif
diff --git a/Source/cmInstallSubdirectoryGenerator.cxx b/Source/cmInstallSubdirectoryGenerator.cxx
new file mode 100644
index 000000000..8a0fefac2
--- /dev/null
+++ b/Source/cmInstallSubdirectoryGenerator.cxx
@@ -0,0 +1,76 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmInstallSubdirectoryGenerator.h"
+
+#include <sstream>
+#include <vector>
+
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmPolicies.h"
+#include "cmScriptGenerator.h"
+#include "cmSystemTools.h"
+
+cmInstallSubdirectoryGenerator::cmInstallSubdirectoryGenerator(
+ cmMakefile* makefile, const char* binaryDirectory, bool excludeFromAll)
+ : cmInstallGenerator(nullptr, std::vector<std::string>(), nullptr,
+ MessageDefault, excludeFromAll)
+ , Makefile(makefile)
+ , BinaryDirectory(binaryDirectory)
+{
+}
+
+cmInstallSubdirectoryGenerator::~cmInstallSubdirectoryGenerator() = default;
+
+bool cmInstallSubdirectoryGenerator::HaveInstall()
+{
+ for (auto generator : this->Makefile->GetInstallGenerators()) {
+ if (generator->HaveInstall()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void cmInstallSubdirectoryGenerator::CheckCMP0082(
+ bool& haveSubdirectoryInstall, bool& /*unused*/)
+{
+ if (this->HaveInstall()) {
+ haveSubdirectoryInstall = true;
+ }
+}
+
+bool cmInstallSubdirectoryGenerator::Compute(cmLocalGenerator* lg)
+{
+ this->LocalGenerator = lg;
+ return true;
+}
+
+void cmInstallSubdirectoryGenerator::GenerateScript(std::ostream& os)
+{
+ if (!this->ExcludeFromAll) {
+ cmPolicies::PolicyStatus status =
+ this->LocalGenerator->GetPolicyStatus(cmPolicies::CMP0082);
+ switch (status) {
+ case cmPolicies::WARN:
+ case cmPolicies::OLD:
+ // OLD behavior is handled in cmLocalGenerator::GenerateInstallRules()
+ break;
+
+ case cmPolicies::NEW:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS: {
+ Indent indent;
+ std::string odir = this->BinaryDirectory;
+ cmSystemTools::ConvertToUnixSlashes(odir);
+ os << indent << "if(NOT CMAKE_INSTALL_LOCAL_ONLY)\n"
+ << indent.Next()
+ << "# Include the install script for the subdirectory.\n"
+ << indent.Next() << "include(\"" << odir
+ << "/cmake_install.cmake\")\n"
+ << indent << "endif()\n\n";
+ } break;
+ }
+ }
+}
diff --git a/Source/cmInstallSubdirectoryGenerator.h b/Source/cmInstallSubdirectoryGenerator.h
new file mode 100644
index 000000000..b99bdd5ff
--- /dev/null
+++ b/Source/cmInstallSubdirectoryGenerator.h
@@ -0,0 +1,41 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmInstallSubdirectoryGenerator_h
+#define cmInstallSubdirectoryGenerator_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <iosfwd>
+#include <string>
+
+#include "cmInstallGenerator.h"
+
+class cmLocalGenerator;
+class cmMakefile;
+
+/** \class cmInstallSubdirectoryGenerator
+ * \brief Generate target installation rules.
+ */
+class cmInstallSubdirectoryGenerator : public cmInstallGenerator
+{
+public:
+ cmInstallSubdirectoryGenerator(cmMakefile* makefile,
+ const char* binaryDirectory,
+ bool excludeFromAll);
+ ~cmInstallSubdirectoryGenerator() override;
+
+ bool HaveInstall() override;
+ void CheckCMP0082(bool& haveSubdirectoryInstall,
+ bool& haveInstallAfterSubdirectory) override;
+
+ bool Compute(cmLocalGenerator* lg) override;
+
+protected:
+ void GenerateScript(std::ostream& os) override;
+
+ cmMakefile* Makefile;
+ std::string BinaryDirectory;
+ cmLocalGenerator* LocalGenerator;
+};
+
+#endif
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 84d6f7ac9..aa92fa71a 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -2,7 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallTargetGenerator.h"
-#include <assert.h>
+#include <cassert>
#include <map>
#include <set>
#include <sstream>
@@ -15,47 +15,34 @@
#include "cmInstallType.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmOutputConverter.h"
+#include "cmPolicies.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmake.h"
cmInstallTargetGenerator::cmInstallTargetGenerator(
- const std::string& targetName, const char* dest, bool implib,
+ std::string targetName, const char* dest, bool implib,
const char* file_permissions, std::vector<std::string> const& configurations,
const char* component, MessageLevel message, bool exclude_from_all,
- bool optional)
+ bool optional, cmListFileBacktrace backtrace)
: cmInstallGenerator(dest, configurations, component, message,
exclude_from_all)
- , TargetName(targetName)
- , Target(CM_NULLPTR)
+ , TargetName(std::move(targetName))
+ , Target(nullptr)
, FilePermissions(file_permissions)
, ImportLibrary(implib)
, Optional(optional)
+ , Backtrace(std::move(backtrace))
{
this->ActionsPerConfig = true;
this->NamelinkMode = NamelinkModeNone;
}
-cmInstallTargetGenerator::~cmInstallTargetGenerator()
-{
-}
-
-void cmInstallTargetGenerator::GenerateScript(std::ostream& os)
-{
- // Warn if installing an exclude-from-all target.
- if (this->Target->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
- std::ostringstream msg;
- msg << "WARNING: Target \"" << this->Target->GetName()
- << "\" has EXCLUDE_FROM_ALL set and will not be built by default "
- << "but an install rule has been provided for it. CMake does "
- << "not define behavior for this case.";
- cmSystemTools::Message(msg.str().c_str(), "Warning");
- }
-
- // Perform the main install script generation.
- this->cmInstallGenerator::GenerateScript(os);
-}
+cmInstallTargetGenerator::~cmInstallTargetGenerator() = default;
void cmInstallTargetGenerator::GenerateScriptForConfig(
std::ostream& os, const std::string& config, Indent indent)
@@ -90,7 +77,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
case cmStateEnums::GLOBAL_TARGET:
case cmStateEnums::UNKNOWN_LIBRARY:
this->Target->GetLocalGenerator()->IssueMessage(
- cmake::INTERNAL_ERROR,
+ MessageType::INTERNAL_ERROR,
"cmInstallTargetGenerator created with non-installable target.");
return;
}
@@ -99,20 +86,18 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
std::string fromDirConfig;
if (this->Target->NeedRelinkBeforeInstall(config)) {
fromDirConfig =
- this->Target->GetLocalGenerator()->GetCurrentBinaryDirectory();
- fromDirConfig += cmake::GetCMakeFilesDirectory();
- fromDirConfig += "/CMakeRelink.dir/";
+ cmStrCat(this->Target->GetLocalGenerator()->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/CMakeRelink.dir/");
} else {
cmStateEnums::ArtifactType artifact = this->ImportLibrary
? cmStateEnums::ImportLibraryArtifact
: cmStateEnums::RuntimeBinaryArtifact;
- fromDirConfig = this->Target->GetDirectory(config, artifact);
- fromDirConfig += "/";
+ fromDirConfig =
+ cmStrCat(this->Target->GetDirectory(config, artifact), '/');
}
- std::string toDir =
- this->ConvertToAbsoluteDestination(this->GetDestination(config));
- toDir += "/";
+ std::string toDir = cmStrCat(
+ this->ConvertToAbsoluteDestination(this->GetDestination(config)), '/');
// Compute the list of files to install for this target.
std::vector<std::string> filesFrom;
@@ -123,19 +108,15 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
// There is a bug in cmInstallCommand if this fails.
assert(this->NamelinkMode == NamelinkModeNone);
- std::string targetName;
- std::string targetNameReal;
- std::string targetNameImport;
- std::string targetNamePDB;
- this->Target->GetExecutableNames(targetName, targetNameReal,
- targetNameImport, targetNamePDB, config);
+ cmGeneratorTarget::Names targetNames =
+ this->Target->GetExecutableNames(config);
if (this->ImportLibrary) {
- std::string from1 = fromDirConfig + targetNameImport;
- std::string to1 = toDir + targetNameImport;
- filesFrom.push_back(from1);
- filesTo.push_back(to1);
+ std::string from1 = fromDirConfig + targetNames.ImportLibrary;
+ std::string to1 = toDir + targetNames.ImportLibrary;
+ filesFrom.push_back(std::move(from1));
+ filesTo.push_back(std::move(to1));
std::string targetNameImportLib;
- if (this->Target->GetImplibGNUtoMS(targetNameImport,
+ if (this->Target->GetImplibGNUtoMS(config, targetNames.ImportLibrary,
targetNameImportLib)) {
filesFrom.push_back(fromDirConfig + targetNameImportLib);
filesTo.push_back(toDir + targetNameImportLib);
@@ -144,8 +125,8 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
// An import library looks like a static library.
type = cmInstallType_STATIC_LIBRARY;
} else {
- std::string from1 = fromDirConfig + targetName;
- std::string to1 = toDir + targetName;
+ std::string from1 = fromDirConfig + targetNames.Output;
+ std::string to1 = toDir + targetNames.Output;
// Handle OSX Bundles.
if (this->Target->IsAppBundleOnApple()) {
@@ -167,41 +148,36 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
to1 += ".";
to1 += ext;
to1 += "/";
- if (!mf->PlatformIsAppleIos()) {
+ if (!mf->PlatformIsAppleEmbedded()) {
to1 += "Contents/MacOS/";
}
- to1 += targetName;
+ to1 += targetNames.Output;
} else {
// Tweaks apply to the real file, so list it first.
- if (targetNameReal != targetName) {
- std::string from2 = fromDirConfig + targetNameReal;
- std::string to2 = toDir += targetNameReal;
- filesFrom.push_back(from2);
- filesTo.push_back(to2);
+ if (targetNames.Real != targetNames.Output) {
+ std::string from2 = fromDirConfig + targetNames.Real;
+ std::string to2 = toDir += targetNames.Real;
+ 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;
- std::string targetNameSO;
- std::string targetNameReal;
- std::string targetNameImport;
- std::string targetNamePDB;
- this->Target->GetLibraryNames(targetName, targetNameSO, targetNameReal,
- targetNameImport, targetNamePDB, config);
+ cmGeneratorTarget::Names targetNames =
+ this->Target->GetLibraryNames(config);
if (this->ImportLibrary) {
// There is a bug in cmInstallCommand if this fails.
assert(this->NamelinkMode == NamelinkModeNone);
- std::string from1 = fromDirConfig + targetNameImport;
- std::string to1 = toDir + targetNameImport;
- filesFrom.push_back(from1);
- filesTo.push_back(to1);
+ std::string from1 = fromDirConfig + targetNames.ImportLibrary;
+ std::string to1 = toDir + targetNames.ImportLibrary;
+ filesFrom.push_back(std::move(from1));
+ filesTo.push_back(std::move(to1));
std::string targetNameImportLib;
- if (this->Target->GetImplibGNUtoMS(targetNameImport,
+ if (this->Target->GetImplibGNUtoMS(config, targetNames.ImportLibrary,
targetNameImportLib)) {
filesFrom.push_back(fromDirConfig + targetNameImportLib);
filesTo.push_back(toDir + targetNameImportLib);
@@ -210,56 +186,84 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
// An import library looks like a static library.
type = cmInstallType_STATIC_LIBRARY;
} else if (this->Target->IsFrameworkOnApple()) {
- // There is a bug in cmInstallCommand if this fails.
- assert(this->NamelinkMode == NamelinkModeNone);
+ // FIXME: In principle we should be able to
+ // assert(this->NamelinkMode == NamelinkModeNone);
+ // but since the current install() command implementation checks
+ // the FRAMEWORK property immediately instead of delaying until
+ // generate time, it is possible for project code to set the
+ // property after calling install(). In such a case, the install()
+ // command will use the LIBRARY code path and create two install
+ // generators, one for the namelink component (NamelinkModeOnly)
+ // and one for the primary artifact component (NamelinkModeSkip).
+ // Historically this was not diagnosed and resulted in silent
+ // installation of a framework to the LIBRARY destination.
+ // Retain that behavior and warn about the case.
+ switch (this->NamelinkMode) {
+ case NamelinkModeNone:
+ // Normal case.
+ break;
+ case NamelinkModeOnly:
+ // Assume the NamelinkModeSkip instance will warn and install.
+ return;
+ case NamelinkModeSkip: {
+ std::string e = "Target '" + this->Target->GetName() +
+ "' was changed to a FRAMEWORK sometime after install(). "
+ "This may result in the wrong install DESTINATION. "
+ "Set the FRAMEWORK property earlier.";
+ this->Target->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
+ MessageType::AUTHOR_WARNING, e, this->GetBacktrace());
+ } break;
+ }
// Install the whole framework directory.
type = cmInstallType_DIRECTORY;
literal_args += " USE_SOURCE_PERMISSIONS";
- std::string from1 = fromDirConfig + targetName;
+ std::string from1 = fromDirConfig + targetNames.Output;
from1 = cmSystemTools::GetFilenamePath(from1);
// Tweaks apply to the binary inside the bundle.
- std::string to1 = toDir + targetNameReal;
+ std::string to1 = toDir + targetNames.Real;
- 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;
literal_args += " USE_SOURCE_PERMISSIONS";
- std::string targetNameBase = targetName.substr(0, targetName.find('/'));
+ std::string targetNameBase =
+ targetNames.Output.substr(0, targetNames.Output.find('/'));
std::string from1 = fromDirConfig + targetNameBase;
- std::string to1 = toDir + targetName;
+ std::string to1 = toDir + targetNames.Output;
- filesFrom.push_back(from1);
- filesTo.push_back(to1);
+ filesFrom.push_back(std::move(from1));
+ filesTo.push_back(std::move(to1));
} else {
bool haveNamelink = false;
// Library link name.
- std::string fromName = fromDirConfig + targetName;
- std::string toName = toDir + targetName;
+ std::string fromName = fromDirConfig + targetNames.Output;
+ std::string toName = toDir + targetNames.Output;
// Library interface name.
std::string fromSOName;
std::string toSOName;
- if (targetNameSO != targetName) {
+ if (targetNames.SharedObject != targetNames.Output) {
haveNamelink = true;
- fromSOName = fromDirConfig + targetNameSO;
- toSOName = toDir + targetNameSO;
+ fromSOName = fromDirConfig + targetNames.SharedObject;
+ toSOName = toDir + targetNames.SharedObject;
}
// Library implementation name.
std::string fromRealName;
std::string toRealName;
- if (targetNameReal != targetName && targetNameReal != targetNameSO) {
+ if (targetNames.Real != targetNames.Output &&
+ targetNames.Real != targetNames.SharedObject) {
haveNamelink = true;
- fromRealName = fromDirConfig + targetNameReal;
- toRealName = toDir + targetNameReal;
+ fromRealName = fromDirConfig + targetNames.Real;
+ toRealName = toDir + targetNames.Real;
}
// Add the names based on the current namelink mode.
@@ -312,8 +316,8 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
&cmInstallTargetGenerator::PreReplacementTweaks);
// Write code to install the target file.
- const char* no_dir_permissions = CM_NULLPTR;
- const char* no_rename = CM_NULLPTR;
+ const char* no_dir_permissions = nullptr;
+ const char* no_rename = nullptr;
bool optional = this->Optional || this->ImportLibrary;
this->AddInstallRule(os, this->GetDestination(config), type, filesFrom,
optional, this->FilePermissions.c_str(),
@@ -351,8 +355,8 @@ void cmInstallTargetGenerator::GenerateScriptForConfigObjectLibrary(
std::string const obj_dir = this->Target->GetObjectDirectory(config);
std::string const literal_args = " FILES_FROM_DIR \"" + obj_dir + "\"";
- const char* no_dir_permissions = CM_NULLPTR;
- const char* no_rename = CM_NULLPTR;
+ const char* no_dir_permissions = nullptr;
+ const char* no_rename = nullptr;
this->AddInstallRule(os, dest, cmInstallType_FILES, objects, this->Optional,
this->FilePermissions.c_str(), no_dir_permissions,
no_rename, literal_args.c_str(), indent);
@@ -362,18 +366,16 @@ void cmInstallTargetGenerator::GetInstallObjectNames(
std::string const& config, std::vector<std::string>& objects) const
{
this->Target->GetTargetObjectNames(config, objects);
- for (std::vector<std::string>::iterator i = objects.begin();
- i != objects.end(); ++i) {
- *i = computeInstallObjectDir(this->Target, config) + "/" + *i;
+ for (std::string& o : objects) {
+ o = cmStrCat(computeInstallObjectDir(this->Target, config), "/", o);
}
}
std::string cmInstallTargetGenerator::GetDestination(
std::string const& config) const
{
- cmGeneratorExpression ge;
- return ge.Parse(this->Destination)
- ->Evaluate(this->Target->GetLocalGenerator(), config);
+ return cmGeneratorExpression::Evaluate(
+ this->Destination, this->Target->GetLocalGenerator(), config);
}
std::string cmInstallTargetGenerator::GetInstallFilename(
@@ -391,57 +393,54 @@ std::string cmInstallTargetGenerator::GetInstallFilename(
std::string fname;
// Compute the name of the library.
if (target->GetType() == cmStateEnums::EXECUTABLE) {
- std::string targetName;
- std::string targetNameReal;
- std::string targetNameImport;
- std::string targetNamePDB;
- target->GetExecutableNames(targetName, targetNameReal, targetNameImport,
- targetNamePDB, config);
+ cmGeneratorTarget::Names targetNames = target->GetExecutableNames(config);
if (nameType == NameImplib) {
// Use the import library name.
- if (!target->GetImplibGNUtoMS(targetNameImport, fname,
+ if (!target->GetImplibGNUtoMS(config, targetNames.ImportLibrary, fname,
"${CMAKE_IMPORT_LIBRARY_SUFFIX}")) {
- fname = targetNameImport;
+ fname = targetNames.ImportLibrary;
}
} else if (nameType == NameReal) {
// Use the canonical name.
- fname = targetNameReal;
+ fname = targetNames.Real;
} else {
// Use the canonical name.
- fname = targetName;
+ fname = targetNames.Output;
}
} else {
- std::string targetName;
- std::string targetNameSO;
- std::string targetNameReal;
- std::string targetNameImport;
- std::string targetNamePDB;
- target->GetLibraryNames(targetName, targetNameSO, targetNameReal,
- targetNameImport, targetNamePDB, config);
+ cmGeneratorTarget::Names targetNames = target->GetLibraryNames(config);
if (nameType == NameImplib) {
// Use the import library name.
- if (!target->GetImplibGNUtoMS(targetNameImport, fname,
+ if (!target->GetImplibGNUtoMS(config, targetNames.ImportLibrary, fname,
"${CMAKE_IMPORT_LIBRARY_SUFFIX}")) {
- fname = targetNameImport;
+ fname = targetNames.ImportLibrary;
}
} else if (nameType == NameSO) {
// Use the soname.
- fname = targetNameSO;
+ fname = targetNames.SharedObject;
} else if (nameType == NameReal) {
// Use the real name.
- fname = targetNameReal;
+ fname = targetNames.Real;
} else {
// Use the canonical name.
- fname = targetName;
+ fname = targetNames.Output;
}
}
return fname;
}
-void cmInstallTargetGenerator::Compute(cmLocalGenerator* lg)
+bool cmInstallTargetGenerator::Compute(cmLocalGenerator* lg)
{
+ // Lookup this target in the current directory.
this->Target = lg->FindLocalNonAliasGeneratorTarget(this->TargetName);
+ if (!this->Target) {
+ // If no local target has been found, find it in the global scope.
+ this->Target =
+ lg->GetGlobalGenerator()->FindGeneratorTarget(this->TargetName);
+ }
+
+ return true;
}
void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent,
@@ -476,9 +475,8 @@ void cmInstallTargetGenerator::AddTweak(std::ostream& os, Indent indent,
if (!tws.empty()) {
Indent indent2 = indent.Next().Next();
os << indent << "foreach(file\n";
- for (std::vector<std::string>::const_iterator i = files.begin();
- i != files.end(); ++i) {
- os << indent2 << "\"" << this->GetDestDirPath(*i) << "\"\n";
+ for (std::string const& f : files) {
+ os << indent2 << "\"" << this->GetDestDirPath(f) << "\"\n";
}
os << indent2 << ")\n";
os << tws;
@@ -546,11 +544,7 @@ void cmInstallTargetGenerator::AddInstallNamePatchRule(
this->Target->GetLinkInformation(config)) {
std::set<cmGeneratorTarget const*> const& sharedLibs =
cli->GetSharedLibrariesLinked();
- for (std::set<cmGeneratorTarget const*>::const_iterator j =
- sharedLibs.begin();
- j != sharedLibs.end(); ++j) {
- cmGeneratorTarget const* tgt = *j;
-
+ for (cmGeneratorTarget const* tgt : sharedLibs) {
// The install_name of an imported target does not change.
if (tgt->IsImported()) {
continue;
@@ -596,8 +590,8 @@ void cmInstallTargetGenerator::AddInstallNamePatchRule(
// on the installed file.
if (for_build != for_install) {
// Prepare to refer to the install-tree install_name.
- new_id = for_install;
- new_id += this->GetInstallFilename(this->Target, config, NameSO);
+ new_id = cmStrCat(
+ for_install, this->GetInstallFilename(this->Target, config, NameSO));
}
}
@@ -609,12 +603,9 @@ void cmInstallTargetGenerator::AddInstallNamePatchRule(
if (!new_id.empty()) {
os << "\n" << indent << " -id \"" << new_id << "\"";
}
- for (std::map<std::string, std::string>::const_iterator i =
- install_name_remap.begin();
- i != install_name_remap.end(); ++i) {
+ for (auto const& i : install_name_remap) {
os << "\n"
- << indent << " -change \"" << i->first << "\" \"" << i->second
- << "\"";
+ << indent << " -change \"" << i.first << "\" \"" << i.second << "\"";
}
os << "\n" << indent << " \"" << toDestDirPath << "\")\n";
}
@@ -641,17 +632,34 @@ void cmInstallTargetGenerator::AddRPathCheckRule(
return;
}
- // Get the install RPATH from the link information.
- std::string newRpath = cli->GetChrpathString();
-
// Write a rule to remove the installed file if its rpath is not the
// new rpath. This is needed for existing build/install trees when
// the installed rpath changes but the file is not rebuilt.
- /* clang-format off */
os << indent << "file(RPATH_CHECK\n"
- << indent << " FILE \"" << toDestDirPath << "\"\n"
- << indent << " RPATH \"" << newRpath << "\")\n";
- /* clang-format on */
+ << indent << " FILE \"" << toDestDirPath << "\"\n";
+
+ // CMP0095: ``RPATH`` entries are properly escaped in the intermediary
+ // CMake install script.
+ switch (this->Target->GetPolicyStatusCMP0095()) {
+ case cmPolicies::WARN:
+ // No author warning needed here, we warn later in
+ // cmInstallTargetGenerator::AddChrpathPatchRule().
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD: {
+ // Get the install RPATH from the link information.
+ std::string newRpath = cli->GetChrpathString();
+ os << indent << " RPATH \"" << newRpath << "\")\n";
+ break;
+ }
+ default: {
+ // Get the install RPATH from the link information and
+ // escape any CMake syntax in the install RPATH.
+ std::string escapedNewRpath =
+ cmOutputConverter::EscapeForCMake(cli->GetChrpathString());
+ os << indent << " RPATH " << escapedNewRpath << ")\n";
+ break;
+ }
+ }
}
void cmInstallTargetGenerator::AddChrpathPatchRule(
@@ -677,7 +685,8 @@ void cmInstallTargetGenerator::AddChrpathPatchRule(
std::string installNameTool =
mf->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL");
- std::vector<std::string> oldRuntimeDirs, newRuntimeDirs;
+ std::vector<std::string> oldRuntimeDirs;
+ std::vector<std::string> newRuntimeDirs;
cli->GetRPath(oldRuntimeDirs, false);
cli->GetRPath(newRuntimeDirs, true);
@@ -697,15 +706,14 @@ void cmInstallTargetGenerator::AddChrpathPatchRule(
<< "Therefore, runtime paths will not be changed when installing. "
<< "CMAKE_BUILD_WITH_INSTALL_RPATH may be used to work around"
" this limitation.";
- mf->IssueMessage(cmake::WARNING, msg.str());
+ mf->IssueMessage(MessageType::WARNING, msg.str());
} else {
// Note: These paths are kept unique to avoid
// install_name_tool corruption.
std::set<std::string> runpaths;
- for (std::vector<std::string>::const_iterator i = oldRuntimeDirs.begin();
- i != oldRuntimeDirs.end(); ++i) {
+ for (std::string const& i : oldRuntimeDirs) {
std::string runpath =
- mf->GetGlobalGenerator()->ExpandCFGIntDir(*i, config);
+ mf->GetGlobalGenerator()->ExpandCFGIntDir(i, config);
if (runpaths.find(runpath) == runpaths.end()) {
runpaths.insert(runpath);
@@ -717,10 +725,9 @@ void cmInstallTargetGenerator::AddChrpathPatchRule(
}
runpaths.clear();
- for (std::vector<std::string>::const_iterator i = newRuntimeDirs.begin();
- i != newRuntimeDirs.end(); ++i) {
+ for (std::string const& i : newRuntimeDirs) {
std::string runpath =
- mf->GetGlobalGenerator()->ExpandCFGIntDir(*i, config);
+ mf->GetGlobalGenerator()->ExpandCFGIntDir(i, config);
if (runpaths.find(runpath) == runpaths.end()) {
os << indent << "execute_process(COMMAND " << installNameTool
@@ -742,11 +749,34 @@ void cmInstallTargetGenerator::AddChrpathPatchRule(
return;
}
+ // Escape any CMake syntax in the RPATHs.
+ std::string escapedOldRpath = cmOutputConverter::EscapeForCMake(oldRpath);
+ std::string escapedNewRpath = cmOutputConverter::EscapeForCMake(newRpath);
+
// Write a rule to run chrpath to set the install-tree RPATH
os << indent << "file(RPATH_CHANGE\n"
<< indent << " FILE \"" << toDestDirPath << "\"\n"
- << indent << " OLD_RPATH \"" << oldRpath << "\"\n"
- << indent << " NEW_RPATH \"" << newRpath << "\")\n";
+ << indent << " OLD_RPATH " << escapedOldRpath << "\n";
+
+ // CMP0095: ``RPATH`` entries are properly escaped in the intermediary
+ // CMake install script.
+ switch (this->Target->GetPolicyStatusCMP0095()) {
+ case cmPolicies::WARN:
+ this->IssueCMP0095Warning(newRpath);
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ os << indent << " NEW_RPATH \"" << newRpath << "\"";
+ break;
+ default:
+ os << indent << " NEW_RPATH " << escapedNewRpath;
+ break;
+ }
+
+ if (this->Target->GetPropertyAsBool("INSTALL_REMOVE_ENVIRONMENT_RPATH")) {
+ os << "\n" << indent << " INSTALL_REMOVE_ENVIRONMENT_RPATH)\n";
+ } else {
+ os << ")\n";
+ }
}
}
@@ -771,10 +801,22 @@ void cmInstallTargetGenerator::AddStripRule(std::ostream& os, Indent indent,
return;
}
+ std::string stripArgs;
+
+ // macOS 'strip' is picky, executables need '-u -r' and dylibs need '-x'.
+ if (this->Target->Target->GetMakefile()->IsOn("APPLE")) {
+ if (this->Target->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->Target->GetType() == cmStateEnums::MODULE_LIBRARY) {
+ stripArgs = "-x ";
+ } else if (this->Target->GetType() == cmStateEnums::EXECUTABLE) {
+ stripArgs = "-u -r ";
+ }
+ }
+
os << indent << "if(CMAKE_INSTALL_DO_STRIP)\n";
os << indent << " execute_process(COMMAND \""
<< this->Target->Target->GetMakefile()->GetDefinition("CMAKE_STRIP")
- << "\" \"" << toDestDirPath << "\")\n";
+ << "\" " << stripArgs << "\"" << toDestDirPath << "\")\n";
os << indent << "endif()\n";
}
@@ -792,7 +834,7 @@ void cmInstallTargetGenerator::AddRanlibRule(std::ostream& os, Indent indent,
return;
}
- std::string ranlib =
+ const std::string& ranlib =
this->Target->Target->GetMakefile()->GetRequiredDefinition("CMAKE_RANLIB");
if (ranlib.empty()) {
return;
@@ -807,7 +849,7 @@ void cmInstallTargetGenerator::AddUniversalInstallRule(
{
cmMakefile const* mf = this->Target->Target->GetMakefile();
- if (!mf->PlatformIsAppleIos() || !mf->IsOn("XCODE")) {
+ if (!mf->PlatformIsAppleEmbedded() || !mf->IsOn("XCODE")) {
return;
}
@@ -837,3 +879,26 @@ void cmInstallTargetGenerator::AddUniversalInstallRule(
<< "\"" << this->Target->Target->GetName() << "\" "
<< "\"" << toDestDirPath << "\")\n";
}
+
+void cmInstallTargetGenerator::IssueCMP0095Warning(
+ const std::string& unescapedRpath)
+{
+ // Reduce warning noise to cases where used RPATHs may actually be affected
+ // by CMP0095. This filter is meant to skip warnings in cases when
+ // non-curly-braces syntax (e.g. $ORIGIN) or no keyword is used which has
+ // worked already before CMP0095. We intend to issue a warning in all cases
+ // with curly-braces syntax, even if the workaround of double-escaping is in
+ // place, since we deprecate the need for it with CMP0095.
+ const bool potentially_affected(unescapedRpath.find("${") !=
+ std::string::npos);
+
+ if (potentially_affected) {
+ std::ostringstream w;
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0095) << "\n";
+ w << "RPATH entries for target '" << this->Target->GetName() << "' "
+ << "will not be escaped in the intermediary "
+ << "cmake_install.cmake script.";
+ this->Target->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
+ MessageType::AUTHOR_WARNING, w.str(), this->GetBacktrace());
+ }
+}
diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h
index cf2de58f9..8730454b1 100644
--- a/Source/cmInstallTargetGenerator.h
+++ b/Source/cmInstallTargetGenerator.h
@@ -3,15 +3,16 @@
#ifndef cmInstallTargetGenerator_h
#define cmInstallTargetGenerator_h
-#include "cmConfigure.h"
-
-#include "cmInstallGenerator.h"
-#include "cmScriptGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
#include <vector>
+#include "cmInstallGenerator.h"
+#include "cmListFileCache.h"
+#include "cmScriptGenerator.h"
+
class cmGeneratorTarget;
class cmLocalGenerator;
@@ -21,12 +22,13 @@ class cmLocalGenerator;
class cmInstallTargetGenerator : public cmInstallGenerator
{
public:
- cmInstallTargetGenerator(std::string const& targetName, const char* dest,
- bool implib, const char* file_permissions,
- std::vector<std::string> const& configurations,
- const char* component, MessageLevel message,
- bool exclude_from_all, bool optional);
- ~cmInstallTargetGenerator() CM_OVERRIDE;
+ cmInstallTargetGenerator(
+ std::string targetName, const char* dest, bool implib,
+ const char* file_permissions,
+ std::vector<std::string> const& configurations, const char* component,
+ MessageLevel message, bool exclude_from_all, bool optional,
+ cmListFileBacktrace backtrace = cmListFileBacktrace());
+ ~cmInstallTargetGenerator() override;
/** Select the policy for installing shared library linkable name
symlinks. */
@@ -56,7 +58,7 @@ public:
const std::string& config,
NameType nameType = NameNormal);
- void Compute(cmLocalGenerator* lg) CM_OVERRIDE;
+ bool Compute(cmLocalGenerator* lg) override;
cmGeneratorTarget* GetTarget() const { return this->Target; }
@@ -64,16 +66,17 @@ public:
std::string GetDestination(std::string const& config) const;
+ cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; }
+
protected:
- void GenerateScript(std::ostream& os) CM_OVERRIDE;
void GenerateScriptForConfig(std::ostream& os, const std::string& config,
- Indent indent) CM_OVERRIDE;
+ Indent indent) override;
void GenerateScriptForConfigObjectLibrary(std::ostream& os,
const std::string& config,
Indent indent);
- typedef void (cmInstallTargetGenerator::*TweakMethod)(std::ostream&, Indent,
- const std::string&,
- std::string const&);
+ using TweakMethod = void (cmInstallTargetGenerator::*)(std::ostream&, Indent,
+ const std::string&,
+ const std::string&);
void AddTweak(std::ostream& os, Indent indent, const std::string& config,
std::string const& file, TweakMethod tweak);
void AddTweak(std::ostream& os, Indent indent, const std::string& config,
@@ -101,6 +104,7 @@ protected:
const std::string& toDestDirPath);
void AddUniversalInstallRule(std::ostream& os, Indent indent,
const std::string& toDestDirPath);
+ void IssueCMP0095Warning(const std::string& unescapedRpath);
std::string TargetName;
cmGeneratorTarget* Target;
@@ -108,6 +112,7 @@ protected:
NamelinkModeType NamelinkMode;
bool ImportLibrary;
bool Optional;
+ cmListFileBacktrace Backtrace;
};
#endif
diff --git a/Source/cmInstallTargetsCommand.cxx b/Source/cmInstallTargetsCommand.cxx
index e00eba012..44f23a581 100644
--- a/Source/cmInstallTargetsCommand.cxx
+++ b/Source/cmInstallTargetsCommand.cxx
@@ -2,57 +2,57 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallTargetsCommand.h"
+#include <unordered_map>
#include <utility>
+#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmTarget.h"
-#include "cm_unordered_map.hxx"
-class cmExecutionStatus;
-
-// cmExecutableCommand
-bool cmInstallTargetsCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmInstallTargetsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
+ cmMakefile& mf = status.GetMakefile();
+
// Enable the install target.
- this->Makefile->GetGlobalGenerator()->EnableInstallTarget();
+ mf.GetGlobalGenerator()->EnableInstallTarget();
- cmTargets& tgts = this->Makefile->GetTargets();
- std::vector<std::string>::const_iterator s = args.begin();
+ cmMakefile::cmTargetMap& tgts = mf.GetTargets();
+ auto s = args.begin();
++s;
std::string runtime_dir = "/bin";
for (; s != args.end(); ++s) {
if (*s == "RUNTIME_DIRECTORY") {
++s;
if (s == args.end()) {
- this->SetError("called with RUNTIME_DIRECTORY but no actual "
- "directory");
+ status.SetError("called with RUNTIME_DIRECTORY but no actual "
+ "directory");
return false;
}
runtime_dir = *s;
} else {
- cmTargets::iterator ti = tgts.find(*s);
+ auto ti = tgts.find(*s);
if (ti != tgts.end()) {
- ti->second.SetInstallPath(args[0].c_str());
- ti->second.SetRuntimeInstallPath(runtime_dir.c_str());
+ ti->second.SetInstallPath(args[0]);
+ ti->second.SetRuntimeInstallPath(runtime_dir);
ti->second.SetHaveInstallRule(true);
} else {
std::string str = "Cannot find target: \"" + *s + "\" to install.";
- this->SetError(str);
+ status.SetError(str);
return false;
}
}
}
- this->Makefile->GetGlobalGenerator()->AddInstallComponent(
- this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"));
+ mf.GetGlobalGenerator()->AddInstallComponent(
+ mf.GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"));
return true;
}
diff --git a/Source/cmInstallTargetsCommand.h b/Source/cmInstallTargetsCommand.h
index cc8484365..0c5850c91 100644
--- a/Source/cmInstallTargetsCommand.h
+++ b/Source/cmInstallTargetsCommand.h
@@ -3,36 +3,14 @@
#ifndef cmInstallTargetsCommand_h
#define cmInstallTargetsCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmInstallTargetsCommand
- * \brief Specifies where to install some targets
- *
- * cmInstallTargetsCommand specifies the relative path where a list of
- * targets should be installed. The targets can be executables or
- * libraries.
- */
-class cmInstallTargetsCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmInstallTargetsCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmInstallTargetsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx
index d51fd8d74..eabe5903b 100644
--- a/Source/cmInstalledFile.cxx
+++ b/Source/cmInstalledFile.cxx
@@ -2,29 +2,22 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstalledFile.h"
+#include <utility>
+
#include "cmAlgorithms.h"
+#include "cmGeneratorExpression.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
-#include "cmSystemTools.h"
+#include "cmStringAlgorithms.h"
-#include "cmConfigure.h"
-#include <utility>
-
-cmInstalledFile::cmInstalledFile()
- : NameExpression(CM_NULLPTR)
-{
-}
+cmInstalledFile::cmInstalledFile() = default;
cmInstalledFile::~cmInstalledFile()
{
- if (NameExpression) {
- delete NameExpression;
- }
+ delete NameExpression;
}
-cmInstalledFile::Property::Property()
-{
-}
+cmInstalledFile::Property::Property() = default;
cmInstalledFile::Property::~Property()
{
@@ -81,7 +74,7 @@ bool cmInstalledFile::HasProperty(const std::string& prop) const
bool cmInstalledFile::GetProperty(const std::string& prop,
std::string& value) const
{
- PropertyMapType::const_iterator i = this->Properties.find(prop);
+ auto i = this->Properties.find(prop);
if (i == this->Properties.end()) {
return false;
}
@@ -91,11 +84,9 @@ bool cmInstalledFile::GetProperty(const std::string& prop,
std::string output;
std::string separator;
- for (ExpressionVectorType::const_iterator j =
- property.ValueExpressions.begin();
- j != property.ValueExpressions.end(); ++j) {
+ for (auto ve : property.ValueExpressions) {
output += separator;
- output += (*j)->GetInput();
+ output += ve->GetInput();
separator = ";";
}
@@ -107,7 +98,7 @@ bool cmInstalledFile::GetPropertyAsBool(const std::string& prop) const
{
std::string value;
bool isSet = this->GetProperty(prop, value);
- return isSet && cmSystemTools::IsOn(value.c_str());
+ return isSet && cmIsOn(value);
}
void cmInstalledFile::GetPropertyAsList(const std::string& prop,
@@ -117,5 +108,5 @@ void cmInstalledFile::GetPropertyAsList(const std::string& prop,
this->GetProperty(prop, value);
list.clear();
- cmSystemTools::ExpandListArgument(value, list);
+ cmExpandList(value, list);
}
diff --git a/Source/cmInstalledFile.h b/Source/cmInstalledFile.h
index fbf754ffd..ee809ee79 100644
--- a/Source/cmInstalledFile.h
+++ b/Source/cmInstalledFile.h
@@ -5,13 +5,12 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmGeneratorExpression.h"
-#include "cm_auto_ptr.hxx"
-
#include <map>
+#include <memory>
#include <string>
#include <vector>
+class cmCompiledGeneratorExpression;
class cmMakefile;
/** \class cmInstalledFile
@@ -22,25 +21,31 @@ class cmMakefile;
class cmInstalledFile
{
public:
- typedef CM_AUTO_PTR<cmCompiledGeneratorExpression>
- CompiledGeneratorExpressionPtrType;
+ using CompiledGeneratorExpressionPtrType =
+ std::unique_ptr<cmCompiledGeneratorExpression>;
- typedef std::vector<cmCompiledGeneratorExpression*> ExpressionVectorType;
+ using ExpressionVectorType = std::vector<cmCompiledGeneratorExpression*>;
struct Property
{
Property();
~Property();
+ Property(const Property&) = delete;
+ Property& operator=(const Property&) = delete;
+
ExpressionVectorType ValueExpressions;
};
- typedef std::map<std::string, Property> PropertyMapType;
+ using PropertyMapType = std::map<std::string, Property>;
cmInstalledFile();
~cmInstalledFile();
+ cmInstalledFile(const cmInstalledFile&) = delete;
+ cmInstalledFile& operator=(const cmInstalledFile&) = delete;
+
void RemoveProperty(const std::string& prop);
void SetProperty(cmMakefile const* mf, const std::string& prop,
@@ -68,7 +73,7 @@ public:
private:
std::string Name;
- cmCompiledGeneratorExpression* NameExpression;
+ cmCompiledGeneratorExpression* NameExpression = nullptr;
PropertyMapType Properties;
};
diff --git a/Source/cmJsonObjectDictionary.h b/Source/cmJsonObjectDictionary.h
new file mode 100644
index 000000000..8a2b52995
--- /dev/null
+++ b/Source/cmJsonObjectDictionary.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. */
+#pragma once
+
+#include <string>
+
+// Vocabulary:
+
+static const std::string kARTIFACTS_KEY = "artifacts";
+static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory";
+static const std::string kCOMPILE_FLAGS_KEY = "compileFlags";
+static const std::string kCONFIGURATIONS_KEY = "configurations";
+static const std::string kDEFINES_KEY = "defines";
+static const std::string kFILE_GROUPS_KEY = "fileGroups";
+static const std::string kFRAMEWORK_PATH_KEY = "frameworkPath";
+static const std::string kFULL_NAME_KEY = "fullName";
+static const std::string kINCLUDE_PATH_KEY = "includePath";
+static const std::string kIS_CMAKE_KEY = "isCMake";
+static const std::string kIS_GENERATED_KEY = "isGenerated";
+static const std::string kIS_SYSTEM_KEY = "isSystem";
+static const std::string kIS_TEMPORARY_KEY = "isTemporary";
+static const std::string kKEY_KEY = "key";
+static const std::string kLANGUAGE_KEY = "language";
+static const std::string kLINKER_LANGUAGE_KEY = "linkerLanguage";
+static const std::string kLINK_FLAGS_KEY = "linkFlags";
+static const std::string kLINK_LANGUAGE_FLAGS_KEY = "linkLanguageFlags";
+static const std::string kLINK_LIBRARIES_KEY = "linkLibraries";
+static const std::string kLINK_PATH_KEY = "linkPath";
+static const std::string kNAME_KEY = "name";
+static const std::string kPATH_KEY = "path";
+static const std::string kPROJECTS_KEY = "projects";
+static const std::string kPROPERTIES_KEY = "properties";
+static const std::string kSOURCE_DIRECTORY_KEY = "sourceDirectory";
+static const std::string kSOURCES_KEY = "sources";
+static const std::string kSYSROOT_KEY = "sysroot";
+static const std::string kTARGETS_KEY = "targets";
+static const std::string kTYPE_KEY = "type";
+static const std::string kVALUE_KEY = "value";
+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";
diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx
new file mode 100644
index 000000000..b23ab43d8
--- /dev/null
+++ b/Source/cmJsonObjects.cxx
@@ -0,0 +1,692 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmJsonObjects.h" // IWYU pragma: keep
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <functional>
+#include <limits>
+#include <map>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include "cmAlgorithms.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstallGenerator.h"
+#include "cmInstallSubdirectoryGenerator.h"
+#include "cmInstallTargetGenerator.h"
+#include "cmJsonObjectDictionary.h"
+#include "cmJsonObjects.h"
+#include "cmLinkLineComputer.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmPropertyMap.h"
+#include "cmSourceFile.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmTest.h"
+#include "cmake.h"
+
+namespace {
+
+std::vector<std::string> getConfigurations(const cmake* cm)
+{
+ std::vector<std::string> configurations;
+ auto makefiles = cm->GetGlobalGenerator()->GetMakefiles();
+ if (makefiles.empty()) {
+ return configurations;
+ }
+
+ makefiles[0]->GetConfigurations(configurations);
+ if (configurations.empty()) {
+ configurations.emplace_back();
+ }
+ return configurations;
+}
+
+bool hasString(const Json::Value& v, const std::string& s)
+{
+ return !v.isNull() &&
+ std::any_of(v.begin(), v.end(),
+ [s](const Json::Value& i) { return i.asString() == s; });
+}
+
+template <class T>
+Json::Value fromStringList(const T& in)
+{
+ Json::Value result = Json::arrayValue;
+ for (std::string const& i : in) {
+ result.append(i);
+ }
+ return result;
+}
+
+} // namespace
+
+void cmGetCMakeInputs(const cmGlobalGenerator* gg,
+ const std::string& sourceDir,
+ const std::string& buildDir,
+ std::vector<std::string>* internalFiles,
+ std::vector<std::string>* explicitFiles,
+ std::vector<std::string>* tmpFiles)
+{
+ const std::string cmakeRootDir = cmSystemTools::GetCMakeRoot() + '/';
+ std::vector<cmMakefile*> const& makefiles = gg->GetMakefiles();
+ for (cmMakefile const* mf : makefiles) {
+ for (std::string const& lf : mf->GetListFiles()) {
+
+ const std::string startOfFile = lf.substr(0, cmakeRootDir.size());
+ const bool isInternal = (startOfFile == cmakeRootDir);
+ const bool isTemporary = !isInternal && (lf.find(buildDir + '/') == 0);
+
+ std::string toAdd = lf;
+ if (!sourceDir.empty()) {
+ const std::string& relative =
+ cmSystemTools::RelativePath(sourceDir, lf);
+ if (toAdd.size() > relative.size()) {
+ toAdd = relative;
+ }
+ }
+
+ if (isInternal) {
+ if (internalFiles) {
+ internalFiles->push_back(std::move(toAdd));
+ }
+ } else {
+ if (isTemporary) {
+ if (tmpFiles) {
+ tmpFiles->push_back(std::move(toAdd));
+ }
+ } else {
+ if (explicitFiles) {
+ explicitFiles->push_back(std::move(toAdd));
+ }
+ }
+ }
+ }
+ }
+}
+
+Json::Value cmDumpCMakeInputs(const cmake* cm)
+{
+ const cmGlobalGenerator* gg = cm->GetGlobalGenerator();
+ const std::string& buildDir = cm->GetHomeOutputDirectory();
+ const std::string& sourceDir = cm->GetHomeDirectory();
+
+ std::vector<std::string> internalFiles;
+ std::vector<std::string> explicitFiles;
+ std::vector<std::string> tmpFiles;
+ cmGetCMakeInputs(gg, sourceDir, buildDir, &internalFiles, &explicitFiles,
+ &tmpFiles);
+
+ Json::Value array = Json::arrayValue;
+
+ Json::Value tmp = Json::objectValue;
+ tmp[kIS_CMAKE_KEY] = true;
+ tmp[kIS_TEMPORARY_KEY] = false;
+ tmp[kSOURCES_KEY] = fromStringList(internalFiles);
+ array.append(tmp);
+
+ tmp = Json::objectValue;
+ tmp[kIS_CMAKE_KEY] = false;
+ tmp[kIS_TEMPORARY_KEY] = false;
+ tmp[kSOURCES_KEY] = fromStringList(explicitFiles);
+ array.append(tmp);
+
+ tmp = Json::objectValue;
+ tmp[kIS_CMAKE_KEY] = false;
+ tmp[kIS_TEMPORARY_KEY] = true;
+ tmp[kSOURCES_KEY] = fromStringList(tmpFiles);
+ array.append(tmp);
+
+ return array;
+}
+
+class LanguageData
+{
+public:
+ bool operator==(const LanguageData& other) const;
+
+ void SetDefines(const std::set<std::string>& defines);
+
+ bool IsGenerated = false;
+ std::string Language;
+ std::string Flags;
+ std::vector<std::string> Defines;
+ std::vector<std::pair<std::string, bool>> IncludePathList;
+};
+
+bool LanguageData::operator==(const LanguageData& other) const
+{
+ return Language == other.Language && Defines == other.Defines &&
+ Flags == other.Flags && IncludePathList == other.IncludePathList &&
+ IsGenerated == other.IsGenerated;
+}
+
+void LanguageData::SetDefines(const std::set<std::string>& defines)
+{
+ std::vector<std::string> result;
+ result.reserve(defines.size());
+ for (std::string const& i : defines) {
+ result.push_back(i);
+ }
+ std::sort(result.begin(), result.end());
+ Defines = std::move(result);
+}
+
+namespace std {
+
+template <>
+struct hash<LanguageData>
+{
+ std::size_t operator()(const LanguageData& in) const
+ {
+ using std::hash;
+ size_t result =
+ hash<std::string>()(in.Language) ^ hash<std::string>()(in.Flags);
+ for (auto const& i : in.IncludePathList) {
+ result = result ^
+ (hash<std::string>()(i.first) ^
+ (i.second ? std::numeric_limits<size_t>::max() : 0));
+ }
+ for (auto const& i : in.Defines) {
+ result = result ^ hash<std::string>()(i);
+ }
+ result =
+ result ^ (in.IsGenerated ? std::numeric_limits<size_t>::max() : 0);
+ return result;
+ }
+};
+
+} // namespace std
+
+static Json::Value DumpSourceFileGroup(const LanguageData& data,
+ const std::vector<std::string>& files,
+ const std::string& baseDir)
+{
+ Json::Value result = Json::objectValue;
+
+ if (!data.Language.empty()) {
+ result[kLANGUAGE_KEY] = data.Language;
+ if (!data.Flags.empty()) {
+ result[kCOMPILE_FLAGS_KEY] = data.Flags;
+ }
+ if (!data.IncludePathList.empty()) {
+ Json::Value includes = Json::arrayValue;
+ for (auto const& i : data.IncludePathList) {
+ Json::Value tmp = Json::objectValue;
+ tmp[kPATH_KEY] = i.first;
+ if (i.second) {
+ tmp[kIS_SYSTEM_KEY] = i.second;
+ }
+ includes.append(tmp);
+ }
+ result[kINCLUDE_PATH_KEY] = includes;
+ }
+ if (!data.Defines.empty()) {
+ result[kDEFINES_KEY] = fromStringList(data.Defines);
+ }
+ }
+
+ result[kIS_GENERATED_KEY] = data.IsGenerated;
+
+ Json::Value sourcesValue = Json::arrayValue;
+ for (auto const& i : files) {
+ const std::string relPath = cmSystemTools::RelativePath(baseDir, i);
+ sourcesValue.append(relPath.size() < i.size() ? relPath : i);
+ }
+
+ result[kSOURCES_KEY] = sourcesValue;
+ return result;
+}
+
+static Json::Value DumpSourceFilesList(
+ cmGeneratorTarget* target, const std::string& config,
+ const std::map<std::string, LanguageData>& languageDataMap)
+{
+ // Collect sourcefile groups:
+
+ std::vector<cmSourceFile*> files;
+ target->GetSourceFiles(files, config);
+
+ std::unordered_map<LanguageData, std::vector<std::string>> fileGroups;
+ for (cmSourceFile* file : files) {
+ LanguageData fileData;
+ fileData.Language = file->GetOrDetermineLanguage();
+ if (!fileData.Language.empty()) {
+ const LanguageData& ld = languageDataMap.at(fileData.Language);
+ cmLocalGenerator* lg = target->GetLocalGenerator();
+ cmGeneratorExpressionInterpreter genexInterpreter(lg, config, target,
+ fileData.Language);
+
+ std::string compileFlags = ld.Flags;
+ 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;
+
+ // 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 std::string& evaluatedIncludes =
+ genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES);
+ lg->AppendIncludeDirectories(includes, evaluatedIncludes, *file);
+
+ for (const auto& include : includes) {
+ fileData.IncludePathList.emplace_back(
+ 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;
+ 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);
+ 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);
+ }
+
+ fileData.IsGenerated = file->GetIsGenerated();
+ std::vector<std::string>& groupFileList = fileGroups[fileData];
+ groupFileList.push_back(file->ResolveFullPath());
+ }
+
+ const std::string& baseDir = target->Makefile->GetCurrentSourceDirectory();
+ Json::Value result = Json::arrayValue;
+ for (auto const& it : fileGroups) {
+ Json::Value group = DumpSourceFileGroup(it.first, it.second, baseDir);
+ if (!group.isNull()) {
+ result.append(group);
+ }
+ }
+
+ 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.
+ result[kCTEST_COMMAND] =
+ cmGeneratorExpression::Evaluate(command, lg, config);
+
+ // Build up the list of properties that may have been specified
+ Json::Value properties = Json::arrayValue;
+ for (auto& prop : testInfo->GetProperties().GetList()) {
+ Json::Value entry = Json::objectValue;
+ entry[kKEY_KEY] = prop.first;
+
+ // Remove config variables from the value too.
+ entry[kVALUE_KEY] =
+ cmGeneratorExpression::Evaluate(prop.second, lg, config);
+ 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;
+}
+
+Json::Value cmDumpCTestInfo(const cmake* cm)
+{
+ Json::Value result = Json::objectValue;
+ result[kCONFIGURATIONS_KEY] = DumpCTestConfigurationsList(cm);
+ return result;
+}
+
+static Json::Value DumpTarget(cmGeneratorTarget* target,
+ const std::string& config)
+{
+ cmLocalGenerator* lg = target->GetLocalGenerator();
+
+ const cmStateEnums::TargetType type = target->GetType();
+ const std::string typeName = cmState::GetTargetTypeName(type);
+
+ Json::Value ttl = Json::arrayValue;
+ ttl.append("EXECUTABLE");
+ ttl.append("STATIC_LIBRARY");
+ ttl.append("SHARED_LIBRARY");
+ ttl.append("MODULE_LIBRARY");
+ ttl.append("OBJECT_LIBRARY");
+ ttl.append("UTILITY");
+ ttl.append("INTERFACE_LIBRARY");
+
+ if (!hasString(ttl, typeName) || target->IsImported()) {
+ return Json::Value();
+ }
+
+ 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();
+
+ if (type == cmStateEnums::INTERFACE_LIBRARY) {
+ return result;
+ }
+
+ 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 {
+ installPath = cmStrCat(
+ target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"), '/',
+ dest);
+ }
+
+ installPaths.append(installPath);
+ }
+ }
+
+ result[kINSTALL_PATHS] = installPaths;
+ }
+
+ if (target->HaveWellDefinedOutputFiles()) {
+ Json::Value artifacts = Json::arrayValue;
+ artifacts.append(
+ target->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact));
+ if (target->HasImportLibrary(config)) {
+ artifacts.append(
+ target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact));
+ }
+ if (target->IsDLLPlatform()) {
+ const cmGeneratorTarget::OutputInfo* output =
+ target->GetOutputInfo(config);
+ if (output && !output->PdbDir.empty()) {
+ artifacts.append(output->PdbDir + '/' + target->GetPDBName(config));
+ }
+ }
+ result[kARTIFACTS_KEY] = artifacts;
+
+ result[kLINKER_LANGUAGE_KEY] = target->GetLinkerLanguage(config);
+
+ std::string linkLibs;
+ std::string linkFlags;
+ std::string linkLanguageFlags;
+ std::string frameworkPath;
+ std::string linkPath;
+ cmLinkLineComputer linkLineComputer(lg,
+ lg->GetStateSnapshot().GetDirectory());
+ lg->GetTargetFlags(&linkLineComputer, config, linkLibs, linkLanguageFlags,
+ linkFlags, frameworkPath, linkPath, target);
+
+ linkLibs = cmTrimWhitespace(linkLibs);
+ linkFlags = cmTrimWhitespace(linkFlags);
+ linkLanguageFlags = cmTrimWhitespace(linkLanguageFlags);
+ frameworkPath = cmTrimWhitespace(frameworkPath);
+ linkPath = cmTrimWhitespace(linkPath);
+
+ if (!cmTrimWhitespace(linkLibs).empty()) {
+ result[kLINK_LIBRARIES_KEY] = linkLibs;
+ }
+ if (!cmTrimWhitespace(linkFlags).empty()) {
+ result[kLINK_FLAGS_KEY] = linkFlags;
+ }
+ if (!cmTrimWhitespace(linkLanguageFlags).empty()) {
+ result[kLINK_LANGUAGE_FLAGS_KEY] = linkLanguageFlags;
+ }
+ if (!frameworkPath.empty()) {
+ result[kFRAMEWORK_PATH_KEY] = frameworkPath;
+ }
+ if (!linkPath.empty()) {
+ result[kLINK_PATH_KEY] = linkPath;
+ }
+ const std::string sysroot =
+ lg->GetMakefile()->GetSafeDefinition("CMAKE_SYSROOT");
+ if (!sysroot.empty()) {
+ result[kSYSROOT_KEY] = sysroot;
+ }
+ }
+
+ std::set<std::string> languages;
+ target->GetLanguages(languages, config);
+ std::map<std::string, LanguageData> languageDataMap;
+
+ for (std::string const& lang : languages) {
+ LanguageData& ld = languageDataMap[lang];
+ ld.Language = lang;
+ lg->GetTargetCompileFlags(target, config, lang, ld.Flags);
+ std::set<std::string> defines;
+ lg->GetTargetDefines(target, config, lang, defines);
+ ld.SetDefines(defines);
+ std::vector<std::string> includePathList;
+ lg->GetIncludeDirectories(includePathList, target, lang, config);
+ for (std::string const& i : includePathList) {
+ ld.IncludePathList.emplace_back(
+ i, target->IsSystemIncludeDirectory(i, config, lang));
+ }
+ }
+
+ Json::Value sourceGroupsValue =
+ DumpSourceFilesList(target, config, languageDataMap);
+ if (!sourceGroupsValue.empty()) {
+ result[kFILE_GROUPS_KEY] = sourceGroupsValue;
+ }
+
+ return result;
+}
+
+static Json::Value DumpTargetsList(
+ const std::vector<cmLocalGenerator*>& generators, const std::string& config)
+{
+ Json::Value result = Json::arrayValue;
+
+ std::vector<cmGeneratorTarget*> targetList;
+ for (auto const& lgIt : generators) {
+ cmAppend(targetList, lgIt->GetGeneratorTargets());
+ }
+ std::sort(targetList.begin(), targetList.end());
+
+ for (cmGeneratorTarget* target : targetList) {
+ Json::Value tmp = DumpTarget(target, config);
+ if (!tmp.isNull()) {
+ result.append(tmp);
+ }
+ }
+
+ return result;
+}
+
+static Json::Value DumpProjectList(const cmake* cm, std::string const& config)
+{
+ Json::Value result = Json::arrayValue;
+
+ auto globalGen = cm->GetGlobalGenerator();
+
+ for (auto const& projectIt : globalGen->GetProjectMap()) {
+ Json::Value pObj = Json::objectValue;
+ pObj[kNAME_KEY] = projectIt.first;
+
+ // All Projects must have at least one local generator
+ assert(!projectIt.second.empty());
+ const cmLocalGenerator* lg = projectIt.second.at(0);
+
+ // 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) {
+ for (const auto installGen :
+ generator->GetMakefile()->GetInstallGenerators()) {
+ if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(installGen)) {
+ hasInstallRule = true;
+ break;
+ }
+ }
+
+ if (hasInstallRule) {
+ break;
+ }
+ }
+
+ pObj[kHAS_INSTALL_RULE] = hasInstallRule;
+
+ result.append(pObj);
+ }
+
+ return result;
+}
+
+static Json::Value DumpConfiguration(const cmake* cm,
+ const std::string& config)
+{
+ Json::Value result = Json::objectValue;
+ result[kNAME_KEY] = config;
+
+ result[kPROJECTS_KEY] = DumpProjectList(cm, config);
+
+ return result;
+}
+
+static Json::Value DumpConfigurationsList(const cmake* cm)
+{
+ Json::Value result = Json::arrayValue;
+
+ for (std::string const& c : getConfigurations(cm)) {
+ result.append(DumpConfiguration(cm, c));
+ }
+
+ return result;
+}
+
+Json::Value cmDumpCodeModel(const cmake* cm)
+{
+ Json::Value result = Json::objectValue;
+ result[kCONFIGURATIONS_KEY] = DumpConfigurationsList(cm);
+ return result;
+}
diff --git a/Source/cmJsonObjects.h b/Source/cmJsonObjects.h
new file mode 100644
index 000000000..64291cc06
--- /dev/null
+++ b/Source/cmJsonObjects.h
@@ -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. */
+#ifndef cmJsonObjects_h
+#define cmJsonObjects_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+#include "cm_jsoncpp_value.h"
+
+class cmake;
+class cmGlobalGenerator;
+
+extern void cmGetCMakeInputs(const cmGlobalGenerator* gg,
+ const std::string& sourceDir,
+ const std::string& buildDir,
+ std::vector<std::string>* internalFiles,
+ std::vector<std::string>* explicitFiles,
+ std::vector<std::string>* tmpFiles);
+
+extern Json::Value cmDumpCodeModel(const cmake* cm);
+extern Json::Value cmDumpCTestInfo(const cmake* cm);
+extern Json::Value cmDumpCMakeInputs(const cmake* cm);
+
+#endif
diff --git a/Source/cmLDConfigLDConfigTool.cxx b/Source/cmLDConfigLDConfigTool.cxx
new file mode 100644
index 000000000..cce6178da
--- /dev/null
+++ b/Source/cmLDConfigLDConfigTool.cxx
@@ -0,0 +1,71 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmLDConfigLDConfigTool.h"
+
+#include <istream>
+#include <string>
+#include <vector>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmMakefile.h"
+#include "cmRuntimeDependencyArchive.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmUVProcessChain.h"
+
+cmLDConfigLDConfigTool::cmLDConfigLDConfigTool(
+ cmRuntimeDependencyArchive* archive)
+ : cmLDConfigTool(archive)
+{
+}
+
+bool cmLDConfigLDConfigTool::GetLDConfigPaths(std::vector<std::string>& paths)
+{
+ std::string ldConfigPath =
+ this->Archive->GetMakefile()->GetSafeDefinition("CMAKE_LDCONFIG_COMMAND");
+ if (ldConfigPath.empty()) {
+ ldConfigPath = cmSystemTools::FindProgram(
+ "ldconfig", { "/sbin", "/usr/sbin", "/usr/local/sbin" });
+ if (ldConfigPath.empty()) {
+ this->Archive->SetError("Could not find ldconfig");
+ return false;
+ }
+ }
+
+ std::vector<std::string> ldConfigCommand = cmExpandedList(ldConfigPath);
+ ldConfigCommand.emplace_back("-v");
+ ldConfigCommand.emplace_back("-N"); // Don't rebuild the cache.
+ ldConfigCommand.emplace_back("-X"); // Don't update links.
+
+ cmUVProcessChainBuilder builder;
+ builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
+ .AddCommand(ldConfigCommand);
+ auto process = builder.Start();
+ if (!process.Valid()) {
+ this->Archive->SetError("Failed to start ldconfig process");
+ return false;
+ }
+
+ std::string line;
+ static const cmsys::RegularExpression regex("^([^\t:]*):");
+ while (std::getline(*process.OutputStream(), line)) {
+ cmsys::RegularExpressionMatch match;
+ if (regex.find(line.c_str(), match)) {
+ paths.push_back(match.match(1));
+ }
+ }
+
+ if (!process.Wait()) {
+ this->Archive->SetError("Failed to wait on ldconfig process");
+ return false;
+ }
+ auto status = process.GetStatus();
+ if (!status[0] || status[0]->ExitStatus != 0) {
+ this->Archive->SetError("Failed to run ldconfig");
+ return false;
+ }
+
+ return true;
+}
diff --git a/Source/cmLDConfigLDConfigTool.h b/Source/cmLDConfigLDConfigTool.h
new file mode 100644
index 000000000..34bf6c61f
--- /dev/null
+++ b/Source/cmLDConfigLDConfigTool.h
@@ -0,0 +1,22 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmLDConfigLDConfigTool_h
+#define cmLDConfigLDConfigTool_h
+
+#include <string>
+#include <vector>
+
+#include "cmLDConfigTool.h"
+
+class cmRuntimeDependencyArchive;
+
+class cmLDConfigLDConfigTool : public cmLDConfigTool
+{
+public:
+ cmLDConfigLDConfigTool(cmRuntimeDependencyArchive* archive);
+
+ bool GetLDConfigPaths(std::vector<std::string>& paths) override;
+};
+
+#endif
diff --git a/Source/cmLDConfigTool.cxx b/Source/cmLDConfigTool.cxx
new file mode 100644
index 000000000..8d5d5630b
--- /dev/null
+++ b/Source/cmLDConfigTool.cxx
@@ -0,0 +1,9 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmLDConfigTool.h"
+
+cmLDConfigTool::cmLDConfigTool(cmRuntimeDependencyArchive* archive)
+ : Archive(archive)
+{
+}
diff --git a/Source/cmLDConfigTool.h b/Source/cmLDConfigTool.h
new file mode 100644
index 000000000..c816562d4
--- /dev/null
+++ b/Source/cmLDConfigTool.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. */
+
+#ifndef cmLDConfigTool_h
+#define cmLDConfigTool_h
+
+#include <string>
+#include <vector>
+
+class cmRuntimeDependencyArchive;
+
+class cmLDConfigTool
+{
+public:
+ cmLDConfigTool(cmRuntimeDependencyArchive* archive);
+ virtual ~cmLDConfigTool() = default;
+
+ virtual bool GetLDConfigPaths(std::vector<std::string>& paths) = 0;
+
+protected:
+ cmRuntimeDependencyArchive* Archive;
+};
+
+#endif
diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx
index 9b0c28817..29140462a 100644
--- a/Source/cmLinkDirectoriesCommand.cxx
+++ b/Source/cmLinkDirectoriesCommand.cxx
@@ -4,33 +4,53 @@
#include <sstream>
+#include "cmExecutionStatus.h"
+#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmake.h"
-class cmExecutionStatus;
+static void AddLinkDir(cmMakefile& mf, std::string const& dir,
+ std::vector<std::string>& directories);
-// cmLinkDirectoriesCommand
-bool cmLinkDirectoriesCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmLinkDirectoriesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
return true;
}
- for (std::vector<std::string>::const_iterator i = args.begin();
- i != args.end(); ++i) {
- this->AddLinkDir(*i);
+ cmMakefile& mf = status.GetMakefile();
+ bool before = mf.IsOn("CMAKE_LINK_DIRECTORIES_BEFORE");
+
+ auto i = args.cbegin();
+ if ((*i) == "BEFORE") {
+ before = true;
+ ++i;
+ } else if ((*i) == "AFTER") {
+ before = false;
+ ++i;
+ }
+
+ std::vector<std::string> directories;
+ for (; i != args.cend(); ++i) {
+ AddLinkDir(mf, *i, directories);
}
+
+ mf.AddLinkDirectory(cmJoin(directories, ";"), before);
+
return true;
}
-void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir)
+static void AddLinkDir(cmMakefile& mf, std::string const& dir,
+ std::vector<std::string>& directories)
{
std::string unixPath = dir;
cmSystemTools::ConvertToUnixSlashes(unixPath);
- if (!cmSystemTools::FileIsFullPath(unixPath.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(unixPath) &&
+ !cmGeneratorExpression::StartsWithGeneratorExpression(unixPath)) {
bool convertToAbsolute = false;
std::ostringstream e;
/* clang-format off */
@@ -38,17 +58,18 @@ void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir)
<< " " << unixPath << "\n"
<< "as a link directory.\n";
/* clang-format on */
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0015)) {
+ switch (mf.GetPolicyStatus(cmPolicies::CMP0015)) {
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0015);
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ mf.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
+ break;
case cmPolicies::OLD:
// OLD behavior does not convert
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0015);
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf.IssueMessage(MessageType::FATAL_ERROR, e.str());
CM_FALLTHROUGH;
case cmPolicies::NEW:
// NEW behavior converts
@@ -56,11 +77,8 @@ void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir)
break;
}
if (convertToAbsolute) {
- std::string tmp = this->Makefile->GetCurrentSourceDirectory();
- tmp += "/";
- tmp += unixPath;
- unixPath = tmp;
+ unixPath = cmStrCat(mf.GetCurrentSourceDirectory(), '/', unixPath);
}
}
- this->Makefile->AppendProperty("LINK_DIRECTORIES", unixPath.c_str());
+ directories.push_back(unixPath);
}
diff --git a/Source/cmLinkDirectoriesCommand.h b/Source/cmLinkDirectoriesCommand.h
index b64e48d70..a7caa5c63 100644
--- a/Source/cmLinkDirectoriesCommand.h
+++ b/Source/cmLinkDirectoriesCommand.h
@@ -3,40 +3,14 @@
#ifndef cmLinkDirectoriesCommand_h
#define cmLinkDirectoriesCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmLinkDirectoriesCommand
- * \brief Define a list of directories containing files to link.
- *
- * cmLinkDirectoriesCommand is used to specify a list
- * of directories containing files to link into executable(s).
- * Note that the command supports the use of CMake built-in variables
- * such as CMAKE_BINARY_DIR and CMAKE_SOURCE_DIR.
- */
-class cmLinkDirectoriesCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmLinkDirectoriesCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- void AddLinkDir(std::string const& dir);
-};
+bool cmLinkDirectoriesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmLinkItem.cxx b/Source/cmLinkItem.cxx
new file mode 100644
index 000000000..91eb18337
--- /dev/null
+++ b/Source/cmLinkItem.cxx
@@ -0,0 +1,64 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmLinkItem.h"
+
+#include <utility> // IWYU pragma: keep
+
+#include "cmGeneratorTarget.h"
+
+cmLinkItem::cmLinkItem() = default;
+
+cmLinkItem::cmLinkItem(std::string n, cmListFileBacktrace bt)
+ : String(std::move(n))
+ , Backtrace(std::move(bt))
+{
+}
+
+cmLinkItem::cmLinkItem(cmGeneratorTarget const* t, cmListFileBacktrace bt)
+ : Target(t)
+ , Backtrace(std::move(bt))
+{
+}
+
+std::string const& cmLinkItem::AsStr() const
+{
+ return this->Target ? this->Target->GetName() : this->String;
+}
+
+bool operator<(cmLinkItem const& l, cmLinkItem const& r)
+{
+ // Order among targets.
+ if (l.Target && r.Target) {
+ return l.Target < r.Target;
+ }
+ // Order targets before strings.
+ if (l.Target) {
+ return true;
+ }
+ if (r.Target) {
+ return false;
+ }
+ // Order among strings.
+ return l.String < r.String;
+}
+
+bool operator==(cmLinkItem const& l, cmLinkItem const& r)
+{
+ return l.Target == r.Target && l.String == r.String;
+}
+
+std::ostream& operator<<(std::ostream& os, cmLinkItem const& item)
+{
+ return os << item.AsStr();
+}
+
+cmLinkImplItem::cmLinkImplItem()
+ : cmLinkItem()
+{
+}
+
+cmLinkImplItem::cmLinkImplItem(cmLinkItem item, bool fromGenex)
+ : cmLinkItem(std::move(item))
+ , FromGenex(fromGenex)
+{
+}
diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h
index f0fded21f..2d9378bd5 100644
--- a/Source/cmLinkItem.h
+++ b/Source/cmLinkItem.h
@@ -3,13 +3,14 @@
#ifndef cmLinkItem_h
#define cmLinkItem_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include <algorithm>
#include <map>
+#include <ostream>
#include <string>
#include <vector>
+#include "cmAlgorithms.h"
#include "cmListFileCache.h"
#include "cmSystemTools.h"
#include "cmTargetLinkLibraryType.h"
@@ -17,42 +18,28 @@
class cmGeneratorTarget;
// Basic information about each link item.
-class cmLinkItem : public std::string
+class cmLinkItem
{
- typedef std::string std_string;
+ std::string String;
public:
- cmLinkItem()
- : std_string()
- , Target(CM_NULLPTR)
- {
- }
- cmLinkItem(const std_string& n, cmGeneratorTarget const* t)
- : std_string(n)
- , Target(t)
- {
- }
- cmGeneratorTarget const* Target;
+ cmLinkItem();
+ cmLinkItem(std::string s, cmListFileBacktrace bt);
+ cmLinkItem(cmGeneratorTarget const* t, cmListFileBacktrace bt);
+ std::string const& AsStr() const;
+ cmGeneratorTarget const* Target = nullptr;
+ cmListFileBacktrace Backtrace;
+ friend bool operator<(cmLinkItem const& l, cmLinkItem const& r);
+ friend bool operator==(cmLinkItem const& l, cmLinkItem const& r);
+ friend std::ostream& operator<<(std::ostream& os, cmLinkItem const& item);
};
class cmLinkImplItem : public cmLinkItem
{
public:
- cmLinkImplItem()
- : cmLinkItem()
- , Backtrace()
- , FromGenex(false)
- {
- }
- cmLinkImplItem(std::string const& n, cmGeneratorTarget const* t,
- cmListFileBacktrace const& bt, bool fromGenex)
- : cmLinkItem(n, t)
- , Backtrace(bt)
- , FromGenex(fromGenex)
- {
- }
- cmListFileBacktrace Backtrace;
- bool FromGenex;
+ cmLinkImplItem();
+ cmLinkImplItem(cmLinkItem item, bool fromGenex);
+ bool FromGenex = false;
};
/** The link implementation specifies the direct library
@@ -71,6 +58,9 @@ struct cmLinkInterfaceLibraries
{
// Libraries listed in the interface.
std::vector<cmLinkItem> Libraries;
+
+ // Whether the list depends on a genex referencing the head target.
+ bool HadHeadSensitiveCondition = false;
};
struct cmLinkInterface : public cmLinkInterfaceLibraries
@@ -83,36 +73,21 @@ struct cmLinkInterface : public cmLinkInterfaceLibraries
// Number of repetitions of a strongly connected component of two
// or more static libraries.
- unsigned int Multiplicity;
+ unsigned int Multiplicity = 0;
// Libraries listed for other configurations.
// Needed only for OLD behavior of CMP0003.
std::vector<cmLinkItem> WrongConfigLibraries;
- bool ImplementationIsInterface;
-
- cmLinkInterface()
- : Multiplicity(0)
- , ImplementationIsInterface(false)
- {
- }
+ bool ImplementationIsInterface = false;
};
struct cmOptionalLinkInterface : public cmLinkInterface
{
- cmOptionalLinkInterface()
- : LibrariesDone(false)
- , AllDone(false)
- , Exists(false)
- , HadHeadSensitiveCondition(false)
- , ExplicitLibraries(CM_NULLPTR)
- {
- }
- bool LibrariesDone;
- bool AllDone;
- bool Exists;
- bool HadHeadSensitiveCondition;
- const char* ExplicitLibraries;
+ bool LibrariesDone = false;
+ bool AllDone = false;
+ bool Exists = false;
+ bool Explicit = false;
};
struct cmHeadToLinkInterfaceMap
@@ -129,15 +104,9 @@ struct cmLinkImplementation : public cmLinkImplementationLibraries
// Cache link implementation computation from each configuration.
struct cmOptionalLinkImplementation : public cmLinkImplementation
{
- cmOptionalLinkImplementation()
- : LibrariesDone(false)
- , LanguagesDone(false)
- , HadHeadSensitiveCondition(false)
- {
- }
- bool LibrariesDone;
- bool LanguagesDone;
- bool HadHeadSensitiveCondition;
+ bool LibrariesDone = false;
+ bool LanguagesDone = false;
+ bool HadHeadSensitiveCondition = false;
};
/** Compute the link type to use for the given configuration. */
@@ -151,8 +120,7 @@ inline cmTargetLinkLibraryType CMP0003_ComputeLinkType(
// Check if any entry in the list matches this configuration.
std::string configUpper = cmSystemTools::UpperCase(config);
- if (std::find(debugConfigs.begin(), debugConfigs.end(), configUpper) !=
- debugConfigs.end()) {
+ if (cmContains(debugConfigs, configUpper)) {
return DEBUG_LibraryType;
}
// The current configuration is not a debug configuration.
diff --git a/Source/cmLinkLibrariesCommand.cxx b/Source/cmLinkLibrariesCommand.cxx
index 708ec8c00..cb63ceb03 100644
--- a/Source/cmLinkLibrariesCommand.cxx
+++ b/Source/cmLinkLibrariesCommand.cxx
@@ -2,39 +2,37 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLinkLibrariesCommand.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-class cmExecutionStatus;
-
-// cmLinkLibrariesCommand
-bool cmLinkLibrariesCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmLinkLibrariesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
return true;
}
- // add libraries, nothe that there is an optional prefix
+ cmMakefile& mf = status.GetMakefile();
+ // add libraries, note that there is an optional prefix
// of debug and optimized than can be used
- for (std::vector<std::string>::const_iterator i = args.begin();
- i != args.end(); ++i) {
+ for (auto i = args.begin(); i != args.end(); ++i) {
if (*i == "debug") {
++i;
if (i == args.end()) {
- this->SetError("The \"debug\" argument must be followed by "
- "a library");
+ status.SetError("The \"debug\" argument must be followed by "
+ "a library");
return false;
}
- this->Makefile->AppendProperty("LINK_LIBRARIES", "debug");
+ mf.AppendProperty("LINK_LIBRARIES", "debug");
} else if (*i == "optimized") {
++i;
if (i == args.end()) {
- this->SetError("The \"optimized\" argument must be followed by "
- "a library");
+ status.SetError("The \"optimized\" argument must be followed by "
+ "a library");
return false;
}
- this->Makefile->AppendProperty("LINK_LIBRARIES", "optimized");
+ mf.AppendProperty("LINK_LIBRARIES", "optimized");
}
- this->Makefile->AppendProperty("LINK_LIBRARIES", i->c_str());
+ mf.AppendProperty("LINK_LIBRARIES", i->c_str());
}
return true;
diff --git a/Source/cmLinkLibrariesCommand.h b/Source/cmLinkLibrariesCommand.h
index f1b3a6816..34122513c 100644
--- a/Source/cmLinkLibrariesCommand.h
+++ b/Source/cmLinkLibrariesCommand.h
@@ -3,36 +3,14 @@
#ifndef cmLinkLibrariesCommand_h
#define cmLinkLibrariesCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmLinkLibrariesCommand
- * \brief Specify a list of libraries to link into executables.
- *
- * cmLinkLibrariesCommand 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).
- */
-class cmLinkLibrariesCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmLinkLibrariesCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmLinkLibrariesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx
index c0f702e25..0dc6236a0 100644
--- a/Source/cmLinkLineComputer.cxx
+++ b/Source/cmLinkLineComputer.cxx
@@ -4,13 +4,18 @@
#include "cmLinkLineComputer.h"
#include <sstream>
+#include <utility>
#include <vector>
#include "cmComputeLinkInformation.h"
#include "cmGeneratorTarget.h"
+#include "cmLinkItem.h"
+#include "cmListFileCache.h"
#include "cmOutputConverter.h"
#include "cmStateDirectory.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter,
cmStateDirectory const& stateDir)
@@ -22,9 +27,7 @@ cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter,
{
}
-cmLinkLineComputer::~cmLinkLineComputer()
-{
-}
+cmLinkLineComputer::~cmLinkLineComputer() = default;
void cmLinkLineComputer::SetUseWatcomQuote(bool useWatcomQuote)
{
@@ -46,9 +49,8 @@ std::string cmLinkLineComputer::ConvertToLinkReference(
{
std::string relLib = lib;
- if (cmOutputConverter::ContainedInDirectory(
- this->StateDir.GetCurrentBinary(), lib, this->StateDir)) {
- relLib = cmOutputConverter::ForceToRelativePath(
+ if (this->StateDir.ContainsBoth(this->StateDir.GetCurrentBinary(), lib)) {
+ relLib = cmSystemTools::ForceToRelativePath(
this->StateDir.GetCurrentBinary(), lib);
}
return relLib;
@@ -57,23 +59,49 @@ std::string cmLinkLineComputer::ConvertToLinkReference(
std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli)
{
std::string linkLibs;
- typedef cmComputeLinkInformation::ItemVector ItemVector;
+ std::vector<BT<std::string>> linkLibsList;
+ this->ComputeLinkLibs(cli, linkLibsList);
+ cli.AppendValues(linkLibs, linkLibsList);
+ return linkLibs;
+}
+
+void cmLinkLineComputer::ComputeLinkLibs(
+ cmComputeLinkInformation& cli, std::vector<BT<std::string>>& linkLibraries)
+{
+ using ItemVector = cmComputeLinkInformation::ItemVector;
ItemVector const& items = cli.GetItems();
- for (ItemVector::const_iterator li = items.begin(); li != items.end();
- ++li) {
- if (li->Target &&
- li->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ for (auto const& item : items) {
+ if (item.Target &&
+ item.Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
- if (li->IsPath) {
- linkLibs +=
- this->ConvertToOutputFormat(this->ConvertToLinkReference(li->Value));
+
+ BT<std::string> linkLib;
+ if (item.IsPath) {
+ linkLib.Value += cli.GetLibLinkFileFlag();
+ linkLib.Value +=
+ this->ConvertToOutputFormat(this->ConvertToLinkReference(item.Value));
} else {
- linkLibs += li->Value;
+ linkLib.Value += item.Value;
}
- linkLibs += " ";
+ linkLib.Value += " ";
+
+ const cmLinkImplementation* linkImpl =
+ cli.GetTarget()->GetLinkImplementation(cli.GetConfig());
+
+ for (const cmLinkImplItem& iter : linkImpl->Libraries) {
+ if (iter.Target != nullptr &&
+ iter.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ std::string libPath = iter.Target->GetLocation(cli.GetConfig());
+ if (item.Value == libPath) {
+ linkLib.Backtrace = iter.Backtrace;
+ break;
+ }
+ }
+ }
+
+ linkLibraries.emplace_back(linkLib);
}
- return linkLibs;
}
std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input)
@@ -102,18 +130,51 @@ std::string cmLinkLineComputer::ComputeLinkPath(
std::string const& libPathTerminator)
{
std::string linkPath;
- std::vector<std::string> const& libDirs = cli.GetDirectories();
- for (std::vector<std::string>::const_iterator libDir = libDirs.begin();
- libDir != libDirs.end(); ++libDir) {
- std::string libpath = this->ConvertToOutputForExisting(*libDir);
- linkPath += " " + libPathFlag;
- linkPath += libpath;
- linkPath += libPathTerminator;
- linkPath += " ";
- }
+ std::vector<BT<std::string>> linkPathList;
+ this->ComputeLinkPath(cli, libPathFlag, libPathTerminator, linkPathList);
+ cli.AppendValues(linkPath, linkPathList);
return linkPath;
}
+void cmLinkLineComputer::ComputeLinkPath(
+ cmComputeLinkInformation& cli, std::string const& libPathFlag,
+ std::string const& libPathTerminator, std::vector<BT<std::string>>& linkPath)
+{
+ if (cli.GetLinkLanguage() == "Swift") {
+ std::string linkPathNoBT;
+
+ for (const cmComputeLinkInformation::Item& item : cli.GetItems()) {
+ const cmGeneratorTarget* target = item.Target;
+ if (!target) {
+ continue;
+ }
+
+ if (target->GetType() == cmStateEnums::STATIC_LIBRARY ||
+ target->GetType() == cmStateEnums::SHARED_LIBRARY) {
+ cmStateEnums::ArtifactType type = cmStateEnums::RuntimeBinaryArtifact;
+ if (target->HasImportLibrary(cli.GetConfig())) {
+ type = cmStateEnums::ImportLibraryArtifact;
+ }
+
+ linkPathNoBT += cmStrCat(
+ " ", libPathFlag, item.Target->GetDirectory(cli.GetConfig(), type),
+ libPathTerminator, " ");
+ }
+ }
+
+ if (!linkPathNoBT.empty()) {
+ linkPath.emplace_back(std::move(linkPathNoBT));
+ }
+ }
+
+ for (BT<std::string> libDir : cli.GetDirectoriesWithBacktraces()) {
+ libDir.Value = cmStrCat(" ", libPathFlag,
+ this->ConvertToOutputForExisting(libDir.Value),
+ libPathTerminator, " ");
+ linkPath.emplace_back(libDir);
+ }
+}
+
std::string cmLinkLineComputer::ComputeRPath(cmComputeLinkInformation& cli)
{
std::string rpath;
@@ -123,10 +184,9 @@ std::string cmLinkLineComputer::ComputeRPath(cmComputeLinkInformation& cli)
std::vector<std::string> runtimeDirs;
cli.GetRPath(runtimeDirs, this->Relink);
- for (std::vector<std::string>::iterator ri = runtimeDirs.begin();
- ri != runtimeDirs.end(); ++ri) {
+ for (std::string const& rd : runtimeDirs) {
rpath += cli.GetRuntimeFlag();
- rpath += this->ConvertToOutputFormat(*ri);
+ rpath += this->ConvertToOutputFormat(rd);
rpath += " ";
}
} else {
@@ -150,10 +210,9 @@ std::string cmLinkLineComputer::ComputeFrameworkPath(
std::string frameworkPath;
if (!fwSearchFlag.empty()) {
std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
- for (std::vector<std::string>::const_iterator fdi = fwDirs.begin();
- fdi != fwDirs.end(); ++fdi) {
+ for (std::string const& fd : fwDirs) {
frameworkPath += fwSearchFlag;
- frameworkPath += this->ConvertToOutputFormat(*fdi);
+ frameworkPath += this->ConvertToOutputFormat(fd);
frameworkPath += " ";
}
}
@@ -163,13 +222,30 @@ std::string cmLinkLineComputer::ComputeFrameworkPath(
std::string cmLinkLineComputer::ComputeLinkLibraries(
cmComputeLinkInformation& cli, std::string const& stdLibString)
{
- std::ostringstream fout;
- fout << this->ComputeRPath(cli);
+ std::string linkLibraries;
+ std::vector<BT<std::string>> linkLibrariesList;
+ this->ComputeLinkLibraries(cli, stdLibString, linkLibrariesList);
+ cli.AppendValues(linkLibraries, linkLibrariesList);
+ return linkLibraries;
+}
+
+void cmLinkLineComputer::ComputeLinkLibraries(
+ cmComputeLinkInformation& cli, std::string const& stdLibString,
+ std::vector<BT<std::string>>& linkLibraries)
+{
+ std::ostringstream rpathOut;
+ rpathOut << this->ComputeRPath(cli);
+
+ std::string rpath = rpathOut.str();
+ if (!rpath.empty()) {
+ linkLibraries.emplace_back(std::move(rpath));
+ }
// Write the library flags to the build rule.
- fout << this->ComputeLinkLibs(cli);
+ this->ComputeLinkLibs(cli, linkLibraries);
// Add the linker runtime search path if any.
+ std::ostringstream fout;
std::string rpath_link = cli.GetRPathLinkString();
if (!cli.GetRPathLinkFlag().empty() && !rpath_link.empty()) {
fout << cli.GetRPathLinkFlag();
@@ -182,7 +258,10 @@ std::string cmLinkLineComputer::ComputeLinkLibraries(
fout << stdLibString << " ";
}
- return fout.str();
+ std::string remainingLibs = fout.str();
+ if (!remainingLibs.empty()) {
+ linkLibraries.emplace_back(remainingLibs);
+ }
}
std::string cmLinkLineComputer::GetLinkerLanguage(cmGeneratorTarget* target,
diff --git a/Source/cmLinkLineComputer.h b/Source/cmLinkLineComputer.h
index d33e8d1ff..f426976a2 100644
--- a/Source/cmLinkLineComputer.h
+++ b/Source/cmLinkLineComputer.h
@@ -4,25 +4,29 @@
#ifndef cmLinkLineComputer_h
#define cmLinkLineComputer_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
+#include <vector>
#include "cmStateDirectory.h"
class cmComputeLinkInformation;
class cmGeneratorTarget;
class cmOutputConverter;
+template <typename T>
+class BT;
class cmLinkLineComputer
{
- CM_DISABLE_COPY(cmLinkLineComputer)
-
public:
cmLinkLineComputer(cmOutputConverter* outputConverter,
cmStateDirectory const& stateDir);
virtual ~cmLinkLineComputer();
+ cmLinkLineComputer(cmLinkLineComputer const&) = delete;
+ cmLinkLineComputer& operator=(cmLinkLineComputer const&) = delete;
+
void SetUseWatcomQuote(bool useWatcomQuote);
void SetForResponse(bool forResponse);
void SetRelink(bool relink);
@@ -33,17 +37,28 @@ public:
std::string const& libPathFlag,
std::string const& libPathTerminator);
+ void ComputeLinkPath(cmComputeLinkInformation& cli,
+ std::string const& libPathFlag,
+ std::string const& libPathTerminator,
+ std::vector<BT<std::string>>& linkPath);
+
std::string ComputeFrameworkPath(cmComputeLinkInformation& cli,
std::string const& fwSearchFlag);
- virtual std::string ComputeLinkLibraries(cmComputeLinkInformation& cli,
- std::string const& stdLibString);
+ std::string ComputeLinkLibraries(cmComputeLinkInformation& cli,
+ std::string const& stdLibString);
+
+ virtual void ComputeLinkLibraries(
+ cmComputeLinkInformation& cli, std::string const& stdLibString,
+ std::vector<BT<std::string>>& linkLibraries);
virtual std::string GetLinkerLanguage(cmGeneratorTarget* target,
std::string const& config);
protected:
std::string ComputeLinkLibs(cmComputeLinkInformation& cli);
+ void ComputeLinkLibs(cmComputeLinkInformation& cli,
+ std::vector<BT<std::string>>& linkLibraries);
std::string ComputeRPath(cmComputeLinkInformation& cli);
std::string ConvertToOutputFormat(std::string const& input);
diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx
index 942e9b92c..847334b20 100644
--- a/Source/cmLinkLineDeviceComputer.cxx
+++ b/Source/cmLinkLineDeviceComputer.cxx
@@ -4,13 +4,20 @@
#include "cmLinkLineDeviceComputer.h"
#include <set>
-#include <sstream>
-#include <vector>
+#include <utility>
+#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
#include "cmGeneratorTarget.h"
-#include "cmGlobalNinjaGenerator.h"
+#include "cmGlobalGenerator.h"
+#include "cmLinkItem.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
class cmOutputConverter;
@@ -20,65 +27,132 @@ cmLinkLineDeviceComputer::cmLinkLineDeviceComputer(
{
}
-cmLinkLineDeviceComputer::~cmLinkLineDeviceComputer()
+cmLinkLineDeviceComputer::~cmLinkLineDeviceComputer() = default;
+
+static bool cmLinkItemValidForDevice(std::string const& item)
{
+ // Valid items are:
+ // * Non-flags (does not start in '-')
+ // * Specific flags --library, --library-path, -l, -L
+ // For example:
+ // * 'cublas_device' => pass-along
+ // * '--library pthread' => pass-along
+ // * '-lpthread' => pass-along
+ // * '-pthread' => drop
+ // * '-a' => drop
+ // * '-framework Name' (as one string) => drop
+ return (!cmHasLiteralPrefix(item, "-") || //
+ cmHasLiteralPrefix(item, "-l") || //
+ cmHasLiteralPrefix(item, "-L") || //
+ cmHasLiteralPrefix(item, "--library"));
}
-std::string cmLinkLineDeviceComputer::ComputeLinkLibraries(
- cmComputeLinkInformation& cli, std::string const& stdLibString)
+bool cmLinkLineDeviceComputer::ComputeRequiresDeviceLinking(
+ cmComputeLinkInformation& cli)
{
- // Write the library flags to the build rule.
- std::ostringstream fout;
- typedef cmComputeLinkInformation::ItemVector ItemVector;
+ // Determine if this item might requires device linking.
+ // For this we only consider targets
+ using ItemVector = cmComputeLinkInformation::ItemVector;
ItemVector const& items = cli.GetItems();
std::string config = cli.GetConfig();
- for (ItemVector::const_iterator li = items.begin(); li != items.end();
- ++li) {
- if (!li->Target) {
- continue;
+ for (auto const& item : items) {
+ if (item.Target &&
+ item.Target->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ if ((!item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS")) &&
+ item.Target->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) {
+ // this dependency requires us to device link it
+ return true;
+ }
}
+ }
+ return false;
+}
- bool skippable = false;
- switch (li->Target->GetType()) {
- case cmStateEnums::SHARED_LIBRARY:
- case cmStateEnums::MODULE_LIBRARY:
- case cmStateEnums::INTERFACE_LIBRARY:
- skippable = true;
- break;
- case cmStateEnums::STATIC_LIBRARY:
- // If a static library is resolving its device linking, it should
- // be removed for other device linking
- skippable =
- li->Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
- break;
- default:
- break;
+void cmLinkLineDeviceComputer::ComputeLinkLibraries(
+ cmComputeLinkInformation& cli, std::string const& stdLibString,
+ std::vector<BT<std::string>>& linkLibraries)
+{
+ // Generate the unique set of link items when device linking.
+ // The nvcc device linker is designed so that each static library
+ // with device symbols only needs to be listed once as it doesn't
+ // care about link order.
+ std::set<std::string> emitted;
+ using ItemVector = cmComputeLinkInformation::ItemVector;
+ ItemVector const& items = cli.GetItems();
+ std::string config = cli.GetConfig();
+ bool skipItemAfterFramework = false;
+ // Note:
+ // Any modification of this algorithm should be reflected also in
+ // cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions
+ for (auto const& item : items) {
+ if (skipItemAfterFramework) {
+ skipItemAfterFramework = false;
+ continue;
}
- if (skippable) {
- continue;
+ if (item.Target) {
+ bool skip = false;
+ switch (item.Target->GetType()) {
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::INTERFACE_LIBRARY:
+ skip = true;
+ break;
+ case cmStateEnums::STATIC_LIBRARY:
+ skip = item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
+ break;
+ default:
+ break;
+ }
+ if (skip) {
+ continue;
+ }
}
- std::set<std::string> langs;
- li->Target->GetLanguages(langs, config);
- if (langs.count("CUDA") == 0) {
+ BT<std::string> linkLib;
+ if (item.IsPath) {
+ // nvcc understands absolute paths to libraries ending in '.a' or '.lib'.
+ // These should be passed to nvlink. Other extensions need to be left
+ // out because nvlink may not understand or need them. Even though it
+ // can tolerate '.so' or '.dylib' it cannot tolerate '.so.1'.
+ if (cmHasLiteralSuffix(item.Value, ".a") ||
+ cmHasLiteralSuffix(item.Value, ".lib")) {
+ linkLib.Value += this->ConvertToOutputFormat(
+ this->ConvertToLinkReference(item.Value));
+ }
+ } else if (item.Value == "-framework") {
+ // This is the first part of '-framework Name' where the framework
+ // name is specified as a following item. Ignore both.
+ skipItemAfterFramework = true;
continue;
+ } else if (cmLinkItemValidForDevice(item.Value)) {
+ linkLib.Value += item.Value;
}
- if (li->IsPath) {
- fout << this->ConvertToOutputFormat(
- this->ConvertToLinkReference(li->Value));
- } else {
- fout << li->Value;
+ if (emitted.insert(linkLib.Value).second) {
+ linkLib.Value += " ";
+
+ const cmLinkImplementation* linkImpl =
+ cli.GetTarget()->GetLinkImplementation(cli.GetConfig());
+
+ for (const cmLinkImplItem& iter : linkImpl->Libraries) {
+ if (iter.Target != nullptr &&
+ iter.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ std::string libPath = iter.Target->GetLocation(cli.GetConfig());
+ if (item.Value == libPath) {
+ linkLib.Backtrace = iter.Backtrace;
+ break;
+ }
+ }
+ }
+
+ linkLibraries.emplace_back(linkLib);
}
- fout << " ";
}
if (!stdLibString.empty()) {
- fout << stdLibString << " ";
+ linkLibraries.emplace_back(cmStrCat(stdLibString, ' '));
}
-
- return fout.str();
}
std::string cmLinkLineDeviceComputer::GetLinkerLanguage(cmGeneratorTarget*,
@@ -87,16 +161,58 @@ std::string cmLinkLineDeviceComputer::GetLinkerLanguage(cmGeneratorTarget*,
return "CUDA";
}
-cmNinjaLinkLineDeviceComputer::cmNinjaLinkLineDeviceComputer(
- cmOutputConverter* outputConverter, cmStateDirectory const& stateDir,
- cmGlobalNinjaGenerator const* gg)
- : cmLinkLineDeviceComputer(outputConverter, stateDir)
- , GG(gg)
+bool requireDeviceLinking(cmGeneratorTarget& target, cmLocalGenerator& lg,
+ const std::string& config)
{
-}
+ if (!target.GetGlobalGenerator()->GetLanguageEnabled("CUDA")) {
+ return false;
+ }
-std::string cmNinjaLinkLineDeviceComputer::ConvertToLinkReference(
- std::string const& lib) const
-{
- return GG->ConvertToNinjaPath(lib);
+ if (target.GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ return false;
+ }
+
+ if (!lg.GetMakefile()->IsOn("CMAKE_CUDA_COMPILER_HAS_DEVICE_LINK_PHASE")) {
+ return false;
+ }
+
+ if (const char* resolveDeviceSymbols =
+ target.GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) {
+ // If CUDA_RESOLVE_DEVICE_SYMBOLS has been explicitly set we need
+ // to honor the value no matter what it is.
+ return cmIsOn(resolveDeviceSymbols);
+ }
+
+ // Determine if we have any dependencies that require
+ // us to do a device link step
+ cmGeneratorTarget::LinkClosure const* closure =
+ target.GetLinkClosure(config);
+
+ if (cmContains(closure->Languages, "CUDA")) {
+ if (const char* separableCompilation =
+ target.GetProperty("CUDA_SEPARABLE_COMPILATION")) {
+ if (cmIsOn(separableCompilation)) {
+ bool doDeviceLinking = false;
+ switch (target.GetType()) {
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::EXECUTABLE:
+ doDeviceLinking = true;
+ break;
+ default:
+ break;
+ }
+ return doDeviceLinking;
+ }
+ }
+
+ cmComputeLinkInformation* pcli = target.GetLinkInformation(config);
+ if (pcli) {
+ cmLinkLineDeviceComputer deviceLinkComputer(
+ &lg, lg.GetStateSnapshot().GetDirectory());
+ return deviceLinkComputer.ComputeRequiresDeviceLinking(*pcli);
+ }
+ return true;
+ }
+ return false;
}
diff --git a/Source/cmLinkLineDeviceComputer.h b/Source/cmLinkLineDeviceComputer.h
index c3fac6182..a9b01cd9c 100644
--- a/Source/cmLinkLineDeviceComputer.h
+++ b/Source/cmLinkLineDeviceComputer.h
@@ -4,49 +4,43 @@
#ifndef cmLinkLineDeviceComputer_h
#define cmLinkLineDeviceComputer_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
+#include <vector>
#include "cmLinkLineComputer.h"
class cmComputeLinkInformation;
class cmGeneratorTarget;
-class cmGlobalNinjaGenerator;
+class cmLocalGenerator;
class cmOutputConverter;
class cmStateDirectory;
+template <typename T>
+class BT;
class cmLinkLineDeviceComputer : public cmLinkLineComputer
{
- CM_DISABLE_COPY(cmLinkLineDeviceComputer)
-
public:
cmLinkLineDeviceComputer(cmOutputConverter* outputConverter,
cmStateDirectory const& stateDir);
- ~cmLinkLineDeviceComputer() CM_OVERRIDE;
+ ~cmLinkLineDeviceComputer() override;
- std::string ComputeLinkLibraries(cmComputeLinkInformation& cli,
- std::string const& stdLibString)
- CM_OVERRIDE;
+ cmLinkLineDeviceComputer(cmLinkLineDeviceComputer const&) = delete;
+ cmLinkLineDeviceComputer& operator=(cmLinkLineDeviceComputer const&) =
+ delete;
- std::string GetLinkerLanguage(cmGeneratorTarget* target,
- std::string const& config) CM_OVERRIDE;
-};
+ bool ComputeRequiresDeviceLinking(cmComputeLinkInformation& cli);
-class cmNinjaLinkLineDeviceComputer : public cmLinkLineDeviceComputer
-{
- CM_DISABLE_COPY(cmNinjaLinkLineDeviceComputer)
+ void ComputeLinkLibraries(
+ cmComputeLinkInformation& cli, std::string const& stdLibString,
+ std::vector<BT<std::string>>& linkLibraries) override;
-public:
- cmNinjaLinkLineDeviceComputer(cmOutputConverter* outputConverter,
- cmStateDirectory const& stateDir,
- cmGlobalNinjaGenerator const* gg);
-
- std::string ConvertToLinkReference(std::string const& input) const
- CM_OVERRIDE;
-
-private:
- cmGlobalNinjaGenerator const* GG;
+ std::string GetLinkerLanguage(cmGeneratorTarget* target,
+ std::string const& config) override;
};
+bool requireDeviceLinking(cmGeneratorTarget& target, cmLocalGenerator& lg,
+ const std::string& config);
+
#endif
diff --git a/Source/cmLinkedTree.h b/Source/cmLinkedTree.h
index 55592cb35..c7453eac9 100644
--- a/Source/cmLinkedTree.h
+++ b/Source/cmLinkedTree.h
@@ -3,10 +3,9 @@
#ifndef cmLinkedTree_h
#define cmLinkedTree_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include <assert.h>
-#include <iterator>
+#include <cassert>
#include <vector>
/**
@@ -28,12 +27,12 @@
template <typename T>
class cmLinkedTree
{
- typedef typename std::vector<T>::size_type PositionType;
- typedef T* PointerType;
- typedef T& ReferenceType;
+ using PositionType = typename std::vector<T>::size_type;
+ using PointerType = T*;
+ using ReferenceType = T&;
public:
- class iterator : public std::iterator<std::forward_iterator_tag, T>
+ class iterator
{
friend class cmLinkedTree;
cmLinkedTree* Tree;
@@ -49,7 +48,7 @@ public:
public:
iterator()
- : Tree(CM_NULLPTR)
+ : Tree(nullptr)
, Position(0)
{
}
@@ -137,7 +136,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 +176,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/cmListCommand.cxx b/Source/cmListCommand.cxx
index 0542c4fce..5200a160f 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -2,75 +2,49 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmListCommand.h"
-#include "cmsys/RegularExpression.hxx"
#include <algorithm>
-#include <assert.h>
+#include <cassert>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib> // required for atoi
+#include <functional>
#include <iterator>
+#include <set>
#include <sstream>
-#include <stdio.h>
-#include <stdlib.h> // required for atoi
+#include <stdexcept>
+#include <utility>
+#include <vector>
+
+#include <cm/memory>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cm_static_string_view.hxx"
#include "cmAlgorithms.h"
+#include "cmExecutionStatus.h"
+#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmRange.h"
+#include "cmStringAlgorithms.h"
+#include "cmStringReplaceHelper.h"
+#include "cmSubcommandTable.h"
#include "cmSystemTools.h"
-#include "cmake.h"
-class cmExecutionStatus;
+namespace {
-bool cmListCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
-{
- if (args.size() < 2) {
- this->SetError("must be called with at least two arguments.");
- return false;
- }
-
- const std::string& subCommand = args[0];
- if (subCommand == "LENGTH") {
- return this->HandleLengthCommand(args);
- }
- if (subCommand == "GET") {
- return this->HandleGetCommand(args);
- }
- if (subCommand == "APPEND") {
- return this->HandleAppendCommand(args);
- }
- if (subCommand == "FIND") {
- return this->HandleFindCommand(args);
- }
- if (subCommand == "INSERT") {
- return this->HandleInsertCommand(args);
- }
- if (subCommand == "REMOVE_AT") {
- return this->HandleRemoveAtCommand(args);
- }
- if (subCommand == "REMOVE_ITEM") {
- return this->HandleRemoveItemCommand(args);
- }
- if (subCommand == "REMOVE_DUPLICATES") {
- return this->HandleRemoveDuplicatesCommand(args);
- }
- if (subCommand == "SORT") {
- return this->HandleSortCommand(args);
- }
- if (subCommand == "REVERSE") {
- return this->HandleReverseCommand(args);
- }
- if (subCommand == "FILTER") {
- return this->HandleFilterCommand(args);
- }
+bool FilterRegex(std::vector<std::string> const& args, bool includeMatches,
+ std::string const& listName,
+ std::vector<std::string>& varArgsExpanded,
+ cmExecutionStatus& status);
- std::string e = "does not recognize sub-command " + subCommand;
- this->SetError(e);
- return false;
-}
-
-bool cmListCommand::GetListString(std::string& listString,
- const std::string& var)
+bool GetListString(std::string& listString, const std::string& var,
+ const cmMakefile& makefile)
{
// get the old value
- const char* cacheValue = this->Makefile->GetDefinition(var);
+ const char* cacheValue = makefile.GetDefinition(var);
if (!cacheValue) {
return false;
}
@@ -78,11 +52,11 @@ bool cmListCommand::GetListString(std::string& listString,
return true;
}
-bool cmListCommand::GetList(std::vector<std::string>& list,
- const std::string& var)
+bool GetList(std::vector<std::string>& list, const std::string& var,
+ const cmMakefile& makefile)
{
std::string listString;
- if (!this->GetListString(listString, var)) {
+ if (!GetListString(listString, var, makefile)) {
return false;
}
// if the size of the list
@@ -90,25 +64,24 @@ bool cmListCommand::GetList(std::vector<std::string>& list,
return true;
}
// expand the variable into a list
- cmSystemTools::ExpandListArgument(listString, list, true);
+ cmExpandList(listString, list, true);
// if no empty elements then just return
- if (std::find(list.begin(), list.end(), std::string()) == list.end()) {
+ if (!cmContains(list, std::string())) {
return true;
}
// if we have empty elements we need to check policy CMP0007
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0007)) {
+ switch (makefile.GetPolicyStatus(cmPolicies::CMP0007)) {
case cmPolicies::WARN: {
// Default is to warn and use old behavior
// OLD behavior is to allow compatibility, so recall
// ExpandListArgument without the true which will remove
// empty values
list.clear();
- cmSystemTools::ExpandListArgument(listString, list);
- std::string warn = cmPolicies::GetPolicyWarning(cmPolicies::CMP0007);
- warn += " List has value = [";
- warn += listString;
- warn += "].";
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, warn);
+ cmExpandList(listString, list);
+ std::string warn =
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0007),
+ " List has value = [", listString, "].");
+ makefile.IssueMessage(MessageType::AUTHOR_WARNING, warn);
return true;
}
case cmPolicies::OLD:
@@ -116,60 +89,62 @@ bool cmListCommand::GetList(std::vector<std::string>& list,
// ExpandListArgument without the true which will remove
// empty values
list.clear();
- cmSystemTools::ExpandListArgument(listString, list);
+ cmExpandList(listString, list);
return true;
case cmPolicies::NEW:
return true;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ makefile.IssueMessage(
+ MessageType::FATAL_ERROR,
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0007));
return false;
}
return true;
}
-bool cmListCommand::HandleLengthCommand(std::vector<std::string> const& args)
+bool HandleLengthCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() != 3) {
- this->SetError("sub-command LENGTH requires two arguments.");
+ status.SetError("sub-command LENGTH requires two arguments.");
return false;
}
const std::string& listName = args[1];
- const std::string& variableName = args[args.size() - 1];
+ const std::string& variableName = args.back();
std::vector<std::string> varArgsExpanded;
// do not check the return value here
// if the list var is not found varArgsExpanded will have size 0
// and we will return 0
- this->GetList(varArgsExpanded, listName);
+ GetList(varArgsExpanded, listName, status.GetMakefile());
size_t length = varArgsExpanded.size();
char buffer[1024];
sprintf(buffer, "%d", static_cast<int>(length));
- this->Makefile->AddDefinition(variableName, buffer);
+ status.GetMakefile().AddDefinition(variableName, buffer);
return true;
}
-bool cmListCommand::HandleGetCommand(std::vector<std::string> const& args)
+bool HandleGetCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 4) {
- this->SetError("sub-command GET requires at least three arguments.");
+ status.SetError("sub-command GET requires at least three arguments.");
return false;
}
const std::string& listName = args[1];
- const std::string& variableName = args[args.size() - 1];
+ const std::string& variableName = args.back();
// expand the variable
std::vector<std::string> varArgsExpanded;
- if (!this->GetList(varArgsExpanded, listName)) {
- this->Makefile->AddDefinition(variableName, "NOTFOUND");
+ if (!GetList(varArgsExpanded, listName, status.GetMakefile())) {
+ status.GetMakefile().AddDefinition(variableName, "NOTFOUND");
return true;
}
// FIXME: Add policy to make non-existing lists an error like empty lists.
if (varArgsExpanded.empty()) {
- this->SetError("GET given empty list");
+ status.SetError("GET given empty list");
return false;
}
@@ -182,23 +157,22 @@ bool cmListCommand::HandleGetCommand(std::vector<std::string> const& args)
value += sep;
sep = ";";
if (item < 0) {
- item = (int)nitem + item;
+ item = static_cast<int>(nitem) + item;
}
- if (item < 0 || nitem <= (size_t)item) {
- std::ostringstream str;
- str << "index: " << item << " out of range (-" << nitem << ", "
- << nitem - 1 << ")";
- this->SetError(str.str());
+ if (item < 0 || nitem <= static_cast<size_t>(item)) {
+ status.SetError(cmStrCat("index: ", item, " out of range (-", nitem,
+ ", ", nitem - 1, ")"));
return false;
}
value += varArgsExpanded[item];
}
- this->Makefile->AddDefinition(variableName, value.c_str());
+ status.GetMakefile().AddDefinition(variableName, value);
return true;
}
-bool cmListCommand::HandleAppendCommand(std::vector<std::string> const& args)
+bool HandleAppendCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
assert(args.size() >= 2);
@@ -207,53 +181,180 @@ bool cmListCommand::HandleAppendCommand(std::vector<std::string> const& args)
return true;
}
- const std::string& listName = args[1];
+ cmMakefile& makefile = status.GetMakefile();
+ std::string const& listName = args[1];
// expand the variable
std::string listString;
- this->GetListString(listString, listName);
+ GetListString(listString, listName, makefile);
- if (!listString.empty() && !args.empty()) {
- listString += ";";
+ // If `listString` or `args` is empty, no need to append `;`,
+ // then index is going to be `1` and points to the end-of-string ";"
+ auto const offset =
+ std::string::size_type(listString.empty() || args.empty());
+ listString += &";"[offset] + cmJoin(cmMakeRange(args).advance(2), ";");
+
+ makefile.AddDefinition(listName, listString);
+ return true;
+}
+
+bool HandlePrependCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ assert(args.size() >= 2);
+
+ // Skip if nothing to prepend.
+ if (args.size() < 3) {
+ return true;
}
- listString += cmJoin(cmMakeRange(args).advance(2), ";");
- this->Makefile->AddDefinition(listName, listString.c_str());
+ cmMakefile& makefile = status.GetMakefile();
+ std::string const& listName = args[1];
+ // expand the variable
+ std::string listString;
+ GetListString(listString, listName, makefile);
+
+ // If `listString` or `args` is empty, no need to append `;`,
+ // then `offset` is going to be `1` and points to the end-of-string ";"
+ auto const offset =
+ std::string::size_type(listString.empty() || args.empty());
+ listString.insert(0,
+ cmJoin(cmMakeRange(args).advance(2), ";") + &";"[offset]);
+
+ makefile.AddDefinition(listName, listString);
return true;
}
-bool cmListCommand::HandleFindCommand(std::vector<std::string> const& args)
+bool HandlePopBackCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ assert(args.size() >= 2);
+
+ cmMakefile& makefile = status.GetMakefile();
+ auto ai = args.cbegin();
+ ++ai; // Skip subcommand name
+ std::string const& listName = *ai++;
+ std::vector<std::string> varArgsExpanded;
+ if (!GetList(varArgsExpanded, listName, makefile)) {
+ // Can't get the list definition... undefine any vars given after.
+ for (; ai != args.cend(); ++ai) {
+ makefile.RemoveDefinition(*ai);
+ }
+ return true;
+ }
+
+ if (!varArgsExpanded.empty()) {
+ if (ai == args.cend()) {
+ // No variables are given... Just remove one element.
+ varArgsExpanded.pop_back();
+ } else {
+ // Ok, assign elements to be removed to the given variables
+ for (; !varArgsExpanded.empty() && ai != args.cend(); ++ai) {
+ assert(!ai->empty());
+ makefile.AddDefinition(*ai, varArgsExpanded.back());
+ varArgsExpanded.pop_back();
+ }
+ // Undefine the rest variables if the list gets empty earlier...
+ for (; ai != args.cend(); ++ai) {
+ makefile.RemoveDefinition(*ai);
+ }
+ }
+
+ makefile.AddDefinition(listName, cmJoin(varArgsExpanded, ";"));
+
+ } else if (ai !=
+ args.cend()) { // The list is empty, but some args were given
+ // Need to *undefine* 'em all, cuz there are no items to assign...
+ for (; ai != args.cend(); ++ai) {
+ makefile.RemoveDefinition(*ai);
+ }
+ }
+
+ return true;
+}
+
+bool HandlePopFrontCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ assert(args.size() >= 2);
+
+ cmMakefile& makefile = status.GetMakefile();
+ auto ai = args.cbegin();
+ ++ai; // Skip subcommand name
+ std::string const& listName = *ai++;
+ std::vector<std::string> varArgsExpanded;
+ if (!GetList(varArgsExpanded, listName, makefile)) {
+ // Can't get the list definition... undefine any vars given after.
+ for (; ai != args.cend(); ++ai) {
+ makefile.RemoveDefinition(*ai);
+ }
+ return true;
+ }
+
+ if (!varArgsExpanded.empty()) {
+ if (ai == args.cend()) {
+ // No variables are given... Just remove one element.
+ varArgsExpanded.erase(varArgsExpanded.begin());
+ } else {
+ // Ok, assign elements to be removed to the given variables
+ auto vi = varArgsExpanded.begin();
+ for (; vi != varArgsExpanded.end() && ai != args.cend(); ++ai, ++vi) {
+ assert(!ai->empty());
+ makefile.AddDefinition(*ai, *vi);
+ }
+ varArgsExpanded.erase(varArgsExpanded.begin(), vi);
+ // Undefine the rest variables if the list gets empty earlier...
+ for (; ai != args.cend(); ++ai) {
+ makefile.RemoveDefinition(*ai);
+ }
+ }
+
+ makefile.AddDefinition(listName, cmJoin(varArgsExpanded, ";"));
+
+ } else if (ai !=
+ args.cend()) { // The list is empty, but some args were given
+ // Need to *undefine* 'em all, cuz there are no items to assign...
+ for (; ai != args.cend(); ++ai) {
+ makefile.RemoveDefinition(*ai);
+ }
+ }
+
+ return true;
+}
+
+bool HandleFindCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() != 4) {
- this->SetError("sub-command FIND requires three arguments.");
+ status.SetError("sub-command FIND requires three arguments.");
return false;
}
const std::string& listName = args[1];
- const std::string& variableName = args[args.size() - 1];
+ const std::string& variableName = args.back();
// expand the variable
std::vector<std::string> varArgsExpanded;
- if (!this->GetList(varArgsExpanded, listName)) {
- this->Makefile->AddDefinition(variableName, "-1");
+ if (!GetList(varArgsExpanded, listName, status.GetMakefile())) {
+ status.GetMakefile().AddDefinition(variableName, "-1");
return true;
}
- std::vector<std::string>::iterator it =
- std::find(varArgsExpanded.begin(), varArgsExpanded.end(), args[2]);
+ auto it = std::find(varArgsExpanded.begin(), varArgsExpanded.end(), args[2]);
if (it != varArgsExpanded.end()) {
- std::ostringstream indexStream;
- indexStream << std::distance(varArgsExpanded.begin(), it);
- this->Makefile->AddDefinition(variableName, indexStream.str().c_str());
+ status.GetMakefile().AddDefinition(
+ variableName,
+ std::to_string(std::distance(varArgsExpanded.begin(), it)));
return true;
}
- this->Makefile->AddDefinition(variableName, "-1");
+ status.GetMakefile().AddDefinition(variableName, "-1");
return true;
}
-bool cmListCommand::HandleInsertCommand(std::vector<std::string> const& args)
+bool HandleInsertCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 4) {
- this->SetError("sub-command INSERT requires at least three arguments.");
+ status.SetError("sub-command INSERT requires at least three arguments.");
return false;
}
@@ -262,26 +363,22 @@ bool cmListCommand::HandleInsertCommand(std::vector<std::string> const& args)
// expand the variable
int item = atoi(args[2].c_str());
std::vector<std::string> varArgsExpanded;
- if ((!this->GetList(varArgsExpanded, listName) || varArgsExpanded.empty()) &&
+ if ((!GetList(varArgsExpanded, listName, status.GetMakefile()) ||
+ varArgsExpanded.empty()) &&
item != 0) {
- std::ostringstream str;
- str << "index: " << item << " out of range (0, 0)";
- this->SetError(str.str());
+ status.SetError(cmStrCat("index: ", item, " out of range (0, 0)"));
return false;
}
if (!varArgsExpanded.empty()) {
size_t nitem = varArgsExpanded.size();
if (item < 0) {
- item = (int)nitem + item;
- }
- if (item < 0 || nitem <= (size_t)item) {
- std::ostringstream str;
- str << "index: " << item << " out of range (-" << varArgsExpanded.size()
- << ", "
- << (varArgsExpanded.empty() ? 0 : (varArgsExpanded.size() - 1))
- << ")";
- this->SetError(str.str());
+ item = static_cast<int>(nitem) + item;
+ }
+ if (item < 0 || nitem < static_cast<size_t>(item)) {
+ status.SetError(cmStrCat("index: ", item, " out of range (-",
+ varArgsExpanded.size(), ", ",
+ varArgsExpanded.size(), ")"));
return false;
}
}
@@ -290,130 +387,928 @@ bool cmListCommand::HandleInsertCommand(std::vector<std::string> const& args)
args.end());
std::string value = cmJoin(varArgsExpanded, ";");
- this->Makefile->AddDefinition(listName, value.c_str());
+ status.GetMakefile().AddDefinition(listName, value);
return true;
}
-bool cmListCommand::HandleRemoveItemCommand(
- std::vector<std::string> const& args)
+bool HandleJoinCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- if (args.size() < 3) {
- this->SetError("sub-command REMOVE_ITEM requires two or more arguments.");
+ if (args.size() != 4) {
+ status.SetError(cmStrCat("sub-command JOIN requires three arguments (",
+ args.size() - 1, " found)."));
return false;
}
const std::string& listName = args[1];
+ const std::string& glue = args[2];
+ const std::string& variableName = args[3];
+
// expand the variable
std::vector<std::string> varArgsExpanded;
- if (!this->GetList(varArgsExpanded, listName)) {
- this->SetError("sub-command REMOVE_ITEM requires list to be present.");
+ if (!GetList(varArgsExpanded, listName, status.GetMakefile())) {
+ status.GetMakefile().AddDefinition(variableName, "");
+ return true;
+ }
+
+ std::string value =
+ cmJoin(cmMakeRange(varArgsExpanded.begin(), varArgsExpanded.end()), glue);
+
+ status.GetMakefile().AddDefinition(variableName, value);
+ return true;
+}
+
+bool HandleRemoveItemCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.size() < 3) {
+ status.SetError("sub-command REMOVE_ITEM requires two or more arguments.");
return false;
}
+ const std::string& listName = args[1];
+ // expand the variable
+ std::vector<std::string> varArgsExpanded;
+ if (!GetList(varArgsExpanded, listName, status.GetMakefile())) {
+ return true;
+ }
+
std::vector<std::string> remove(args.begin() + 2, args.end());
std::sort(remove.begin(), remove.end());
- std::vector<std::string>::const_iterator remEnd =
- std::unique(remove.begin(), remove.end());
- std::vector<std::string>::const_iterator remBegin = remove.begin();
+ auto remEnd = std::unique(remove.begin(), remove.end());
+ auto remBegin = remove.begin();
- std::vector<std::string>::const_iterator argsEnd =
+ auto argsEnd =
cmRemoveMatching(varArgsExpanded, cmMakeRange(remBegin, remEnd));
- std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin();
+ auto argsBegin = varArgsExpanded.cbegin();
std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";");
- this->Makefile->AddDefinition(listName, value.c_str());
+ status.GetMakefile().AddDefinition(listName, value);
return true;
}
-bool cmListCommand::HandleReverseCommand(std::vector<std::string> const& args)
+bool HandleReverseCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
assert(args.size() >= 2);
if (args.size() > 2) {
- this->SetError("sub-command REVERSE only takes one argument.");
+ status.SetError("sub-command REVERSE only takes one argument.");
return false;
}
const std::string& listName = args[1];
// expand the variable
std::vector<std::string> varArgsExpanded;
- if (!this->GetList(varArgsExpanded, listName)) {
- this->SetError("sub-command REVERSE requires list to be present.");
- return false;
+ if (!GetList(varArgsExpanded, listName, status.GetMakefile())) {
+ return true;
}
std::string value = cmJoin(cmReverseRange(varArgsExpanded), ";");
- this->Makefile->AddDefinition(listName, value.c_str());
+ status.GetMakefile().AddDefinition(listName, value);
return true;
}
-bool cmListCommand::HandleRemoveDuplicatesCommand(
- std::vector<std::string> const& args)
+bool HandleRemoveDuplicatesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
assert(args.size() >= 2);
if (args.size() > 2) {
- this->SetError("sub-command REMOVE_DUPLICATES only takes one argument.");
+ status.SetError("sub-command REMOVE_DUPLICATES only takes one argument.");
return false;
}
const std::string& listName = args[1];
// expand the variable
std::vector<std::string> varArgsExpanded;
- if (!this->GetList(varArgsExpanded, listName)) {
- this->SetError(
- "sub-command REMOVE_DUPLICATES requires list to be present.");
- return false;
+ if (!GetList(varArgsExpanded, listName, status.GetMakefile())) {
+ return true;
}
- std::vector<std::string>::const_iterator argsEnd =
- cmRemoveDuplicates(varArgsExpanded);
- std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin();
+ auto argsEnd = cmRemoveDuplicates(varArgsExpanded);
+ auto argsBegin = varArgsExpanded.cbegin();
std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";");
- this->Makefile->AddDefinition(listName, value.c_str());
+ status.GetMakefile().AddDefinition(listName, value);
return true;
}
-bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args)
+// Helpers for list(TRANSFORM <list> ...)
+using transform_type = std::function<std::string(const std::string&)>;
+
+class transform_error : public std::runtime_error
+{
+public:
+ transform_error(const std::string& error)
+ : std::runtime_error(error)
+ {
+ }
+};
+
+class TransformSelector
+{
+public:
+ virtual ~TransformSelector() = default;
+
+ std::string Tag;
+
+ virtual bool Validate(std::size_t count = 0) = 0;
+
+ virtual bool InSelection(const std::string&) = 0;
+
+ virtual void Transform(std::vector<std::string>& list,
+ const transform_type& transform)
+ {
+ std::transform(list.begin(), list.end(), list.begin(), transform);
+ }
+
+protected:
+ TransformSelector(std::string&& tag)
+ : Tag(std::move(tag))
+ {
+ }
+};
+class TransformNoSelector : public TransformSelector
+{
+public:
+ TransformNoSelector()
+ : TransformSelector("NO SELECTOR")
+ {
+ }
+
+ bool Validate(std::size_t) override { return true; }
+
+ bool InSelection(const std::string&) override { return true; }
+};
+class TransformSelectorRegex : public TransformSelector
+{
+public:
+ TransformSelectorRegex(const std::string& regex)
+ : TransformSelector("REGEX")
+ , Regex(regex)
+ {
+ }
+
+ bool Validate(std::size_t) override { return this->Regex.is_valid(); }
+
+ bool InSelection(const std::string& value) override
+ {
+ return this->Regex.find(value);
+ }
+
+ cmsys::RegularExpression Regex;
+};
+class TransformSelectorIndexes : public TransformSelector
+{
+public:
+ std::vector<int> Indexes;
+
+ bool InSelection(const std::string&) override { return true; }
+
+ void Transform(std::vector<std::string>& list,
+ const transform_type& transform) override
+ {
+ this->Validate(list.size());
+
+ for (auto index : this->Indexes) {
+ list[index] = transform(list[index]);
+ }
+ }
+
+protected:
+ TransformSelectorIndexes(std::string&& tag)
+ : TransformSelector(std::move(tag))
+ {
+ }
+ TransformSelectorIndexes(std::string&& tag, std::vector<int>&& indexes)
+ : TransformSelector(std::move(tag))
+ , Indexes(indexes)
+ {
+ }
+
+ int NormalizeIndex(int index, std::size_t count)
+ {
+ if (index < 0) {
+ index = static_cast<int>(count) + index;
+ }
+ if (index < 0 || count <= static_cast<std::size_t>(index)) {
+ throw transform_error(cmStrCat(
+ "sub-command TRANSFORM, selector ", this->Tag, ", index: ", index,
+ " out of range (-", count, ", ", count - 1, ")."));
+ }
+ return index;
+ }
+};
+class TransformSelectorAt : public TransformSelectorIndexes
+{
+public:
+ TransformSelectorAt(std::vector<int>&& indexes)
+ : TransformSelectorIndexes("AT", std::move(indexes))
+ {
+ }
+
+ bool Validate(std::size_t count) override
+ {
+ decltype(Indexes) indexes;
+
+ for (auto index : Indexes) {
+ indexes.push_back(this->NormalizeIndex(index, count));
+ }
+ this->Indexes = std::move(indexes);
+
+ return true;
+ }
+};
+class TransformSelectorFor : public TransformSelectorIndexes
+{
+public:
+ TransformSelectorFor(int start, int stop, int step)
+ : TransformSelectorIndexes("FOR")
+ , Start(start)
+ , Stop(stop)
+ , Step(step)
+ {
+ }
+
+ bool Validate(std::size_t count) override
+ {
+ this->Start = this->NormalizeIndex(this->Start, count);
+ this->Stop = this->NormalizeIndex(this->Stop, count);
+
+ // compute indexes
+ auto size = (this->Stop - this->Start + 1) / this->Step;
+ if ((this->Stop - this->Start + 1) % this->Step != 0) {
+ size += 1;
+ }
+
+ this->Indexes.resize(size);
+ auto start = this->Start;
+ auto step = this->Step;
+ std::generate(this->Indexes.begin(), this->Indexes.end(),
+ [&start, step]() -> int {
+ auto r = start;
+ start += step;
+ return r;
+ });
+
+ return true;
+ }
+
+private:
+ int Start, Stop, Step;
+};
+
+class TransformAction
+{
+public:
+ virtual ~TransformAction() = default;
+
+ virtual std::string Transform(const std::string& input) = 0;
+};
+class TransformReplace : public TransformAction
+{
+public:
+ TransformReplace(const std::vector<std::string>& arguments,
+ cmMakefile* makefile)
+ : ReplaceHelper(arguments[0], arguments[1], makefile)
+ {
+ makefile->ClearMatches();
+
+ if (!this->ReplaceHelper.IsRegularExpressionValid()) {
+ throw transform_error(
+ cmStrCat("sub-command TRANSFORM, action REPLACE: Failed to compile "
+ "regex \"",
+ arguments[0], "\"."));
+ }
+ if (!this->ReplaceHelper.IsReplaceExpressionValid()) {
+ throw transform_error(cmStrCat("sub-command TRANSFORM, action REPLACE: ",
+ this->ReplaceHelper.GetError(), "."));
+ }
+ }
+
+ std::string Transform(const std::string& input) override
+ {
+ // Scan through the input for all matches.
+ std::string output;
+
+ if (!this->ReplaceHelper.Replace(input, output)) {
+ throw transform_error(cmStrCat("sub-command TRANSFORM, action REPLACE: ",
+ this->ReplaceHelper.GetError(), "."));
+ }
+
+ return output;
+ }
+
+private:
+ cmStringReplaceHelper ReplaceHelper;
+};
+
+bool HandleTransformCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.size() < 3) {
+ status.SetError(
+ "sub-command TRANSFORM requires an action to be specified.");
+ return false;
+ }
+
+ // Structure collecting all elements of the command
+ struct Command
+ {
+ Command(const std::string& listName)
+ : ListName(listName)
+ , OutputName(listName)
+ {
+ }
+
+ std::string Name;
+ std::string ListName;
+ std::vector<std::string> Arguments;
+ std::unique_ptr<TransformAction> Action;
+ std::unique_ptr<TransformSelector> Selector;
+ std::string OutputName;
+ } command(args[1]);
+
+ // Descriptor of action
+ // Arity: number of arguments required for the action
+ // Transform: lambda function implementing the action
+ struct ActionDescriptor
+ {
+ ActionDescriptor(std::string name)
+ : Name(std::move(name))
+ {
+ }
+ ActionDescriptor(std::string name, int arity, transform_type transform)
+ : Name(std::move(name))
+ , Arity(arity)
+#if defined(__GNUC__) && __GNUC__ == 6 && defined(__aarch64__)
+ // std::function move constructor miscompiles on this architecture
+ , Transform(transform)
+#else
+ , Transform(std::move(transform))
+#endif
+ {
+ }
+
+ operator const std::string&() const { return Name; }
+
+ std::string Name;
+ int Arity = 0;
+ transform_type Transform;
+ };
+
+ // Build a set of supported actions.
+ std::set<ActionDescriptor,
+ std::function<bool(const std::string&, const std::string&)>>
+ descriptors(
+ [](const std::string& x, const std::string& y) { return x < y; });
+ descriptors = { { "APPEND", 1,
+ [&command](const std::string& s) -> std::string {
+ if (command.Selector->InSelection(s)) {
+ return s + command.Arguments[0];
+ }
+
+ return s;
+ } },
+ { "PREPEND", 1,
+ [&command](const std::string& s) -> std::string {
+ if (command.Selector->InSelection(s)) {
+ return command.Arguments[0] + s;
+ }
+
+ return s;
+ } },
+ { "TOUPPER", 0,
+ [&command](const std::string& s) -> std::string {
+ if (command.Selector->InSelection(s)) {
+ return cmSystemTools::UpperCase(s);
+ }
+
+ return s;
+ } },
+ { "TOLOWER", 0,
+ [&command](const std::string& s) -> std::string {
+ if (command.Selector->InSelection(s)) {
+ return cmSystemTools::LowerCase(s);
+ }
+
+ return s;
+ } },
+ { "STRIP", 0,
+ [&command](const std::string& s) -> std::string {
+ if (command.Selector->InSelection(s)) {
+ return cmTrimWhitespace(s);
+ }
+
+ return s;
+ } },
+ { "GENEX_STRIP", 0,
+ [&command](const std::string& s) -> std::string {
+ if (command.Selector->InSelection(s)) {
+ return cmGeneratorExpression::Preprocess(
+ s,
+ cmGeneratorExpression::StripAllGeneratorExpressions);
+ }
+
+ return s;
+ } },
+ { "REPLACE", 2,
+ [&command](const std::string& s) -> std::string {
+ if (command.Selector->InSelection(s)) {
+ return command.Action->Transform(s);
+ }
+
+ return s;
+ } } };
+
+ using size_type = std::vector<std::string>::size_type;
+ size_type index = 2;
+
+ // Parse all possible function parameters
+ auto descriptor = descriptors.find(args[index]);
+
+ if (descriptor == descriptors.end()) {
+ status.SetError(
+ cmStrCat(" sub-command TRANSFORM, ", args[index], " invalid action."));
+ return false;
+ }
+
+ // Action arguments
+ index += 1;
+ if (args.size() < index + descriptor->Arity) {
+ status.SetError(cmStrCat("sub-command TRANSFORM, action ",
+ descriptor->Name, " expects ", descriptor->Arity,
+ " argument(s)."));
+ return false;
+ }
+
+ command.Name = descriptor->Name;
+ index += descriptor->Arity;
+ if (descriptor->Arity > 0) {
+ command.Arguments =
+ std::vector<std::string>(args.begin() + 3, args.begin() + index);
+ }
+
+ if (command.Name == "REPLACE") {
+ try {
+ command.Action = cm::make_unique<TransformReplace>(
+ command.Arguments, &status.GetMakefile());
+ } catch (const transform_error& e) {
+ status.SetError(e.what());
+ return false;
+ }
+ }
+
+ const std::string REGEX{ "REGEX" };
+ const std::string AT{ "AT" };
+ const std::string FOR{ "FOR" };
+ const std::string OUTPUT_VARIABLE{ "OUTPUT_VARIABLE" };
+
+ // handle optional arguments
+ while (args.size() > index) {
+ if ((args[index] == REGEX || args[index] == AT || args[index] == FOR) &&
+ command.Selector) {
+ status.SetError(
+ cmStrCat("sub-command TRANSFORM, selector already specified (",
+ command.Selector->Tag, ")."));
+
+ return false;
+ }
+
+ // REGEX selector
+ if (args[index] == REGEX) {
+ if (args.size() == ++index) {
+ status.SetError("sub-command TRANSFORM, selector REGEX expects "
+ "'regular expression' argument.");
+ return false;
+ }
+
+ command.Selector = cm::make_unique<TransformSelectorRegex>(args[index]);
+ if (!command.Selector->Validate()) {
+ status.SetError(
+ cmStrCat("sub-command TRANSFORM, selector REGEX failed to compile "
+ "regex \"",
+ args[index], "\"."));
+ return false;
+ }
+
+ index += 1;
+ continue;
+ }
+
+ // AT selector
+ if (args[index] == AT) {
+ // get all specified indexes
+ std::vector<int> indexes;
+ while (args.size() > ++index) {
+ std::size_t pos;
+ int value;
+
+ try {
+ value = std::stoi(args[index], &pos);
+ if (pos != args[index].length()) {
+ // this is not a number, stop processing
+ break;
+ }
+ indexes.push_back(value);
+ } catch (const std::invalid_argument&) {
+ // this is not a number, stop processing
+ break;
+ }
+ }
+
+ if (indexes.empty()) {
+ status.SetError(
+ "sub-command TRANSFORM, selector AT expects at least one "
+ "numeric value.");
+ return false;
+ }
+
+ command.Selector =
+ cm::make_unique<TransformSelectorAt>(std::move(indexes));
+
+ continue;
+ }
+
+ // FOR selector
+ if (args[index] == FOR) {
+ if (args.size() <= ++index + 1) {
+ status.SetError(
+ "sub-command TRANSFORM, selector FOR expects, at least,"
+ " two arguments.");
+ return false;
+ }
+
+ int start = 0;
+ int stop = 0;
+ int step = 1;
+ bool valid = true;
+ try {
+ std::size_t pos;
+
+ start = std::stoi(args[index], &pos);
+ if (pos != args[index].length()) {
+ // this is not a number
+ valid = false;
+ } else {
+ stop = std::stoi(args[++index], &pos);
+ if (pos != args[index].length()) {
+ // this is not a number
+ valid = false;
+ }
+ }
+ } catch (const std::invalid_argument&) {
+ // this is not numbers
+ valid = false;
+ }
+ if (!valid) {
+ status.SetError("sub-command TRANSFORM, selector FOR expects, "
+ "at least, two numeric values.");
+ return false;
+ }
+ // try to read a third numeric value for step
+ if (args.size() > ++index) {
+ try {
+ std::size_t pos;
+
+ step = std::stoi(args[index], &pos);
+ if (pos != args[index].length()) {
+ // this is not a number
+ step = 1;
+ } else {
+ index += 1;
+ }
+ } catch (const std::invalid_argument&) {
+ // this is not number, ignore exception
+ }
+ }
+
+ if (step < 0) {
+ status.SetError("sub-command TRANSFORM, selector FOR expects "
+ "non negative numeric value for <step>.");
+ }
+
+ command.Selector =
+ cm::make_unique<TransformSelectorFor>(start, stop, step);
+
+ continue;
+ }
+
+ // output variable
+ if (args[index] == OUTPUT_VARIABLE) {
+ if (args.size() == ++index) {
+ status.SetError("sub-command TRANSFORM, OUTPUT_VARIABLE "
+ "expects variable name argument.");
+ return false;
+ }
+
+ command.OutputName = args[index++];
+ continue;
+ }
+
+ status.SetError(cmStrCat("sub-command TRANSFORM, '",
+ cmJoin(cmMakeRange(args).advance(index), " "),
+ "': unexpected argument(s)."));
+ return false;
+ }
+
+ // expand the list variable
+ std::vector<std::string> varArgsExpanded;
+ if (!GetList(varArgsExpanded, command.ListName, status.GetMakefile())) {
+ status.GetMakefile().AddDefinition(command.OutputName, "");
+ return true;
+ }
+
+ if (!command.Selector) {
+ // no selector specified, apply transformation to all elements
+ command.Selector = cm::make_unique<TransformNoSelector>();
+ }
+
+ try {
+ command.Selector->Transform(varArgsExpanded, descriptor->Transform);
+ } catch (const transform_error& e) {
+ status.SetError(e.what());
+ return false;
+ }
+
+ status.GetMakefile().AddDefinition(command.OutputName,
+ cmJoin(varArgsExpanded, ";"));
+
+ return true;
+}
+
+class cmStringSorter
+{
+public:
+ enum class Order
+ {
+ UNINITIALIZED,
+ ASCENDING,
+ DESCENDING,
+ };
+
+ enum class Compare
+ {
+ UNINITIALIZED,
+ STRING,
+ FILE_BASENAME,
+ };
+ enum class CaseSensitivity
+ {
+ UNINITIALIZED,
+ SENSITIVE,
+ INSENSITIVE,
+ };
+
+protected:
+ using StringFilter = std::string (*)(const std::string&);
+ StringFilter GetCompareFilter(Compare compare)
+ {
+ return (compare == Compare::FILE_BASENAME) ? cmSystemTools::GetFilenameName
+ : nullptr;
+ }
+
+ StringFilter GetCaseFilter(CaseSensitivity sensitivity)
+ {
+ return (sensitivity == CaseSensitivity::INSENSITIVE)
+ ? cmSystemTools::LowerCase
+ : nullptr;
+ }
+
+public:
+ cmStringSorter(Compare compare, CaseSensitivity caseSensitivity,
+ Order desc = Order::ASCENDING)
+ : filters{ GetCompareFilter(compare), GetCaseFilter(caseSensitivity) }
+ , descending(desc == Order::DESCENDING)
+ {
+ }
+
+ std::string ApplyFilter(const std::string& argument)
+ {
+ std::string result = argument;
+ for (auto filter : filters) {
+ if (filter != nullptr) {
+ result = filter(result);
+ }
+ }
+ return result;
+ }
+
+ bool operator()(const std::string& a, const std::string& b)
+ {
+ std::string af = ApplyFilter(a);
+ std::string bf = ApplyFilter(b);
+ bool result;
+ if (descending) {
+ result = bf < af;
+ } else {
+ result = af < bf;
+ }
+ return result;
+ }
+
+protected:
+ StringFilter filters[2] = { nullptr, nullptr };
+ bool descending;
+};
+
+bool HandleSortCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
assert(args.size() >= 2);
- if (args.size() > 2) {
- this->SetError("sub-command SORT only takes one argument.");
+ if (args.size() > 8) {
+ status.SetError("sub-command SORT only takes up to six arguments.");
return false;
}
+ auto sortCompare = cmStringSorter::Compare::UNINITIALIZED;
+ auto sortCaseSensitivity = cmStringSorter::CaseSensitivity::UNINITIALIZED;
+ auto sortOrder = cmStringSorter::Order::UNINITIALIZED;
+
+ size_t argumentIndex = 2;
+ const std::string messageHint = "sub-command SORT ";
+
+ while (argumentIndex < args.size()) {
+ const std::string option = args[argumentIndex++];
+ if (option == "COMPARE") {
+ if (sortCompare != cmStringSorter::Compare::UNINITIALIZED) {
+ std::string error = cmStrCat(messageHint, "option \"", option,
+ "\" has been specified multiple times.");
+ status.SetError(error);
+ return false;
+ }
+ if (argumentIndex < args.size()) {
+ const std::string argument = args[argumentIndex++];
+ if (argument == "STRING") {
+ sortCompare = cmStringSorter::Compare::STRING;
+ } else if (argument == "FILE_BASENAME") {
+ sortCompare = cmStringSorter::Compare::FILE_BASENAME;
+ } else {
+ std::string error =
+ cmStrCat(messageHint, "value \"", argument, "\" for option \"",
+ option, "\" is invalid.");
+ status.SetError(error);
+ return false;
+ }
+ } else {
+ status.SetError(cmStrCat(messageHint, "missing argument for option \"",
+ option, "\"."));
+ return false;
+ }
+ } else if (option == "CASE") {
+ if (sortCaseSensitivity !=
+ cmStringSorter::CaseSensitivity::UNINITIALIZED) {
+ status.SetError(cmStrCat(messageHint, "option \"", option,
+ "\" has been specified multiple times."));
+ return false;
+ }
+ if (argumentIndex < args.size()) {
+ const std::string argument = args[argumentIndex++];
+ if (argument == "SENSITIVE") {
+ sortCaseSensitivity = cmStringSorter::CaseSensitivity::SENSITIVE;
+ } else if (argument == "INSENSITIVE") {
+ sortCaseSensitivity = cmStringSorter::CaseSensitivity::INSENSITIVE;
+ } else {
+ status.SetError(cmStrCat(messageHint, "value \"", argument,
+ "\" for option \"", option,
+ "\" is invalid."));
+ return false;
+ }
+ } else {
+ status.SetError(cmStrCat(messageHint, "missing argument for option \"",
+ option, "\"."));
+ return false;
+ }
+ } else if (option == "ORDER") {
+
+ if (sortOrder != cmStringSorter::Order::UNINITIALIZED) {
+ status.SetError(cmStrCat(messageHint, "option \"", option,
+ "\" has been specified multiple times."));
+ return false;
+ }
+ if (argumentIndex < args.size()) {
+ const std::string argument = args[argumentIndex++];
+ if (argument == "ASCENDING") {
+ sortOrder = cmStringSorter::Order::ASCENDING;
+ } else if (argument == "DESCENDING") {
+ sortOrder = cmStringSorter::Order::DESCENDING;
+ } else {
+ status.SetError(cmStrCat(messageHint, "value \"", argument,
+ "\" for option \"", option,
+ "\" is invalid."));
+ return false;
+ }
+ } else {
+ status.SetError(cmStrCat(messageHint, "missing argument for option \"",
+ option, "\"."));
+ return false;
+ }
+ } else {
+ status.SetError(
+ cmStrCat(messageHint, "option \"", option, "\" is unknown."));
+ return false;
+ }
+ }
+ // set Default Values if Option is not given
+ if (sortCompare == cmStringSorter::Compare::UNINITIALIZED) {
+ sortCompare = cmStringSorter::Compare::STRING;
+ }
+ if (sortCaseSensitivity == cmStringSorter::CaseSensitivity::UNINITIALIZED) {
+ sortCaseSensitivity = cmStringSorter::CaseSensitivity::SENSITIVE;
+ }
+ if (sortOrder == cmStringSorter::Order::UNINITIALIZED) {
+ sortOrder = cmStringSorter::Order::ASCENDING;
+ }
+
const std::string& listName = args[1];
// expand the variable
std::vector<std::string> varArgsExpanded;
- if (!this->GetList(varArgsExpanded, listName)) {
- this->SetError("sub-command SORT requires list to be present.");
- return false;
+ if (!GetList(varArgsExpanded, listName, status.GetMakefile())) {
+ return true;
}
- std::sort(varArgsExpanded.begin(), varArgsExpanded.end());
+ if ((sortCompare == cmStringSorter::Compare::STRING) &&
+ (sortCaseSensitivity == cmStringSorter::CaseSensitivity::SENSITIVE) &&
+ (sortOrder == cmStringSorter::Order::ASCENDING)) {
+ std::sort(varArgsExpanded.begin(), varArgsExpanded.end());
+ } else {
+ cmStringSorter sorter(sortCompare, sortCaseSensitivity, sortOrder);
+ std::sort(varArgsExpanded.begin(), varArgsExpanded.end(), sorter);
+ }
std::string value = cmJoin(varArgsExpanded, ";");
- this->Makefile->AddDefinition(listName, value.c_str());
+ status.GetMakefile().AddDefinition(listName, value);
return true;
}
-bool cmListCommand::HandleRemoveAtCommand(std::vector<std::string> const& args)
+bool HandleSublistCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- if (args.size() < 3) {
- this->SetError("sub-command REMOVE_AT requires at least "
- "two arguments.");
+ if (args.size() != 5) {
+ status.SetError(cmStrCat("sub-command SUBLIST requires four arguments (",
+ args.size() - 1, " found)."));
return false;
}
const std::string& listName = args[1];
+ const std::string& variableName = args.back();
+
// expand the variable
std::vector<std::string> varArgsExpanded;
- if (!this->GetList(varArgsExpanded, listName)) {
- this->SetError("sub-command REMOVE_AT requires list to be present.");
+ if (!GetList(varArgsExpanded, listName, status.GetMakefile()) ||
+ varArgsExpanded.empty()) {
+ status.GetMakefile().AddDefinition(variableName, "");
+ return true;
+ }
+
+ const int start = atoi(args[2].c_str());
+ const int length = atoi(args[3].c_str());
+
+ using size_type = decltype(varArgsExpanded)::size_type;
+
+ if (start < 0 || size_type(start) >= varArgsExpanded.size()) {
+ status.SetError(cmStrCat("begin index: ", start, " is out of range 0 - ",
+ varArgsExpanded.size() - 1));
return false;
}
- // FIXME: Add policy to make non-existing lists an error like empty lists.
- if (varArgsExpanded.empty()) {
- this->SetError("REMOVE_AT given empty list");
+ if (length < -1) {
+ status.SetError(cmStrCat("length: ", length, " should be -1 or greater"));
+ return false;
+ }
+
+ const size_type end =
+ (length == -1 || size_type(start + length) > varArgsExpanded.size())
+ ? varArgsExpanded.size()
+ : size_type(start + length);
+ std::vector<std::string> sublist(varArgsExpanded.begin() + start,
+ varArgsExpanded.begin() + end);
+ status.GetMakefile().AddDefinition(variableName, cmJoin(sublist, ";"));
+ return true;
+}
+
+bool HandleRemoveAtCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.size() < 3) {
+ status.SetError("sub-command REMOVE_AT requires at least "
+ "two arguments.");
+ return false;
+ }
+
+ const std::string& listName = args[1];
+ // expand the variable
+ std::vector<std::string> varArgsExpanded;
+ if (!GetList(varArgsExpanded, listName, status.GetMakefile()) ||
+ varArgsExpanded.empty()) {
+ std::ostringstream str;
+ str << "index: ";
+ for (size_t i = 1; i < args.size(); ++i) {
+ str << args[i];
+ if (i != args.size() - 1) {
+ str << ", ";
+ }
+ }
+ str << " out of range (0, 0)";
+ status.SetError(str.str());
return false;
}
@@ -423,54 +1318,45 @@ bool cmListCommand::HandleRemoveAtCommand(std::vector<std::string> const& args)
for (cc = 2; cc < args.size(); ++cc) {
int item = atoi(args[cc].c_str());
if (item < 0) {
- item = (int)nitem + item;
+ item = static_cast<int>(nitem) + item;
}
- if (item < 0 || nitem <= (size_t)item) {
- std::ostringstream str;
- str << "index: " << item << " out of range (-" << nitem << ", "
- << nitem - 1 << ")";
- this->SetError(str.str());
+ if (item < 0 || nitem <= static_cast<size_t>(item)) {
+ status.SetError(cmStrCat("index: ", item, " out of range (-", nitem,
+ ", ", nitem - 1, ")"));
return false;
}
removed.push_back(static_cast<size_t>(item));
}
std::sort(removed.begin(), removed.end());
- std::vector<size_t>::const_iterator remEnd =
- std::unique(removed.begin(), removed.end());
- std::vector<size_t>::const_iterator remBegin = removed.begin();
+ auto remEnd = std::unique(removed.begin(), removed.end());
+ auto remBegin = removed.begin();
- std::vector<std::string>::const_iterator argsEnd =
+ auto argsEnd =
cmRemoveIndices(varArgsExpanded, cmMakeRange(remBegin, remEnd));
- std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin();
+ auto argsBegin = varArgsExpanded.cbegin();
std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";");
- this->Makefile->AddDefinition(listName, value.c_str());
+ status.GetMakefile().AddDefinition(listName, value);
return true;
}
-bool cmListCommand::HandleFilterCommand(std::vector<std::string> const& args)
+bool HandleFilterCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("sub-command FILTER requires a list to be specified.");
+ status.SetError("sub-command FILTER requires a list to be specified.");
return false;
}
if (args.size() < 3) {
- this->SetError("sub-command FILTER requires an operator to be specified.");
+ status.SetError(
+ "sub-command FILTER requires an operator to be specified.");
return false;
}
if (args.size() < 4) {
- this->SetError("sub-command FILTER requires a mode to be specified.");
- return false;
- }
-
- const std::string& listName = args[1];
- // expand the variable
- std::vector<std::string> varArgsExpanded;
- if (!this->GetList(varArgsExpanded, listName)) {
- this->SetError("sub-command FILTER requires list to be present.");
+ status.SetError("sub-command FILTER requires a mode to be specified.");
return false;
}
@@ -481,21 +1367,29 @@ bool cmListCommand::HandleFilterCommand(std::vector<std::string> const& args)
} else if (op == "EXCLUDE") {
includeMatches = false;
} else {
- this->SetError("sub-command FILTER does not recognize operator " + op);
+ status.SetError("sub-command FILTER does not recognize operator " + op);
return false;
}
+ const std::string& listName = args[1];
+ // expand the variable
+ std::vector<std::string> varArgsExpanded;
+ if (!GetList(varArgsExpanded, listName, status.GetMakefile())) {
+ return true;
+ }
+
const std::string& mode = args[3];
if (mode == "REGEX") {
if (args.size() != 5) {
- this->SetError("sub-command FILTER, mode REGEX "
- "requires five arguments.");
+ status.SetError("sub-command FILTER, mode REGEX "
+ "requires five arguments.");
return false;
}
- return this->FilterRegex(args, includeMatches, listName, varArgsExpanded);
+ return FilterRegex(args, includeMatches, listName, varArgsExpanded,
+ status);
}
- this->SetError("sub-command FILTER does not recognize mode " + mode);
+ status.SetError("sub-command FILTER does not recognize mode " + mode);
return false;
}
@@ -518,28 +1412,60 @@ private:
const bool includeMatches;
};
-bool cmListCommand::FilterRegex(std::vector<std::string> const& args,
- bool includeMatches,
- std::string const& listName,
- std::vector<std::string>& varArgsExpanded)
+bool FilterRegex(std::vector<std::string> const& args, bool includeMatches,
+ std::string const& listName,
+ std::vector<std::string>& varArgsExpanded,
+ cmExecutionStatus& status)
{
const std::string& pattern = args[4];
cmsys::RegularExpression regex(pattern);
if (!regex.is_valid()) {
- std::string error = "sub-command FILTER, mode REGEX ";
- error += "failed to compile regex \"";
- error += pattern;
- error += "\".";
- this->SetError(error);
+ std::string error =
+ cmStrCat("sub-command FILTER, mode REGEX failed to compile regex \"",
+ pattern, "\".");
+ status.SetError(error);
return false;
}
- std::vector<std::string>::iterator argsBegin = varArgsExpanded.begin();
- std::vector<std::string>::iterator argsEnd = varArgsExpanded.end();
- std::vector<std::string>::iterator newArgsEnd =
+ auto argsBegin = varArgsExpanded.begin();
+ auto argsEnd = varArgsExpanded.end();
+ auto newArgsEnd =
std::remove_if(argsBegin, argsEnd, MatchesRegex(regex, includeMatches));
std::string value = cmJoin(cmMakeRange(argsBegin, newArgsEnd), ";");
- this->Makefile->AddDefinition(listName, value.c_str());
+ status.GetMakefile().AddDefinition(listName, value);
return true;
}
+
+} // namespace
+
+bool cmListCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.size() < 2) {
+ status.SetError("must be called with at least two arguments.");
+ return false;
+ }
+
+ static cmSubcommandTable const subcommand{
+ { "LENGTH"_s, HandleLengthCommand },
+ { "GET"_s, HandleGetCommand },
+ { "APPEND"_s, HandleAppendCommand },
+ { "PREPEND"_s, HandlePrependCommand },
+ { "POP_BACK"_s, HandlePopBackCommand },
+ { "POP_FRONT"_s, HandlePopFrontCommand },
+ { "FIND"_s, HandleFindCommand },
+ { "INSERT"_s, HandleInsertCommand },
+ { "JOIN"_s, HandleJoinCommand },
+ { "REMOVE_AT"_s, HandleRemoveAtCommand },
+ { "REMOVE_ITEM"_s, HandleRemoveItemCommand },
+ { "REMOVE_DUPLICATES"_s, HandleRemoveDuplicatesCommand },
+ { "TRANSFORM"_s, HandleTransformCommand },
+ { "SORT"_s, HandleSortCommand },
+ { "SUBLIST"_s, HandleSublistCommand },
+ { "REVERSE"_s, HandleReverseCommand },
+ { "FILTER"_s, HandleFilterCommand },
+ };
+
+ return subcommand(args[0], args, status);
+}
diff --git a/Source/cmListCommand.h b/Source/cmListCommand.h
index 7789f7df1..274d9fdbd 100644
--- a/Source/cmListCommand.h
+++ b/Source/cmListCommand.h
@@ -3,52 +3,18 @@
#ifndef cmListCommand_h
#define cmListCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmListCommand
+/**
* \brief Common list operations
*
*/
-class cmListCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmListCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-protected:
- bool HandleLengthCommand(std::vector<std::string> const& args);
- bool HandleGetCommand(std::vector<std::string> const& args);
- bool HandleAppendCommand(std::vector<std::string> const& args);
- bool HandleFindCommand(std::vector<std::string> const& args);
- bool HandleInsertCommand(std::vector<std::string> const& args);
- bool HandleRemoveAtCommand(std::vector<std::string> const& args);
- bool HandleRemoveItemCommand(std::vector<std::string> const& args);
- bool HandleRemoveDuplicatesCommand(std::vector<std::string> const& args);
- bool HandleSortCommand(std::vector<std::string> const& args);
- bool HandleReverseCommand(std::vector<std::string> const& args);
- bool HandleFilterCommand(std::vector<std::string> const& args);
- bool FilterRegex(std::vector<std::string> const& args, bool includeMatches,
- std::string const& listName,
- std::vector<std::string>& varArgsExpanded);
-
- bool GetList(std::vector<std::string>& list, const std::string& var);
- bool GetListString(std::string& listString, const std::string& var);
-};
+bool cmListCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 0c73cd725..47679c932 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -2,23 +2,34 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmListFileCache.h"
+#include <cassert>
+#include <memory>
+#include <sstream>
+#include <utility>
+
#include "cmListFileLexer.h"
+#include "cmMessageType.h"
#include "cmMessenger.h"
-#include "cmOutputConverter.h"
#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmake.h"
-#include "cmConfigure.h"
-#include <algorithm>
-#include <assert.h>
-#include <sstream>
+cmCommandContext::cmCommandName& cmCommandContext::cmCommandName::operator=(
+ std::string const& name)
+{
+ this->Original = name;
+ this->Lower = cmSystemTools::LowerCase(name);
+ return *this;
+}
struct cmListFileParser
{
- cmListFileParser(cmListFile* lf, cmListFileBacktrace const& lfbt,
+ cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt,
cmMessenger* messenger, const char* filename);
~cmListFileParser();
+ cmListFileParser(const cmListFileParser&) = delete;
+ cmListFileParser& operator=(const cmListFileParser&) = delete;
void IssueFileOpenError(std::string const& text) const;
void IssueError(std::string const& text) const;
bool ParseFile();
@@ -39,12 +50,11 @@ struct cmListFileParser
} Separation;
};
-cmListFileParser::cmListFileParser(cmListFile* lf,
- cmListFileBacktrace const& lfbt,
+cmListFileParser::cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt,
cmMessenger* messenger,
const char* filename)
: ListFile(lf)
- , Backtrace(lfbt)
+ , Backtrace(std::move(lfbt))
, Messenger(messenger)
, FileName(filename)
, Lexer(cmListFileLexer_New())
@@ -58,7 +68,8 @@ cmListFileParser::~cmListFileParser()
void cmListFileParser::IssueFileOpenError(const std::string& text) const
{
- this->Messenger->IssueMessage(cmake::FATAL_ERROR, text, this->Backtrace);
+ this->Messenger->IssueMessage(MessageType::FATAL_ERROR, text,
+ this->Backtrace);
}
void cmListFileParser::IssueError(const std::string& text) const
@@ -68,7 +79,7 @@ void cmListFileParser::IssueError(const std::string& text) const
lfc.Line = cmListFileLexer_GetCurrentLine(this->Lexer);
cmListFileBacktrace lfbt = this->Backtrace;
lfbt = lfbt.Push(lfc);
- this->Messenger->IssueMessage(cmake::FATAL_ERROR, text, lfbt);
+ this->Messenger->IssueMessage(MessageType::FATAL_ERROR, text, lfbt);
cmSystemTools::SetFatalErrorOccured();
}
@@ -82,7 +93,7 @@ bool cmListFileParser::ParseFile()
}
if (bom == cmListFileLexer_BOM_Broken) {
- cmListFileLexer_SetFileName(this->Lexer, CM_NULLPTR, CM_NULLPTR);
+ cmListFileLexer_SetFileName(this->Lexer, nullptr, nullptr);
this->IssueFileOpenError("Error while reading Byte-Order-Mark. "
"File not seekable?");
return false;
@@ -90,7 +101,7 @@ bool cmListFileParser::ParseFile()
// Verify the Byte-Order-Mark, if any.
if (bom != cmListFileLexer_BOM_None && bom != cmListFileLexer_BOM_UTF8) {
- cmListFileLexer_SetFileName(this->Lexer, CM_NULLPTR, CM_NULLPTR);
+ cmListFileLexer_SetFileName(this->Lexer, nullptr, nullptr);
this->IssueFileOpenError(
"File starts with a Byte-Order-Mark that is not UTF-8.");
return false;
@@ -182,11 +193,9 @@ bool cmListFileParser::ParseFunction(const char* name, long line)
}
// Arguments.
- unsigned long lastLine;
unsigned long parenDepth = 0;
this->Separation = SeparationOkay;
- while ((lastLine = cmListFileLexer_GetCurrentLine(this->Lexer),
- token = cmListFileLexer_Scan(this->Lexer))) {
+ while ((token = cmListFileLexer_Scan(this->Lexer))) {
if (token->type == cmListFileLexer_Token_Space ||
token->type == cmListFileLexer_Token_Newline) {
this->Separation = SeparationOkay;
@@ -241,20 +250,19 @@ bool cmListFileParser::ParseFunction(const char* name, long line)
std::ostringstream error;
cmListFileContext lfc;
lfc.FilePath = this->FileName;
- lfc.Line = lastLine;
+ lfc.Line = line;
cmListFileBacktrace lfbt = this->Backtrace;
lfbt = lfbt.Push(lfc);
error << "Parse error. Function missing ending \")\". "
<< "End of file reached.";
- this->Messenger->IssueMessage(cmake::FATAL_ERROR, error.str(), lfbt);
+ this->Messenger->IssueMessage(MessageType::FATAL_ERROR, error.str(), lfbt);
return false;
}
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;
}
@@ -272,98 +280,74 @@ bool cmListFileParser::AddArgument(cmListFileLexer_Token* token,
<< "Argument not separated from preceding token by whitespace.";
/* clang-format on */
if (isError) {
- this->Messenger->IssueMessage(cmake::FATAL_ERROR, m.str(), lfbt);
+ this->Messenger->IssueMessage(MessageType::FATAL_ERROR, m.str(), lfbt);
return false;
}
- this->Messenger->IssueMessage(cmake::AUTHOR_WARNING, m.str(), lfbt);
+ this->Messenger->IssueMessage(MessageType::AUTHOR_WARNING, m.str(), lfbt);
return true;
}
-struct cmListFileBacktrace::Entry : public cmListFileContext
+// We hold either the bottom scope of a directory or a call/file context.
+// Discriminate these cases via the parent pointer.
+struct cmListFileBacktrace::Entry
{
- Entry(cmListFileContext const& lfc, Entry* up)
- : cmListFileContext(lfc)
- , Up(up)
- , RefCount(0)
+ Entry(cmStateSnapshot bottom)
+ : Bottom(bottom)
{
- if (this->Up) {
- this->Up->Ref();
- }
}
- ~Entry()
+
+ Entry(std::shared_ptr<Entry const> parent, cmListFileContext lfc)
+ : Context(std::move(lfc))
+ , Parent(std::move(parent))
{
- if (this->Up) {
- this->Up->Unref();
- }
}
- void Ref() { ++this->RefCount; }
- void Unref()
+
+ ~Entry()
{
- if (--this->RefCount == 0) {
- delete this;
+ if (this->Parent) {
+ this->Context.~cmListFileContext();
+ } else {
+ this->Bottom.~cmStateSnapshot();
}
}
- Entry* Up;
- unsigned int RefCount;
-};
-cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& bottom,
- Entry* up,
- cmListFileContext const& lfc)
- : Bottom(bottom)
- , Cur(new Entry(lfc, up))
-{
- assert(this->Bottom.IsValid());
- this->Cur->Ref();
-}
+ bool IsBottom() const { return !this->Parent; }
-cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& bottom,
- Entry* cur)
- : Bottom(bottom)
- , Cur(cur)
-{
- if (this->Cur) {
- assert(this->Bottom.IsValid());
- this->Cur->Ref();
- }
-}
-
-cmListFileBacktrace::cmListFileBacktrace()
- : Bottom()
- , Cur(CM_NULLPTR)
-{
-}
+ union
+ {
+ cmStateSnapshot Bottom;
+ cmListFileContext Context;
+ };
+ std::shared_ptr<Entry const> Parent;
+};
cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& snapshot)
- : Bottom(snapshot.GetCallStackBottom())
- , Cur(CM_NULLPTR)
+ : TopEntry(std::make_shared<Entry const>(snapshot.GetCallStackBottom()))
{
}
-cmListFileBacktrace::cmListFileBacktrace(cmListFileBacktrace const& r)
- : Bottom(r.Bottom)
- , Cur(r.Cur)
+/* NOLINTNEXTLINE(performance-unnecessary-value-param) */
+cmListFileBacktrace::cmListFileBacktrace(std::shared_ptr<Entry const> parent,
+ cmListFileContext const& lfc)
+ : TopEntry(std::make_shared<Entry const>(std::move(parent), lfc))
{
- if (this->Cur) {
- assert(this->Bottom.IsValid());
- this->Cur->Ref();
- }
}
-cmListFileBacktrace& cmListFileBacktrace::operator=(
- cmListFileBacktrace const& r)
+cmListFileBacktrace::cmListFileBacktrace(std::shared_ptr<Entry const> top)
+ : TopEntry(std::move(top))
{
- cmListFileBacktrace tmp(r);
- std::swap(this->Cur, tmp.Cur);
- std::swap(this->Bottom, tmp.Bottom);
- return *this;
}
-cmListFileBacktrace::~cmListFileBacktrace()
+cmStateSnapshot cmListFileBacktrace::GetBottom() const
{
- if (this->Cur) {
- this->Cur->Unref();
+ cmStateSnapshot bottom;
+ if (Entry const* cur = this->TopEntry.get()) {
+ while (Entry const* parent = cur->Parent.get()) {
+ cur = parent;
+ }
+ bottom = cur->Bottom;
}
+ return bottom;
}
cmListFileBacktrace cmListFileBacktrace::Push(std::string const& file) const
@@ -374,54 +358,60 @@ cmListFileBacktrace cmListFileBacktrace::Push(std::string const& file) const
// skipped during call stack printing.
cmListFileContext lfc;
lfc.FilePath = file;
- return cmListFileBacktrace(this->Bottom, this->Cur, lfc);
+ return this->Push(lfc);
}
cmListFileBacktrace cmListFileBacktrace::Push(
cmListFileContext const& lfc) const
{
- return cmListFileBacktrace(this->Bottom, this->Cur, lfc);
+ assert(this->TopEntry);
+ assert(!this->TopEntry->IsBottom() || this->TopEntry->Bottom.IsValid());
+ return cmListFileBacktrace(this->TopEntry, lfc);
}
cmListFileBacktrace cmListFileBacktrace::Pop() const
{
- assert(this->Cur);
- return cmListFileBacktrace(this->Bottom, this->Cur->Up);
+ assert(this->TopEntry);
+ assert(!this->TopEntry->IsBottom());
+ return cmListFileBacktrace(this->TopEntry->Parent);
}
cmListFileContext const& cmListFileBacktrace::Top() const
{
- if (this->Cur) {
- return *this->Cur;
- }
- static cmListFileContext const empty;
- return empty;
+ assert(this->TopEntry);
+ assert(!this->TopEntry->IsBottom());
+ return this->TopEntry->Context;
}
void cmListFileBacktrace::PrintTitle(std::ostream& out) const
{
- if (!this->Cur) {
+ // The title exists only if we have a call on top of the bottom.
+ if (!this->TopEntry || this->TopEntry->IsBottom()) {
return;
}
- cmOutputConverter converter(this->Bottom);
- cmListFileContext lfc = *this->Cur;
- if (!this->Bottom.GetState()->GetIsInTryCompile()) {
- lfc.FilePath = converter.ConvertToRelativePath(
- this->Bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
+ cmListFileContext lfc = this->TopEntry->Context;
+ cmStateSnapshot bottom = this->GetBottom();
+ if (!bottom.GetState()->GetIsInTryCompile()) {
+ lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfNotContained(
+ bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
}
out << (lfc.Line ? " at " : " in ") << lfc;
}
void cmListFileBacktrace::PrintCallStack(std::ostream& out) const
{
- if (!this->Cur || !this->Cur->Up) {
+ // The call stack exists only if we have at least two calls on top
+ // of the bottom.
+ if (!this->TopEntry || this->TopEntry->IsBottom() ||
+ this->TopEntry->Parent->IsBottom()) {
return;
}
bool first = true;
- cmOutputConverter converter(this->Bottom);
- for (Entry* i = this->Cur->Up; i; i = i->Up) {
- if (i->Name.empty()) {
+ cmStateSnapshot bottom = this->GetBottom();
+ for (Entry const* cur = this->TopEntry->Parent.get(); !cur->IsBottom();
+ cur = cur->Parent.get()) {
+ if (cur->Context.Name.empty()) {
// Skip this whole-file scope. When we get here we already will
// have printed a more-specific context within the file.
continue;
@@ -430,15 +420,31 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out) const
first = false;
out << "Call Stack (most recent call first):\n";
}
- cmListFileContext lfc = *i;
- if (!this->Bottom.GetState()->GetIsInTryCompile()) {
- lfc.FilePath = converter.ConvertToRelativePath(
- this->Bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
+ cmListFileContext lfc = cur->Context;
+ if (!bottom.GetState()->GetIsInTryCompile()) {
+ lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfNotContained(
+ bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
}
out << " " << lfc << "\n";
}
}
+size_t cmListFileBacktrace::Depth() const
+{
+ size_t depth = 0;
+ if (Entry const* cur = this->TopEntry.get()) {
+ for (; !cur->IsBottom(); cur = cur->Parent.get()) {
+ ++depth;
+ }
+ }
+ return depth;
+}
+
+bool cmListFileBacktrace::Empty() const
+{
+ return !this->TopEntry || this->TopEntry->IsBottom();
+}
+
std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc)
{
os << lfc.FilePath;
@@ -468,3 +474,20 @@ bool operator!=(const cmListFileContext& lhs, const cmListFileContext& rhs)
{
return !(lhs == rhs);
}
+
+std::ostream& operator<<(std::ostream& os, BT<std::string> const& s)
+{
+ return os << s.Value;
+}
+
+std::vector<BT<std::string>> ExpandListWithBacktrace(
+ std::string const& list, cmListFileBacktrace const& bt)
+{
+ std::vector<BT<std::string>> result;
+ std::vector<std::string> tmp = cmExpandedList(list);
+ result.reserve(tmp.size());
+ for (std::string& i : tmp) {
+ result.emplace_back(std::move(i), bt);
+ }
+ return result;
+}
diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h
index 349ddef91..9cae8277b 100644
--- a/Source/cmListFileCache.h
+++ b/Source/cmListFileCache.h
@@ -5,8 +5,11 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <iosfwd>
+#include <memory>
#include <string>
+#include <utility>
#include <vector>
#include "cmStateSnapshot.h"
@@ -22,11 +25,19 @@ class cmMessenger;
struct cmCommandContext
{
- std::string Name;
- long Line;
- cmCommandContext()
- : Name()
- , Line(0)
+ struct cmCommandName
+ {
+ std::string Lower;
+ std::string Original;
+ cmCommandName() = default;
+ cmCommandName(std::string const& name) { *this = name; }
+ cmCommandName& operator=(std::string const& name);
+ } Name;
+ long Line = 0;
+ cmCommandContext() = default;
+ cmCommandContext(const char* name, int line)
+ : Name(name)
+ , Line(line)
{
}
};
@@ -39,14 +50,9 @@ struct cmListFileArgument
Quoted,
Bracket
};
- cmListFileArgument()
- : Value()
- , Delim(Unquoted)
- , Line(0)
- {
- }
- cmListFileArgument(const std::string& v, Delimiter d, long line)
- : Value(v)
+ cmListFileArgument() = default;
+ cmListFileArgument(std::string v, Delimiter d, long line)
+ : Value(std::move(v))
, Delim(d)
, Line(line)
{
@@ -57,8 +63,8 @@ struct cmListFileArgument
}
bool operator!=(const cmListFileArgument& r) const { return !(*this == r); }
std::string Value;
- Delimiter Delim;
- long Line;
+ Delimiter Delim = Unquoted;
+ long Line = 0;
};
class cmListFileContext
@@ -66,13 +72,7 @@ class cmListFileContext
public:
std::string Name;
std::string FilePath;
- long Line;
- cmListFileContext()
- : Name()
- , FilePath()
- , Line(0)
- {
- }
+ long Line = 0;
static cmListFileContext FromCommandContext(cmCommandContext const& lfcc,
std::string const& fileName)
@@ -80,7 +80,7 @@ public:
cmListFileContext lfc;
lfc.FilePath = fileName;
lfc.Line = lfcc.Line;
- lfc.Name = lfcc.Name;
+ lfc.Name = lfcc.Name.Original;
return lfc;
}
};
@@ -103,18 +103,13 @@ public:
// Default-constructed backtrace may not be used until after
// set via assignment from a backtrace constructed with a
// valid snapshot.
- cmListFileBacktrace();
+ cmListFileBacktrace() = default;
// Construct an empty backtrace whose bottom sits in the directory
// indicated by the given valid snapshot.
cmListFileBacktrace(cmStateSnapshot const& snapshot);
- // Backtraces may be copied and assigned as values.
- cmListFileBacktrace(cmListFileBacktrace const& r);
- cmListFileBacktrace& operator=(cmListFileBacktrace const& r);
- ~cmListFileBacktrace();
-
- cmStateSnapshot GetBottom() const { return this->Bottom; }
+ cmStateSnapshot GetBottom() const;
// Get a backtrace with the given file scope added to the top.
// May not be called until after construction with a valid snapshot.
@@ -129,7 +124,7 @@ public:
cmListFileBacktrace Pop() const;
// Get the context at the top of the backtrace.
- // Returns an empty context if the backtrace is empty.
+ // This may be called only if Empty() would return false.
cmListFileContext const& Top() const;
// Print the top of the backtrace.
@@ -138,16 +133,52 @@ 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;
+
+ // Return true if this backtrace is empty.
+ bool Empty() const;
+
private:
struct Entry;
-
- cmStateSnapshot Bottom;
- Entry* Cur;
- cmListFileBacktrace(cmStateSnapshot const& bottom, Entry* up,
+ std::shared_ptr<Entry const> TopEntry;
+ cmListFileBacktrace(std::shared_ptr<Entry const> parent,
cmListFileContext const& lfc);
- cmListFileBacktrace(cmStateSnapshot const& bottom, Entry* cur);
+ cmListFileBacktrace(std::shared_ptr<Entry const> top);
};
+// Wrap type T as a value with a backtrace. For purposes of
+// ordering and equality comparison, only the original value is
+// used. The backtrace is considered incidental.
+template <typename T>
+class BT
+{
+public:
+ BT(T v = T(), cmListFileBacktrace bt = cmListFileBacktrace())
+ : Value(std::move(v))
+ , Backtrace(std::move(bt))
+ {
+ }
+ T Value;
+ cmListFileBacktrace Backtrace;
+ friend bool operator==(BT<T> const& l, BT<T> const& r)
+ {
+ return l.Value == r.Value;
+ }
+ friend bool operator<(BT<T> const& l, BT<T> const& r)
+ {
+ return l.Value < r.Value;
+ }
+ friend bool operator==(BT<T> const& l, T const& r) { return l.Value == r; }
+ friend bool operator==(T const& l, BT<T> const& r) { return l == r.Value; }
+};
+
+std::ostream& operator<<(std::ostream& os, BT<std::string> const& s);
+
+std::vector<BT<std::string>> ExpandListWithBacktrace(
+ std::string const& list,
+ cmListFileBacktrace const& bt = cmListFileBacktrace());
+
struct cmListFile
{
bool ParseFile(const char* path, cmMessenger* messenger,
diff --git a/Source/cmListFileLexer.h b/Source/cmListFileLexer.h
index f243010ad..ec6b3cd77 100644
--- a/Source/cmListFileLexer.h
+++ b/Source/cmListFileLexer.h
@@ -3,7 +3,13 @@
#ifndef cmListFileLexer_h
#define cmListFileLexer_h
-typedef enum cmListFileLexer_Type_e {
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOLINTNEXTLINE(modernize-use-using) */
+typedef enum cmListFileLexer_Type_e
+{
cmListFileLexer_Token_None,
cmListFileLexer_Token_Space,
cmListFileLexer_Token_Newline,
@@ -19,6 +25,7 @@ typedef enum cmListFileLexer_Type_e {
cmListFileLexer_Token_BadString
} cmListFileLexer_Type;
+/* NOLINTNEXTLINE(modernize-use-using) */
typedef struct cmListFileLexer_Token_s cmListFileLexer_Token;
struct cmListFileLexer_Token_s
{
@@ -39,14 +46,13 @@ enum cmListFileLexer_BOM_e
cmListFileLexer_BOM_UTF32BE,
cmListFileLexer_BOM_UTF32LE
};
+
+/* NOLINTNEXTLINE(modernize-use-using) */
typedef enum cmListFileLexer_BOM_e cmListFileLexer_BOM;
+/* NOLINTNEXTLINE(modernize-use-using) */
typedef struct cmListFileLexer_s cmListFileLexer;
-#ifdef __cplusplus
-extern "C" {
-#endif
-
cmListFileLexer* cmListFileLexer_New(void);
int cmListFileLexer_SetFileName(cmListFileLexer*, const char*,
cmListFileLexer_BOM* bom);
diff --git a/Source/cmLoadCacheCommand.cxx b/Source/cmLoadCacheCommand.cxx
index 00a30bf0e..1184bcb58 100644
--- a/Source/cmLoadCacheCommand.cxx
+++ b/Source/cmLoadCacheCommand.cxx
@@ -2,42 +2,48 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLoadCacheCommand.h"
+#include <set>
+
#include "cmsys/FStream.hxx"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmake.h"
-class cmExecutionStatus;
+static bool ReadWithPrefix(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+
+static void CheckLine(cmMakefile& mf, std::string const& prefix,
+ std::set<std::string> const& variablesToRead,
+ const char* line);
-// cmLoadCacheCommand
-bool cmLoadCacheCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmLoadCacheCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with wrong number of arguments.");
+ status.SetError("called with wrong number of arguments.");
}
if (args.size() >= 2 && args[1] == "READ_WITH_PREFIX") {
- return this->ReadWithPrefix(args);
+ return ReadWithPrefix(args, status);
}
// Cache entries to be excluded from the import list.
// If this set is empty, all cache entries are brought in
// and they can not be overridden.
bool excludeFiles = false;
- unsigned int i;
std::set<std::string> excludes;
- for (i = 0; i < args.size(); i++) {
+ for (std::string const& arg : args) {
if (excludeFiles) {
- excludes.insert(args[i]);
+ excludes.insert(arg);
}
- if (args[i] == "EXCLUDE") {
+ if (arg == "EXCLUDE") {
excludeFiles = true;
}
- if (excludeFiles && (args[i] == "INCLUDE_INTERNALS")) {
+ if (excludeFiles && (arg == "INCLUDE_INTERNALS")) {
break;
}
}
@@ -48,54 +54,58 @@ bool cmLoadCacheCommand::InitialPass(std::vector<std::string> const& args,
bool includeFiles = false;
std::set<std::string> includes;
- for (i = 0; i < args.size(); i++) {
+ for (std::string const& arg : args) {
if (includeFiles) {
- includes.insert(args[i]);
+ includes.insert(arg);
}
- if (args[i] == "INCLUDE_INTERNALS") {
+ if (arg == "INCLUDE_INTERNALS") {
includeFiles = true;
}
- if (includeFiles && (args[i] == "EXCLUDE")) {
+ if (includeFiles && (arg == "EXCLUDE")) {
break;
}
}
+ cmMakefile& mf = status.GetMakefile();
+
// Loop over each build directory listed in the arguments. Each
// directory has a cache file.
- for (i = 0; i < args.size(); i++) {
- if ((args[i] == "EXCLUDE") || (args[i] == "INCLUDE_INTERNALS")) {
+ for (std::string const& arg : args) {
+ if ((arg == "EXCLUDE") || (arg == "INCLUDE_INTERNALS")) {
break;
}
- this->Makefile->GetCMakeInstance()->LoadCache(args[i], false, excludes,
- includes);
+ mf.GetCMakeInstance()->LoadCache(arg, false, excludes, includes);
}
return true;
}
-bool cmLoadCacheCommand::ReadWithPrefix(std::vector<std::string> const& args)
+static bool ReadWithPrefix(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
// Make sure we have a prefix.
if (args.size() < 3) {
- this->SetError("READ_WITH_PREFIX form must specify a prefix.");
+ status.SetError("READ_WITH_PREFIX form must specify a prefix.");
return false;
}
// 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);
+ status.SetError(e);
return false;
}
// Prepare the table of variables to read.
- this->Prefix = args[2];
- this->VariablesToRead.insert(args.begin() + 3, args.end());
+ std::string const prefix = args[2];
+ std::set<std::string> const variablesToRead(args.begin() + 3, args.end());
// Read the cache file.
cmsys::ifstream fin(cacheFile.c_str());
+ cmMakefile& mf = status.GetMakefile();
+
// This is a big hack read loop to overcome a buggy ifstream
// implementation on HP-UX. This should work on all platforms even
// for small buffer sizes.
@@ -124,8 +134,8 @@ bool cmLoadCacheCommand::ReadWithPrefix(std::vector<std::string> const& args)
}
if (i != end) {
// Completed a line.
- this->CheckLine(line.c_str());
- line = "";
+ CheckLine(mf, prefix, variablesToRead, line.c_str());
+ line.clear();
// Skip the newline character.
++i;
@@ -135,13 +145,15 @@ bool cmLoadCacheCommand::ReadWithPrefix(std::vector<std::string> const& args)
}
if (!line.empty()) {
// Partial last line.
- this->CheckLine(line.c_str());
+ CheckLine(mf, prefix, variablesToRead, line.c_str());
}
return true;
}
-void cmLoadCacheCommand::CheckLine(const char* line)
+static void CheckLine(cmMakefile& mf, std::string const& prefix,
+ std::set<std::string> const& variablesToRead,
+ const char* line)
{
// Check one line of the cache file.
std::string var;
@@ -149,14 +161,14 @@ void cmLoadCacheCommand::CheckLine(const char* line)
cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED;
if (cmake::ParseCacheEntry(line, var, value, type)) {
// Found a real entry. See if this one was requested.
- if (this->VariablesToRead.find(var) != this->VariablesToRead.end()) {
+ if (variablesToRead.find(var) != variablesToRead.end()) {
// This was requested. Set this variable locally with the given
// prefix.
- var = this->Prefix + var;
+ var = prefix + var;
if (!value.empty()) {
- this->Makefile->AddDefinition(var, value.c_str());
+ mf.AddDefinition(var, value);
} else {
- this->Makefile->RemoveDefinition(var);
+ mf.RemoveDefinition(var);
}
}
}
diff --git a/Source/cmLoadCacheCommand.h b/Source/cmLoadCacheCommand.h
index 1a8a0fc4c..7cee6637c 100644
--- a/Source/cmLoadCacheCommand.h
+++ b/Source/cmLoadCacheCommand.h
@@ -3,42 +3,14 @@
#ifndef cmLoadCacheCommand_h
#define cmLoadCacheCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include <set>
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmLoadCacheCommand
- * \brief load a cache file
- *
- * cmLoadCacheCommand loads the non internal values of a cache file
- */
-class cmLoadCacheCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmLoadCacheCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-protected:
- std::set<std::string> VariablesToRead;
- std::string Prefix;
-
- bool ReadWithPrefix(std::vector<std::string> const& args);
- void CheckLine(const char* line);
-};
+bool cmLoadCacheCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx
index 92a32a147..23ace649a 100644
--- a/Source/cmLoadCommandCommand.cxx
+++ b/Source/cmLoadCommandCommand.cxx
@@ -2,49 +2,121 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLoadCommandCommand.h"
-#include <signal.h>
-#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <csignal>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <utility>
+
+#include <cm/memory>
-#include "cmCPluginAPI.cxx"
#include "cmCPluginAPI.h"
+#include "cmCommand.h"
#include "cmDynamicLoader.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmState.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
+#include "cmCPluginAPI.cxx"
#ifdef __QNX__
-#include <malloc.h> /* for malloc/free on QNX */
+# include <malloc.h> /* for malloc/free on QNX */
#endif
-extern "C" void TrapsForSignalsCFunction(int sig);
+namespace {
+
+const char* LastName = nullptr;
+
+extern "C" void TrapsForSignals(int sig)
+{
+ fprintf(stderr, "CMake loaded command %s crashed with signal: %d.\n",
+ LastName, sig);
+}
+
+struct SignalHandlerGuard
+{
+ explicit SignalHandlerGuard(const char* name)
+ {
+ LastName = name != nullptr ? name : "????";
+
+ signal(SIGSEGV, TrapsForSignals);
+#ifdef SIGBUS
+ signal(SIGBUS, TrapsForSignals);
+#endif
+ signal(SIGILL, TrapsForSignals);
+ }
+
+ ~SignalHandlerGuard()
+ {
+ signal(SIGSEGV, nullptr);
+#ifdef SIGBUS
+ signal(SIGBUS, nullptr);
+#endif
+ signal(SIGILL, nullptr);
+ }
+
+ SignalHandlerGuard(SignalHandlerGuard const&) = delete;
+ SignalHandlerGuard& operator=(SignalHandlerGuard const&) = delete;
+};
+
+struct LoadedCommandImpl : cmLoadedCommandInfo
+{
+ explicit LoadedCommandImpl(CM_INIT_FUNCTION init)
+ : cmLoadedCommandInfo{ 0, 0, &cmStaticCAPI, 0,
+ nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr }
+ {
+ init(this);
+ }
+
+ ~LoadedCommandImpl()
+ {
+ if (this->Destructor) {
+ SignalHandlerGuard guard(this->Name);
+ this->Destructor(this);
+ }
+ if (this->Error != nullptr) {
+ free(this->Error);
+ }
+ }
+
+ LoadedCommandImpl(LoadedCommandImpl const&) = delete;
+ LoadedCommandImpl& operator=(LoadedCommandImpl const&) = delete;
+
+ int DoInitialPass(cmMakefile* mf, int argc, char* argv[])
+ {
+ SignalHandlerGuard guard(this->Name);
+ return this->InitialPass(this, mf, argc, argv);
+ }
+
+ void DoFinalPass(cmMakefile* mf)
+ {
+ SignalHandlerGuard guard(this->Name);
+ this->FinalPass(this, mf);
+ }
+};
// a class for loadabple commands
class cmLoadedCommand : public cmCommand
{
public:
- cmLoadedCommand()
+ cmLoadedCommand() = default;
+ explicit cmLoadedCommand(CM_INIT_FUNCTION init)
+ : Impl(std::make_shared<LoadedCommandImpl>(init))
{
- memset(&this->info, 0, sizeof(this->info));
- this->info.CAPI = &cmStaticCAPI;
}
- ///! clean up any memory allocated by the plugin
- ~cmLoadedCommand() CM_OVERRIDE;
-
/**
* This is a virtual constructor for the command.
*/
- cmCommand* Clone() CM_OVERRIDE
+ std::unique_ptr<cmCommand> Clone() override
{
- cmLoadedCommand* newC = new cmLoadedCommand;
+ auto newC = cm::make_unique<cmLoadedCommand>();
// we must copy when we clone
- memcpy(&newC->info, &this->info, sizeof(info));
- return newC;
+ newC->Impl = this->Impl;
+ return std::unique_ptr<cmCommand>(std::move(newC));
}
/**
@@ -52,121 +124,58 @@ public:
* the CMakeLists.txt file.
*/
bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&) CM_OVERRIDE;
-
- /**
- * This is called at the end after all the information
- * specified by the command is accumulated. Most commands do
- * not implement this method. At this point, reading and
- * writing to the cache can be done.
- */
- void FinalPass() CM_OVERRIDE;
- bool HasFinalPass() const CM_OVERRIDE
- {
- return this->info.FinalPass != CM_NULLPTR;
- }
-
- static const char* LastName;
- static void TrapsForSignals(int sig)
- {
- fprintf(stderr, "CMake loaded command %s crashed with signal: %d.\n",
- cmLoadedCommand::LastName, sig);
- }
- static void InstallSignalHandlers(const char* name, int remove = 0)
- {
- cmLoadedCommand::LastName = name;
- if (!name) {
- cmLoadedCommand::LastName = "????";
- }
-
- if (!remove) {
- signal(SIGSEGV, TrapsForSignalsCFunction);
-#ifdef SIGBUS
- signal(SIGBUS, TrapsForSignalsCFunction);
-#endif
- signal(SIGILL, TrapsForSignalsCFunction);
- } else {
- signal(SIGSEGV, CM_NULLPTR);
-#ifdef SIGBUS
- signal(SIGBUS, CM_NULLPTR);
-#endif
- signal(SIGILL, CM_NULLPTR);
- }
- }
+ cmExecutionStatus&) override;
- cmLoadedCommandInfo info;
+private:
+ std::shared_ptr<LoadedCommandImpl> Impl;
};
-extern "C" void TrapsForSignalsCFunction(int sig)
-{
- cmLoadedCommand::TrapsForSignals(sig);
-}
-
-const char* cmLoadedCommand::LastName = CM_NULLPTR;
-
bool cmLoadedCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus&)
{
- if (!info.InitialPass) {
+ if (!this->Impl->InitialPass) {
return true;
}
// clear the error string
- if (this->info.Error) {
- free(this->info.Error);
+ if (this->Impl->Error) {
+ free(this->Impl->Error);
}
// create argc and argv and then invoke the command
int argc = static_cast<int>(args.size());
- char** argv = CM_NULLPTR;
+ char** argv = nullptr;
if (argc) {
- argv = (char**)malloc(argc * sizeof(char*));
+ argv = static_cast<char**>(malloc(argc * sizeof(char*)));
}
int i;
for (i = 0; i < argc; ++i) {
argv[i] = strdup(args[i].c_str());
}
- cmLoadedCommand::InstallSignalHandlers(info.Name);
- int result =
- info.InitialPass((void*)&info, (void*)this->Makefile, argc, argv);
- cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
+ int result = this->Impl->DoInitialPass(this->Makefile, argc, argv);
cmFreeArguments(argc, argv);
if (result) {
+ if (this->Impl->FinalPass) {
+ auto impl = this->Impl;
+ this->Makefile->AddFinalAction(
+ [impl](cmMakefile& makefile) { impl->DoFinalPass(&makefile); });
+ }
return true;
}
/* Initial Pass must have failed so set the error string */
- if (this->info.Error) {
- this->SetError(this->info.Error);
+ if (this->Impl->Error) {
+ this->SetError(this->Impl->Error);
}
return false;
}
-void cmLoadedCommand::FinalPass()
-{
- if (this->info.FinalPass) {
- cmLoadedCommand::InstallSignalHandlers(info.Name);
- this->info.FinalPass((void*)&this->info, (void*)this->Makefile);
- cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
- }
-}
-
-cmLoadedCommand::~cmLoadedCommand()
-{
- if (this->info.Destructor) {
- cmLoadedCommand::InstallSignalHandlers(info.Name);
- this->info.Destructor((void*)&this->info);
- cmLoadedCommand::InstallSignalHandlers(info.Name, 1);
- }
- if (this->info.Error) {
- free(this->info.Error);
- }
-}
+} // namespace
// cmLoadCommandCommand
-bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmLoadCommandCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
return true;
@@ -174,16 +183,14 @@ bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args,
// Construct a variable to report what file was loaded, if any.
// Start by removing the definition in case of failure.
- std::string reportVar = "CMAKE_LOADED_COMMAND_";
- reportVar += args[0];
- this->Makefile->RemoveDefinition(reportVar);
+ std::string reportVar = cmStrCat("CMAKE_LOADED_COMMAND_", args[0]);
+ status.GetMakefile().RemoveDefinition(reportVar);
// the file must exist
- std::string moduleName =
- this->Makefile->GetRequiredDefinition("CMAKE_SHARED_MODULE_PREFIX");
- moduleName += "cm" + args[0];
- moduleName +=
- this->Makefile->GetRequiredDefinition("CMAKE_SHARED_MODULE_SUFFIX");
+ std::string moduleName = cmStrCat(
+ status.GetMakefile().GetRequiredDefinition("CMAKE_SHARED_MODULE_PREFIX"),
+ "cm", args[0],
+ status.GetMakefile().GetRequiredDefinition("CMAKE_SHARED_MODULE_SUFFIX"));
// search for the file
std::vector<std::string> path;
@@ -198,10 +205,9 @@ bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args,
// Try to find the program.
std::string fullPath = cmSystemTools::FindFile(moduleName, path);
- if (fullPath == "") {
- std::ostringstream e;
- e << "Attempt to load command failed from file \"" << moduleName << "\"";
- this->SetError(e.str());
+ if (fullPath.empty()) {
+ status.SetError(cmStrCat("Attempt to load command failed from file \"",
+ moduleName, "\""));
return false;
}
@@ -209,42 +215,38 @@ bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args,
cmsys::DynamicLoader::LibraryHandle lib =
cmDynamicLoader::OpenLibrary(fullPath.c_str());
if (!lib) {
- std::string err = "Attempt to load the library ";
- err += fullPath + " failed.";
+ std::string err =
+ cmStrCat("Attempt to load the library ", fullPath, " failed.");
const char* error = cmsys::DynamicLoader::LastError();
if (error) {
err += " Additional error info is:\n";
err += error;
}
- this->SetError(err);
+ status.SetError(err);
return false;
}
// Report what file was loaded for this command.
- this->Makefile->AddDefinition(reportVar, fullPath.c_str());
+ status.GetMakefile().AddDefinition(reportVar, fullPath);
// find the init function
std::string initFuncName = args[0] + "Init";
- CM_INIT_FUNCTION initFunction =
- (CM_INIT_FUNCTION)cmsys::DynamicLoader::GetSymbolAddress(lib,
- initFuncName);
+ CM_INIT_FUNCTION initFunction = reinterpret_cast<CM_INIT_FUNCTION>(
+ cmsys::DynamicLoader::GetSymbolAddress(lib, initFuncName));
if (!initFunction) {
- initFuncName = "_";
- initFuncName += args[0];
- initFuncName += "Init";
- initFunction = (CM_INIT_FUNCTION)(
+ initFuncName = cmStrCat('_', args[0], "Init");
+ initFunction = reinterpret_cast<CM_INIT_FUNCTION>(
cmsys::DynamicLoader::GetSymbolAddress(lib, initFuncName));
}
// if the symbol is found call it to set the name on the
// function blocker
if (initFunction) {
- // create a function blocker and set it up
- cmLoadedCommand* f = new cmLoadedCommand();
- (*initFunction)(&f->info);
- this->Makefile->GetState()->AddScriptedCommand(args[0], f);
+ status.GetMakefile().GetState()->AddScriptedCommand(
+ args[0],
+ cmLegacyCommandWrapper(cm::make_unique<cmLoadedCommand>(initFunction)));
return true;
}
- this->SetError("Attempt to load command failed. "
- "No init function found.");
+ status.SetError("Attempt to load command failed. "
+ "No init function found.");
return false;
}
diff --git a/Source/cmLoadCommandCommand.h b/Source/cmLoadCommandCommand.h
index 030786e3d..f5fd754b1 100644
--- a/Source/cmLoadCommandCommand.h
+++ b/Source/cmLoadCommandCommand.h
@@ -3,21 +3,14 @@
#ifndef cmLoadCommandCommand_h
#define cmLoadCommandCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmLoadCommandCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE { return new cmLoadCommandCommand; }
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmLoadCommandCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx
index 6524db401..f86955dd0 100644
--- a/Source/cmLocalCommonGenerator.cxx
+++ b/Source/cmLocalCommonGenerator.cxx
@@ -2,19 +2,20 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalCommonGenerator.h"
+#include <utility>
#include <vector>
#include "cmGeneratorTarget.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
+#include "cmStringAlgorithms.h"
class cmGlobalGenerator;
cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg,
- cmMakefile* mf,
- std::string const& wd)
+ cmMakefile* mf, std::string wd)
: cmLocalGenerator(gg, mf)
- , WorkingDirectory(wd)
+ , WorkingDirectory(std::move(wd))
{
// Store the configuration name that will be generated.
if (const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) {
@@ -22,13 +23,11 @@ cmLocalCommonGenerator::cmLocalCommonGenerator(cmGlobalGenerator* gg,
this->ConfigName = config;
} else {
// No configuration type given.
- this->ConfigName = "";
+ this->ConfigName.clear();
}
}
-cmLocalCommonGenerator::~cmLocalCommonGenerator()
-{
-}
+cmLocalCommonGenerator::~cmLocalCommonGenerator() = default;
std::string cmLocalCommonGenerator::GetTargetFortranFlags(
cmGeneratorTarget const* target, std::string const& config)
@@ -36,27 +35,24 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags(
std::string flags;
// Enable module output if necessary.
- if (const char* modout_flag =
- this->Makefile->GetDefinition("CMAKE_Fortran_MODOUT_FLAG")) {
- this->AppendFlags(flags, modout_flag);
- }
+ this->AppendFlags(
+ flags, this->Makefile->GetSafeDefinition("CMAKE_Fortran_MODOUT_FLAG"));
// Add a module output directory flag if necessary.
std::string mod_dir =
target->GetFortranModuleDirectory(this->WorkingDirectory);
if (!mod_dir.empty()) {
mod_dir = this->ConvertToOutputFormat(
- this->ConvertToRelativePath(this->WorkingDirectory, mod_dir),
+ this->MaybeConvertToRelativePath(this->WorkingDirectory, mod_dir),
cmOutputConverter::SHELL);
} else {
mod_dir =
this->Makefile->GetSafeDefinition("CMAKE_Fortran_MODDIR_DEFAULT");
}
if (!mod_dir.empty()) {
- const char* moddir_flag =
- this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG");
- std::string modflag = moddir_flag;
- modflag += mod_dir;
+ std::string modflag = cmStrCat(
+ this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG"),
+ mod_dir);
this->AppendFlags(flags, modflag);
}
@@ -67,13 +63,27 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags(
this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG")) {
std::vector<std::string> includes;
this->GetIncludeDirectories(includes, target, "C", config);
- for (std::vector<std::string>::const_iterator idi = includes.begin();
- idi != includes.end(); ++idi) {
- std::string flg = modpath_flag;
- flg += this->ConvertToOutputFormat(*idi, cmOutputConverter::SHELL);
+ for (std::string const& id : includes) {
+ std::string flg =
+ cmStrCat(modpath_flag,
+ this->ConvertToOutputFormat(id, cmOutputConverter::SHELL));
this->AppendFlags(flags, flg);
}
}
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 a5afcd87d..eaef6ab53 100644
--- a/Source/cmLocalCommonGenerator.h
+++ b/Source/cmLocalCommonGenerator.h
@@ -3,8 +3,9 @@
#ifndef cmLocalCommonGenerator_h
#define cmLocalCommonGenerator_h
-#include "cmConfigure.h"
+#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.
@@ -20,15 +22,19 @@ class cmLocalCommonGenerator : public cmLocalGenerator
{
public:
cmLocalCommonGenerator(cmGlobalGenerator* gg, cmMakefile* mf,
- std::string const& wd);
- ~cmLocalCommonGenerator() CM_OVERRIDE;
+ std::string wd);
+ ~cmLocalCommonGenerator() override;
- std::string const& GetConfigName() { return this->ConfigName; }
+ std::string const& GetConfigName() const { return this->ConfigName; }
std::string GetWorkingDirectory() const { return this->WorkingDirectory; }
std::string GetTargetFortranFlags(cmGeneratorTarget const* target,
- std::string const& config) CM_OVERRIDE;
+ 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 6ce31c5ea..ffd46d454 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -2,10 +2,16 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalGenerator.h"
+#include "cmsys/RegularExpression.hxx"
+
#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
+#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
+#include "cmCustomCommandLines.h"
+#include "cmCustomCommandTypes.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionEvaluationFile.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -13,35 +19,44 @@
#include "cmInstallScriptGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmLinkLineComputer.h"
+#include "cmLinkLineDeviceComputer.h"
#include "cmMakefile.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
+#include "cmSourceFileLocation.h"
+#include "cmSourceFileLocationKind.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTestGenerator.h"
#include "cmVersion.h"
#include "cmake.h"
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#define CM_LG_ENCODE_OBJECT_NAMES
-#include "cmCryptoHash.h"
+#if !defined(CMAKE_BOOTSTRAP)
+# define CM_LG_ENCODE_OBJECT_NAMES
+# include "cmCryptoHash.h"
#endif
-#include "cmsys/RegularExpression.hxx"
#include <algorithm>
-#include <assert.h>
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <initializer_list>
#include <iterator>
#include <sstream>
-#include <stdio.h>
-#include <string.h>
+#include <unordered_set>
#include <utility>
+#include <vector>
+
+#include <cm/string_view>
#if defined(__HAIKU__)
-#include <FindDirectory.h>
-#include <StorageDefs.h>
+# include <FindDirectory.h>
+# include <StorageDefs.h>
#endif
// List of variables that are replaced when
@@ -49,24 +64,23 @@
// replaced in the form <var> with GetSafeDefinition(var).
// ${LANG} is replaced in the variable first with all enabled
// languages.
-static const char* ruleReplaceVars[] = {
- "CMAKE_${LANG}_COMPILER",
- "CMAKE_SHARED_LIBRARY_CREATE_${LANG}_FLAGS",
- "CMAKE_SHARED_MODULE_CREATE_${LANG}_FLAGS",
- "CMAKE_SHARED_MODULE_${LANG}_FLAGS",
- "CMAKE_SHARED_LIBRARY_${LANG}_FLAGS",
- "CMAKE_${LANG}_LINK_FLAGS",
- "CMAKE_SHARED_LIBRARY_SONAME_${LANG}_FLAG",
- "CMAKE_${LANG}_ARCHIVE",
- "CMAKE_AR",
- "CMAKE_CURRENT_SOURCE_DIR",
- "CMAKE_CURRENT_BINARY_DIR",
- "CMAKE_RANLIB",
- "CMAKE_LINKER",
- "CMAKE_CUDA_HOST_COMPILER",
- "CMAKE_CUDA_HOST_LINK_LAUNCHER",
- "CMAKE_CL_SHOWINCLUDES_PREFIX"
-};
+static auto ruleReplaceVars = { "CMAKE_${LANG}_COMPILER",
+ "CMAKE_SHARED_LIBRARY_CREATE_${LANG}_FLAGS",
+ "CMAKE_SHARED_MODULE_CREATE_${LANG}_FLAGS",
+ "CMAKE_SHARED_MODULE_${LANG}_FLAGS",
+ "CMAKE_SHARED_LIBRARY_${LANG}_FLAGS",
+ "CMAKE_${LANG}_LINK_FLAGS",
+ "CMAKE_SHARED_LIBRARY_SONAME_${LANG}_FLAG",
+ "CMAKE_${LANG}_ARCHIVE",
+ "CMAKE_AR",
+ "CMAKE_CURRENT_SOURCE_DIR",
+ "CMAKE_CURRENT_BINARY_DIR",
+ "CMAKE_RANLIB",
+ "CMAKE_LINKER",
+ "CMAKE_MT",
+ "CMAKE_CUDA_HOST_COMPILER",
+ "CMAKE_CUDA_HOST_LINK_LAUNCHER",
+ "CMAKE_CL_SHOWINCLUDES_PREFIX" };
cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
: cmOutputConverter(makefile->GetStateSnapshot())
@@ -85,6 +99,19 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
this->ComputeObjectMaxPath();
+ // Canonicalize entries of the CPATH environment variable the same
+ // way detection of CMAKE_<LANG>_IMPLICIT_INCLUDE_DIRECTORIES does.
+ {
+ std::vector<std::string> cpath;
+ cmSystemTools::GetPath(cpath, "CPATH");
+ for (std::string& cp : cpath) {
+ if (cmSystemTools::FileIsFullPath(cp)) {
+ cp = cmSystemTools::CollapseFullPath(cp);
+ this->EnvCPATH.emplace(std::move(cp));
+ }
+ }
+ }
+
std::vector<std::string> enabledLanguages =
this->GetState()->GetEnabledLanguages();
@@ -102,9 +129,7 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
this->LinkerSysroot = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
}
- for (std::vector<std::string>::iterator i = enabledLanguages.begin();
- i != enabledLanguages.end(); ++i) {
- std::string const& lang = *i;
+ for (std::string const& lang : enabledLanguages) {
if (lang == "NONE") {
continue;
}
@@ -137,15 +162,13 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
this->VariableMappings[compilerOptionSysroot] =
this->Makefile->GetSafeDefinition(compilerOptionSysroot);
- for (const char* const* replaceIter = cmArrayBegin(ruleReplaceVars);
- replaceIter != cmArrayEnd(ruleReplaceVars); ++replaceIter) {
- std::string actualReplace = *replaceIter;
- if (actualReplace.find("${LANG}") != std::string::npos) {
- cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang);
+ for (std::string replaceVar : ruleReplaceVars) {
+ if (replaceVar.find("${LANG}") != std::string::npos) {
+ cmSystemTools::ReplaceString(replaceVar, "${LANG}", lang);
}
- this->VariableMappings[actualReplace] =
- this->Makefile->GetSafeDefinition(actualReplace);
+ this->VariableMappings[replaceVar] =
+ this->Makefile->GetSafeDefinition(replaceVar);
}
}
}
@@ -164,7 +187,7 @@ cmLocalGenerator::~cmLocalGenerator()
cmDeleteAll(this->OwnedImportedGeneratorTargets);
}
-void cmLocalGenerator::IssueMessage(cmake::MessageType t,
+void cmLocalGenerator::IssueMessage(MessageType t,
std::string const& text) const
{
this->GetCMakeInstance()->IssueMessage(t, text, this->DirectoryBacktrace);
@@ -189,38 +212,63 @@ void cmLocalGenerator::ComputeObjectMaxPath()
w << "CMAKE_OBJECT_PATH_MAX is set to " << pmax
<< ", which is less than the minimum of 128. "
<< "The value will be ignored.";
- this->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ this->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
}
} else {
std::ostringstream w;
w << "CMAKE_OBJECT_PATH_MAX is set to \"" << plen
<< "\", which fails to parse as a positive integer. "
<< "The value will be ignored.";
- this->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ this->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
}
}
this->ObjectMaxPathViolations.clear();
}
-void cmLocalGenerator::TraceDependencies()
+static void MoveSystemIncludesToEnd(std::vector<std::string>& includeDirs,
+ const std::string& config,
+ const std::string& lang,
+ const cmGeneratorTarget* target)
{
- std::vector<std::string> configs;
- this->Makefile->GetConfigurations(configs);
- if (configs.empty()) {
- configs.push_back("");
+ if (!target) {
+ return;
}
- for (std::vector<std::string>::const_iterator ci = configs.begin();
- ci != configs.end(); ++ci) {
- this->GlobalGenerator->CreateEvaluationSourceFiles(*ci);
+
+ std::stable_sort(
+ includeDirs.begin(), includeDirs.end(),
+ [&target, &config, &lang](std::string const& a, std::string const& b) {
+ return !target->IsSystemIncludeDirectory(a, config, lang) &&
+ target->IsSystemIncludeDirectory(b, config, lang);
+ });
+}
+
+static void MoveSystemIncludesToEnd(std::vector<BT<std::string>>& includeDirs,
+ const std::string& config,
+ const std::string& lang,
+ const cmGeneratorTarget* target)
+{
+ if (!target) {
+ return;
}
+
+ std::stable_sort(includeDirs.begin(), includeDirs.end(),
+ [target, &config, &lang](BT<std::string> const& a,
+ BT<std::string> const& b) {
+ return !target->IsSystemIncludeDirectory(a.Value, config,
+ lang) &&
+ target->IsSystemIncludeDirectory(b.Value, config, lang);
+ });
+}
+
+void cmLocalGenerator::TraceDependencies()
+{
// Generate the rule files for each target.
- std::vector<cmGeneratorTarget*> targets = this->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator t = targets.begin();
- t != targets.end(); ++t) {
- if ((*t)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets();
+ for (cmGeneratorTarget* target : targets) {
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
- (*t)->TraceDependencies();
+ target->TraceDependencies();
}
}
@@ -235,11 +283,11 @@ void cmLocalGenerator::GenerateTestFiles()
const std::string& config =
this->Makefile->GetConfigurations(configurationTypes, false);
- std::string file = this->StateSnapshot.GetDirectory().GetCurrentBinary();
- file += "/";
- file += "CTestTestfile.cmake";
+ std::string file =
+ cmStrCat(this->StateSnapshot.GetDirectory().GetCurrentBinary(),
+ "/CTestTestfile.cmake");
- cmGeneratedFileStream fout(file.c_str());
+ cmGeneratedFileStream fout(file);
fout.SetCopyIfDifferent(true);
fout << "# CMake generated Testfile for " << std::endl
@@ -259,50 +307,81 @@ void cmLocalGenerator::GenerateTestFiles()
fout << "include(\"" << testIncludeFile << "\")" << std::endl;
}
+ const char* testIncludeFiles =
+ this->Makefile->GetProperty("TEST_INCLUDE_FILES");
+ if (testIncludeFiles) {
+ std::vector<std::string> includesList = cmExpandedList(testIncludeFiles);
+ for (std::string const& i : includesList) {
+ fout << "include(\"" << i << "\")" << std::endl;
+ }
+ }
+
// Ask each test generator to write its code.
std::vector<cmTestGenerator*> const& testers =
this->Makefile->GetTestGenerators();
- for (std::vector<cmTestGenerator*>::const_iterator gi = testers.begin();
- gi != testers.end(); ++gi) {
- (*gi)->Compute(this);
- (*gi)->Generate(fout, config, configurationTypes);
+ for (cmTestGenerator* tester : testers) {
+ tester->Compute(this);
+ tester->Generate(fout, config, configurationTypes);
}
- typedef std::vector<cmStateSnapshot> vec_t;
+ using vec_t = std::vector<cmStateSnapshot>;
vec_t const& children = this->Makefile->GetStateSnapshot().GetChildren();
std::string parentBinDir = this->GetCurrentBinaryDirectory();
- for (vec_t::const_iterator i = children.begin(); i != children.end(); ++i) {
+ for (cmStateSnapshot const& i : children) {
// TODO: Use add_subdirectory instead?
- std::string outP = i->GetDirectory().GetCurrentBinary();
- outP = this->ConvertToRelativePath(parentBinDir, outP);
+ std::string outP = i.GetDirectory().GetCurrentBinary();
+ outP = this->MaybeConvertToRelativePath(parentBinDir, outP);
outP = cmOutputConverter::EscapeForCMake(outP);
fout << "subdirs(" << outP << ")" << std::endl;
}
+
+ // Add directory labels property
+ const char* directoryLabels =
+ this->Makefile->GetDefinition("CMAKE_DIRECTORY_LABELS");
+ const char* labels = this->Makefile->GetProperty("LABELS");
+
+ if (labels || directoryLabels) {
+ fout << "set_directory_properties(PROPERTIES LABELS ";
+ if (labels) {
+ fout << cmOutputConverter::EscapeForCMake(labels);
+ }
+ if (labels && directoryLabels) {
+ fout << ";";
+ }
+ if (directoryLabels) {
+ fout << cmOutputConverter::EscapeForCMake(directoryLabels);
+ }
+ fout << ")" << std::endl;
+ }
+}
+
+void cmLocalGenerator::CreateEvaluationFileOutputs()
+{
+ std::vector<std::string> const& configs =
+ this->Makefile->GetGeneratorConfigs();
+ for (std::string const& c : configs) {
+ this->CreateEvaluationFileOutputs(c);
+ }
}
void cmLocalGenerator::CreateEvaluationFileOutputs(std::string const& config)
{
std::vector<cmGeneratorExpressionEvaluationFile*> ef =
this->Makefile->GetEvaluationFiles();
- for (std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator li =
- ef.begin();
- li != ef.end(); ++li) {
- (*li)->CreateOutputFile(this, config);
+ for (cmGeneratorExpressionEvaluationFile* geef : ef) {
+ geef->CreateOutputFile(this, config);
}
}
void cmLocalGenerator::ProcessEvaluationFiles(
std::vector<std::string>& generatedFiles)
{
- std::vector<cmGeneratorExpressionEvaluationFile*> ef =
- this->Makefile->GetEvaluationFiles();
- for (std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator li =
- ef.begin();
- li != ef.end(); ++li) {
- (*li)->Generate(this);
+ for (cmGeneratorExpressionEvaluationFile* geef :
+ this->Makefile->GetEvaluationFiles()) {
+ geef->Generate(this);
if (cmSystemTools::GetFatalErrorOccured()) {
return;
}
- std::vector<std::string> files = (*li)->GetFiles();
+ std::vector<std::string> files = geef->GetFiles();
std::sort(files.begin(), files.end());
std::vector<std::string> intersection;
@@ -311,15 +390,15 @@ void cmLocalGenerator::ProcessEvaluationFiles(
std::back_inserter(intersection));
if (!intersection.empty()) {
cmSystemTools::Error("Files to be generated by multiple different "
- "commands: ",
- cmWrap('"', intersection, '"', " ").c_str());
+ "commands: " +
+ cmWrap('"', intersection, '"', " "));
return;
}
- generatedFiles.insert(generatedFiles.end(), files.begin(), files.end());
- std::vector<std::string>::iterator newIt =
- generatedFiles.end() - files.size();
- std::inplace_merge(generatedFiles.begin(), newIt, generatedFiles.end());
+ cmAppend(generatedFiles, files);
+ std::inplace_merge(generatedFiles.begin(),
+ generatedFiles.end() - files.size(),
+ generatedFiles.end());
}
}
@@ -327,6 +406,7 @@ void cmLocalGenerator::GenerateInstallRules()
{
// Compute the install prefix.
const char* prefix = this->Makefile->GetDefinition("CMAKE_INSTALL_PREFIX");
+
#if defined(_WIN32) && !defined(__CYGWIN__)
std::string prefix_win32;
if (!prefix) {
@@ -370,12 +450,11 @@ void cmLocalGenerator::GenerateInstallRules()
// Choose a default install configuration.
std::string default_config = config;
const char* default_order[] = { "RELEASE", "MINSIZEREL", "RELWITHDEBINFO",
- "DEBUG", CM_NULLPTR };
+ "DEBUG", nullptr };
for (const char** c = default_order; *c && default_config.empty(); ++c) {
- for (std::vector<std::string>::iterator i = configurationTypes.begin();
- i != configurationTypes.end(); ++i) {
- if (cmSystemTools::UpperCase(*i) == *c) {
- default_config = *i;
+ for (std::string const& configurationType : configurationTypes) {
+ if (cmSystemTools::UpperCase(configurationType) == *c) {
+ default_config = configurationType;
}
}
}
@@ -391,7 +470,7 @@ void cmLocalGenerator::GenerateInstallRules()
toplevel_install = 1;
}
file += "/cmake_install.cmake";
- cmGeneratedFileStream fout(file.c_str());
+ cmGeneratedFileStream fout(file);
fout.SetCopyIfDifferent(true);
// Write the header.
@@ -402,7 +481,7 @@ void cmLocalGenerator::GenerateInstallRules()
<< "if(NOT DEFINED CMAKE_INSTALL_PREFIX)" << std::endl
<< " set(CMAKE_INSTALL_PREFIX \"" << prefix << "\")" << std::endl
<< "endif()" << std::endl
- << "string(REGEX REPLACE \"/$\" \"\" CMAKE_INSTALL_PREFIX "
+ << R"(string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX )"
<< "\"${CMAKE_INSTALL_PREFIX}\")" << std::endl
<< std::endl;
@@ -451,35 +530,90 @@ void cmLocalGenerator::GenerateInstallRules()
/* clang-format on */
}
+ // Copy cmake cross compile state to install code.
+ if (const char* crosscompiling =
+ this->Makefile->GetDefinition("CMAKE_CROSSCOMPILING")) {
+ /* clang-format off */
+ fout <<
+ "# Is this installation the result of a crosscompile?\n"
+ "if(NOT DEFINED CMAKE_CROSSCOMPILING)\n"
+ " set(CMAKE_CROSSCOMPILING \"" << crosscompiling << "\")\n"
+ "endif()\n"
+ "\n";
+ /* 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.
+ cmPolicies::PolicyStatus status = this->GetPolicyStatus(cmPolicies::CMP0082);
std::vector<cmInstallGenerator*> const& installers =
this->Makefile->GetInstallGenerators();
- for (std::vector<cmInstallGenerator*>::const_iterator gi =
- installers.begin();
- gi != installers.end(); ++gi) {
- (*gi)->Generate(fout, config, configurationTypes);
+ bool haveSubdirectoryInstall = false;
+ bool haveInstallAfterSubdirectory = false;
+ if (status == cmPolicies::WARN) {
+ for (cmInstallGenerator* installer : installers) {
+ installer->CheckCMP0082(haveSubdirectoryInstall,
+ haveInstallAfterSubdirectory);
+ installer->Generate(fout, config, configurationTypes);
+ }
+ } else {
+ for (cmInstallGenerator* installer : installers) {
+ installer->Generate(fout, config, configurationTypes);
+ }
}
// Write rules from old-style specification stored in targets.
this->GenerateTargetInstallRules(fout, config, configurationTypes);
// Include install scripts from subdirectories.
- std::vector<cmStateSnapshot> children =
- this->Makefile->GetStateSnapshot().GetChildren();
- if (!children.empty()) {
- fout << "if(NOT CMAKE_INSTALL_LOCAL_ONLY)\n";
- fout << " # Include the install script for each subdirectory.\n";
- for (std::vector<cmStateSnapshot>::const_iterator ci = children.begin();
- ci != children.end(); ++ci) {
- if (!ci->GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
- std::string odir = ci->GetDirectory().GetCurrentBinary();
- cmSystemTools::ConvertToUnixSlashes(odir);
- fout << " include(\"" << odir << "/cmake_install.cmake\")"
- << std::endl;
+ switch (status) {
+ case cmPolicies::WARN:
+ if (haveInstallAfterSubdirectory &&
+ this->Makefile->PolicyOptionalWarningEnabled(
+ "CMAKE_POLICY_WARNING_CMP0082")) {
+ std::ostringstream e;
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0082) << "\n";
+ this->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
}
- }
- fout << "\n";
- fout << "endif()\n\n";
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD: {
+ std::vector<cmStateSnapshot> children =
+ this->Makefile->GetStateSnapshot().GetChildren();
+ if (!children.empty()) {
+ fout << "if(NOT CMAKE_INSTALL_LOCAL_ONLY)\n";
+ fout << " # Include the install script for each subdirectory.\n";
+ for (cmStateSnapshot const& c : children) {
+ if (!c.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+ std::string odir = c.GetDirectory().GetCurrentBinary();
+ cmSystemTools::ConvertToUnixSlashes(odir);
+ fout << " include(\"" << odir << "/cmake_install.cmake\")"
+ << std::endl;
+ }
+ }
+ fout << "\n";
+ fout << "endif()\n\n";
+ }
+ } break;
+
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // NEW behavior is handled in
+ // cmInstallSubdirectoryGenerator::GenerateScript()
+ break;
}
// Record the install manifest.
@@ -504,12 +638,13 @@ void cmLocalGenerator::GenerateInstallRules()
void cmLocalGenerator::AddGeneratorTarget(cmGeneratorTarget* gt)
{
this->GeneratorTargets.push_back(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);
}
@@ -518,32 +653,14 @@ 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
{
- std::vector<cmGeneratorTarget*>::const_iterator ti =
- std::find_if(this->GeneratorTargets.begin(), this->GeneratorTargets.end(),
- NamedGeneratorTargetFinder(name));
- if (ti != this->GeneratorTargets.end()) {
- return *ti;
+ auto ti = this->GeneratorTargetSearchIndex.find(name);
+ if (ti != this->GeneratorTargetSearchIndex.end()) {
+ return ti->second;
}
- return CM_NULLPTR;
+ return nullptr;
}
void cmLocalGenerator::ComputeTargetManifest()
@@ -552,21 +669,17 @@ 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.
- std::vector<cmGeneratorTarget*> targets = this->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator t = targets.begin();
- t != targets.end(); ++t) {
- cmGeneratorTarget* target = *t;
+ const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets();
+ for (cmGeneratorTarget* target : targets) {
if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
- for (std::vector<std::string>::iterator ci = configNames.begin();
- ci != configNames.end(); ++ci) {
- const char* config = ci->c_str();
- target->ComputeTargetManifest(config);
+ for (std::string const& c : configNames) {
+ target->ComputeTargetManifest(c);
}
}
}
@@ -577,20 +690,61 @@ bool cmLocalGenerator::ComputeTargetCompileFeatures()
std::vector<std::string> configNames;
this->Makefile->GetConfigurations(configNames);
if (configNames.empty()) {
- configNames.push_back("");
+ configNames.emplace_back();
+ }
+
+ using LanguagePair = std::pair<std::string, std::string>;
+ std::vector<LanguagePair> pairedLanguages{ { "OBJC", "C" },
+ { "OBJCXX", "CXX" } };
+ std::set<LanguagePair> objcEnabledLanguages;
+ for (auto const& lang : pairedLanguages) {
+ if (this->Makefile->GetState()->GetLanguageEnabled(lang.first)) {
+ objcEnabledLanguages.insert(lang);
+ }
}
// Process compile features of all targets.
- std::vector<cmGeneratorTarget*> targets = this->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator t = targets.begin();
- t != targets.end(); ++t) {
- cmGeneratorTarget* target = *t;
- for (std::vector<std::string>::iterator ci = configNames.begin();
- ci != configNames.end(); ++ci) {
- if (!target->ComputeCompileFeatures(*ci)) {
+ const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets();
+ for (cmGeneratorTarget* target : targets) {
+ for (std::string const& c : configNames) {
+ if (!target->ComputeCompileFeatures(c)) {
return false;
}
}
+
+ // Now that C/C++ _STANDARD values have been computed
+ // set the values to ObjC/ObjCXX _STANDARD variables
+ if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ auto copyStandardToObjLang = [&](LanguagePair const& lang) -> bool {
+ if (!target->GetProperty(cmStrCat(lang.first, "_STANDARD"))) {
+ auto* standard =
+ target->GetProperty(cmStrCat(lang.second, "_STANDARD"));
+ if (!standard) {
+ standard = this->Makefile->GetDefinition(
+ cmStrCat("CMAKE_", lang.second, "_STANDARD_DEFAULT"));
+ }
+ target->Target->SetProperty(cmStrCat(lang.first, "_STANDARD"),
+ standard);
+ return true;
+ }
+ return false;
+ };
+ auto copyPropertyToObjLang = [&](LanguagePair const& lang,
+ const char* property) {
+ if (!target->GetProperty(cmStrCat(lang.first, property)) &&
+ target->GetProperty(cmStrCat(lang.second, property))) {
+ target->Target->SetProperty(
+ cmStrCat(lang.first, property),
+ target->GetProperty(cmStrCat(lang.second, property)));
+ }
+ };
+ for (auto const& lang : objcEnabledLanguages) {
+ if (copyStandardToObjLang(lang)) {
+ copyPropertyToObjLang(lang, "_STANDARD_REQUIRED");
+ copyPropertyToObjLang(lang, "_EXTENSIONS");
+ }
+ }
+ }
}
return true;
@@ -628,7 +782,7 @@ std::string cmLocalGenerator::ConvertToIncludeReference(
}
std::string cmLocalGenerator::GetIncludeFlags(
- const std::vector<std::string>& includes, cmGeneratorTarget* target,
+ const std::vector<std::string>& includeDirs, cmGeneratorTarget* target,
const std::string& lang, bool forceFullPaths, bool forResponseFile,
const std::string& config)
{
@@ -636,15 +790,16 @@ std::string cmLocalGenerator::GetIncludeFlags(
return "";
}
+ std::vector<std::string> includes = includeDirs;
+ MoveSystemIncludesToEnd(includes, config, lang, target);
+
OutputFormat shellFormat = forResponseFile ? RESPONSE : SHELL;
std::ostringstream includeFlags;
- std::string flagVar = "CMAKE_INCLUDE_FLAG_";
- flagVar += lang;
- const char* includeFlag = this->Makefile->GetSafeDefinition(flagVar);
- flagVar = "CMAKE_INCLUDE_FLAG_SEP_";
- flagVar += lang;
- const char* sep = this->Makefile->GetDefinition(flagVar);
+ std::string const& includeFlag =
+ this->Makefile->GetSafeDefinition(cmStrCat("CMAKE_INCLUDE_FLAG_", lang));
+ const char* sep =
+ this->Makefile->GetDefinition(cmStrCat("CMAKE_INCLUDE_FLAG_SEP_", lang));
bool quotePaths = false;
if (this->Makefile->GetDefinition("CMAKE_QUOTE_INCLUDE_PATHS")) {
quotePaths = true;
@@ -661,39 +816,30 @@ std::string cmLocalGenerator::GetIncludeFlags(
// Support special system include flag if it is available and the
// normal flag is repeated for each directory.
- std::string sysFlagVar = "CMAKE_INCLUDE_SYSTEM_FLAG_";
- sysFlagVar += lang;
- const char* sysIncludeFlag = CM_NULLPTR;
+ const char* sysIncludeFlag = nullptr;
if (repeatFlag) {
- sysIncludeFlag = this->Makefile->GetDefinition(sysFlagVar);
+ sysIncludeFlag = this->Makefile->GetDefinition(
+ cmStrCat("CMAKE_INCLUDE_SYSTEM_FLAG_", lang));
}
- std::string fwSearchFlagVar = "CMAKE_";
- fwSearchFlagVar += lang;
- fwSearchFlagVar += "_FRAMEWORK_SEARCH_FLAG";
- const char* fwSearchFlag = this->Makefile->GetDefinition(fwSearchFlagVar);
-
- std::string sysFwSearchFlagVar = "CMAKE_";
- sysFwSearchFlagVar += lang;
- sysFwSearchFlagVar += "_SYSTEM_FRAMEWORK_SEARCH_FLAG";
- const char* sysFwSearchFlag =
- this->Makefile->GetDefinition(sysFwSearchFlagVar);
+ const char* fwSearchFlag = this->Makefile->GetDefinition(
+ cmStrCat("CMAKE_", lang, "_FRAMEWORK_SEARCH_FLAG"));
+ const char* sysFwSearchFlag = this->Makefile->GetDefinition(
+ cmStrCat("CMAKE_", lang, "_SYSTEM_FRAMEWORK_SEARCH_FLAG"));
bool flagUsed = false;
std::set<std::string> emitted;
#ifdef __APPLE__
emitted.insert("/System/Library/Frameworks");
#endif
- std::vector<std::string>::const_iterator i;
- for (i = includes.begin(); i != includes.end(); ++i) {
+ for (std::string const& i : includes) {
if (fwSearchFlag && *fwSearchFlag && this->Makefile->IsOn("APPLE") &&
- cmSystemTools::IsPathToFramework(i->c_str())) {
- std::string frameworkDir = *i;
- frameworkDir += "/../";
- frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir);
+ cmSystemTools::IsPathToFramework(i)) {
+ std::string const frameworkDir =
+ cmSystemTools::CollapseFullPath(cmStrCat(i, "/../"));
if (emitted.insert(frameworkDir).second) {
if (sysFwSearchFlag && target &&
- target->IsSystemIncludeDirectory(*i, config)) {
+ target->IsSystemIncludeDirectory(i, config, lang)) {
includeFlags << sysFwSearchFlag;
} else {
includeFlags << fwSearchFlag;
@@ -706,7 +852,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;
@@ -714,35 +860,35 @@ std::string cmLocalGenerator::GetIncludeFlags(
flagUsed = true;
}
std::string includePath =
- this->ConvertToIncludeReference(*i, shellFormat, forceFullPaths);
- if (quotePaths && !includePath.empty() && includePath[0] != '\"') {
+ this->ConvertToIncludeReference(i, shellFormat, forceFullPaths);
+ if (quotePaths && !includePath.empty() && includePath.front() != '\"') {
includeFlags << "\"";
}
includeFlags << includePath;
- if (quotePaths && !includePath.empty() && includePath[0] != '\"') {
+ if (quotePaths && !includePath.empty() && includePath.front() != '\"') {
includeFlags << "\"";
}
includeFlags << sep;
}
std::string flags = includeFlags.str();
// remove trailing separators
- if ((sep[0] != ' ') && !flags.empty() && flags[flags.size() - 1] == sep[0]) {
- flags[flags.size() - 1] = ' ';
+ if ((sep[0] != ' ') && !flags.empty() && flags.back() == sep[0]) {
+ flags.back() = ' ';
}
return flags;
}
-void cmLocalGenerator::AddCompileDefinitions(std::set<std::string>& defines,
- cmGeneratorTarget const* target,
- const std::string& config,
- const std::string& lang) const
+void cmLocalGenerator::AddCompileOptions(std::string& flags,
+ cmGeneratorTarget* target,
+ const std::string& lang,
+ const std::string& config)
{
- std::vector<std::string> targetDefines;
- target->GetCompileDefinitions(targetDefines, config, lang);
- this->AppendDefines(defines, targetDefines);
+ std::vector<BT<std::string>> tmpFlags;
+ this->AddCompileOptions(tmpFlags, target, lang, config);
+ this->AppendFlags(flags, tmpFlags);
}
-void cmLocalGenerator::AddCompileOptions(std::string& flags,
+void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags,
cmGeneratorTarget* target,
const std::string& lang,
const std::string& config)
@@ -752,74 +898,116 @@ 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")) {
+ std::vector<std::string> opts;
cmSystemTools::ParseWindowsCommandLine(targetFlags, opts);
- }
- target->GetCompileOptions(opts, config, lang);
- for (std::vector<std::string>::const_iterator i = opts.begin();
- i != opts.end(); ++i) {
- if (r.find(i->c_str())) {
- // (Re-)Escape this flag. COMPILE_FLAGS were already parsed
- // as a command line above, and COMPILE_OPTIONS are escaped.
- this->AppendFlagEscape(flags, *i);
+ // Re-escape these flags since COMPILE_FLAGS were already parsed
+ // as a command line above.
+ std::string compileOpts;
+ this->AppendCompileOptions(compileOpts, opts, langFlagRegexStr);
+ if (!compileOpts.empty()) {
+ flags.emplace_back(std::move(compileOpts));
}
}
+ std::vector<BT<std::string>> targetCompileOpts =
+ target->GetCompileOptions(config, lang);
+ // COMPILE_OPTIONS are escaped.
+ this->AppendCompileOptions(flags, targetCompileOpts, langFlagRegexStr);
} else {
// Use all flags.
if (const char* targetFlags = target->GetProperty("COMPILE_FLAGS")) {
// COMPILE_FLAGS are not escaped for historical reasons.
- this->AppendFlags(flags, targetFlags);
- }
- std::vector<std::string> opts;
- target->GetCompileOptions(opts, config, lang);
- for (std::vector<std::string>::const_iterator i = opts.begin();
- i != opts.end(); ++i) {
- // COMPILE_OPTIONS are escaped.
- this->AppendFlagEscape(flags, *i);
+ std::string compileFlags;
+ this->AppendFlags(compileFlags, targetFlags);
+ if (!compileFlags.empty()) {
+ flags.emplace_back(std::move(compileFlags));
+ }
}
+ std::vector<BT<std::string>> targetCompileOpts =
+ target->GetCompileOptions(config, lang);
+ // COMPILE_OPTIONS are escaped.
+ this->AppendCompileOptions(flags, targetCompileOpts);
}
- for (std::map<std::string, std::string>::const_iterator it =
- target->GetMaxLanguageStandards().begin();
- it != target->GetMaxLanguageStandards().end(); ++it) {
- const char* standard = target->GetProperty(it->first + "_STANDARD");
+ for (auto const& it : target->GetMaxLanguageStandards()) {
+ const char* standard = target->GetProperty(it.first + "_STANDARD");
if (!standard) {
continue;
}
- if (this->Makefile->IsLaterStandard(it->first, standard, it->second)) {
+ if (this->Makefile->IsLaterStandard(it.first, standard, it.second)) {
std::ostringstream e;
e << "The COMPILE_FEATURES property of target \"" << target->GetName()
<< "\" was evaluated when computing the link "
"implementation, and the \""
- << it->first << "_STANDARD\" was \"" << it->second
+ << it.first << "_STANDARD\" was \"" << it.second
<< "\" for that computation. Computing the "
"COMPILE_FEATURES based on the link implementation resulted in a "
"higher \""
- << it->first << "_STANDARD\" \"" << standard
+ << it.first << "_STANDARD\" \"" << standard
<< "\". "
"This is not permitted. The COMPILE_FEATURES may not both depend "
"on "
"and be depended on by the link implementation."
<< std::endl;
- this->IssueMessage(cmake::FATAL_ERROR, e.str());
+ this->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
}
- this->AddCompilerRequirementFlag(flags, target, lang);
+
+ std::string compReqFlag;
+ this->AddCompilerRequirementFlag(compReqFlag, target, lang);
+ if (!compReqFlag.empty()) {
+ flags.emplace_back(std::move(compReqFlag));
+ }
+
+ // Add compile flag for the MSVC compiler only.
+ cmMakefile* mf = this->GetMakefile();
+ if (const char* jmc =
+ mf->GetDefinition("CMAKE_" + lang + "_COMPILE_OPTIONS_JMC")) {
+
+ // Handle Just My Code debugging flags, /JMC.
+ // If the target is a Managed C++ one, /JMC is not compatible.
+ if (target->GetManagedType(config) !=
+ cmGeneratorTarget::ManagedType::Managed) {
+ // add /JMC flags if target property VS_JUST_MY_CODE_DEBUGGING is set
+ // to ON
+ if (char const* jmcExprGen =
+ target->GetProperty("VS_JUST_MY_CODE_DEBUGGING")) {
+ std::string isJMCEnabled =
+ cmGeneratorExpression::Evaluate(jmcExprGen, this, config);
+ if (cmIsOn(isJMCEnabled)) {
+ std::vector<std::string> optVec = cmExpandedList(jmc);
+ std::string jmcFlags;
+ this->AppendCompileOptions(jmcFlags, optVec);
+ if (!jmcFlags.empty()) {
+ flags.emplace_back(std::move(jmcFlags));
+ }
+ }
+ }
+ }
+ }
}
-void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
- cmGeneratorTarget const* target,
- const std::string& lang,
- const std::string& config,
- bool stripImplicitInclDirs) const
+std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit(
+ cmGeneratorTarget const* target, std::string const& lang,
+ std::string const& config, bool stripImplicitDirs,
+ bool appendAllImplicitDirs) const
{
- // Need to decide whether to automatically include the source and
- // binary directories at the beginning of the include path.
- bool includeSourceDir = false;
- bool includeBinaryDir = false;
+ std::vector<BT<std::string>> result;
+ // Do not repeat an include path.
+ std::set<std::string> emitted;
+
+ auto emitDir = [&result, &emitted](std::string const& dir) {
+ if (emitted.insert(dir).second) {
+ result.emplace_back(dir);
+ }
+ };
+
+ auto emitBT = [&result, &emitted](BT<std::string> const& dir) {
+ if (emitted.insert(dir.Value).second) {
+ result.emplace_back(dir);
+ }
+ };
// When automatic include directories are requested for a build then
// include the source and binary directories at the beginning of the
@@ -829,130 +1017,228 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
// cannot fix this because not all native build tools support
// per-source-file include paths.
if (this->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR")) {
- includeSourceDir = true;
- includeBinaryDir = true;
- }
-
- // Do not repeat an include path.
- std::set<std::string> emitted;
-
- // Store the automatic include paths.
- if (includeBinaryDir) {
- std::string binDir = this->StateSnapshot.GetDirectory().GetCurrentBinary();
- if (emitted.find(binDir) == emitted.end()) {
- dirs.push_back(binDir);
- emitted.insert(binDir);
- }
- }
- if (includeSourceDir) {
- std::string srcDir = this->StateSnapshot.GetDirectory().GetCurrentSource();
- if (emitted.find(srcDir) == emitted.end()) {
- dirs.push_back(srcDir);
- emitted.insert(srcDir);
- }
+ // Current binary directory
+ emitDir(this->StateSnapshot.GetDirectory().GetCurrentBinary());
+ // Current source directory
+ emitDir(this->StateSnapshot.GetDirectory().GetCurrentSource());
}
if (!target) {
- return;
+ return result;
}
- std::string rootPath;
- if (const char* sysrootCompile =
- this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) {
- rootPath = sysrootCompile;
- } else {
- rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+ // Standard include directories to be added unconditionally at the end.
+ // These are intended to simulate additional implicit include directories.
+ std::vector<std::string> userStandardDirs;
+ {
+ std::string const value = this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", lang, "_STANDARD_INCLUDE_DIRECTORIES"));
+ cmExpandList(value, userStandardDirs);
+ for (std::string& usd : userStandardDirs) {
+ cmSystemTools::ConvertToUnixSlashes(usd);
+ }
}
+ // Implicit include directories
std::vector<std::string> implicitDirs;
- // Load implicit include directories for this language.
- std::string impDirVar = "CMAKE_";
- impDirVar += lang;
- impDirVar += "_IMPLICIT_INCLUDE_DIRECTORIES";
- if (const char* value = this->Makefile->GetDefinition(impDirVar)) {
- std::vector<std::string> impDirVec;
- cmSystemTools::ExpandListArgument(value, impDirVec);
- for (std::vector<std::string>::const_iterator i = impDirVec.begin();
- i != impDirVec.end(); ++i) {
- std::string d = rootPath + *i;
- cmSystemTools::ConvertToUnixSlashes(d);
- emitted.insert(d);
- if (!stripImplicitInclDirs) {
- implicitDirs.push_back(*i);
+ std::set<std::string> implicitSet;
+ // Include directories to be excluded as if they were implicit.
+ std::set<std::string> implicitExclude;
+ {
+ // Raw list of implicit include directories
+ // Start with "standard" directories that we unconditionally add below.
+ std::vector<std::string> impDirVec = userStandardDirs;
+
+ // Load implicit include directories for this language.
+ // We ignore this for Fortran because:
+ // * There are no standard library headers to avoid overriding.
+ // * Compilers like gfortran do not search their own implicit include
+ // directories for modules ('.mod' files).
+ if (lang != "Fortran") {
+ const char* value = this->Makefile->GetDefinition(
+ cmStrCat("CMAKE_", lang, "_IMPLICIT_INCLUDE_DIRECTORIES"));
+ if (value != nullptr) {
+ size_t const impDirVecOldSize = impDirVec.size();
+ cmExpandList(value, impDirVec);
+ // FIXME: Use cmRange with 'advance()' when it supports non-const.
+ for (size_t i = impDirVecOldSize; i < impDirVec.size(); ++i) {
+ cmSystemTools::ConvertToUnixSlashes(impDirVec[i]);
+ }
+ }
+ }
+
+ // The Platform/UnixPaths module used to hard-code /usr/include for C, CXX,
+ // and CUDA in CMAKE_<LANG>_IMPLICIT_INCLUDE_DIRECTORIES, but those
+ // variables are now computed. On macOS the /usr/include directory is
+ // inside the platform SDK so the computed value does not contain it
+ // directly. In this case adding -I/usr/include can hide SDK headers so we
+ // must still exclude it.
+ if ((lang == "C" || lang == "CXX" || lang == "CUDA") &&
+ !cmContains(impDirVec, "/usr/include") &&
+ std::find_if(impDirVec.begin(), impDirVec.end(),
+ [](std::string const& d) {
+ return cmHasLiteralSuffix(d, "/usr/include");
+ }) != impDirVec.end()) {
+ // Only exclude this hard coded path for backwards compatibility.
+ implicitExclude.emplace("/usr/include");
+ }
+
+ for (std::string const& i : impDirVec) {
+ if (implicitSet.insert(cmSystemTools::GetRealPath(i)).second) {
+ implicitDirs.emplace_back(i);
}
}
}
- // Get the target-specific include directories.
- std::vector<std::string> includes;
+ // Checks if this is not an excluded (implicit) include directory.
+ auto notExcluded = [this, &implicitSet, &implicitExclude,
+ &lang](std::string const& dir) {
+ return (
+ // Do not exclude directories that are not in an excluded set.
+ ((!cmContains(implicitSet, cmSystemTools::GetRealPath(dir))) &&
+ (!cmContains(implicitExclude, dir)))
+ // Do not exclude entries of the CPATH environment variable even though
+ // they are implicitly searched by the compiler. They are meant to be
+ // user-specified directories that can be re-ordered or converted to
+ // -isystem without breaking real compiler builtin headers.
+ || ((lang == "C" || lang == "CXX") && cmContains(this->EnvCPATH, dir)));
+ };
- includes = target->GetIncludeDirectories(config, lang);
+ // Get the target-specific include directories.
+ std::vector<BT<std::string>> userDirs =
+ target->GetIncludeDirectories(config, lang);
// 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();
- for (std::vector<std::string>::const_iterator i = includes.begin();
- i != includes.end(); ++i) {
+ std::string const& topSourceDir = this->GetState()->GetSourceDirectory();
+ std::string const& topBinaryDir = this->GetState()->GetBinaryDirectory();
+ for (BT<std::string> const& udr : userDirs) {
// Emit this directory only if it is a subdirectory of the
// top-level source or binary tree.
- if (cmSystemTools::ComparePath(*i, topSourceDir) ||
- cmSystemTools::ComparePath(*i, topBinaryDir) ||
- cmSystemTools::IsSubDirectory(*i, topSourceDir) ||
- cmSystemTools::IsSubDirectory(*i, topBinaryDir)) {
- if (emitted.insert(*i).second) {
- dirs.push_back(*i);
+ if (cmSystemTools::ComparePath(udr.Value, topSourceDir) ||
+ cmSystemTools::ComparePath(udr.Value, topBinaryDir) ||
+ cmSystemTools::IsSubDirectory(udr.Value, topSourceDir) ||
+ cmSystemTools::IsSubDirectory(udr.Value, topBinaryDir)) {
+ if (notExcluded(udr.Value)) {
+ emitBT(udr);
}
}
}
}
- // Construct the final ordered include directory list.
- for (std::vector<std::string>::const_iterator i = includes.begin();
- i != includes.end(); ++i) {
- if (emitted.insert(*i).second) {
- dirs.push_back(*i);
+ // Emit remaining non implicit user direcories.
+ for (BT<std::string> const& udr : userDirs) {
+ if (notExcluded(udr.Value)) {
+ emitBT(udr);
}
}
- // Add standard include directories for this language.
- // We do not filter out implicit directories here.
- std::string const standardIncludesVar =
- "CMAKE_" + lang + "_STANDARD_INCLUDE_DIRECTORIES";
- std::string const standardIncludes =
- this->Makefile->GetSafeDefinition(standardIncludesVar);
- std::vector<std::string>::size_type const before = includes.size();
- cmSystemTools::ExpandListArgument(standardIncludes, includes);
- for (std::vector<std::string>::iterator i = includes.begin() + before;
- i != includes.end(); ++i) {
- cmSystemTools::ConvertToUnixSlashes(*i);
- dirs.push_back(*i);
+ // Sort result
+ MoveSystemIncludesToEnd(result, config, lang, target);
+
+ // Append standard include directories for this language.
+ userDirs.reserve(userDirs.size() + userStandardDirs.size());
+ for (std::string& usd : userStandardDirs) {
+ emitDir(usd);
+ userDirs.emplace_back(std::move(usd));
}
- for (std::vector<std::string>::const_iterator i = implicitDirs.begin();
- i != implicitDirs.end(); ++i) {
- if (std::find(includes.begin(), includes.end(), *i) != includes.end()) {
- dirs.push_back(*i);
+ // Append compiler implicit include directories
+ if (!stripImplicitDirs) {
+ // Append implicit directories that were requested by the user only
+ for (BT<std::string> const& udr : userDirs) {
+ if (cmContains(implicitSet, cmSystemTools::GetRealPath(udr.Value))) {
+ emitBT(udr);
+ }
+ }
+ // Append remaining implicit directories (on demand)
+ if (appendAllImplicitDirs) {
+ for (std::string& imd : implicitDirs) {
+ emitDir(imd);
+ }
}
}
+
+ return result;
+}
+
+void cmLocalGenerator::GetIncludeDirectoriesImplicit(
+ std::vector<std::string>& dirs, cmGeneratorTarget const* target,
+ const std::string& lang, const std::string& config, bool stripImplicitDirs,
+ bool appendAllImplicitDirs) const
+{
+ std::vector<BT<std::string>> tmp = this->GetIncludeDirectoriesImplicit(
+ target, lang, config, stripImplicitDirs, appendAllImplicitDirs);
+ dirs.reserve(dirs.size() + tmp.size());
+ for (BT<std::string>& v : tmp) {
+ dirs.emplace_back(std::move(v.Value));
+ }
+}
+
+std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectories(
+ cmGeneratorTarget const* target, std::string const& lang,
+ std::string const& config) const
+{
+ return this->GetIncludeDirectoriesImplicit(target, lang, config);
+}
+
+void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
+ cmGeneratorTarget const* target,
+ const std::string& lang,
+ const std::string& config) const
+{
+ this->GetIncludeDirectoriesImplicit(dirs, target, lang, config);
}
void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags,
std::string const& config,
+ std::string const& linkLanguage,
cmGeneratorTarget* target)
{
- this->AppendFlags(
- flags, this->Makefile->GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS"));
- if (!config.empty()) {
- std::string name = "CMAKE_STATIC_LINKER_FLAGS_" + config;
- this->AppendFlags(flags, this->Makefile->GetSafeDefinition(name));
+ std::vector<BT<std::string>> tmpFlags =
+ this->GetStaticLibraryFlags(config, linkLanguage, target);
+ this->AppendFlags(flags, tmpFlags);
+}
+
+std::vector<BT<std::string>> cmLocalGenerator::GetStaticLibraryFlags(
+ std::string const& config, std::string const& linkLanguage,
+ cmGeneratorTarget* target)
+{
+ std::vector<BT<std::string>> flags;
+ if (linkLanguage != "Swift") {
+ std::string staticLibFlags;
+ this->AppendFlags(
+ staticLibFlags,
+ this->Makefile->GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS"));
+ if (!config.empty()) {
+ std::string name = "CMAKE_STATIC_LINKER_FLAGS_" + config;
+ this->AppendFlags(staticLibFlags,
+ this->Makefile->GetSafeDefinition(name));
+ }
+ if (!staticLibFlags.empty()) {
+ flags.emplace_back(std::move(staticLibFlags));
+ }
}
- this->AppendFlags(flags, target->GetProperty("STATIC_LIBRARY_FLAGS"));
+
+ std::string staticLibFlags;
+ this->AppendFlags(staticLibFlags,
+ target->GetSafeProperty("STATIC_LIBRARY_FLAGS"));
if (!config.empty()) {
std::string name = "STATIC_LIBRARY_FLAGS_" + config;
- this->AppendFlags(flags, target->GetProperty(name));
+ this->AppendFlags(staticLibFlags, target->GetSafeProperty(name));
+ }
+
+ if (!staticLibFlags.empty()) {
+ flags.emplace_back(std::move(staticLibFlags));
}
+
+ std::vector<BT<std::string>> staticLibOpts =
+ target->GetStaticLibraryLinkOptions(config, linkLanguage);
+ // STATIC_LIBRARY_OPTIONS are escaped.
+ this->AppendCompileOptions(flags, staticLibOpts);
+
+ return flags;
}
void cmLocalGenerator::GetTargetFlags(
@@ -960,6 +1246,22 @@ void cmLocalGenerator::GetTargetFlags(
std::string& linkLibs, std::string& flags, std::string& linkFlags,
std::string& frameworkPath, std::string& linkPath, cmGeneratorTarget* target)
{
+ std::vector<BT<std::string>> linkFlagsList;
+ std::vector<BT<std::string>> linkPathList;
+ std::vector<BT<std::string>> linkLibsList;
+ this->GetTargetFlags(linkLineComputer, config, linkLibsList, flags,
+ linkFlagsList, frameworkPath, linkPathList, target);
+ this->AppendFlags(linkFlags, linkFlagsList);
+ this->AppendFlags(linkPath, linkPathList);
+ this->AppendFlags(linkLibs, linkLibsList);
+}
+
+void cmLocalGenerator::GetTargetFlags(
+ cmLinkLineComputer* linkLineComputer, const std::string& config,
+ std::vector<BT<std::string>>& linkLibs, std::string& flags,
+ std::vector<BT<std::string>>& linkFlags, std::string& frameworkPath,
+ std::vector<BT<std::string>>& linkPath, cmGeneratorTarget* target)
+{
const std::string buildType = cmSystemTools::UpperCase(config);
cmComputeLinkInformation* pcli = target->GetLinkInformation(config);
const char* libraryLinkVariable =
@@ -970,129 +1272,161 @@ void cmLocalGenerator::GetTargetFlags(
switch (target->GetType()) {
case cmStateEnums::STATIC_LIBRARY:
- this->GetStaticLibraryFlags(linkFlags, buildType, target);
+ linkFlags = this->GetStaticLibraryFlags(buildType, linkLanguage, target);
+ if (pcli && dynamic_cast<cmLinkLineDeviceComputer*>(linkLineComputer)) {
+ // Compute the required cuda device link libraries when
+ // resolving cuda device symbols
+ this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
+ frameworkPath, linkPath);
+ }
break;
case cmStateEnums::MODULE_LIBRARY:
libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS";
CM_FALLTHROUGH;
case cmStateEnums::SHARED_LIBRARY: {
- linkFlags = this->Makefile->GetSafeDefinition(libraryLinkVariable);
- linkFlags += " ";
- if (!buildType.empty()) {
- std::string build = libraryLinkVariable;
- build += "_";
- build += buildType;
- linkFlags += this->Makefile->GetSafeDefinition(build);
- linkFlags += " ";
- }
- if (this->Makefile->IsOn("WIN32") &&
- !(this->Makefile->IsOn("CYGWIN") || this->Makefile->IsOn("MINGW"))) {
- std::vector<cmSourceFile*> sources;
- target->GetSourceFiles(sources, buildType);
- std::string defFlag =
- this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
- for (std::vector<cmSourceFile*>::const_iterator i = sources.begin();
- i != sources.end(); ++i) {
- cmSourceFile* sf = *i;
- if (sf->GetExtension() == "def") {
- linkFlags += defFlag;
- linkFlags += this->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(sf->GetFullPath()), SHELL);
- linkFlags += " ";
+ std::string sharedLibFlags;
+ if (linkLanguage != "Swift") {
+ sharedLibFlags = cmStrCat(
+ this->Makefile->GetSafeDefinition(libraryLinkVariable), ' ');
+ if (!buildType.empty()) {
+ std::string build = cmStrCat(libraryLinkVariable, '_', buildType);
+ sharedLibFlags += this->Makefile->GetSafeDefinition(build);
+ sharedLibFlags += " ";
+ }
+ if (this->Makefile->IsOn("WIN32") &&
+ !(this->Makefile->IsOn("CYGWIN") ||
+ this->Makefile->IsOn("MINGW"))) {
+ std::vector<cmSourceFile*> sources;
+ target->GetSourceFiles(sources, buildType);
+ std::string defFlag =
+ this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
+ for (cmSourceFile* sf : sources) {
+ if (sf->GetExtension() == "def") {
+ sharedLibFlags += defFlag;
+ sharedLibFlags += this->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(sf->ResolveFullPath()), SHELL);
+ sharedLibFlags += " ";
+ }
}
}
}
+
const char* targetLinkFlags = target->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
- linkFlags += targetLinkFlags;
- linkFlags += " ";
+ sharedLibFlags += targetLinkFlags;
+ sharedLibFlags += " ";
}
if (!buildType.empty()) {
- std::string configLinkFlags = "LINK_FLAGS_";
- configLinkFlags += buildType;
- targetLinkFlags = target->GetProperty(configLinkFlags);
+ targetLinkFlags =
+ target->GetProperty(cmStrCat("LINK_FLAGS_", buildType));
if (targetLinkFlags) {
- linkFlags += targetLinkFlags;
- linkFlags += " ";
+ sharedLibFlags += targetLinkFlags;
+ sharedLibFlags += " ";
}
}
+
+ if (!sharedLibFlags.empty()) {
+ linkFlags.emplace_back(std::move(sharedLibFlags));
+ }
+
+ std::vector<BT<std::string>> linkOpts =
+ target->GetLinkOptions(config, linkLanguage);
+ // LINK_OPTIONS are escaped.
+ this->AppendCompileOptions(linkFlags, linkOpts);
if (pcli) {
this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
frameworkPath, linkPath);
}
} break;
case cmStateEnums::EXECUTABLE: {
- linkFlags += this->Makefile->GetSafeDefinition("CMAKE_EXE_LINKER_FLAGS");
- linkFlags += " ";
- if (!buildType.empty()) {
- std::string build = "CMAKE_EXE_LINKER_FLAGS_";
- build += buildType;
- linkFlags += this->Makefile->GetSafeDefinition(build);
- linkFlags += " ";
- }
- if (linkLanguage.empty()) {
- cmSystemTools::Error(
- "CMake can not determine linker language for target: ",
- target->GetName().c_str());
- return;
+ std::string exeFlags;
+ if (linkLanguage != "Swift") {
+ exeFlags = this->Makefile->GetSafeDefinition("CMAKE_EXE_LINKER_FLAGS");
+ exeFlags += " ";
+ if (!buildType.empty()) {
+ exeFlags += this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_EXE_LINKER_FLAGS_", buildType));
+ exeFlags += " ";
+ }
+ if (linkLanguage.empty()) {
+ cmSystemTools::Error(
+ "CMake can not determine linker language for target: " +
+ target->GetName());
+ return;
+ }
+
+ if (target->GetPropertyAsBool("WIN32_EXECUTABLE")) {
+ exeFlags +=
+ this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE");
+ exeFlags += " ";
+ } else {
+ exeFlags +=
+ this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE");
+ exeFlags += " ";
+ }
+
+ if (target->IsExecutableWithExports()) {
+ exeFlags += this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_EXE_EXPORTS_", linkLanguage, "_FLAG"));
+ exeFlags += " ";
+ }
}
+
this->AddLanguageFlagsForLinking(flags, target, linkLanguage, buildType);
if (pcli) {
this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
frameworkPath, linkPath);
}
- if (cmSystemTools::IsOn(
- this->Makefile->GetDefinition("BUILD_SHARED_LIBS"))) {
+
+ if (cmIsOn(this->Makefile->GetDefinition("BUILD_SHARED_LIBS"))) {
std::string sFlagVar = std::string("CMAKE_SHARED_BUILD_") +
linkLanguage + std::string("_FLAGS");
- linkFlags += this->Makefile->GetSafeDefinition(sFlagVar);
- linkFlags += " ";
- }
- if (target->GetPropertyAsBool("WIN32_EXECUTABLE")) {
- linkFlags +=
- this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE");
- linkFlags += " ";
- } else {
- linkFlags +=
- this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE");
- linkFlags += " ";
- }
- if (target->IsExecutableWithExports()) {
- std::string exportFlagVar = "CMAKE_EXE_EXPORTS_";
- exportFlagVar += linkLanguage;
- exportFlagVar += "_FLAG";
-
- linkFlags += this->Makefile->GetSafeDefinition(exportFlagVar);
- linkFlags += " ";
+ exeFlags += this->Makefile->GetSafeDefinition(sFlagVar);
+ exeFlags += " ";
}
std::string cmp0065Flags =
this->GetLinkLibsCMP0065(linkLanguage, *target);
if (!cmp0065Flags.empty()) {
- linkFlags += cmp0065Flags;
- linkFlags += " ";
+ exeFlags += cmp0065Flags;
+ exeFlags += " ";
}
const char* targetLinkFlags = target->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
- linkFlags += targetLinkFlags;
- linkFlags += " ";
+ exeFlags += targetLinkFlags;
+ exeFlags += " ";
}
if (!buildType.empty()) {
- std::string configLinkFlags = "LINK_FLAGS_";
- configLinkFlags += buildType;
- targetLinkFlags = target->GetProperty(configLinkFlags);
+ targetLinkFlags =
+ target->GetProperty(cmStrCat("LINK_FLAGS_", buildType));
if (targetLinkFlags) {
- linkFlags += targetLinkFlags;
- linkFlags += " ";
+ exeFlags += targetLinkFlags;
+ exeFlags += " ";
}
}
+
+ if (!exeFlags.empty()) {
+ linkFlags.emplace_back(std::move(exeFlags));
+ }
+
+ std::vector<BT<std::string>> linkOpts =
+ target->GetLinkOptions(config, linkLanguage);
+ // LINK_OPTIONS are escaped.
+ this->AppendCompileOptions(linkFlags, linkOpts);
} break;
default:
break;
}
- this->AppendIPOLinkerFlags(linkFlags, target, config, linkLanguage);
+ std::string extraLinkFlags;
+ this->AppendPositionIndependentLinkerFlags(extraLinkFlags, target, config,
+ linkLanguage);
+ this->AppendIPOLinkerFlags(extraLinkFlags, target, config, linkLanguage);
+
+ if (!extraLinkFlags.empty()) {
+ linkFlags.emplace_back(std::move(extraLinkFlags));
+ }
}
void cmLocalGenerator::GetTargetCompileFlags(cmGeneratorTarget* target,
@@ -1100,22 +1434,45 @@ void cmLocalGenerator::GetTargetCompileFlags(cmGeneratorTarget* target,
std::string const& lang,
std::string& flags)
{
+ std::vector<BT<std::string>> tmpFlags =
+ this->GetTargetCompileFlags(target, config, lang);
+ this->AppendFlags(flags, tmpFlags);
+}
+
+std::vector<BT<std::string>> cmLocalGenerator::GetTargetCompileFlags(
+ cmGeneratorTarget* target, std::string const& config,
+ std::string const& lang)
+{
+ std::vector<BT<std::string>> flags;
+ std::string compileFlags;
+
cmMakefile* mf = this->GetMakefile();
// Add language-specific flags.
- this->AddLanguageFlags(flags, target, lang, config);
+ this->AddLanguageFlags(compileFlags, target, lang, config);
+
+ if (target->IsIPOEnabled(lang, config)) {
+ this->AppendFeatureOptions(compileFlags, lang, "IPO");
+ }
- this->AddArchitectureFlags(flags, target, lang, config);
+ this->AddArchitectureFlags(compileFlags, target, lang, config);
if (lang == "Fortran") {
- this->AppendFlags(flags, this->GetTargetFortranFlags(target, config));
+ this->AppendFlags(compileFlags,
+ this->GetTargetFortranFlags(target, config));
}
- this->AddCMP0018Flags(flags, target, lang, config);
- this->AddVisibilityPresetFlags(flags, target, lang);
- this->AppendFlags(flags, mf->GetDefineFlags());
- this->AppendFlags(flags, this->GetFrameworkFlags(lang, config, target));
+ this->AddCMP0018Flags(compileFlags, target, lang, config);
+ this->AddVisibilityPresetFlags(compileFlags, target, lang);
+ this->AppendFlags(compileFlags, mf->GetDefineFlags());
+ this->AppendFlags(compileFlags,
+ this->GetFrameworkFlags(lang, config, target));
+
+ if (!compileFlags.empty()) {
+ flags.emplace_back(std::move(compileFlags));
+ }
this->AddCompileOptions(flags, target, lang, config);
+ return flags;
}
static std::string GetFrameworkFlags(const std::string& lang,
@@ -1144,11 +1501,9 @@ static std::string GetFrameworkFlags(const std::string& lang,
lg->GetIncludeDirectories(includes, target, "C", config);
// check all include directories for frameworks as this
// will already have added a -F for the framework
- for (std::vector<std::string>::iterator i = includes.begin();
- i != includes.end(); ++i) {
- if (lg->GetGlobalGenerator()->NameResolvesToFramework(*i)) {
- std::string frameworkDir = *i;
- frameworkDir += "/../";
+ for (std::string const& include : includes) {
+ if (lg->GetGlobalGenerator()->NameResolvesToFramework(include)) {
+ std::string frameworkDir = cmStrCat(include, "/../");
frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir);
emitted.insert(frameworkDir);
}
@@ -1157,11 +1512,11 @@ static std::string GetFrameworkFlags(const std::string& lang,
std::string flags;
if (cmComputeLinkInformation* cli = target->GetLinkInformation(config)) {
std::vector<std::string> const& frameworks = cli->GetFrameworkPaths();
- for (std::vector<std::string>::const_iterator i = frameworks.begin();
- i != frameworks.end(); ++i) {
- if (emitted.insert(*i).second) {
+ for (std::string const& framework : frameworks) {
+ if (emitted.insert(framework).second) {
flags += fwSearchFlag;
- flags += lg->ConvertToOutputFormat(*i, cmOutputConverter::SHELL);
+ flags +=
+ lg->ConvertToOutputFormat(framework, cmOutputConverter::SHELL);
flags += " ";
}
}
@@ -1181,13 +1536,29 @@ void cmLocalGenerator::GetTargetDefines(cmGeneratorTarget const* target,
std::string const& lang,
std::set<std::string>& defines) const
{
+ std::set<BT<std::string>> tmp = this->GetTargetDefines(target, config, lang);
+ for (BT<std::string> const& v : tmp) {
+ defines.emplace(v.Value);
+ }
+}
+
+std::set<BT<std::string>> cmLocalGenerator::GetTargetDefines(
+ cmGeneratorTarget const* target, std::string const& config,
+ std::string const& lang) const
+{
+ std::set<BT<std::string>> defines;
+
// Add the export symbol definition for shared library objects.
- if (const char* exportMacro = target->GetExportMacro()) {
- this->AppendDefines(defines, exportMacro);
+ if (const std::string* exportMacro = target->GetExportMacro()) {
+ this->AppendDefines(defines, *exportMacro);
}
// Add preprocessor definitions for this target and configuration.
- this->AddCompileDefinitions(defines, target, config, lang);
+ std::vector<BT<std::string>> targetDefines =
+ target->GetCompileDefinitions(config, lang);
+ this->AppendDefines(defines, targetDefines);
+
+ return defines;
}
std::string cmLocalGenerator::GetTargetFortranFlags(
@@ -1207,36 +1578,53 @@ void cmLocalGenerator::OutputLinkLibraries(
std::string& linkLibraries, std::string& frameworkPath,
std::string& linkPath)
{
+ std::vector<BT<std::string>> linkLibrariesList;
+ std::vector<BT<std::string>> linkPathList;
+ this->OutputLinkLibraries(pcli, linkLineComputer, linkLibrariesList,
+ frameworkPath, linkPathList);
+ pcli->AppendValues(linkLibraries, linkLibrariesList);
+ pcli->AppendValues(linkPath, linkPathList);
+}
+
+void cmLocalGenerator::OutputLinkLibraries(
+ cmComputeLinkInformation* pcli, cmLinkLineComputer* linkLineComputer,
+ std::vector<BT<std::string>>& linkLibraries, std::string& frameworkPath,
+ std::vector<BT<std::string>>& linkPath)
+{
cmComputeLinkInformation& cli = *pcli;
std::string linkLanguage = cli.GetLinkLanguage();
- std::string libPathFlag =
- this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG");
- std::string libPathTerminator =
- this->Makefile->GetSafeDefinition("CMAKE_LIBRARY_PATH_TERMINATOR");
+ std::string libPathFlag;
+ if (const char* value = this->Makefile->GetDefinition(
+ "CMAKE_" + cli.GetLinkLanguage() + "_LIBRARY_PATH_FLAG")) {
+ libPathFlag = value;
+ } else {
+ libPathFlag =
+ this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG");
+ }
- // Add standard libraries for this language.
- std::string standardLibsVar = "CMAKE_";
- standardLibsVar += cli.GetLinkLanguage();
- standardLibsVar += "_STANDARD_LIBRARIES";
- std::string stdLibString;
- if (const char* stdLibs = this->Makefile->GetDefinition(standardLibsVar)) {
- stdLibString = stdLibs;
+ std::string libPathTerminator;
+ if (const char* value = this->Makefile->GetDefinition(
+ "CMAKE_" + cli.GetLinkLanguage() + "_LIBRARY_PATH_TERMINATOR")) {
+ libPathTerminator = value;
+ } else {
+ libPathTerminator =
+ this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_TERMINATOR");
}
+ // Add standard libraries for this language.
+ std::string stdLibString = this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", cli.GetLinkLanguage(), "_STANDARD_LIBRARIES"));
+
// Append the framework search path flags.
- std::string fwSearchFlagVar = "CMAKE_";
- fwSearchFlagVar += linkLanguage;
- fwSearchFlagVar += "_FRAMEWORK_SEARCH_FLAG";
- std::string fwSearchFlag =
- this->Makefile->GetSafeDefinition(fwSearchFlagVar);
+ std::string fwSearchFlag = this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", linkLanguage, "_FRAMEWORK_SEARCH_FLAG"));
frameworkPath = linkLineComputer->ComputeFrameworkPath(cli, fwSearchFlag);
- linkPath =
- linkLineComputer->ComputeLinkPath(cli, libPathFlag, libPathTerminator);
-
- linkLibraries = linkLineComputer->ComputeLinkLibraries(cli, stdLibString);
+ linkLineComputer->ComputeLinkPath(cli, libPathFlag, libPathTerminator,
+ linkPath);
+ linkLineComputer->ComputeLinkLibraries(cli, stdLibString, linkLibraries);
}
std::string cmLocalGenerator::GetLinkLibsCMP0065(
@@ -1261,30 +1649,32 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065(
"additional flags may be added to export symbols on all "
"executables regardless of their ENABLE_EXPORTS property.";
/* clang-format on */
- this->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ this->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
}
CM_FALLTHROUGH;
case cmPolicies::OLD:
- // OLD behavior is to always add the flags
- add_shlib_flags = true;
+ // OLD behavior is to always add the flags, except on AIX where
+ // we compute symbol exports if ENABLE_EXPORTS is on.
+ add_shlib_flags =
+ !(tgt.Target->IsAIX() && tgt.GetPropertyAsBool("ENABLE_EXPORTS"));
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
this->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0065));
CM_FALLTHROUGH;
case cmPolicies::NEW:
- // NEW behavior is to only add the flags if ENABLE_EXPORTS is on
- add_shlib_flags = tgt.GetPropertyAsBool("ENABLE_EXPORTS");
+ // NEW behavior is to only add the flags if ENABLE_EXPORTS is on,
+ // except on AIX where we compute symbol exports.
+ add_shlib_flags =
+ !tgt.Target->IsAIX() && tgt.GetPropertyAsBool("ENABLE_EXPORTS");
break;
}
if (add_shlib_flags) {
- std::string linkFlagsVar = "CMAKE_SHARED_LIBRARY_LINK_";
- linkFlagsVar += linkLanguage;
- linkFlagsVar += "_FLAGS";
- linkFlags = this->Makefile->GetSafeDefinition(linkFlagsVar);
+ linkFlags = this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_SHARED_LIBRARY_LINK_", linkLanguage, "_FLAGS"));
}
}
return linkFlags;
@@ -1295,13 +1685,13 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags,
const std::string& lang,
const std::string& config)
{
- // Only add Mac OS X specific flags on Darwin platforms (OSX and iphone):
+ // Only add macOS specific flags on Darwin platforms (macOS and iOS):
if (this->Makefile->IsOn("APPLE") && this->EmitUniversalBinaryFlags) {
std::vector<std::string> archs;
target->GetAppleArchs(config, archs);
const char* sysroot = this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT");
if (sysroot && sysroot[0] == '/' && !sysroot[1]) {
- sysroot = CM_NULLPTR;
+ sysroot = nullptr;
}
std::string sysrootFlagVar =
std::string("CMAKE_") + lang + "_SYSROOT_FLAG";
@@ -1313,11 +1703,10 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags,
const char* deploymentTargetFlag =
this->Makefile->GetDefinition(deploymentTargetFlagVar);
if (!archs.empty() && !lang.empty() &&
- (lang[0] == 'C' || lang[0] == 'F')) {
- for (std::vector<std::string>::iterator i = archs.begin();
- i != archs.end(); ++i) {
+ (lang[0] == 'C' || lang[0] == 'F' || lang[0] == 'O')) {
+ for (std::string const& arch : archs) {
flags += " -arch ";
- flags += *i;
+ flags += arch;
}
}
@@ -1343,13 +1732,50 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
const std::string& config)
{
// Add language-specific flags.
- std::string flagsVar = "CMAKE_";
- flagsVar += lang;
- flagsVar += "_FLAGS";
- this->AddConfigVariableFlags(flags, flagsVar, config);
+ this->AddConfigVariableFlags(flags, cmStrCat("CMAKE_", lang, "_FLAGS"),
+ config);
+
+ if (lang == "Swift") {
+ if (const char* v = target->GetProperty("Swift_LANGUAGE_VERSION")) {
+ if (cmSystemTools::VersionCompare(
+ cmSystemTools::OP_GREATER_EQUAL,
+ this->Makefile->GetDefinition("CMAKE_Swift_COMPILER_VERSION"),
+ "4.2")) {
+ this->AppendFlags(flags, "-swift-version " + std::string(v));
+ }
+ }
+ }
- if (target->IsIPOEnabled(lang, config)) {
- this->AppendFeatureOptions(flags, lang, "IPO");
+ // Add MSVC runtime library flags. This is activated by the presence
+ // of a default selection whether or not it is overridden by a property.
+ const char* msvcRuntimeLibraryDefault =
+ this->Makefile->GetDefinition("CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT");
+ if (msvcRuntimeLibraryDefault && *msvcRuntimeLibraryDefault) {
+ const char* msvcRuntimeLibraryValue =
+ target->GetProperty("MSVC_RUNTIME_LIBRARY");
+ if (!msvcRuntimeLibraryValue) {
+ msvcRuntimeLibraryValue = msvcRuntimeLibraryDefault;
+ }
+ std::string const msvcRuntimeLibrary = cmGeneratorExpression::Evaluate(
+ msvcRuntimeLibraryValue, this, config, target);
+ if (!msvcRuntimeLibrary.empty()) {
+ if (const char* msvcRuntimeLibraryOptions =
+ this->Makefile->GetDefinition(
+ "CMAKE_" + lang + "_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_" +
+ msvcRuntimeLibrary)) {
+ this->AppendCompileOptions(flags, msvcRuntimeLibraryOptions);
+ } else if ((this->Makefile->GetSafeDefinition(
+ "CMAKE_" + lang + "_COMPILER_ID") == "MSVC" ||
+ this->Makefile->GetSafeDefinition(
+ "CMAKE_" + lang + "_SIMULATE_ID") == "MSVC") &&
+ !cmSystemTools::GetErrorOccuredFlag()) {
+ // The compiler uses the MSVC ABI so it needs a known runtime library.
+ this->IssueMessage(MessageType::FATAL_ERROR,
+ "MSVC_RUNTIME_LIBRARY value '" +
+ msvcRuntimeLibrary + "' not known for this " +
+ lang + " compiler.");
+ }
+ }
}
}
@@ -1367,16 +1793,18 @@ void cmLocalGenerator::AddLanguageFlagsForLinking(
}
this->AddLanguageFlags(flags, target, lang, config);
+
+ if (target->IsIPOEnabled(lang, config)) {
+ this->AppendFeatureOptions(flags, lang, "IPO");
+ }
}
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));
+ auto imported = this->ImportedGeneratorTargets.find(name);
if (imported != this->ImportedGeneratorTargets.end()) {
- return *imported;
+ return imported->second;
}
if (cmGeneratorTarget* t = this->FindLocalNonAliasGeneratorTarget(name)) {
@@ -1399,7 +1827,7 @@ bool cmLocalGenerator::GetRealDependency(const std::string& inName,
// If the input name is the empty string, there is no real
// dependency. Short-circuit the other checks:
- if (name == "") {
+ if (name.empty()) {
return false;
}
@@ -1411,7 +1839,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) {
@@ -1455,7 +1883,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;
@@ -1464,15 +1892,14 @@ bool cmLocalGenerator::GetRealDependency(const std::string& inName,
// Check for a source file in this directory that matches the
// dependency.
if (cmSourceFile* sf = this->Makefile->GetSource(inName)) {
- dep = sf->GetFullPath();
+ dep = sf->ResolveFullPath();
return true;
}
// Treat the name as relative to the source directory in which it
// was given.
- dep = this->StateSnapshot.GetDirectory().GetCurrentSource();
- dep += "/";
- dep += inName;
+ dep = cmStrCat(this->StateSnapshot.GetDirectory().GetCurrentSource(), '/',
+ inName);
return true;
}
@@ -1483,10 +1910,9 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags,
// Add flags for dealing with shared libraries for this language.
if (shared) {
- flagsVar = "CMAKE_SHARED_LIBRARY_";
- flagsVar += lang;
- flagsVar += "_FLAGS";
- this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar));
+ this->AppendFlags(flags,
+ this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_SHARED_LIBRARY_", lang, "_FLAGS")));
}
}
@@ -1502,20 +1928,33 @@ void cmLocalGenerator::AddCompilerRequirementFlag(
// This compiler has no notion of language standard levels.
return;
}
- std::string stdProp = lang + "_STANDARD";
- const char* standardProp = target->GetProperty(stdProp);
- if (!standardProp) {
- return;
- }
std::string extProp = lang + "_EXTENSIONS";
- std::string type = "EXTENSION";
bool ext = true;
if (const char* extPropValue = target->GetProperty(extProp)) {
- if (cmSystemTools::IsOff(extPropValue)) {
+ if (cmIsOff(extPropValue)) {
ext = false;
- type = "STANDARD";
}
}
+ std::string stdProp = lang + "_STANDARD";
+ const char* standardProp = target->GetProperty(stdProp);
+ if (!standardProp) {
+ if (ext) {
+ // No language standard is specified and extensions are not disabled.
+ // Check if this compiler needs a flag to enable extensions.
+ std::string const option_flag =
+ "CMAKE_" + lang + "_EXTENSION_COMPILE_OPTION";
+ if (const char* opt =
+ target->Target->GetMakefile()->GetDefinition(option_flag)) {
+ std::vector<std::string> optVec = cmExpandedList(opt);
+ for (std::string const& i : optVec) {
+ this->AppendFlagEscape(flags, i);
+ }
+ }
+ }
+ return;
+ }
+
+ std::string const type = ext ? "EXTENSION" : "STANDARD";
if (target->GetPropertyAsBool(lang + "_STANDARD_REQUIRED")) {
std::string option_flag =
@@ -1525,90 +1964,102 @@ void cmLocalGenerator::AddCompilerRequirementFlag(
target->Target->GetMakefile()->GetDefinition(option_flag);
if (!opt) {
std::ostringstream e;
- e << "Target \"" << target->GetName() << "\" requires the language "
- "dialect \""
+ e << "Target \"" << target->GetName()
+ << "\" requires the language "
+ "dialect \""
<< lang << standardProp << "\" "
<< (ext ? "(with compiler extensions)" : "")
<< ", but CMake "
"does not know the compile flags to use to enable it.";
- this->IssueMessage(cmake::FATAL_ERROR, e.str());
+ this->IssueMessage(MessageType::FATAL_ERROR, e.str());
} else {
- std::vector<std::string> optVec;
- cmSystemTools::ExpandListArgument(opt, optVec);
- for (size_t i = 0; i < optVec.size(); ++i) {
- this->AppendFlagEscape(flags, optVec[i]);
+ std::vector<std::string> optVec = cmExpandedList(opt);
+ for (std::string const& i : optVec) {
+ this->AppendFlagEscape(flags, i);
}
}
return;
}
- static std::map<std::string, std::vector<std::string> > langStdMap;
+ static std::map<std::string, std::vector<std::string>> langStdMap;
if (langStdMap.empty()) {
// Maintain sorted order, most recent first.
- langStdMap["CXX"].push_back("17");
- langStdMap["CXX"].push_back("14");
- langStdMap["CXX"].push_back("11");
- langStdMap["CXX"].push_back("98");
+ langStdMap["CXX"].emplace_back("20");
+ langStdMap["CXX"].emplace_back("17");
+ langStdMap["CXX"].emplace_back("14");
+ langStdMap["CXX"].emplace_back("11");
+ langStdMap["CXX"].emplace_back("98");
+
+ langStdMap["OBJCXX"].emplace_back("20");
+ langStdMap["OBJCXX"].emplace_back("17");
+ langStdMap["OBJCXX"].emplace_back("14");
+ langStdMap["OBJCXX"].emplace_back("11");
+ langStdMap["OBJCXX"].emplace_back("98");
+
+ langStdMap["C"].emplace_back("11");
+ langStdMap["C"].emplace_back("99");
+ langStdMap["C"].emplace_back("90");
- langStdMap["C"].push_back("11");
- langStdMap["C"].push_back("99");
- langStdMap["C"].push_back("90");
+ langStdMap["OBJC"].emplace_back("11");
+ langStdMap["OBJC"].emplace_back("99");
+ langStdMap["OBJC"].emplace_back("90");
- langStdMap["CUDA"].push_back("14");
- langStdMap["CUDA"].push_back("11");
- langStdMap["CUDA"].push_back("98");
+ langStdMap["CUDA"].emplace_back("14");
+ langStdMap["CUDA"].emplace_back("11");
+ langStdMap["CUDA"].emplace_back("98");
}
std::string standard(standardProp);
std::vector<std::string>& stds = langStdMap[lang];
- std::vector<std::string>::const_iterator stdIt =
- std::find(stds.begin(), stds.end(), standard);
+ auto stdIt = std::find(stds.begin(), stds.end(), standard);
if (stdIt == stds.end()) {
std::string e =
lang + "_STANDARD is set to invalid value '" + standard + "'";
this->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
- cmake::FATAL_ERROR, e, target->GetBacktrace());
+ MessageType::FATAL_ERROR, e, target->GetBacktrace());
return;
}
- std::vector<std::string>::const_iterator defaultStdIt =
- std::find(stds.begin(), stds.end(), defaultStd);
+ auto defaultStdIt = std::find(stds.begin(), stds.end(), defaultStd);
if (defaultStdIt == stds.end()) {
std::string e = "CMAKE_" + lang +
"_STANDARD_DEFAULT is set to invalid value '" + std::string(defaultStd) +
"'";
- this->IssueMessage(cmake::INTERNAL_ERROR, e);
+ this->IssueMessage(MessageType::INTERNAL_ERROR, e);
return;
}
- // Greater or equal because the standards are stored in
- // backward chronological order.
+ // If the standard requested is older than the compiler's default
+ // then we need to use a flag to change it. The comparison is
+ // greater-or-equal because the standards are stored in backward
+ // chronological order.
if (stdIt >= defaultStdIt) {
std::string option_flag =
"CMAKE_" + lang + *stdIt + "_" + type + "_COMPILE_OPTION";
- const char* opt =
+ std::string const& opt =
target->Target->GetMakefile()->GetRequiredDefinition(option_flag);
- std::vector<std::string> optVec;
- cmSystemTools::ExpandListArgument(opt, optVec);
- for (size_t i = 0; i < optVec.size(); ++i) {
- this->AppendFlagEscape(flags, optVec[i]);
+ std::vector<std::string> optVec = cmExpandedList(opt);
+ for (std::string const& i : optVec) {
+ this->AppendFlagEscape(flags, i);
}
return;
}
+ // The standard requested is at least as new as the compiler's default,
+ // and the standard request is not required. Decay to the newest standard
+ // for which a flag is defined.
for (; stdIt < defaultStdIt; ++stdIt) {
std::string option_flag =
- "CMAKE_" + lang + *stdIt + "_" + type + "_COMPILE_OPTION";
+ cmStrCat("CMAKE_", lang, *stdIt, "_", type, "_COMPILE_OPTION");
if (const char* opt =
target->Target->GetMakefile()->GetDefinition(option_flag)) {
- std::vector<std::string> optVec;
- cmSystemTools::ExpandListArgument(opt, optVec);
- for (size_t i = 0; i < optVec.size(); ++i) {
- this->AppendFlagEscape(flags, optVec[i]);
+ std::vector<std::string> optVec = cmExpandedList(opt);
+ for (std::string const& i : optVec) {
+ this->AppendFlagEscape(flags, i);
}
return;
}
@@ -1640,8 +2091,10 @@ static void AddVisibilityCompileOption(std::string& flags,
strcmp(prop, "protected") != 0 && strcmp(prop, "internal") != 0) {
std::ostringstream e;
e << "Target " << target->GetName() << " uses unsupported value \"" << prop
- << "\" for " << flagDefine << ".";
- cmSystemTools::Error(e.str().c_str());
+ << "\" for " << flagDefine << "."
+ << " The supported values are: default, hidden, protected, and "
+ "internal.";
+ cmSystemTools::Error(e.str());
return;
}
std::string option = std::string(opt) + prop;
@@ -1651,10 +2104,11 @@ static void AddVisibilityCompileOption(std::string& flags,
static void AddInlineVisibilityCompileOption(std::string& flags,
cmGeneratorTarget const* target,
cmLocalGenerator* lg,
- std::string* warnCMP0063)
+ std::string* warnCMP0063,
+ const std::string& lang)
{
std::string compileOption =
- "CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN";
+ cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN");
const char* opt = lg->GetMakefile()->GetDefinition(compileOption);
if (!opt) {
return;
@@ -1679,7 +2133,7 @@ void cmLocalGenerator::AddVisibilityPresetFlags(
}
std::string warnCMP0063;
- std::string* pWarnCMP0063 = CM_NULLPTR;
+ std::string* pWarnCMP0063 = nullptr;
if (target->GetType() != cmStateEnums::SHARED_LIBRARY &&
target->GetType() != cmStateEnums::MODULE_LIBRARY &&
!target->IsExecutableWithExports()) {
@@ -1696,8 +2150,8 @@ void cmLocalGenerator::AddVisibilityPresetFlags(
AddVisibilityCompileOption(flags, target, this, lang, pWarnCMP0063);
- if (lang == "CXX") {
- AddInlineVisibilityCompileOption(flags, target, this, pWarnCMP0063);
+ if (lang == "CXX" || lang == "OBJCXX") {
+ AddInlineVisibilityCompileOption(flags, target, this, pWarnCMP0063, lang);
}
if (!warnCMP0063.empty() && this->WarnCMP0063.insert(target).second) {
@@ -1712,7 +2166,7 @@ void cmLocalGenerator::AddVisibilityPresetFlags(
"For compatibility CMake is not honoring them for this target.";
/* clang-format on */
target->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
- cmake::AUTHOR_WARNING, w.str(), target->GetBacktrace());
+ MessageType::AUTHOR_WARNING, w.str(), target->GetBacktrace());
}
}
@@ -1752,12 +2206,10 @@ bool cmLocalGenerator::GetShouldUseOldFlags(bool shared,
std::string originalFlags =
this->GlobalGenerator->GetSharedLibFlagsForLanguage(lang);
if (shared) {
- std::string flagsVar = "CMAKE_SHARED_LIBRARY_";
- flagsVar += lang;
- flagsVar += "_FLAGS";
- const char* flags = this->Makefile->GetSafeDefinition(flagsVar);
+ std::string flagsVar = cmStrCat("CMAKE_SHARED_LIBRARY_", lang, "_FLAGS");
+ std::string const& flags = this->Makefile->GetSafeDefinition(flagsVar);
- if (flags && flags != originalFlags) {
+ if (flags != originalFlags) {
switch (this->GetPolicyStatus(cmPolicies::CMP0018)) {
case cmPolicies::WARN: {
std::ostringstream e;
@@ -1771,7 +2223,7 @@ bool cmLocalGenerator::GetShouldUseOldFlags(bool shared,
<< flagsVar << " was removed.\n"
<< cmPolicies::GetPolicyWarning(cmPolicies::CMP0018);
- this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ this->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
CM_FALLTHROUGH;
}
case cmPolicies::OLD:
@@ -1790,26 +2242,20 @@ void cmLocalGenerator::AddPositionIndependentFlags(std::string& flags,
std::string const& lang,
int targetType)
{
- const char* picFlags = CM_NULLPTR;
+ std::string picFlags;
if (targetType == cmStateEnums::EXECUTABLE) {
- std::string flagsVar = "CMAKE_";
- flagsVar += lang;
- flagsVar += "_COMPILE_OPTIONS_PIE";
- picFlags = this->Makefile->GetSafeDefinition(flagsVar);
+ picFlags = this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_PIE"));
}
- if (!picFlags) {
- std::string flagsVar = "CMAKE_";
- flagsVar += lang;
- flagsVar += "_COMPILE_OPTIONS_PIC";
- picFlags = this->Makefile->GetSafeDefinition(flagsVar);
+ if (picFlags.empty()) {
+ picFlags = this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_PIC"));
}
- if (picFlags) {
- std::vector<std::string> options;
- cmSystemTools::ExpandListArgument(picFlags, options);
- for (std::vector<std::string>::const_iterator oi = options.begin();
- oi != options.end(); ++oi) {
- this->AppendFlagEscape(flags, *oi);
+ if (!picFlags.empty()) {
+ std::vector<std::string> options = cmExpandedList(picFlags);
+ for (std::string const& o : options) {
+ this->AppendFlagEscape(flags, o);
}
}
}
@@ -1819,18 +2265,17 @@ void cmLocalGenerator::AddConfigVariableFlags(std::string& flags,
const std::string& config)
{
// Add the flags from the variable itself.
- std::string flagsVar = var;
- this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar));
+ this->AppendFlags(flags, this->Makefile->GetSafeDefinition(var));
// Add the flags from the build-type specific variable.
if (!config.empty()) {
- flagsVar += "_";
- flagsVar += cmSystemTools::UpperCase(config);
- this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar));
+ const std::string flagsVar =
+ cmStrCat(var, '_', cmSystemTools::UpperCase(config));
+ this->AppendFlags(flags, this->Makefile->GetSafeDefinition(flagsVar));
}
}
void cmLocalGenerator::AppendFlags(std::string& flags,
- const std::string& newFlags)
+ const std::string& newFlags) const
{
if (!newFlags.empty()) {
if (!flags.empty()) {
@@ -1840,19 +2285,284 @@ void cmLocalGenerator::AppendFlags(std::string& flags,
}
}
-void cmLocalGenerator::AppendFlags(std::string& flags, const char* newFlags)
+void cmLocalGenerator::AppendFlags(
+ std::string& flags, const std::vector<BT<std::string>>& newFlags) const
{
- if (newFlags && *newFlags) {
- this->AppendFlags(flags, std::string(newFlags));
+ for (BT<std::string> const& flag : newFlags) {
+ this->AppendFlags(flags, flag.Value);
}
}
void cmLocalGenerator::AppendFlagEscape(std::string& flags,
- const std::string& rawFlag)
+ const std::string& rawFlag) const
{
this->AppendFlags(flags, this->EscapeForShell(rawFlag));
}
+void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
+{
+ // FIXME: Handle all configurations in multi-config generators.
+ std::string config;
+ if (!this->GetGlobalGenerator()->IsMultiConfig()) {
+ config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ }
+ const std::string buildType = cmSystemTools::UpperCase(config);
+
+ // FIXME: Refactor collection of sources to not evaluate object libraries.
+ std::vector<cmSourceFile*> sources;
+ target->GetSourceFiles(sources, buildType);
+
+ for (const std::string& lang : { "C", "CXX", "OBJC", "OBJCXX" }) {
+ auto langSources =
+ std::count_if(sources.begin(), sources.end(), [lang](cmSourceFile* sf) {
+ return lang == sf->GetLanguage() &&
+ !sf->GetProperty("SKIP_PRECOMPILE_HEADERS");
+ });
+ if (langSources == 0) {
+ continue;
+ }
+
+ const std::string pchSource = target->GetPchSource(config, lang);
+ const std::string pchHeader = target->GetPchHeader(config, lang);
+
+ if (pchSource.empty() || pchHeader.empty()) {
+ continue;
+ }
+
+ const std::string pchExtension =
+ this->Makefile->GetSafeDefinition("CMAKE_PCH_EXTENSION");
+
+ if (pchExtension.empty()) {
+ continue;
+ }
+
+ const char* pchReuseFrom =
+ target->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
+
+ auto pch_sf = this->Makefile->GetOrCreateSource(
+ pchSource, false, cmSourceFileLocationKind::Known);
+
+ if (!this->GetGlobalGenerator()->IsXcode()) {
+ if (!pchReuseFrom) {
+ target->AddSource(pchSource, true);
+ }
+
+ const std::string pchFile = target->GetPchFile(config, lang);
+
+ // Exclude the pch files from linking
+ if (this->Makefile->IsOn("CMAKE_LINK_PCH")) {
+ if (!pchReuseFrom) {
+ pch_sf->SetProperty("OBJECT_OUTPUTS", pchFile.c_str());
+ } else {
+ auto reuseTarget =
+ this->GlobalGenerator->FindGeneratorTarget(pchReuseFrom);
+
+ if (this->Makefile->IsOn("CMAKE_PCH_COPY_COMPILE_PDB")) {
+
+ const std::string pdb_prefix =
+ this->GetGlobalGenerator()->IsMultiConfig()
+ ? cmStrCat(this->GlobalGenerator->GetCMakeCFGIntDir(), "/")
+ : "";
+
+ const std::string target_compile_pdb_dir = cmStrCat(
+ target->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/",
+ target->GetName(), ".dir/");
+
+ const std::string copy_script =
+ cmStrCat(target_compile_pdb_dir, "copy_idb_pdb.cmake");
+ cmGeneratedFileStream file(copy_script);
+
+ file << "# CMake generated file\n";
+ for (auto extension : { ".pdb", ".idb" }) {
+ const std::string from_file = cmStrCat(
+ reuseTarget->GetLocalGenerator()->GetCurrentBinaryDirectory(),
+ "/", pchReuseFrom, ".dir/${PDB_PREFIX}", pchReuseFrom,
+ extension);
+
+ const std::string to_dir = cmStrCat(
+ target->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/",
+ target->GetName(), ".dir/${PDB_PREFIX}");
+
+ const std::string to_file =
+ cmStrCat(to_dir, pchReuseFrom, extension);
+
+ std::string dest_file = to_file;
+
+ const std::string prefix = target->GetSafeProperty("PREFIX");
+ if (!prefix.empty()) {
+ dest_file = cmStrCat(to_dir, prefix, pchReuseFrom, extension);
+ }
+
+ file << "if (EXISTS \"" << from_file << "\" AND \"" << from_file
+ << "\" IS_NEWER_THAN \"" << dest_file << "\")\n";
+ file << " file(COPY \"" << from_file << "\""
+ << " DESTINATION \"" << to_dir << "\")\n";
+ if (!prefix.empty()) {
+ file << " file(REMOVE \"" << dest_file << "\")\n";
+ file << " file(RENAME \"" << to_file << "\" \"" << dest_file
+ << "\")\n";
+ }
+ file << "endif()\n";
+ }
+
+ cmCustomCommandLines commandLines;
+ cmCustomCommandLine currentLine;
+ currentLine.push_back(cmSystemTools::GetCMakeCommand());
+ currentLine.push_back(cmStrCat("-DPDB_PREFIX=", pdb_prefix));
+ currentLine.push_back("-P");
+ currentLine.push_back(copy_script);
+ commandLines.push_back(std::move(currentLine));
+
+ const std::string no_main_dependency;
+ const std::vector<std::string> no_deps;
+ const char* no_message = "";
+ const char* no_current_dir = nullptr;
+ std::vector<std::string> no_byproducts;
+
+ std::vector<std::string> outputs;
+ outputs.push_back(cmStrCat(target_compile_pdb_dir, pdb_prefix,
+ pchReuseFrom, ".pdb"));
+
+ if (this->GetGlobalGenerator()->IsMultiConfig()) {
+ this->Makefile->AddCustomCommandToTarget(
+ target->GetName(), outputs, no_deps, commandLines,
+ cmCustomCommandType::PRE_BUILD, no_message, no_current_dir);
+ } else {
+ cmImplicitDependsList no_implicit_depends;
+ cmSourceFile* copy_rule =
+ this->Makefile->AddCustomCommandToOutput(
+ outputs, no_byproducts, no_deps, no_main_dependency,
+ no_implicit_depends, commandLines, no_message,
+ no_current_dir);
+
+ if (copy_rule) {
+ target->AddSource(copy_rule->ResolveFullPath());
+ }
+ }
+
+ target->Target->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY",
+ target_compile_pdb_dir.c_str());
+ }
+
+ std::string pchSourceObj =
+ reuseTarget->GetPchFileObject(config, lang);
+
+ // Link to the pch object file
+ target->Target->AppendProperty(
+ "LINK_FLAGS",
+ cmStrCat(" ", this->ConvertToOutputFormat(pchSourceObj, SHELL))
+ .c_str(),
+ true);
+ }
+ } else {
+ pch_sf->SetProperty("PCH_EXTENSION", pchExtension.c_str());
+ }
+
+ // Add pchHeader to source files, which will
+ // be grouped as "Precompile Header File"
+ auto pchHeader_sf = this->Makefile->GetOrCreateSource(
+ pchHeader, false, cmSourceFileLocationKind::Known);
+ std::string err;
+ pchHeader_sf->ResolveFullPath(&err);
+ target->AddSource(pchHeader);
+ }
+ }
+}
+
+void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
+{
+ if (!target->GetPropertyAsBool("UNITY_BUILD")) {
+ return;
+ }
+
+ // FIXME: Handle all configurations in multi-config generators.
+ std::string config;
+ if (!this->GetGlobalGenerator()->IsMultiConfig()) {
+ config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ }
+
+ const std::string buildType = cmSystemTools::UpperCase(config);
+
+ std::string filename_base =
+ cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/",
+ target->GetName(), ".dir/Unity/");
+
+ // FIXME: Refactor collection of sources to not evaluate object libraries.
+ std::vector<cmSourceFile*> sources;
+ target->GetSourceFiles(sources, buildType);
+
+ auto batchSizeString = target->GetProperty("UNITY_BUILD_BATCH_SIZE");
+ const size_t unityBatchSize =
+ static_cast<size_t>(std::atoi(batchSizeString));
+
+ auto beforeInclude = target->GetProperty("UNITY_BUILD_CODE_BEFORE_INCLUDE");
+ auto afterInclude = target->GetProperty("UNITY_BUILD_CODE_AFTER_INCLUDE");
+
+ for (std::string lang : { "C", "CXX" }) {
+ std::vector<cmSourceFile*> filtered_sources;
+ std::copy_if(sources.begin(), sources.end(),
+ std::back_inserter(filtered_sources), [&](cmSourceFile* sf) {
+ return sf->GetLanguage() == lang &&
+ !sf->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION") &&
+ !sf->GetPropertyAsBool("HEADER_FILE_ONLY") &&
+ !sf->GetProperty("COMPILE_OPTIONS") &&
+ !sf->GetProperty("COMPILE_DEFINITIONS") &&
+ !sf->GetProperty("COMPILE_FLAGS") &&
+ !sf->GetProperty("INCLUDE_DIRECTORIES");
+ });
+
+ size_t batchSize = unityBatchSize;
+ if (unityBatchSize == 0) {
+ batchSize = filtered_sources.size();
+ }
+
+ for (size_t itemsLeft = filtered_sources.size(), chunk = batchSize,
+ batch = 0;
+ itemsLeft > 0; itemsLeft -= chunk, ++batch) {
+
+ chunk = std::min(itemsLeft, batchSize);
+
+ std::string filename = cmStrCat(filename_base, "unity_", batch,
+ (lang == "C") ? "_c.c" : "_cxx.cxx");
+
+ const std::string filename_tmp = cmStrCat(filename, ".tmp");
+ {
+ size_t begin = batch * batchSize;
+ size_t end = begin + chunk;
+
+ cmGeneratedFileStream file(
+ filename_tmp, false,
+ this->GetGlobalGenerator()->GetMakefileEncoding());
+ file << "/* generated by CMake */\n\n";
+
+ for (; begin != end; ++begin) {
+ cmSourceFile* sf = filtered_sources[begin];
+
+ target->AddSourceFileToUnityBatch(sf->ResolveFullPath());
+ sf->SetProperty("UNITY_SOURCE_FILE", filename.c_str());
+
+ if (beforeInclude) {
+ file << beforeInclude << "\n";
+ }
+
+ file << "#include \"" << sf->ResolveFullPath() << "\"\n";
+
+ if (afterInclude) {
+ file << afterInclude << "\n";
+ }
+ }
+ }
+ cmSystemTools::MoveFileIfDifferent(filename_tmp, filename);
+
+ target->AddSource(filename, true);
+
+ auto unity = this->Makefile->GetOrCreateSource(filename);
+ unity->SetProperty("SKIP_UNITY_BUILD_INCLUSION", "ON");
+ unity->SetProperty("UNITY_SOURCE_FILE", filename.c_str());
+ }
+ }
+}
+
void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags,
cmGeneratorTarget* target,
const std::string& config,
@@ -1873,43 +2583,186 @@ void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags,
const std::string name = "CMAKE_" + lang + "_LINK_OPTIONS_IPO";
const char* rawFlagsList = this->Makefile->GetDefinition(name);
- if (rawFlagsList == CM_NULLPTR) {
+ if (rawFlagsList == nullptr) {
+ return;
+ }
+
+ std::vector<std::string> flagsList = cmExpandedList(rawFlagsList);
+ for (std::string const& o : flagsList) {
+ this->AppendFlagEscape(flags, o);
+ }
+}
+
+void cmLocalGenerator::AppendPositionIndependentLinkerFlags(
+ std::string& flags, cmGeneratorTarget* target, const std::string& config,
+ const std::string& lang)
+{
+ // For now, only EXECUTABLE is concerned
+ if (target->GetType() != cmStateEnums::EXECUTABLE) {
+ return;
+ }
+
+ const char* PICValue = target->GetLinkPIEProperty(config);
+ if (PICValue == nullptr) {
+ // POSITION_INDEPENDENT_CODE is not set
+ return;
+ }
+
+ const std::string mode = cmIsOn(PICValue) ? "PIE" : "NO_PIE";
+
+ std::string supported = "CMAKE_" + lang + "_LINK_" + mode + "_SUPPORTED";
+ if (cmIsOff(this->Makefile->GetDefinition(supported))) {
+ return;
+ }
+
+ std::string name = "CMAKE_" + lang + "_LINK_OPTIONS_" + mode;
+
+ auto pieFlags = this->Makefile->GetSafeDefinition(name);
+ if (pieFlags.empty()) {
+ return;
+ }
+
+ std::vector<std::string> flagsList = cmExpandedList(pieFlags);
+ for (const auto& flag : flagsList) {
+ this->AppendFlagEscape(flags, flag);
+ }
+}
+
+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;
}
- std::vector<std::string> flagsList;
- cmSystemTools::ExpandListArgument(rawFlagsList, flagsList);
- for (std::vector<std::string>::const_iterator oi = flagsList.begin();
- oi != flagsList.end(); ++oi) {
- this->AppendFlagEscape(flags, *oi);
+ // Expand the list of options.
+ std::vector<std::string> options_vec = cmExpandedList(options_list);
+ 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)) {
+ this->AppendFlagEscape(options, opt);
+ }
+ }
+ } else {
+ for (std::string const& opt : options_vec) {
+ this->AppendFlagEscape(options, opt);
+ }
+ }
+}
+
+void cmLocalGenerator::AppendCompileOptions(
+ std::vector<BT<std::string>>& options,
+ const std::vector<BT<std::string>>& options_vec, const char* regex) const
+{
+ if (regex != nullptr) {
+ // Filter flags upon specified regular expressions.
+ cmsys::RegularExpression r(regex);
+
+ for (BT<std::string> const& opt : options_vec) {
+ if (r.find(opt.Value)) {
+ std::string flag;
+ this->AppendFlagEscape(flag, opt.Value);
+ options.emplace_back(std::move(flag), opt.Backtrace);
+ }
+ }
+ } else {
+ for (BT<std::string> const& opt : options_vec) {
+ std::string flag;
+ this->AppendFlagEscape(flag, opt.Value);
+ options.emplace_back(std::move(flag), opt.Backtrace);
+ }
+ }
+}
+
+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 = cmExpandedList(includes_list);
+ 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(MessageType::FATAL_ERROR, e.str());
+ return;
+ }
+
+ std::string inc = include;
+
+ if (!cmIsOff(inc)) {
+ 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
+ std::string const& defines_list) const
+{
+ std::set<BT<std::string>> tmp;
+ this->AppendDefines(tmp, ExpandListWithBacktrace(defines_list));
+ for (BT<std::string> const& i : tmp) {
+ defines.emplace(i.Value);
+ }
+}
+
+void cmLocalGenerator::AppendDefines(std::set<BT<std::string>>& defines,
+ std::string const& defines_list) const
{
// Short-circuit if there are no definitions.
- if (!defines_list) {
+ if (defines_list.empty()) {
return;
}
// Expand the list of definitions.
- std::vector<std::string> defines_vec;
- cmSystemTools::ExpandListArgument(defines_list, defines_vec);
- this->AppendDefines(defines, defines_vec);
+ this->AppendDefines(defines, ExpandListWithBacktrace(defines_list));
}
void cmLocalGenerator::AppendDefines(
- std::set<std::string>& defines,
- const std::vector<std::string>& defines_vec) const
+ std::set<BT<std::string>>& defines,
+ const std::vector<BT<std::string>>& defines_vec) const
{
- for (std::vector<std::string>::const_iterator di = defines_vec.begin();
- di != defines_vec.end(); ++di) {
+ for (BT<std::string> const& d : defines_vec) {
// Skip unsupported definitions.
- if (!this->CheckDefinition(*di)) {
+ if (!this->CheckDefinition(d.Value)) {
continue;
}
- defines.insert(*di);
+ defines.insert(d);
}
}
@@ -1920,19 +2773,14 @@ void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines,
// Lookup the define flag for the current language.
std::string dflag = "-D";
if (!lang.empty()) {
- std::string defineFlagVar = "CMAKE_";
- defineFlagVar += lang;
- defineFlagVar += "_DEFINE_FLAG";
- const char* df = this->Makefile->GetDefinition(defineFlagVar);
+ const char* df =
+ this->Makefile->GetDefinition(cmStrCat("CMAKE_", lang, "_DEFINE_FLAG"));
if (df && *df) {
dflag = df;
}
}
-
- std::set<std::string>::const_iterator defineIt = defines.begin();
- const std::set<std::string>::const_iterator defineEnd = defines.end();
const char* itemSeparator = definesString.empty() ? "" : " ";
- for (; defineIt != defineEnd; ++defineIt) {
+ for (std::string const& define : defines) {
// Append the definition with proper escaping.
std::string def = dflag;
if (this->GetState()->UseWatcomWMake()) {
@@ -1946,7 +2794,7 @@ void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines,
// command line without any escapes. However we still have to
// get the '$' and '#' characters through WMake as '$$' and
// '$#'.
- for (const char* c = defineIt->c_str(); *c; ++c) {
+ for (const char* c = define.c_str(); *c; ++c) {
if (*c == '$' || *c == '#') {
def += '$';
}
@@ -1955,11 +2803,11 @@ void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines,
} else {
// Make the definition appear properly on the command line. Use
// -DNAME="value" instead of -D"NAME=value" for historical reasons.
- std::string::size_type eq = defineIt->find("=");
- def += defineIt->substr(0, eq);
+ std::string::size_type eq = define.find('=');
+ def += define.substr(0, eq);
if (eq != std::string::npos) {
def += "=";
- def += this->EscapeForShell(defineIt->c_str() + eq + 1, true);
+ def += this->EscapeForShell(define.substr(eq + 1), true);
}
}
definesString += itemSeparator;
@@ -1972,16 +2820,12 @@ void cmLocalGenerator::AppendFeatureOptions(std::string& flags,
const std::string& lang,
const char* feature)
{
- std::string optVar = "CMAKE_";
- optVar += lang;
- optVar += "_COMPILE_OPTIONS_";
- optVar += feature;
- if (const char* optionList = this->Makefile->GetDefinition(optVar)) {
- std::vector<std::string> options;
- cmSystemTools::ExpandListArgument(optionList, options);
- for (std::vector<std::string>::const_iterator oi = options.begin();
- oi != options.end(); ++oi) {
- this->AppendFlagEscape(flags, *oi);
+ const char* optionList = this->Makefile->GetDefinition(
+ cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_", feature));
+ if (optionList != nullptr) {
+ std::vector<std::string> options = cmExpandedList(optionList);
+ for (std::string const& o : options) {
+ this->AppendFlagEscape(flags, o);
}
}
}
@@ -2003,7 +2847,7 @@ const char* cmLocalGenerator::GetFeature(const std::string& feature,
}
snp = snp.GetBuildsystemDirectoryParent();
}
- return CM_NULLPTR;
+ return nullptr;
}
std::string cmLocalGenerator::GetProjectName() const
@@ -2025,10 +2869,9 @@ std::string cmLocalGenerator::ConstructComment(
comment = "Generating ";
const char* sep = "";
std::string currentBinaryDir = this->GetCurrentBinaryDirectory();
- for (std::vector<std::string>::const_iterator o = ccg.GetOutputs().begin();
- o != ccg.GetOutputs().end(); ++o) {
+ for (std::string const& o : ccg.GetOutputs()) {
comment += sep;
- comment += this->ConvertToRelativePath(currentBinaryDir, *o);
+ comment += this->MaybeConvertToRelativePath(currentBinaryDir, o);
sep = ", ";
}
return comment;
@@ -2058,37 +2901,36 @@ void cmLocalGenerator::GenerateTargetInstallRules(
{
// Convert the old-style install specification from each target to
// an install generator and run it.
- std::vector<cmGeneratorTarget*> tgts = this->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin();
- l != tgts.end(); ++l) {
- if ((*l)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets();
+ for (cmGeneratorTarget* l : tgts) {
+ if (l->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
// Include the user-specified pre-install script for this target.
- if (const char* preinstall = (*l)->GetProperty("PRE_INSTALL_SCRIPT")) {
- cmInstallScriptGenerator g(preinstall, false, CM_NULLPTR, false);
+ if (const char* preinstall = l->GetProperty("PRE_INSTALL_SCRIPT")) {
+ cmInstallScriptGenerator g(preinstall, false, nullptr, false);
g.Generate(os, config, configurationTypes);
}
// Install this target if a destination is given.
- if ((*l)->Target->GetInstallPath() != "") {
+ if (!l->Target->GetInstallPath().empty()) {
// Compute the full install destination. Note that converting
// to unix slashes also removes any trailing slash.
// We also skip over the leading slash given by the user.
- std::string destination = (*l)->Target->GetInstallPath().substr(1);
+ std::string destination = l->Target->GetInstallPath().substr(1);
cmSystemTools::ConvertToUnixSlashes(destination);
if (destination.empty()) {
destination = ".";
}
// Generate the proper install generator for this target type.
- switch ((*l)->GetType()) {
+ switch (l->GetType()) {
case cmStateEnums::EXECUTABLE:
case cmStateEnums::STATIC_LIBRARY:
case cmStateEnums::MODULE_LIBRARY: {
// Use a target install generator.
- cmInstallTargetGeneratorLocal g(this, (*l)->GetName(),
+ cmInstallTargetGeneratorLocal g(this, l->GetName(),
destination.c_str(), false);
g.Generate(os, config, configurationTypes);
} break;
@@ -2097,18 +2939,18 @@ void cmLocalGenerator::GenerateTargetInstallRules(
// Special code to handle DLL. Install the import library
// to the normal destination and the DLL to the runtime
// destination.
- cmInstallTargetGeneratorLocal g1(this, (*l)->GetName(),
+ cmInstallTargetGeneratorLocal g1(this, l->GetName(),
destination.c_str(), true);
g1.Generate(os, config, configurationTypes);
// We also skip over the leading slash given by the user.
- destination = (*l)->Target->GetRuntimeInstallPath().substr(1);
+ destination = l->Target->GetRuntimeInstallPath().substr(1);
cmSystemTools::ConvertToUnixSlashes(destination);
- cmInstallTargetGeneratorLocal g2(this, (*l)->GetName(),
+ cmInstallTargetGeneratorLocal g2(this, l->GetName(),
destination.c_str(), false);
g2.Generate(os, config, configurationTypes);
#else
// Use a target install generator.
- cmInstallTargetGeneratorLocal g(this, (*l)->GetName(),
+ cmInstallTargetGeneratorLocal g(this, l->GetName(),
destination.c_str(), false);
g.Generate(os, config, configurationTypes);
#endif
@@ -2119,8 +2961,8 @@ void cmLocalGenerator::GenerateTargetInstallRules(
}
// Include the user-specified post-install script for this target.
- if (const char* postinstall = (*l)->GetProperty("POST_INSTALL_SCRIPT")) {
- cmInstallScriptGenerator g(postinstall, false, CM_NULLPTR, false);
+ if (const char* postinstall = l->GetProperty("POST_INSTALL_SCRIPT")) {
+ cmInstallScriptGenerator g(postinstall, false, nullptr, false);
g.Generate(os, config, configurationTypes);
}
}
@@ -2136,8 +2978,8 @@ static bool cmLocalGeneratorShortenObjectName(std::string& objName,
objName.find('/', objName.size() - max_len + 32);
if (pos != std::string::npos) {
cmCryptoHash md5(cmCryptoHash::AlgoMD5);
- std::string md5name = md5.HashString(objName.substr(0, pos));
- md5name += objName.substr(pos);
+ std::string md5name = cmStrCat(md5.HashString(objName.substr(0, pos)),
+ cm::string_view(objName).substr(pos));
objName = md5name;
// The object name is now short enough.
@@ -2172,8 +3014,7 @@ std::string& cmLocalGenerator::CreateSafeUniqueObjectFileName(
const std::string& sin, std::string const& dir_max)
{
// Look for an existing mapped name for this object file.
- std::map<std::string, std::string>::iterator it =
- this->UniqueObjectNamesMap.find(sin);
+ auto it = this->UniqueObjectNamesMap.find(sin);
// If no entry exists create one.
if (it == this->UniqueObjectNamesMap.end()) {
@@ -2235,7 +3076,7 @@ std::string& cmLocalGenerator::CreateSafeUniqueObjectFileName(
<< "cannot be safely placed under this directory. "
<< "The build may not work correctly.";
/* clang-format on */
- this->IssueMessage(cmake::WARNING, m.str());
+ this->IssueMessage(MessageType::WARNING, m.str());
}
}
#else
@@ -2286,17 +3127,17 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
std::string const& fullPath = source.GetFullPath();
// Try referencing the source relative to the source tree.
- std::string relFromSource =
- this->ConvertToRelativePath(this->GetCurrentSourceDirectory(), fullPath);
+ std::string relFromSource = this->MaybeConvertToRelativePath(
+ 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);
+ std::string relFromBinary = this->MaybeConvertToRelativePath(
+ 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
@@ -2315,12 +3156,29 @@ 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());
}
}
+ // Ensure that for the CMakeFiles/<target>.dir/generated_source_file
+ // we don't end up having:
+ // CMakeFiles/<target>.dir/CMakeFiles/<target>.dir/generated_source_file.obj
+ const char* unitySourceFile = source.GetProperty("UNITY_SOURCE_FILE");
+ const char* pchExtension = source.GetProperty("PCH_EXTENSION");
+ const bool isPchObject = objectName.find("cmake_pch") != std::string::npos;
+ if (unitySourceFile || pchExtension || isPchObject) {
+ if (pchExtension) {
+ customOutputExtension = pchExtension;
+ }
+
+ cmsys::RegularExpression var("(CMakeFiles/[^/]+.dir/)");
+ if (var.find(objectName)) {
+ objectName.erase(var.start(), var.end() - var.start());
+ }
+ }
+
// Replace the original source file extension with the object file
// extension.
bool keptSourceExtension = true;
@@ -2332,10 +3190,8 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
if (!replaceExt) {
std::string lang = source.GetLanguage();
if (!lang.empty()) {
- std::string repVar = "CMAKE_";
- repVar += lang;
- repVar += "_OUTPUT_EXTENSION_REPLACE";
- replaceExt = this->Makefile->IsOn(repVar);
+ replaceExt = this->Makefile->IsOn(
+ cmStrCat("CMAKE_", lang, "_OUTPUT_EXTENSION_REPLACE"));
}
}
@@ -2373,26 +3229,33 @@ 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();
}
-const char* cmLocalGenerator::GetCurrentBinaryDirectory() const
+std::string const& cmLocalGenerator::GetCurrentBinaryDirectory() const
{
return this->StateSnapshot.GetDirectory().GetCurrentBinary();
}
-const char* cmLocalGenerator::GetCurrentSourceDirectory() const
+std::string const& cmLocalGenerator::GetCurrentSourceDirectory() const
{
return this->StateSnapshot.GetDirectory().GetCurrentSource();
}
+std::string cmLocalGenerator::MaybeConvertToRelativePath(
+ std::string const& local_path, std::string const& remote_path) const
+{
+ return this->StateSnapshot.GetDirectory().ConvertToRelPathIfNotContained(
+ local_path, remote_path);
+}
+
std::string cmLocalGenerator::GetTargetDirectory(
const cmGeneratorTarget* /*unused*/) const
{
@@ -2479,7 +3342,7 @@ bool cmLocalGenerator::CheckDefinition(std::string const& define) const
<< "CMake is dropping a preprocessor definition: " << define << "\n"
<< "Consider defining the macro in a (configured) header file.\n";
/* clang-format on */
- cmSystemTools::Message(e.str().c_str());
+ cmSystemTools::Message(e.str());
return false;
}
}
@@ -2494,7 +3357,7 @@ bool cmLocalGenerator::CheckDefinition(std::string const& define) const
<< "CMake is dropping a preprocessor definition: " << define << "\n"
<< "Consider defining the macro in a (configured) header file.\n";
/* clang-format on */
- cmSystemTools::Message(e.str().c_str());
+ cmSystemTools::Message(e.str());
return false;
}
@@ -2512,22 +3375,22 @@ static void cmLGInfoProp(cmMakefile* mf, cmGeneratorTarget* target,
void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target,
const std::string& targetName,
- const char* fname)
+ const std::string& fname)
{
// 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())) {
- std::string inMod = this->Makefile->GetModulesFile(inFile.c_str());
+ if (!cmSystemTools::FileIsFullPath(inFile)) {
+ std::string inMod = this->Makefile->GetModulesFile(inFile);
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.";
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
return;
}
@@ -2537,7 +3400,7 @@ void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target,
// back to the directory-level values set by the user.
cmMakefile* mf = this->Makefile;
cmMakefile::ScopePushPop varScope(mf);
- mf->AddDefinition("MACOSX_BUNDLE_EXECUTABLE_NAME", targetName.c_str());
+ mf->AddDefinition("MACOSX_BUNDLE_EXECUTABLE_NAME", targetName);
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_INFO_STRING");
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_ICON_FILE");
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_GUI_IDENTIFIER");
@@ -2546,26 +3409,27 @@ void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target,
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_SHORT_VERSION_STRING");
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_BUNDLE_VERSION");
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_COPYRIGHT");
- mf->ConfigureFile(inFile.c_str(), fname, false, false, false);
+ mf->ConfigureFile(inFile, fname, false, false, false);
}
void cmLocalGenerator::GenerateFrameworkInfoPList(
- cmGeneratorTarget* target, const std::string& targetName, const char* fname)
+ cmGeneratorTarget* target, const std::string& targetName,
+ const std::string& fname)
{
// 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())) {
- std::string inMod = this->Makefile->GetModulesFile(inFile.c_str());
+ if (!cmSystemTools::FileIsFullPath(inFile)) {
+ std::string inMod = this->Makefile->GetModulesFile(inFile);
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.";
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
return;
}
@@ -2575,10 +3439,10 @@ void cmLocalGenerator::GenerateFrameworkInfoPList(
// back to the directory-level values set by the user.
cmMakefile* mf = this->Makefile;
cmMakefile::ScopePushPop varScope(mf);
- mf->AddDefinition("MACOSX_FRAMEWORK_NAME", targetName.c_str());
+ mf->AddDefinition("MACOSX_FRAMEWORK_NAME", targetName);
cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_ICON_FILE");
cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_IDENTIFIER");
cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_SHORT_VERSION_STRING");
cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_BUNDLE_VERSION");
- mf->ConfigureFile(inFile.c_str(), fname, false, false, false);
+ mf->ConfigureFile(inFile, fname, false, false, false);
}
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 9f78be465..12359dbdd 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -3,20 +3,22 @@
#ifndef cmLocalGenerator_h
#define cmLocalGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cm_kwiml.h"
#include <iosfwd>
#include <map>
#include <set>
#include <string>
+#include <unordered_map>
#include <vector>
+#include "cm_kwiml.h"
+
#include "cmListFileCache.h"
+#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmStateSnapshot.h"
-#include "cmake.h"
class cmComputeLinkInformation;
class cmCustomCommandGenerator;
@@ -27,6 +29,7 @@ class cmMakefile;
class cmRulePlaceholderExpander;
class cmSourceFile;
class cmState;
+class cmake;
/** \class cmLocalGenerator
* \brief Create required build files for a directory.
@@ -74,13 +77,13 @@ public:
bool IsRootMakefile() const;
- ///! Get the makefile for this generator
+ //! Get the makefile for this generator
cmMakefile* GetMakefile() { return this->Makefile; }
- ///! Get the makefile for this generator, const version
+ //! Get the makefile for this generator, const version
const cmMakefile* GetMakefile() const { return this->Makefile; }
- ///! Get the GlobalGenerator this is associated with
+ //! Get the GlobalGenerator this is associated with
cmGlobalGenerator* GetGlobalGenerator() { return this->GlobalGenerator; }
const cmGlobalGenerator* GetGlobalGenerator() const
{
@@ -116,15 +119,23 @@ public:
void AddCompilerRequirementFlag(std::string& flags,
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);
+ //! Append flags to a string.
+ virtual void AppendFlags(std::string& flags,
+ const std::string& newFlags) const;
+ virtual void AppendFlags(std::string& flags,
+ const std::vector<BT<std::string>>& newFlags) const;
virtual void AppendFlagEscape(std::string& flags,
- const std::string& rawFlag);
+ const std::string& rawFlag) const;
+ void AddPchDependencies(cmGeneratorTarget* target);
+ void AddUnityBuild(cmGeneratorTarget* target);
void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target,
const std::string& config,
const std::string& lang);
- ///! Get the include flags for the current makefile and language
+ void AppendPositionIndependentLinkerFlags(std::string& flags,
+ cmGeneratorTarget* target,
+ const std::string& config,
+ const std::string& lang);
+ //! Get the include flags for the current makefile and language
std::string GetIncludeFlags(const std::vector<std::string>& includes,
cmGeneratorTarget* target,
const std::string& lang,
@@ -137,11 +148,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);
@@ -151,18 +157,51 @@ 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.
*/
void AppendDefines(std::set<std::string>& defines,
- const char* defines_list) const;
- void AppendDefines(std::set<std::string>& defines,
- std::string const& defines_list) const
+ std::string const& defines_list) const;
+ void AppendDefines(std::set<BT<std::string>>& defines,
+ std::string const& defines_list) const;
+ void AppendDefines(std::set<BT<std::string>>& defines,
+ const std::vector<BT<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->AppendDefines(defines, defines_list.c_str());
+ this->AppendCompileOptions(options, options_list.c_str(), regex);
}
- void AppendDefines(std::set<std::string>& defines,
- const std::vector<std::string>& defines_vec) const;
+ void AppendCompileOptions(std::string& options,
+ const std::vector<std::string>& options_vec,
+ const char* regex = nullptr) const;
+ void AppendCompileOptions(std::vector<BT<std::string>>& options,
+ const std::vector<BT<std::string>>& options_vec,
+ const char* regex = nullptr) const;
/**
* Join a set of defines into a definesString with a space separator.
@@ -201,24 +240,57 @@ public:
virtual void ClearDependencies(cmMakefile* /* mf */, bool /* verbose */) {}
/** Called from command-line hook to update dependencies. */
- virtual bool UpdateDependencies(const char* /* tgtInfo */, bool /*verbose*/,
- bool /*color*/)
+ virtual bool UpdateDependencies(const std::string& /* tgtInfo */,
+ bool /*verbose*/, bool /*color*/)
{
return true;
}
- /** Get the include flags for the current makefile and language. */
+ /** @brief Get the include directories for the current makefile and language
+ * and optional the compiler implicit include directories.
+ *
+ * @arg stripImplicitDirs Strip all directories found in
+ * CMAKE_<LANG>_IMPLICIT_INCLUDE_DIRECTORIES from the result.
+ * @arg appendAllImplicitDirs Append all directories found in
+ * CMAKE_<LANG>_IMPLICIT_INCLUDE_DIRECTORIES to the result.
+ */
+ std::vector<BT<std::string>> GetIncludeDirectoriesImplicit(
+ cmGeneratorTarget const* target, std::string const& lang = "C",
+ std::string const& config = "", bool stripImplicitDirs = true,
+ bool appendAllImplicitDirs = false) const;
+
+ /** @brief Get the include directories for the current makefile and language
+ * and optional the compiler implicit include directories.
+ *
+ * @arg dirs Directories are appended to this list
+ */
+ void GetIncludeDirectoriesImplicit(std::vector<std::string>& dirs,
+ cmGeneratorTarget const* target,
+ const std::string& lang = "C",
+ const std::string& config = "",
+ bool stripImplicitDirs = true,
+ bool appendAllImplicitDirs = false) const;
+
+ /** @brief Get the include directories for the current makefile and language.
+ * @arg dirs Include directories are appended to this list
+ */
void GetIncludeDirectories(std::vector<std::string>& dirs,
cmGeneratorTarget const* target,
const std::string& lang = "C",
- const std::string& config = "",
- bool stripImplicitInclDirs = true) const;
+ const std::string& config = "") const;
+
+ /** @brief Get the include directories for the current makefile and language.
+ * @return The include directory list
+ */
+ std::vector<BT<std::string>> GetIncludeDirectories(
+ cmGeneratorTarget const* target, std::string const& lang = "C",
+ std::string const& config = "") const;
+
void AddCompileOptions(std::string& flags, cmGeneratorTarget* target,
const std::string& lang, const std::string& config);
- void AddCompileDefinitions(std::set<std::string>& defines,
- cmGeneratorTarget const* target,
- const std::string& config,
- const std::string& lang) const;
+ void AddCompileOptions(std::vector<BT<std::string>>& flags,
+ cmGeneratorTarget* target, const std::string& lang,
+ const std::string& config);
std::string GetProjectName() const;
@@ -257,37 +329,51 @@ 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;
+ std::string const& GetCurrentBinaryDirectory() const;
+ std::string const& GetCurrentSourceDirectory() const;
/**
- * Generate a Mac OS X application bundle Info.plist file.
+ * Convert the given remote path to a relative path with respect to
+ * the given local path. Both paths must use forward slashes and not
+ * already be escaped or quoted.
+ * The conversion is skipped if the paths are not both in the source
+ * or both in the binary tree.
+ */
+ std::string MaybeConvertToRelativePath(std::string const& local_path,
+ std::string const& remote_path) const;
+
+ /**
+ * Generate a macOS application bundle Info.plist file.
*/
void GenerateAppleInfoPList(cmGeneratorTarget* target,
const std::string& targetName,
- const char* fname);
+ const std::string& fname);
/**
- * Generate a Mac OS X framework Info.plist file.
+ * Generate a macOS framework Info.plist file.
*/
void GenerateFrameworkInfoPList(cmGeneratorTarget* target,
const std::string& targetName,
- const char* fname);
+ const std::string& fname);
/** Construct a comment for a custom command. */
std::string ConstructComment(cmCustomCommandGenerator const& ccg,
const char* default_comment = "");
// Compute object file names.
std::string GetObjectFileNameWithoutTarget(
const cmSourceFile& source, std::string const& dir_max,
- bool* hasSourceExtension = CM_NULLPTR,
- char const* customOutputExtension = CM_NULLPTR);
+ bool* hasSourceExtension = nullptr,
+ char const* customOutputExtension = nullptr);
/** Fill out the static linker flags for the given target. */
void GetStaticLibraryFlags(std::string& flags, std::string const& config,
+ std::string const& linkLanguage,
cmGeneratorTarget* target);
+ std::vector<BT<std::string>> GetStaticLibraryFlags(
+ std::string const& config, std::string const& linkLanguage,
+ cmGeneratorTarget* target);
/** Fill out these strings for the given target. Libraries to link,
* flags, and linkflags. */
@@ -296,12 +382,23 @@ public:
std::string& flags, std::string& linkFlags,
std::string& frameworkPath, std::string& linkPath,
cmGeneratorTarget* target);
+ void GetTargetFlags(
+ cmLinkLineComputer* linkLineComputer, const std::string& config,
+ std::vector<BT<std::string>>& linkLibs, std::string& flags,
+ std::vector<BT<std::string>>& linkFlags, std::string& frameworkPath,
+ std::vector<BT<std::string>>& linkPath, cmGeneratorTarget* target);
void GetTargetDefines(cmGeneratorTarget const* target,
std::string const& config, std::string const& lang,
std::set<std::string>& defines) const;
+ std::set<BT<std::string>> GetTargetDefines(cmGeneratorTarget const* target,
+ std::string const& config,
+ std::string const& lang) const;
void GetTargetCompileFlags(cmGeneratorTarget* target,
std::string const& config,
std::string const& lang, std::string& flags);
+ std::vector<BT<std::string>> GetTargetCompileFlags(cmGeneratorTarget* target,
+ std::string const& config,
+ std::string const& lang);
std::string GetFrameworkFlags(std::string const& l,
std::string const& config,
@@ -311,15 +408,16 @@ public:
virtual void ComputeObjectFilenames(
std::map<cmSourceFile const*, std::string>& mapping,
- cmGeneratorTarget const* gt = CM_NULLPTR);
+ cmGeneratorTarget const* gt = nullptr);
bool IsWindowsShell() const;
bool IsWatcomWMake() const;
bool IsMinGWMake() const;
bool IsNMake() const;
- void IssueMessage(cmake::MessageType t, std::string const& text) const;
+ void IssueMessage(MessageType t, std::string const& text) const;
+ void CreateEvaluationFileOutputs();
void CreateEvaluationFileOutputs(const std::string& config);
void ProcessEvaluationFiles(std::vector<std::string>& generatedFiles);
@@ -327,11 +425,16 @@ public:
const std::string& prop);
protected:
- ///! put all the libraries for a target on into the given stream
+ //! put all the libraries for a target on into the given stream
void OutputLinkLibraries(cmComputeLinkInformation* pcli,
cmLinkLineComputer* linkLineComputer,
std::string& linkLibraries,
std::string& frameworkPath, std::string& linkPath);
+ void OutputLinkLibraries(cmComputeLinkInformation* pcli,
+ cmLinkLineComputer* linkLineComputer,
+ std::vector<BT<std::string>>& linkLibraries,
+ std::string& frameworkPath,
+ std::vector<BT<std::string>>& linkPath);
// Handle old-style install rules stored in the targets.
void GenerateTargetInstallRules(
@@ -353,9 +456,15 @@ protected:
std::string::size_type ObjectPathMax;
std::set<std::string> ObjectMaxPathViolations;
- std::set<cmGeneratorTarget const*> WarnCMP0063;
+ std::set<std::string> EnvCPATH;
+
+ using GeneratorTargetMap =
+ std::unordered_map<std::string, cmGeneratorTarget*>;
+ GeneratorTargetMap GeneratorTargetSearchIndex;
std::vector<cmGeneratorTarget*> GeneratorTargets;
- std::vector<cmGeneratorTarget*> ImportedGeneratorTargets;
+
+ std::set<cmGeneratorTarget const*> WarnCMP0063;
+ GeneratorTargetMap ImportedGeneratorTargets;
std::vector<cmGeneratorTarget*> OwnedImportedGeneratorTargets;
std::map<std::string, std::string> AliasTargets;
@@ -379,7 +488,7 @@ private:
void ComputeObjectMaxPath();
};
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
bool cmLocalGeneratorCheckObjectName(std::string& objName,
std::string::size_type dir_len,
std::string::size_type max_total_len);
diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx
index 5f37af528..4b10798e1 100644
--- a/Source/cmLocalGhsMultiGenerator.cxx
+++ b/Source/cmLocalGhsMultiGenerator.cxx
@@ -2,11 +2,16 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalGhsMultiGenerator.h"
-#include "cmGeneratedFileStream.h"
+#include <algorithm>
+#include <utility>
+
#include "cmGeneratorTarget.h"
#include "cmGhsMultiTargetGenerator.h"
-#include "cmGlobalGhsMultiGenerator.h"
-#include "cmMakefile.h"
+#include "cmGlobalGenerator.h"
+#include "cmSourceFile.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
cmLocalGhsMultiGenerator::cmLocalGhsMultiGenerator(cmGlobalGenerator* gg,
cmMakefile* mf)
@@ -14,20 +19,80 @@ cmLocalGhsMultiGenerator::cmLocalGhsMultiGenerator(cmGlobalGenerator* gg,
{
}
-cmLocalGhsMultiGenerator::~cmLocalGhsMultiGenerator()
+cmLocalGhsMultiGenerator::~cmLocalGhsMultiGenerator() = default;
+
+std::string cmLocalGhsMultiGenerator::GetTargetDirectory(
+ cmGeneratorTarget const* target) const
{
+ std::string dir = cmStrCat(target->GetName(), ".dir");
+ return dir;
+}
+
+void cmLocalGhsMultiGenerator::GenerateTargetsDepthFirst(
+ cmGeneratorTarget* target, std::vector<cmGeneratorTarget*>& remaining)
+{
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return;
+ }
+ // Find this target in the list of remaining targets.
+ auto it = std::find(remaining.begin(), remaining.end(), target);
+ if (it == remaining.end()) {
+ // This target was already handled.
+ return;
+ }
+ // Remove this target from the list of remaining targets because
+ // we are handling it now.
+ *it = nullptr;
+
+ cmGhsMultiTargetGenerator tg(target);
+ tg.Generate();
}
void cmLocalGhsMultiGenerator::Generate()
{
- std::vector<cmGeneratorTarget*> tgts = this->GetGeneratorTargets();
+ std::vector<cmGeneratorTarget*> remaining = this->GetGeneratorTargets();
+ for (auto& t : remaining) {
+ if (t) {
+ GenerateTargetsDepthFirst(t, remaining);
+ }
+ }
+}
+
+void cmLocalGhsMultiGenerator::ComputeObjectFilenames(
+ std::map<cmSourceFile const*, std::string>& mapping,
+ cmGeneratorTarget const* gt)
+{
+ std::string dir_max = cmStrCat(this->GetCurrentBinaryDirectory(), '/',
+ this->GetTargetDirectory(gt), '/');
+
+ // Count the number of object files with each name. Note that
+ // filesystem may not be case sensitive.
+ std::map<std::string, int> counts;
+
+ for (auto const& si : mapping) {
+ cmSourceFile const* sf = si.first;
+ std::string objectNameLower = cmStrCat(
+ cmSystemTools::LowerCase(
+ cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath())),
+ this->GlobalGenerator->GetLanguageOutputExtension(*sf));
+ counts[objectNameLower] += 1;
+ }
+
+ // For all source files producing duplicate names we need unique
+ // object name computation.
+ for (auto& si : mapping) {
+ cmSourceFile const* sf = si.first;
+ std::string objectName = cmStrCat(
+ cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()),
+ this->GlobalGenerator->GetLanguageOutputExtension(*sf));
- for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin();
- l != tgts.end(); ++l) {
- if ((*l)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
- continue;
+ if (counts[cmSystemTools::LowerCase(objectName)] > 1) {
+ const_cast<cmGeneratorTarget*>(gt)->AddExplicitObjectName(sf);
+ bool keptSourceExtension;
+ objectName = this->GetObjectFileNameWithoutTarget(*sf, dir_max,
+ &keptSourceExtension);
+ cmsys::SystemTools::ReplaceString(objectName, "/", "_");
}
- cmGhsMultiTargetGenerator tg(*l);
- tg.Generate();
+ si.second = objectName;
}
}
diff --git a/Source/cmLocalGhsMultiGenerator.h b/Source/cmLocalGhsMultiGenerator.h
index aa842d74b..2250e5745 100644
--- a/Source/cmLocalGhsMultiGenerator.h
+++ b/Source/cmLocalGhsMultiGenerator.h
@@ -3,9 +3,16 @@
#ifndef cmLocalGhsMultiGenerator_h
#define cmLocalGhsMultiGenerator_h
+#include <map>
+#include <string>
+#include <vector>
+
#include "cmLocalGenerator.h"
-class cmGeneratedFileStream;
+class cmGeneratorTarget;
+class cmGlobalGenerator;
+class cmMakefile;
+class cmSourceFile;
/** \class cmLocalGhsMultiGenerator
* \brief Write Green Hills MULTI project files.
@@ -18,12 +25,23 @@ class cmLocalGhsMultiGenerator : public cmLocalGenerator
public:
cmLocalGhsMultiGenerator(cmGlobalGenerator* gg, cmMakefile* mf);
- virtual ~cmLocalGhsMultiGenerator();
+ ~cmLocalGhsMultiGenerator() override;
/**
* Generate the makefile for this directory.
*/
- virtual void Generate();
+ void Generate() override;
+
+ std::string GetTargetDirectory(
+ cmGeneratorTarget const* target) const override;
+
+ void ComputeObjectFilenames(
+ std::map<cmSourceFile const*, std::string>& mapping,
+ cmGeneratorTarget const* gt = nullptr) override;
+
+private:
+ void GenerateTargetsDepthFirst(cmGeneratorTarget* target,
+ std::vector<cmGeneratorTarget*>& remaining);
};
#endif
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 266710cb1..134bbe18a 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -3,26 +3,32 @@
#include "cmLocalNinjaGenerator.h"
#include <algorithm>
-#include <assert.h>
+#include <cassert>
+#include <cstdio>
#include <iterator>
+#include <memory>
#include <sstream>
-#include <stdio.h>
#include <utility>
+#include "cmsys/FStream.hxx"
+
+#include "cmCryptoHash.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalNinjaGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmNinjaTargetGenerator.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cm_auto_ptr.hxx"
#include "cmake.h"
cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg,
@@ -38,24 +44,21 @@ cmRulePlaceholderExpander*
cmLocalNinjaGenerator::CreateRulePlaceholderExpander() const
{
cmRulePlaceholderExpander* ret =
- new cmRulePlaceholderExpander(this->Compilers, this->VariableMappings,
- this->CompilerSysroot, this->LinkerSysroot);
+ this->cmLocalGenerator::CreateRulePlaceholderExpander();
ret->SetTargetImpLib("$TARGET_IMPLIB");
return ret;
}
-cmLocalNinjaGenerator::~cmLocalNinjaGenerator()
-{
-}
+cmLocalNinjaGenerator::~cmLocalNinjaGenerator() = default;
void cmLocalNinjaGenerator::Generate()
{
// Compute the path to use when referencing the current output
// directory from the top output directory.
- this->HomeRelativeOutputPath = this->ConvertToRelativePath(
+ this->HomeRelativeOutputPath = this->MaybeConvertToRelativePath(
this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory());
if (this->HomeRelativeOutputPath == ".") {
- this->HomeRelativeOutputPath = "";
+ this->HomeRelativeOutputPath.clear();
}
this->WriteProcessedMakefile(this->GetBuildFileStream());
@@ -69,43 +72,35 @@ void cmLocalNinjaGenerator::Generate()
this->WritePools(this->GetRulesFileStream());
- const std::string showIncludesPrefix =
+ const std::string& showIncludesPrefix =
this->GetMakefile()->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX");
if (!showIncludesPrefix.empty()) {
cmGlobalNinjaGenerator::WriteComment(this->GetRulesFileStream(),
"localized /showIncludes string");
- this->GetRulesFileStream() << "msvc_deps_prefix = " << showIncludesPrefix
- << "\n\n";
+ this->GetRulesFileStream()
+ << "msvc_deps_prefix = " << showIncludesPrefix << "\n\n";
}
}
- std::vector<cmGeneratorTarget*> targets = this->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator t = targets.begin();
- t != targets.end(); ++t) {
- if ((*t)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ for (cmGeneratorTarget* target : this->GetGeneratorTargets()) {
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
- cmNinjaTargetGenerator* tg = cmNinjaTargetGenerator::New(*t);
+ auto tg = cmNinjaTargetGenerator::New(target);
if (tg) {
tg->Generate();
- // Add the target to "all" if required.
- if (!this->GetGlobalNinjaGenerator()->IsExcluded(
- this->GetGlobalNinjaGenerator()->GetLocalGenerators()[0], *t)) {
- this->GetGlobalNinjaGenerator()->AddDependencyToAll(*t);
- }
- delete tg;
}
}
this->WriteCustomCommandBuildStatements();
+ this->AdditionalCleanFiles();
}
// TODO: Picked up from cmLocalUnixMakefileGenerator3. Refactor it.
std::string cmLocalNinjaGenerator::GetTargetDirectory(
cmGeneratorTarget const* target) const
{
- std::string dir = cmake::GetCMakeFilesDirectoryPostSlash();
- dir += target->GetName();
+ std::string dir = cmStrCat("CMakeFiles/", target->GetName());
#if defined(__VMS)
dir += "_dir";
#else
@@ -139,7 +134,8 @@ std::string cmLocalNinjaGenerator::ConvertToIncludeReference(
format);
}
return this->ConvertToOutputFormat(
- this->ConvertToRelativePath(this->GetBinaryDirectory(), path), format);
+ this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), path),
+ format);
}
// Private methods.
@@ -186,13 +182,22 @@ void cmLocalNinjaGenerator::WriteProjectHeader(std::ostream& os)
void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os)
{
// Default required version
- std::string requiredVersion =
- this->GetGlobalNinjaGenerator()->RequiredNinjaVersion();
+ std::string requiredVersion = cmGlobalNinjaGenerator::RequiredNinjaVersion();
// Ninja generator uses the 'console' pool if available (>= 1.5)
if (this->GetGlobalNinjaGenerator()->SupportsConsolePool()) {
requiredVersion =
- this->GetGlobalNinjaGenerator()->RequiredNinjaVersionForConsolePool();
+ cmGlobalNinjaGenerator::RequiredNinjaVersionForConsolePool();
+ }
+
+ // The Ninja generator writes rules which require support for restat
+ // when rebuilding build.ninja manifest (>= 1.8)
+ if (this->GetGlobalNinjaGenerator()->SupportsManifestRestat() &&
+ this->GetCMakeInstance()->DoWriteGlobVerifyTarget() &&
+ !this->GetGlobalNinjaGenerator()->GlobalSettingIsOn(
+ "CMAKE_SUPPRESS_REGENERATION")) {
+ requiredVersion =
+ cmGlobalNinjaGenerator::RequiredNinjaVersionForManifestRestat();
}
cmGlobalNinjaGenerator::WriteComment(
@@ -207,13 +212,14 @@ 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");
- std::vector<std::string> pools;
- cmSystemTools::ExpandListArgument(jobpools, pools);
- for (size_t i = 0; i < pools.size(); ++i) {
- std::string const& pool = pools[i];
+ std::vector<std::string> pools = cmExpandedList(jobpools);
+ for (std::string const& pool : pools) {
const std::string::size_type eq = pool.find('=');
unsigned int jobs;
if (eq != std::string::npos &&
@@ -222,8 +228,8 @@ void cmLocalNinjaGenerator::WritePools(std::ostream& os)
os << " depth = " << jobs << std::endl;
os << std::endl;
} else {
- cmSystemTools::Error("Invalid pool defined by property 'JOB_POOLS': ",
- pool.c_str());
+ cmSystemTools::Error("Invalid pool defined by property 'JOB_POOLS': " +
+ pool);
}
}
}
@@ -237,29 +243,12 @@ void cmLocalNinjaGenerator::WriteNinjaFilesInclusion(std::ostream& os)
cmGlobalNinjaGenerator* ng = this->GetGlobalNinjaGenerator();
std::string const ninjaRulesFile =
ng->NinjaOutputPath(cmGlobalNinjaGenerator::NINJA_RULES_FILE);
- std::string const rulesFilePath =
- ng->EncodeIdent(ng->EncodePath(ninjaRulesFile), os);
+ std::string const rulesFilePath = ng->EncodePath(ninjaRulesFile);
cmGlobalNinjaGenerator::WriteInclude(os, rulesFilePath,
"Include rules file.");
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 (std::map<cmSourceFile const*, std::string>::iterator si =
- mapping.begin();
- si != mapping.end(); ++si) {
- 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);
@@ -290,19 +279,72 @@ void cmLocalNinjaGenerator::AppendTargetDepends(cmGeneratorTarget* target,
void cmLocalNinjaGenerator::AppendCustomCommandDeps(
cmCustomCommandGenerator const& ccg, cmNinjaDeps& ninjaDeps)
{
- const std::vector<std::string>& deps = ccg.GetDepends();
- for (std::vector<std::string>::const_iterator i = deps.begin();
- i != deps.end(); ++i) {
+ for (std::string const& i : ccg.GetDepends()) {
std::string dep;
- if (this->GetRealDependency(*i, this->GetConfigName(), dep)) {
+ if (this->GetRealDependency(i, this->GetConfigName(), dep)) {
ninjaDeps.push_back(
this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(dep));
}
}
}
+std::string cmLocalNinjaGenerator::WriteCommandScript(
+ std::vector<std::string> const& cmdLines, std::string const& customStep,
+ cmGeneratorTarget const* target) const
+{
+ std::string scriptPath;
+ if (target) {
+ scriptPath = target->GetSupportDirectory();
+ } else {
+ scriptPath = cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles");
+ }
+ cmSystemTools::MakeDirectory(scriptPath);
+ scriptPath += '/';
+ scriptPath += customStep;
+#ifdef _WIN32
+ scriptPath += ".bat";
+#else
+ scriptPath += ".sh";
+#endif
+
+ cmsys::ofstream script(scriptPath.c_str());
+
+#ifdef _WIN32
+ script << "@echo off\n";
+ int line = 1;
+#else
+ script << "set -e\n\n";
+#endif
+
+ for (auto const& i : cmdLines) {
+ std::string cmd = i;
+ // The command line was built assuming it would be written to
+ // the build.ninja file, so it uses '$$' for '$'. Remove this
+ // for the raw shell script.
+ cmSystemTools::ReplaceString(cmd, "$$", "$");
+#ifdef _WIN32
+ script << cmd << " || (set FAIL_LINE=" << ++line << "& goto :ABORT)"
+ << '\n';
+#else
+ script << cmd << '\n';
+#endif
+ }
+
+#ifdef _WIN32
+ script << "goto :EOF\n\n"
+ ":ABORT\n"
+ "set ERROR_CODE=%ERRORLEVEL%\n"
+ "echo Batch file failed at line %FAIL_LINE% "
+ "with errorcode %ERRORLEVEL%\n"
+ "exit /b %ERROR_CODE%";
+#endif
+
+ return scriptPath;
+}
+
std::string cmLocalNinjaGenerator::BuildCommandLine(
- const std::vector<std::string>& cmdLines)
+ std::vector<std::string> const& cmdLines, std::string const& customStep,
+ cmGeneratorTarget const* target) const
{
// If we have no commands but we need to build a command anyway, use noop.
// This happens when building a POST_BUILD value for link targets that
@@ -311,9 +353,37 @@ std::string cmLocalNinjaGenerator::BuildCommandLine(
return cmGlobalNinjaGenerator::SHELL_NOOP;
}
+ // If this is a custom step then we will have no '$VAR' ninja placeholders.
+ // This means we can deal with long command sequences by writing to a script.
+ // Do this if the command lines are on the scale of the OS limit.
+ if (!customStep.empty()) {
+ size_t cmdLinesTotal = 0;
+ for (std::string const& cmd : cmdLines) {
+ cmdLinesTotal += cmd.length() + 6;
+ }
+ if (cmdLinesTotal > cmSystemTools::CalculateCommandLineLengthLimit() / 2) {
+ std::string const scriptPath =
+ this->WriteCommandScript(cmdLines, customStep, target);
+ std::string cmd
+#ifndef _WIN32
+ = "/bin/sh "
+#endif
+ ;
+ cmd += this->ConvertToOutputFormat(
+ this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(scriptPath),
+ cmOutputConverter::SHELL);
+
+ // Add an unused argument based on script content so that Ninja
+ // knows when the command lines change.
+ cmd += " ";
+ cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
+ cmd += hash.HashFile(scriptPath).substr(0, 16);
+ return cmd;
+ }
+ }
+
std::ostringstream cmd;
- for (std::vector<std::string>::const_iterator li = cmdLines.begin();
- li != cmdLines.end(); ++li)
+ for (auto li = cmdLines.begin(); li != cmdLines.end(); ++li)
#ifdef _WIN32
{
if (li != cmdLines.begin()) {
@@ -378,7 +448,8 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines(
void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
cmCustomCommand const* cc, const cmNinjaDeps& orderOnlyDeps)
{
- if (this->GetGlobalNinjaGenerator()->SeenCustomCommand(cc)) {
+ cmGlobalNinjaGenerator* gg = this->GetGlobalNinjaGenerator();
+ if (gg->SeenCustomCommand(cc)) {
return;
}
@@ -386,46 +457,56 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
const std::vector<std::string>& outputs = ccg.GetOutputs();
const std::vector<std::string>& byproducts = ccg.GetByproducts();
- cmNinjaDeps ninjaOutputs(outputs.size() + byproducts.size()), ninjaDeps;
bool symbolic = false;
- for (std::vector<std::string>::const_iterator o = outputs.begin();
- !symbolic && o != outputs.end(); ++o) {
- if (cmSourceFile* sf = this->Makefile->GetSource(*o)) {
- symbolic = sf->GetPropertyAsBool("SYMBOLIC");
+ for (std::string const& output : outputs) {
+ if (cmSourceFile* sf = this->Makefile->GetSource(output)) {
+ if (sf->GetPropertyAsBool("SYMBOLIC")) {
+ symbolic = true;
+ break;
+ }
}
}
#if 0
-#error TODO: Once CC in an ExternalProject target must provide the \
+# error TODO: Once CC in an ExternalProject target must provide the \
file of each imported target that has an add_dependencies pointing \
at us. How to know which ExternalProject step actually provides it?
#endif
+ cmNinjaDeps ninjaOutputs(outputs.size() + byproducts.size());
std::transform(outputs.begin(), outputs.end(), ninjaOutputs.begin(),
- this->GetGlobalNinjaGenerator()->MapToNinjaPath());
+ gg->MapToNinjaPath());
std::transform(byproducts.begin(), byproducts.end(),
- ninjaOutputs.begin() + outputs.size(),
- this->GetGlobalNinjaGenerator()->MapToNinjaPath());
- this->AppendCustomCommandDeps(ccg, ninjaDeps);
+ ninjaOutputs.begin() + outputs.size(), gg->MapToNinjaPath());
- for (cmNinjaDeps::iterator i = ninjaOutputs.begin(); i != ninjaOutputs.end();
- ++i) {
- this->GetGlobalNinjaGenerator()->SeenCustomCommandOutput(*i);
+ for (std::string const& ninjaOutput : ninjaOutputs) {
+ gg->SeenCustomCommandOutput(ninjaOutput);
}
+ cmNinjaDeps ninjaDeps;
+ this->AppendCustomCommandDeps(ccg, ninjaDeps);
+
std::vector<std::string> cmdLines;
this->AppendCustomCommandLines(ccg, cmdLines);
if (cmdLines.empty()) {
- this->GetGlobalNinjaGenerator()->WritePhonyBuild(
- this->GetBuildFileStream(),
- "Phony custom command for " + ninjaOutputs[0], ninjaOutputs, ninjaDeps,
- cmNinjaDeps(), orderOnlyDeps, cmNinjaVars());
+ cmNinjaBuild build("phony");
+ build.Comment = "Phony custom command for " + ninjaOutputs[0];
+ build.Outputs = std::move(ninjaOutputs);
+ build.ExplicitDeps = std::move(ninjaDeps);
+ build.OrderOnlyDeps = orderOnlyDeps;
+ gg->WriteBuild(this->GetBuildFileStream(), build);
} else {
- this->GetGlobalNinjaGenerator()->WriteCustomCommandBuild(
- this->BuildCommandLine(cmdLines), this->ConstructComment(ccg),
- "Custom command for " + ninjaOutputs[0], cc->GetDepfile(),
- cc->GetUsesTerminal(),
+ std::string customStep = cmSystemTools::GetFilenameName(ninjaOutputs[0]);
+ // Hash full path to make unique.
+ customStep += '-';
+ cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
+ customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7);
+
+ gg->WriteCustomCommandBuild(
+ this->BuildCommandLine(cmdLines, customStep),
+ this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0],
+ cc->GetDepfile(), cc->GetJobPool(), cc->GetUsesTerminal(),
/*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, ninjaDeps,
orderOnlyDeps);
}
@@ -445,10 +526,8 @@ void cmLocalNinjaGenerator::AddCustomCommandTarget(cmCustomCommand const* cc,
void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements()
{
- for (std::vector<cmCustomCommand const*>::iterator vi =
- this->CustomCommands.begin();
- vi != this->CustomCommands.end(); ++vi) {
- CustomCommandTargetMap::iterator i = this->CustomCommandTargets.find(*vi);
+ for (cmCustomCommand const* customCommand : this->CustomCommands) {
+ auto i = this->CustomCommandTargets.find(customCommand);
assert(i != this->CustomCommandTargets.end());
// A custom command may appear on multiple targets. However, some build
@@ -460,7 +539,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements()
//
// FIXME: This won't work in certain obscure scenarios involving indirect
// dependencies.
- std::set<cmGeneratorTarget*>::iterator j = i->second.begin();
+ auto j = i->second.begin();
assert(j != i->second.end());
std::vector<std::string> ccTargetDeps;
this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j,
@@ -469,7 +548,8 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements()
++j;
for (; j != i->second.end(); ++j) {
- std::vector<std::string> jDeps, depsIntersection;
+ std::vector<std::string> jDeps;
+ std::vector<std::string> depsIntersection;
this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j, jDeps);
std::sort(jDeps.begin(), jDeps.end());
std::set_intersection(ccTargetDeps.begin(), ccTargetDeps.end(),
@@ -492,8 +572,7 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
return std::string();
}
- // Expand rules in the empty string. It may insert the launcher and
- // perform replacements.
+ // Expand rule variables referenced in the given launcher command.
cmRulePlaceholderExpander::RuleVariables vars;
std::string output;
@@ -501,19 +580,17 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
if (!outputs.empty()) {
output = outputs[0];
if (ccg.GetWorkingDirectory().empty()) {
- output =
- this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), output);
+ output = this->MaybeConvertToRelativePath(
+ this->GetCurrentBinaryDirectory(), output);
}
output = this->ConvertToOutputFormat(output, cmOutputConverter::SHELL);
}
vars.Output = output.c_str();
- std::string launcher = property_value;
- launcher += " ";
-
- CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+ std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->CreateRulePlaceholderExpander());
+ std::string launcher = property_value;
rulePlaceholderExpander->ExpandRuleVariables(this, launcher, vars);
if (!launcher.empty()) {
launcher += " ";
@@ -521,3 +598,24 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
return launcher;
}
+
+void cmLocalNinjaGenerator::AdditionalCleanFiles()
+{
+ if (const char* prop_value =
+ this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) {
+ std::vector<std::string> cleanFiles;
+ {
+ cmExpandList(cmGeneratorExpression::Evaluate(
+ prop_value, this,
+ this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")),
+ cleanFiles);
+ }
+ std::string const& binaryDir = this->GetCurrentBinaryDirectory();
+ cmGlobalNinjaGenerator* gg = this->GetGlobalNinjaGenerator();
+ for (std::string const& cleanFile : cleanFiles) {
+ // Support relative paths
+ gg->AddAdditionalCleanFile(
+ cmSystemTools::CollapseFullPath(cleanFile, binaryDir));
+ }
+ }
+}
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index a45e01851..f64534ce1 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -3,7 +3,7 @@
#ifndef cmLocalNinjaGenerator_h
#define cmLocalNinjaGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <map>
@@ -23,7 +23,6 @@ class cmGlobalGenerator;
class cmGlobalNinjaGenerator;
class cmMakefile;
class cmRulePlaceholderExpander;
-class cmSourceFile;
class cmake;
/**
@@ -38,14 +37,14 @@ class cmLocalNinjaGenerator : public cmLocalCommonGenerator
public:
cmLocalNinjaGenerator(cmGlobalGenerator* gg, cmMakefile* mf);
- ~cmLocalNinjaGenerator() CM_OVERRIDE;
+ ~cmLocalNinjaGenerator() override;
- void Generate() CM_OVERRIDE;
+ void Generate() override;
- cmRulePlaceholderExpander* CreateRulePlaceholderExpander() const CM_OVERRIDE;
+ cmRulePlaceholderExpander* CreateRulePlaceholderExpander() const override;
- std::string GetTargetDirectory(cmGeneratorTarget const* target) const
- CM_OVERRIDE;
+ std::string GetTargetDirectory(
+ cmGeneratorTarget const* target) const override;
const cmGlobalNinjaGenerator* GetGlobalNinjaGenerator() const;
cmGlobalNinjaGenerator* GetGlobalNinjaGenerator();
@@ -60,7 +59,10 @@ public:
return this->HomeRelativeOutputPath;
}
- std::string BuildCommandLine(const std::vector<std::string>& cmdLines);
+ std::string BuildCommandLine(
+ std::vector<std::string> const& cmdLines,
+ std::string const& customStep = std::string(),
+ cmGeneratorTarget const* target = nullptr) const;
void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs);
void AppendTargetDepends(
@@ -74,15 +76,11 @@ public:
void AppendCustomCommandDeps(cmCustomCommandGenerator const& ccg,
cmNinjaDeps& ninjaDeps);
- void ComputeObjectFilenames(
- std::map<cmSourceFile const*, std::string>& mapping,
- cmGeneratorTarget const* gt = CM_NULLPTR) CM_OVERRIDE;
-
protected:
std::string ConvertToIncludeReference(
std::string const& path,
cmOutputConverter::OutputFormat format = cmOutputConverter::SHELL,
- bool forceFullPaths = false) CM_OVERRIDE;
+ bool forceFullPaths = false) override;
private:
cmGeneratedFileStream& GetBuildFileStream() const;
@@ -95,7 +93,6 @@ private:
void WriteProcessedMakefile(std::ostream& os);
void WritePools(std::ostream& os);
- void WriteCustomCommandRule();
void WriteCustomCommandBuildStatement(cmCustomCommand const* cc,
const cmNinjaDeps& orderOnlyDeps);
@@ -103,10 +100,16 @@ private:
std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg);
+ std::string WriteCommandScript(std::vector<std::string> const& cmdLines,
+ std::string const& customStep,
+ cmGeneratorTarget const* target) const;
+
+ void AdditionalCleanFiles();
+
std::string HomeRelativeOutputPath;
- typedef std::map<cmCustomCommand const*, std::set<cmGeneratorTarget*> >
- CustomCommandTargetMap;
+ using CustomCommandTargetMap =
+ std::map<cmCustomCommand const*, std::set<cmGeneratorTarget*>>;
CustomCommandTargetMap CustomCommandTargets;
std::vector<cmCustomCommand const*> CustomCommands;
};
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 9b9d22cf5..4a70248d6 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -2,43 +2,48 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalUnixMakefileGenerator3.h"
-#include "cmsys/FStream.hxx"
-#include "cmsys/Terminal.h"
#include <algorithm>
-#include <functional>
+#include <cstdio>
#include <sstream>
-#include <stdio.h>
#include <utility>
+#include <cm/memory>
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/Terminal.h"
+
#include "cmAlgorithms.h"
-#include "cmCustomCommand.h"
+#include "cmCustomCommand.h" // IWYU pragma: keep
#include "cmCustomCommandGenerator.h"
-#include "cmFileTimeComparison.h"
+#include "cmFileTimeCache.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMakefileTargetGenerator.h"
#include "cmOutputConverter.h"
+#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
-#include "cm_auto_ptr.hxx"
#include "cmake.h"
// Include dependency scanners for supported languages. Only the
// C/C++ scanner is needed for bootstrapping CMake.
#include "cmDependsC.h"
-#ifdef CMAKE_BUILD_WITH_CMAKE
-#include "cmDependsFortran.h"
-#include "cmDependsJava.h"
+#ifndef CMAKE_BOOTSTRAP
+# include "cmDependsFortran.h"
+# include "cmDependsJava.h"
#endif
// Escape special characters in Makefile dependency lines
@@ -99,9 +104,7 @@ cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3(
this->BorlandMakeCurlyHack = false;
}
-cmLocalUnixMakefileGenerator3::~cmLocalUnixMakefileGenerator3()
-{
-}
+cmLocalUnixMakefileGenerator3::~cmLocalUnixMakefileGenerator3() = default;
void cmLocalUnixMakefileGenerator3::Generate()
{
@@ -116,17 +119,15 @@ void cmLocalUnixMakefileGenerator3::Generate()
this->Makefile->IsOn("CMAKE_SKIP_ASSEMBLY_SOURCE_RULES");
// Generate the rule files for each target.
- std::vector<cmGeneratorTarget*> targets = this->GetGeneratorTargets();
cmGlobalUnixMakefileGenerator3* gg =
static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
- for (std::vector<cmGeneratorTarget*>::iterator t = targets.begin();
- t != targets.end(); ++t) {
- if ((*t)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ for (cmGeneratorTarget* target : this->GetGeneratorTargets()) {
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
- CM_AUTO_PTR<cmMakefileTargetGenerator> tg(
- cmMakefileTargetGenerator::New(*t));
- if (tg.get()) {
+ std::unique_ptr<cmMakefileTargetGenerator> tg(
+ cmMakefileTargetGenerator::New(target));
+ if (tg) {
tg->WriteRuleFiles();
gg->RecordTargetProgress(tg.get());
}
@@ -146,61 +147,36 @@ void cmLocalUnixMakefileGenerator3::ComputeHomeRelativeOutputPath()
this->HomeRelativeOutputPath = this->MaybeConvertToRelativePath(
this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory());
if (this->HomeRelativeOutputPath == ".") {
- this->HomeRelativeOutputPath = "";
+ this->HomeRelativeOutputPath.clear();
}
if (!this->HomeRelativeOutputPath.empty()) {
this->HomeRelativeOutputPath += "/";
}
}
-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 (std::map<cmSourceFile const*, std::string>::iterator si =
- mapping.begin();
- si != mapping.end(); ++si) {
- 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)
{
- std::vector<cmGeneratorTarget*> targets = this->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator ti = targets.begin();
- ti != targets.end(); ++ti) {
- cmGeneratorTarget* gt = *ti;
+ for (cmGeneratorTarget* gt : this->GetGeneratorTargets()) {
if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
std::vector<cmSourceFile const*> objectSources;
- gt->GetObjectSources(
- objectSources, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
+ gt->GetObjectSources(objectSources, this->ConfigName);
// Compute full path to object file directory for this target.
- std::string dir;
- dir += gt->LocalGenerator->GetCurrentBinaryDirectory();
- dir += "/";
- dir += this->GetTargetDirectory(gt);
- dir += "/";
+ std::string dir = cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(),
+ '/', this->GetTargetDirectory(gt), '/');
// Compute the name of each object file.
- for (std::vector<cmSourceFile const*>::iterator si = objectSources.begin();
- si != objectSources.end(); ++si) {
- cmSourceFile const* sf = *si;
+ for (cmSourceFile const* sf : objectSources) {
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());
}
}
}
@@ -210,18 +186,16 @@ void cmLocalUnixMakefileGenerator3::GetIndividualFileTargets(
{
std::map<std::string, LocalObjectInfo> localObjectFiles;
this->GetLocalObjectFiles(localObjectFiles);
- for (std::map<std::string, LocalObjectInfo>::iterator lo =
- localObjectFiles.begin();
- lo != localObjectFiles.end(); ++lo) {
- targets.push_back(lo->first);
-
- std::string::size_type dot_pos = lo->first.rfind(".");
- std::string base = lo->first.substr(0, dot_pos);
- if (lo->second.HasPreprocessRule) {
+ for (auto const& localObjectFile : localObjectFiles) {
+ targets.push_back(localObjectFile.first);
+
+ std::string::size_type dot_pos = localObjectFile.first.rfind(".");
+ std::string base = localObjectFile.first.substr(0, dot_pos);
+ if (localObjectFile.second.HasPreprocessRule) {
targets.push_back(base + ".i");
}
- if (lo->second.HasAssembleRule) {
+ if (localObjectFile.second.HasAssembleRule) {
targets.push_back(base + ".s");
}
}
@@ -236,8 +210,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile()
// rules may depend on this file itself.
std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName);
cmGeneratedFileStream ruleFileStream(
- ruleFileNameFull.c_str(), false,
- this->GlobalGenerator->GetMakefileEncoding());
+ ruleFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding());
if (!ruleFileStream) {
return;
}
@@ -270,23 +243,20 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile()
// now write out the object rules
// for each object file name
- for (std::map<std::string, LocalObjectInfo>::iterator lo =
- localObjectFiles.begin();
- lo != localObjectFiles.end(); ++lo) {
+ for (auto& localObjectFile : localObjectFiles) {
// Add a convenience rule for building the object file.
- this->WriteObjectConvenienceRule(ruleFileStream,
- "target to build an object file",
- lo->first.c_str(), lo->second);
+ this->WriteObjectConvenienceRule(
+ ruleFileStream, "target to build an object file", localObjectFile.first,
+ localObjectFile.second);
// Check whether preprocessing and assembly rules make sense.
// They make sense only for C and C++ sources.
bool lang_has_preprocessor = false;
bool lang_has_assembly = false;
- for (std::vector<LocalObjectEntry>::const_iterator ei = lo->second.begin();
- ei != lo->second.end(); ++ei) {
- if (ei->Language == "C" || ei->Language == "CXX" ||
- ei->Language == "CUDA" || ei->Language == "Fortran") {
+ for (LocalObjectEntry const& entry : localObjectFile.second) {
+ if (entry.Language == "C" || entry.Language == "CXX" ||
+ entry.Language == "CUDA" || entry.Language == "Fortran") {
// Right now, C, C++, Fortran and CUDA have both a preprocessor and the
// ability to generate assembly code
lang_has_preprocessor = true;
@@ -297,21 +267,21 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile()
// Add convenience rules for preprocessed and assembly files.
if (lang_has_preprocessor && do_preprocess_rules) {
- std::string::size_type dot_pos = lo->first.rfind(".");
- std::string base = lo->first.substr(0, dot_pos);
+ std::string::size_type dot_pos = localObjectFile.first.rfind(".");
+ std::string base = localObjectFile.first.substr(0, dot_pos);
this->WriteObjectConvenienceRule(ruleFileStream,
"target to preprocess a source file",
- (base + ".i").c_str(), lo->second);
- lo->second.HasPreprocessRule = true;
+ (base + ".i"), localObjectFile.second);
+ localObjectFile.second.HasPreprocessRule = true;
}
if (lang_has_assembly && do_assembly_rules) {
- std::string::size_type dot_pos = lo->first.rfind(".");
- std::string base = lo->first.substr(0, dot_pos);
+ std::string::size_type dot_pos = localObjectFile.first.rfind(".");
+ std::string base = localObjectFile.first.substr(0, dot_pos);
this->WriteObjectConvenienceRule(
ruleFileStream, "target to generate assembly for a file",
- (base + ".s").c_str(), lo->second);
- lo->second.HasAssembleRule = true;
+ (base + ".s"), localObjectFile.second);
+ localObjectFile.second.HasAssembleRule = true;
}
}
@@ -326,7 +296,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefile()
}
void cmLocalUnixMakefileGenerator3::WriteObjectConvenienceRule(
- std::ostream& ruleFileStream, const char* comment, const char* output,
+ std::ostream& ruleFileStream, const char* comment, const std::string& output,
LocalObjectInfo const& info)
{
// If the rule includes the source file extension then create a
@@ -346,24 +316,23 @@ void cmLocalUnixMakefileGenerator3::WriteObjectConvenienceRule(
// Add a rule to drive the rule below.
std::vector<std::string> depends;
- depends.push_back(output);
+ depends.emplace_back(output);
std::vector<std::string> no_commands;
- this->WriteMakeRule(ruleFileStream, CM_NULLPTR, outNoExt, depends,
+ this->WriteMakeRule(ruleFileStream, nullptr, outNoExt, depends,
no_commands, true, true);
inHelp = false;
}
// Recursively make the rule for each target using the object file.
std::vector<std::string> commands;
- for (std::vector<LocalObjectEntry>::const_iterator t = info.begin();
- t != info.end(); ++t) {
- std::string tgtMakefileName = this->GetRelativeTargetDirectory(t->Target);
+ for (LocalObjectEntry const& t : info) {
+ std::string tgtMakefileName = this->GetRelativeTargetDirectory(t.Target);
std::string targetName = tgtMakefileName;
tgtMakefileName += "/build.make";
targetName += "/";
targetName += output;
commands.push_back(
- this->GetRecursiveMakeCall(tgtMakefileName.c_str(), targetName));
+ this->GetRecursiveMakeCall(tgtMakefileName, targetName));
}
this->CreateCDCommand(commands, this->GetBinaryDirectory(),
this->GetCurrentBinaryDirectory());
@@ -382,54 +351,48 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets(
// for each target we just provide a rule to cd up to the top and do a make
// on the target
- std::vector<cmGeneratorTarget*> targets = this->GetGeneratorTargets();
std::string localName;
- for (std::vector<cmGeneratorTarget*>::iterator t = targets.begin();
- t != targets.end(); ++t) {
- if (((*t)->GetType() == cmStateEnums::EXECUTABLE) ||
- ((*t)->GetType() == cmStateEnums::STATIC_LIBRARY) ||
- ((*t)->GetType() == cmStateEnums::SHARED_LIBRARY) ||
- ((*t)->GetType() == cmStateEnums::MODULE_LIBRARY) ||
- ((*t)->GetType() == cmStateEnums::OBJECT_LIBRARY) ||
- ((*t)->GetType() == cmStateEnums::UTILITY)) {
- emitted.insert((*t)->GetName());
+ for (cmGeneratorTarget* target : this->GetGeneratorTargets()) {
+ if ((target->GetType() == cmStateEnums::EXECUTABLE) ||
+ (target->GetType() == cmStateEnums::STATIC_LIBRARY) ||
+ (target->GetType() == cmStateEnums::SHARED_LIBRARY) ||
+ (target->GetType() == cmStateEnums::MODULE_LIBRARY) ||
+ (target->GetType() == cmStateEnums::OBJECT_LIBRARY) ||
+ (target->GetType() == cmStateEnums::UTILITY)) {
+ emitted.insert(target->GetName());
// for subdirs add a rule to build this specific target by name.
- localName = this->GetRelativeTargetDirectory(*t);
- localName += "/rule";
+ localName = cmStrCat(this->GetRelativeTargetDirectory(target), "/rule");
commands.clear();
depends.clear();
// Build the target for this pass.
- std::string makefile2 = cmake::GetCMakeFilesDirectoryPostSlash();
- makefile2 += "Makefile2";
- commands.push_back(
- this->GetRecursiveMakeCall(makefile2.c_str(), localName));
+ std::string makefile2 = "CMakeFiles/Makefile2";
+ commands.push_back(this->GetRecursiveMakeCall(makefile2, localName));
this->CreateCDCommand(commands, this->GetBinaryDirectory(),
this->GetCurrentBinaryDirectory());
this->WriteMakeRule(ruleFileStream, "Convenience name for target.",
localName, depends, commands, true);
// Add a target with the canonical name (no prefix, suffix or path).
- if (localName != (*t)->GetName()) {
+ if (localName != target->GetName()) {
commands.clear();
depends.push_back(localName);
this->WriteMakeRule(ruleFileStream, "Convenience name for target.",
- (*t)->GetName(), depends, commands, true);
+ target->GetName(), depends, commands, true);
}
// Add a fast rule to build the target
- std::string makefileName = this->GetRelativeTargetDirectory(*t);
- makefileName += "/build.make";
+ std::string makefileName =
+ cmStrCat(this->GetRelativeTargetDirectory(target), "/build.make");
// make sure the makefile name is suitable for a makefile
- std::string makeTargetName = this->GetRelativeTargetDirectory(*t);
- makeTargetName += "/build";
- localName = (*t)->GetName();
- localName += "/fast";
+ std::string makeTargetName =
+ cmStrCat(this->GetRelativeTargetDirectory(target), "/build");
+ localName = cmStrCat(target->GetName(), "/fast");
depends.clear();
commands.clear();
commands.push_back(
- this->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName));
+ this->GetRecursiveMakeCall(makefileName, makeTargetName));
this->CreateCDCommand(commands, this->GetBinaryDirectory(),
this->GetCurrentBinaryDirectory());
this->WriteMakeRule(ruleFileStream, "fast build rule for target.",
@@ -437,15 +400,14 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets(
// Add a local name for the rule to relink the target before
// installation.
- if ((*t)->NeedRelinkBeforeInstall(this->ConfigName)) {
- makeTargetName = this->GetRelativeTargetDirectory(*t);
- makeTargetName += "/preinstall";
- localName = (*t)->GetName();
- localName += "/preinstall";
+ if (target->NeedRelinkBeforeInstall(this->ConfigName)) {
+ makeTargetName =
+ cmStrCat(this->GetRelativeTargetDirectory(target), "/preinstall");
+ localName = cmStrCat(target->GetName(), "/preinstall");
depends.clear();
commands.clear();
commands.push_back(
- this->GetRecursiveMakeCall(makefile2.c_str(), makeTargetName));
+ this->GetRecursiveMakeCall(makefile2, makeTargetName));
this->CreateCDCommand(commands, this->GetBinaryDirectory(),
this->GetCurrentBinaryDirectory());
this->WriteMakeRule(ruleFileStream,
@@ -458,12 +420,12 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets(
void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile()
{
- std::string infoFileName = this->GetCurrentBinaryDirectory();
- infoFileName += cmake::GetCMakeFilesDirectory();
- infoFileName += "/CMakeDirectoryInformation.cmake";
+ std::string infoFileName =
+ cmStrCat(this->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/CMakeDirectoryInformation.cmake");
// Open the output file.
- cmGeneratedFileStream infoFileStream(infoFileName.c_str());
+ cmGeneratedFileStream infoFileStream(infoFileName);
if (!infoFileStream) {
return;
}
@@ -500,12 +462,12 @@ void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile()
<< "# The C and CXX include file regular expressions for "
<< "this directory.\n";
infoFileStream << "set(CMAKE_C_INCLUDE_REGEX_SCAN ";
- this->WriteCMakeArgument(infoFileStream,
- this->Makefile->GetIncludeRegularExpression());
+ cmLocalUnixMakefileGenerator3::WriteCMakeArgument(
+ infoFileStream, this->Makefile->GetIncludeRegularExpression());
infoFileStream << ")\n";
infoFileStream << "set(CMAKE_C_INCLUDE_REGEX_COMPLAIN ";
- this->WriteCMakeArgument(infoFileStream,
- this->Makefile->GetComplainRegularExpression());
+ cmLocalUnixMakefileGenerator3::WriteCMakeArgument(
+ infoFileStream, this->Makefile->GetComplainRegularExpression());
infoFileStream << ")\n";
infoFileStream
<< "set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN})\n";
@@ -516,9 +478,8 @@ void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile()
std::string cmLocalUnixMakefileGenerator3::ConvertToFullPath(
const std::string& localPath)
{
- std::string dir = this->GetCurrentBinaryDirectory();
- dir += "/";
- dir += localPath;
+ std::string dir =
+ cmStrCat(this->GetCurrentBinaryDirectory(), '/', localPath);
return dir;
}
@@ -534,8 +495,11 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule(
{
// Make sure there is a target.
if (target.empty()) {
- cmSystemTools::Error("No target for WriteMakeRule! called with comment: ",
- comment);
+ std::string err("No target for WriteMakeRule! called with comment: ");
+ if (comment) {
+ err += comment;
+ }
+ cmSystemTools::Error(err);
return;
}
@@ -555,8 +519,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) {
@@ -581,11 +544,10 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule(
// Split dependencies into multiple rule lines. This allows for
// very long dependency lists even on older make implementations.
std::string binDir = this->GetBinaryDirectory();
- for (std::vector<std::string>::const_iterator dep = depends.begin();
- dep != depends.end(); ++dep) {
- replace = *dep;
+ 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";
}
}
@@ -605,7 +567,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
@@ -717,8 +679,8 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsTop(
}
// Add a fake suffix to keep HP happy. Must be max 32 chars for SGI make.
std::vector<std::string> depends;
- depends.push_back(".hpux_make_needs_suffix_list");
- this->WriteMakeRule(makefileStream, CM_NULLPTR, ".SUFFIXES", depends,
+ depends.emplace_back(".hpux_make_needs_suffix_list");
+ this->WriteMakeRule(makefileStream, nullptr, ".SUFFIXES", depends,
no_commands, false);
if (this->IsWatcomWMake()) {
// Switch on WMake feature, if an error or interrupt occurs during
@@ -767,11 +729,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
@@ -792,31 +754,39 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsBottom(
// Write special "cmake_check_build_system" target to run cmake with
// the --check-build-system flag.
- {
+ if (!this->GlobalGenerator->GlobalSettingIsOn(
+ "CMAKE_SUPPRESS_REGENERATION")) {
// Build command to run CMake to check if anything needs regenerating.
- 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 += " 0";
+ std::vector<std::string> commands;
+ cmake* cm = this->GlobalGenerator->GetCMakeInstance();
+ if (cm->DoWriteGlobVerifyTarget()) {
+ std::string rescanRule =
+ cmStrCat("$(CMAKE_COMMAND) -P ",
+ this->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
+ cmOutputConverter::SHELL));
+ commands.push_back(rescanRule);
+ }
+ std::string cmakefileName = "CMakeFiles/Makefile.cmake";
+ std::string runRule = cmStrCat(
+ "$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) "
+ "--check-build-system ",
+ this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL),
+ " 0");
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());
}
- this->WriteMakeRule(
- makefileStream, "Special rule to run CMake to check the build system "
- "integrity.\n"
- "No rule that depends on this can have "
- "commands that come from listfiles\n"
- "because they might be regenerated.",
- "cmake_check_build_system", no_depends, commands, true);
+ this->WriteMakeRule(makefileStream,
+ "Special rule to run CMake to check the build system "
+ "integrity.\n"
+ "No rule that depends on this can have "
+ "commands that come from listfiles\n"
+ "because they might be regenerated.",
+ "cmake_check_build_system", no_depends, commands,
+ true);
}
}
@@ -840,15 +810,15 @@ void cmLocalUnixMakefileGenerator3::WriteConvenienceRule(
}
std::string cmLocalUnixMakefileGenerator3::GetRelativeTargetDirectory(
- cmGeneratorTarget* target)
+ cmGeneratorTarget const* target) const
{
- std::string dir = this->HomeRelativeOutputPath;
- dir += this->GetTargetDirectory(target);
+ std::string dir =
+ cmStrCat(this->HomeRelativeOutputPath, this->GetTargetDirectory(target));
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;
@@ -861,12 +831,6 @@ void cmLocalUnixMakefileGenerator3::AppendFlags(std::string& flags,
this->cmLocalGenerator::AppendFlags(flags, newFlags);
}
-void cmLocalUnixMakefileGenerator3::AppendFlags(std::string& flags,
- const char* newFlags)
-{
- this->cmLocalGenerator::AppendFlags(flags, newFlags);
-}
-
void cmLocalUnixMakefileGenerator3::AppendRuleDepend(
std::vector<std::string>& depends, const char* ruleFileName)
{
@@ -874,8 +838,8 @@ void cmLocalUnixMakefileGenerator3::AppendRuleDepend(
// it is specifically enabled by the user or project.
const char* nodep =
this->Makefile->GetDefinition("CMAKE_SKIP_RULE_DEPENDENCY");
- if (!nodep || cmSystemTools::IsOff(nodep)) {
- depends.push_back(ruleFileName);
+ if (!nodep || cmIsOff(nodep)) {
+ depends.emplace_back(ruleFileName);
}
}
@@ -885,16 +849,15 @@ void cmLocalUnixMakefileGenerator3::AppendRuleDepends(
// Add a dependency on the rule file itself unless an option to skip
// it is specifically enabled by the user or project.
if (!this->Makefile->IsOn("CMAKE_SKIP_RULE_DEPENDENCY")) {
- depends.insert(depends.end(), ruleFiles.begin(), ruleFiles.end());
+ cmAppend(depends, ruleFiles);
}
}
void cmLocalUnixMakefileGenerator3::AppendCustomDepends(
std::vector<std::string>& depends, const std::vector<cmCustomCommand>& ccs)
{
- for (std::vector<cmCustomCommand>::const_iterator i = ccs.begin();
- i != ccs.end(); ++i) {
- cmCustomCommandGenerator ccg(*i, this->ConfigName, this);
+ for (cmCustomCommand const& cc : ccs) {
+ cmCustomCommandGenerator ccg(cc, this->ConfigName, this);
this->AppendCustomDepend(depends, ccg);
}
}
@@ -902,12 +865,11 @@ void cmLocalUnixMakefileGenerator3::AppendCustomDepends(
void cmLocalUnixMakefileGenerator3::AppendCustomDepend(
std::vector<std::string>& depends, cmCustomCommandGenerator const& ccg)
{
- for (std::vector<std::string>::const_iterator d = ccg.GetDepends().begin();
- d != ccg.GetDepends().end(); ++d) {
+ for (std::string const& d : ccg.GetDepends()) {
// 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);
+ if (this->GetRealDependency(d, this->ConfigName, dep)) {
+ depends.push_back(std::move(dep));
}
}
}
@@ -916,9 +878,8 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommands(
std::vector<std::string>& commands, const std::vector<cmCustomCommand>& ccs,
cmGeneratorTarget* target, std::string const& relative)
{
- for (std::vector<cmCustomCommand>::const_iterator i = ccs.begin();
- i != ccs.end(); ++i) {
- cmCustomCommandGenerator ccg(*i, this->ConfigName, this);
+ for (cmCustomCommand const& cc : ccs) {
+ cmCustomCommandGenerator ccg(cc, this->ConfigName, this);
this->AppendCustomCommand(commands, ccg, target, relative, true);
}
}
@@ -950,7 +911,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
*content << dir;
}
- CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+ std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->CreateRulePlaceholderExpander());
// Add each command line to the set of commands.
@@ -987,15 +948,14 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
// This command was specified as a path to a file in the
// current directory. Add a leading "./" so it can run
// without the current directory being in the search path.
- cmd = "./" + cmd;
+ cmd = cmStrCat("./", cmd);
}
std::string launcher;
// Short-circuit if there is no launcher.
const char* val = this->GetRuleLauncher(target, "RULE_LAUNCH_CUSTOM");
if (val && *val) {
- // Expand rules in the empty string. It may insert the launcher and
- // perform replacements.
+ // Expand rule variables referenced in the given launcher command.
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = target->GetName().c_str();
vars.CMTargetType = cmState::GetTargetTypeName(target->GetType());
@@ -1013,7 +973,6 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
vars.Output = output.c_str();
launcher = val;
- launcher += " ";
rulePlaceholderExpander->ExpandRuleVariables(this, launcher, vars);
if (!launcher.empty()) {
launcher += " ";
@@ -1043,40 +1002,36 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
std::string::size_type rcurly = cmd.find('}');
if (rcurly == std::string::npos || rcurly > lcurly) {
// The first curly is a left curly. Use the hack.
- std::string hack_cmd = cmd.substr(0, lcurly);
- hack_cmd += "{{}";
- hack_cmd += cmd.substr(lcurly + 1);
- cmd = hack_cmd;
+ cmd =
+ cmStrCat(cmd.substr(0, lcurly), "{{}", cmd.substr(lcurly + 1));
}
}
}
if (launcher.empty()) {
if (useCall) {
- cmd = "call " + cmd;
+ cmd = cmStrCat("call ", cmd);
} else if (this->IsNMake() && cmd[0] == '"') {
- cmd = "echo >nul && " + cmd;
+ cmd = cmStrCat("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());
+ cmAppend(commands, commands1);
}
void cmLocalUnixMakefileGenerator3::AppendCleanCommand(
- std::vector<std::string>& commands, const std::vector<std::string>& files,
+ std::vector<std::string>& commands, const std::set<std::string>& files,
cmGeneratorTarget* target, const char* filename)
{
std::string currentBinDir = this->GetCurrentBinaryDirectory();
- std::string cleanfile = currentBinDir;
- cleanfile += "/";
- cleanfile += this->GetTargetDirectory(target);
- cleanfile += "/cmake_clean";
+ std::string cleanfile = cmStrCat(
+ currentBinDir, '/', this->GetTargetDirectory(target), "/cmake_clean");
if (filename) {
cleanfile += "_";
cleanfile += filename;
@@ -1085,23 +1040,25 @@ void cmLocalUnixMakefileGenerator3::AppendCleanCommand(
std::string cleanfilePath = cmSystemTools::CollapseFullPath(cleanfile);
cmsys::ofstream fout(cleanfilePath.c_str());
if (!fout) {
- cmSystemTools::Error("Could not create ", cleanfilePath.c_str());
+ cmSystemTools::Error("Could not create " + cleanfilePath);
}
if (!files.empty()) {
fout << "file(REMOVE_RECURSE\n";
- for (std::vector<std::string>::const_iterator f = files.begin();
- f != files.end(); ++f) {
- std::string fc = this->MaybeConvertToRelativePath(currentBinDir, *f);
+ for (std::string const& file : files) {
+ std::string fc = this->MaybeConvertToRelativePath(currentBinDir, file);
fout << " " << cmOutputConverter::EscapeForCMake(fc) << "\n";
}
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 =
+ cmStrCat("$(CMAKE_COMMAND) -P ",
+ 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) {
@@ -1120,6 +1077,55 @@ void cmLocalUnixMakefileGenerator3::AppendCleanCommand(
}
}
+void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand(
+ std::vector<std::string>& commands)
+{
+ std::vector<std::string> cleanFiles;
+ // Look for additional files registered for cleaning in this directory.
+ if (const char* prop_value =
+ this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) {
+ cmExpandList(cmGeneratorExpression::Evaluate(
+ prop_value, this,
+ this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")),
+ cleanFiles);
+ }
+ if (cleanFiles.empty()) {
+ return;
+ }
+
+ cmLocalGenerator* rootLG =
+ this->GetGlobalGenerator()->GetLocalGenerators().at(0);
+ std::string const& binaryDir = rootLG->GetCurrentBinaryDirectory();
+ std::string const& currentBinaryDir = this->GetCurrentBinaryDirectory();
+ std::string cleanfile =
+ cmStrCat(currentBinaryDir, "/CMakeFiles/cmake_directory_clean.cmake");
+ // Write clean script
+ {
+ std::string cleanfilePath = cmSystemTools::CollapseFullPath(cleanfile);
+ cmsys::ofstream fout(cleanfilePath.c_str());
+ if (!fout) {
+ cmSystemTools::Error("Could not create " + cleanfilePath);
+ return;
+ }
+ fout << "file(REMOVE_RECURSE\n";
+ for (std::string const& cfl : cleanFiles) {
+ std::string fc = rootLG->MaybeConvertToRelativePath(
+ binaryDir, cmSystemTools::CollapseFullPath(cfl, currentBinaryDir));
+ fout << " " << cmOutputConverter::EscapeForCMake(fc) << "\n";
+ }
+ fout << ")\n";
+ }
+ // Create command
+ {
+ std::string remove =
+ cmStrCat("$(CMAKE_COMMAND) -P ",
+ this->ConvertToOutputFormat(
+ rootLG->MaybeConvertToRelativePath(binaryDir, cleanfile),
+ cmOutputConverter::SHELL));
+ commands.push_back(std::move(remove));
+ }
+}
+
void cmLocalUnixMakefileGenerator3::AppendEcho(
std::vector<std::string>& commands, std::string const& text, EchoColor color,
EchoProgress const* progress)
@@ -1161,12 +1167,12 @@ void cmLocalUnixMakefileGenerator3::AppendEcho(
std::string cmd;
if (color_name.empty() && !progress) {
// Use the native echo command.
- cmd = "@echo ";
- cmd += this->EscapeForShell(line, false, true);
+ cmd = cmStrCat("@echo ", this->EscapeForShell(line, false, true));
} else {
// Use cmake to echo the text in color.
- cmd = "@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) ";
- cmd += color_name;
+ cmd = cmStrCat(
+ "@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) ",
+ color_name);
if (progress) {
cmd += "--progress-dir=";
cmd += this->ConvertToOutputFormat(
@@ -1179,14 +1185,14 @@ void cmLocalUnixMakefileGenerator3::AppendEcho(
}
cmd += this->EscapeForShell(line);
}
- commands.push_back(cmd);
+ commands.push_back(std::move(cmd));
}
- // Reset the line to emtpy.
- line = "";
+ // Reset the line to empty.
+ line.clear();
// Progress appears only on first line.
- progress = CM_NULLPTR;
+ progress = nullptr;
// Terminate on end-of-string.
if (*c == '\0') {
@@ -1202,8 +1208,7 @@ void cmLocalUnixMakefileGenerator3::AppendEcho(
std::string cmLocalUnixMakefileGenerator3::CreateMakeVariable(
std::string const& s, std::string const& s2)
{
- std::string unmodified = s;
- unmodified += s2;
+ std::string unmodified = cmStrCat(s, s2);
// if there is no restriction on the length of make variables
// and there are no "." characters in the string, then return the
// unmodified combination.
@@ -1218,8 +1223,7 @@ std::string cmLocalUnixMakefileGenerator3::CreateMakeVariable(
// see if the variable has been defined before and return
// the modified version of the variable
- std::map<std::string, std::string>::iterator i =
- this->MakeVariableMap.find(unmodified);
+ auto i = this->MakeVariableMap.find(unmodified);
if (i != this->MakeVariableMap.end()) {
return i->second;
}
@@ -1281,9 +1285,8 @@ std::string cmLocalUnixMakefileGenerator3::CreateMakeVariable(
return ret;
}
-bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo,
- bool verbose,
- bool color)
+bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
+ const std::string& tgtInfo, bool verbose, bool color)
{
// read in the target info file
if (!this->Makefile->ReadListFile(tgtInfo) ||
@@ -1294,26 +1297,25 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo,
// Check if any multiple output pairs have a missing file.
this->CheckMultipleOutputs(verbose);
- std::string dir = cmSystemTools::GetFilenamePath(tgtInfo);
- std::string internalDependFile = dir + "/depend.internal";
- std::string dependFile = dir + "/depend.make";
+ std::string const targetDir = cmSystemTools::GetFilenamePath(tgtInfo);
+ std::string const internalDependFile = targetDir + "/depend.internal";
+ std::string const dependFile = targetDir + "/depend.make";
// If the target DependInfo.cmake file has changed since the last
// time dependencies were scanned then force rescanning. This may
// happen when a new source file is added and CMake regenerates the
// project but no other sources were touched.
bool needRescanDependInfo = false;
- cmFileTimeComparison* ftc =
- this->GlobalGenerator->GetCMakeInstance()->GetFileComparison();
+ cmFileTimeCache* ftc =
+ this->GlobalGenerator->GetCMakeInstance()->GetFileTimeCache();
{
int result;
- if (!ftc->FileTimeCompare(internalDependFile.c_str(), tgtInfo, &result) ||
- result < 0) {
+ if (!ftc->Compare(internalDependFile, tgtInfo, &result) || result < 0) {
if (verbose) {
std::ostringstream msg;
msg << "Dependee \"" << tgtInfo << "\" is newer than depender \""
<< internalDependFile << "\"." << std::endl;
- cmSystemTools::Stdout(msg.str().c_str());
+ cmSystemTools::Stdout(msg.str());
}
needRescanDependInfo = true;
}
@@ -1322,19 +1324,18 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo,
// If the directory information is newer than depend.internal, include dirs
// may have changed. In this case discard all old dependencies.
bool needRescanDirInfo = false;
- std::string dirInfoFile = this->GetCurrentBinaryDirectory();
- dirInfoFile += cmake::GetCMakeFilesDirectory();
- dirInfoFile += "/CMakeDirectoryInformation.cmake";
{
+ std::string dirInfoFile =
+ cmStrCat(this->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/CMakeDirectoryInformation.cmake");
int result;
- if (!ftc->FileTimeCompare(internalDependFile.c_str(), dirInfoFile.c_str(),
- &result) ||
+ if (!ftc->Compare(internalDependFile, dirInfoFile, &result) ||
result < 0) {
if (verbose) {
std::ostringstream msg;
msg << "Dependee \"" << dirInfoFile << "\" is newer than depender \""
<< internalDependFile << "\"." << std::endl;
- cmSystemTools::Stdout(msg.str().c_str());
+ cmSystemTools::Stdout(msg.str());
}
needRescanDirInfo = true;
}
@@ -1344,12 +1345,12 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo,
// The build.make file may have explicit dependencies for the object
// files but these will not affect the scanning process so they need
// not be considered.
- std::map<std::string, cmDepends::DependencyVector> validDependencies;
+ cmDepends::DependencyMap validDependencies;
bool needRescanDependencies = false;
if (!needRescanDirInfo) {
cmDependsC checker;
checker.SetVerbose(verbose);
- checker.SetFileComparison(ftc);
+ checker.SetFileTimeCache(ftc);
// cmDependsC::Check() fills the vector validDependencies() with the
// dependencies for those files where they are still valid, i.e. neither
// the files themselves nor any files they depend on have changed.
@@ -1360,21 +1361,22 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo,
// dependency vector. This means that in the normal case, when only
// few or one file have been edited, then also only this one file is
// actually scanned again, instead of all files for this target.
- needRescanDependencies = !checker.Check(
- dependFile.c_str(), internalDependFile.c_str(), validDependencies);
+ needRescanDependencies =
+ !checker.Check(dependFile, internalDependFile, validDependencies);
}
if (needRescanDependInfo || needRescanDirInfo || needRescanDependencies) {
// The dependencies must be regenerated.
- std::string targetName = cmSystemTools::GetFilenameName(dir);
+ std::string targetName = cmSystemTools::GetFilenameName(targetDir);
targetName = targetName.substr(0, targetName.length() - 4);
- std::string message = "Scanning dependencies of target ";
- message += targetName;
+ std::string message =
+ cmStrCat("Scanning dependencies of target ", targetName);
cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta |
cmsysTerminal_Color_ForegroundBold,
message.c_str(), true, color);
- return this->ScanDependencies(dir.c_str(), validDependencies);
+ return this->ScanDependencies(targetDir, dependFile, internalDependFile,
+ validDependencies);
}
// The dependencies are already up-to-date.
@@ -1382,25 +1384,27 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo,
}
bool cmLocalUnixMakefileGenerator3::ScanDependencies(
- const char* targetDir,
- std::map<std::string, cmDepends::DependencyVector>& validDeps)
+ std::string const& targetDir, std::string const& dependFile,
+ std::string const& internalDependFile, cmDepends::DependencyMap& validDeps)
{
// Read the directory information file.
cmMakefile* mf = this->Makefile;
bool haveDirectoryInfo = false;
- std::string dirInfoFile = this->GetCurrentBinaryDirectory();
- dirInfoFile += cmake::GetCMakeFilesDirectory();
- dirInfoFile += "/CMakeDirectoryInformation.cmake";
- if (mf->ReadListFile(dirInfoFile.c_str()) &&
- !cmSystemTools::GetErrorOccuredFlag()) {
- haveDirectoryInfo = true;
+ {
+ std::string dirInfoFile =
+ cmStrCat(this->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/CMakeDirectoryInformation.cmake");
+ if (mf->ReadListFile(dirInfoFile) &&
+ !cmSystemTools::GetErrorOccuredFlag()) {
+ haveDirectoryInfo = true;
+ }
}
// Lookup useful directory information.
if (haveDirectoryInfo) {
// Test whether we need to force Unix paths.
if (const char* force = mf->GetDefinition("CMAKE_FORCE_UNIX_PATHS")) {
- if (!cmSystemTools::IsOff(force)) {
+ if (!cmIsOff(force)) {
cmSystemTools::SetForceUnixPaths(true);
}
}
@@ -1420,16 +1424,10 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(
cmSystemTools::Error("Directory Information file not found");
}
- // create the file stream for the depends file
- std::string dir = targetDir;
-
// Open the make depends file. This should be copy-if-different
// because the make tool may try to reload it needlessly otherwise.
- std::string ruleFileNameFull = dir;
- ruleFileNameFull += "/depend.make";
cmGeneratedFileStream ruleFileStream(
- ruleFileNameFull.c_str(), false,
- this->GlobalGenerator->GetMakefileEncoding());
+ dependFile, false, this->GlobalGenerator->GetMakefileEncoding());
ruleFileStream.SetCopyIfDifferent(true);
if (!ruleFileStream) {
return false;
@@ -1438,11 +1436,8 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(
// Open the cmake dependency tracking file. This should not be
// copy-if-different because dependencies are re-scanned when it is
// older than the DependInfo.cmake.
- std::string internalRuleFileNameFull = dir;
- internalRuleFileNameFull += "/depend.internal";
cmGeneratedFileStream internalRuleFileStream(
- internalRuleFileNameFull.c_str(), false,
- this->GlobalGenerator->GetMakefileEncoding());
+ internalDependFile, false, this->GlobalGenerator->GetMakefileEncoding());
if (!internalRuleFileStream) {
return false;
}
@@ -1451,39 +1446,34 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(
this->WriteDisclaimer(internalRuleFileStream);
// for each language we need to scan, scan it
- const char* langStr = mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES");
- std::vector<std::string> langs;
- cmSystemTools::ExpandListArgument(langStr, langs);
- for (std::vector<std::string>::iterator li = langs.begin();
- li != langs.end(); ++li) {
+ std::vector<std::string> langs =
+ cmExpandedList(mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES"));
+ for (std::string const& lang : langs) {
// construct the checker
- std::string lang = *li;
-
// Create the scanner for this language
- cmDepends* scanner = CM_NULLPTR;
+ std::unique_ptr<cmDepends> scanner;
if (lang == "C" || lang == "CXX" || lang == "RC" || lang == "ASM" ||
lang == "CUDA") {
// TODO: Handle RC (resource files) dependencies correctly.
- scanner = new cmDependsC(this, targetDir, lang, &validDeps);
+ scanner = cm::make_unique<cmDependsC>(this, targetDir, lang, &validDeps);
}
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
else if (lang == "Fortran") {
- scanner = new cmDependsFortran(this);
+ ruleFileStream << "# Note that incremental build could trigger "
+ << "a call to cmake_copy_f90_mod on each re-build\n";
+ scanner = cm::make_unique<cmDependsFortran>(this);
} else if (lang == "Java") {
- scanner = new cmDependsJava();
+ scanner = cm::make_unique<cmDependsJava>();
}
#endif
if (scanner) {
scanner->SetLocalGenerator(this);
- scanner->SetFileComparison(
- this->GlobalGenerator->GetCMakeInstance()->GetFileComparison());
+ scanner->SetFileTimeCache(
+ this->GlobalGenerator->GetCMakeInstance()->GetFileTimeCache());
scanner->SetLanguage(lang);
- scanner->SetTargetDirectory(dir.c_str());
+ scanner->SetTargetDirectory(targetDir);
scanner->Write(ruleFileStream, internalRuleFileStream);
-
- // free the scanner for this language
- delete scanner;
}
}
@@ -1501,23 +1491,21 @@ void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose)
}
// Convert the string to a list and preserve empty entries.
- std::vector<std::string> pairs;
- cmSystemTools::ExpandListArgument(pairs_string, pairs, true);
- for (std::vector<std::string>::const_iterator i = pairs.begin();
- i != pairs.end() && (i + 1) != pairs.end();) {
+ std::vector<std::string> pairs = cmExpandedList(pairs_string, true);
+ for (auto i = pairs.begin(); i != pairs.end() && (i + 1) != pairs.end();) {
const std::string& depender = *i++;
const std::string& dependee = *i++;
// 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
<< "\" because another output \"" << depender
<< "\" does not exist." << std::endl;
- cmSystemTools::Stdout(msg.str().c_str());
+ cmSystemTools::Stdout(msg.str());
}
cmSystemTools::RemoveFile(dependee);
}
@@ -1535,7 +1523,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
// Just depend on the all target to drive the build.
std::vector<std::string> depends;
std::vector<std::string> no_commands;
- depends.push_back("all");
+ depends.emplace_back("all");
// Write the rule.
this->WriteMakeRule(ruleFileStream,
@@ -1548,9 +1536,10 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
if (gg->AllowNotParallel()) {
std::vector<std::string> no_depends;
- this->WriteMakeRule(ruleFileStream, "Allow only one \"make -f "
- "Makefile2\" at a time, but pass "
- "parallelism.",
+ this->WriteMakeRule(ruleFileStream,
+ "Allow only one \"make -f "
+ "Makefile2\" at a time, but pass "
+ "parallelism.",
".NOTPARALLEL", no_depends, no_commands, false);
}
}
@@ -1562,26 +1551,25 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
this->WriteDivider(ruleFileStream);
ruleFileStream << "# Targets provided globally by CMake.\n"
<< "\n";
- std::vector<cmGeneratorTarget*> targets = this->GetGeneratorTargets();
- std::vector<cmGeneratorTarget*>::iterator glIt;
- for (glIt = targets.begin(); glIt != targets.end(); ++glIt) {
- if ((*glIt)->GetType() == cmStateEnums::GLOBAL_TARGET) {
+ const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets();
+ for (cmGeneratorTarget* gt : targets) {
+ if (gt->GetType() == cmStateEnums::GLOBAL_TARGET) {
std::string targetString =
- "Special rule for the target " + (*glIt)->GetName();
+ "Special rule for the target " + gt->GetName();
std::vector<std::string> commands;
std::vector<std::string> depends;
- const char* text = (*glIt)->GetProperty("EchoString");
+ const char* text = gt->GetProperty("EchoString");
if (!text) {
text = "Running external command ...";
}
- depends.insert(depends.end(), (*glIt)->GetUtilities().begin(),
- (*glIt)->GetUtilities().end());
+ depends.reserve(gt->GetUtilities().size());
+ for (BT<std::string> const& u : gt->GetUtilities()) {
+ depends.push_back(u.Value);
+ }
this->AppendEcho(commands, text,
cmLocalUnixMakefileGenerator3::EchoGlobal);
- cmGeneratorTarget* gt = *glIt;
-
// Global targets store their rules in pre- and post-build commands.
this->AppendCustomDepends(depends, gt->GetPreBuildCommands());
this->AppendCustomDepends(depends, gt->GetPostBuildCommands());
@@ -1599,7 +1587,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
(targetName == "install/strip")) {
// Provide a fast install target that does not depend on all
// but has the same command.
- depends.push_back("preinstall/fast");
+ depends.emplace_back("preinstall/fast");
} else {
// Just forward to the real target so at least it will work.
depends.push_back(targetName);
@@ -1615,21 +1603,24 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
std::vector<std::string> commands;
// Write the all rule.
- std::string recursiveTarget = this->GetCurrentBinaryDirectory();
- recursiveTarget += "/all";
+ std::string recursiveTarget =
+ cmStrCat(this->GetCurrentBinaryDirectory(), "/all");
- depends.push_back("cmake_check_build_system");
+ bool regenerate =
+ !this->GlobalGenerator->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
+ if (regenerate) {
+ depends.emplace_back("cmake_check_build_system");
+ }
- std::string progressDir = this->GetBinaryDirectory();
- progressDir += cmake::GetCMakeFilesDirectory();
+ std::string progressDir =
+ cmStrCat(this->GetBinaryDirectory(), "/CMakeFiles");
{
std::ostringstream progCmd;
progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start ";
progCmd << this->ConvertToOutputFormat(
cmSystemTools::CollapseFullPath(progressDir), cmOutputConverter::SHELL);
- std::string progressFile = cmake::GetCMakeFilesDirectory();
- progressFile += "/progress.marks";
+ std::string progressFile = "/CMakeFiles/progress.marks";
std::string progressFileNameFull = this->ConvertToFullPath(progressFile);
progCmd << " "
<< this->ConvertToOutputFormat(
@@ -1637,10 +1628,8 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
cmOutputConverter::SHELL);
commands.push_back(progCmd.str());
}
- std::string mf2Dir = cmake::GetCMakeFilesDirectoryPostSlash();
- mf2Dir += "Makefile2";
- commands.push_back(
- this->GetRecursiveMakeCall(mf2Dir.c_str(), recursiveTarget));
+ std::string mf2Dir = "CMakeFiles/Makefile2";
+ commands.push_back(this->GetRecursiveMakeCall(mf2Dir, recursiveTarget));
this->CreateCDCommand(commands, this->GetBinaryDirectory(),
this->GetCurrentBinaryDirectory());
{
@@ -1655,38 +1644,34 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
commands, true);
// Write the clean rule.
- recursiveTarget = this->GetCurrentBinaryDirectory();
- recursiveTarget += "/clean";
+ recursiveTarget = cmStrCat(this->GetCurrentBinaryDirectory(), "/clean");
commands.clear();
depends.clear();
- commands.push_back(
- this->GetRecursiveMakeCall(mf2Dir.c_str(), recursiveTarget));
+ commands.push_back(this->GetRecursiveMakeCall(mf2Dir, recursiveTarget));
this->CreateCDCommand(commands, this->GetBinaryDirectory(),
this->GetCurrentBinaryDirectory());
this->WriteMakeRule(ruleFileStream, "The main clean target", "clean",
depends, commands, true);
commands.clear();
depends.clear();
- depends.push_back("clean");
+ depends.emplace_back("clean");
this->WriteMakeRule(ruleFileStream, "The main clean target", "clean/fast",
depends, commands, true);
// Write the preinstall rule.
- recursiveTarget = this->GetCurrentBinaryDirectory();
- recursiveTarget += "/preinstall";
+ recursiveTarget = cmStrCat(this->GetCurrentBinaryDirectory(), "/preinstall");
commands.clear();
depends.clear();
const char* noall =
this->Makefile->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
- if (!noall || cmSystemTools::IsOff(noall)) {
+ if (!noall || cmIsOff(noall)) {
// Drive the build before installing.
- depends.push_back("all");
- } else {
+ depends.emplace_back("all");
+ } else if (regenerate) {
// At least make sure the build system is up to date.
- depends.push_back("cmake_check_build_system");
+ depends.emplace_back("cmake_check_build_system");
}
- commands.push_back(
- this->GetRecursiveMakeCall(mf2Dir.c_str(), recursiveTarget));
+ commands.push_back(this->GetRecursiveMakeCall(mf2Dir, recursiveTarget));
this->CreateCDCommand(commands, this->GetBinaryDirectory(),
this->GetCurrentBinaryDirectory());
this->WriteMakeRule(ruleFileStream, "Prepare targets for installation.",
@@ -1695,22 +1680,32 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
this->WriteMakeRule(ruleFileStream, "Prepare targets for installation.",
"preinstall/fast", depends, commands, true);
- // write the depend rule, really a recompute depends rule
- depends.clear();
- 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);
- this->CreateCDCommand(commands, this->GetBinaryDirectory(),
- this->GetCurrentBinaryDirectory());
- this->WriteMakeRule(ruleFileStream, "clear depends", "depend", depends,
- commands, true);
+ if (regenerate) {
+ // write the depend rule, really a recompute depends rule
+ depends.clear();
+ commands.clear();
+ cmake* cm = this->GlobalGenerator->GetCMakeInstance();
+ if (cm->DoWriteGlobVerifyTarget()) {
+ std::string rescanRule =
+ cmStrCat("$(CMAKE_COMMAND) -P ",
+ this->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
+ cmOutputConverter::SHELL));
+ commands.push_back(rescanRule);
+ }
+ std::string cmakefileName = "CMakeFiles/Makefile.cmake";
+ {
+ std::string runRule = cmStrCat(
+ "$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) "
+ "--check-build-system ",
+ this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL),
+ " 1");
+ commands.push_back(std::move(runRule));
+ }
+ this->CreateCDCommand(commands, this->GetBinaryDirectory(),
+ this->GetCurrentBinaryDirectory());
+ this->WriteMakeRule(ruleFileStream, "clear depends", "depend", depends,
+ commands, true);
+ }
}
void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf,
@@ -1721,20 +1716,18 @@ void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf,
if (!infoDef) {
return;
}
- std::vector<std::string> files;
- cmSystemTools::ExpandListArgument(infoDef, files);
+ std::vector<std::string> files = cmExpandedList(infoDef);
// Each depend information file corresponds to a target. Clear the
// dependencies for that target.
cmDepends clearer;
clearer.SetVerbose(verbose);
- for (std::vector<std::string>::iterator l = files.begin(); l != files.end();
- ++l) {
- std::string dir = cmSystemTools::GetFilenamePath(*l);
+ for (std::string const& file : files) {
+ std::string dir = cmSystemTools::GetFilenamePath(file);
// Clear the implicit dependency makefile.
std::string dependFile = dir + "/depend.make";
- clearer.Clear(dependFile.c_str());
+ clearer.Clear(dependFile);
// Remove the internal dependency check file to force
// regeneration.
@@ -1751,9 +1744,9 @@ class NotInProjectDir
{
public:
// Constructor with the source and binary directory's path
- NotInProjectDir(const std::string& sourceDir, const std::string& binaryDir)
- : SourceDir(sourceDir)
- , BinaryDir(binaryDir)
+ NotInProjectDir(std::string sourceDir, std::string binaryDir)
+ : SourceDir(std::move(sourceDir))
+ , BinaryDir(std::move(binaryDir))
{
}
@@ -1802,54 +1795,61 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
cmakefileStream
<< "# The set of languages for which implicit dependencies are needed:\n";
cmakefileStream << "set(CMAKE_DEPENDS_LANGUAGES\n";
- for (ImplicitDependLanguageMap::const_iterator l = implicitLangs.begin();
- l != implicitLangs.end(); ++l) {
- cmakefileStream << " \"" << l->first << "\"\n";
+ for (auto const& implicitLang : implicitLangs) {
+ cmakefileStream << " \"" << implicitLang.first << "\"\n";
}
cmakefileStream << " )\n";
// now list the files for each language
cmakefileStream
<< "# The set of files for implicit dependencies of each language:\n";
- for (ImplicitDependLanguageMap::const_iterator l = implicitLangs.begin();
- l != implicitLangs.end(); ++l) {
- cmakefileStream << "set(CMAKE_DEPENDS_CHECK_" << l->first << "\n";
- ImplicitDependFileMap const& implicitPairs = l->second;
+ for (auto const& implicitLang : implicitLangs) {
+ cmakefileStream << "set(CMAKE_DEPENDS_CHECK_" << implicitLang.first
+ << "\n";
+ ImplicitDependFileMap const& implicitPairs = implicitLang.second;
// for each file pair
- for (ImplicitDependFileMap::const_iterator pi = implicitPairs.begin();
- pi != implicitPairs.end(); ++pi) {
- for (cmDepends::DependencyVector::const_iterator di = pi->second.begin();
- di != pi->second.end(); ++di) {
- cmakefileStream << " \"" << *di << "\" ";
- cmakefileStream << "\"" << pi->first << "\"\n";
+ for (auto const& implicitPair : implicitPairs) {
+ for (auto const& di : implicitPair.second) {
+ cmakefileStream << " \"" << di << "\" ";
+ cmakefileStream << "\"" << implicitPair.first << "\"\n";
}
}
cmakefileStream << " )\n";
// Tell the dependency scanner what compiler is used.
- std::string cidVar = "CMAKE_";
- cidVar += l->first;
- cidVar += "_COMPILER_ID";
+ std::string cidVar =
+ cmStrCat("CMAKE_", implicitLang.first, "_COMPILER_ID");
const char* cid = this->Makefile->GetDefinition(cidVar);
if (cid && *cid) {
- cmakefileStream << "set(CMAKE_" << l->first << "_COMPILER_ID \"" << cid
+ cmakefileStream << "set(CMAKE_" << implicitLang.first
+ << "_COMPILER_ID \"" << cid << "\")\n";
+ }
+
+ if (implicitLang.first == "Fortran") {
+ std::string smodSep =
+ this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_SEP");
+ std::string smodExt =
+ this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_EXT");
+ cmakefileStream << "set(CMAKE_Fortran_SUBMODULE_SEP \"" << smodSep
+ << "\")\n";
+ cmakefileStream << "set(CMAKE_Fortran_SUBMODULE_EXT \"" << smodExt
<< "\")\n";
}
// Build a list of preprocessor definitions for the target.
std::set<std::string> defines;
- this->AddCompileDefinitions(defines, target, this->ConfigName, l->first);
+ this->GetTargetDefines(target, this->ConfigName, implicitLang.first,
+ defines);
if (!defines.empty()) {
/* clang-format off */
cmakefileStream
<< "\n"
<< "# Preprocessor definitions for this target.\n"
- << "set(CMAKE_TARGET_DEFINITIONS_" << l->first << "\n";
+ << "set(CMAKE_TARGET_DEFINITIONS_" << implicitLang.first << "\n";
/* clang-format on */
- for (std::set<std::string>::const_iterator di = defines.begin();
- di != defines.end(); ++di) {
- cmakefileStream << " " << cmOutputConverter::EscapeForCMake(*di)
+ for (std::string const& define : defines) {
+ cmakefileStream << " " << cmOutputConverter::EscapeForCMake(define)
<< "\n";
}
cmakefileStream << " )\n";
@@ -1858,21 +1858,20 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
// Target-specific include directories:
cmakefileStream << "\n"
<< "# The include file search paths:\n";
- cmakefileStream << "set(CMAKE_" << l->first << "_TARGET_INCLUDE_PATH\n";
+ cmakefileStream << "set(CMAKE_" << implicitLang.first
+ << "_TARGET_INCLUDE_PATH\n";
std::vector<std::string> includes;
- const std::string& config =
- this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
- this->GetIncludeDirectories(includes, target, l->first, config);
+ this->GetIncludeDirectories(includes, target, implicitLang.first,
+ this->ConfigName);
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::vector<std::string>::iterator i = includes.begin();
- i != includes.end(); ++i) {
+ for (std::string const& include : includes) {
cmakefileStream << " \""
- << this->MaybeConvertToRelativePath(binaryDir, *i)
+ << this->MaybeConvertToRelativePath(binaryDir, include)
<< "\"\n";
}
cmakefileStream << " )\n";
@@ -1883,18 +1882,16 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
std::vector<std::string> transformRules;
if (const char* xform =
this->Makefile->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) {
- cmSystemTools::ExpandListArgument(xform, transformRules);
+ cmExpandList(xform, transformRules);
}
if (const char* xform =
target->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) {
- cmSystemTools::ExpandListArgument(xform, transformRules);
+ cmExpandList(xform, transformRules);
}
if (!transformRules.empty()) {
cmakefileStream << "set(CMAKE_INCLUDE_TRANSFORMS\n";
- for (std::vector<std::string>::const_iterator tri = transformRules.begin();
- tri != transformRules.end(); ++tri) {
- cmakefileStream << " " << cmOutputConverter::EscapeForCMake(*tri)
- << "\n";
+ for (std::string const& tr : transformRules) {
+ cmakefileStream << " " << cmOutputConverter::EscapeForCMake(tr) << "\n";
}
cmakefileStream << " )\n";
}
@@ -1909,13 +1906,12 @@ void cmLocalUnixMakefileGenerator3::WriteDisclaimer(std::ostream& os)
}
std::string cmLocalUnixMakefileGenerator3::GetRecursiveMakeCall(
- const char* makefile, const std::string& tgt)
+ const std::string& makefile, const std::string& tgt)
{
// Call make on the given file.
- std::string cmd;
- cmd += "$(MAKE) -f ";
- cmd += this->ConvertToOutputFormat(makefile, cmOutputConverter::SHELL);
- cmd += " ";
+ std::string cmd = cmStrCat(
+ "$(MAKE) -f ",
+ this->ConvertToOutputFormat(makefile, cmOutputConverter::SHELL), ' ');
cmGlobalUnixMakefileGenerator3* gg =
static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
@@ -1979,7 +1975,7 @@ void cmLocalUnixMakefileGenerator3::WriteCMakeArgument(std::ostream& os,
}
std::string cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(
- const char* p, bool useWatcomQuote)
+ const std::string& p, bool useWatcomQuote)
{
// Split the path into its components.
std::vector<std::string> components;
@@ -2004,10 +2000,9 @@ std::string cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(
#if defined(_WIN32) && !defined(__CYGWIN__)
if (!cmSystemTools::GetForceUnixPaths()) {
slash = "\\";
- for (std::string::iterator i = components[0].begin();
- i != components[0].end(); ++i) {
- if (*i == '/') {
- *i = '\\';
+ for (char& i : components[0]) {
+ if (i == '/') {
+ i = '\\';
}
}
}
@@ -2019,10 +2014,9 @@ std::string cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(
if (components.size() > 1) {
// Now add the rest of the components separated by the proper slash
// direction for this platform.
- std::vector<std::string>::const_iterator compEnd = std::remove(
- components.begin() + 1, components.end() - 1, std::string());
- std::vector<std::string>::const_iterator compStart =
- components.begin() + 1;
+ auto compEnd = std::remove(components.begin() + 1, components.end() - 1,
+ std::string());
+ auto compStart = components.begin() + 1;
result += cmJoin(cmMakeRange(compStart, compEnd), slash);
// Only the last component can be empty to avoid double slashes.
result += slash;
@@ -2047,8 +2041,7 @@ std::string cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(
std::string cmLocalUnixMakefileGenerator3::GetTargetDirectory(
cmGeneratorTarget const* target) const
{
- std::string dir = cmake::GetCMakeFilesDirectoryPostSlash();
- dir += target->GetName();
+ std::string dir = cmStrCat("CMakeFiles/", target->GetName());
#if defined(__VMS)
dir += "_dir";
#else
@@ -2064,14 +2057,14 @@ cmLocalUnixMakefileGenerator3::GetImplicitDepends(const cmGeneratorTarget* tgt)
}
void cmLocalUnixMakefileGenerator3::AddImplicitDepends(
- const cmGeneratorTarget* tgt, const std::string& lang, const char* obj,
- const char* src)
+ const cmGeneratorTarget* tgt, const std::string& lang,
+ const std::string& obj, const std::string& src)
{
this->ImplicitDepends[tgt->GetName()][lang][obj].push_back(src);
}
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?
@@ -2091,14 +2084,13 @@ void cmLocalUnixMakefileGenerator3::CreateCDCommand(
// On Windows we must perform each step separately and then change
// back because the shell keeps the working directory between
// commands.
- std::string cmd = cd_cmd;
- cmd += this->ConvertToOutputForExisting(tgtDir);
+ std::string cmd =
+ cmStrCat(cd_cmd, this->ConvertToOutputForExisting(tgtDir));
commands.insert(commands.begin(), cmd);
// Change back to the starting directory.
- cmd = cd_cmd;
- cmd += this->ConvertToOutputForExisting(relDir);
- commands.push_back(cmd);
+ cmd = cmStrCat(cd_cmd, this->ConvertToOutputForExisting(relDir));
+ 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
@@ -2106,16 +2098,6 @@ void cmLocalUnixMakefileGenerator3::CreateCDCommand(
std::string outputForExisting = this->ConvertToOutputForExisting(tgtDir);
std::string prefix = cd_cmd + outputForExisting + " && ";
std::transform(commands.begin(), commands.end(), commands.begin(),
- std::bind1st(std::plus<std::string>(), prefix));
- }
-}
-
-std::string cmLocalUnixMakefileGenerator3::MaybeConvertToRelativePath(
- std::string const& base, std::string const& path)
-{
- if (!cmOutputConverter::ContainedInDirectory(
- base, path, this->GetStateSnapshot().GetDirectory())) {
- return path;
+ [&prefix](std::string const& s) { return prefix + s; });
}
- return cmOutputConverter::ForceToRelativePath(base, path);
}
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index f64409cba..f12ae8b16 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -3,23 +3,23 @@
#ifndef cmLocalUnixMakefileGenerator3_h
#define cmLocalUnixMakefileGenerator3_h
-#include "cmConfigure.h"
-
-#include "cmDepends.h"
-#include "cmLocalCommonGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <map>
#include <set>
#include <string>
+#include <utility>
#include <vector>
+#include "cmDepends.h"
+#include "cmLocalCommonGenerator.h"
+
class cmCustomCommand;
class cmCustomCommandGenerator;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmMakefile;
-class cmSourceFile;
/** \class cmLocalUnixMakefileGenerator3
* \brief Write a LocalUnix makefiles.
@@ -31,14 +31,14 @@ class cmLocalUnixMakefileGenerator3 : public cmLocalCommonGenerator
{
public:
cmLocalUnixMakefileGenerator3(cmGlobalGenerator* gg, cmMakefile* mf);
- ~cmLocalUnixMakefileGenerator3() CM_OVERRIDE;
+ ~cmLocalUnixMakefileGenerator3() override;
- void ComputeHomeRelativeOutputPath() CM_OVERRIDE;
+ void ComputeHomeRelativeOutputPath() override;
/**
* Generate the makefile for this directory.
*/
- void Generate() CM_OVERRIDE;
+ void Generate() override;
// this returns the relative path between the HomeOutputDirectory and this
// local generators StartOutputDirectory
@@ -84,13 +84,13 @@ public:
void WriteDivider(std::ostream& os);
/** used to create a recursive make call */
- std::string GetRecursiveMakeCall(const char* makefile,
+ std::string GetRecursiveMakeCall(const std::string& makefile,
const std::string& tgt);
// append flags to a string
void AppendFlags(std::string& flags,
- const std::string& newFlags) CM_OVERRIDE;
- void AppendFlags(std::string& flags, const char* newFlags) CM_OVERRIDE;
+ const std::string& newFlags) const override;
+ using cmLocalCommonGenerator::AppendFlags;
// append an echo command
enum EchoColor
@@ -108,20 +108,20 @@ public:
std::string Arg;
};
void AppendEcho(std::vector<std::string>& commands, std::string const& text,
- EchoColor color = EchoNormal,
- EchoProgress const* = CM_NULLPTR);
+ EchoColor color = EchoNormal, EchoProgress const* = nullptr);
/** Get whether the makefile is to have color. */
bool GetColorMakefile() const { return this->ColorMakefile; }
- std::string GetTargetDirectory(cmGeneratorTarget const* target) const
- CM_OVERRIDE;
+ std::string GetTargetDirectory(
+ cmGeneratorTarget const* target) const override;
// 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,
+ static std::string ConvertToQuotedOutputPath(const std::string& p,
bool useWatcomQuote);
std::string CreateMakeVariable(const std::string& sin,
@@ -129,22 +129,22 @@ public:
/** Called from command-line hook to bring dependencies up to date
for a target. */
- bool UpdateDependencies(const char* tgtInfo, bool verbose,
- bool color) CM_OVERRIDE;
+ bool UpdateDependencies(const std::string& tgtInfo, bool verbose,
+ bool color) override;
/** Called from command-line hook to clear dependencies. */
- void ClearDependencies(cmMakefile* mf, bool verbose) CM_OVERRIDE;
+ void ClearDependencies(cmMakefile* mf, bool verbose) override;
/** write some extra rules such as make test etc */
void WriteSpecialTargetsTop(std::ostream& makefileStream);
void WriteSpecialTargetsBottom(std::ostream& makefileStream);
- std::string GetRelativeTargetDirectory(cmGeneratorTarget* target);
+ std::string GetRelativeTargetDirectory(
+ cmGeneratorTarget const* target) const;
// File pairs for implicit dependency scanning. The key of the map
// is the depender and the value is the explicit dependee.
- struct ImplicitDependFileMap
- : public std::map<std::string, cmDepends::DependencyVector>
+ struct ImplicitDependFileMap : public cmDepends::DependencyMap
{
};
struct ImplicitDependLanguageMap
@@ -159,8 +159,8 @@ public:
cmGeneratorTarget const* tgt);
void AddImplicitDepends(cmGeneratorTarget const* tgt,
- const std::string& lang, const char* obj,
- const char* src);
+ const std::string& lang, const std::string& obj,
+ const std::string& src);
// write the target rules for the local Makefile into the stream
void WriteLocalAllRules(std::ostream& ruleFileStream);
@@ -184,9 +184,6 @@ public:
// Eclipse generator.
void GetIndividualFileTargets(std::vector<std::string>& targets);
- std::string MaybeConvertToRelativePath(std::string const& base,
- std::string const& path);
-
protected:
void WriteLocalMakefile();
@@ -201,9 +198,6 @@ protected:
void WriteDependLanguageInfo(std::ostream& cmakefileStream,
cmGeneratorTarget* tgt);
- // write the local help rule
- void WriteHelpRule(std::ostream& ruleFileStream);
-
// this converts a file name that is relative to the StartOuputDirectory
// into a full path
std::string ConvertToFullPath(const std::string& localPath);
@@ -212,15 +206,6 @@ protected:
const std::string& realTarget,
const std::string& helpTarget);
- void WriteTargetDependRule(std::ostream& ruleFileStream,
- cmGeneratorTarget* target);
- void WriteTargetCleanRule(std::ostream& ruleFileStream,
- cmGeneratorTarget* target,
- const std::vector<std::string>& files);
- void WriteTargetRequiresRule(std::ostream& ruleFileStream,
- cmGeneratorTarget* target,
- const std::vector<std::string>& objects);
-
void AppendRuleDepend(std::vector<std::string>& depends,
const char* ruleFileName);
void AppendRuleDepends(std::vector<std::string>& depends,
@@ -238,25 +223,23 @@ protected:
cmGeneratorTarget* target,
std::string const& relative,
bool echo_comment = false,
- std::ostream* content = CM_NULLPTR);
+ std::ostream* content = nullptr);
void AppendCleanCommand(std::vector<std::string>& commands,
- const std::vector<std::string>& files,
+ const std::set<std::string>& files,
cmGeneratorTarget* target,
- const char* filename = CM_NULLPTR);
-
- // Helper methods for dependeny updates.
- bool ScanDependencies(
- const char* targetDir,
- std::map<std::string, cmDepends::DependencyVector>& validDeps);
+ const char* filename = nullptr);
+ void AppendDirectoryCleanCommand(std::vector<std::string>& commands);
+
+ // Helper methods for dependency updates.
+ bool ScanDependencies(std::string const& targetDir,
+ std::string const& dependFile,
+ std::string const& internalDependFile,
+ cmDepends::DependencyMap& validDeps);
void CheckMultipleOutputs(bool verbose);
private:
std::string MaybeConvertWatcomShellCommand(std::string const& cmd);
- void ComputeObjectFilenames(
- std::map<cmSourceFile const*, std::string>& mapping,
- cmGeneratorTarget const* gt = CM_NULLPTR) CM_OVERRIDE;
-
friend class cmMakefileTargetGenerator;
friend class cmMakefileExecutableTargetGenerator;
friend class cmMakefileLibraryTargetGenerator;
@@ -269,36 +252,27 @@ private:
struct LocalObjectEntry
{
- cmGeneratorTarget* Target;
+ cmGeneratorTarget* Target = nullptr;
std::string Language;
- LocalObjectEntry()
- : Target(CM_NULLPTR)
- , Language()
- {
- }
- LocalObjectEntry(cmGeneratorTarget* t, const std::string& lang)
+ LocalObjectEntry() = default;
+ LocalObjectEntry(cmGeneratorTarget* t, std::string lang)
: Target(t)
- , Language(lang)
+ , Language(std::move(lang))
{
}
};
struct LocalObjectInfo : public std::vector<LocalObjectEntry>
{
- bool HasSourceExtension;
- bool HasPreprocessRule;
- bool HasAssembleRule;
- LocalObjectInfo()
- : HasSourceExtension(false)
- , HasPreprocessRule(false)
- , HasAssembleRule(false)
- {
- }
+ bool HasSourceExtension = false;
+ bool HasPreprocessRule = false;
+ bool HasAssembleRule = false;
};
void GetLocalObjectFiles(
std::map<std::string, LocalObjectInfo>& localObjectFiles);
void WriteObjectConvenienceRule(std::ostream& ruleFileStream,
- const char* comment, const char* output,
+ const char* comment,
+ const std::string& output,
LocalObjectInfo const& info);
std::vector<std::string> LocalHelp;
diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx
index 85d4a73b7..f3d828b28 100644
--- a/Source/cmLocalVisualStudio10Generator.cxx
+++ b/Source/cmLocalVisualStudio10Generator.cxx
@@ -2,13 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalVisualStudio10Generator.h"
+#include "cm_expat.h"
+
#include "cmGeneratorTarget.h"
#include "cmGlobalVisualStudio10Generator.h"
#include "cmMakefile.h"
#include "cmVisualStudio10TargetGenerator.h"
#include "cmXMLParser.h"
-
-#include "cm_expat.h"
+#include "cmake.h"
class cmVS10XMLParser : public cmXMLParser
{
@@ -17,7 +18,12 @@ public:
virtual void CharacterDataHandler(const char* data, int length)
{
if (this->DoGUID) {
- this->GUID.assign(data + 1, length - 2);
+ if (data[0] == '{') {
+ // remove surrounding curly brackets
+ this->GUID.assign(data + 1, length - 2);
+ } else {
+ this->GUID.assign(data, length);
+ }
this->DoGUID = false;
}
}
@@ -57,23 +63,48 @@ cmLocalVisualStudio10Generator::~cmLocalVisualStudio10Generator()
{
}
-void cmLocalVisualStudio10Generator::Generate()
+void cmLocalVisualStudio10Generator::GenerateTargetsDepthFirst(
+ cmGeneratorTarget* target, std::vector<cmGeneratorTarget*>& remaining)
{
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return;
+ }
+ // Find this target in the list of remaining targets.
+ auto it = std::find(remaining.begin(), remaining.end(), target);
+ if (it == remaining.end()) {
+ // This target was already handled.
+ return;
+ }
+ // Remove this target from the list of remaining targets because
+ // we are handling it now.
+ *it = nullptr;
+ auto& deps = this->GlobalGenerator->GetTargetDirectDepends(target);
+ for (auto& d : deps) {
+ // FIXME: Revise CreateSingleVCProj so we do not have to drop `const` here.
+ auto dependee = const_cast<cmGeneratorTarget*>(&*d);
+ GenerateTargetsDepthFirst(dependee, remaining);
+ // Take the union of visited source files of custom commands
+ auto visited = GetSourcesVisited(dependee);
+ GetSourcesVisited(target).insert(visited.begin(), visited.end());
+ }
+ if (static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
+ ->TargetIsFortranOnly(target)) {
+ this->CreateSingleVCProj(target->GetName(), target);
+ } else {
+ cmVisualStudio10TargetGenerator tg(
+ target,
+ static_cast<cmGlobalVisualStudio10Generator*>(
+ this->GetGlobalGenerator()));
+ tg.Generate();
+ }
+}
- std::vector<cmGeneratorTarget*> tgts = this->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin();
- l != tgts.end(); ++l) {
- if ((*l)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
- continue;
- }
- if (static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
- ->TargetIsFortranOnly(*l)) {
- this->CreateSingleVCProj((*l)->GetName().c_str(), *l);
- } else {
- cmVisualStudio10TargetGenerator tg(
- *l, static_cast<cmGlobalVisualStudio10Generator*>(
- this->GetGlobalGenerator()));
- tg.Generate();
+void cmLocalVisualStudio10Generator::Generate()
+{
+ std::vector<cmGeneratorTarget*> remaining = this->GetGeneratorTargets();
+ for (auto& t : remaining) {
+ if (t) {
+ GenerateTargetsDepthFirst(t, remaining);
}
}
this->WriteStampFiles();
@@ -90,8 +121,7 @@ void cmLocalVisualStudio10Generator::ReadAndStoreExternalGUID(
return;
}
- std::string guidStoreName = name;
- guidStoreName += "_GUID_CMAKE";
+ std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE");
// save the GUID in the cache
this->GlobalGenerator->GetCMakeInstance()->AddCacheEntry(
guidStoreName.c_str(), parser.GUID.c_str(), "Stored GUID",
diff --git a/Source/cmLocalVisualStudio10Generator.h b/Source/cmLocalVisualStudio10Generator.h
index e57dd8f20..5c6400e9f 100644
--- a/Source/cmLocalVisualStudio10Generator.h
+++ b/Source/cmLocalVisualStudio10Generator.h
@@ -3,7 +3,7 @@
#ifndef cmLocalVisualStudio10Generator_h
#define cmLocalVisualStudio10Generator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
@@ -21,7 +21,7 @@ class cmMakefile;
class cmLocalVisualStudio10Generator : public cmLocalVisualStudio7Generator
{
public:
- ///! Set cache only and recurse to false by default.
+ //! Set cache only and recurse to false by default.
cmLocalVisualStudio10Generator(cmGlobalGenerator* gg, cmMakefile* mf);
virtual ~cmLocalVisualStudio10Generator();
@@ -29,14 +29,23 @@ 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;
+
+ std::set<cmSourceFile const*>& GetSourcesVisited(cmGeneratorTarget* target)
+ {
+ return SourcesVisited[target];
+ };
protected:
- virtual const char* ReportErrorLabel() const;
- virtual bool CustomCommandUseLocal() const { return true; }
+ const char* ReportErrorLabel() const override;
+ bool CustomCommandUseLocal() const override { return true; }
private:
+ void GenerateTargetsDepthFirst(cmGeneratorTarget* target,
+ std::vector<cmGeneratorTarget*>& remaining);
+
+ std::map<cmGeneratorTarget*, std::set<cmSourceFile const*>> SourcesVisited;
};
#endif
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index dd08e5bdb..f19549d7b 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -2,22 +2,26 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalVisualStudio7Generator.h"
+#include <windows.h>
+
+#include <ctype.h> // for isspace
+
+#include "cm_expat.h"
+
+#include "cmComputeLinkInformation.h"
+#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalVisualStudio7Generator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmSourceFile.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
-#include "cm_expat.h"
#include "cmake.h"
-#include "cmComputeLinkInformation.h"
-#include "cmGeneratedFileStream.h"
-
-#include <ctype.h> // for isspace
-#include <windows.h>
-
static bool cmLVS7G_IsFAT(const char* dir);
class cmLocalVisualStudio7GeneratorInternals
@@ -27,7 +31,7 @@ public:
: LocalGenerator(e)
{
}
- typedef cmComputeLinkInformation::ItemVector ItemVector;
+ using ItemVector = cmComputeLinkInformation::ItemVector;
void OutputLibraries(std::ostream& fout, ItemVector const& libs);
void OutputObjects(std::ostream& fout, cmGeneratorTarget* t,
std::string const& config, const char* isep = 0);
@@ -36,16 +40,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)
@@ -62,15 +64,14 @@ cmLocalVisualStudio7Generator::~cmLocalVisualStudio7Generator()
void cmLocalVisualStudio7Generator::AddHelperCommands()
{
// Now create GUIDs for targets
- std::vector<cmGeneratorTarget*> tgts = this->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin();
- l != tgts.end(); ++l) {
- if ((*l)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets();
+ 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,53 +84,28 @@ 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.
- std::vector<cmGeneratorTarget*> tgts = this->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::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.
- std::vector<cmGeneratorTarget*> tgts = this->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin();
- l != tgts.end(); l++) {
- if ((*l)->GetType() == cmStateEnums::GLOBAL_TARGET) {
+ const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets();
+ for (cmGeneratorTarget* l : tgts) {
+ if (l->GetType() == cmStateEnums::GLOBAL_TARGET) {
std::vector<std::string> no_depends;
- cmCustomCommandLine force_command;
- force_command.push_back("cd");
- force_command.push_back(".");
- cmCustomCommandLines force_commands;
- force_commands.push_back(force_command);
- std::string no_main_dependency = "";
- std::string force = this->GetCurrentBinaryDirectory();
- force += cmake::GetCMakeFilesDirectory();
- force += "/";
- force += (*l)->GetName();
- force += "_force";
+ cmCustomCommandLines force_commands =
+ cmMakeSingleCommandLine({ "cd", "." });
+ std::string no_main_dependency;
+ std::string force = cmStrCat(this->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/", l->GetName(), "_force");
+ if (cmSourceFile* sf =
+ this->Makefile->GetOrCreateGeneratedSource(force)) {
+ sf->SetProperty("SYMBOLIC", "1");
+ }
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->ResolveFullPath());
}
}
}
@@ -141,27 +117,25 @@ 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 ",
+ cmSystemTools::Error("Error creating directory " +
this->GetCurrentBinaryDirectory());
}
}
// Get the set of targets in this directory.
- std::vector<cmGeneratorTarget*> tgts = this->GetGeneratorTargets();
+ const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets();
// Create the project file for each target.
- for (std::vector<cmGeneratorTarget*>::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);
}
}
}
@@ -170,11 +144,10 @@ void cmLocalVisualStudio7Generator::WriteStampFiles()
{
// Touch a timestamp file used to determine when the project file is
// out of date.
- std::string stampName = this->GetCurrentBinaryDirectory();
- stampName += cmake::GetCMakeFilesDirectory();
+ std::string stampName =
+ cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles");
cmSystemTools::MakeDirectory(stampName.c_str());
- stampName += "/";
- stampName += "generate.stamp";
+ stampName += "/generate.stamp";
cmsys::ofstream stamp(stampName.c_str());
stamp << "# CMake generation timestamp file for this directory.\n";
@@ -184,14 +157,24 @@ void cmLocalVisualStudio7Generator::WriteStampFiles()
// dependencies. If any file listed in it is newer than itself then
// CMake must rerun. Otherwise the project files are up to date and
// the stamp file can just be touched.
- std::string depName = stampName;
- depName += ".depend";
+ std::string depName = cmStrCat(stampName, ".depend");
cmsys::ofstream depFile(depName.c_str());
depFile << "# CMake generation dependency list for this directory.\n";
- std::vector<std::string> const& listFiles = this->Makefile->GetListFiles();
- for (std::vector<std::string>::const_iterator lf = listFiles.begin();
- lf != listFiles.end(); ++lf) {
- depFile << *lf << std::endl;
+
+ std::vector<std::string> listFiles(this->Makefile->GetListFiles());
+ cmake* cm = this->GlobalGenerator->GetCMakeInstance();
+ if (cm->DoWriteGlobVerifyTarget()) {
+ listFiles.push_back(cm->GetGlobVerifyStamp());
+ }
+
+ // Sort the list of input files and remove duplicates.
+ std::sort(listFiles.begin(), listFiles.end(), std::less<std::string>());
+ std::vector<std::string>::iterator new_end =
+ std::unique(listFiles.begin(), listFiles.end());
+ listFiles.erase(new_end, listFiles.end());
+
+ for (const std::string& lf : listFiles) {
+ depFile << lf << "\n";
}
}
@@ -214,9 +197,7 @@ void cmLocalVisualStudio7Generator::CreateSingleVCProj(
target->Target->SetProperty("GENERATOR_FILE_NAME", lname.c_str());
// create the dsp.cmake file
std::string fname;
- fname = this->GetCurrentBinaryDirectory();
- fname += "/";
- fname += lname;
+ fname = cmStrCat(this->GetCurrentBinaryDirectory(), '/', lname);
if (this->FortranProject) {
fname += ".vfproj";
} else {
@@ -238,46 +219,57 @@ void cmLocalVisualStudio7Generator::CreateSingleVCProj(
cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
{
- 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;
- args = "-H";
- args += this->GetSourceDirectory();
- commandLine.push_back(args);
- args = "-B";
- args += this->GetBinaryDirectory();
- commandLine.push_back(args);
- commandLine.push_back("--check-stamp-file");
- commandLine.push_back(stampName);
-
- std::vector<std::string> const& listFiles = this->Makefile->GetListFiles();
-
- cmCustomCommandLines commandLines;
- commandLines.push_back(commandLine);
- const char* no_working_directory = 0;
+ if (this->GlobalGenerator->GlobalSettingIsOn(
+ "CMAKE_SUPPRESS_REGENERATION")) {
+ return nullptr;
+ }
+
+ std::string makefileIn =
+ cmStrCat(this->GetCurrentSourceDirectory(), "/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::vector<std::string> listFiles = this->Makefile->GetListFiles();
+ cmake* cm = this->GlobalGenerator->GetCMakeInstance();
+ if (cm->DoWriteGlobVerifyTarget()) {
+ listFiles.push_back(cm->GetGlobVerifyStamp());
+ }
+
+ // Sort the list of input files and remove duplicates.
+ std::sort(listFiles.begin(), listFiles.end(), std::less<std::string>());
+ std::vector<std::string>::iterator new_end =
+ std::unique(listFiles.begin(), listFiles.end());
+ listFiles.erase(new_end, listFiles.end());
+
+ std::string argS = cmStrCat("-S", this->GetSourceDirectory());
+ std::string argB = cmStrCat("-B", this->GetBinaryDirectory());
+ std::string stampName =
+ cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/generate.stamp");
+ cmCustomCommandLines commandLines =
+ cmMakeSingleCommandLine({ cmSystemTools::GetCMakeCommand(), argS, argB,
+ "--check-stamp-file", stampName });
+ std::string comment = cmStrCat("Building Custom Rule ", makefileIn);
+ const char* no_working_directory = nullptr;
std::string fullpathStampName =
cmSystemTools::CollapseFullPath(stampName.c_str());
this->Makefile->AddCustomCommandToOutput(
- fullpathStampName.c_str(), listFiles, makefileIn.c_str(), commandLines,
- comment.c_str(), no_working_directory, true, false);
+ fullpathStampName, listFiles, makefileIn, 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->ResolveFullPath();
return file;
} else {
- cmSystemTools::Error("Error adding rule for ", makefileIn.c_str());
- return 0;
+ cmSystemTools::Error("Error adding rule for " + makefileIn);
+ return nullptr;
}
}
@@ -286,9 +278,8 @@ void cmLocalVisualStudio7Generator::WriteConfigurations(
const std::string& libName, cmGeneratorTarget* target)
{
fout << "\t<Configurations>\n";
- for (std::vector<std::string>::const_iterator i = configs.begin();
- i != configs.end(); ++i) {
- this->WriteConfiguration(fout, i->c_str(), libName, target);
+ for (std::string const& config : configs) {
+ this->WriteConfiguration(fout, config.c_str(), libName, target);
}
fout << "\t</Configurations>\n";
}
@@ -356,7 +347,7 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorFortranFlagTable[] = {
{ "EnableRecursion", "recursive", "", "true", 0 },
{ "ReentrantCode", "reentrancy", "", "true", 0 },
// done up to Language
- { 0, 0, 0, 0, 0 }
+ { "", "", "", "", 0 }
};
// fill the table here currently the comment field is not used for
// anything other than documentation NOTE: Make sure the longer
@@ -466,7 +457,7 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[] = {
{ "WarnAsError", "WX", "Treat warnings as errors", "true", 0 },
{ "BrowseInformation", "FR", "Generate browse information", "1", 0 },
{ "StringPooling", "GF", "Enable StringPooling", "true", 0 },
- { 0, 0, 0, 0, 0 }
+ { "", "", "", "", 0 }
};
cmVS7FlagTable cmLocalVisualStudio7GeneratorLinkFlagTable[] = {
@@ -525,12 +516,13 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorLinkFlagTable[] = {
{ "TargetMachine", "MACHINE:SH5", "Machine SH5", "15", 0 },
{ "TargetMachine", "MACHINE:THUMB", "Machine THUMB", "16", 0 },
{ "TargetMachine", "MACHINE:X64", "Machine x64", "17", 0 },
+ { "TargetMachine", "MACHINE:ARM64", "Machine ARM64", "18", 0 },
{ "TurnOffAssemblyGeneration", "NOASSEMBLY",
"No assembly even if CLR information is present in objects.", "true", 0 },
{ "ModuleDefinitionFile", "DEF:", "add an export def file", "",
cmVS7FlagTable::UserValue },
{ "GenerateMapFile", "MAP", "enable generation of map file", "true", 0 },
- { 0, 0, 0, 0, 0 }
+ { "", "", "", "", 0 }
};
cmVS7FlagTable cmLocalVisualStudio7GeneratorFortranLinkFlagTable[] = {
@@ -538,7 +530,15 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorFortranLinkFlagTable[] = {
"linkIncrementalNo", 0 },
{ "LinkIncremental", "INCREMENTAL:YES", "link incremental",
"linkIncrementalYes", 0 },
- { 0, 0, 0, 0, 0 }
+ { "EnableCOMDATFolding", "OPT:NOICF", "Do not remove redundant COMDATs",
+ "optNoFolding", 0 },
+ { "EnableCOMDATFolding", "OPT:ICF", "Remove redundant COMDATs", "optFolding",
+ 0 },
+ { "OptimizeReferences", "OPT:NOREF", "Keep unreferenced data",
+ "optNoReferences", 0 },
+ { "OptimizeReferences", "OPT:REF", "Eliminate unreferenced data",
+ "optReferences", 0 },
+ { "", "", "", "", 0 }
};
// Helper class to write build event <Tool .../> elements.
@@ -561,9 +561,8 @@ public:
void Finish() { this->Stream << (this->First ? "" : "\"") << "/>\n"; }
void Write(std::vector<cmCustomCommand> const& ccs)
{
- for (std::vector<cmCustomCommand>::const_iterator ci = ccs.begin();
- ci != ccs.end(); ++ci) {
- this->Write(*ci);
+ for (cmCustomCommand const& command : ccs) {
+ this->Write(command);
}
}
void Write(cmCustomCommand const& cc)
@@ -616,6 +615,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";
@@ -631,6 +631,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
case cmStateEnums::UTILITY:
case cmStateEnums::GLOBAL_TARGET:
configType = "10";
+ CM_FALLTHROUGH;
default:
targetBuilds = false;
break;
@@ -639,26 +640,21 @@ 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));
if (linkLanguage.empty()) {
cmSystemTools::Error(
- "CMake can not determine linker language for target: ",
- target->GetName().c_str());
+ "CMake can not determine linker language for target: " +
+ target->GetName());
return;
}
- if (linkLanguage == "C" || linkLanguage == "CXX" ||
- linkLanguage == "Fortran") {
- std::string baseFlagVar = "CMAKE_";
- baseFlagVar += linkLanguage;
- baseFlagVar += "_FLAGS";
- flags = this->Makefile->GetRequiredDefinition(baseFlagVar.c_str());
- std::string flagVar =
- baseFlagVar + std::string("_") + cmSystemTools::UpperCase(configName);
- flags += " ";
- flags += this->Makefile->GetRequiredDefinition(flagVar.c_str());
+ langForClCompile = linkLanguage;
+ if (langForClCompile == "C" || langForClCompile == "CXX" ||
+ langForClCompile == "Fortran") {
+ this->AddLanguageFlags(flags, target, langForClCompile, configName);
}
// set the correct language
if (linkLanguage == "C") {
@@ -669,7 +665,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);
@@ -699,33 +695,36 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
}
Options targetOptions(this, t, table, gg->ExtraFlagTable);
targetOptions.FixExceptionHandlingDefault();
- std::string asmLocation = configName + "/";
- targetOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str());
- targetOptions.Parse(flags.c_str());
- targetOptions.Parse(defineFlags.c_str());
+ targetOptions.AddFlag("AssemblerListingLocation", "$(IntDir)\\");
+ targetOptions.Parse(flags);
+ targetOptions.Parse(defineFlags);
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"));
// Add a definition for the configuration name.
- std::string configDefine = "CMAKE_INTDIR=\"";
- configDefine += configName;
- configDefine += "\"";
+ std::string configDefine = cmStrCat("CMAKE_INTDIR=\"", configName, '"');
targetOptions.AddDefine(configDefine);
// Add the export symbol definition for shared library objects.
- if (const char* exportMacro = target->GetExportMacro()) {
- targetOptions.AddDefine(exportMacro);
+ if (const std::string* exportMacro = target->GetExportMacro()) {
+ targetOptions.AddDefine(*exportMacro);
}
// The intermediate directory name consists of a directory for the
// target and a subdirectory for the configuration name.
- std::string intermediateDir = this->GetTargetDirectory(target);
- intermediateDir += "/";
- intermediateDir += configName;
+ std::string intermediateDir =
+ cmStrCat(this->GetTargetDirectory(target), '/', configName);
if (target->GetType() < cmStateEnums::UTILITY) {
std::string const& outDir =
@@ -784,8 +783,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
target->GetProperty("Fortran_MODULE_DIRECTORY");
std::string modDir;
if (target_mod_dir) {
- modDir = this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(),
- target_mod_dir);
+ modDir = this->MaybeConvertToRelativePath(
+ this->GetCurrentBinaryDirectory(), target_mod_dir);
} else {
modDir = ".";
}
@@ -793,26 +792,10 @@ 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.OutputFlagMap(fout, "\t\t\t\t");
- targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n", "CXX");
+ targetOptions.OutputAdditionalIncludeDirectories(
+ fout, 4, this->FortranProject ? "Fortran" : langForClCompile);
+ targetOptions.OutputFlagMap(fout, 4);
+ targetOptions.OutputPreprocessorDefinitions(fout, 4, langForClCompile);
fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n";
if (target->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
// Specify the compiler program database file if configured.
@@ -829,21 +812,12 @@ 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, 4, "ASM_MASM");
// Use same preprocessor definitions as VCCLCompilerTool.
- targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n",
- "ASM_MASM");
- masmOptions.OutputFlagMap(fout, "\t\t\t\t");
+ targetOptions.OutputPreprocessorDefinitions(fout, 4, "ASM_MASM");
+ masmOptions.OutputFlagMap(fout, 4);
/* clang-format off */
fout <<
"\t\t\t\tObjectFile=\"$(IntDir)\\\"\n"
@@ -859,27 +833,17 @@ 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, 4, "RC");
// add the -D flags to the RC tool
- fout << "\"";
- targetOptions.OutputPreprocessorDefinitions(fout, "\n\t\t\t\t", "", "RC");
- fout << "/>\n";
+ targetOptions.OutputPreprocessorDefinitions(fout, 4, "RC");
+ fout << "\t\t\t/>\n";
tool = "VCMIDLTool";
if (this->FortranProject) {
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, 4, "MIDL");
fout << "\t\t\t\tMkTypLibCompatible=\"false\"\n";
if (gg->GetPlatformName() == "x64") {
fout << "\t\t\t\tTargetEnvironment=\"3\"\n";
@@ -913,10 +877,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
target->GetManifests(manifest_srcs, configName);
if (!manifest_srcs.empty()) {
fout << "\n\t\t\t\tAdditionalManifestFiles=\"";
- for (std::vector<cmSourceFile const*>::const_iterator mi =
- manifest_srcs.begin();
- mi != manifest_srcs.end(); ++mi) {
- std::string m = (*mi)->GetFullPath();
+ for (cmSourceFile const* manifest : manifest_srcs) {
+ std::string m = manifest->GetFullPath();
fout << this->ConvertToXMLOutputPath(m.c_str()) << ";";
}
fout << "\"";
@@ -947,9 +909,8 @@ std::string cmLocalVisualStudio7Generator::GetBuildTypeLinkerFlags(
std::string extraLinkOptionsBuildTypeDef =
rootLinkerFlags + "_" + configTypeUpper;
- std::string extraLinkOptionsBuildType =
- this->Makefile->GetRequiredDefinition(
- extraLinkOptionsBuildTypeDef.c_str());
+ const std::string& extraLinkOptionsBuildType =
+ this->Makefile->GetRequiredDefinition(extraLinkOptionsBuildTypeDef);
return extraLinkOptionsBuildType;
}
@@ -964,21 +925,18 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
std::string extraLinkOptions;
if (target->GetType() == cmStateEnums::EXECUTABLE) {
extraLinkOptions =
- this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS") +
- std::string(" ") +
+ this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS") + " " +
GetBuildTypeLinkerFlags("CMAKE_EXE_LINKER_FLAGS", configName);
}
if (target->GetType() == cmStateEnums::SHARED_LIBRARY) {
extraLinkOptions =
this->Makefile->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS") +
- std::string(" ") +
- GetBuildTypeLinkerFlags("CMAKE_SHARED_LINKER_FLAGS", configName);
+ " " + GetBuildTypeLinkerFlags("CMAKE_SHARED_LINKER_FLAGS", configName);
}
if (target->GetType() == cmStateEnums::MODULE_LIBRARY) {
extraLinkOptions =
this->Makefile->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS") +
- std::string(" ") +
- GetBuildTypeLinkerFlags("CMAKE_MODULE_LINKER_FLAGS", configName);
+ " " + GetBuildTypeLinkerFlags("CMAKE_MODULE_LINKER_FLAGS", configName);
}
const char* targetLinkFlags = target->GetProperty("LINK_FLAGS");
@@ -987,38 +945,41 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
extraLinkOptions += targetLinkFlags;
}
std::string configTypeUpper = cmSystemTools::UpperCase(configName);
- std::string linkFlagsConfig = "LINK_FLAGS_";
- linkFlagsConfig += configTypeUpper;
+ std::string linkFlagsConfig = cmStrCat("LINK_FLAGS_", configTypeUpper);
targetLinkFlags = target->GetProperty(linkFlagsConfig.c_str());
if (targetLinkFlags) {
extraLinkOptions += " ";
extraLinkOptions += targetLinkFlags;
}
+
+ std::vector<std::string> opts;
+ target->GetLinkOptions(opts, configName,
+ target->GetLinkerLanguage(configName));
+ // LINK_OPTIONS are escaped.
+ this->AppendCompileOptions(extraLinkOptions, opts);
+
Options linkOptions(this, Options::Linker);
if (this->FortranProject) {
linkOptions.AddTable(cmLocalVisualStudio7GeneratorFortranLinkFlagTable);
}
linkOptions.AddTable(cmLocalVisualStudio7GeneratorLinkFlagTable);
- linkOptions.Parse(extraLinkOptions.c_str());
+ linkOptions.Parse(extraLinkOptions);
cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
target->GetModuleDefinitionInfo(configName);
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()) {
case cmStateEnums::UNKNOWN_LIBRARY:
break;
case cmStateEnums::OBJECT_LIBRARY: {
- std::string libpath = this->GetTargetDirectory(target);
- libpath += "/";
- libpath += configName;
- libpath += "/";
- libpath += target->GetName();
- libpath += ".lib";
+ std::string libpath =
+ cmStrCat(this->GetTargetDirectory(target), '/', configName, '/',
+ target->GetName(), ".lib");
const char* tool =
this->FortranProject ? "VFLibrarianTool" : "VCLibrarianTool";
fout << "\t\t\t<Tool\n"
@@ -1029,9 +990,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
}
case cmStateEnums::STATIC_LIBRARY: {
std::string targetNameFull = target->GetFullName(configName);
- std::string libpath = target->GetDirectory(configName);
- libpath += "/";
- libpath += targetNameFull;
+ std::string libpath =
+ cmStrCat(target->GetDirectory(configName), '/', targetNameFull);
const char* tool = "VCLibrarianTool";
if (this->FortranProject) {
tool = "VFLibrarianTool";
@@ -1048,7 +1008,9 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
}
}
std::string libflags;
- this->GetStaticLibraryFlags(libflags, configTypeUpper, target);
+ this->GetStaticLibraryFlags(libflags, configTypeUpper,
+ target->GetLinkerLanguage(configName),
+ target);
if (!libflags.empty()) {
fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\n";
}
@@ -1058,13 +1020,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
}
case cmStateEnums::SHARED_LIBRARY:
case cmStateEnums::MODULE_LIBRARY: {
- std::string targetName;
- std::string targetNameSO;
- std::string targetNameFull;
- std::string targetNameImport;
- std::string targetNamePDB;
- target->GetLibraryNames(targetName, targetNameSO, targetNameFull,
- targetNameImport, targetNamePDB, configName);
+ cmGeneratorTarget::Names targetNames =
+ target->GetLibraryNames(configName);
// Compute the link library and directory information.
cmComputeLinkInformation* pcli = target->GetLinkInformation(configName);
@@ -1076,9 +1033,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
// Compute the variable name to lookup standard libraries for this
// language.
- std::string standardLibsVar = "CMAKE_";
- standardLibsVar += linkLanguage;
- standardLibsVar += "_STANDARD_LIBRARIES";
+ std::string standardLibsVar =
+ cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LIBRARIES");
const char* tool = "VCLinkerTool";
if (this->FortranProject) {
tool = "VFLinkerTool";
@@ -1091,26 +1047,24 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
// Use the NOINHERIT macro to avoid getting VS project default
// libraries which may be set by the user to something bad.
fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
- << this->Makefile->GetSafeDefinition(standardLibsVar.c_str());
+ << this->Makefile->GetSafeDefinition(standardLibsVar);
if (this->FortranProject) {
this->Internal->OutputObjects(fout, target, configName, " ");
}
fout << " ";
this->Internal->OutputLibraries(fout, cli.GetItems());
fout << "\"\n";
- temp = target->GetDirectory(configName);
- temp += "/";
- temp += targetNameFull;
+ temp =
+ cmStrCat(target->GetDirectory(configName), '/', targetNames.Output);
fout << "\t\t\t\tOutputFile=\""
<< this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
this->WriteTargetVersionAttribute(fout, target);
- linkOptions.OutputFlagMap(fout, "\t\t\t\t");
+ linkOptions.OutputFlagMap(fout, 4);
fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
this->OutputLibraryDirectories(fout, cli.GetDirectories());
fout << "\"\n";
- temp = target->GetPDBDirectory(configName);
- temp += "/";
- temp += targetNamePDB;
+ temp =
+ cmStrCat(target->GetPDBDirectory(configName), '/', targetNames.PDB);
fout << "\t\t\t\tProgramDatabaseFile=\""
<< this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
if (targetOptions.IsDebug()) {
@@ -1123,17 +1077,14 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
fout << "\t\t\t\tSubSystem=\"8\"\n";
}
}
- std::string stackVar = "CMAKE_";
- stackVar += linkLanguage;
- stackVar += "_STACK_SIZE";
+ std::string stackVar = cmStrCat("CMAKE_", linkLanguage, "_STACK_SIZE");
const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str());
if (stackVal) {
fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\"\n";
}
- temp =
- target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact);
- temp += "/";
- temp += targetNameImport;
+ temp = cmStrCat(
+ target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact),
+ '/', targetNames.ImportLibrary);
fout << "\t\t\t\tImportLibrary=\""
<< this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"";
if (this->FortranProject) {
@@ -1142,12 +1093,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
fout << "/>\n";
} break;
case cmStateEnums::EXECUTABLE: {
- std::string targetName;
- std::string targetNameFull;
- std::string targetNameImport;
- std::string targetNamePDB;
- target->GetExecutableNames(targetName, targetNameFull, targetNameImport,
- targetNamePDB, configName);
+ cmGeneratorTarget::Names targetNames =
+ target->GetExecutableNames(configName);
// Compute the link library and directory information.
cmComputeLinkInformation* pcli = target->GetLinkInformation(configName);
@@ -1161,9 +1108,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
// Compute the variable name to lookup standard libraries for this
// language.
- std::string standardLibsVar = "CMAKE_";
- standardLibsVar += linkLanguage;
- standardLibsVar += "_STANDARD_LIBRARIES";
+ std::string standardLibsVar =
+ cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LIBRARIES");
const char* tool = "VCLinkerTool";
if (this->FortranProject) {
tool = "VFLinkerTool";
@@ -1176,27 +1122,26 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
// Use the NOINHERIT macro to avoid getting VS project default
// libraries which may be set by the user to something bad.
fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
- << this->Makefile->GetSafeDefinition(standardLibsVar.c_str());
+ << this->Makefile->GetSafeDefinition(standardLibsVar);
if (this->FortranProject) {
this->Internal->OutputObjects(fout, target, configName, " ");
}
fout << " ";
this->Internal->OutputLibraries(fout, cli.GetItems());
fout << "\"\n";
- temp = target->GetDirectory(configName);
- temp += "/";
- temp += targetNameFull;
+ temp =
+ cmStrCat(target->GetDirectory(configName), '/', targetNames.Output);
fout << "\t\t\t\tOutputFile=\""
<< this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
this->WriteTargetVersionAttribute(fout, target);
- linkOptions.OutputFlagMap(fout, "\t\t\t\t");
+ linkOptions.OutputFlagMap(fout, 4);
fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
this->OutputLibraryDirectories(fout, cli.GetDirectories());
fout << "\"\n";
std::string path = this->ConvertToXMLOutputPathSingle(
target->GetPDBDirectory(configName).c_str());
- fout << "\t\t\t\tProgramDatabaseFile=\"" << path << "/" << targetNamePDB
- << "\"\n";
+ fout << "\t\t\t\tProgramDatabaseFile=\"" << path << "/"
+ << targetNames.PDB << "\"\n";
if (targetOptions.IsDebug()) {
fout << "\t\t\t\tGenerateDebugInformation=\"true\"\n";
}
@@ -1221,17 +1166,14 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
fout << "\t\t\t\tSubSystem=\"" << (isWin32Executable ? "2" : "1")
<< "\"\n";
}
- std::string stackVar = "CMAKE_";
- stackVar += linkLanguage;
- stackVar += "_STACK_SIZE";
+ std::string stackVar = cmStrCat("CMAKE_", linkLanguage, "_STACK_SIZE");
const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str());
if (stackVal) {
fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\"";
}
- temp =
- target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact);
- temp += "/";
- temp += targetNameImport;
+ temp = cmStrCat(
+ target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact),
+ '/', targetNames.ImportLibrary);
fout << "\t\t\t\tImportLibrary=\""
<< this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"/>\n";
break;
@@ -1243,30 +1185,56 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
}
}
+static std::string cmLocalVisualStudio7GeneratorEscapeForXML(
+ const std::string& s)
+{
+ std::string ret = s;
+ cmSystemTools::ReplaceString(ret, "&", "&amp;");
+ cmSystemTools::ReplaceString(ret, "\"", "&quot;");
+ cmSystemTools::ReplaceString(ret, "<", "&lt;");
+ cmSystemTools::ReplaceString(ret, ">", "&gt;");
+ cmSystemTools::ReplaceString(ret, "\n", "&#x0D;&#x0A;");
+ return ret;
+}
+
+static std::string GetEscapedPropertyIfValueNotNULL(const char* propertyValue)
+{
+ return propertyValue == nullptr
+ ? std::string()
+ : cmLocalVisualStudio7GeneratorEscapeForXML(propertyValue);
+}
+
void cmLocalVisualStudio7Generator::OutputDeploymentDebuggerTool(
std::ostream& fout, std::string const& config, cmGeneratorTarget* target)
{
if (this->WindowsCEProject) {
- if (const char* dir = target->GetProperty("DEPLOYMENT_REMOTE_DIRECTORY")) {
- /* clang-format off */
- fout <<
- "\t\t\t<DeploymentTool\n"
- "\t\t\t\tForceDirty=\"-1\"\n"
- "\t\t\t\tRemoteDirectory=\"" << this->EscapeForXML(dir) << "\"\n"
- "\t\t\t\tRegisterOutput=\"0\"\n"
- "\t\t\t\tAdditionalFiles=\"\"/>\n"
- ;
- /* clang-format on */
+ const char* dir = target->GetProperty("DEPLOYMENT_REMOTE_DIRECTORY");
+ const char* additionalFiles =
+ target->GetProperty("DEPLOYMENT_ADDITIONAL_FILES");
+
+ if (dir == nullptr && additionalFiles == nullptr) {
+ return;
+ }
+
+ fout << "\t\t\t<DeploymentTool\n"
+ "\t\t\t\tForceDirty=\"-1\"\n"
+ "\t\t\t\tRemoteDirectory=\""
+ << GetEscapedPropertyIfValueNotNULL(dir)
+ << "\"\n"
+ "\t\t\t\tRegisterOutput=\"0\"\n"
+ "\t\t\t\tAdditionalFiles=\""
+ << GetEscapedPropertyIfValueNotNULL(additionalFiles) << "\"/>\n";
+
+ if (dir != nullptr) {
std::string const exe =
dir + std::string("\\") + target->GetFullName(config);
- /* clang-format off */
- fout <<
- "\t\t\t<DebuggerTool\n"
- "\t\t\t\tRemoteExecutable=\"" << this->EscapeForXML(exe) << "\"\n"
- "\t\t\t\tArguments=\"\"\n"
- "\t\t\t/>\n"
- ;
- /* clang-format on */
+
+ fout << "\t\t\t<DebuggerTool\n"
+ "\t\t\t\tRemoteExecutable=\""
+ << this->EscapeForXML(exe)
+ << "\"\n"
+ "\t\t\t\tArguments=\"\"\n"
+ "\t\t\t/>\n";
}
}
}
@@ -1285,14 +1253,14 @@ void cmLocalVisualStudio7GeneratorInternals::OutputLibraries(
{
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
std::string currentBinDir = lg->GetCurrentBinaryDirectory();
- for (ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l) {
- if (l->IsPath) {
+ for (auto const& lib : libs) {
+ if (lib.IsPath) {
std::string rel =
- lg->ConvertToRelativePath(currentBinDir, l->Value.c_str());
+ lg->MaybeConvertToRelativePath(currentBinDir, lib.Value.c_str());
fout << lg->ConvertToXMLOutputPath(rel.c_str()) << " ";
- } else if (!l->Target ||
- l->Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
- fout << l->Value << " ";
+ } else if (!lib.Target ||
+ lib.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ fout << lib.Value << " ";
}
}
}
@@ -1310,11 +1278,10 @@ void cmLocalVisualStudio7GeneratorInternals::OutputObjects(
gt->GetExternalObjects(objs, configName);
const char* sep = isep ? isep : "";
- for (std::vector<cmSourceFile const*>::const_iterator i = objs.begin();
- i != objs.end(); ++i) {
- if (!(*i)->GetObjectLibrary().empty()) {
- std::string const& objFile = (*i)->GetFullPath();
- std::string rel = lg->ConvertToRelativePath(currentBinDir, objFile);
+ for (cmSourceFile const* obj : objs) {
+ if (!obj->GetObjectLibrary().empty()) {
+ std::string const& objFile = obj->GetFullPath();
+ std::string rel = lg->MaybeConvertToRelativePath(currentBinDir, objFile);
fout << sep << lg->ConvertToXMLOutputPath(rel.c_str());
sep = " ";
}
@@ -1326,11 +1293,9 @@ void cmLocalVisualStudio7Generator::OutputLibraryDirectories(
{
const char* comma = "";
std::string currentBinDir = this->GetCurrentBinaryDirectory();
- for (std::vector<std::string>::const_iterator d = dirs.begin();
- d != dirs.end(); ++d) {
+ for (std::string dir : dirs) {
// Remove any trailing slash and skip empty paths.
- std::string dir = *d;
- if (dir[dir.size() - 1] == '/') {
+ if (dir.back() == '/') {
dir = dir.substr(0, dir.size() - 1);
}
if (dir.empty()) {
@@ -1340,7 +1305,7 @@ void cmLocalVisualStudio7Generator::OutputLibraryDirectories(
// Switch to a relative path specification if it is shorter.
if (cmSystemTools::FileIsFullPath(dir.c_str())) {
std::string rel =
- this->ConvertToRelativePath(currentBinDir, dir.c_str());
+ this->MaybeConvertToRelativePath(currentBinDir, dir.c_str());
if (rel.size() < dir.size()) {
dir = rel;
}
@@ -1366,13 +1331,37 @@ 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);
+ }
+ bool haveCMakeLists = false;
+ for (cmGeneratorTarget::AllConfigSource& si : sources.Sources) {
+ if (si.Source == sf) {
+ haveCMakeLists = true;
+ // Replace the explicit source reference with our generated one.
+ si = acs;
+ break;
+ }
+ }
+ if (!haveCMakeLists) {
+ 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
@@ -1384,7 +1373,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);
}
@@ -1398,7 +1387,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";
@@ -1414,6 +1403,7 @@ struct cmLVS7GFileConfig
std::string CompileDefs;
std::string CompileDefsConfig;
std::string AdditionalDeps;
+ std::string IncludeDirs;
bool ExcludedFromBuild;
};
@@ -1440,21 +1430,54 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
// Compute per-source, per-config information.
size_t ci = 0;
- for (std::vector<std::string>::const_iterator i = configs.begin();
- i != configs.end(); ++i, ++ci) {
- std::string configUpper = cmSystemTools::UpperCase(*i);
+ for (std::string const& config : configs) {
+ std::string configUpper = cmSystemTools::UpperCase(config);
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, config, gt, lang);
+
bool needfc = false;
if (!objectName.empty()) {
fc.ObjectName = objectName;
needfc = true;
}
- if (const char* cflags = sf.GetProperty("COMPILE_FLAGS")) {
- cmGeneratorExpression ge;
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(cflags);
- fc.CompileFlags = cge->Evaluate(lg, *i);
+ 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;
}
+ // Add precompile headers compile options.
+ const std::string pchSource = gt->GetPchSource(config, lang);
+ if (!pchSource.empty() && !sf.GetProperty("SKIP_PRECOMPILE_HEADERS")) {
+ std::string pchOptions;
+ if (sf.GetFullPath() == pchSource) {
+ pchOptions = gt->GetPchCreateCompileOptions(config, lang);
+ } else {
+ pchOptions = gt->GetPchUseCompileOptions(config, lang);
+ }
+
+ lg->AppendCompileOptions(
+ fc.CompileFlags,
+ genexInterpreter.Evaluate(pchOptions, COMPILE_OPTIONS));
+ needfc = true;
+ }
+
if (lg->FortranProject) {
switch (cmOutputConverter::GetFortranFormat(
sf.GetProperty("Fortran_FORMAT"))) {
@@ -1470,21 +1493,27 @@ 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 = cmStrCat("COMPILE_DEFINITIONS_", configUpper);
+ if (const char* ccdefs = sf.GetProperty(defPropName)) {
+ fc.CompileDefsConfig =
+ genexInterpreter.Evaluate(ccdefs, COMPILE_DEFINITIONS);
needfc = true;
}
- std::string defPropName = "COMPILE_DEFINITIONS_";
- defPropName += configUpper;
- if (const char* ccdefs = sf.GetProperty(defPropName.c_str())) {
- fc.CompileDefsConfig = ccdefs;
+
+ const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
+ if (const char* cincs = sf.GetProperty(INCLUDE_DIRECTORIES)) {
+ fc.IncludeDirs = genexInterpreter.Evaluate(cincs, INCLUDE_DIRECTORIES);
needfc = true;
}
// Check for extra object-file dependencies.
if (const char* deps = sf.GetProperty("OBJECT_DEPENDS")) {
- std::vector<std::string> depends;
- cmSystemTools::ExpandListArgument(deps, depends);
+ std::vector<std::string> depends = cmExpandedList(deps);
const char* sep = "";
for (std::vector<std::string>::iterator j = depends.begin();
j != depends.end(); ++j) {
@@ -1495,21 +1524,14 @@ 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;
- }
+ const std::string& linkLanguage = gt->GetLinkerLanguage(config.c_str());
// If HEADER_FILE_ONLY is set, we must suppress this generation in
// the project file
fc.ExcludedFromBuild = sf.GetPropertyAsBool("HEADER_FILE_ONLY") ||
- std::find(acs.Configs.begin(), acs.Configs.end(), ci) ==
- acs.Configs.end();
+ !cmContains(acs.Configs, ci) ||
+ (gt->GetPropertyAsBool("UNITY_BUILD") &&
+ sf.GetProperty("UNITY_SOURCE_FILE") &&
+ !sf.GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION"));
if (fc.ExcludedFromBuild) {
needfc = true;
}
@@ -1529,8 +1551,9 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
}
if (needfc) {
- this->FileConfigMap[*i] = fc;
+ this->FileConfigMap[config] = fc;
}
+ ++ci;
}
}
@@ -1552,20 +1575,16 @@ std::string cmLocalVisualStudio7Generator::ComputeLongestObjectDirectory(
// Compute the maximum length full path to the intermediate
// files directory for any configuration. This is used to construct
// object file names that do not produce paths that are too long.
- std::string dir_max;
- dir_max += this->GetCurrentBinaryDirectory();
- dir_max += "/";
- dir_max += this->GetTargetDirectory(target);
- dir_max += "/";
- dir_max += config_max;
- dir_max += "/";
+ std::string dir_max =
+ cmStrCat(this->GetCurrentBinaryDirectory(), '/',
+ this->GetTargetDirectory(target), '/', config_max, '/');
return dir_max;
}
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);
@@ -1577,7 +1596,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;
}
}
@@ -1588,28 +1607,24 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
}
// If the group has a name, write the header.
- std::string name = sg->GetName();
- if (name != "") {
+ 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();
- sf != sourceFiles.end(); ++sf) {
- std::string source = (*sf)->GetFullPath();
+ for (const cmSourceFile* sf : sourceFiles) {
+ std::string source = sf->GetFullPath();
if (source != libName || target->GetType() == cmStateEnums::UTILITY ||
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);
@@ -1618,16 +1633,16 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
// Tell MS-Dev what the source is. If the compiler knows how to
// build it, then it will.
fout << "\t\t\t\tRelativePath=\"" << d << "\">\n";
- if (cmCustomCommand const* command = (*sf)->GetCustomCommand()) {
+ if (cmCustomCommand const* command = sf->GetCustomCommand()) {
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";
}
- std::string const& lang = (*sf)->GetLanguage();
- std::string ext = (*sf)->GetExtension();
+ std::string const& lang = sf->GetLanguage();
+ std::string ext = sf->GetExtension();
ext = cmSystemTools::LowerCase(ext);
if (ext == "idl") {
aCompilerTool = "VCMIDLTool";
@@ -1655,12 +1670,10 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
if (acs.Kind == cmGeneratorTarget::SourceKindExternalObject) {
aCompilerTool = "VCCustomBuildTool";
}
- for (std::map<std::string, cmLVS7GFileConfig>::const_iterator fci =
- fcinfo.FileConfigMap.begin();
- fci != fcinfo.FileConfigMap.end(); ++fci) {
- cmLVS7GFileConfig const& fc = fci->second;
+ for (auto const& fci : fcinfo.FileConfigMap) {
+ cmLVS7GFileConfig const& fc = fci.second;
fout << "\t\t\t\t<FileConfiguration\n"
- << "\t\t\t\t\tName=\"" << fci->first << "|"
+ << "\t\t\t\t\tName=\"" << fci.first << "|"
<< gg->GetPlatformName() << "\"";
if (fc.ExcludedFromBuild) {
fout << " ExcludedFromBuild=\"true\"";
@@ -1669,7 +1682,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;
@@ -1678,12 +1691,18 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
table = cmLocalVisualStudio7GeneratorFortranFlagTable;
}
Options fileOptions(this, tool, table, gg->ExtraFlagTable);
- fileOptions.Parse(fc.CompileFlags.c_str());
- fileOptions.AddDefines(fc.CompileDefs.c_str());
- fileOptions.AddDefines(fc.CompileDefsConfig.c_str());
- fileOptions.OutputFlagMap(fout, "\t\t\t\t\t");
- fileOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t\t", "\n",
- ppLang);
+ fileOptions.Parse(fc.CompileFlags);
+ fileOptions.AddDefines(fc.CompileDefs);
+ fileOptions.AddDefines(fc.CompileDefsConfig);
+ // validate source level include directories
+ std::vector<std::string> includes;
+ this->AppendIncludeDirectories(includes, fc.IncludeDirs, *sf);
+ fileOptions.AddIncludes(includes);
+ fileOptions.OutputFlagMap(fout, 5);
+ fileOptions.OutputAdditionalIncludeDirectories(
+ fout, 5,
+ ppLang == "CXX" && this->FortranProject ? "Fortran" : ppLang);
+ fileOptions.OutputPreprocessorDefinitions(fout, 5, ppLang);
}
if (!fc.AdditionalDeps.empty()) {
fout << "\t\t\t\t\tAdditionalDependencies=\"" << fc.AdditionalDeps
@@ -1707,7 +1726,7 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
}
// If the group has a name, write the footer.
- if (name != "") {
+ if (!name.empty()) {
this->WriteVCProjEndGroup(fout);
}
@@ -1730,12 +1749,11 @@ void cmLocalVisualStudio7Generator::WriteCustomRule(
if (this->FortranProject) {
customTool = "VFCustomBuildTool";
}
- for (std::vector<std::string>::const_iterator i = configs.begin();
- i != configs.end(); ++i) {
- cmCustomCommandGenerator ccg(command, *i, this);
- cmLVS7GFileConfig const& fc = fcinfo.FileConfigMap[*i];
+ for (std::string const& config : configs) {
+ cmCustomCommandGenerator ccg(command, config, this);
+ cmLVS7GFileConfig const& fc = fcinfo.FileConfigMap[config];
fout << "\t\t\t\t<FileConfiguration\n";
- fout << "\t\t\t\t\tName=\"" << *i << "|" << gg->GetPlatformName()
+ fout << "\t\t\t\t\tName=\"" << config << "|" << gg->GetPlatformName()
<< "\">\n";
if (!fc.CompileFlags.empty()) {
fout << "\t\t\t\t\t<Tool\n"
@@ -1747,7 +1765,7 @@ void cmLocalVisualStudio7Generator::WriteCustomRule(
std::string comment = this->ConstructComment(ccg);
std::string script = this->ConstructScript(ccg);
if (this->FortranProject) {
- cmSystemTools::ReplaceString(script, "$(Configuration)", i->c_str());
+ cmSystemTools::ReplaceString(script, "$(Configuration)", config.c_str());
}
/* clang-format off */
fout << "\t\t\t\t\t<Tool\n"
@@ -1768,12 +1786,10 @@ void cmLocalVisualStudio7Generator::WriteCustomRule(
fout << this->ConvertToXMLOutputPath(source);
} else {
// Write out the dependencies for the rule.
- for (std::vector<std::string>::const_iterator d =
- ccg.GetDepends().begin();
- d != ccg.GetDepends().end(); ++d) {
+ for (std::string const& d : ccg.GetDepends()) {
// Get the real name of the dependency in case it is a CMake target.
std::string dep;
- if (this->GetRealDependency(d->c_str(), i->c_str(), dep)) {
+ if (this->GetRealDependency(d.c_str(), config.c_str(), dep)) {
fout << this->ConvertToXMLOutputPath(dep.c_str()) << ";";
}
}
@@ -1785,10 +1801,8 @@ void cmLocalVisualStudio7Generator::WriteCustomRule(
} else {
// Write a rule for the output generated by this command.
const char* sep = "";
- for (std::vector<std::string>::const_iterator o =
- ccg.GetOutputs().begin();
- o != ccg.GetOutputs().end(); ++o) {
- fout << sep << this->ConvertToXMLOutputPathSingle(o->c_str());
+ for (std::string const& output : ccg.GetOutputs()) {
+ fout << sep << this->ConvertToXMLOutputPathSingle(output.c_str());
sep = ";";
}
}
@@ -1847,7 +1861,7 @@ void cmLocalVisualStudio7Generator::OutputTargetRules(
if (!addedPrelink) {
event.Write(target->GetPreLinkCommands());
}
- CM_AUTO_PTR<cmCustomCommand> pcc(
+ std::unique_ptr<cmCustomCommand> pcc(
this->MaybeCreateImplibDir(target, configName, this->FortranProject));
if (pcc.get()) {
event.Write(*pcc);
@@ -1999,16 +2013,14 @@ void cmLocalVisualStudio7Generator::WriteVCProjFooter(
{
fout << "\t<Globals>\n";
- std::vector<std::string> const& props = target->GetPropertyKeys();
- for (std::vector<std::string>::const_iterator i = props.begin();
- i != props.end(); ++i) {
- if (i->find("VS_GLOBAL_") == 0) {
- std::string name = i->substr(10);
- if (name != "") {
+ for (std::string const& key : target->GetPropertyKeys()) {
+ if (key.find("VS_GLOBAL_") == 0) {
+ std::string name = key.substr(10);
+ if (!name.empty()) {
/* clang-format off */
fout << "\t\t<Global\n"
<< "\t\t\tName=\"" << name << "\"\n"
- << "\t\t\tValue=\"" << target->GetProperty(*i) << "\"\n"
+ << "\t\t\tValue=\"" << target->GetProperty(key) << "\"\n"
<< "\t\t/>\n";
/* clang-format on */
}
@@ -2019,17 +2031,6 @@ void cmLocalVisualStudio7Generator::WriteVCProjFooter(
<< "</VisualStudioProject>\n";
}
-std::string cmLocalVisualStudio7GeneratorEscapeForXML(const std::string& s)
-{
- std::string ret = s;
- cmSystemTools::ReplaceString(ret, "&", "&amp;");
- cmSystemTools::ReplaceString(ret, "\"", "&quot;");
- cmSystemTools::ReplaceString(ret, "<", "&lt;");
- cmSystemTools::ReplaceString(ret, ">", "&gt;");
- cmSystemTools::ReplaceString(ret, "\n", "&#x0D;&#x0A;");
- return ret;
-}
-
std::string cmLocalVisualStudio7Generator::EscapeForXML(const std::string& s)
{
return cmLocalVisualStudio7GeneratorEscapeForXML(s);
@@ -2059,6 +2060,19 @@ std::string cmLocalVisualStudio7Generator::ConvertToXMLOutputPathSingle(
return ret;
}
+void cmVS7GeneratorOptions::OutputFlag(std::ostream& fout, int indent,
+ const char* flag,
+ const std::string& content)
+{
+ fout.fill('\t');
+ fout.width(indent);
+ // write an empty string to get the fill level indent to print
+ fout << "";
+ fout << flag << "=\"";
+ fout << cmLocalVisualStudio7GeneratorEscapeForXML(content);
+ fout << "\"\n";
+}
+
// This class is used to parse an existing vs 7 project
// and extract the GUID
class cmVS7XMLParser : public cmXMLParser
@@ -2077,9 +2091,12 @@ public:
if (strcmp(atts[i], "ProjectGUID") == 0) {
if (atts[i + 1]) {
this->GUID = atts[i + 1];
- this->GUID = this->GUID.substr(1, this->GUID.size() - 2);
+ if (this->GUID[0] == '{') {
+ // remove surrounding curly brackets
+ this->GUID = this->GUID.substr(1, this->GUID.size() - 2);
+ }
} else {
- this->GUID = "";
+ this->GUID.clear();
}
return;
}
@@ -2110,8 +2127,7 @@ void cmLocalVisualStudio7Generator::ReadAndStoreExternalGUID(
if (parser.GUID.empty()) {
return;
}
- std::string guidStoreName = name;
- guidStoreName += "_GUID_CMAKE";
+ std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE");
// save the GUID in the cache
this->GlobalGenerator->GetCMakeInstance()->AddCacheEntry(
guidStoreName.c_str(), parser.GUID.c_str(), "Stored GUID",
@@ -2121,9 +2137,7 @@ void cmLocalVisualStudio7Generator::ReadAndStoreExternalGUID(
std::string cmLocalVisualStudio7Generator::GetTargetDirectory(
cmGeneratorTarget const* target) const
{
- std::string dir;
- dir += target->GetName();
- dir += ".dir";
+ std::string dir = cmStrCat(target->GetName(), ".dir");
return dir;
}
diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h
index 89a3ee353..671783fa5 100644
--- a/Source/cmLocalVisualStudio7Generator.h
+++ b/Source/cmLocalVisualStudio7Generator.h
@@ -3,7 +3,7 @@
#ifndef cmLocalVisualStudio7Generator_h
#define cmLocalVisualStudio7Generator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
@@ -21,6 +21,19 @@ class cmMakefile;
class cmSourceFile;
class cmSourceGroup;
+class cmVS7GeneratorOptions : public cmVisualStudioGeneratorOptions
+{
+public:
+ cmVS7GeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool,
+ cmVS7FlagTable const* table = nullptr,
+ cmVS7FlagTable const* extraTable = nullptr)
+ : cmVisualStudioGeneratorOptions(lg, tool, table, extraTable)
+ {
+ }
+ void OutputFlag(std::ostream& fout, int indent, const char* tag,
+ const std::string& content) override;
+};
+
/** \class cmLocalVisualStudio7Generator
* \brief Write Visual Studio .NET project files.
*
@@ -30,17 +43,17 @@ class cmSourceGroup;
class cmLocalVisualStudio7Generator : public cmLocalVisualStudioGenerator
{
public:
- ///! Set cache only and recurse to false by default.
+ //! Set cache only and recurse to false by default.
cmLocalVisualStudio7Generator(cmGlobalGenerator* gg, cmMakefile* mf);
virtual ~cmLocalVisualStudio7Generator();
- virtual void AddHelperCommands();
+ void AddHelperCommands() override;
/**
* Generate the makefile for this directory.
*/
- virtual void Generate();
+ void Generate() override;
enum BuildType
{
@@ -56,23 +69,22 @@ 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);
private:
- typedef cmVisualStudioGeneratorOptions Options;
- typedef cmLocalVisualStudio7GeneratorFCInfo FCInfo;
+ using Options = cmVS7GeneratorOptions;
+ using FCInfo = cmLocalVisualStudio7GeneratorFCInfo;
std::string GetBuildTypeLinkerFlags(std::string rootLinkerFlags,
const std::string& configName);
void FixGlobalTargets();
@@ -117,10 +129,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 41025af6c..336e3a5a1 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -2,13 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalVisualStudioGenerator.h"
+#include "windows.h"
+
+#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmSystemTools.h"
-#include "windows.h"
cmLocalVisualStudioGenerator::cmLocalVisualStudioGenerator(
cmGlobalGenerator* gg, cmMakefile* mf)
@@ -39,10 +41,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 +57,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,16 +72,16 @@ void cmLocalVisualStudioGenerator::ComputeObjectFilenames(
objectName = this->GetObjectFileNameWithoutTarget(
*sf, dir_max, &keptSourceExtension, custom_ext);
}
- si->second = objectName;
+ si.second = objectName;
}
}
-CM_AUTO_PTR<cmCustomCommand>
+std::unique_ptr<cmCustomCommand>
cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmGeneratorTarget* target,
const std::string& config,
bool isFortran)
{
- CM_AUTO_PTR<cmCustomCommand> pcc;
+ std::unique_ptr<cmCustomCommand> pcc;
// If an executable exports symbols then VS wants to create an
// import library but forgets to create the output directory.
@@ -101,16 +99,11 @@ cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmGeneratorTarget* target,
}
// Add a pre-build event to create the directory.
- cmCustomCommandLine command;
- command.push_back(cmSystemTools::GetCMakeCommand());
- command.push_back("-E");
- command.push_back("make_directory");
- command.push_back(impDir);
std::vector<std::string> no_output;
std::vector<std::string> no_byproducts;
std::vector<std::string> no_depends;
- cmCustomCommandLines commands;
- commands.push_back(command);
+ cmCustomCommandLines commands = cmMakeSingleCommandLine(
+ { cmSystemTools::GetCMakeCommand(), "-E", "make_directory", impDir });
pcc.reset(new cmCustomCommand(0, no_output, no_byproducts, no_depends,
commands, 0, 0));
pcc->SetEscapeOldStyle(false);
@@ -135,7 +128,7 @@ std::string cmLocalVisualStudioGenerator::ConstructScript(
std::string workingDirectory = ccg.GetWorkingDirectory();
// Avoid leading or trailing newlines.
- std::string newline = "";
+ std::string newline;
// Line to check for error between commands.
std::string check_error = newline_text;
@@ -191,13 +184,17 @@ std::string cmLocalVisualStudioGenerator::ConstructScript(
// Write each command on a single line.
for (unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c) {
+ // Add this command line.
+ std::string cmd = ccg.GetCommand(c);
+
+ if (cmd.empty()) {
+ continue;
+ }
+
// Start a new line.
script += newline;
newline = newline_text;
- // Add this command line.
- std::string cmd = ccg.GetCommand(c);
-
// Use "call " before any invocations of .bat or .cmd files
// invoked as custom commands.
//
@@ -210,9 +207,10 @@ std::string cmLocalVisualStudioGenerator::ConstructScript(
}
if (workingDirectory.empty()) {
- script += this->ConvertToOutputFormat(
- this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), cmd),
- cmOutputConverter::SHELL);
+ script +=
+ this->ConvertToOutputFormat(this->MaybeConvertToRelativePath(
+ this->GetCurrentBinaryDirectory(), cmd),
+ cmOutputConverter::SHELL);
} else {
script += this->ConvertToOutputFormat(cmd.c_str(), SHELL);
}
diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h
index 85fb8a511..585eb3c33 100644
--- a/Source/cmLocalVisualStudioGenerator.h
+++ b/Source/cmLocalVisualStudioGenerator.h
@@ -3,7 +3,7 @@
#ifndef cmLocalVisualStudioGenerator_h
#define cmLocalVisualStudioGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
#include <memory>
@@ -11,7 +11,6 @@
#include "cmGlobalVisualStudioGenerator.h"
#include "cmLocalGenerator.h"
-#include "cm_auto_ptr.hxx"
class cmCustomCommand;
class cmCustomCommandGenerator;
@@ -45,20 +44,17 @@ 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;
virtual bool CustomCommandUseLocal() const { return false; }
/** Construct a custom command to make exe import lib dir. */
- CM_AUTO_PTR<cmCustomCommand> MaybeCreateImplibDir(cmGeneratorTarget* target,
- const std::string& config,
- bool isFortran);
+ std::unique_ptr<cmCustomCommand> MaybeCreateImplibDir(
+ cmGeneratorTarget* target, const std::string& config, bool isFortran);
};
#endif
diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx
index 739ef4367..5a06d4a53 100644
--- a/Source/cmLocalXCodeGenerator.cxx
+++ b/Source/cmLocalXCodeGenerator.cxx
@@ -19,9 +19,7 @@ cmLocalXCodeGenerator::cmLocalXCodeGenerator(cmGlobalGenerator* gg,
this->EmitUniversalBinaryFlags = false;
}
-cmLocalXCodeGenerator::~cmLocalXCodeGenerator()
-{
-}
+cmLocalXCodeGenerator::~cmLocalXCodeGenerator() = default;
std::string cmLocalXCodeGenerator::GetTargetDirectory(
cmGeneratorTarget const*) const
@@ -31,10 +29,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,10 +40,8 @@ void cmLocalXCodeGenerator::Generate()
{
cmLocalGenerator::Generate();
- std::vector<cmGeneratorTarget*> targets = this->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator iter = targets.begin();
- iter != targets.end(); ++iter) {
- (*iter)->HasMacOSXRpathInstallNameDir("");
+ for (auto target : this->GetGeneratorTargets()) {
+ target->HasMacOSXRpathInstallNameDir("");
}
}
@@ -53,10 +49,8 @@ void cmLocalXCodeGenerator::GenerateInstallRules()
{
cmLocalGenerator::GenerateInstallRules();
- std::vector<cmGeneratorTarget*> targets = this->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator iter = targets.begin();
- iter != targets.end(); ++iter) {
- (*iter)->HasMacOSXRpathInstallNameDir("");
+ for (auto target : this->GetGeneratorTargets()) {
+ target->HasMacOSXRpathInstallNameDir("");
}
}
@@ -69,19 +63,16 @@ void cmLocalXCodeGenerator::ComputeObjectFilenames(
// to avoid exact duplicate file names. Note that Mac file names are not
// typically case sensitive, hence the LowerCase.
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;
- std::string objectName =
- cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
- objectName += ".o";
+ for (auto& si : mapping) {
+ cmSourceFile const* sf = si.first;
+ std::string objectName = cmStrCat(
+ cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()), ".o");
std::string objectNameLower = cmSystemTools::LowerCase(objectName);
counts[objectNameLower] += 1;
if (2 == counts[objectNameLower]) {
// TODO: emit warning about duplicate name?
}
- si->second = objectName;
+ si.second = objectName;
}
}
diff --git a/Source/cmLocalXCodeGenerator.h b/Source/cmLocalXCodeGenerator.h
index 4ca02a9d0..42de20b47 100644
--- a/Source/cmLocalXCodeGenerator.h
+++ b/Source/cmLocalXCodeGenerator.h
@@ -24,19 +24,19 @@ class cmSourceFile;
class cmLocalXCodeGenerator : public cmLocalGenerator
{
public:
- ///! Set cache only and recurse to false by default.
+ //! Set cache only and recurse to false by default.
cmLocalXCodeGenerator(cmGlobalGenerator* gg, cmMakefile* mf);
- virtual ~cmLocalXCodeGenerator();
- virtual std::string GetTargetDirectory(
- cmGeneratorTarget const* target) const;
- virtual void AppendFlagEscape(std::string& flags,
- const std::string& rawFlag);
- virtual void Generate();
+ ~cmLocalXCodeGenerator() override;
+ std::string GetTargetDirectory(
+ cmGeneratorTarget const* target) const override;
+ void AppendFlagEscape(std::string& flags,
+ const std::string& rawFlag) const override;
+ void Generate() override;
virtual void GenerateInstallRules();
- virtual void ComputeObjectFilenames(
+ void ComputeObjectFilenames(
std::map<cmSourceFile const*, std::string>& mapping,
- cmGeneratorTarget const* gt = 0);
+ cmGeneratorTarget const* gt = nullptr) override;
private:
};
diff --git a/Source/cmLocale.h b/Source/cmLocale.h
index 9f90a3a99..c44a42db7 100644
--- a/Source/cmLocale.h
+++ b/Source/cmLocale.h
@@ -3,23 +3,25 @@
#ifndef cmLocale_h
#define cmLocale_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include <locale.h>
+#include <clocale>
#include <string>
class cmLocaleRAII
{
- CM_DISABLE_COPY(cmLocaleRAII)
-
public:
cmLocaleRAII()
- : OldLocale(setlocale(LC_CTYPE, CM_NULLPTR))
+ : OldLocale(setlocale(LC_CTYPE, nullptr))
{
setlocale(LC_CTYPE, "");
}
+
~cmLocaleRAII() { setlocale(LC_CTYPE, this->OldLocale.c_str()); }
+ cmLocaleRAII(cmLocaleRAII const&) = delete;
+ cmLocaleRAII& operator=(cmLocaleRAII const&) = delete;
+
private:
std::string OldLocale;
};
diff --git a/Source/cmMSVC60LinkLineComputer.cxx b/Source/cmMSVC60LinkLineComputer.cxx
index 5298d1a79..74c94351c 100644
--- a/Source/cmMSVC60LinkLineComputer.cxx
+++ b/Source/cmMSVC60LinkLineComputer.cxx
@@ -4,7 +4,7 @@
#include "cmMSVC60LinkLineComputer.h"
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include "cmSystemTools.h"
+# include "cmSystemTools.h"
#endif
class cmOutputConverter;
diff --git a/Source/cmMSVC60LinkLineComputer.h b/Source/cmMSVC60LinkLineComputer.h
index f2892d53f..d767914b9 100644
--- a/Source/cmMSVC60LinkLineComputer.h
+++ b/Source/cmMSVC60LinkLineComputer.h
@@ -4,7 +4,7 @@
#ifndef cmMSVC60LinkLineComputer_h
#define cmMSVC60LinkLineComputer_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
@@ -15,14 +15,15 @@ class cmStateDirectory;
class cmMSVC60LinkLineComputer : public cmLinkLineComputer
{
- CM_DISABLE_COPY(cmMSVC60LinkLineComputer)
-
public:
cmMSVC60LinkLineComputer(cmOutputConverter* outputConverter,
cmStateDirectory const& stateDir);
- std::string ConvertToLinkReference(std::string const& input) const
- CM_OVERRIDE;
+ cmMSVC60LinkLineComputer(cmMSVC60LinkLineComputer const&) = delete;
+ cmMSVC60LinkLineComputer& operator=(cmMSVC60LinkLineComputer const&) =
+ delete;
+
+ std::string ConvertToLinkReference(std::string const& input) const override;
};
#endif
diff --git a/Source/cmMachO.cxx b/Source/cmMachO.cxx
index a4350f7ce..6cbed36d9 100644
--- a/Source/cmMachO.cxx
+++ b/Source/cmMachO.cxx
@@ -2,12 +2,16 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMachO.h"
-#include "cmsys/FStream.hxx"
-#include <algorithm>
-#include <stddef.h>
+#include <cstddef>
#include <string>
#include <vector>
+#include <cm/memory>
+
+#include "cmsys/FStream.hxx"
+
+#include "cmAlgorithms.h"
+
// Include the Mach-O format information system header.
#include <mach-o/fat.h>
#include <mach-o/loader.h>
@@ -52,10 +56,7 @@ bool peek(cmsys::ifstream& fin, T& v)
template <typename T>
bool read(cmsys::ifstream& fin, T& v)
{
- if (!fin.read(reinterpret_cast<char*>(&v), sizeof(T))) {
- return false;
- }
- return true;
+ return !!fin.read(reinterpret_cast<char*>(&v), sizeof(T));
}
// read from the file and fill multiple data structures where
@@ -67,10 +68,7 @@ bool read(cmsys::ifstream& fin, std::vector<T>& v)
if (v.empty()) {
return true;
}
- if (!fin.read(reinterpret_cast<char*>(&v[0]), sizeof(T) * v.size())) {
- return false;
- }
- return true;
+ return !!fin.read(reinterpret_cast<char*>(&v[0]), sizeof(T) * v.size());
}
}
@@ -97,7 +95,7 @@ public:
: Swap(_swap)
{
}
- virtual ~cmMachOHeaderAndLoadCommands() {}
+ virtual ~cmMachOHeaderAndLoadCommands() = default;
virtual bool read_mach_o(cmsys::ifstream& fin) = 0;
@@ -126,7 +124,7 @@ protected:
// Implementation for reading Mach-O header and load commands.
// This is 32 or 64 bit arch specific.
-template <class T>
+template <typename T>
class cmMachOHeaderAndLoadCommandsImpl : public cmMachOHeaderAndLoadCommands
{
public:
@@ -134,7 +132,7 @@ public:
: cmMachOHeaderAndLoadCommands(_swap)
{
}
- bool read_mach_o(cmsys::ifstream& fin)
+ bool read_mach_o(cmsys::ifstream& fin) override
{
if (!read(fin, this->Header)) {
return false;
@@ -251,8 +249,7 @@ cmMachOInternal::cmMachOInternal(const char* fname)
}
// parse each Mach-O file
- for (size_t i = 0; i < this->FatArchs.size(); i++) {
- const fat_arch& arch = this->FatArchs[i];
+ for (const auto& arch : this->FatArchs) {
if (!this->read_mach_o(OSSwapBigToHostInt32(arch.offset))) {
return;
}
@@ -265,8 +262,8 @@ cmMachOInternal::cmMachOInternal(const char* fname)
cmMachOInternal::~cmMachOInternal()
{
- for (size_t i = 0; i < this->MachOList.size(); i++) {
- delete this->MachOList[i];
+ for (auto& i : this->MachOList) {
+ delete i;
}
}
@@ -283,7 +280,7 @@ bool cmMachOInternal::read_mach_o(uint32_t file_offset)
return false;
}
- cmMachOHeaderAndLoadCommands* f = NULL;
+ cmMachOHeaderAndLoadCommands* f = nullptr;
if (magic == MH_CIGAM || magic == MH_MAGIC) {
bool swap = false;
if (magic == MH_CIGAM) {
@@ -313,15 +310,11 @@ bool cmMachOInternal::read_mach_o(uint32_t file_offset)
// External class implementation.
cmMachO::cmMachO(const char* fname)
- : Internal(0)
+ : Internal(cm::make_unique<cmMachOInternal>(fname))
{
- this->Internal = new cmMachOInternal(fname);
}
-cmMachO::~cmMachO()
-{
- delete this->Internal;
-}
+cmMachO::~cmMachO() = default;
std::string const& cmMachO::GetErrorMessage() const
{
diff --git a/Source/cmMachO.h b/Source/cmMachO.h
index 42745cf60..0c44b5564 100644
--- a/Source/cmMachO.h
+++ b/Source/cmMachO.h
@@ -3,13 +3,13 @@
#ifndef cmMachO_h
#define cmMachO_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
#if !defined(CMAKE_USE_MACH_PARSER)
-#error "This file may be included only if CMAKE_USE_MACH_PARSER is enabled."
+# error "This file may be included only if CMAKE_USE_MACH_PARSER is enabled."
#endif
class cmMachOInternal;
@@ -30,7 +30,7 @@ public:
std::string const& GetErrorMessage() const;
/** Boolean conversion. True if the Mach-O file is valid. */
- operator bool() const { return this->Valid(); }
+ explicit operator bool() const { return this->Valid(); }
/** Get Install name from binary **/
bool GetInstallName(std::string& install_name);
@@ -41,7 +41,7 @@ public:
private:
friend class cmMachOInternal;
bool Valid() const;
- cmMachOInternal* Internal;
+ std::unique_ptr<cmMachOInternal> Internal;
};
#endif
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx
index a6a9ea316..ba9947a33 100644
--- a/Source/cmMacroCommand.cxx
+++ b/Source/cmMacroCommand.cxx
@@ -2,51 +2,37 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMacroCommand.h"
-#include <sstream>
-#include <stdio.h>
+#include <cstdio>
+#include <utility>
+
+#include <cm/memory>
+#include <cm/string_view>
+
+#include "cm_static_string_view.hxx"
#include "cmAlgorithms.h"
#include "cmExecutionStatus.h"
+#include "cmFunctionBlocker.h"
+#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
+#include "cmRange.h"
#include "cmState.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+namespace {
+
// define the class for macro commands
-class cmMacroHelperCommand : public cmCommand
+class cmMacroHelperCommand
{
public:
- cmMacroHelperCommand() {}
-
- ///! clean up any memory allocated by the macro
- ~cmMacroHelperCommand() CM_OVERRIDE {}
-
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE
- {
- cmMacroHelperCommand* newC = new cmMacroHelperCommand;
- // we must copy when we clone
- newC->Args = this->Args;
- newC->Functions = this->Functions;
- newC->FilePath = this->FilePath;
- newC->Policies = this->Policies;
- return newC;
- }
-
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
- bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
- cmExecutionStatus&) CM_OVERRIDE;
-
- bool InitialPass(std::vector<std::string> const&,
- cmExecutionStatus&) CM_OVERRIDE
- {
- return false;
- }
+ bool operator()(std::vector<cmListFileArgument> const& args,
+ cmExecutionStatus& inStatus) const;
std::vector<std::string> Args;
std::vector<cmListFileFunction> Functions;
@@ -54,33 +40,33 @@ public:
std::string FilePath;
};
-bool cmMacroHelperCommand::InvokeInitialPass(
- const std::vector<cmListFileArgument>& args, cmExecutionStatus& inStatus)
+bool cmMacroHelperCommand::operator()(
+ std::vector<cmListFileArgument> const& args,
+ cmExecutionStatus& inStatus) const
{
+ cmMakefile& makefile = inStatus.GetMakefile();
+
// Expand the argument list to the macro.
std::vector<std::string> expandedArgs;
- this->Makefile->ExpandArguments(args, expandedArgs);
+ makefile.ExpandArguments(args, expandedArgs);
// make sure the number of arguments passed is at least the number
// required by the signature
if (expandedArgs.size() < this->Args.size() - 1) {
std::string errorMsg =
- "Macro invoked with incorrect arguments for macro named: ";
- errorMsg += this->Args[0];
- this->SetError(errorMsg);
+ cmStrCat("Macro invoked with incorrect arguments for macro named: ",
+ this->Args[0]);
+ inStatus.SetError(errorMsg);
return false;
}
- cmMakefile::MacroPushPop macroScope(this->Makefile, this->FilePath,
+ cmMakefile::MacroPushPop macroScope(&makefile, this->FilePath,
this->Policies);
// set the value of argc
- std::ostringstream argcDefStream;
- argcDefStream << expandedArgs.size();
- std::string argcDef = argcDefStream.str();
+ std::string argcDef = std::to_string(expandedArgs.size());
- std::vector<std::string>::const_iterator eit =
- expandedArgs.begin() + (this->Args.size() - 1);
+ auto eit = expandedArgs.begin() + (this->Args.size() - 1);
std::string expandedArgn = cmJoin(cmMakeRange(eit, expandedArgs.end()), ";");
std::string expandedArgv = cmJoin(expandedArgs, ";");
std::vector<std::string> variables;
@@ -92,26 +78,24 @@ bool cmMacroHelperCommand::InvokeInitialPass(
argVs.reserve(expandedArgs.size());
char argvName[60];
for (unsigned int j = 0; j < expandedArgs.size(); ++j) {
- sprintf(argvName, "${ARGV%i}", j);
- argVs.push_back(argvName);
+ sprintf(argvName, "${ARGV%u}", j);
+ argVs.emplace_back(argvName);
}
// Invoke all the functions that were collected in the block.
cmListFileFunction newLFF;
// for each function
- for (unsigned int c = 0; c < this->Functions.size(); ++c) {
+ for (cmListFileFunction const& func : this->Functions) {
// Replace the formal arguments and then invoke the command.
newLFF.Arguments.clear();
- newLFF.Arguments.reserve(this->Functions[c].Arguments.size());
- newLFF.Name = this->Functions[c].Name;
- newLFF.Line = this->Functions[c].Line;
+ newLFF.Arguments.reserve(func.Arguments.size());
+ newLFF.Name = func.Name;
+ newLFF.Line = func.Line;
// for each argument of the current function
- for (std::vector<cmListFileArgument>::iterator k =
- this->Functions[c].Arguments.begin();
- k != this->Functions[c].Arguments.end(); ++k) {
+ for (cmListFileArgument const& k : func.Arguments) {
cmListFileArgument arg;
- arg.Value = k->Value;
- if (k->Delim != cmListFileArgument::Bracket) {
+ arg.Value = k.Value;
+ if (k.Delim != cmListFileArgument::Bracket) {
// replace formal arguments
for (unsigned int j = 0; j < variables.size(); ++j) {
cmSystemTools::ReplaceString(arg.Value, variables[j],
@@ -131,13 +115,12 @@ bool cmMacroHelperCommand::InvokeInitialPass(
}
}
}
- arg.Delim = k->Delim;
- arg.Line = k->Line;
- newLFF.Arguments.push_back(arg);
+ arg.Delim = k.Delim;
+ arg.Line = k.Line;
+ newLFF.Arguments.push_back(std::move(arg));
}
- cmExecutionStatus status;
- if (!this->Makefile->ExecuteCommand(newLFF, status) ||
- status.GetNestedError()) {
+ cmExecutionStatus status(makefile);
+ if (!makefile.ExecuteCommand(newLFF, status) || status.GetNestedError()) {
// The error message should have already included the call stack
// so we do not need to report an error here.
macroScope.Quiet();
@@ -156,68 +139,59 @@ bool cmMacroHelperCommand::InvokeInitialPass(
return true;
}
-bool cmMacroFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
- cmMakefile& mf,
- cmExecutionStatus&)
+class cmMacroFunctionBlocker : public cmFunctionBlocker
{
- // record commands until we hit the ENDMACRO
- // at the ENDMACRO call we shift gears and start looking for invocations
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "macro")) {
- this->Depth++;
- } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endmacro")) {
- // if this is the endmacro for this macro then execute
- if (!this->Depth) {
- mf.AppendProperty("MACROS", this->Args[0].c_str());
- // create a new command and add it to cmake
- cmMacroHelperCommand* f = new cmMacroHelperCommand();
- f->Args = this->Args;
- f->Functions = this->Functions;
- f->FilePath = this->GetStartingContext().FilePath;
- mf.RecordPolicies(f->Policies);
- mf.GetState()->AddScriptedCommand(this->Args[0], f);
- // remove the function blocker now that the macro is defined
- mf.RemoveFunctionBlocker(this, lff);
- return true;
- }
- // decrement for each nested macro that ends
- this->Depth--;
- }
+public:
+ cm::string_view StartCommandName() const override { return "macro"_s; }
+ cm::string_view EndCommandName() const override { return "endmacro"_s; }
- // if it wasn't an endmacro and we are not executing then we must be
- // recording
- this->Functions.push_back(lff);
- return true;
-}
+ bool ArgumentsMatch(cmListFileFunction const&,
+ cmMakefile& mf) const override;
+
+ bool Replay(std::vector<cmListFileFunction> functions,
+ cmExecutionStatus& status) override;
-bool cmMacroFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
- cmMakefile& mf)
+ std::vector<std::string> Args;
+};
+
+bool cmMacroFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
+ cmMakefile& mf) const
{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endmacro")) {
- std::vector<std::string> expandedArguments;
- mf.ExpandArguments(lff.Arguments, expandedArguments,
- this->GetStartingContext().FilePath.c_str());
- // if the endmacro has arguments make sure they
- // match the arguments of the macro
- if ((expandedArguments.empty() ||
- (expandedArguments[0] == this->Args[0]))) {
- return true;
- }
- }
+ std::vector<std::string> expandedArguments;
+ mf.ExpandArguments(lff.Arguments, expandedArguments,
+ this->GetStartingContext().FilePath.c_str());
+ return expandedArguments.empty() || expandedArguments[0] == this->Args[0];
+}
- return false;
+bool cmMacroFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,
+ cmExecutionStatus& status)
+{
+ cmMakefile& mf = status.GetMakefile();
+ mf.AppendProperty("MACROS", this->Args[0].c_str());
+ // create a new command and add it to cmake
+ cmMacroHelperCommand f;
+ f.Args = this->Args;
+ f.Functions = std::move(functions);
+ f.FilePath = this->GetStartingContext().FilePath;
+ mf.RecordPolicies(f.Policies);
+ mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f));
+ return true;
+}
}
-bool cmMacroCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmMacroCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
// create a function blocker
- cmMacroFunctionBlocker* f = new cmMacroFunctionBlocker();
- f->Args.insert(f->Args.end(), args.begin(), args.end());
- this->Makefile->AddFunctionBlocker(f);
+ {
+ auto fb = cm::make_unique<cmMacroFunctionBlocker>();
+ cmAppend(fb->Args, args);
+ status.GetMakefile().AddFunctionBlocker(std::move(fb));
+ }
return true;
}
diff --git a/Source/cmMacroCommand.h b/Source/cmMacroCommand.h
index 0d35fe06e..25091eacf 100644
--- a/Source/cmMacroCommand.h
+++ b/Source/cmMacroCommand.h
@@ -3,47 +3,15 @@
#ifndef cmMacroCommand_h
#define cmMacroCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-#include "cmFunctionBlocker.h"
-#include "cmListFileCache.h"
-
class cmExecutionStatus;
-class cmMakefile;
-
-class cmMacroFunctionBlocker : public cmFunctionBlocker
-{
-public:
- cmMacroFunctionBlocker() { this->Depth = 0; }
- ~cmMacroFunctionBlocker() CM_OVERRIDE {}
- bool IsFunctionBlocked(const cmListFileFunction&, cmMakefile& mf,
- cmExecutionStatus&) CM_OVERRIDE;
- bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) CM_OVERRIDE;
-
- std::vector<std::string> Args;
- std::vector<cmListFileFunction> Functions;
- int Depth;
-};
/// Starts macro() ... endmacro() block
-class cmMacroCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmMacroCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmMacroCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmMakeDirectoryCommand.cxx b/Source/cmMakeDirectoryCommand.cxx
index 06e295bc0..cdde6f990 100644
--- a/Source/cmMakeDirectoryCommand.cxx
+++ b/Source/cmMakeDirectoryCommand.cxx
@@ -2,26 +2,25 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMakeDirectoryCommand.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
-
// cmMakeDirectoryCommand
-bool cmMakeDirectoryCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmMakeDirectoryCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() != 1) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
- if (!this->Makefile->CanIWriteThisFile(args[0].c_str())) {
+ if (!status.GetMakefile().CanIWriteThisFile(args[0])) {
std::string e = "attempted to create a directory: " + args[0] +
" into a source directory.";
- this->SetError(e);
+ status.SetError(e);
cmSystemTools::SetFatalErrorOccured();
return false;
}
- cmSystemTools::MakeDirectory(args[0].c_str());
+ cmSystemTools::MakeDirectory(args[0]);
return true;
}
diff --git a/Source/cmMakeDirectoryCommand.h b/Source/cmMakeDirectoryCommand.h
index af72eab96..2474383bb 100644
--- a/Source/cmMakeDirectoryCommand.h
+++ b/Source/cmMakeDirectoryCommand.h
@@ -3,16 +3,14 @@
#ifndef cmMakeDirectoryCommand_h
#define cmMakeDirectoryCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmMakeDirectoryCommand
+/**
* \brief Specify auxiliary source code directories.
*
* cmMakeDirectoryCommand specifies source code directories
@@ -21,20 +19,7 @@ class cmExecutionStatus;
* A side effect of this command is to create a subdirectory in the build
* directory structure.
*/
-class cmMakeDirectoryCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmMakeDirectoryCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmMakeDirectoryCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 608b18a46..f143ef704 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -1,52 +1,69 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmConfigure.h" // IWYU pragma: keep
+
#include "cmMakefile.h"
-#include "cmsys/FStream.hxx"
-#include "cmsys/RegularExpression.hxx"
#include <algorithm>
-#include <assert.h>
-#include <ctype.h>
+#include <cassert>
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
#include <sstream>
-#include <stdlib.h>
-#include <string.h>
#include <utility>
+#include <cm/iterator>
+#include <cm/memory>
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+
+#include "cm_sys_stat.h"
+
#include "cmAlgorithms.h"
-#include "cmCommand.h"
#include "cmCommandArgumentParserHelper.h"
#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 "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionEvaluationFile.h"
#include "cmGlobalGenerator.h"
#include "cmInstallGenerator.h" // IWYU pragma: keep
+#include "cmInstallSubdirectoryGenerator.h"
#include "cmListFileCache.h"
+#include "cmMessageType.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmTarget.h"
#include "cmTargetLinkLibraryType.h"
#include "cmTest.h"
#include "cmTestGenerator.h" // IWYU pragma: keep
#include "cmVersion.h"
#include "cmWorkingDirectory.h"
-#include "cm_auto_ptr.hxx"
-#include "cm_sys_stat.h"
#include "cmake.h"
-#ifdef CMAKE_BUILD_WITH_CMAKE
-#include "cmVariableWatch.h"
+#ifndef CMAKE_BOOTSTRAP
+# include "cmVariableWatch.h"
#endif
class cmMessenger;
+cmDirectoryId::cmDirectoryId(std::string s)
+ : String(std::move(s))
+{
+}
+
// default is not to be building executables
cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator,
cmStateSnapshot const& snapshot)
@@ -59,21 +76,22 @@ cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator,
this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused();
this->CheckSystemVars = this->GetCMakeInstance()->GetCheckSystemVars();
- this->SuppressWatches = false;
+ this->SuppressSideEffects = false;
// Setup the default include complaint regular expression (match nothing).
this->ComplainFileRegularExpression = "^$";
this->DefineFlags = " ";
- this->cmDefineRegex.compile("#cmakedefine[ \t]+([A-Za-z_0-9]*)");
- this->cmDefine01Regex.compile("#cmakedefine01[ \t]+([A-Za-z_0-9]*)");
+ this->cmDefineRegex.compile("#([ \t]*)cmakedefine[ \t]+([A-Za-z_0-9]*)");
+ this->cmDefine01Regex.compile("#([ \t]*)cmakedefine01[ \t]+([A-Za-z_0-9]*)");
this->cmAtVarRegex.compile("(@[A-Za-z_0-9/.+-]+@)");
this->cmNamedCurly.compile("^[A-Za-z0-9/_.+-]+{");
this->StateSnapshot =
this->StateSnapshot.GetState()->CreatePolicyScopeSnapshot(
this->StateSnapshot);
+ this->RecursionDepth = 0;
// Enter a policy level for this directory.
this->PushPolicy();
@@ -85,19 +103,17 @@ cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator,
// cmListFileCache in the top level if necessary.
this->CheckCMP0000 = false;
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
this->AddSourceGroup("", "^.*$");
- this->AddSourceGroup("Source Files",
- "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|f|f90|for|fpp"
- "|ftn|m|mm|rc|def|r|odl|idl|hpj|bat)$");
+ this->AddSourceGroup("Source Files", CM_SOURCE_REGEX);
this->AddSourceGroup("Header Files", CM_HEADER_REGEX);
+ this->AddSourceGroup("Precompile Header File", CM_PCH_REGEX);
this->AddSourceGroup("CMake Rules", "\\.rule$");
- this->AddSourceGroup("Resources", "\\.plist$");
+ this->AddSourceGroup("Resources", CM_RESOURCE_REGEX);
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
}
@@ -108,22 +124,93 @@ cmMakefile::~cmMakefile()
cmDeleteAll(this->SourceFiles);
cmDeleteAll(this->Tests);
cmDeleteAll(this->ImportedTargetsOwned);
- cmDeleteAll(this->FinalPassCommands);
- cmDeleteAll(this->FunctionBlockers);
cmDeleteAll(this->EvaluationFiles);
}
-void cmMakefile::IssueMessage(cmake::MessageType t,
- std::string const& text) const
+cmDirectoryId cmMakefile::GetDirectoryId() const
+{
+ // Use the instance pointer value to uniquely identify this directory.
+ // If we ever need to expose this to CMake language code we should
+ // add a read-only property in cmMakefile::GetProperty.
+ char buf[32];
+ sprintf(buf, "<%p>",
+ static_cast<void const*>(this)); // cast avoids format warning
+ return std::string(buf);
+}
+
+void cmMakefile::IssueMessage(MessageType t, std::string const& text) const
{
if (!this->ExecutionStatusStack.empty()) {
- if ((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR)) {
+ if ((t == MessageType::FATAL_ERROR) ||
+ (t == MessageType::INTERNAL_ERROR)) {
this->ExecutionStatusStack.back()->SetNestedError();
}
}
this->GetCMakeInstance()->IssueMessage(t, text, this->GetBacktrace());
}
+bool cmMakefile::CheckCMP0037(std::string const& targetName,
+ cmStateEnums::TargetType targetType) const
+{
+ MessageType messageType = MessageType::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 = MessageType::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 == MessageType::FATAL_ERROR) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void cmMakefile::MaybeWarnCMP0074(std::string const& pkg)
+{
+ // Warn if a <pkg>_ROOT variable we may use is set.
+ std::string const varName = pkg + "_ROOT";
+ const char* var = this->GetDefinition(varName);
+ std::string env;
+ cmSystemTools::GetEnv(varName, env);
+
+ bool const haveVar = var && *var;
+ bool const haveEnv = !env.empty();
+ if ((haveVar || haveEnv) && this->WarnedCMP0074.insert(varName).second) {
+ std::ostringstream w;
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0074) << "\n";
+ if (haveVar) {
+ w << "CMake variable " << varName << " is set to:\n"
+ << " " << var << "\n";
+ }
+ if (haveEnv) {
+ w << "Environment variable " << varName << " is set to:\n"
+ << " " << env << "\n";
+ }
+ w << "For compatibility, CMake is ignoring the variable.";
+ this->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
+ }
+}
+
cmStringRange cmMakefile::GetIncludeDirectoriesEntries() const
{
return this->StateSnapshot.GetDirectory().GetIncludeDirectoriesEntries();
@@ -156,6 +243,27 @@ cmBacktraceRange cmMakefile::GetCompileDefinitionsBacktraces() const
.GetCompileDefinitionsEntryBacktraces();
}
+cmStringRange cmMakefile::GetLinkOptionsEntries() const
+{
+ return this->StateSnapshot.GetDirectory().GetLinkOptionsEntries();
+}
+
+cmBacktraceRange cmMakefile::GetLinkOptionsBacktraces() const
+{
+ return this->StateSnapshot.GetDirectory().GetLinkOptionsEntryBacktraces();
+}
+
+cmStringRange cmMakefile::GetLinkDirectoriesEntries() const
+{
+ return this->StateSnapshot.GetDirectory().GetLinkDirectoriesEntries();
+}
+
+cmBacktraceRange cmMakefile::GetLinkDirectoriesBacktraces() const
+{
+ return this->StateSnapshot.GetDirectory()
+ .GetLinkDirectoriesEntryBacktraces();
+}
+
cmListFileBacktrace cmMakefile::GetBacktrace() const
{
return this->Backtrace;
@@ -164,7 +272,7 @@ cmListFileBacktrace cmMakefile::GetBacktrace() const
cmListFileBacktrace cmMakefile::GetBacktrace(cmCommandContext const& cc) const
{
cmListFileContext lfc;
- lfc.Name = cc.Name;
+ lfc.Name = cc.Name.Original;
lfc.Line = cc.Line;
lfc.FilePath = this->StateSnapshot.GetExecutionListFile();
return this->Backtrace.Push(lfc);
@@ -189,13 +297,14 @@ void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const
std::string const& only_filename = cmSystemTools::GetFilenameName(full_path);
bool trace = trace_only_this_files.empty();
if (!trace) {
- for (std::vector<std::string>::const_iterator i =
- trace_only_this_files.begin();
- !trace && i != trace_only_this_files.end(); ++i) {
- std::string::size_type const pos = full_path.rfind(*i);
+ for (std::string const& file : trace_only_this_files) {
+ std::string::size_type const pos = full_path.rfind(file);
trace = (pos != std::string::npos) &&
- ((pos + i->size()) == full_path.size()) &&
- (only_filename == cmSystemTools::GetFilenameName(*i));
+ ((pos + file.size()) == full_path.size()) &&
+ (only_filename == cmSystemTools::GetFilenameName(file));
+ if (trace) {
+ break;
+ }
}
// Do nothing if current file wasn't requested for trace...
if (!trace) {
@@ -205,23 +314,27 @@ void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const
std::ostringstream msg;
msg << full_path << "(" << lff.Line << "): ";
- msg << lff.Name << "(";
+ msg << lff.Name.Original << "(";
bool expand = this->GetCMakeInstance()->GetTraceExpand();
std::string temp;
- for (std::vector<cmListFileArgument>::const_iterator i =
- lff.Arguments.begin();
- i != lff.Arguments.end(); ++i) {
+ for (cmListFileArgument const& arg : lff.Arguments) {
if (expand) {
- temp = i->Value;
+ temp = arg.Value;
this->ExpandVariablesInString(temp);
msg << temp;
} else {
- msg << i->Value;
+ msg << arg.Value;
}
msg << " ";
}
msg << ")";
- cmSystemTools::Message(msg.str().c_str());
+
+ auto& f = this->GetCMakeInstance()->GetTraceFile();
+ if (f) {
+ f << msg.str() << '\n';
+ } else {
+ cmSystemTools::Message(msg.str());
+ }
}
// Helper class to make sure the call stack is valid.
@@ -235,19 +348,29 @@ public:
cmListFileContext const& lfc = cmListFileContext::FromCommandContext(
cc, this->Makefile->StateSnapshot.GetExecutionListFile());
this->Makefile->Backtrace = this->Makefile->Backtrace.Push(lfc);
+ ++this->Makefile->RecursionDepth;
this->Makefile->ExecutionStatusStack.push_back(&status);
}
~cmMakefileCall()
{
this->Makefile->ExecutionStatusStack.pop_back();
+ --this->Makefile->RecursionDepth;
this->Makefile->Backtrace = this->Makefile->Backtrace.Pop();
}
+ cmMakefileCall(const cmMakefileCall&) = delete;
+ cmMakefileCall& operator=(const cmMakefileCall&) = delete;
+
private:
cmMakefile* Makefile;
};
+void cmMakefile::OnExecuteCommand(std::function<void()> callback)
+{
+ this->ExecuteCommandCallback = std::move(callback);
+}
+
bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
cmExecutionStatus& status)
{
@@ -259,18 +382,35 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
return result;
}
- std::string name = lff.Name;
+ if (this->ExecuteCommandCallback) {
+ this->ExecuteCommandCallback();
+ }
// Place this call on the call stack.
cmMakefileCall stack_manager(this, lff, status);
static_cast<void>(stack_manager);
- // Lookup the command prototype.
- if (cmCommand* proto = this->GetState()->GetCommand(name)) {
- // Clone the prototype.
- CM_AUTO_PTR<cmCommand> pcmd(proto->Clone());
- pcmd->SetMakefile(this);
+ // Check for maximum recursion depth.
+ int depth = CMake_DEFAULT_RECURSION_LIMIT;
+ const char* depthStr = this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH");
+ if (depthStr) {
+ std::istringstream s(depthStr);
+ int d;
+ if (s >> d) {
+ depth = d;
+ }
+ }
+ if (this->RecursionDepth > depth) {
+ std::ostringstream e;
+ e << "Maximum recursion depth of " << depth << " exceeded";
+ this->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+ // Lookup the command prototype.
+ if (cmState::Command command =
+ this->GetState()->GetCommandByExactName(lff.Name.Lower)) {
// Decide whether to invoke the command.
if (!cmSystemTools::GetFatalErrorOccured()) {
// if trace is enabled, print out invoke information
@@ -278,29 +418,26 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
this->PrintCommandTrace(lff);
}
// Try invoking the command.
- bool invokeSucceeded = pcmd->InvokeInitialPass(lff.Arguments, status);
+ bool invokeSucceeded = command(lff.Arguments, status);
bool hadNestedError = status.GetNestedError();
if (!invokeSucceeded || hadNestedError) {
if (!hadNestedError) {
// The command invocation requested that we report an error.
- std::string const error = name + " " + pcmd->GetError();
- this->IssueMessage(cmake::FATAL_ERROR, error);
+ std::string const error =
+ std::string(lff.Name.Original) + " " + status.GetError();
+ this->IssueMessage(MessageType::FATAL_ERROR, error);
}
result = false;
if (this->GetCMakeInstance()->GetWorkingMode() != cmake::NORMAL_MODE) {
cmSystemTools::SetFatalErrorOccured();
}
- } else if (pcmd->HasFinalPass()) {
- // use the command
- this->FinalPassCommands.push_back(pcmd.release());
}
}
} else {
if (!cmSystemTools::GetFatalErrorOccured()) {
- std::string error = "Unknown CMake command \"";
- error += lff.Name;
- error += "\".";
- this->IssueMessage(cmake::FATAL_ERROR, error);
+ std::string error =
+ cmStrCat("Unknown CMake command \"", lff.Name.Original, "\".");
+ this->IssueMessage(MessageType::FATAL_ERROR, error);
result = false;
cmSystemTools::SetFatalErrorOccured();
}
@@ -317,6 +454,9 @@ public:
~IncludeScope();
void Quiet() { this->ReportError = false; }
+ IncludeScope(const IncludeScope&) = delete;
+ IncludeScope& operator=(const IncludeScope&) = delete;
+
private:
cmMakefile* Makefile;
bool NoPolicyScope;
@@ -412,7 +552,7 @@ void cmMakefile::IncludeScope::EnforceCMP0011()
<< "affects policy settings. "
<< "CMake is implying the NO_POLICY_SCOPE option for compatibility, "
<< "so the effects are applied to the including context.";
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
}
break;
case cmPolicies::REQUIRED_IF_USED:
@@ -424,7 +564,7 @@ void cmMakefile::IncludeScope::EnforceCMP0011()
<< this->Makefile->GetExecutionFilePath() << "\n"
<< "affects policy settings, so it requires this policy to be set.";
/* clang-format on */
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
} break;
case cmPolicies::OLD:
case cmPolicies::NEW:
@@ -435,10 +575,12 @@ void cmMakefile::IncludeScope::EnforceCMP0011()
}
}
-bool cmMakefile::ReadDependentFile(const char* filename, bool noPolicyScope)
+bool cmMakefile::ReadDependentFile(const std::string& filename,
+ bool noPolicyScope)
{
- this->AddDefinition("CMAKE_PARENT_LIST_FILE",
- this->GetDefinition("CMAKE_CURRENT_LIST_FILE"));
+ if (const char* def = this->GetDefinition("CMAKE_CURRENT_LIST_FILE")) {
+ this->AddDefinition("CMAKE_PARENT_LIST_FILE", def);
+ }
std::string filenametoread = cmSystemTools::CollapseFullPath(
filename, this->GetCurrentSourceDirectory());
@@ -483,12 +625,15 @@ public:
void Quiet() { this->ReportError = false; }
+ ListFileScope(const ListFileScope&) = delete;
+ ListFileScope& operator=(const ListFileScope&) = delete;
+
private:
cmMakefile* Makefile;
bool ReportError;
};
-bool cmMakefile::ReadListFile(const char* filename)
+bool cmMakefile::ReadListFile(const std::string& filename)
{
std::string filenametoread = cmSystemTools::CollapseFullPath(
filename, this->GetCurrentSourceDirectory());
@@ -518,9 +663,9 @@ void cmMakefile::ReadListFile(cmListFile const& listFile,
this->GetSafeDefinition("CMAKE_PARENT_LIST_FILE");
std::string currentFile = this->GetSafeDefinition("CMAKE_CURRENT_LIST_FILE");
- this->AddDefinition("CMAKE_CURRENT_LIST_FILE", filenametoread.c_str());
+ this->AddDefinition("CMAKE_CURRENT_LIST_FILE", filenametoread);
this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
- cmSystemTools::GetFilenamePath(filenametoread).c_str());
+ cmSystemTools::GetFilenamePath(filenametoread));
this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
@@ -529,7 +674,7 @@ void cmMakefile::ReadListFile(cmListFile const& listFile,
// Run the parsed commands.
const size_t numberFunctions = listFile.Functions.size();
for (size_t i = 0; i < numberFunctions; ++i) {
- cmExecutionStatus status;
+ cmExecutionStatus status(*this);
this->ExecuteCommand(listFile.Functions[i], status);
if (cmSystemTools::GetFatalErrorOccured()) {
break;
@@ -541,10 +686,10 @@ void cmMakefile::ReadListFile(cmListFile const& listFile,
}
this->CheckForUnusedVariables();
- this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile.c_str());
- this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile.c_str());
+ this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile);
+ this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile);
this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
- cmSystemTools::GetFilenamePath(currentFile).c_str());
+ cmSystemTools::GetFilenamePath(currentFile));
this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");
@@ -566,9 +711,9 @@ 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,
+ this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING,
msg.str(), this->Backtrace);
case cmPolicies::OLD:
// OLD behavior is to use policy version 2.4 set in
@@ -578,8 +723,8 @@ void cmMakefile::EnforceDirectoryLevelRules() const
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
// NEW behavior is to issue an error.
- this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, msg.str(),
- this->Backtrace);
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
+ msg.str(), this->Backtrace);
cmSystemTools::SetFatalErrorOccured();
return;
}
@@ -588,11 +733,13 @@ void cmMakefile::EnforceDirectoryLevelRules() const
void cmMakefile::AddEvaluationFile(
const std::string& inputFile,
- CM_AUTO_PTR<cmCompiledGeneratorExpression> outputName,
- CM_AUTO_PTR<cmCompiledGeneratorExpression> condition, bool inputIsContent)
+ std::unique_ptr<cmCompiledGeneratorExpression> outputName,
+ std::unique_ptr<cmCompiledGeneratorExpression> condition,
+ bool inputIsContent)
{
this->EvaluationFiles.push_back(new cmGeneratorExpressionEvaluationFile(
- inputFile, outputName, condition, inputIsContent));
+ inputFile, std::move(outputName), std::move(condition), inputIsContent,
+ this->GetPolicyStatus(cmPolicies::CMP0070)));
}
std::vector<cmGeneratorExpressionEvaluationFile*>
@@ -610,9 +757,8 @@ cmMakefile::GetExportBuildFileGenerators() const
void cmMakefile::RemoveExportBuildFileGeneratorCMP0024(
cmExportBuildFileGenerator* gen)
{
- std::vector<cmExportBuildFileGenerator*>::iterator it =
- std::find(this->ExportBuildFileGenerators.begin(),
- this->ExportBuildFileGenerators.end(), gen);
+ auto it = std::find(this->ExportBuildFileGenerators.begin(),
+ this->ExportBuildFileGenerators.end(), gen);
if (it != this->ExportBuildFileGenerators.end()) {
this->ExportBuildFileGenerators.erase(it);
}
@@ -629,11 +775,16 @@ 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));
}
};
}
+void cmMakefile::AddFinalAction(FinalAction action)
+{
+ this->FinalActions.push_back(std::move(action));
+}
+
void cmMakefile::FinalPass()
{
// do all the variable expansions here
@@ -641,9 +792,8 @@ void cmMakefile::FinalPass()
// give all the commands a chance to do something
// after the file has been parsed before generation
- for (std::vector<cmCommand*>::iterator i = this->FinalPassCommands.begin();
- i != this->FinalPassCommands.end(); ++i) {
- (*i)->FinalPass();
+ for (FinalAction& action : this->FinalActions) {
+ action(*this);
}
// go through all configured files and see which ones still exist.
@@ -666,7 +816,7 @@ void cmMakefile::ConfigureFinalPass()
if (oldValue &&
cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, oldValue, "2.4")) {
this->GetCMakeInstance()->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"You have set CMAKE_BACKWARDS_COMPATIBILITY to a CMake version less "
"than 2.4. This version of CMake only supports backwards compatibility "
"with CMake 2.4 or later. For compatibility with older versions please "
@@ -675,19 +825,30 @@ void cmMakefile::ConfigureFinalPass()
}
}
-void cmMakefile::AddCustomCommandToTarget(
- const std::string& target, const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type,
- const char* comment, const char* workingDir, bool escapeOldStyle,
- bool uses_terminal, const std::string& depfile, bool command_expand_lists,
- ObjectLibraryCommands objLibraryCommands)
+bool cmMakefile::ValidateCustomCommand(
+ const cmCustomCommandLines& commandLines) const
+{
+ // TODO: More strict?
+ for (cmCustomCommandLine const& cl : commandLines) {
+ if (!cl.empty() && !cl[0].empty() && cl[0][0] == '"') {
+ std::ostringstream e;
+ e << "COMMAND may not contain literal quotes:\n " << cl[0] << "\n";
+ this->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return false;
+ }
+ }
+
+ return true;
+}
+
+cmTarget* cmMakefile::GetCustomCommandTarget(
+ const std::string& target, cmObjectLibraryCommands objLibCommands) const
{
// Find the target to which to add the custom command.
- cmTargets::iterator ti = this->Targets.find(target);
+ auto ti = this->Targets.find(target);
if (ti == this->Targets.end()) {
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ MessageType messageType = MessageType::AUTHOR_WARNING;
bool issueMessage = false;
std::ostringstream e;
switch (this->GetPolicyStatus(cmPolicies::CMP0040)) {
@@ -700,7 +861,7 @@ void cmMakefile::AddCustomCommandToTarget(
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
issueMessage = true;
- messageType = cmake::FATAL_ERROR;
+ messageType = MessageType::FATAL_ERROR;
}
if (issueMessage) {
@@ -715,38 +876,67 @@ void cmMakefile::AddCustomCommandToTarget(
e << "No TARGET '" << target
<< "' has been created in this directory.";
}
- IssueMessage(messageType, e.str());
+ this->IssueMessage(messageType, e.str());
}
- return;
+ return nullptr;
}
- if (objLibraryCommands == RejectObjectLibraryCommands &&
- ti->second.GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ cmTarget* t = &ti->second;
+ if (objLibCommands == cmObjectLibraryCommands::Reject &&
+ t->GetType() == cmStateEnums::OBJECT_LIBRARY) {
std::ostringstream e;
e << "Target \"" << target
<< "\" is an OBJECT library "
"that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands.";
- this->IssueMessage(cmake::FATAL_ERROR, e.str());
- return;
+ this->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return nullptr;
}
- if (ti->second.GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (t->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
std::ostringstream e;
e << "Target \"" << target
<< "\" is an INTERFACE library "
"that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands.";
- this->IssueMessage(cmake::FATAL_ERROR, e.str());
- return;
+ this->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return nullptr;
}
- // Always create the byproduct sources and mark them generated.
- for (std::vector<std::string>::const_iterator o = byproducts.begin();
- o != byproducts.end(); ++o) {
- if (cmSourceFile* out = this->GetOrCreateSource(*o, true)) {
- out->SetProperty("GENERATED", "1");
- }
+ return t;
+}
+
+cmTarget* cmMakefile::AddCustomCommandToTarget(
+ const std::string& target, const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines, cmCustomCommandType type,
+ const char* comment, const char* workingDir, bool escapeOldStyle,
+ bool uses_terminal, const std::string& depfile, const std::string& job_pool,
+ bool command_expand_lists, cmObjectLibraryCommands objLibCommands)
+{
+ cmTarget* t = this->GetCustomCommandTarget(target, objLibCommands);
+
+ // Validate custom commands.
+ if (!t || !this->ValidateCustomCommand(commandLines)) {
+ return t;
}
+ // Always create the byproduct sources and mark them generated.
+ this->CreateGeneratedSources(byproducts);
+
+ this->CommitCustomCommandToTarget(
+ t, byproducts, depends, commandLines, type, comment, workingDir,
+ escapeOldStyle, uses_terminal, depfile, job_pool, command_expand_lists);
+
+ return t;
+}
+
+void cmMakefile::CommitCustomCommandToTarget(
+ cmTarget* target, const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines, cmCustomCommandType type,
+ const char* comment, const char* workingDir, bool escapeOldStyle,
+ bool uses_terminal, const std::string& depfile, const std::string& job_pool,
+ bool command_expand_lists)
+{
// Add the command to the appropriate build step for the target.
std::vector<std::string> no_output;
cmCustomCommand cc(this, no_output, byproducts, depends, commandLines,
@@ -756,47 +946,82 @@ void cmMakefile::AddCustomCommandToTarget(
cc.SetUsesTerminal(uses_terminal);
cc.SetCommandExpandLists(command_expand_lists);
cc.SetDepfile(depfile);
+ cc.SetJobPool(job_pool);
switch (type) {
- case cmTarget::PRE_BUILD:
- ti->second.AddPreBuildCommand(cc);
+ case cmCustomCommandType::PRE_BUILD:
+ target->AddPreBuildCommand(std::move(cc));
break;
- case cmTarget::PRE_LINK:
- ti->second.AddPreLinkCommand(cc);
+ case cmCustomCommandType::PRE_LINK:
+ target->AddPreLinkCommand(std::move(cc));
break;
- case cmTarget::POST_BUILD:
- ti->second.AddPostBuildCommand(cc);
+ case cmCustomCommandType::POST_BUILD:
+ target->AddPostBuildCommand(std::move(cc));
break;
}
+
+ this->AddTargetByproducts(target, byproducts);
+}
+
+cmSourceFile* cmMakefile::AddCustomCommandToOutput(
+ const std::string& output, const std::vector<std::string>& depends,
+ const std::string& main_dependency, const cmCustomCommandLines& commandLines,
+ const char* comment, const char* workingDir, bool replace,
+ bool escapeOldStyle, bool uses_terminal, bool command_expand_lists,
+ const std::string& depfile, const std::string& job_pool)
+{
+ std::vector<std::string> outputs;
+ outputs.push_back(output);
+ std::vector<std::string> no_byproducts;
+ cmImplicitDependsList no_implicit_depends;
+ return this->AddCustomCommandToOutput(
+ outputs, no_byproducts, depends, main_dependency, no_implicit_depends,
+ commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal,
+ command_expand_lists, depfile, job_pool);
}
cmSourceFile* cmMakefile::AddCustomCommandToOutput(
const std::vector<std::string>& outputs,
const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends, const std::string& main_dependency,
+ const cmImplicitDependsList& implicit_depends,
const cmCustomCommandLines& commandLines, const char* comment,
const char* workingDir, bool replace, bool escapeOldStyle,
- bool uses_terminal, bool command_expand_lists, const std::string& depfile)
+ bool uses_terminal, bool command_expand_lists, const std::string& depfile,
+ const std::string& job_pool)
{
// Make sure there is at least one output.
if (outputs.empty()) {
cmSystemTools::Error("Attempt to add a custom rule with no output!");
- return CM_NULLPTR;
+ return nullptr;
}
- // Validate custom commands. TODO: More strict?
- for (cmCustomCommandLines::const_iterator i = commandLines.begin();
- i != commandLines.end(); ++i) {
- cmCustomCommandLine const& cl = *i;
- if (!cl.empty() && !cl[0].empty() && cl[0][0] == '"') {
- std::ostringstream e;
- e << "COMMAND may not contain literal quotes:\n " << cl[0] << "\n";
- this->IssueMessage(cmake::FATAL_ERROR, e.str());
- return CM_NULLPTR;
- }
+ // Validate custom commands.
+ if (!this->ValidateCustomCommand(commandLines)) {
+ return nullptr;
}
+ // Always create the output sources and mark them generated.
+ this->CreateGeneratedSources(outputs);
+ this->CreateGeneratedSources(byproducts);
+
+ return this->CommitCustomCommandToOutput(
+ outputs, byproducts, depends, main_dependency, implicit_depends,
+ commandLines, comment, workingDir, replace, escapeOldStyle, uses_terminal,
+ command_expand_lists, depfile, job_pool);
+}
+
+cmSourceFile* cmMakefile::CommitCustomCommandToOutput(
+ const std::vector<std::string>& outputs,
+ const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends, const std::string& main_dependency,
+ const cmImplicitDependsList& implicit_depends,
+ const cmCustomCommandLines& commandLines, const char* comment,
+ const char* workingDir, bool replace, bool escapeOldStyle,
+ bool uses_terminal, bool command_expand_lists, const std::string& depfile,
+ const std::string& job_pool)
+{
// Choose a source file on which to store the custom command.
- cmSourceFile* file = CM_NULLPTR;
+ cmSourceFile* file = nullptr;
if (!commandLines.empty() && !main_dependency.empty()) {
// The main dependency was specified. Use it unless a different
// custom command already used it.
@@ -810,7 +1035,7 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput(
}
// The existing custom command is different. We need to
// generate a rule file for this new command.
- file = CM_NULLPTR;
+ file = nullptr;
} else if (!file) {
file = this->CreateSource(main_dependency);
}
@@ -824,38 +1049,24 @@ 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()) {
- cmSystemTools::Error("Attempt to add a custom rule to output \"",
- outName.c_str(),
- "\" which already has a custom rule.");
+ cmSystemTools::Error("Attempt to add a custom rule to output \"" +
+ outName + "\" which already has a custom rule.");
}
return file;
}
// 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::vector<std::string>::const_iterator o = outputs.begin();
- o != outputs.end(); ++o) {
- if (cmSourceFile* out = this->GetOrCreateSource(*o, true)) {
- out->SetProperty("GENERATED", "1");
- }
- }
- for (std::vector<std::string>::const_iterator o = byproducts.begin();
- o != byproducts.end(); ++o) {
- if (cmSourceFile* out = this->GetOrCreateSource(*o, true)) {
- out->SetProperty("GENERATED", "1");
- }
- }
-
// Attach the custom command to the file.
if (file) {
// Construct a complete list of dependencies.
@@ -864,60 +1075,20 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput(
depends2.push_back(main_dependency);
}
- cmCustomCommand* cc = new cmCustomCommand(
+ std::unique_ptr<cmCustomCommand> cc = cm::make_unique<cmCustomCommand>(
this, outputs, byproducts, depends2, commandLines, comment, workingDir);
cc->SetEscapeOldStyle(escapeOldStyle);
cc->SetEscapeAllowMakeVars(true);
+ cc->SetImplicitDepends(implicit_depends);
cc->SetUsesTerminal(uses_terminal);
cc->SetCommandExpandLists(command_expand_lists);
cc->SetDepfile(depfile);
- file->SetCustomCommand(cc);
- this->UpdateOutputToSourceMap(outputs, file);
- }
- return file;
-}
+ cc->SetJobPool(job_pool);
+ file->SetCustomCommand(std::move(cc));
-void cmMakefile::UpdateOutputToSourceMap(
- std::vector<std::string> const& outputs, cmSourceFile* source)
-{
- for (std::vector<std::string>::const_iterator o = outputs.begin();
- o != outputs.end(); ++o) {
- this->UpdateOutputToSourceMap(*o, source);
+ this->AddSourceOutputs(file, outputs, byproducts);
}
-}
-
-void cmMakefile::UpdateOutputToSourceMap(std::string const& output,
- cmSourceFile* source)
-{
- OutputToSourceMap::iterator i = this->OutputToSource.find(output);
- if (i != this->OutputToSource.end()) {
- // Multiple custom commands produce the same output but may
- // be attached to a different source file (MAIN_DEPENDENCY).
- // LinearGetSourceFileWithOutput would return the first one,
- // so keep the mapping for the first one.
- //
- // TODO: Warn the user about this case. However, the VS 8 generator
- // triggers it for separate generate.stamp rules in ZERO_CHECK and
- // individual targets.
- return;
- }
- this->OutputToSource[output] = source;
-}
-
-cmSourceFile* cmMakefile::AddCustomCommandToOutput(
- const std::string& output, const std::vector<std::string>& depends,
- const std::string& main_dependency, const cmCustomCommandLines& commandLines,
- const char* comment, const char* workingDir, bool replace,
- bool escapeOldStyle, bool uses_terminal, bool command_expand_lists,
- const std::string& depfile)
-{
- std::vector<std::string> outputs;
- outputs.push_back(output);
- std::vector<std::string> no_byproducts;
- return this->AddCustomCommandToOutput(
- outputs, no_byproducts, depends, main_dependency, commandLines, comment,
- workingDir, replace, escapeOldStyle, uses_terminal, command_expand_lists,
- depfile);
+ return file;
}
void cmMakefile::AddCustomCommandOldStyle(
@@ -932,198 +1103,210 @@ void cmMakefile::AddCustomCommandOldStyle(
// same then it added a post-build rule to the target. Preserve
// this behavior.
std::vector<std::string> no_byproducts;
- this->AddCustomCommandToTarget(target, no_byproducts, depends,
- commandLines, cmTarget::POST_BUILD, comment,
- CM_NULLPTR);
+ this->AddCustomCommandToTarget(
+ target, no_byproducts, depends, commandLines,
+ cmCustomCommandType::POST_BUILD, comment, nullptr);
return;
}
- // Each output must get its own copy of this rule.
- cmsys::RegularExpression sourceFiles("\\.(C|M|c|c\\+\\+|cc|cpp|cxx|m|mm|"
- "rc|def|r|odl|idl|hpj|bat|h|h\\+\\+|"
- "hm|hpp|hxx|in|txx|inl)$");
- for (std::vector<std::string>::const_iterator oi = outputs.begin();
- oi != outputs.end(); ++oi) {
- // Get the name of this output.
- const char* output = oi->c_str();
- cmSourceFile* sf;
-
- // Choose whether to use a main dependency.
- if (sourceFiles.find(source)) {
- // The source looks like a real file. Use it as the main dependency.
- sf = this->AddCustomCommandToOutput(output, depends, source,
- commandLines, comment, CM_NULLPTR);
- } else {
- // The source may not be a real file. Do not use a main dependency.
- std::string no_main_dependency;
- std::vector<std::string> depends2 = depends;
- depends2.push_back(source);
- sf = this->AddCustomCommandToOutput(output, depends2, no_main_dependency,
- commandLines, comment, CM_NULLPTR);
- }
+ auto ti = this->Targets.find(target);
+ cmTarget* t = ti != this->Targets.end() ? &ti->second : nullptr;
+ auto addRuleFileToTarget = [=](cmSourceFile* sf) {
// If the rule was added to the source (and not a .rule file),
// then add the source to the target to make sure the rule is
// included.
- if (sf && !sf->GetPropertyAsBool("__CMAKE_RULE")) {
- cmTargets::iterator ti = this->Targets.find(target);
- if (ti != this->Targets.end()) {
- ti->second.AddSource(sf->GetFullPath());
+ if (!sf->GetPropertyAsBool("__CMAKE_RULE")) {
+ if (t) {
+ t->AddSource(sf->ResolveFullPath());
} else {
cmSystemTools::Error("Attempt to add a custom rule to a target "
- "that does not exist yet for target ",
- target.c_str());
- return;
+ "that does not exist yet for target " +
+ target);
+ }
+ }
+ };
+
+ // Each output must get its own copy of this rule.
+ 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)$");
+
+ // Choose whether to use a main dependency.
+ if (sourceFiles.find(source)) {
+ // The source looks like a real file. Use it as the main dependency.
+ for (std::string const& output : outputs) {
+ cmSourceFile* sf = this->AddCustomCommandToOutput(
+ output, depends, source, commandLines, comment, nullptr);
+ if (sf) {
+ addRuleFileToTarget(sf);
+ }
+ }
+ } else {
+ std::string no_main_dependency;
+ std::vector<std::string> depends2 = depends;
+ depends2.push_back(source);
+
+ // The source may not be a real file. Do not use a main dependency.
+ for (std::string const& output : outputs) {
+ cmSourceFile* sf = this->AddCustomCommandToOutput(
+ output, depends2, no_main_dependency, commandLines, comment, nullptr);
+ if (sf) {
+ addRuleFileToTarget(sf);
}
}
}
}
-cmTarget* cmMakefile::AddUtilityCommand(
- const std::string& utilityName, 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)
+bool cmMakefile::AppendCustomCommandToOutput(
+ const std::string& output, const std::vector<std::string>& depends,
+ const cmImplicitDependsList& implicit_depends,
+ const cmCustomCommandLines& commandLines)
{
- // Construct the command line for the custom command.
- cmCustomCommandLine commandLine;
- commandLine.push_back(command);
- if (arg1) {
- commandLine.push_back(arg1);
- }
- if (arg2) {
- commandLine.push_back(arg2);
- }
- if (arg3) {
- commandLine.push_back(arg3);
+ // Check as good as we can if there will be a command for this output.
+ if (!this->MightHaveCustomCommand(output)) {
+ return false;
}
- if (arg4) {
- commandLine.push_back(arg4);
+
+ // Validate custom commands.
+ if (this->ValidateCustomCommand(commandLines)) {
+ // Add command factory to allow generator expressions in output.
+ this->CommitAppendCustomCommandToOutput(output, depends, implicit_depends,
+ commandLines);
}
- cmCustomCommandLines commandLines;
- commandLines.push_back(commandLine);
- // Call the real signature of this method.
- return this->AddUtilityCommand(utilityName, excludeFromAll, workingDirectory,
- depends, commandLines);
+ return true;
+}
+
+void cmMakefile::CommitAppendCustomCommandToOutput(
+ const std::string& output, const std::vector<std::string>& depends,
+ const cmImplicitDependsList& implicit_depends,
+ const cmCustomCommandLines& commandLines)
+{
+ // Lookup an existing command.
+ if (cmSourceFile* sf = this->GetSourceFileWithOutput(output)) {
+ if (cmCustomCommand* cc = sf->GetCustomCommand()) {
+ cc->AppendCommands(commandLines);
+ cc->AppendDepends(depends);
+ cc->AppendImplicitDepends(implicit_depends);
+ }
+ }
}
-cmTarget* cmMakefile::AddUtilityCommand(
- const std::string& utilityName, 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)
+cmUtilityOutput cmMakefile::GetUtilityOutput(cmTarget* target)
{
- std::vector<std::string> no_byproducts;
- return this->AddUtilityCommand(utilityName, excludeFromAll, workingDirectory,
- no_byproducts, depends, commandLines,
- escapeOldStyle, comment, uses_terminal,
- command_expand_lists);
+ std::string force = cmStrCat(this->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/", target->GetName());
+ std::string forceCMP0049 = target->GetSourceCMP0049(force);
+ {
+ cmSourceFile* sf = nullptr;
+ if (!forceCMP0049.empty()) {
+ sf = this->GetOrCreateSource(forceCMP0049, false,
+ cmSourceFileLocationKind::Known);
+ }
+ // The output is not actually created so mark it symbolic.
+ if (sf) {
+ sf->SetProperty("SYMBOLIC", "1");
+ } else {
+ cmSystemTools::Error("Could not get source file entry for " + force);
+ }
+ }
+ return { std::move(force), std::move(forceCMP0049) };
}
cmTarget* cmMakefile::AddUtilityCommand(
- const std::string& utilityName, bool excludeFromAll,
+ const std::string& utilityName, cmCommandOrigin origin, bool excludeFromAll,
const char* workingDirectory, const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines, bool escapeOldStyle,
- const char* comment, bool uses_terminal, bool command_expand_lists)
+ const char* comment, bool uses_terminal, bool command_expand_lists,
+ const std::string& job_pool)
{
- // Create a target instance for this utility.
- cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName);
- if (excludeFromAll) {
- target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
+ cmTarget* target =
+ this->AddNewUtilityTarget(utilityName, origin, excludeFromAll);
+
+ // Validate custom commands.
+ if ((commandLines.empty() && depends.empty()) ||
+ !this->ValidateCustomCommand(commandLines)) {
+ return target;
}
+
+ // Get the output name of the utility target and mark it generated.
+ cmUtilityOutput force = this->GetUtilityOutput(target);
+ this->GetOrCreateGeneratedSource(force.Name);
+
+ // Always create the byproduct sources and mark them generated.
+ this->CreateGeneratedSources(byproducts);
+
if (!comment) {
// Use an empty comment to avoid generation of default comment.
comment = "";
}
- // Store the custom command in the target.
- if (!commandLines.empty() || !depends.empty()) {
- std::string force = this->GetCurrentBinaryDirectory();
- force += cmake::GetCMakeFilesDirectory();
- force += "/";
- force += utilityName;
- std::vector<std::string> forced;
- forced.push_back(force);
- std::string no_main_dependency;
- bool no_replace = false;
- this->AddCustomCommandToOutput(
- forced, byproducts, depends, no_main_dependency, commandLines, comment,
- workingDirectory, no_replace, escapeOldStyle, uses_terminal,
- command_expand_lists);
- cmSourceFile* sf = target->AddSourceCMP0049(force);
-
- // The output is not actually created so mark it symbolic.
- if (sf) {
- sf->SetProperty("SYMBOLIC", "1");
- } else {
- cmSystemTools::Error("Could not get source file entry for ",
- force.c_str());
- }
+ this->CommitUtilityCommand(target, force, workingDirectory, byproducts,
+ depends, commandLines, escapeOldStyle, comment,
+ uses_terminal, command_expand_lists, job_pool);
- // Always create the byproduct sources and mark them generated.
- for (std::vector<std::string>::const_iterator o = byproducts.begin();
- o != byproducts.end(); ++o) {
- if (cmSourceFile* out = this->GetOrCreateSource(*o, true)) {
- out->SetProperty("GENERATED", "1");
- }
- }
- }
return target;
}
-void cmMakefile::AddDefineFlag(const char* flag)
+void cmMakefile::CommitUtilityCommand(
+ cmTarget* target, const cmUtilityOutput& force, const char* workingDirectory,
+ const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines, bool escapeOldStyle,
+ const char* comment, bool uses_terminal, bool command_expand_lists,
+ const std::string& job_pool)
{
- if (!flag) {
- return;
+ std::vector<std::string> forced;
+ forced.push_back(force.Name);
+ std::string no_main_dependency;
+ cmImplicitDependsList no_implicit_depends;
+ bool no_replace = false;
+ cmSourceFile* sf = this->AddCustomCommandToOutput(
+ forced, byproducts, depends, no_main_dependency, no_implicit_depends,
+ commandLines, comment, workingDirectory, no_replace, escapeOldStyle,
+ uses_terminal, command_expand_lists, /*depfile=*/"", job_pool);
+ if (!force.NameCMP0049.empty()) {
+ target->AddSource(force.NameCMP0049);
}
-
- // Update the string used for the old DEFINITIONS property.
- this->AddDefineFlag(flag, this->DefineFlagsOrig);
-
- // If this is really a definition, update COMPILE_DEFINITIONS.
- if (this->ParseDefineFlag(flag, false)) {
- return;
+ if (sf) {
+ this->AddTargetByproducts(target, byproducts);
}
-
- // Add this flag that does not look like a definition.
- this->AddDefineFlag(flag, this->DefineFlags);
}
-void cmMakefile::AddDefineFlag(const char* flag, std::string& dflags)
+static void s_AddDefineFlag(std::string const& flag, std::string& dflags)
{
// remove any \n\r
std::string::size_type initSize = dflags.size();
- dflags += std::string(" ") + flag;
+ dflags += ' ';
+ dflags += flag;
std::string::iterator flagStart = dflags.begin() + initSize + 1;
std::replace(flagStart, dflags.end(), '\n', ' ');
std::replace(flagStart, dflags.end(), '\r', ' ');
}
-void cmMakefile::RemoveDefineFlag(const char* flag)
+void cmMakefile::AddDefineFlag(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;
}
// Update the string used for the old DEFINITIONS property.
- this->RemoveDefineFlag(flag, len, this->DefineFlagsOrig);
+ s_AddDefineFlag(flag, this->DefineFlagsOrig);
// If this is really a definition, update COMPILE_DEFINITIONS.
- if (this->ParseDefineFlag(flag, true)) {
+ if (this->ParseDefineFlag(flag, false)) {
return;
}
- // Remove this flag that does not look like a definition.
- this->RemoveDefineFlag(flag, len, this->DefineFlags);
+ // Add this flag that does not look like a definition.
+ s_AddDefineFlag(flag, this->DefineFlags);
}
-void cmMakefile::RemoveDefineFlag(const char* flag, std::string::size_type len,
- std::string& dflags)
+static void s_RemoveDefineFlag(std::string const& flag, std::string& dflags)
{
+ std::string::size_type const len = flag.length();
// Remove all instances of the flag that are surrounded by
// whitespace or the beginning/end of the string.
for (std::string::size_type lpos = dflags.find(flag, 0);
@@ -1138,9 +1321,50 @@ void cmMakefile::RemoveDefineFlag(const char* flag, std::string::size_type len,
}
}
-void cmMakefile::AddCompileOption(const char* option)
+void cmMakefile::RemoveDefineFlag(std::string const& flag)
+{
+ // Check the length of the flag to remove.
+ if (flag.empty()) {
+ return;
+ }
+
+ // Update the string used for the old DEFINITIONS property.
+ s_RemoveDefineFlag(flag, this->DefineFlagsOrig);
+
+ // If this is really a definition, update COMPILE_DEFINITIONS.
+ if (this->ParseDefineFlag(flag, true)) {
+ return;
+ }
+
+ // Remove this flag that does not look like a definition.
+ s_RemoveDefineFlag(flag, this->DefineFlags);
+}
+
+void cmMakefile::AddCompileDefinition(std::string const& option)
+{
+ this->AppendProperty("COMPILE_DEFINITIONS", option.c_str());
+}
+
+void cmMakefile::AddCompileOption(std::string const& option)
+{
+ this->AppendProperty("COMPILE_OPTIONS", option.c_str());
+}
+
+void cmMakefile::AddLinkOption(std::string const& option)
{
- this->AppendProperty("COMPILE_OPTIONS", option);
+ this->AppendProperty("LINK_OPTIONS", option.c_str());
+}
+
+void cmMakefile::AddLinkDirectory(std::string const& directory, bool before)
+{
+ cmListFileBacktrace lfbt = this->GetBacktrace();
+ if (before) {
+ this->StateSnapshot.GetDirectory().PrependLinkDirectoriesEntry(directory,
+ lfbt);
+ } else {
+ this->StateSnapshot.GetDirectory().AppendLinkDirectoriesEntry(directory,
+ lfbt);
+ }
}
bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)
@@ -1149,18 +1373,18 @@ 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:
- this->IssueMessage(cmake::AUTHOR_WARNING,
+ this->IssueMessage(MessageType::AUTHOR_WARNING,
cmPolicies::GetPolicyWarning(cmPolicies::CMP0005));
CM_FALLTHROUGH;
case cmPolicies::OLD:
@@ -1170,7 +1394,7 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
this->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0005));
return false;
case cmPolicies::NEW:
@@ -1186,13 +1410,11 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)
if (remove) {
if (const char* cdefs = this->GetProperty("COMPILE_DEFINITIONS")) {
// Expand the list.
- std::vector<std::string> defs;
- cmSystemTools::ExpandListArgument(cdefs, defs);
+ std::vector<std::string> defs = cmExpandedList(cdefs);
// Recompose the list without the definition.
- std::vector<std::string>::const_iterator defEnd =
- std::remove(defs.begin(), defs.end(), define);
- std::vector<std::string>::const_iterator defBegin = defs.begin();
+ auto defEnd = std::remove(defs.begin(), defs.end(), define);
+ auto defBegin = defs.begin();
std::string ndefs = cmJoin(cmMakeRange(defBegin, defEnd), ";");
// Store the new list.
@@ -1227,22 +1449,20 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent)
parent->GetProperty("COMPILE_DEFINITIONS"));
std::vector<std::string> configs;
this->GetConfigurations(configs);
- for (std::vector<std::string>::const_iterator ci = configs.begin();
- ci != configs.end(); ++ci) {
- std::string defPropName = "COMPILE_DEFINITIONS_";
- defPropName += cmSystemTools::UpperCase(*ci);
+ for (std::string const& config : configs) {
+ std::string defPropName =
+ cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config));
const char* prop = parent->GetProperty(defPropName);
this->SetProperty(defPropName, prop);
}
}
+ // labels
+ this->SetProperty("LABELS", parent->GetProperty("LABELS"));
+
// link libraries
this->SetProperty("LINK_LIBRARIES", parent->GetProperty("LINK_LIBRARIES"));
- // link directories
- this->SetProperty("LINK_DIRECTORIES",
- parent->GetProperty("LINK_DIRECTORIES"));
-
// the initial project name
this->StateSnapshot.SetProjectName(parent->StateSnapshot.GetProjectName());
@@ -1251,6 +1471,9 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent)
// Imported targets.
this->ImportedTargets = parent->ImportedTargets;
+
+ // Recursion depth.
+ this->RecursionDepth = parent->RecursionDepth;
}
void cmMakefile::PushFunctionScope(std::string const& fileName,
@@ -1262,7 +1485,7 @@ void cmMakefile::PushFunctionScope(std::string const& fileName,
this->PushLoopBlockBarrier();
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
this->GetGlobalGenerator()->GetFileLockPool().PushFunctionScope();
#endif
@@ -1279,7 +1502,7 @@ void cmMakefile::PopFunctionScope(bool reportError)
this->PopFunctionBlockerBarrier(reportError);
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
this->GetGlobalGenerator()->GetFileLockPool().PopFunctionScope();
#endif
@@ -1321,8 +1544,8 @@ public:
, ReportError(true)
{
std::string currentStart =
- this->Makefile->StateSnapshot.GetDirectory().GetCurrentSource();
- currentStart += "/CMakeLists.txt";
+ cmStrCat(this->Makefile->StateSnapshot.GetDirectory().GetCurrentSource(),
+ "/CMakeLists.txt");
this->Makefile->StateSnapshot.SetListFile(currentStart);
this->Makefile->StateSnapshot =
this->Makefile->StateSnapshot.GetState()->CreatePolicyScopeSnapshot(
@@ -1334,7 +1557,7 @@ public:
this->Snapshot = this->GG->GetCMakeInstance()->GetCurrentSnapshot();
this->GG->GetCMakeInstance()->SetCurrentSnapshot(this->Snapshot);
this->GG->SetCurrentMakefile(mf);
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
this->GG->GetFileLockPool().PushFileScope();
#endif
}
@@ -1343,7 +1566,7 @@ public:
{
this->Makefile->PopFunctionBlockerBarrier(this->ReportError);
this->Makefile->PopSnapshot(this->ReportError);
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
this->GG->GetFileLockPool().PopFileScope();
#endif
this->GG->SetCurrentMakefile(this->CurrentMakefile);
@@ -1352,6 +1575,9 @@ public:
void Quiet() { this->ReportError = false; }
+ BuildsystemFileScope(const BuildsystemFileScope&) = delete;
+ BuildsystemFileScope& operator=(const BuildsystemFileScope&) = delete;
+
private:
cmMakefile* Makefile;
cmGlobalGenerator* GG;
@@ -1362,9 +1588,8 @@ private:
void cmMakefile::Configure()
{
- std::string currentStart =
- this->StateSnapshot.GetDirectory().GetCurrentSource();
- currentStart += "/CMakeLists.txt";
+ std::string currentStart = cmStrCat(
+ this->StateSnapshot.GetDirectory().GetCurrentSource(), "/CMakeLists.txt");
// Add the bottom of all backtraces within this directory.
// We will never pop this scope because it should be available
@@ -1374,12 +1599,12 @@ void cmMakefile::Configure()
BuildsystemFileScope scope(this);
// make sure the CMakeFiles dir is there
- std::string filesDir = this->StateSnapshot.GetDirectory().GetCurrentBinary();
- filesDir += cmake::GetCMakeFilesDirectory();
- cmSystemTools::MakeDirectory(filesDir.c_str());
+ std::string filesDir = cmStrCat(
+ this->StateSnapshot.GetDirectory().GetCurrentBinary(), "/CMakeFiles");
+ cmSystemTools::MakeDirectory(filesDir);
- assert(cmSystemTools::FileExists(currentStart.c_str(), true));
- this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentStart.c_str());
+ assert(cmSystemTools::FileExists(currentStart, true));
+ this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentStart);
cmListFile listFile;
if (!listFile.ParseFile(currentStart.c_str(), this->GetMessenger(),
@@ -1389,10 +1614,8 @@ void cmMakefile::Configure()
if (this->IsRootMakefile()) {
bool hasVersion = false;
// search for the right policy command
- for (std::vector<cmListFileFunction>::iterator i =
- listFile.Functions.begin();
- i != listFile.Functions.end(); ++i) {
- if (cmSystemTools::LowerCase(i->Name) == "cmake_minimum_required") {
+ for (cmListFileFunction const& func : listFile.Functions) {
+ if (func.Name.Lower == "cmake_minimum_required") {
hasVersion = true;
break;
}
@@ -1418,11 +1641,8 @@ void cmMakefile::Configure()
allowedCommands.insert("option");
allowedCommands.insert("message");
isProblem = false;
- for (std::vector<cmListFileFunction>::iterator i =
- listFile.Functions.begin();
- i != listFile.Functions.end(); ++i) {
- std::string name = cmSystemTools::LowerCase(i->Name);
- if (allowedCommands.find(name) == allowedCommands.end()) {
+ for (cmListFileFunction const& func : listFile.Functions) {
+ if (!cmContains(allowedCommands, func.Name.Lower)) {
isProblem = true;
break;
}
@@ -1435,25 +1655,35 @@ void cmMakefile::Configure()
this->SetCheckCMP0000(true);
// Implicitly set the version for the user.
- this->SetPolicyVersion("2.4");
+ this->SetPolicyVersion("2.4", std::string());
}
}
bool hasProject = false;
// search for a project command
- for (std::vector<cmListFileFunction>::iterator i =
- listFile.Functions.begin();
- i != listFile.Functions.end(); ++i) {
- if (cmSystemTools::LowerCase(i->Name) == "project") {
+ for (cmListFileFunction const& func : listFile.Functions) {
+ if (func.Name.Lower == "project") {
hasProject = true;
break;
}
}
// if no project command is found, add one
if (!hasProject) {
+ this->GetCMakeInstance()->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ "No project() command is present. The top-level CMakeLists.txt "
+ "file must contain a literal, direct call to the project() command. "
+ "Add a line of code such as\n"
+ " project(ProjectName)\n"
+ "near the top of the file, but after cmake_minimum_required().\n"
+ "CMake is pretending there is a \"project(Project)\" command on "
+ "the first line.",
+ this->Backtrace);
cmListFileFunction project;
- project.Name = "PROJECT";
- cmListFileArgument prj("Project", cmListFileArgument::Unquoted, 0);
- project.Arguments.push_back(prj);
+ project.Name.Lower = "project";
+ project.Arguments.emplace_back("Project", cmListFileArgument::Unquoted,
+ 0);
+ project.Arguments.emplace_back("__CMAKE_INJECTED_PROJECT_COMMAND__",
+ cmListFileArgument::Unquoted, 0);
listFile.Functions.insert(listFile.Functions.begin(), project);
}
}
@@ -1467,7 +1697,7 @@ void cmMakefile::Configure()
std::vector<cmMakefile*> subdirs = this->UnConfiguredDirectories;
// for each subdir recurse
- std::vector<cmMakefile*>::iterator sdi = subdirs.begin();
+ auto sdi = subdirs.begin();
for (; sdi != subdirs.end(); ++sdi) {
(*sdi)->StateSnapshot.InitializeFromParent_ForSubdirsCommand();
this->ConfigureSubDirectory(*sdi);
@@ -1481,9 +1711,8 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf)
mf->InitializeFromParent(this);
std::string currentStart = mf->GetCurrentSourceDirectory();
if (this->GetCMakeInstance()->GetDebugOutput()) {
- std::string msg = " Entering ";
- msg += currentStart;
- cmSystemTools::Message(msg.c_str());
+ std::string msg = cmStrCat(" Entering ", currentStart);
+ cmSystemTools::Message(msg);
}
std::string const currentStartFile = currentStart + "/CMakeLists.txt";
@@ -1506,7 +1735,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf)
<< "\n"
<< cmPolicies::GetPolicyWarning(cmPolicies::CMP0014);
/* clang-format on */
- this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ this->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
case cmPolicies::OLD:
// OLD behavior does not warn.
break;
@@ -1516,7 +1745,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf)
CM_FALLTHROUGH;
case cmPolicies::NEW:
// NEW behavior prints the error.
- this->IssueMessage(cmake::FATAL_ERROR, e.str());
+ this->IssueMessage(MessageType::FATAL_ERROR, e.str());
}
return;
}
@@ -1524,9 +1753,9 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf)
mf->Configure();
if (this->GetCMakeInstance()->GetDebugOutput()) {
- std::string msg = " Returning to ";
- msg += this->GetCurrentSourceDirectory();
- cmSystemTools::Message(msg.c_str());
+ std::string msg =
+ cmStrCat(" Returning to ", this->GetCurrentSourceDirectory());
+ cmSystemTools::Message(msg);
}
}
@@ -1545,7 +1774,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);
@@ -1559,14 +1788,17 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath,
} else {
this->UnConfiguredDirectories.push_back(subMf);
}
+
+ this->AddInstallGenerator(new cmInstallSubdirectoryGenerator(
+ subMf, binPath.c_str(), excludeFromAll));
}
-const char* cmMakefile::GetCurrentSourceDirectory() const
+const std::string& cmMakefile::GetCurrentSourceDirectory() const
{
return this->StateSnapshot.GetDirectory().GetCurrentSource();
}
-const char* cmMakefile::GetCurrentBinaryDirectory() const
+const std::string& cmMakefile::GetCurrentBinaryDirectory() const
{
return this->StateSnapshot.GetDirectory().GetCurrentBinary();
}
@@ -1575,9 +1807,8 @@ std::vector<cmTarget*> cmMakefile::GetImportedTargets() const
{
std::vector<cmTarget*> tgts;
tgts.reserve(this->ImportedTargets.size());
- for (TargetMap::const_iterator it = this->ImportedTargets.begin();
- it != this->ImportedTargets.end(); ++it) {
- tgts.push_back(it->second);
+ for (auto const& impTarget : this->ImportedTargets) {
+ tgts.push_back(impTarget.second);
}
return tgts;
}
@@ -1600,9 +1831,8 @@ void cmMakefile::AddIncludeDirectories(const std::vector<std::string>& incs,
}
// Property on each target:
- for (cmTargets::iterator l = this->Targets.begin(); l != this->Targets.end();
- ++l) {
- cmTarget& t = l->second;
+ for (auto& target : this->Targets) {
+ cmTarget& t = target.second;
t.InsertInclude(entryString, lfbt, before);
}
}
@@ -1615,58 +1845,60 @@ void cmMakefile::AddSystemIncludeDirectories(const std::set<std::string>& incs)
this->SystemIncludeDirectories.insert(incs.begin(), incs.end());
- for (cmTargets::iterator l = this->Targets.begin(); l != this->Targets.end();
- ++l) {
- cmTarget& t = l->second;
+ for (auto& target : this->Targets) {
+ cmTarget& t = target.second;
t.AddSystemIncludeDirectories(incs);
}
}
-void cmMakefile::AddDefinition(const std::string& name, const char* value)
+void cmMakefile::AddDefinition(const std::string& name, cm::string_view value)
{
- if (!value) {
- return;
- }
-
if (this->VariableInitialized(name)) {
this->LogUnused("changing definition", name);
}
this->StateSnapshot.SetDefinition(name, value);
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
cmVariableWatch* vv = this->GetVariableWatch();
if (vv) {
vv->VariableAccessed(name, cmVariableWatch::VARIABLE_MODIFIED_ACCESS,
- value, this);
+ value.data(), this);
}
#endif
}
+void cmMakefile::AddDefinitionBool(const std::string& name, bool value)
+{
+ this->AddDefinition(name, value ? "ON" : "OFF");
+}
+
void cmMakefile::AddCacheDefinition(const std::string& name, const char* value,
const char* doc,
cmStateEnums::CacheEntryType type,
bool force)
{
- const char* existingValue = this->GetState()->GetInitializedCacheValue(name);
+ const std::string* existingValue =
+ this->GetState()->GetInitializedCacheValue(name);
// must be outside the following if() to keep it alive long enough
std::string nvalue;
- if (existingValue && (this->GetState()->GetCacheEntryType(name) ==
- cmStateEnums::UNINITIALIZED)) {
+ if (existingValue &&
+ (this->GetState()->GetCacheEntryType(name) ==
+ cmStateEnums::UNINITIALIZED)) {
// if this is not a force, then use the value from the cache
// if it is a force, then use the value being passed in
if (!force) {
- value = existingValue;
+ value = existingValue->c_str();
}
if (type == cmStateEnums::PATH || type == cmStateEnums::FILEPATH) {
std::vector<std::string>::size_type cc;
std::vector<std::string> files;
nvalue = value ? value : "";
- cmSystemTools::ExpandListArgument(nvalue, files);
- nvalue = "";
+ cmExpandList(nvalue, files);
+ nvalue.clear();
for (cc = 0; cc < files.size(); cc++) {
- if (!cmSystemTools::IsOff(files[cc].c_str())) {
+ if (!cmIsOff(files[cc])) {
files[cc] = cmSystemTools::CollapseFullPath(files[cc]);
}
if (cc > 0) {
@@ -1676,7 +1908,7 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value,
}
this->GetCMakeInstance()->AddCacheEntry(name, nvalue.c_str(), doc, type);
- nvalue = this->GetState()->GetInitializedCacheValue(name);
+ nvalue = *this->GetState()->GetInitializedCacheValue(name);
value = nvalue.c_str();
}
}
@@ -1685,32 +1917,13 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value,
this->StateSnapshot.RemoveDefinition(name);
}
-void cmMakefile::AddDefinition(const std::string& name, bool value)
-{
- if (this->VariableInitialized(name)) {
- this->LogUnused("changing definition", name);
- }
-
- this->StateSnapshot.SetDefinition(name, value ? "ON" : "OFF");
-
-#ifdef CMAKE_BUILD_WITH_CMAKE
- cmVariableWatch* vv = this->GetVariableWatch();
- if (vv) {
- vv->VariableAccessed(name, cmVariableWatch::VARIABLE_MODIFIED_ACCESS,
- value ? "ON" : "OFF", this);
- }
-#endif
-}
-
void cmMakefile::CheckForUnusedVariables() const
{
if (!this->WarnUnused) {
return;
}
- const std::vector<std::string>& unused = this->StateSnapshot.UnusedKeys();
- std::vector<std::string>::const_iterator it = unused.begin();
- for (; it != unused.end(); ++it) {
- this->LogUnused("out of scope", *it);
+ for (const std::string& key : this->StateSnapshot.UnusedKeys()) {
+ this->LogUnused("out of scope", key);
}
}
@@ -1724,6 +1937,23 @@ bool cmMakefile::VariableInitialized(const std::string& var) const
return this->StateSnapshot.IsInitialized(var);
}
+void cmMakefile::MaybeWarnUninitialized(std::string const& variable,
+ const char* sourceFilename) const
+{
+ // check to see if we need to print a warning
+ // if strict mode is on and the variable has
+ // not been "cleared"/initialized with a set(foo ) call
+ if (this->GetCMakeInstance()->GetWarnUninitialized() &&
+ !this->VariableInitialized(variable)) {
+ if (this->CheckSystemVars ||
+ (sourceFilename && this->IsProjectFile(sourceFilename))) {
+ std::ostringstream msg;
+ msg << "uninitialized variable \'" << variable << "\'";
+ this->IssueMessage(MessageType::AUTHOR_WARNING, msg.str());
+ }
+ }
+}
+
void cmMakefile::LogUnused(const char* reason, const std::string& name) const
{
if (this->WarnUnused) {
@@ -1731,18 +1961,13 @@ void cmMakefile::LogUnused(const char* reason, const std::string& name) const
if (!this->ExecutionStatusStack.empty()) {
path = this->GetExecutionContext().FilePath;
} else {
- path = this->GetCurrentSourceDirectory();
- path += "/CMakeLists.txt";
+ path = cmStrCat(this->GetCurrentSourceDirectory(), "/CMakeLists.txt");
}
- if (this->CheckSystemVars ||
- cmSystemTools::IsSubDirectory(path, this->GetHomeDirectory()) ||
- (cmSystemTools::IsSubDirectory(path, this->GetHomeOutputDirectory()) &&
- !cmSystemTools::IsSubDirectory(path,
- cmake::GetCMakeFilesDirectory()))) {
+ if (this->CheckSystemVars || this->IsProjectFile(path.c_str())) {
std::ostringstream msg;
msg << "unused variable (" << reason << ") \'" << name << "\'";
- this->IssueMessage(cmake::AUTHOR_WARNING, msg.str());
+ this->IssueMessage(MessageType::AUTHOR_WARNING, msg.str());
}
}
}
@@ -1753,11 +1978,11 @@ void cmMakefile::RemoveDefinition(const std::string& name)
this->LogUnused("unsetting", name);
}
this->StateSnapshot.RemoveDefinition(name);
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
cmVariableWatch* vv = this->GetVariableWatch();
if (vv) {
vv->VariableAccessed(name, cmVariableWatch::VARIABLE_REMOVED_ACCESS,
- CM_NULLPTR, this);
+ nullptr, this);
}
#endif
}
@@ -1782,27 +2007,11 @@ void cmMakefile::AddGlobalLinkInformation(cmTarget& target)
return;
default:;
}
- if (const char* linkDirsProp = this->GetProperty("LINK_DIRECTORIES")) {
- std::vector<std::string> linkDirs;
- cmSystemTools::ExpandListArgument(linkDirsProp, linkDirs);
-
- for (std::vector<std::string>::iterator j = linkDirs.begin();
- j != linkDirs.end(); ++j) {
- std::string newdir = *j;
- // remove trailing slashes
- if (*j->rbegin() == '/') {
- newdir = j->substr(0, j->size() - 1);
- }
- target.AddLinkDirectory(*j);
- }
- }
if (const char* linkLibsProp = this->GetProperty("LINK_LIBRARIES")) {
- std::vector<std::string> linkLibs;
- cmSystemTools::ExpandListArgument(linkLibsProp, linkLibs);
+ std::vector<std::string> linkLibs = cmExpandedList(linkLibsProp);
- for (std::vector<std::string>::iterator j = linkLibs.begin();
- j != linkLibs.end(); ++j) {
+ for (auto j = linkLibs.begin(); j != linkLibs.end(); ++j) {
std::string libraryName = *j;
cmTargetLinkLibraryType libType = GENERAL_LibraryType;
if (libraryName == "optimized") {
@@ -1844,7 +2053,7 @@ cmTarget* cmMakefile::AddLibrary(const std::string& lname,
// Clear its dependencies. Otherwise, dependencies might persist
// over changes in CMakeLists.txt, making the information stale and
// hence useless.
- target->ClearDependencyInformation(*this, lname);
+ target->ClearDependencyInformation(*this);
if (excludeFromAll) {
target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
}
@@ -1853,7 +2062,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)
{
@@ -1869,86 +2078,248 @@ cmTarget* cmMakefile::AddExecutable(const char* exeName,
cmTarget* cmMakefile::AddNewTarget(cmStateEnums::TargetType type,
const std::string& name)
{
- cmTargets::iterator it =
+ auto it =
this->Targets
- .insert(cmTargets::value_type(
- name, cmTarget(name, type, cmTarget::VisibilityNormal, this)))
+ .emplace(name, cmTarget(name, type, cmTarget::VisibilityNormal, this))
.first;
+ this->OrderedTargets.push_back(&it->second);
this->GetGlobalGenerator()->IndexTarget(&it->second);
this->GetStateSnapshot().GetDirectory().AddNormalTargetName(name);
return &it->second;
}
+cmTarget* cmMakefile::AddNewUtilityTarget(const std::string& utilityName,
+ cmCommandOrigin origin,
+ bool excludeFromAll)
+{
+ cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName);
+ target->SetIsGeneratorProvided(origin == cmCommandOrigin::Generator);
+ if (excludeFromAll) {
+ target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
+ }
+ return target;
+}
+
+namespace {
+bool AnyOutputMatches(const std::string& name,
+ const std::vector<std::string>& outputs)
+{
+ for (std::string const& output : outputs) {
+ std::string::size_type pos = output.rfind(name);
+ // If the output matches exactly
+ if (pos != std::string::npos && pos == output.size() - name.size() &&
+ (pos == 0 || output[pos - 1] == '/')) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool AnyTargetCommandOutputMatches(
+ const std::string& name, const std::vector<cmCustomCommand>& commands)
+{
+ for (cmCustomCommand const& command : commands) {
+ if (AnyOutputMatches(name, command.GetByproducts())) {
+ return true;
+ }
+ }
+ return false;
+}
+}
+
+cmTarget* cmMakefile::LinearGetTargetWithOutput(const std::string& name) const
+{
+ // We go through the ordered vector of targets to get reproducible results
+ // should multiple names match.
+ for (cmTarget* t : this->OrderedTargets) {
+ // Does the output of any command match the source file name?
+ if (AnyTargetCommandOutputMatches(name, t->GetPreBuildCommands())) {
+ return t;
+ }
+ if (AnyTargetCommandOutputMatches(name, t->GetPreLinkCommands())) {
+ return t;
+ }
+ if (AnyTargetCommandOutputMatches(name, t->GetPostBuildCommands())) {
+ return t;
+ }
+ }
+ return nullptr;
+}
+
cmSourceFile* cmMakefile::LinearGetSourceFileWithOutput(
- const std::string& name) const
+ const std::string& name, cmSourceOutputKind kind, bool& byproduct) const
{
- std::string out;
+ // Outputs take precedence over byproducts.
+ byproduct = false;
+ cmSourceFile* fallback = nullptr;
- // look through all the source files that have custom commands
- // and see if the custom command has the passed source file as an output
- for (std::vector<cmSourceFile*>::const_iterator i =
- this->SourceFiles.begin();
- i != this->SourceFiles.end(); ++i) {
- // does this source file have a custom command?
- if ((*i)->GetCustomCommand()) {
+ // Look through all the source files that have custom commands and see if the
+ // custom command has the passed source file as an output.
+ for (cmSourceFile* src : this->SourceFiles) {
+ // Does this source file have a custom command?
+ if (src->GetCustomCommand()) {
// Does the output of the custom command match the source file name?
- const std::vector<std::string>& outputs =
- (*i)->GetCustomCommand()->GetOutputs();
- for (std::vector<std::string>::const_iterator o = outputs.begin();
- o != outputs.end(); ++o) {
- out = *o;
- std::string::size_type pos = out.rfind(name);
- // If the output matches exactly
- if (pos != std::string::npos && pos == out.size() - name.size() &&
- (pos == 0 || out[pos - 1] == '/')) {
- return *i;
+ if (AnyOutputMatches(name, src->GetCustomCommand()->GetOutputs())) {
+ // Return the first matching output.
+ return src;
+ }
+ if (kind == cmSourceOutputKind::OutputOrByproduct) {
+ if (AnyOutputMatches(name, src->GetCustomCommand()->GetByproducts())) {
+ // Do not return the source yet as there might be a matching output.
+ fallback = src;
}
}
}
}
- // otherwise return NULL
- return CM_NULLPTR;
+ // Did we find a byproduct?
+ byproduct = fallback != nullptr;
+ return fallback;
}
-cmSourceFile* cmMakefile::GetSourceFileWithOutput(
+cmSourcesWithOutput cmMakefile::GetSourcesWithOutput(
const std::string& name) const
{
+ // Linear search? Also see GetSourceFileWithOutput for detail.
+ if (!cmSystemTools::FileIsFullPath(name)) {
+ cmSourcesWithOutput sources;
+ sources.Target = this->LinearGetTargetWithOutput(name);
+ sources.Source = this->LinearGetSourceFileWithOutput(
+ name, cmSourceOutputKind::OutputOrByproduct, sources.SourceIsByproduct);
+ return sources;
+ }
+ // Otherwise we use an efficient lookup map.
+ auto o = this->OutputToSource.find(name);
+ if (o != this->OutputToSource.end()) {
+ return o->second.Sources;
+ }
+ return {};
+}
+
+cmSourceFile* cmMakefile::GetSourceFileWithOutput(
+ const std::string& name, cmSourceOutputKind kind) const
+{
// 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())) {
- return this->LinearGetSourceFileWithOutput(name);
+ if (!cmSystemTools::FileIsFullPath(name)) {
+ bool byproduct = false;
+ return this->LinearGetSourceFileWithOutput(name, kind, byproduct);
}
// Otherwise we use an efficient lookup map.
- OutputToSourceMap::const_iterator o = this->OutputToSource.find(name);
- if (o != this->OutputToSource.end()) {
- return (*o).second;
+ auto o = this->OutputToSource.find(name);
+ if (o != this->OutputToSource.end() &&
+ (!o->second.Sources.SourceIsByproduct ||
+ kind == cmSourceOutputKind::OutputOrByproduct)) {
+ // Source file could also be null pointer for example if we found the
+ // byproduct of a utility target or a PRE_BUILD, PRE_LINK, or POST_BUILD
+ // command of a target.
+ return o->second.Sources.Source;
+ }
+ return nullptr;
+}
+
+bool cmMakefile::MightHaveCustomCommand(const std::string& name) const
+{
+ // This will have to be changed for delaying custom command creation, because
+ // GetSourceFileWithOutput requires the command to be already created.
+ if (cmSourceFile* sf = this->GetSourceFileWithOutput(name)) {
+ if (sf->GetCustomCommand()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void cmMakefile::AddTargetByproducts(
+ cmTarget* target, const std::vector<std::string>& byproducts)
+{
+ for (std::string const& o : byproducts) {
+ this->UpdateOutputToSourceMap(o, target);
+ }
+}
+
+void cmMakefile::AddSourceOutputs(cmSourceFile* source,
+ const std::vector<std::string>& outputs,
+ const std::vector<std::string>& byproducts)
+{
+ for (std::string const& o : outputs) {
+ this->UpdateOutputToSourceMap(o, source, false);
+ }
+ for (std::string const& o : byproducts) {
+ this->UpdateOutputToSourceMap(o, source, true);
+ }
+}
+
+void cmMakefile::UpdateOutputToSourceMap(std::string const& byproduct,
+ cmTarget* target)
+{
+ SourceEntry entry;
+ entry.Sources.Target = target;
+
+ auto pr = this->OutputToSource.emplace(byproduct, entry);
+ if (!pr.second) {
+ SourceEntry& current = pr.first->second;
+ // Has the target already been set?
+ if (!current.Sources.Target) {
+ current.Sources.Target = target;
+ } else {
+ // Multiple custom commands/targets produce the same output (source file
+ // or target). See also comment in other UpdateOutputToSourceMap
+ // overload.
+ //
+ // TODO: Warn the user about this case.
+ }
}
- return CM_NULLPTR;
}
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+void cmMakefile::UpdateOutputToSourceMap(std::string const& output,
+ cmSourceFile* source, bool byproduct)
+{
+ SourceEntry entry;
+ entry.Sources.Source = source;
+ entry.Sources.SourceIsByproduct = byproduct;
+
+ auto pr = this->OutputToSource.emplace(output, entry);
+ if (!pr.second) {
+ SourceEntry& current = pr.first->second;
+ // Outputs take precedence over byproducts
+ if (!current.Sources.Source ||
+ (current.Sources.SourceIsByproduct && !byproduct)) {
+ current.Sources.Source = source;
+ current.Sources.SourceIsByproduct = false;
+ } else {
+ // Multiple custom commands produce the same output but may
+ // be attached to a different source file (MAIN_DEPENDENCY).
+ // LinearGetSourceFileWithOutput would return the first one,
+ // so keep the mapping for the first one.
+ //
+ // TODO: Warn the user about this case. However, the VS 8 generator
+ // triggers it for separate generate.stamp rules in ZERO_CHECK and
+ // individual targets.
+ }
+ }
+}
+
+#if !defined(CMAKE_BOOTSTRAP)
cmSourceGroup* cmMakefile::GetSourceGroup(
const std::vector<std::string>& name) const
{
- cmSourceGroup* sg = CM_NULLPTR;
+ cmSourceGroup* sg = nullptr;
// first look for source group starting with the same as the one we want
- for (std::vector<cmSourceGroup>::const_iterator sgIt =
- this->SourceGroups.begin();
- sgIt != this->SourceGroups.end(); ++sgIt) {
- std::string sgName = sgIt->GetName();
+ for (cmSourceGroup const& srcGroup : this->SourceGroups) {
+ std::string const& sgName = srcGroup.GetName();
if (sgName == name[0]) {
- sg = const_cast<cmSourceGroup*>(&(*sgIt));
+ sg = const_cast<cmSourceGroup*>(&srcGroup);
break;
}
}
- if (sg != CM_NULLPTR) {
+ 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());
- if (sg == CM_NULLPTR) {
+ sg = sg->LookupChild(name[i]);
+ if (sg == nullptr) {
break;
}
}
@@ -1966,14 +2337,14 @@ void cmMakefile::AddSourceGroup(const std::string& name, const char* regex)
void cmMakefile::AddSourceGroup(const std::vector<std::string>& name,
const char* regex)
{
- cmSourceGroup* sg = CM_NULLPTR;
+ cmSourceGroup* sg = nullptr;
std::vector<std::string> currentName;
int i = 0;
const int lastElement = static_cast<int>(name.size() - 1);
for (i = lastElement; i >= 0; --i) {
currentName.assign(name.begin(), name.begin() + i + 1);
sg = this->GetSourceGroup(currentName);
- if (sg != CM_NULLPTR) {
+ if (sg != nullptr) {
break;
}
}
@@ -1991,7 +2362,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.emplace_back(name[0], regex);
sg = this->GetSourceGroup(currentName);
i = 0; // last component found
}
@@ -2001,14 +2372,62 @@ 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(), CM_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);
}
+cmSourceGroup* cmMakefile::GetOrCreateSourceGroup(
+ const std::vector<std::string>& folders)
+{
+ cmSourceGroup* sg = this->GetSourceGroup(folders);
+ if (sg == nullptr) {
+ this->AddSourceGroup(folders);
+ sg = this->GetSourceGroup(folders);
+ }
+ return sg;
+}
+
+cmSourceGroup* cmMakefile::GetOrCreateSourceGroup(const std::string& name)
+{
+ const char* delimiter = this->GetDefinition("SOURCE_GROUP_DELIMITER");
+ if (delimiter == nullptr) {
+ delimiter = "\\";
+ }
+ return this->GetOrCreateSourceGroup(cmTokenize(name, delimiter));
+}
+
+/**
+ * Find a source group whose regular expression matches the filename
+ * part of the given source name. Search backward through the list of
+ * source groups, and take the first matching group found. This way
+ * non-inherited SOURCE_GROUP commands will have precedence over
+ * inherited ones.
+ */
+cmSourceGroup* cmMakefile::FindSourceGroup(
+ const std::string& source, std::vector<cmSourceGroup>& groups) const
+{
+ // First search for a group that lists the file explicitly.
+ for (auto sg = groups.rbegin(); sg != groups.rend(); ++sg) {
+ cmSourceGroup* result = sg->MatchChildrenFiles(source);
+ if (result) {
+ return result;
+ }
+ }
+
+ // Now search for a group whose regex matches the file.
+ for (auto sg = groups.rbegin(); sg != groups.rend(); ++sg) {
+ cmSourceGroup* result = sg->MatchChildrenRegex(source);
+ if (result) {
+ return result;
+ }
+ }
+
+ // Shouldn't get here, but just in case, return the default group.
+ return groups.data();
+}
#endif
static bool mightExpandVariablesCMP0019(const char* s)
@@ -2041,9 +2460,8 @@ void cmMakefile::ExpandVariablesCMP0019()
}
// Also for each target's INCLUDE_DIRECTORIES property:
- for (cmTargets::iterator l = this->Targets.begin(); l != this->Targets.end();
- ++l) {
- cmTarget& t = l->second;
+ for (auto& target : this->Targets) {
+ cmTarget& t = target.second;
if (t.GetType() == cmStateEnums::INTERFACE_LIBRARY ||
t.GetType() == cmStateEnums::GLOBAL_TARGET) {
continue;
@@ -2081,11 +2499,9 @@ void cmMakefile::ExpandVariablesCMP0019()
}
if (const char* linkLibsProp = this->GetProperty("LINK_LIBRARIES")) {
- std::vector<std::string> linkLibs;
- cmSystemTools::ExpandListArgument(linkLibsProp, linkLibs);
+ std::vector<std::string> linkLibs = cmExpandedList(linkLibsProp);
- for (std::vector<std::string>::iterator l = linkLibs.begin();
- l != linkLibs.end(); ++l) {
+ for (auto l = linkLibs.begin(); l != linkLibs.end(); ++l) {
std::string libName = *l;
if (libName == "optimized") {
++l;
@@ -2117,15 +2533,15 @@ void cmMakefile::ExpandVariablesCMP0019()
<< "The following variable evaluations were encountered:\n"
<< w.str();
/* clang-format on */
- this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, m.str(),
- this->Backtrace);
+ this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING,
+ m.str(), this->Backtrace);
}
}
bool cmMakefile::IsOn(const std::string& name) const
{
const char* value = this->GetDefinition(name);
- return cmSystemTools::IsOn(value);
+ return cmIsOn(value);
}
bool cmMakefile::IsSet(const std::string& name) const
@@ -2139,7 +2555,7 @@ bool cmMakefile::IsSet(const std::string& name) const
return false;
}
- if (cmSystemTools::IsNOTFOUND(value)) {
+ if (cmIsNOTFOUND(value)) {
return false;
}
@@ -2179,25 +2595,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 (size_t i = 0; i < sizeof(embedded) / sizeof(embedded[0]); ++i) {
- if (sdkRoot.find(embedded[i]) == 0 ||
- sdkRoot.find(std::string("/") + embedded[i]) != std::string::npos) {
- return true;
+ for (auto const& 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
@@ -2211,7 +2640,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;
@@ -2223,51 +2652,56 @@ bool cmMakefile::CanIWriteThisFile(const char* fileName) const
}
return !cmSystemTools::IsSubDirectory(fileName, this->GetHomeDirectory()) ||
- cmSystemTools::IsSubDirectory(fileName, this->GetHomeOutputDirectory());
+ cmSystemTools::IsSubDirectory(fileName, this->GetHomeOutputDirectory()) ||
+ cmSystemTools::SameFile(fileName, this->GetHomeOutputDirectory());
}
-const char* cmMakefile::GetRequiredDefinition(const std::string& name) const
+const std::string& cmMakefile::GetRequiredDefinition(
+ const std::string& name) const
{
- const char* ret = this->GetDefinition(name);
- if (!ret) {
+ static std::string const empty;
+ const std::string* def = GetDef(name);
+ if (!def) {
cmSystemTools::Error("Error required internal CMake variable not "
- "set, cmake may not be built correctly.\n",
- "Missing variable is:\n", name.c_str());
- return "";
+ "set, cmake may not be built correctly.\n"
+ "Missing variable is:\n" +
+ name);
+ return empty;
}
- return ret;
+ return *def;
}
bool cmMakefile::IsDefinitionSet(const std::string& name) const
{
- const char* def = this->StateSnapshot.GetDefinition(name);
+ const std::string* def = this->StateSnapshot.GetDefinition(name);
if (!def) {
def = this->GetState()->GetInitializedCacheValue(name);
}
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
if (cmVariableWatch* vv = this->GetVariableWatch()) {
if (!def) {
vv->VariableAccessed(
- name, cmVariableWatch::UNKNOWN_VARIABLE_DEFINED_ACCESS, def, this);
+ name, cmVariableWatch::UNKNOWN_VARIABLE_DEFINED_ACCESS, nullptr, this);
}
}
#endif
- return def != CM_NULLPTR;
+ return def != nullptr;
}
-const char* cmMakefile::GetDefinition(const std::string& name) const
+const std::string* cmMakefile::GetDef(const std::string& name) const
{
- const char* def = this->StateSnapshot.GetDefinition(name);
+ const std::string* def = this->StateSnapshot.GetDefinition(name);
if (!def) {
def = this->GetState()->GetInitializedCacheValue(name);
}
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
cmVariableWatch* vv = this->GetVariableWatch();
- if (vv && !this->SuppressWatches) {
- bool const watch_function_executed = vv->VariableAccessed(
- name, def ? cmVariableWatch::VARIABLE_READ_ACCESS
- : cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS,
- def, this);
+ if (vv && !this->SuppressSideEffects) {
+ bool const watch_function_executed =
+ vv->VariableAccessed(name,
+ def ? cmVariableWatch::VARIABLE_READ_ACCESS
+ : cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS,
+ (def ? def->c_str() : nullptr), this);
if (watch_function_executed) {
// A callback was executed and may have caused re-allocation of the
@@ -2283,35 +2717,45 @@ const char* cmMakefile::GetDefinition(const std::string& name) const
return def;
}
-const char* cmMakefile::GetSafeDefinition(const std::string& def) const
+const char* cmMakefile::GetDefinition(const std::string& name) const
+{
+ const std::string* def = GetDef(name);
+ if (!def) {
+ return nullptr;
+ }
+ return def->c_str();
+}
+
+const std::string& cmMakefile::GetSafeDefinition(const std::string& name) const
{
- const char* ret = this->GetDefinition(def);
- if (!ret) {
- return "";
+ static std::string const empty;
+ const std::string* def = GetDef(name);
+ if (!def) {
+ return empty;
}
- return ret;
+ return *def;
}
std::vector<std::string> cmMakefile::GetDefinitions() const
{
std::vector<std::string> res = this->StateSnapshot.ClosureKeys();
- std::vector<std::string> cacheKeys = this->GetState()->GetCacheEntryKeys();
- res.insert(res.end(), cacheKeys.begin(), cacheKeys.end());
+ cmAppend(res, this->GetState()->GetCacheEntryKeys());
std::sort(res.begin(), res.end());
return res;
}
-const char* cmMakefile::ExpandVariablesInString(std::string& source) const
+const std::string& cmMakefile::ExpandVariablesInString(
+ std::string& source) const
{
return this->ExpandVariablesInString(source, false, false);
}
-const char* cmMakefile::ExpandVariablesInString(
+const std::string& cmMakefile::ExpandVariablesInString(
std::string& source, bool escapeQuotes, bool noEscapes, bool atOnly,
const char* filename, long line, bool removeEmpty, bool replaceAt) const
{
bool compareResults = false;
- cmake::MessageType mtype = cmake::LOG;
+ MessageType mtype = MessageType::LOG;
std::string errorstr;
std::string original;
@@ -2319,16 +2763,16 @@ const char* cmMakefile::ExpandVariablesInString(
if (atOnly && (!noEscapes || !removeEmpty)) {
// This case should never be called. At-only is for
// configure-file/string which always does no escapes.
- this->IssueMessage(cmake::INTERNAL_ERROR,
+ this->IssueMessage(MessageType::INTERNAL_ERROR,
"ExpandVariablesInString @ONLY called "
"on something with escapes.");
- return source.c_str();
+ return source;
}
// Variables used in the WARN case.
std::string newResult;
std::string newErrorstr;
- cmake::MessageType newError = cmake::LOG;
+ MessageType newError = MessageType::LOG;
switch (this->GetPolicyStatus(cmPolicies::CMP0053)) {
case cmPolicies::WARN: {
@@ -2338,11 +2782,11 @@ const char* cmMakefile::ExpandVariablesInString(
compareResults = true;
// Suppress variable watches to avoid calling hooks twice. Suppress new
// dereferences since the OLD behavior is still what is actually used.
- this->SuppressWatches = true;
- newError = ExpandVariablesInStringNew(
- newErrorstr, newResult, escapeQuotes, noEscapes, atOnly, filename,
- line, removeEmpty, replaceAt);
- this->SuppressWatches = false;
+ this->SuppressSideEffects = true;
+ newError = ExpandVariablesInStringNew(newErrorstr, newResult,
+ escapeQuotes, noEscapes, atOnly,
+ filename, line, replaceAt);
+ this->SuppressSideEffects = false;
CM_FALLTHROUGH;
}
case cmPolicies::OLD:
@@ -2354,23 +2798,23 @@ const char* cmMakefile::ExpandVariablesInString(
case cmPolicies::REQUIRED_ALWAYS:
// Messaging here would be *very* verbose.
case cmPolicies::NEW:
- mtype = ExpandVariablesInStringNew(errorstr, source, escapeQuotes,
- noEscapes, atOnly, filename, line,
- removeEmpty, replaceAt);
+ mtype =
+ ExpandVariablesInStringNew(errorstr, source, escapeQuotes, noEscapes,
+ atOnly, filename, line, replaceAt);
break;
}
// If it's an error in either case, just report the error...
- if (mtype != cmake::LOG) {
- if (mtype == cmake::FATAL_ERROR) {
+ if (mtype != MessageType::LOG) {
+ if (mtype == MessageType::FATAL_ERROR) {
cmSystemTools::SetFatalErrorOccured();
}
this->IssueMessage(mtype, errorstr);
}
// ...otherwise, see if there's a difference that needs to be warned about.
else if (compareResults && (newResult != source || newError != mtype)) {
- std::string msg = cmPolicies::GetPolicyWarning(cmPolicies::CMP0053);
- msg += "\n";
+ std::string msg =
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0053), '\n');
std::string msg_input = original;
cmSystemTools::ReplaceString(msg_input, "\n", "\n ");
@@ -2401,20 +2845,20 @@ const char* cmMakefile::ExpandVariablesInString(
msg +=
"Using the old result for compatibility since the policy is not set.";
- this->IssueMessage(cmake::AUTHOR_WARNING, msg);
+ this->IssueMessage(MessageType::AUTHOR_WARNING, msg);
}
- return source.c_str();
+ return source;
}
-cmake::MessageType cmMakefile::ExpandVariablesInStringOld(
+MessageType cmMakefile::ExpandVariablesInStringOld(
std::string& errorstr, std::string& source, bool escapeQuotes,
bool noEscapes, bool atOnly, const char* filename, long line,
bool removeEmpty, bool replaceAt) const
{
// Fast path strings without any special characters.
if (source.find_first_of("$@\\") == std::string::npos) {
- return cmake::LOG;
+ return MessageType::LOG;
}
// Special-case the @ONLY mode.
@@ -2423,7 +2867,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld(
std::string input = source;
// Start with empty output.
- source = "";
+ source.clear();
// Look for one @VAR@ at a time.
const char* in = input.c_str();
@@ -2440,7 +2884,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld(
if (const char* val = this->GetDefinition(var)) {
// Store the value in the output escaping as requested.
if (escapeQuotes) {
- source.append(cmSystemTools::EscapeQuotes(val));
+ source.append(cmEscapeQuotes(val));
} else {
source.append(val);
}
@@ -2453,7 +2897,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld(
// Append the rest of the unchanged part of the string.
source.append(in);
- return cmake::LOG;
+ return MessageType::LOG;
}
// This method replaces ${VAR} and @VAR@ where VAR is looked up
@@ -2470,7 +2914,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld(
parser.SetRemoveEmpty(removeEmpty);
int res = parser.ParseString(source.c_str(), 0);
const char* emsg = parser.GetError();
- cmake::MessageType mtype = cmake::LOG;
+ MessageType mtype = MessageType::LOG;
if (res && !emsg[0]) {
source = parser.GetResult();
} else {
@@ -2493,7 +2937,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld(
// parser reported an error message without failing because the
// helper implementation is unhappy, which has always reported an
// error.
- mtype = cmake::FATAL_ERROR;
+ mtype = MessageType::FATAL_ERROR;
if (!res) {
// This is a real argument parsing error. Use policy CMP0010 to
// decide whether it is an error.
@@ -2503,7 +2947,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld(
CM_FALLTHROUGH;
case cmPolicies::OLD:
// OLD behavior is to just warn and continue.
- mtype = cmake::AUTHOR_WARNING;
+ mtype = MessageType::AUTHOR_WARNING;
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
@@ -2519,22 +2963,40 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld(
return mtype;
}
-typedef enum { NORMAL, ENVIRONMENT, CACHE } t_domain;
+enum t_domain
+{
+ NORMAL,
+ ENVIRONMENT,
+ CACHE
+};
+
struct t_lookup
{
- t_lookup()
- : domain(NORMAL)
- , loc(0)
- {
- }
- t_domain domain;
- size_t loc;
+ t_domain domain = NORMAL;
+ size_t loc = 0;
};
-cmake::MessageType cmMakefile::ExpandVariablesInStringNew(
+bool cmMakefile::IsProjectFile(const char* filename) const
+{
+ return cmSystemTools::IsSubDirectory(filename, this->GetHomeDirectory()) ||
+ (cmSystemTools::IsSubDirectory(filename, this->GetHomeOutputDirectory()) &&
+ !cmSystemTools::IsSubDirectory(filename, "/CMakeFiles"));
+}
+
+int cmMakefile::GetRecursionDepth() const
+{
+ return this->RecursionDepth;
+}
+
+void cmMakefile::SetRecursionDepth(int recursionDepth)
+{
+ this->RecursionDepth = recursionDepth;
+}
+
+MessageType cmMakefile::ExpandVariablesInStringNew(
std::string& errorstr, std::string& source, bool escapeQuotes,
bool noEscapes, bool atOnly, const char* filename, long line,
- bool removeEmpty, bool replaceAt) const
+ bool replaceAt) const
{
// This method replaces ${VAR} and @VAR@ where VAR is looked up
// with GetDefinition(), if not found in the map, nothing is expanded.
@@ -2548,10 +3010,11 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew(
std::vector<t_lookup> openstack;
bool error = false;
bool done = false;
- cmake::MessageType mtype = cmake::LOG;
+ MessageType mtype = MessageType::LOG;
cmState* state = this->GetCMakeInstance()->GetState();
+ static const std::string lineVar = "CMAKE_CURRENT_LIST_LINE";
do {
char inc = *in;
switch (inc) {
@@ -2561,16 +3024,13 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew(
openstack.pop_back();
result.append(last, in - last);
std::string const& lookup = result.substr(var.loc);
- const char* value = CM_NULLPTR;
+ const char* value = nullptr;
std::string varresult;
std::string svalue;
- static const std::string lineVar = "CMAKE_CURRENT_LIST_LINE";
switch (var.domain) {
case NORMAL:
if (filename && lookup == lineVar) {
- std::ostringstream ostr;
- ostr << line;
- varresult = ostr.str();
+ varresult = std::to_string(line);
} else {
value = this->GetDefinition(lookup);
}
@@ -2587,26 +3047,12 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew(
// Get the string we're meant to append to.
if (value) {
if (escapeQuotes) {
- varresult = cmSystemTools::EscapeQuotes(value);
+ varresult = cmEscapeQuotes(value);
} else {
varresult = value;
}
- } else if (!removeEmpty) {
- // check to see if we need to print a warning
- // if strict mode is on and the variable has
- // not been "cleared"/initialized with a set(foo ) call
- if (this->GetCMakeInstance()->GetWarnUninitialized() &&
- !this->VariableInitialized(lookup)) {
- if (this->CheckSystemVars ||
- cmSystemTools::IsSubDirectory(filename,
- this->GetHomeDirectory()) ||
- cmSystemTools::IsSubDirectory(
- filename, this->GetHomeOutputDirectory())) {
- std::ostringstream msg;
- msg << "uninitialized variable \'" << lookup << "\'";
- this->IssueMessage(cmake::AUTHOR_WARNING, msg.str());
- }
- }
+ } else if (!this->SuppressSideEffects) {
+ this->MaybeWarnUninitialized(lookup, filename);
}
result.replace(var.loc, result.size() - var.loc, varresult);
// Start looking from here on out.
@@ -2617,7 +3063,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew(
if (!atOnly) {
t_lookup lookup;
const char* next = in + 1;
- const char* start = CM_NULLPTR;
+ const char* start = nullptr;
char nextc = *next;
if (nextc == '{') {
// Looking for a variable.
@@ -2641,7 +3087,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew(
std::string(next, this->cmNamedCurly.end()) +
"{} is not supported. Only ${}, $ENV{}, "
"and $CACHE{} are allowed.";
- mtype = cmake::FATAL_ERROR;
+ mtype = MessageType::FATAL_ERROR;
error = true;
}
}
@@ -2707,13 +3153,27 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew(
const char* nextAt = strchr(in + 1, '@');
if (nextAt && nextAt != in + 1 &&
nextAt ==
- in + 1 + strspn(in + 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789/_.+-")) {
+ in + 1 +
+ strspn(in + 1,
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789/_.+-")) {
std::string variable(in + 1, nextAt - in - 1);
- std::string varresult = this->GetSafeDefinition(variable);
+
+ std::string varresult;
+ if (filename && variable == lineVar) {
+ varresult = std::to_string(line);
+ } else {
+ const std::string* def = this->GetDef(variable);
+ if (def) {
+ varresult = *def;
+ } else if (!this->SuppressSideEffects) {
+ this->MaybeWarnUninitialized(variable, filename);
+ }
+ }
+
if (escapeQuotes) {
- varresult = cmSystemTools::EscapeQuotes(varresult);
+ varresult = cmEscapeQuotes(varresult);
}
// Skip over the variable.
result.append(last, in - last);
@@ -2735,7 +3195,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew(
errorstr += "\') in a variable name: "
"'" +
result.substr(openstack.back().loc) + "'";
- mtype = cmake::FATAL_ERROR;
+ mtype = MessageType::FATAL_ERROR;
error = true;
}
break;
@@ -2766,7 +3226,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew(
emsg << "when parsing string\n"
<< " " << source << "\n";
emsg << errorstr;
- mtype = cmake::FATAL_ERROR;
+ mtype = MessageType::FATAL_ERROR;
errorstr = emsg.str();
} else {
// Append the rest of the unchanged part of the string.
@@ -2806,7 +3266,7 @@ std::string cmMakefile::GetConfigurations(std::vector<std::string>& configs,
if (this->GetGlobalGenerator()->IsMultiConfig()) {
if (const char* configTypes =
this->GetDefinition("CMAKE_CONFIGURATION_TYPES")) {
- cmSystemTools::ExpandListArgument(configTypes, configs);
+ cmExpandList(configTypes, configs);
}
return "";
}
@@ -2817,59 +3277,25 @@ std::string cmMakefile::GetConfigurations(std::vector<std::string>& configs,
return buildType;
}
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-/**
- * Find a source group whose regular expression matches the filename
- * part of the given source name. Search backward through the list of
- * source groups, and take the first matching group found. This way
- * non-inherited SOURCE_GROUP commands will have precedence over
- * inherited ones.
- */
-cmSourceGroup* cmMakefile::FindSourceGroup(
- const char* source, std::vector<cmSourceGroup>& groups) const
+std::vector<std::string> cmMakefile::GetGeneratorConfigs() const
{
- // First search for a group that lists the file explicitly.
- for (std::vector<cmSourceGroup>::reverse_iterator sg = groups.rbegin();
- sg != groups.rend(); ++sg) {
- cmSourceGroup* result = sg->MatchChildrenFiles(source);
- if (result) {
- return result;
- }
- }
-
- // Now search for a group whose regex matches the file.
- for (std::vector<cmSourceGroup>::reverse_iterator sg = groups.rbegin();
- sg != groups.rend(); ++sg) {
- cmSourceGroup* result = sg->MatchChildrenRegex(source);
- if (result) {
- return result;
- }
+ std::vector<std::string> configs;
+ GetConfigurations(configs);
+ if (configs.empty()) {
+ configs.emplace_back();
}
-
- // Shouldn't get here, but just in case, return the default group.
- return &groups.front();
+ return configs;
}
-#endif
bool cmMakefile::IsFunctionBlocked(const cmListFileFunction& lff,
cmExecutionStatus& status)
{
// if there are no blockers get out of here
- if (this->FunctionBlockers.begin() == this->FunctionBlockers.end()) {
+ if (this->FunctionBlockers.empty()) {
return false;
}
- // loop over all function blockers to see if any block this command
- // evaluate in reverse, this is critical for balanced IF statements etc
- std::vector<cmFunctionBlocker*>::reverse_iterator pos;
- for (pos = this->FunctionBlockers.rbegin();
- pos != this->FunctionBlockers.rend(); ++pos) {
- if ((*pos)->IsFunctionBlocked(lff, *this, status)) {
- return true;
- }
- }
-
- return false;
+ return this->FunctionBlockers.top()->IsFunctionBlocked(lff, status);
}
void cmMakefile::PushFunctionBlockerBarrier()
@@ -2883,8 +3309,9 @@ void cmMakefile::PopFunctionBlockerBarrier(bool reportError)
FunctionBlockersType::size_type barrier =
this->FunctionBlockerBarriers.back();
while (this->FunctionBlockers.size() > barrier) {
- CM_AUTO_PTR<cmFunctionBlocker> fb(this->FunctionBlockers.back());
- this->FunctionBlockers.pop_back();
+ std::unique_ptr<cmFunctionBlocker> fb(
+ std::move(this->FunctionBlockers.top()));
+ this->FunctionBlockers.pop();
if (reportError) {
// Report the context in which the unclosed block was opened.
cmListFileContext const& lfc = fb->GetStartingContext();
@@ -2894,7 +3321,7 @@ void cmMakefile::PopFunctionBlockerBarrier(bool reportError)
<< " " << lfc << "\n"
<< "is not closed.";
/* clang-format on */
- this->IssueMessage(cmake::FATAL_ERROR, e.str());
+ this->IssueMessage(MessageType::FATAL_ERROR, e.str());
reportError = false;
}
}
@@ -2948,26 +3375,25 @@ bool cmMakefile::ExpandArguments(std::vector<cmListFileArgument> const& inArgs,
if (!filename) {
filename = efp.c_str();
}
- std::vector<cmListFileArgument>::const_iterator i;
std::string value;
outArgs.reserve(inArgs.size());
- for (i = inArgs.begin(); i != inArgs.end(); ++i) {
+ for (cmListFileArgument const& i : inArgs) {
// No expansion in a bracket argument.
- if (i->Delim == cmListFileArgument::Bracket) {
- outArgs.push_back(i->Value);
+ if (i.Delim == cmListFileArgument::Bracket) {
+ outArgs.push_back(i.Value);
continue;
}
// Expand the variables in the argument.
- value = i->Value;
- this->ExpandVariablesInString(value, false, false, false, filename,
- i->Line, false, false);
+ value = i.Value;
+ this->ExpandVariablesInString(value, false, false, false, filename, i.Line,
+ false, false);
// If the argument is quoted, it should be one argument.
// Otherwise, it may be a list of arguments.
- if (i->Delim == cmListFileArgument::Quoted) {
+ if (i.Delim == cmListFileArgument::Quoted) {
outArgs.push_back(value);
} else {
- cmSystemTools::ExpandListArgument(value, outArgs);
+ cmExpandList(value, outArgs);
}
}
return !cmSystemTools::GetFatalErrorOccured();
@@ -2981,147 +3407,158 @@ bool cmMakefile::ExpandArguments(
if (!filename) {
filename = efp.c_str();
}
- std::vector<cmListFileArgument>::const_iterator i;
std::string value;
outArgs.reserve(inArgs.size());
- for (i = inArgs.begin(); i != inArgs.end(); ++i) {
+ for (cmListFileArgument const& i : inArgs) {
// No expansion in a bracket argument.
- if (i->Delim == cmListFileArgument::Bracket) {
- outArgs.push_back(cmExpandedCommandArgument(i->Value, true));
+ if (i.Delim == cmListFileArgument::Bracket) {
+ outArgs.emplace_back(i.Value, true);
continue;
}
// Expand the variables in the argument.
- value = i->Value;
- this->ExpandVariablesInString(value, false, false, false, filename,
- i->Line, false, false);
+ value = i.Value;
+ this->ExpandVariablesInString(value, false, false, false, filename, i.Line,
+ false, false);
// 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));
+ if (i.Delim == cmListFileArgument::Quoted) {
+ outArgs.emplace_back(value, true);
} else {
- std::vector<std::string> stringArgs;
- cmSystemTools::ExpandListArgument(value, stringArgs);
- for (size_t j = 0; j < stringArgs.size(); ++j) {
- outArgs.push_back(cmExpandedCommandArgument(stringArgs[j], false));
+ std::vector<std::string> stringArgs = cmExpandedList(value);
+ for (std::string const& stringArg : stringArgs) {
+ outArgs.emplace_back(stringArg, false);
}
}
}
return !cmSystemTools::GetFatalErrorOccured();
}
-void cmMakefile::AddFunctionBlocker(cmFunctionBlocker* fb)
+void cmMakefile::AddFunctionBlocker(std::unique_ptr<cmFunctionBlocker> fb)
{
if (!this->ExecutionStatusStack.empty()) {
// Record the context in which the blocker is created.
fb->SetStartingContext(this->GetExecutionContext());
}
- this->FunctionBlockers.push_back(fb);
+ this->FunctionBlockers.push(std::move(fb));
}
-CM_AUTO_PTR<cmFunctionBlocker> cmMakefile::RemoveFunctionBlocker(
- cmFunctionBlocker* fb, const cmListFileFunction& lff)
+std::unique_ptr<cmFunctionBlocker> cmMakefile::RemoveFunctionBlocker()
{
- // Find the function blocker stack barrier for the current scope.
- // We only remove a blocker whose index is not less than the barrier.
- FunctionBlockersType::size_type barrier = 0;
- if (!this->FunctionBlockerBarriers.empty()) {
- barrier = this->FunctionBlockerBarriers.back();
- }
-
- // Search for the function blocker whose scope this command ends.
- for (FunctionBlockersType::size_type i = this->FunctionBlockers.size();
- i > barrier; --i) {
- std::vector<cmFunctionBlocker*>::iterator pos =
- this->FunctionBlockers.begin() + (i - 1);
- if (*pos == fb) {
- // Warn if the arguments do not match, but always remove.
- if (!(*pos)->ShouldRemove(lff, *this)) {
- cmListFileContext const& lfc = fb->GetStartingContext();
- cmListFileContext closingContext =
- cmListFileContext::FromCommandContext(lff, lfc.FilePath);
- std::ostringstream e;
- /* clang-format off */
- e << "A logical block opening on the line\n"
- << " " << lfc << "\n"
- << "closes on the line\n"
- << " " << closingContext << "\n"
- << "with mis-matching arguments.";
- /* clang-format on */
- this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
- }
- cmFunctionBlocker* b = *pos;
- this->FunctionBlockers.erase(pos);
- return CM_AUTO_PTR<cmFunctionBlocker>(b);
- }
- }
+ assert(!this->FunctionBlockers.empty());
+ assert(this->FunctionBlockerBarriers.empty() ||
+ this->FunctionBlockers.size() > this->FunctionBlockerBarriers.back());
- return CM_AUTO_PTR<cmFunctionBlocker>();
+ auto b = std::move(this->FunctionBlockers.top());
+ this->FunctionBlockers.pop();
+ return b;
}
-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);
}
void cmMakefile::SetArgcArgv(const std::vector<std::string>& args)
{
- std::ostringstream strStream;
- strStream << args.size();
- this->AddDefinition("CMAKE_ARGC", strStream.str().c_str());
+ this->AddDefinition("CMAKE_ARGC", std::to_string(args.size()));
// this->MarkVariableAsUsed("CMAKE_ARGC");
for (unsigned int t = 0; t < args.size(); ++t) {
std::ostringstream tmpStream;
tmpStream << "CMAKE_ARGV" << t;
- this->AddDefinition(tmpStream.str(), args[t].c_str());
+ this->AddDefinition(tmpStream.str(), args[t]);
// this->MarkVariableAsUsed(tmpStream.str().c_str());
}
}
-cmSourceFile* cmMakefile::GetSource(const std::string& sourceName) const
+cmSourceFile* cmMakefile::GetSource(const std::string& sourceName,
+ cmSourceFileLocationKind kind) const
{
- cmSourceFileLocation sfl(this, sourceName);
- for (std::vector<cmSourceFile*>::const_iterator sfi =
- this->SourceFiles.begin();
- sfi != this->SourceFiles.end(); ++sfi) {
- cmSourceFile* sf = *sfi;
- if (sf->Matches(sfl)) {
- return sf;
+ // First check "Known" paths (avoids the creation of cmSourceFileLocation)
+ if (kind == cmSourceFileLocationKind::Known) {
+ auto sfsi = this->KnownFileSearchIndex.find(sourceName);
+ if (sfsi != this->KnownFileSearchIndex.end()) {
+ return sfsi->second;
}
}
- return CM_NULLPTR;
+
+ 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);
+ // for "Known" paths add direct lookup (used for faster lookup in GetSource)
+ if (kind == cmSourceFileLocationKind::Known) {
+ this->KnownFileSearchIndex[sourceName] = 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);
+}
+
+cmSourceFile* cmMakefile::GetOrCreateGeneratedSource(
+ const std::string& sourceName)
+{
+ cmSourceFile* sf =
+ this->GetOrCreateSource(sourceName, true, cmSourceFileLocationKind::Known);
+ sf->SetProperty("GENERATED", "1");
+ return sf;
+}
+
+void cmMakefile::CreateGeneratedSources(
+ const std::vector<std::string>& outputs)
+{
+ for (std::string const& output : outputs) {
+ this->GetOrCreateGeneratedSource(output);
+ }
}
void cmMakefile::AddTargetObject(std::string const& tgtName,
@@ -3130,29 +3567,29 @@ void cmMakefile::AddTargetObject(std::string const& tgtName,
cmSourceFile* sf = this->GetOrCreateSource(objFile, true);
sf->SetObjectLibrary(tgtName);
sf->SetProperty("EXTERNAL_OBJECT", "1");
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
this->SourceGroups[this->ObjectLibrariesSourceGroupIndex].AddGroupFile(
- sf->GetFullPath());
+ sf->ResolveFullPath());
#endif
}
void cmMakefile::EnableLanguage(std::vector<std::string> const& lang,
bool optional)
{
- this->AddDefinition("CMAKE_CFG_INTDIR",
- this->GetGlobalGenerator()->GetCMakeCFGIntDir());
+ if (const char* def = this->GetGlobalGenerator()->GetCMakeCFGIntDir()) {
+ this->AddDefinition("CMAKE_CFG_INTDIR", def);
+ }
// If RC is explicitly listed we need to do it after other languages.
// On some platforms we enable RC implicitly while enabling others.
// Do not let that look like recursive enable_language(RC).
std::vector<std::string> langs;
std::vector<std::string> langsRC;
langs.reserve(lang.size());
- for (std::vector<std::string>::const_iterator i = lang.begin();
- i != lang.end(); ++i) {
- if (*i == "RC") {
- langsRC.push_back(*i);
+ for (std::string const& i : lang) {
+ if (i == "RC") {
+ langsRC.push_back(i);
} else {
- langs.push_back(*i);
+ langs.push_back(i);
}
}
if (!langs.empty()) {
@@ -3166,42 +3603,53 @@ void cmMakefile::EnableLanguage(std::vector<std::string> const& lang,
int cmMakefile::TryCompile(const std::string& srcdir,
const std::string& bindir,
const std::string& projectName,
- const std::string& targetName, bool fast,
+ const std::string& targetName, bool fast, int jobs,
const std::vector<std::string>* cmakeArgs,
std::string& output)
{
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
// use the cmake object instead of calling cmake
cmWorkingDirectory workdir(bindir);
+ if (workdir.Failed()) {
+ this->IssueMessage(MessageType::FATAL_ERROR,
+ "Failed to set working directory to " + bindir + " : " +
+ std::strerror(workdir.GetLastResult()));
+ cmSystemTools::SetFatalErrorOccured();
+ this->IsSourceFileTryCompile = false;
+ return 1;
+ }
// make sure the same generator is used
// use this program as the cmake to be run, it should not
// be run that way but the cmake object requires a vailid path
- cmake cm(cmake::RoleProject);
+ cmake cm(cmake::RoleProject, cmState::Project);
cm.SetIsInTryCompile(true);
cmGlobalGenerator* gg =
cm.CreateGlobalGenerator(this->GetGlobalGenerator()->GetName());
if (!gg) {
- this->IssueMessage(cmake::INTERNAL_ERROR, "Global generator '" +
+ this->IssueMessage(MessageType::INTERNAL_ERROR,
+ "Global generator '" +
this->GetGlobalGenerator()->GetName() +
"' could not be created.");
cmSystemTools::SetFatalErrorOccured();
this->IsSourceFileTryCompile = false;
return 1;
}
+ gg->RecursionDepth = this->RecursionDepth;
cm.SetGlobalGenerator(gg);
// do a configure
cm.SetHomeDirectory(srcdir);
cm.SetHomeOutputDirectory(bindir);
- cm.SetGeneratorPlatform(this->GetCMakeInstance()->GetGeneratorPlatform());
- cm.SetGeneratorToolset(this->GetCMakeInstance()->GetGeneratorToolset());
+ cm.SetGeneratorInstance(this->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE"));
+ cm.SetGeneratorPlatform(this->GetSafeDefinition("CMAKE_GENERATOR_PLATFORM"));
+ cm.SetGeneratorToolset(this->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET"));
cm.LoadCache();
if (!gg->IsMultiConfig()) {
if (const char* config =
@@ -3213,6 +3661,12 @@ int cmMakefile::TryCompile(const std::string& srcdir,
cmStateEnums::STRING);
}
}
+ const char* recursionDepth =
+ this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH");
+ if (recursionDepth) {
+ cm.AddCacheEntry("CMAKE_MAXIMUM_RECURSION_DEPTH", recursionDepth,
+ "Maximum recursion depth", cmStateEnums::STRING);
+ }
// if cmake args were provided then pass them in
if (cmakeArgs) {
// FIXME: Workaround to ignore unused CLI variables in try-compile.
@@ -3252,7 +3706,7 @@ int cmMakefile::TryCompile(const std::string& srcdir,
cmStateEnums::INTERNAL);
}
if (cm.Configure() != 0) {
- this->IssueMessage(cmake::FATAL_ERROR,
+ this->IssueMessage(MessageType::FATAL_ERROR,
"Failed to configure test project build system.");
cmSystemTools::SetFatalErrorOccured();
this->IsSourceFileTryCompile = false;
@@ -3260,7 +3714,7 @@ int cmMakefile::TryCompile(const std::string& srcdir,
}
if (cm.Generate() != 0) {
- this->IssueMessage(cmake::FATAL_ERROR,
+ this->IssueMessage(MessageType::FATAL_ERROR,
"Failed to generate test project build system.");
cmSystemTools::SetFatalErrorOccured();
this->IsSourceFileTryCompile = false;
@@ -3269,7 +3723,7 @@ int cmMakefile::TryCompile(const std::string& srcdir,
// finally call the generator to actually build the resulting project
int ret = this->GetGlobalGenerator()->TryCompile(
- srcdir, bindir, projectName, targetName, fast, output, this);
+ jobs, srcdir, bindir, projectName, targetName, fast, output, this);
this->IsSourceFileTryCompile = false;
return ret;
@@ -3295,14 +3749,14 @@ cmGlobalGenerator* cmMakefile::GetGlobalGenerator() const
return this->GlobalGenerator;
}
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
cmVariableWatch* cmMakefile::GetVariableWatch() const
{
if (this->GetCMakeInstance() &&
this->GetCMakeInstance()->GetVariableWatch()) {
return this->GetCMakeInstance()->GetVariableWatch();
}
- return CM_NULLPTR;
+ return nullptr;
}
#endif
@@ -3311,7 +3765,7 @@ cmState* cmMakefile::GetState() const
return this->GetCMakeInstance()->GetState();
}
-void cmMakefile::DisplayStatus(const char* message, float s) const
+void cmMakefile::DisplayStatus(const std::string& message, float s) const
{
cmake* cm = this->GetCMakeInstance();
if (cm->GetWorkingMode() == cmake::FIND_PACKAGE_MODE) {
@@ -3322,7 +3776,8 @@ void cmMakefile::DisplayStatus(const char* message, float s) const
cm->UpdateProgress(message, s);
}
-std::string cmMakefile::GetModulesFile(const char* filename) const
+std::string cmMakefile::GetModulesFile(const std::string& filename,
+ bool& system) const
{
std::string result;
@@ -3342,17 +3797,14 @@ std::string cmMakefile::GetModulesFile(const char* filename) const
// Always search in CMAKE_MODULE_PATH:
const char* cmakeModulePath = this->GetDefinition("CMAKE_MODULE_PATH");
if (cmakeModulePath) {
- std::vector<std::string> modulePath;
- cmSystemTools::ExpandListArgument(cmakeModulePath, modulePath);
+ std::vector<std::string> modulePath = cmExpandedList(cmakeModulePath);
// Look through the possible module directories.
- for (std::vector<std::string>::iterator i = modulePath.begin();
- i != modulePath.end(); ++i) {
- std::string itempl = *i;
+ for (std::string itempl : modulePath) {
cmSystemTools::ConvertToUnixSlashes(itempl);
itempl += "/";
itempl += filename;
- if (cmSystemTools::FileExists(itempl.c_str())) {
+ if (cmSystemTools::FileExists(itempl)) {
moduleInCMakeModulePath = itempl;
break;
}
@@ -3360,19 +3812,20 @@ std::string cmMakefile::GetModulesFile(const char* filename) const
}
// Always search in the standard modules location.
- moduleInCMakeRoot = cmSystemTools::GetCMakeRoot();
- moduleInCMakeRoot += "/Modules/";
- moduleInCMakeRoot += filename;
+ moduleInCMakeRoot =
+ cmStrCat(cmSystemTools::GetCMakeRoot(), "/Modules/", filename);
cmSystemTools::ConvertToUnixSlashes(moduleInCMakeRoot);
- if (!cmSystemTools::FileExists(moduleInCMakeRoot.c_str())) {
- moduleInCMakeRoot = "";
+ if (!cmSystemTools::FileExists(moduleInCMakeRoot)) {
+ moduleInCMakeRoot.clear();
}
// Normally, prefer the files found in CMAKE_MODULE_PATH. Only when the file
// from which we are being called is located itself in CMAKE_ROOT, then
// prefer results from CMAKE_ROOT depending on the policy setting.
+ system = false;
result = moduleInCMakeModulePath;
if (result.empty()) {
+ system = true;
result = moduleInCMakeRoot;
}
@@ -3391,15 +3844,17 @@ std::string cmMakefile::GetModulesFile(const char* filename) const
<< cmPolicies::GetPolicyWarning(cmPolicies::CMP0017);
/* clang-format on */
- this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ this->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
CM_FALLTHROUGH;
}
case cmPolicies::OLD:
+ system = false;
result = moduleInCMakeModulePath;
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
+ system = true;
result = moduleInCMakeRoot;
break;
}
@@ -3432,20 +3887,24 @@ void cmMakefile::ConfigureString(const std::string& input, std::string& output,
// Replace #cmakedefine instances.
if (this->cmDefineRegex.find(line)) {
- const char* def = this->GetDefinition(this->cmDefineRegex.match(1));
- if (!cmSystemTools::IsOff(def)) {
- cmSystemTools::ReplaceString(line, "#cmakedefine", "#define");
+ const char* def = this->GetDefinition(this->cmDefineRegex.match(2));
+ if (!cmIsOff(def)) {
+ const std::string indentation = this->cmDefineRegex.match(1);
+ cmSystemTools::ReplaceString(line, "#" + indentation + "cmakedefine",
+ "#" + indentation + "define");
output += line;
} else {
output += "/* #undef ";
- output += this->cmDefineRegex.match(1);
+ output += this->cmDefineRegex.match(2);
output += " */";
}
} else if (this->cmDefine01Regex.find(line)) {
- const char* def = this->GetDefinition(this->cmDefine01Regex.match(1));
- cmSystemTools::ReplaceString(line, "#cmakedefine01", "#define");
+ const std::string indentation = this->cmDefine01Regex.match(1);
+ const char* def = this->GetDefinition(this->cmDefine01Regex.match(2));
+ cmSystemTools::ReplaceString(line, "#" + indentation + "cmakedefine01",
+ "#" + indentation + "define");
output += line;
- if (!cmSystemTools::IsOff(def)) {
+ if (!cmIsOff(def)) {
output += " 1";
} else {
output += " 0";
@@ -3463,26 +3922,34 @@ void cmMakefile::ConfigureString(const std::string& input, std::string& output,
}
// Perform variable replacements.
- this->ExpandVariablesInString(output, escapeQuotes, true, atOnly, CM_NULLPTR,
- -1, true, true);
+ const char* filename = nullptr;
+ long lineNumber = -1;
+ if (!this->Backtrace.Empty()) {
+ const auto& currentTrace = this->Backtrace.Top();
+ filename = currentTrace.FilePath.c_str();
+ lineNumber = currentTrace.Line;
+ }
+ this->ExpandVariablesInString(output, escapeQuotes, true, atOnly, filename,
+ lineNumber, true, true);
}
-int cmMakefile::ConfigureFile(const char* infile, const char* outfile,
- bool copyonly, bool atOnly, bool escapeQuotes,
+int cmMakefile::ConfigureFile(const std::string& infile,
+ const std::string& outfile, bool copyonly,
+ bool atOnly, bool escapeQuotes,
cmNewLineStyle newLine)
{
int res = 1;
if (!this->CanIWriteThisFile(outfile)) {
- cmSystemTools::Error("Attempt to write file: ", outfile,
+ cmSystemTools::Error("Attempt to write file: " + outfile +
" into a source directory.");
return 0;
}
if (!cmSystemTools::FileExists(infile)) {
- cmSystemTools::Error("File ", infile, " does not exist.");
+ cmSystemTools::Error("File " + infile + " does not exist.");
return 0;
}
std::string soutfile = outfile;
- std::string sinfile = infile;
+ const std::string& sinfile = infile;
this->AddCMakeDependFile(sinfile);
cmSystemTools::ConvertToUnixSlashes(soutfile);
@@ -3492,16 +3959,15 @@ 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) {
- if (!cmSystemTools::CopyFileIfDifferent(sinfile.c_str(),
- soutfile.c_str())) {
+ if (!cmSystemTools::CopyFileIfDifferent(sinfile, soutfile)) {
return 0;
}
} else {
@@ -3513,19 +3979,18 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile,
} else {
newLineCharacters = "\n";
}
- std::string tempOutputFile = soutfile;
- tempOutputFile += ".tmp";
+ std::string tempOutputFile = cmStrCat(soutfile, ".tmp");
cmsys::ofstream fout(tempOutputFile.c_str(), omode);
if (!fout) {
- cmSystemTools::Error("Could not open file for write in copy operation ",
- tempOutputFile.c_str());
+ cmSystemTools::Error("Could not open file for write in copy operation " +
+ tempOutputFile);
cmSystemTools::ReportLastSystemError("");
return 0;
}
cmsys::ifstream fin(sinfile.c_str());
if (!fin) {
- cmSystemTools::Error("Could not open file for read in copy operation ",
- sinfile.c_str());
+ cmSystemTools::Error("Could not open file for read in copy operation " +
+ sinfile);
return 0;
}
@@ -3534,7 +3999,7 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile,
std::ostringstream e;
e << "File starts with a Byte-Order-Mark that is not UTF-8:\n "
<< sinfile;
- this->IssueMessage(cmake::FATAL_ERROR, e.str());
+ this->IssueMessage(MessageType::FATAL_ERROR, e.str());
return 0;
}
// rewind to copy BOM to output file
@@ -3545,18 +4010,17 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile,
std::string inLine;
std::string outLine;
while (cmSystemTools::GetLineFromStream(fin, inLine)) {
- outLine = "";
+ outLine.clear();
this->ConfigureString(inLine, outLine, atOnly, escapeQuotes);
fout << outLine << newLineCharacters;
}
// close the files before attempting to copy
fin.close();
fout.close();
- if (!cmSystemTools::CopyFileIfDifferent(tempOutputFile.c_str(),
- soutfile.c_str())) {
+ if (!cmSystemTools::CopyFileIfDifferent(tempOutputFile, soutfile)) {
res = 0;
} else {
- cmSystemTools::SetPermissions(soutfile.c_str(), perm);
+ cmSystemTools::SetPermissions(soutfile, perm);
}
cmSystemTools::RemoveFile(tempOutputFile);
}
@@ -3579,6 +4043,20 @@ void cmMakefile::AppendProperty(const std::string& prop, const char* value,
const char* cmMakefile::GetProperty(const std::string& prop) const
{
+ // Check for computed properties.
+ static std::string output;
+ if (prop == "TESTS") {
+ std::vector<std::string> keys;
+ // get list of keys
+ std::transform(this->Tests.begin(), this->Tests.end(),
+ std::back_inserter(keys),
+ [](decltype(this->Tests)::value_type const& pair) {
+ return pair.first;
+ });
+ output = cmJoin(keys, ";");
+ return output.c_str();
+ }
+
return this->StateSnapshot.GetDirectory().GetProperty(prop);
}
@@ -3589,7 +4067,7 @@ const char* cmMakefile::GetProperty(const std::string& prop, bool chain) const
bool cmMakefile::GetPropertyAsBool(const std::string& prop) const
{
- return cmSystemTools::IsOn(this->GetProperty(prop));
+ return cmIsOn(this->GetProperty(prop));
}
std::vector<std::string> cmMakefile::GetPropertyKeys() const
@@ -3599,11 +4077,11 @@ std::vector<std::string> cmMakefile::GetPropertyKeys() const
cmTarget* cmMakefile::FindLocalNonAliasTarget(const std::string& name) const
{
- cmTargets::iterator i = this->Targets.find(name);
+ auto i = this->Targets.find(name);
if (i != this->Targets.end()) {
return &i->second;
}
- return CM_NULLPTR;
+ return nullptr;
}
cmTest* cmMakefile::CreateTest(const std::string& testName)
@@ -3620,28 +4098,34 @@ cmTest* cmMakefile::CreateTest(const std::string& testName)
cmTest* cmMakefile::GetTest(const std::string& testName) const
{
- std::map<std::string, cmTest*>::const_iterator mi =
- this->Tests.find(testName);
+ auto mi = this->Tests.find(testName);
if (mi != this->Tests.end()) {
return mi->second;
}
- return CM_NULLPTR;
+ 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;
if (const char* deps_str = this->GetProperty("CMAKE_CONFIGURE_DEPENDS")) {
- cmSystemTools::ExpandListArgument(deps_str, deps);
+ cmExpandList(deps_str, deps);
}
- for (std::vector<std::string>::iterator i = deps.begin(); i != deps.end();
- ++i) {
- if (cmSystemTools::FileIsFullPath(i->c_str())) {
- this->AddCMakeDependFile(*i);
+ for (std::string const& dep : deps) {
+ if (cmSystemTools::FileIsFullPath(dep)) {
+ this->AddCMakeDependFile(dep);
} else {
- std::string f = this->GetCurrentSourceDirectory();
- f += "/";
- f += *i;
+ std::string f = cmStrCat(this->GetCurrentSourceDirectory(), '/', dep);
this->AddCMakeDependFile(f);
}
}
@@ -3659,7 +4143,7 @@ std::string cmMakefile::FormatListFileStack() const
std::ostringstream tmp;
size_t depth = listFiles.size();
if (depth > 0) {
- std::vector<std::string>::const_iterator it = listFiles.end();
+ auto it = listFiles.end();
do {
if (depth != listFiles.size()) {
tmp << "\n ";
@@ -3681,14 +4165,14 @@ void cmMakefile::PushScope()
this->GetState()->CreateVariableScopeSnapshot(this->StateSnapshot);
this->PushLoopBlockBarrier();
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
this->GetGlobalGenerator()->GetFileLockPool().PushFunctionScope();
#endif
}
void cmMakefile::PopScope()
{
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
this->GetGlobalGenerator()->GetFileLockPool().PopFunctionScope();
#endif
@@ -3708,8 +4192,17 @@ void cmMakefile::RaiseScope(const std::string& var, const char* varDef)
if (!this->StateSnapshot.RaiseScope(var, varDef)) {
std::ostringstream m;
m << "Cannot set \"" << var << "\": current scope has no parent.";
- this->IssueMessage(cmake::AUTHOR_WARNING, m.str());
+ this->IssueMessage(MessageType::AUTHOR_WARNING, m.str());
+ return;
+ }
+
+#ifndef CMAKE_BOOTSTRAP
+ cmVariableWatch* vv = this->GetVariableWatch();
+ if (vv) {
+ vv->VariableAccessed(var, cmVariableWatch::VARIABLE_MODIFIED_ACCESS,
+ varDef, this);
}
+#endif
}
cmTarget* cmMakefile::AddImportedTarget(const std::string& name,
@@ -3717,9 +4210,10 @@ cmTarget* cmMakefile::AddImportedTarget(const std::string& name,
bool global)
{
// Create the target.
- CM_AUTO_PTR<cmTarget> target(
- new cmTarget(name, type, global ? cmTarget::VisibilityImportedGlobally
- : cmTarget::VisibilityImported,
+ std::unique_ptr<cmTarget> target(
+ new cmTarget(name, type,
+ global ? cmTarget::VisibilityImportedGlobally
+ : cmTarget::VisibilityImported,
this));
// Add to the set of available imported targets.
@@ -3736,7 +4230,7 @@ cmTarget* cmMakefile::FindTargetToUse(const std::string& name,
{
// Look for an imported target. These take priority because they
// are more local in scope and do not have to be globally unique.
- TargetMap::const_iterator imported = this->ImportedTargets.find(name);
+ auto imported = this->ImportedTargets.find(name);
if (imported != this->ImportedTargets.end()) {
return imported->second;
}
@@ -3752,7 +4246,7 @@ cmTarget* cmMakefile::FindTargetToUse(const std::string& name,
bool cmMakefile::IsAlias(const std::string& name) const
{
- if (this->AliasTargets.find(name) != this->AliasTargets.end()) {
+ if (cmContains(this->AliasTargets, name)) {
return true;
}
return this->GetGlobalGenerator()->IsAlias(name);
@@ -3783,7 +4277,7 @@ bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg,
// target names must be globally unique
switch (this->GetPolicyStatus(cmPolicies::CMP0002)) {
case cmPolicies::WARN:
- this->IssueMessage(cmake::AUTHOR_WARNING,
+ this->IssueMessage(MessageType::AUTHOR_WARNING,
cmPolicies::GetPolicyWarning(cmPolicies::CMP0002));
CM_FALLTHROUGH;
case cmPolicies::OLD:
@@ -3791,7 +4285,7 @@ bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg,
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
this->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0002));
return true;
case cmPolicies::NEW:
@@ -3870,7 +4364,7 @@ bool cmMakefile::EnforceUniqueDir(const std::string& srcPath,
<< "to work accidentally and is being allowed for "
<< "compatibility.";
/* clang-format on */
- this->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ this->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
CM_FALLTHROUGH;
case cmPolicies::OLD:
// OLD behavior does not warn.
@@ -3889,23 +4383,13 @@ bool cmMakefile::EnforceUniqueDir(const std::string& srcPath,
<< " " << srcPath << "\n"
<< "Specify a unique binary directory name.";
/* clang-format on */
- this->IssueMessage(cmake::FATAL_ERROR, e.str());
+ this->IssueMessage(MessageType::FATAL_ERROR, e.str());
break;
}
return false;
}
-void cmMakefile::AddQtUiFileWithOptions(cmSourceFile* sf)
-{
- this->QtUiFilesWithOptions.push_back(sf);
-}
-
-std::vector<cmSourceFile*> cmMakefile::GetQtUiFilesWithOptions() const
-{
- return this->QtUiFilesWithOptions;
-}
-
static std::string const matchVariables[] = {
"CMAKE_MATCH_0", "CMAKE_MATCH_1", "CMAKE_MATCH_2", "CMAKE_MATCH_3",
"CMAKE_MATCH_4", "CMAKE_MATCH_5", "CMAKE_MATCH_6", "CMAKE_MATCH_7",
@@ -3940,7 +4424,7 @@ void cmMakefile::StoreMatches(cmsys::RegularExpression& re)
std::string const& m = re.match(i);
if (!m.empty()) {
std::string const& var = matchVariables[i];
- this->AddDefinition(var, m.c_str());
+ this->AddDefinition(var, m);
this->MarkVariableAsUsed(var);
highest = static_cast<char>('0' + i);
}
@@ -3960,17 +4444,17 @@ const char* cmMakefile::GetDefineFlagsCMP0059() const
return this->DefineFlagsOrig.c_str();
}
-cmPolicies::PolicyStatus cmMakefile::GetPolicyStatus(
- cmPolicies::PolicyID id) const
+cmPolicies::PolicyStatus cmMakefile::GetPolicyStatus(cmPolicies::PolicyID id,
+ bool parent_scope) const
{
- return this->StateSnapshot.GetPolicy(id);
+ return this->StateSnapshot.GetPolicy(id, parent_scope);
}
bool cmMakefile::PolicyOptionalWarningEnabled(std::string const& var)
{
// Check for an explicit CMAKE_POLICY_WARNING_CMP<NNNN> setting.
if (const char* val = this->GetDefinition(var)) {
- return cmSystemTools::IsOn(val);
+ return cmIsOn(val);
}
// Enable optional policy warnings with --debug-output, --trace,
// or --trace-expand.
@@ -3984,7 +4468,7 @@ bool cmMakefile::SetPolicy(const char* id, cmPolicies::PolicyStatus status)
if (!cmPolicies::GetPolicyID(id, /* out */ pid)) {
std::ostringstream e;
e << "Policy \"" << id << "\" is not known to this version of CMake.";
- this->IssueMessage(cmake::FATAL_ERROR, e.str());
+ this->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
return this->SetPolicy(pid, status);
@@ -3997,14 +4481,18 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id,
if (status != cmPolicies::NEW &&
cmPolicies::GetPolicyStatus(id) == cmPolicies::REQUIRED_ALWAYS) {
std::string msg = cmPolicies::GetRequiredAlwaysPolicyError(id);
- this->IssueMessage(cmake::FATAL_ERROR, msg);
+ this->IssueMessage(MessageType::FATAL_ERROR, msg);
return false;
}
// Deprecate old policies, especially those that require a lot
// of code to maintain the old behavior.
- if (status == cmPolicies::OLD && id <= cmPolicies::CMP0036) {
- this->IssueMessage(cmake::DEPRECATION_WARNING,
+ if (status == cmPolicies::OLD && id <= cmPolicies::CMP0067 &&
+ !(this->GetCMakeInstance()->GetIsInTryCompile() &&
+ (
+ // Policies set by cmCoreTryCompile::TryCompileCode.
+ id == cmPolicies::CMP0065))) {
+ this->IssueMessage(MessageType::DEPRECATION_WARNING,
cmPolicies::GetPolicyDeprecatedWarning(id));
}
@@ -4031,7 +4519,7 @@ void cmMakefile::PushPolicy(bool weak, cmPolicies::PolicyMap const& pm)
void cmMakefile::PopPolicy()
{
if (!this->StateSnapshot.PopPolicy()) {
- this->IssueMessage(cmake::FATAL_ERROR,
+ this->IssueMessage(MessageType::FATAL_ERROR,
"cmake_policy POP without matching PUSH");
}
}
@@ -4043,7 +4531,7 @@ void cmMakefile::PopSnapshot(bool reportError)
// reject any still-open nested policy scopes with an error.
while (!this->StateSnapshot.CanPopPolicyScope()) {
if (reportError) {
- this->IssueMessage(cmake::FATAL_ERROR,
+ this->IssueMessage(MessageType::FATAL_ERROR,
"cmake_policy PUSH without matching POP");
reportError = false;
}
@@ -4054,9 +4542,10 @@ void cmMakefile::PopSnapshot(bool reportError)
assert(this->StateSnapshot.IsValid());
}
-bool cmMakefile::SetPolicyVersion(const char* version)
+bool cmMakefile::SetPolicyVersion(std::string const& version_min,
+ std::string const& version_max)
{
- return cmPolicies::ApplyPolicyVersion(this, version);
+ return cmPolicies::ApplyPolicyVersion(this, version_min, version_max);
}
bool cmMakefile::HasCMP0054AlreadyBeenReported(
@@ -4068,7 +4557,7 @@ bool cmMakefile::HasCMP0054AlreadyBeenReported(
void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm)
{
/* Record the setting of every policy. */
- typedef cmPolicies::PolicyID PolicyID;
+ using PolicyID = cmPolicies::PolicyID;
for (PolicyID pid = cmPolicies::CMP0000; pid != cmPolicies::CMPCOUNT;
pid = PolicyID(pid + 1)) {
pm.Set(pid, this->GetPolicyStatus(pid));
@@ -4093,15 +4582,15 @@ bool cmMakefile::IgnoreErrorsCMP0061() const
}
#define FEATURE_STRING(F) , #F
-static const char* const C_FEATURES[] = { CM_NULLPTR FOR_EACH_C_FEATURE(
+static const char* const C_FEATURES[] = { nullptr FOR_EACH_C_FEATURE(
FEATURE_STRING) };
-static const char* const CXX_FEATURES[] = { CM_NULLPTR FOR_EACH_CXX_FEATURE(
+static const char* const CXX_FEATURES[] = { nullptr FOR_EACH_CXX_FEATURE(
FEATURE_STRING) };
#undef FEATURE_STRING
static const char* const C_STANDARDS[] = { "90", "99", "11" };
-static const char* const CXX_STANDARDS[] = { "98", "11", "14", "17" };
+static const char* const CXX_STANDARDS[] = { "98", "11", "14", "17", "20" };
bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
const std::string& feature,
@@ -4122,10 +4611,8 @@ bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
return false;
}
- std::vector<std::string> availableFeatures;
- cmSystemTools::ExpandListArgument(features, availableFeatures);
- if (std::find(availableFeatures.begin(), availableFeatures.end(), feature) ==
- availableFeatures.end()) {
+ std::vector<std::string> availableFeatures = cmExpandedList(features);
+ if (!cmContains(availableFeatures, feature)) {
std::ostringstream e;
e << "The compiler feature \"" << feature << "\" is not known to " << lang
<< " compiler\n\""
@@ -4135,7 +4622,7 @@ bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
if (error) {
*error = e.str();
} else {
- this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(),
this->Backtrace);
}
return false;
@@ -4143,9 +4630,9 @@ bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
target->AppendProperty("COMPILE_FEATURES", feature.c_str());
- return lang == "C"
- ? this->AddRequiredTargetCFeature(target, feature, error)
- : this->AddRequiredTargetCxxFeature(target, feature, error);
+ return lang == "C" || lang == "OBJC"
+ ? this->AddRequiredTargetCFeature(target, feature, lang, error)
+ : this->AddRequiredTargetCxxFeature(target, feature, lang, error);
}
bool cmMakefile::CompileFeatureKnown(cmTarget const* target,
@@ -4156,15 +4643,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;
@@ -4175,13 +4662,14 @@ bool cmMakefile::CompileFeatureKnown(cmTarget const* target,
} else {
e << "Specified";
}
- e << " unknown feature \"" << feature << "\" for "
- "target \""
+ e << " unknown feature \"" << feature
+ << "\" for "
+ "target \""
<< target->GetName() << "\".";
if (error) {
*error = e.str();
} else {
- this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(),
this->Backtrace);
}
return false;
@@ -4201,10 +4689,10 @@ const char* cmMakefile::CompileFeaturesAvailable(const std::string& lang,
if (error) {
*error = e.str();
} else {
- this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(),
this->Backtrace);
}
- return CM_NULLPTR;
+ return nullptr;
}
const char* featuresKnown =
@@ -4224,10 +4712,10 @@ const char* cmMakefile::CompileFeaturesAvailable(const std::string& lang,
if (error) {
*error = e.str();
} else {
- this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(),
this->Backtrace);
}
- return CM_NULLPTR;
+ return nullptr;
}
return featuresKnown;
}
@@ -4236,30 +4724,33 @@ bool cmMakefile::HaveStandardAvailable(cmTarget const* target,
std::string const& lang,
const std::string& feature) const
{
- return lang == "C" ? this->HaveCStandardAvailable(target, feature)
- : this->HaveCxxStandardAvailable(target, feature);
+ return lang == "C" || lang == "OBJC"
+ ? this->HaveCStandardAvailable(target, feature, lang)
+ : this->HaveCxxStandardAvailable(target, feature, lang);
}
bool cmMakefile::HaveCStandardAvailable(cmTarget const* target,
- const std::string& feature) const
+ const std::string& feature,
+ std::string const& lang) const
{
const char* defaultCStandard =
- this->GetDefinition("CMAKE_C_STANDARD_DEFAULT");
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
if (!defaultCStandard) {
- std::ostringstream e;
- e << "CMAKE_C_STANDARD_DEFAULT is not set. COMPILE_FEATURES support "
- "not fully configured for this compiler.";
- this->IssueMessage(cmake::INTERNAL_ERROR, e.str());
+ this->IssueMessage(
+ MessageType::INTERNAL_ERROR,
+ cmStrCat("CMAKE_", lang,
+ "_STANDARD_DEFAULT is not set. COMPILE_FEATURES support "
+ "not fully configured for this compiler."));
// 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)) {
- std::ostringstream e;
- e << "The CMAKE_C_STANDARD_DEFAULT variable contains an "
- "invalid value: \""
- << defaultCStandard << "\".";
- this->IssueMessage(cmake::INTERNAL_ERROR, e.str());
+ if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
+ cmStrCmp(defaultCStandard)) == cm::cend(C_STANDARDS)) {
+ const std::string e = cmStrCat("The CMAKE_", lang,
+ "_STANDARD_DEFAULT variable contains an "
+ "invalid value: \"",
+ defaultCStandard, "\".");
+ this->IssueMessage(MessageType::INTERNAL_ERROR, e);
return false;
}
@@ -4267,40 +4758,41 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target,
bool needC99 = false;
bool needC11 = false;
- this->CheckNeededCLanguage(feature, needC90, needC99, needC11);
+ this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11);
- const char* existingCStandard = target->GetProperty("C_STANDARD");
+ const char* existingCStandard =
+ target->GetProperty(cmStrCat(lang, "_STANDARD"));
if (!existingCStandard) {
existingCStandard = defaultCStandard;
}
- if (std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS),
- cmStrCmp(existingCStandard)) == cmArrayEnd(C_STANDARDS)) {
- std::ostringstream e;
- e << "The C_STANDARD property on target \"" << target->GetName()
- << "\" contained an invalid value: \"" << existingCStandard << "\".";
- this->IssueMessage(cmake::FATAL_ERROR, e.str());
+ if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
+ cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) {
+ const std::string e = cmStrCat(
+ "The ", lang, "_STANDARD property on target \"", target->GetName(),
+ "\" contained an invalid value: \"", existingCStandard, "\".");
+ this->IssueMessage(MessageType::FATAL_ERROR, e);
return false;
}
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;
@@ -4310,41 +4802,41 @@ bool cmMakefile::IsLaterStandard(std::string const& lang,
std::string const& lhs,
std::string const& rhs)
{
- if (lang == "C") {
+ if (lang == "C" || lang == "OBJC") {
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,
- const std::string& feature) const
+ const std::string& feature,
+ std::string const& lang) const
{
const char* defaultCxxStandard =
- this->GetDefinition("CMAKE_CXX_STANDARD_DEFAULT");
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
if (!defaultCxxStandard) {
- std::ostringstream e;
- e << "CMAKE_CXX_STANDARD_DEFAULT is not set. COMPILE_FEATURES support "
- "not fully configured for this compiler.";
- this->IssueMessage(cmake::INTERNAL_ERROR, e.str());
+ this->IssueMessage(
+ MessageType::INTERNAL_ERROR,
+ cmStrCat("CMAKE_", lang,
+ "_STANDARD_DEFAULT is not set. COMPILE_FEATURES support "
+ "not fully configured for this compiler."));
// 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)) {
- std::ostringstream e;
- e << "The CMAKE_CXX_STANDARD_DEFAULT variable contains an "
- "invalid value: \""
- << defaultCxxStandard << "\".";
- this->IssueMessage(cmake::INTERNAL_ERROR, e.str());
+ if (std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
+ cmStrCmp(defaultCxxStandard)) == cm::cend(CXX_STANDARDS)) {
+ const std::string e =
+ cmStrCat("The CMAKE_", lang, "_STANDARD_DEFAULT variable contains an ",
+ "invalid value: \"", defaultCxxStandard, "\".");
+ this->IssueMessage(MessageType::INTERNAL_ERROR, e);
return false;
}
@@ -4352,232 +4844,250 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
bool needCxx11 = false;
bool needCxx14 = false;
bool needCxx17 = false;
- this->CheckNeededCxxLanguage(feature, needCxx98, needCxx11, needCxx14,
- needCxx17);
+ bool needCxx20 = false;
+ this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14,
+ needCxx17, needCxx20);
- const char* existingCxxStandard = target->GetProperty("CXX_STANDARD");
+ const char* existingCxxStandard =
+ target->GetProperty(cmStrCat(lang, "_STANDARD"));
if (!existingCxxStandard) {
existingCxxStandard = defaultCxxStandard;
}
- if (std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS),
- cmStrCmp(existingCxxStandard)) ==
- cmArrayEnd(CXX_STANDARDS)) {
- std::ostringstream e;
- e << "The CXX_STANDARD property on target \"" << target->GetName()
- << "\" contained an invalid value: \"" << existingCxxStandard << "\".";
- this->IssueMessage(cmake::FATAL_ERROR, e.str());
+ const char* const* existingCxxLevel =
+ std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
+ cmStrCmp(existingCxxStandard));
+ if (existingCxxLevel == cm::cend(CXX_STANDARDS)) {
+ const std::string e = cmStrCat(
+ "The ", lang, "_STANDARD property on target \"", target->GetName(),
+ "\" contained an invalid value: \"", existingCxxStandard, "\".");
+ this->IssueMessage(MessageType::FATAL_ERROR, e);
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 =
+ needCxx20 ? &CXX_STANDARDS[4]
+ : needCxx17 ? &CXX_STANDARDS[3]
+ : needCxx14 ? &CXX_STANDARDS[2]
+ : needCxx11 ? &CXX_STANDARDS[1]
+ : needCxx98 ? &CXX_STANDARDS[0]
+ : nullptr;
+ /* clang-format on */
- 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,
+ std::string const& lang,
bool& needCxx98, bool& needCxx11,
- bool& needCxx14, bool& needCxx17) const
+ bool& needCxx14, bool& needCxx17,
+ bool& needCxx20) const
{
if (const char* propCxx98 =
- this->GetDefinition("CMAKE_CXX98_COMPILE_FEATURES")) {
- std::vector<std::string> props;
- cmSystemTools::ExpandListArgument(propCxx98, props);
- needCxx98 = std::find(props.begin(), props.end(), feature) != props.end();
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "98_COMPILE_FEATURES"))) {
+ std::vector<std::string> props = cmExpandedList(propCxx98);
+ needCxx98 = cmContains(props, feature);
}
if (const char* propCxx11 =
- this->GetDefinition("CMAKE_CXX11_COMPILE_FEATURES")) {
- std::vector<std::string> props;
- cmSystemTools::ExpandListArgument(propCxx11, props);
- needCxx11 = std::find(props.begin(), props.end(), feature) != props.end();
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "11_COMPILE_FEATURES"))) {
+ std::vector<std::string> props = cmExpandedList(propCxx11);
+ needCxx11 = cmContains(props, feature);
}
if (const char* propCxx14 =
- this->GetDefinition("CMAKE_CXX14_COMPILE_FEATURES")) {
- std::vector<std::string> props;
- cmSystemTools::ExpandListArgument(propCxx14, props);
- needCxx14 = std::find(props.begin(), props.end(), feature) != props.end();
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "14_COMPILE_FEATURES"))) {
+ std::vector<std::string> props = cmExpandedList(propCxx14);
+ needCxx14 = cmContains(props, feature);
}
if (const char* propCxx17 =
- this->GetDefinition("CMAKE_CXX17_COMPILE_FEATURES")) {
- std::vector<std::string> props;
- cmSystemTools::ExpandListArgument(propCxx17, props);
- needCxx17 = std::find(props.begin(), props.end(), feature) != props.end();
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "17_COMPILE_FEATURES"))) {
+ std::vector<std::string> props = cmExpandedList(propCxx17);
+ needCxx17 = cmContains(props, feature);
+ }
+ if (const char* propCxx20 =
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "20_COMPILE_FEATURES"))) {
+ std::vector<std::string> props = cmExpandedList(propCxx20);
+ needCxx20 = cmContains(props, feature);
}
}
bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
const std::string& feature,
+ std::string const& lang,
std::string* error) const
{
bool needCxx98 = false;
bool needCxx11 = false;
bool needCxx14 = false;
bool needCxx17 = false;
-
- this->CheckNeededCxxLanguage(feature, needCxx98, needCxx11, needCxx14,
- needCxx17);
-
- const char* existingCxxStandard = target->GetProperty("CXX_STANDARD");
+ bool needCxx20 = false;
+
+ this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14,
+ needCxx17, needCxx20);
+
+ const char* existingCxxStandard =
+ target->GetProperty(cmStrCat(lang, "_STANDARD"));
+ if (existingCxxStandard == nullptr) {
+ const char* defaultCxxStandard =
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
+ if (defaultCxxStandard && *defaultCxxStandard) {
+ existingCxxStandard = defaultCxxStandard;
+ }
+ }
+ 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)) {
+ const std::string e = cmStrCat(
+ "The ", lang, "_STANDARD property on target \"", target->GetName(),
+ "\" contained an invalid value: \"", existingCxxStandard, "\".");
+ if (error) {
+ *error = e;
+ } else {
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e,
+ this->Backtrace);
+ }
+ return false;
+ }
+ }
+
+ 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 CXX_STANDARD property on target \"" << target->GetName()
- << "\" contained an invalid value: \"" << existingCxxStandard << "\".";
+ 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);
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
+ e.str(), this->Backtrace);
}
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");
+
+ /* clang-format off */
+ const char* const* needCxxLevel =
+ needCxx20 ? &CXX_STANDARDS[4]
+ : 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(cmStrCat(lang, "_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;
}
void cmMakefile::CheckNeededCLanguage(const std::string& feature,
- bool& needC90, bool& needC99,
- bool& needC11) const
+ std::string const& lang, bool& needC90,
+ bool& needC99, bool& needC11) const
{
if (const char* propC90 =
- this->GetDefinition("CMAKE_C90_COMPILE_FEATURES")) {
- std::vector<std::string> props;
- cmSystemTools::ExpandListArgument(propC90, props);
- needC90 = std::find(props.begin(), props.end(), feature) != props.end();
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "90_COMPILE_FEATURES"))) {
+ std::vector<std::string> props = cmExpandedList(propC90);
+ needC90 = cmContains(props, feature);
}
if (const char* propC99 =
- this->GetDefinition("CMAKE_C99_COMPILE_FEATURES")) {
- std::vector<std::string> props;
- cmSystemTools::ExpandListArgument(propC99, props);
- needC99 = std::find(props.begin(), props.end(), feature) != props.end();
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "99_COMPILE_FEATURES"))) {
+ std::vector<std::string> props = cmExpandedList(propC99);
+ needC99 = cmContains(props, feature);
}
if (const char* propC11 =
- this->GetDefinition("CMAKE_C11_COMPILE_FEATURES")) {
- std::vector<std::string> props;
- cmSystemTools::ExpandListArgument(propC11, props);
- needC11 = std::find(props.begin(), props.end(), feature) != props.end();
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "11_COMPILE_FEATURES"))) {
+ std::vector<std::string> props = cmExpandedList(propC11);
+ needC11 = cmContains(props, feature);
}
}
bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target,
const std::string& feature,
+ std::string const& lang,
std::string* error) const
{
bool needC90 = false;
bool needC99 = false;
bool needC11 = false;
- this->CheckNeededCLanguage(feature, needC90, needC99, needC11);
+ this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11);
- const char* existingCStandard = target->GetProperty("C_STANDARD");
+ const char* existingCStandard =
+ target->GetProperty(cmStrCat(lang, "_STANDARD"));
+ if (existingCStandard == nullptr) {
+ const char* defaultCStandard =
+ this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
+ if (defaultCStandard && *defaultCStandard) {
+ existingCStandard = defaultCStandard;
+ }
+ }
if (existingCStandard) {
- if (std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS),
- cmStrCmp(existingCStandard)) == cmArrayEnd(C_STANDARDS)) {
- std::ostringstream e;
- e << "The C_STANDARD property on target \"" << target->GetName()
- << "\" contained an invalid value: \"" << existingCStandard << "\".";
+ if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
+ cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) {
+ const std::string e = cmStrCat(
+ "The ", lang, "_STANDARD property on target \"", target->GetName(),
+ "\" contained an invalid value: \"", existingCStandard, "\".");
if (error) {
- *error = e.str();
+ *error = e;
} else {
- this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e,
this->Backtrace);
}
return false;
}
}
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;
}
if (setC11) {
- target->SetProperty("C_STANDARD", "11");
+ target->SetProperty(cmStrCat(lang, "_STANDARD"), "11");
} else if (setC99) {
- target->SetProperty("C_STANDARD", "99");
+ target->SetProperty(cmStrCat(lang, "_STANDARD"), "99");
} else if (setC90) {
- target->SetProperty("C_STANDARD", "90");
+ target->SetProperty(cmStrCat(lang, "_STANDARD"), "90");
}
return true;
}
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index e65ba468f..6e5949404 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -3,33 +3,42 @@
#ifndef cmMakefile_h
#define cmMakefile_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmsys/RegularExpression.hxx"
+#include <cstddef>
#include <deque>
+#include <functional>
#include <map>
+#include <memory>
#include <set>
#include <stack>
-#include <stddef.h>
#include <string>
+#include <unordered_map>
#include <vector>
+#include <cm/string_view>
+
+#include "cmsys/RegularExpression.hxx"
+
#include "cmAlgorithms.h"
+#include "cmCustomCommandTypes.h"
#include "cmListFileCache.h"
+#include "cmMessageType.h"
#include "cmNewLineStyle.h"
#include "cmPolicies.h"
+#include "cmSourceFileLocationKind.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
-#include "cmTarget.h"
-#include "cm_auto_ptr.hxx"
-#include "cm_unordered_map.hxx"
-#include "cmake.h"
+#include "cmStringAlgorithms.h"
+
+// IWYU does not see that 'std::unordered_map<std::string, cmTarget>'
+// will not compile without the complete type.
+#include "cmTarget.h" // IWYU pragma: keep
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmSourceGroup.h"
+#if !defined(CMAKE_BOOTSTRAP)
+# include "cmSourceGroup.h"
#endif
-class cmCommand;
class cmCompiledGeneratorExpression;
class cmCustomCommandLines;
class cmExecutionStatus;
@@ -38,6 +47,7 @@ class cmExportBuildFileGenerator;
class cmFunctionBlocker;
class cmGeneratorExpressionEvaluationFile;
class cmGlobalGenerator;
+class cmImplicitDependsList;
class cmInstallGenerator;
class cmMessenger;
class cmSourceFile;
@@ -45,6 +55,33 @@ class cmState;
class cmTest;
class cmTestGenerator;
class cmVariableWatch;
+class cmake;
+
+/** Flag if byproducts shall also be considered. */
+enum class cmSourceOutputKind
+{
+ OutputOnly,
+ OutputOrByproduct
+};
+
+/** Target and source file which have a specific output. */
+struct cmSourcesWithOutput
+{
+ /** Target with byproduct. */
+ cmTarget* Target = nullptr;
+
+ /** Source file with output or byproduct. */
+ cmSourceFile* Source = nullptr;
+ bool SourceIsByproduct = false;
+};
+
+/** A type-safe wrapper for a string representing a directory id. */
+class cmDirectoryId
+{
+public:
+ cmDirectoryId(std::string s);
+ std::string String;
+};
/** \class cmMakefile
* \brief Process the input CMakeLists.txt file.
@@ -55,8 +92,6 @@ class cmVariableWatch;
*/
class cmMakefile
{
- CM_DISABLE_COPY(cmMakefile)
-
public:
/* Mark a variable as used */
void MarkVariableAsUsed(const std::string& var);
@@ -74,16 +109,20 @@ public:
*/
~cmMakefile();
- bool ReadListFile(const char* filename);
+ cmMakefile(cmMakefile const&) = delete;
+ cmMakefile& operator=(cmMakefile const&) = delete;
+
+ cmDirectoryId GetDirectoryId() const;
- bool ReadDependentFile(const char* filename, bool noPolicyScope = true);
+ bool ReadListFile(const std::string& filename);
- bool ProcessBuildsystemFile(const char* filename);
+ bool ReadDependentFile(const std::string& filename,
+ bool noPolicyScope = true);
/**
* Add a function blocker to this makefile
*/
- void AddFunctionBlocker(cmFunctionBlocker* fb);
+ void AddFunctionBlocker(std::unique_ptr<cmFunctionBlocker> fb);
/// @return whether we are processing the top CMakeLists.txt file.
bool IsRootMakefile() const;
@@ -92,8 +131,7 @@ public:
* Remove the function blocker whose scope ends with the given command.
* This returns ownership of the function blocker object.
*/
- CM_AUTO_PTR<cmFunctionBlocker> RemoveFunctionBlocker(
- cmFunctionBlocker* fb, const cmListFileFunction& lff);
+ std::unique_ptr<cmFunctionBlocker> RemoveFunctionBlocker();
/**
* Try running cmake and building a file. This is used for dynalically
@@ -101,7 +139,8 @@ public:
*/
int TryCompile(const std::string& srcdir, const std::string& bindir,
const std::string& projectName, const std::string& targetName,
- bool fast, const std::vector<std::string>* cmakeArgs,
+ bool fast, int jobs,
+ const std::vector<std::string>* cmakeArgs,
std::string& output);
bool GetIsSourceFileTryCompile() const;
@@ -112,6 +151,13 @@ public:
bool EnforceUniqueName(std::string const& name, std::string& msg,
bool isCustom = false) const;
+ using FinalAction = std::function<void(cmMakefile&)>;
+
+ /**
+ * Register an action that is executed during FinalPass
+ */
+ void AddFinalAction(FinalAction action);
+
/**
* Perform FinalPass, Library dependency analysis etc before output of the
* makefile.
@@ -119,55 +165,75 @@ public:
void ConfigureFinalPass();
/**
- * run the final pass on all commands.
+ * run all FinalActions.
*/
void FinalPass();
- /** How to handle custom commands for object libraries */
- enum ObjectLibraryCommands
- {
- RejectObjectLibraryCommands,
- AcceptObjectLibraryCommands
- };
+ /**
+ * Get the target for PRE_BUILD, PRE_LINK, or POST_BUILD commands.
+ */
+ cmTarget* GetCustomCommandTarget(
+ const std::string& target, cmObjectLibraryCommands objLibCommands) const;
/** Add a custom command to the build. */
- void AddCustomCommandToTarget(
+ cmTarget* AddCustomCommandToTarget(
const std::string& target, const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type,
+ const cmCustomCommandLines& commandLines, cmCustomCommandType type,
const char* comment, const char* workingDir, bool escapeOldStyle = true,
bool uses_terminal = false, const std::string& depfile = "",
- bool command_expand_lists = false,
- ObjectLibraryCommands objLibraryCommands = RejectObjectLibraryCommands);
+ const std::string& job_pool = "", bool command_expand_lists = false,
+ cmObjectLibraryCommands objLibCommands = cmObjectLibraryCommands::Reject);
cmSourceFile* AddCustomCommandToOutput(
- const std::vector<std::string>& outputs,
- const std::vector<std::string>& byproducts,
- const std::vector<std::string>& depends,
+ const std::string& output, const std::vector<std::string>& depends,
const std::string& main_dependency,
const cmCustomCommandLines& commandLines, const char* comment,
const char* workingDir, bool replace = false, bool escapeOldStyle = true,
bool uses_terminal = false, bool command_expand_lists = false,
- const std::string& depfile = "");
+ const std::string& depfile = "", const std::string& job_pool = "");
cmSourceFile* AddCustomCommandToOutput(
- const std::string& output, const std::vector<std::string>& depends,
+ const std::vector<std::string>& outputs,
+ const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
const std::string& main_dependency,
+ const cmImplicitDependsList& implicit_depends,
const cmCustomCommandLines& commandLines, const char* comment,
const char* workingDir, bool replace = false, bool escapeOldStyle = true,
bool uses_terminal = false, bool command_expand_lists = false,
- const std::string& depfile = "");
+ const std::string& depfile = "", const std::string& job_pool = "");
void AddCustomCommandOldStyle(const std::string& target,
const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
const std::string& source,
const cmCustomCommandLines& commandLines,
const char* comment);
+ bool AppendCustomCommandToOutput(
+ const std::string& output, const std::vector<std::string>& depends,
+ const cmImplicitDependsList& implicit_depends,
+ const cmCustomCommandLines& commandLines);
+
+ /**
+ * Add target byproducts.
+ */
+ void AddTargetByproducts(cmTarget* target,
+ const std::vector<std::string>& byproducts);
+
+ /**
+ * Add source file outputs.
+ */
+ void AddSourceOutputs(cmSourceFile* source,
+ const std::vector<std::string>& outputs,
+ const std::vector<std::string>& byproducts);
/**
* 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 AddCompileDefinition(std::string const& definition);
+ void AddCompileOption(std::string const& option);
+ void AddLinkOption(std::string const& option);
+ void AddLinkDirectory(std::string const& directory, bool before = false);
/** Create a new imported target with the name and type given. */
cmTarget* AddImportedTarget(const std::string& name,
@@ -176,36 +242,34 @@ public:
cmTarget* AddNewTarget(cmStateEnums::TargetType type,
const std::string& name);
+ /** Create a target instance for the utility. */
+ cmTarget* AddNewUtilityTarget(const std::string& utilityName,
+ cmCommandOrigin origin, bool excludeFromAll);
+
/**
* 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);
/**
- * Add a utility to the build. A utiltity target is a command that
+ * Return the utility target output source file name and the CMP0049 name.
+ */
+ cmUtilityOutput GetUtilityOutput(cmTarget* target);
+
+ /**
+ * 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,
- const std::vector<std::string>& depends, const char* workingDirectory,
- const char* command, const char* arg1 = CM_NULLPTR,
- const char* arg2 = CM_NULLPTR, const char* arg3 = CM_NULLPTR,
- const char* arg4 = CM_NULLPTR);
- cmTarget* AddUtilityCommand(
- const std::string& utilityName, bool excludeFromAll,
- const char* workingDirectory, const std::vector<std::string>& depends,
- const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
- const char* comment = CM_NULLPTR, bool uses_terminal = false,
- bool command_expand_lists = false);
- cmTarget* AddUtilityCommand(
- const std::string& utilityName, bool excludeFromAll,
- const char* workingDirectory, const std::vector<std::string>& byproducts,
+ const std::string& utilityName, cmCommandOrigin origin,
+ bool excludeFromAll, const char* workingDirectory,
+ const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
- const char* comment = CM_NULLPTR, bool uses_terminal = false,
- bool command_expand_lists = false);
+ const char* comment = nullptr, bool uses_terminal = false,
+ bool command_expand_lists = false, const std::string& job_pool = "");
/**
* Add a subdirectory to the build.
@@ -231,23 +295,22 @@ public:
* Add a variable definition to the build. This variable
* can be used in CMake to refer to lists, directories, etc.
*/
- void AddDefinition(const std::string& name, const char* value);
- ///! Add a definition to this makefile and the global cmake cache.
- void AddCacheDefinition(const std::string& name, const char* value,
- const char* doc, cmStateEnums::CacheEntryType type,
- bool force = false);
-
+ void AddDefinition(const std::string& name, cm::string_view value);
/**
* Add bool variable definition to the build.
*/
- void AddDefinition(const std::string& name, bool);
+ void AddDefinitionBool(const std::string& name, bool);
+ //! Add a definition to this makefile and the global cmake cache.
+ void AddCacheDefinition(const std::string& name, const char* value,
+ const char* doc, cmStateEnums::CacheEntryType type,
+ bool force = false);
/**
* Remove a variable definition from the build. This is not valid
* for cache entries, and will only affect the current makefile.
*/
void RemoveDefinition(const std::string& name);
- ///! Remove a definition from the cache.
+ //! Remove a definition from the cache.
void RemoveCacheDefinition(const std::string& name);
/**
@@ -259,6 +322,9 @@ public:
std::string GetConfigurations(std::vector<std::string>& configs,
bool single = true) const;
+ /** Get the configurations for dependency checking. */
+ std::vector<std::string> GetGeneratorConfigs() const;
+
/**
* Set the name of the library.
*/
@@ -268,29 +334,16 @@ public:
bool excludeFromAll = false);
void AddAlias(const std::string& libname, const std::string& tgt);
-#if defined(CMAKE_BUILD_WITH_CMAKE)
- /**
- * Add a root source group for consideration when adding a new source.
- */
- void AddSourceGroup(const std::string& name, const char* regex = CM_NULLPTR);
-
- /**
- * Add a source group for consideration when adding a new source.
- * name is tokenized.
- */
- void AddSourceGroup(const std::vector<std::string>& name,
- const char* regex = CM_NULLPTR);
-
-#endif
-
//@{
/**
- * Set, Push, Pop policy values for CMake.
- */
+ * Set, Push, Pop policy values for CMake.
+ */
bool SetPolicy(cmPolicies::PolicyID id, cmPolicies::PolicyStatus status);
bool SetPolicy(const char* id, cmPolicies::PolicyStatus status);
- cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id) const;
- bool SetPolicyVersion(const char* version);
+ cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id,
+ bool parent_scope = false) const;
+ bool SetPolicyVersion(std::string const& version_min,
+ std::string const& version_max);
void RecordPolicies(cmPolicies::PolicyMap& pm);
//@}
@@ -301,6 +354,9 @@ public:
PolicyPushPop(cmMakefile* m);
~PolicyPushPop();
+ PolicyPushPop(const PolicyPushPop&) = delete;
+ PolicyPushPop& operator=(const PolicyPushPop&) = delete;
+
private:
cmMakefile* Makefile;
};
@@ -314,21 +370,21 @@ 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.
*/
void SetArgcArgv(const std::vector<std::string>& args);
- const char* GetCurrentSourceDirectory() const;
- const char* GetCurrentBinaryDirectory() const;
+ std::string const& GetCurrentSourceDirectory() const;
+ std::string const& GetCurrentBinaryDirectory() const;
//@}
@@ -358,14 +414,13 @@ public:
return this->ComplainFileRegularExpression.c_str();
}
- /**
- * Get the list of targets
- */
- cmTargets& GetTargets() { return this->Targets; }
- /**
- * Get the list of targets, const version
- */
- const cmTargets& GetTargets() const { return this->Targets; }
+ // -- List of targets
+ using cmTargetMap = std::unordered_map<std::string, cmTarget>;
+ /** Get the target map */
+ cmTargetMap& GetTargets() { return this->Targets; }
+ /** Get the target map - const version */
+ cmTargetMap const& GetTargets() const { return this->Targets; }
+
const std::vector<cmTarget*>& GetOwnedImportedTargets() const
{
return this->ImportedTargetsOwned;
@@ -393,22 +448,32 @@ 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);
+
+ /** Get a cmSourceFile pointer for a given source name and always mark the
+ * file as generated, if the name is not found, then create the source file
+ * and return it.
+ */
+ cmSourceFile* GetOrCreateGeneratedSource(const std::string& sourceName);
void AddTargetObject(std::string const& tgtName, std::string const& objFile);
@@ -418,8 +483,9 @@ public:
* cache is then queried.
*/
const char* GetDefinition(const std::string&) const;
- const char* GetSafeDefinition(const std::string&) const;
- const char* GetRequiredDefinition(const std::string& name) const;
+ const std::string* GetDef(const std::string&) const;
+ const std::string& GetSafeDefinition(const std::string&) const;
+ const std::string& GetRequiredDefinition(const std::string& name) const;
bool IsDefinitionSet(const std::string&) const;
/**
* Get the list of all variables in the current space. If argument
@@ -445,8 +511,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;
@@ -459,9 +540,9 @@ 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)
+#if !defined(CMAKE_BOOTSTRAP)
/**
* Get the vector source groups.
*/
@@ -474,6 +555,36 @@ public:
* Get the source group
*/
cmSourceGroup* GetSourceGroup(const std::vector<std::string>& name) const;
+
+ /**
+ * Add a root source group for consideration when adding a new source.
+ */
+ void AddSourceGroup(const std::string& name, const char* regex = nullptr);
+
+ /**
+ * Add a source group for consideration when adding a new source.
+ * name is tokenized.
+ */
+ void AddSourceGroup(const std::vector<std::string>& name,
+ const char* regex = nullptr);
+
+ /**
+ * Get and existing or create a new source group.
+ */
+ cmSourceGroup* GetOrCreateSourceGroup(
+ const std::vector<std::string>& folders);
+
+ /**
+ * Get and existing or create a new source group.
+ * The name will be tokenized.
+ */
+ cmSourceGroup* GetOrCreateSourceGroup(const std::string& name);
+
+ /**
+ * find what source group this source is in
+ */
+ cmSourceGroup* FindSourceGroup(const std::string& source,
+ std::vector<cmSourceGroup>& groups) const;
#endif
/**
@@ -483,7 +594,7 @@ public:
{
return this->ListFiles;
}
- ///! When the file changes cmake will be re-run from the build system.
+ //! When the file changes cmake will be re-run from the build system.
void AddCMakeDependFile(const std::string& file)
{
this->ListFiles.push_back(file);
@@ -518,12 +629,11 @@ public:
* entry in the this->Definitions map. Also \@var\@ is
* expanded to match autoconf style expansions.
*/
- const char* ExpandVariablesInString(std::string& source) const;
- const char* ExpandVariablesInString(std::string& source, bool escapeQuotes,
- bool noEscapes, bool atOnly = false,
- const char* filename = CM_NULLPTR,
- long line = -1, bool removeEmpty = false,
- bool replaceAt = false) const;
+ const std::string& ExpandVariablesInString(std::string& source) const;
+ const std::string& ExpandVariablesInString(
+ std::string& source, bool escapeQuotes, bool noEscapes,
+ bool atOnly = false, const char* filename = nullptr, long line = -1,
+ bool removeEmpty = false, bool replaceAt = false) const;
/**
* Remove any remaining variables in the string. Anything with ${var} or
@@ -544,24 +654,21 @@ 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,
+ int ConfigureFile(const std::string& infile, const std::string& outfile,
+ bool copyonly, bool atOnly, bool escapeQuotes,
cmNewLineStyle = cmNewLineStyle());
-#if defined(CMAKE_BUILD_WITH_CMAKE)
/**
- * find what source group this source is in
+ * Print a command's invocation
*/
- cmSourceGroup* FindSourceGroup(const char* source,
- std::vector<cmSourceGroup>& groups) const;
-#endif
+ void PrintCommandTrace(const cmListFileFunction& lff) const;
/**
- * Print a command's invocation
+ * Set a callback that is invoked whenever ExecuteCommand is called.
*/
- void PrintCommandTrace(const cmListFileFunction& lff) const;
+ void OnExecuteCommand(std::function<void()> callback);
/**
* Execute a single CMake command. Returns true if the command
@@ -570,7 +677,7 @@ public:
bool ExecuteCommand(const cmListFileFunction& lff,
cmExecutionStatus& status);
- ///! Enable support for named language, if nil then all languages are
+ //! Enable support for named language, if nil then all languages are
/// enabled.
void EnableLanguage(std::vector<std::string> const& languages,
bool optional);
@@ -581,12 +688,12 @@ public:
* Get the variable watch. This is used to determine when certain variables
* are accessed.
*/
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
cmVariableWatch* GetVariableWatch() const;
#endif
- ///! Display progress or status message.
- void DisplayStatus(const char*, float) const;
+ //! Display progress or status message.
+ void DisplayStatus(const std::string&, float) const;
/**
* Expand the given list file arguments into the full set after
@@ -594,11 +701,11 @@ public:
*/
bool ExpandArguments(std::vector<cmListFileArgument> const& inArgs,
std::vector<std::string>& outArgs,
- const char* filename = CM_NULLPTR) const;
+ const char* filename = nullptr) const;
bool ExpandArguments(std::vector<cmListFileArgument> const& inArgs,
std::vector<cmExpandedCommandArgument>& outArgs,
- const char* filename = CM_NULLPTR) const;
+ const char* filename = nullptr) const;
/**
* Get the instance
@@ -614,15 +721,23 @@ public:
{
return this->SourceFiles;
}
- std::vector<cmSourceFile*>& GetSourceFiles() { return this->SourceFiles; }
/**
- * Is there a source file that has the provided source file as an output?
- * if so then return it
+ * Return the target if the provided source name is a byproduct of a utility
+ * target or a PRE_BUILD, PRE_LINK, or POST_BUILD command.
+ * Return the source file which has the provided source name as output.
+ */
+ cmSourcesWithOutput GetSourcesWithOutput(const std::string& name) const;
+
+ /**
+ * Is there a source file that has the provided source name as an output?
+ * If so then return it.
*/
- cmSourceFile* GetSourceFileWithOutput(const std::string& outName) const;
+ cmSourceFile* GetSourceFileWithOutput(
+ const std::string& name,
+ cmSourceOutputKind kind = cmSourceOutputKind::OutputOnly) const;
- ///! Add a new cmTest to the list of tests for this makefile.
+ //! Add a new cmTest to the list of tests for this makefile.
cmTest* CreateTest(const std::string& testName);
/** Get a cmTest pointer for a given test name, if the name is
@@ -631,11 +746,22 @@ 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;
+ std::string GetModulesFile(const std::string& name) const
+ {
+ bool system;
+ return this->GetModulesFile(name, system);
+ }
+
+ std::string GetModulesFile(const std::string& name, bool& system) const;
- ///! Set/Get a property of this directory
+ //! Set/Get a property of this directory
void SetProperty(const std::string& prop, const char* value);
void AppendProperty(const std::string& prop, const char* value,
bool asString = false);
@@ -644,7 +770,7 @@ public:
bool GetPropertyAsBool(const std::string& prop) const;
std::vector<std::string> GetPropertyKeys() const;
- ///! Initialize a makefile from its parent
+ //! Initialize a makefile from its parent
void InitializeFromParent(cmMakefile* parent);
void AddInstallGenerator(cmInstallGenerator* g)
@@ -657,6 +783,10 @@ public:
{
return this->InstallGenerators;
}
+ const std::vector<cmInstallGenerator*>& GetInstallGenerators() const
+ {
+ return this->InstallGenerators;
+ }
void AddTestGenerator(cmTestGenerator* g)
{
@@ -676,7 +806,11 @@ public:
cmPolicies::PolicyMap const& pm);
~FunctionPushPop();
+ FunctionPushPop(const FunctionPushPop&) = delete;
+ FunctionPushPop& operator=(const FunctionPushPop&) = delete;
+
void Quiet() { this->ReportError = false; }
+
private:
cmMakefile* Makefile;
bool ReportError;
@@ -689,7 +823,11 @@ public:
cmPolicies::PolicyMap const& pm);
~MacroPushPop();
+ MacroPushPop(const MacroPushPop&) = delete;
+ MacroPushPop& operator=(const MacroPushPop&) = delete;
+
void Quiet() { this->ReportError = false; }
+
private:
cmMakefile* Makefile;
bool ReportError;
@@ -712,32 +850,40 @@ public:
/** Helper class to push and pop scopes automatically. */
class ScopePushPop
{
- CM_DISABLE_COPY(ScopePushPop)
public:
ScopePushPop(cmMakefile* m)
: Makefile(m)
{
this->Makefile->PushScope();
}
+
~ScopePushPop() { this->Makefile->PopScope(); }
+
+ ScopePushPop(ScopePushPop const&) = delete;
+ ScopePushPop& operator=(ScopePushPop const&) = delete;
+
private:
cmMakefile* Makefile;
};
- void IssueMessage(cmake::MessageType t, std::string const& text) const;
+ void IssueMessage(MessageType t, std::string const& text) const;
/** 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;
cmBacktraceRange GetCompileOptionsBacktraces() const;
cmStringRange GetCompileDefinitionsEntries() const;
cmBacktraceRange GetCompileDefinitionsBacktraces() const;
-
- void AddQtUiFileWithOptions(cmSourceFile* sf);
- std::vector<cmSourceFile*> GetQtUiFilesWithOptions() const;
+ cmStringRange GetLinkOptionsEntries() const;
+ cmBacktraceRange GetLinkOptionsBacktraces() const;
+ cmStringRange GetLinkDirectoriesEntries() const;
+ cmBacktraceRange GetLinkDirectoriesBacktraces() const;
std::set<std::string> const& GetSystemIncludeDirectories() const
{
@@ -747,7 +893,7 @@ public:
bool PolicyOptionalWarningEnabled(std::string const& var);
bool AddRequiredTargetFeature(cmTarget* target, const std::string& feature,
- std::string* error = CM_NULLPTR) const;
+ std::string* error = nullptr) const;
bool CompileFeatureKnown(cmTarget const* target, const std::string& feature,
std::string& lang, std::string* error) const;
@@ -776,10 +922,11 @@ public:
void EnforceDirectoryLevelRules() const;
- void AddEvaluationFile(const std::string& inputFile,
- CM_AUTO_PTR<cmCompiledGeneratorExpression> outputName,
- CM_AUTO_PTR<cmCompiledGeneratorExpression> condition,
- bool inputIsContent);
+ void AddEvaluationFile(
+ const std::string& inputFile,
+ std::unique_ptr<cmCompiledGeneratorExpression> outputName,
+ std::unique_ptr<cmCompiledGeneratorExpression> condition,
+ bool inputIsContent);
std::vector<cmGeneratorExpressionEvaluationFile*> GetEvaluationFiles() const;
std::vector<cmExportBuildFileGenerator*> GetExportBuildFileGenerators()
@@ -787,9 +934,17 @@ public:
void RemoveExportBuildFileGeneratorCMP0024(cmExportBuildFileGenerator* gen);
void AddExportBuildFileGenerator(cmExportBuildFileGenerator* gen);
- // Maintain a stack of pacakge names to determine the depth of find modules
- // we are currently being called with
- std::deque<std::string> FindPackageModuleStack;
+ // Maintain a stack of package roots to allow nested PACKAGE_ROOT_PATH
+ // searches
+ std::deque<std::vector<std::string>> FindPackageRootPathStack;
+
+ void MaybeWarnCMP0074(std::string const& pkg);
+ void MaybeWarnUninitialized(std::string const& variable,
+ const char* sourceFilename) const;
+ bool IsProjectFile(const char* filename) const;
+
+ int GetRecursionDepth() const;
+ void SetRecursionDepth(int recursionDepth);
protected:
// add link libraries and directories to the target
@@ -801,9 +956,26 @@ protected:
mutable std::set<cmListFileContext> CMP0054ReportedIds;
// libraries, classes, and executables
- mutable cmTargets Targets;
+ mutable cmTargetMap Targets;
std::map<std::string, std::string> AliasTargets;
- std::vector<cmSourceFile*> SourceFiles;
+
+ using TargetsVec = std::vector<cmTarget*>;
+ TargetsVec OrderedTargets;
+
+ using SourceFileVec = std::vector<cmSourceFile*>;
+ 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.
+ using SourceFileMap = std::unordered_map<std::string, SourceFileVec>;
+ SourceFileMap SourceFileSearchIndex;
+
+ // For "Known" paths we can store a direct filename to cmSourceFile map
+ std::unordered_map<std::string, cmSourceFile*> KnownFileSearchIndex;
// Tests
std::map<std::string, cmTest*> Tests;
@@ -822,16 +994,14 @@ 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&);
std::string DefineFlagsOrig;
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
std::vector<cmSourceGroup> SourceGroups;
size_t ObjectLibrariesSourceGroupIndex;
#endif
- std::vector<cmCommand*> FinalPassCommands;
+ std::vector<FinalAction> FinalActions;
cmGlobalGenerator* GlobalGenerator;
bool IsFunctionBlocked(const cmListFileFunction& lff,
cmExecutionStatus& status);
@@ -839,6 +1009,7 @@ protected:
private:
cmStateSnapshot StateSnapshot;
cmListFileBacktrace Backtrace;
+ int RecursionDepth;
void ReadListFile(cmListFile const& listFile,
const std::string& filenametoread);
@@ -848,7 +1019,10 @@ private:
bool EnforceUniqueDir(const std::string& srcPath,
const std::string& binPath) const;
- typedef std::vector<cmFunctionBlocker*> FunctionBlockersType;
+ std::function<void()> ExecuteCommandCallback;
+ using FunctionBlockerPtr = std::unique_ptr<cmFunctionBlocker>;
+ using FunctionBlockersType =
+ std::stack<FunctionBlockerPtr, std::vector<FunctionBlockerPtr>>;
FunctionBlockersType FunctionBlockers;
std::vector<FunctionBlockersType::size_type> FunctionBlockerBarriers;
void PushFunctionBlockerBarrier();
@@ -871,7 +1045,7 @@ private:
friend class cmParseFileScope;
std::vector<cmTarget*> ImportedTargetsOwned;
- typedef CM_UNORDERED_MAP<std::string, cmTarget*> TargetMap;
+ using TargetMap = std::unordered_map<std::string, cmTarget*>;
TargetMap ImportedTargets;
// Internal policy stack management.
@@ -879,63 +1053,122 @@ private:
cmPolicies::PolicyMap const& pm = cmPolicies::PolicyMap());
void PopPolicy();
void PopSnapshot(bool reportError = true);
- friend class cmCMakePolicyCommand;
+ friend bool cmCMakePolicyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
class IncludeScope;
-
friend class IncludeScope;
- class ListFileScope;
+ class ListFileScope;
friend class ListFileScope;
- class BuildsystemFileScope;
+ class BuildsystemFileScope;
friend class BuildsystemFileScope;
// CMP0053 == old
- cmake::MessageType ExpandVariablesInStringOld(
- std::string& errorstr, std::string& source, bool escapeQuotes,
- bool noEscapes, bool atOnly, const char* filename, long line,
- bool removeEmpty, bool replaceAt) const;
+ MessageType ExpandVariablesInStringOld(std::string& errorstr,
+ std::string& source,
+ bool escapeQuotes, bool noEscapes,
+ bool atOnly, const char* filename,
+ long line, bool removeEmpty,
+ bool replaceAt) const;
// CMP0053 == new
- cmake::MessageType ExpandVariablesInStringNew(
- std::string& errorstr, std::string& source, bool escapeQuotes,
- bool noEscapes, bool atOnly, const char* filename, long line,
- bool removeEmpty, bool replaceAt) const;
+ MessageType ExpandVariablesInStringNew(std::string& errorstr,
+ std::string& source,
+ bool escapeQuotes, bool noEscapes,
+ bool atOnly, const char* filename,
+ long line, bool replaceAt) const;
+
+ bool ValidateCustomCommand(const cmCustomCommandLines& commandLines) const;
+
+ void CreateGeneratedSources(const std::vector<std::string>& outputs);
+
+ void CommitCustomCommandToTarget(
+ cmTarget* target, const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines, cmCustomCommandType type,
+ const char* comment, const char* workingDir, bool escapeOldStyle,
+ bool uses_terminal, const std::string& depfile,
+ const std::string& job_pool, bool command_expand_lists);
+ cmSourceFile* CommitCustomCommandToOutput(
+ const std::vector<std::string>& outputs,
+ const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
+ const std::string& main_dependency,
+ const cmImplicitDependsList& implicit_depends,
+ const cmCustomCommandLines& commandLines, const char* comment,
+ const char* workingDir, bool replace, bool escapeOldStyle,
+ bool uses_terminal, bool command_expand_lists, const std::string& depfile,
+ const std::string& job_pool);
+ void CommitAppendCustomCommandToOutput(
+ const std::string& output, const std::vector<std::string>& depends,
+ const cmImplicitDependsList& implicit_depends,
+ const cmCustomCommandLines& commandLines);
+
+ void CommitUtilityCommand(cmTarget* target, const cmUtilityOutput& force,
+ const char* workingDirectory,
+ const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines,
+ bool escapeOldStyle, const char* comment,
+ bool uses_terminal, bool command_expand_lists,
+ const std::string& job_pool);
+
+ /**
+ * See LinearGetSourceFileWithOutput for background information
+ */
+ cmTarget* LinearGetTargetWithOutput(const std::string& name) const;
+
/**
- * Old version of GetSourceFileWithOutput(const std::string&) kept for
- * backward-compatibility. It implements a linear search and support
- * relative file paths. It is used as a fall back by
- * GetSourceFileWithOutput(const std::string&).
+ * Generalized old version of GetSourceFileWithOutput kept for
+ * backward-compatibility. It implements a linear search and supports
+ * relative file paths. It is used as a fall back by GetSourceFileWithOutput
+ * and GetSourcesWithOutput.
*/
- cmSourceFile* LinearGetSourceFileWithOutput(const std::string& cname) const;
+ cmSourceFile* LinearGetSourceFileWithOutput(const std::string& name,
+ cmSourceOutputKind kind,
+ bool& byproduct) const;
+
+ struct SourceEntry
+ {
+ cmSourcesWithOutput Sources;
+ };
// A map for fast output to input look up.
- typedef CM_UNORDERED_MAP<std::string, cmSourceFile*> OutputToSourceMap;
+ using OutputToSourceMap = std::unordered_map<std::string, SourceEntry>;
OutputToSourceMap OutputToSource;
- void UpdateOutputToSourceMap(std::vector<std::string> const& outputs,
- cmSourceFile* source);
- void UpdateOutputToSourceMap(std::string const& output,
- cmSourceFile* source);
+ void UpdateOutputToSourceMap(std::string const& byproduct, cmTarget* target);
+ void UpdateOutputToSourceMap(std::string const& output, cmSourceFile* source,
+ bool byproduct);
- std::vector<cmSourceFile*> QtUiFilesWithOptions;
+ /**
+ * Return if the provided source file might have a custom command.
+ */
+ bool MightHaveCustomCommand(const std::string& name) const;
bool AddRequiredTargetCFeature(cmTarget* target, const std::string& feature,
- std::string* error = CM_NULLPTR) const;
+ std::string const& lang,
+ std::string* error = nullptr) const;
bool AddRequiredTargetCxxFeature(cmTarget* target,
const std::string& feature,
- std::string* error = CM_NULLPTR) const;
+ std::string const& lang,
+ std::string* error = nullptr) const;
- void CheckNeededCLanguage(const std::string& feature, bool& needC90,
+ void CheckNeededCLanguage(const std::string& feature,
+ std::string const& lang, bool& needC90,
bool& needC99, bool& needC11) const;
- void CheckNeededCxxLanguage(const std::string& feature, bool& needCxx98,
+ void CheckNeededCxxLanguage(const std::string& feature,
+ std::string const& lang, bool& needCxx98,
bool& needCxx11, bool& needCxx14,
- bool& needCxx17) const;
+ bool& needCxx17, bool& needCxx20) const;
bool HaveCStandardAvailable(cmTarget const* target,
- const std::string& feature) const;
+ const std::string& feature,
+ std::string const& lang) const;
bool HaveCxxStandardAvailable(cmTarget const* target,
- const std::string& feature) const;
+ const std::string& feature,
+ std::string const& lang) const;
void CheckForUnusedVariables() const;
@@ -943,8 +1176,9 @@ private:
bool WarnUnused;
bool CheckSystemVars;
bool CheckCMP0000;
+ std::set<std::string> WarnedCMP0074;
bool IsSourceFileTryCompile;
- mutable bool SuppressWatches;
+ mutable bool SuppressSideEffects;
};
#endif
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 359b9fdbb..40265ff65 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -2,11 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMakefileExecutableTargetGenerator.h"
-#include <algorithm>
+#include <set>
#include <sstream>
#include <string>
+#include <utility>
#include <vector>
+#include <cm/memory>
+
+#include "cmAlgorithms.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalUnixMakefileGenerator3.h"
@@ -22,28 +26,24 @@
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cm_auto_ptr.hxx"
-#include "cmake.h"
cmMakefileExecutableTargetGenerator::cmMakefileExecutableTargetGenerator(
cmGeneratorTarget* target)
: cmMakefileTargetGenerator(target)
{
this->CustomCommandDriver = OnDepends;
- this->GeneratorTarget->GetExecutableNames(
- this->TargetNameOut, this->TargetNameReal, this->TargetNameImport,
- this->TargetNamePDB, this->ConfigName);
+ this->TargetNames =
+ this->GeneratorTarget->GetExecutableNames(this->ConfigName);
this->OSXBundleGenerator =
- new cmOSXBundleGenerator(target, this->ConfigName);
+ cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
}
-cmMakefileExecutableTargetGenerator::~cmMakefileExecutableTargetGenerator()
-{
- delete this->OSXBundleGenerator;
-}
+cmMakefileExecutableTargetGenerator::~cmMakefileExecutableTargetGenerator() =
+ default;
void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
{
@@ -69,9 +69,6 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
this->WriteExecutableRule(true);
}
- // Write the requires target.
- this->WriteTargetRequiresRules();
-
// Write clean target
this->WriteTargetCleanRules();
@@ -86,29 +83,24 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
bool relink)
{
-#ifdef CMAKE_BUILD_WITH_CMAKE
- const std::string cuda_lang("CUDA");
- cmGeneratorTarget::LinkClosure const* closure =
- this->GeneratorTarget->GetLinkClosure(this->ConfigName);
-
- const bool hasCUDA =
- (std::find(closure->Languages.begin(), closure->Languages.end(),
- cuda_lang) != closure->Languages.end());
- if (!hasCUDA) {
+#ifndef CMAKE_BOOTSTRAP
+ const bool requiresDeviceLinking = requireDeviceLinking(
+ *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName);
+ if (!requiresDeviceLinking) {
return;
}
std::vector<std::string> commands;
- // Build list of dependencies.
- std::vector<std::string> depends;
- this->AppendLinkDepends(depends);
-
// Get the language to use for linking this library.
std::string linkLanguage = "CUDA";
- std::string const objExt =
+ std::string const& objExt =
this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION");
+ // Build list of dependencies.
+ std::vector<std::string> depends;
+ this->AppendLinkDepends(depends, linkLanguage);
+
// Get the name of the device object to generate.
std::string const targetOutputReal =
this->GeneratorTarget->ObjectDirectory + "cmake_device_link" + objExt;
@@ -119,14 +111,13 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
cmLocalUnixMakefileGenerator3::EchoProgress progress;
this->MakeEchoProgress(progress);
// Add the link message.
- std::string buildEcho = "Linking ";
- buildEcho += linkLanguage;
- buildEcho += " device code ";
- buildEcho += this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(),
- this->DeviceLinkObject),
- cmOutputConverter::SHELL);
+ std::string buildEcho =
+ cmStrCat("Linking ", linkLanguage, " device code ",
+ this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(),
+ this->DeviceLinkObject),
+ cmOutputConverter::SHELL));
this->LocalGenerator->AppendEcho(
commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
}
@@ -138,11 +129,10 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
// Add flags to create an executable.
// Add symbol export flags if necessary.
if (this->GeneratorTarget->IsExecutableWithExports()) {
- std::string export_flag_var = "CMAKE_EXE_EXPORTS_";
- export_flag_var += linkLanguage;
- export_flag_var += "_FLAG";
+ std::string export_flag_var =
+ cmStrCat("CMAKE_EXE_EXPORTS_", linkLanguage, "_FLAG");
this->LocalGenerator->AppendFlags(
- linkFlags, this->Makefile->GetDefinition(export_flag_var));
+ linkFlags, this->Makefile->GetSafeDefinition(export_flag_var));
}
this->LocalGenerator->AppendFlags(linkFlags,
@@ -157,12 +147,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
linkLanguage, this->ConfigName);
// Add target-specific linker flags.
- this->LocalGenerator->AppendFlags(
- linkFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
- std::string linkFlagsConfig = "LINK_FLAGS_";
- linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
- this->LocalGenerator->AppendFlags(
- linkFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
+ this->GetTargetLinkFlags(linkFlags, linkLanguage);
// Construct a list of files associated with this executable that
// may need to be cleaned.
@@ -178,7 +163,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
const std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_EXECUTABLE";
const std::string linkRule = this->GetLinkRule(linkRuleVar);
std::vector<std::string> commands1;
- cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
+ cmExpandList(linkRule, real_link_commands);
bool useResponseFileForObjects =
this->CheckUseResponseFileForObjects(linkLanguage);
@@ -193,7 +178,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
// Set path conversion for link script shells.
this->LocalGenerator->SetLinkScriptShell(useLinkScript);
- CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+ std::unique_ptr<cmLinkLineComputer> linkLineComputer(
new cmLinkLineDeviceComputer(
this->LocalGenerator,
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
@@ -247,20 +232,18 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
const char* val = this->LocalGenerator->GetRuleLauncher(
this->GeneratorTarget, "RULE_LAUNCH_LINK");
if (val && *val) {
- launcher = val;
- launcher += " ";
+ launcher = cmStrCat(val, ' ');
}
- CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+ std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->LocalGenerator->CreateRulePlaceholderExpander());
// Expand placeholders in the commands.
rulePlaceholderExpander->SetTargetImpLib(targetOutputReal);
- for (std::vector<std::string>::iterator i = real_link_commands.begin();
- i != real_link_commands.end(); ++i) {
- *i = launcher + *i;
- rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, *i,
- vars);
+ for (std::string& real_link_command : real_link_commands) {
+ real_link_command = cmStrCat(launcher, real_link_command);
+ rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+ real_link_command, vars);
}
// Restore path conversion to normal shells.
@@ -280,11 +263,11 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
this->LocalGenerator->CreateCDCommand(
commands1, this->Makefile->GetCurrentBinaryDirectory(),
this->LocalGenerator->GetBinaryDirectory());
- commands.insert(commands.end(), commands1.begin(), commands1.end());
+ cmAppend(commands, commands1);
commands1.clear();
// Write the build rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
targetOutputReal, depends, commands,
false);
@@ -292,8 +275,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
this->WriteTargetDriverRule(targetOutputReal, relink);
// Clean all the possible executable names and symlinks.
- this->CleanFiles.insert(this->CleanFiles.end(), exeCleanFiles.begin(),
- exeCleanFiles.end());
+ this->CleanFiles.insert(exeCleanFiles.begin(), exeCleanFiles.end());
#else
static_cast<void>(relink);
#endif
@@ -303,61 +285,48 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
{
std::vector<std::string> commands;
- // Build list of dependencies.
- std::vector<std::string> depends;
- this->AppendLinkDepends(depends);
- if (!this->DeviceLinkObject.empty()) {
- depends.push_back(this->DeviceLinkObject);
- }
-
// Get the name of the executable to generate.
- std::string targetName;
- std::string targetNameReal;
- std::string targetNameImport;
- std::string targetNamePDB;
- this->GeneratorTarget->GetExecutableNames(targetName, targetNameReal,
- targetNameImport, targetNamePDB,
- this->ConfigName);
+ cmGeneratorTarget::Names targetNames =
+ this->GeneratorTarget->GetExecutableNames(this->ConfigName);
// Construct the full path version of the names.
std::string outpath = this->GeneratorTarget->GetDirectory(this->ConfigName);
if (this->GeneratorTarget->IsAppBundleOnApple()) {
- this->OSXBundleGenerator->CreateAppBundle(targetName, outpath);
+ this->OSXBundleGenerator->CreateAppBundle(targetNames.Output, outpath);
}
- outpath += "/";
+ outpath += '/';
std::string outpathImp;
if (relink) {
- outpath = this->Makefile->GetCurrentBinaryDirectory();
- outpath += cmake::GetCMakeFilesDirectory();
- outpath += "/CMakeRelink.dir";
- cmSystemTools::MakeDirectory(outpath.c_str());
- outpath += "/";
- if (!targetNameImport.empty()) {
+ outpath = cmStrCat(this->Makefile->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/CMakeRelink.dir");
+ cmSystemTools::MakeDirectory(outpath);
+ outpath += '/';
+ if (!targetNames.ImportLibrary.empty()) {
outpathImp = outpath;
}
} else {
- cmSystemTools::MakeDirectory(outpath.c_str());
- if (!targetNameImport.empty()) {
+ cmSystemTools::MakeDirectory(outpath);
+ if (!targetNames.ImportLibrary.empty()) {
outpathImp = this->GeneratorTarget->GetDirectory(
this->ConfigName, cmStateEnums::ImportLibraryArtifact);
- cmSystemTools::MakeDirectory(outpathImp.c_str());
- outpathImp += "/";
+ 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());
- pdbOutputPath += "/";
+ cmSystemTools::MakeDirectory(pdbOutputPath);
+ pdbOutputPath += '/';
- std::string targetFullPath = outpath + targetName;
- std::string targetFullPathReal = outpath + targetNameReal;
- std::string targetFullPathPDB = pdbOutputPath + targetNamePDB;
- std::string targetFullPathImport = outpathImp + targetNameImport;
+ std::string targetFullPath = outpath + targetNames.Output;
+ std::string targetFullPathReal = outpath + targetNames.Real;
+ std::string targetFullPathPDB = pdbOutputPath + targetNames.PDB;
+ std::string targetFullPathImport = outpathImp + targetNames.ImportLibrary;
std::string targetOutPathPDB = this->LocalGenerator->ConvertToOutputFormat(
targetFullPathPDB, cmOutputConverter::SHELL);
// Convert to the output path to use in constructing commands.
@@ -382,20 +351,25 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// Make sure we have a link language.
if (linkLanguage.empty()) {
- cmSystemTools::Error("Cannot determine link language for target \"",
- this->GeneratorTarget->GetName().c_str(), "\".");
+ cmSystemTools::Error("Cannot determine link language for target \"" +
+ this->GeneratorTarget->GetName() + "\".");
return;
}
+ // Build list of dependencies.
+ std::vector<std::string> depends;
+ this->AppendLinkDepends(depends, linkLanguage);
+ if (!this->DeviceLinkObject.empty()) {
+ depends.push_back(this->DeviceLinkObject);
+ }
+
this->NumberOfProgressActions++;
if (!this->NoRuleMessages) {
cmLocalUnixMakefileGenerator3::EchoProgress progress;
this->MakeEchoProgress(progress);
// Add the link message.
- std::string buildEcho = "Linking ";
- buildEcho += linkLanguage;
- buildEcho += " executable ";
- buildEcho += targetOutPath;
+ std::string buildEcho =
+ cmStrCat("Linking ", linkLanguage, " executable ", targetOutPath);
this->LocalGenerator->AppendEcho(
commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
}
@@ -410,19 +384,19 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
if (this->GeneratorTarget->GetPropertyAsBool("WIN32_EXECUTABLE")) {
this->LocalGenerator->AppendFlags(
- linkFlags, this->Makefile->GetDefinition("CMAKE_CREATE_WIN32_EXE"));
+ linkFlags, this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE"));
} else {
this->LocalGenerator->AppendFlags(
- linkFlags, this->Makefile->GetDefinition("CMAKE_CREATE_CONSOLE_EXE"));
+ linkFlags,
+ this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE"));
}
// Add symbol export flags if necessary.
if (this->GeneratorTarget->IsExecutableWithExports()) {
- std::string export_flag_var = "CMAKE_EXE_EXPORTS_";
- export_flag_var += linkLanguage;
- export_flag_var += "_FLAG";
+ std::string export_flag_var =
+ cmStrCat("CMAKE_EXE_EXPORTS_", linkLanguage, "_FLAG");
this->LocalGenerator->AppendFlags(
- linkFlags, this->Makefile->GetDefinition(export_flag_var));
+ linkFlags, this->Makefile->GetSafeDefinition(export_flag_var));
}
this->LocalGenerator->AppendFlags(linkFlags,
@@ -441,15 +415,10 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
linkLanguage, this->ConfigName);
// Add target-specific linker flags.
- this->LocalGenerator->AppendFlags(
- linkFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
- std::string linkFlagsConfig = "LINK_FLAGS_";
- linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
- this->LocalGenerator->AppendFlags(
- linkFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
+ this->GetTargetLinkFlags(linkFlags, linkLanguage);
{
- CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+ std::unique_ptr<cmLinkLineComputer> linkLineComputer(
this->CreateLinkLineComputer(
this->LocalGenerator,
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
@@ -470,19 +439,19 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// clean set just in case.
exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(),
- (targetFullPath + ".manifest").c_str()));
+ targetFullPath + ".manifest"));
#endif
- if (targetNameReal != targetName) {
+ if (this->TargetNames.Real != this->TargetNames.Output) {
exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal));
}
- if (!targetNameImport.empty()) {
+ if (!this->TargetNames.ImportLibrary.empty()) {
exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(),
targetFullPathImport));
std::string implib;
- if (this->GeneratorTarget->GetImplibGNUtoMS(targetFullPathImport,
- implib)) {
+ if (this->GeneratorTarget->GetImplibGNUtoMS(
+ this->ConfigName, targetFullPathImport, implib)) {
exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(), implib));
}
@@ -491,7 +460,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// List the PDB for cleaning only when the whole target is
// cleaned. We do not want to delete the .pdb file just before
// linking the target.
- this->CleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ this->CleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathPDB));
// Add the pre-build and pre-link rules building but not when relinking.
@@ -509,20 +478,18 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// Construct the main link rule.
std::vector<std::string> real_link_commands;
- std::string linkRuleVar = "CMAKE_";
- linkRuleVar += linkLanguage;
- linkRuleVar += "_LINK_EXECUTABLE";
+ std::string linkRuleVar = this->GeneratorTarget->GetCreateRuleVariable(
+ linkLanguage, this->ConfigName);
std::string linkRule = this->GetLinkRule(linkRuleVar);
std::vector<std::string> commands1;
- cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
+ cmExpandList(linkRule, real_link_commands);
if (this->GeneratorTarget->IsExecutableWithExports()) {
// If a separate rule for creating an import library is specified
// add it now.
- std::string implibRuleVar = "CMAKE_";
- implibRuleVar += linkLanguage;
- implibRuleVar += "_CREATE_IMPORT_LIBRARY";
+ std::string implibRuleVar =
+ cmStrCat("CMAKE_", linkLanguage, "_CREATE_IMPORT_LIBRARY");
if (const char* rule = this->Makefile->GetDefinition(implibRuleVar)) {
- cmSystemTools::ExpandListArgument(rule, real_link_commands);
+ cmExpandList(rule, real_link_commands);
}
}
@@ -539,7 +506,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// Set path conversion for link script shells.
this->LocalGenerator->SetLinkScriptShell(useLinkScript);
- CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+ std::unique_ptr<cmLinkLineComputer> linkLineComputer(
this->CreateLinkLineComputer(
this->LocalGenerator,
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
@@ -617,11 +584,11 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
vars.Manifests = manifests.c_str();
if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
- std::string cmakeCommand = this->LocalGenerator->ConvertToOutputFormat(
- cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
- cmakeCommand += " -E __run_iwyu --lwyu=";
- cmakeCommand += targetOutPathReal;
- real_link_commands.push_back(cmakeCommand);
+ std::string cmakeCommand =
+ cmStrCat(this->LocalGenerator->ConvertToOutputFormat(
+ cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
+ " -E __run_co_compile --lwyu=", targetOutPathReal);
+ real_link_commands.push_back(std::move(cmakeCommand));
}
std::string launcher;
@@ -629,20 +596,18 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
const char* val = this->LocalGenerator->GetRuleLauncher(
this->GeneratorTarget, "RULE_LAUNCH_LINK");
if (val && *val) {
- launcher = val;
- launcher += " ";
+ launcher = cmStrCat(val, ' ');
}
- CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+ std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->LocalGenerator->CreateRulePlaceholderExpander());
// Expand placeholders in the commands.
rulePlaceholderExpander->SetTargetImpLib(targetOutPathImport);
- for (std::vector<std::string>::iterator i = real_link_commands.begin();
- i != real_link_commands.end(); ++i) {
- *i = launcher + *i;
- rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, *i,
- vars);
+ for (std::string& real_link_command : real_link_commands) {
+ real_link_command = cmStrCat(launcher, real_link_command);
+ rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+ real_link_command, vars);
}
// Restore path conversion to normal shells.
@@ -662,20 +627,19 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
this->LocalGenerator->CreateCDCommand(
commands1, this->Makefile->GetCurrentBinaryDirectory(),
this->LocalGenerator->GetBinaryDirectory());
- commands.insert(commands.end(), commands1.begin(), commands1.end());
+ cmAppend(commands, commands1);
commands1.clear();
// Add a rule to create necessary symlinks for the library.
if (targetOutPath != targetOutPathReal) {
- std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_executable ";
- symlink += targetOutPathReal;
- symlink += " ";
- symlink += targetOutPath;
- commands1.push_back(symlink);
+ std::string symlink =
+ cmStrCat("$(CMAKE_COMMAND) -E cmake_symlink_executable ",
+ targetOutPathReal, ' ', targetOutPath);
+ commands1.push_back(std::move(symlink));
this->LocalGenerator->CreateCDCommand(
commands1, this->Makefile->GetCurrentBinaryDirectory(),
this->LocalGenerator->GetBinaryDirectory());
- commands.insert(commands.end(), commands1.begin(), commands1.end());
+ cmAppend(commands, commands1);
commands1.clear();
}
@@ -687,7 +651,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
}
// Write the build rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
targetFullPathReal, depends, commands,
false);
@@ -698,7 +662,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
depends.clear();
commands.clear();
depends.push_back(targetFullPathReal);
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
targetFullPath, depends, commands,
false);
}
@@ -707,6 +671,5 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
this->WriteTargetDriverRule(targetFullPath, relink);
// Clean all the possible executable names and symlinks.
- this->CleanFiles.insert(this->CleanFiles.end(), exeCleanFiles.begin(),
- exeCleanFiles.end());
+ this->CleanFiles.insert(exeCleanFiles.begin(), exeCleanFiles.end());
}
diff --git a/Source/cmMakefileExecutableTargetGenerator.h b/Source/cmMakefileExecutableTargetGenerator.h
index 01aa6270c..b9bbe8667 100644
--- a/Source/cmMakefileExecutableTargetGenerator.h
+++ b/Source/cmMakefileExecutableTargetGenerator.h
@@ -3,7 +3,7 @@
#ifndef cmMakefileExecutableTargetGenerator_h
#define cmMakefileExecutableTargetGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
@@ -15,11 +15,11 @@ class cmMakefileExecutableTargetGenerator : public cmMakefileTargetGenerator
{
public:
cmMakefileExecutableTargetGenerator(cmGeneratorTarget* target);
- ~cmMakefileExecutableTargetGenerator() CM_OVERRIDE;
+ ~cmMakefileExecutableTargetGenerator() override;
/* the main entry point for this class. Writes the Makefiles associated
with this target */
- void WriteRuleFiles() CM_OVERRIDE;
+ void WriteRuleFiles() override;
protected:
virtual void WriteExecutableRule(bool relink);
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 3d1594bdb..54a66065c 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -2,10 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMakefileLibraryTargetGenerator.h"
-#include <algorithm>
+#include <cstddef>
+#include <set>
#include <sstream>
+#include <utility>
#include <vector>
+#include <cm/memory>
+
+#include "cmAlgorithms.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalUnixMakefileGenerator3.h"
@@ -21,9 +26,8 @@
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cm_auto_ptr.hxx"
-#include "cmake.h"
cmMakefileLibraryTargetGenerator::cmMakefileLibraryTargetGenerator(
cmGeneratorTarget* target)
@@ -31,20 +35,17 @@ cmMakefileLibraryTargetGenerator::cmMakefileLibraryTargetGenerator(
{
this->CustomCommandDriver = OnDepends;
if (this->GeneratorTarget->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
- this->GeneratorTarget->GetLibraryNames(
- this->TargetNameOut, this->TargetNameSO, this->TargetNameReal,
- this->TargetNameImport, this->TargetNamePDB, this->ConfigName);
+ this->TargetNames =
+ this->GeneratorTarget->GetLibraryNames(this->ConfigName);
}
this->OSXBundleGenerator =
- new cmOSXBundleGenerator(target, this->ConfigName);
+ cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
}
-cmMakefileLibraryTargetGenerator::~cmMakefileLibraryTargetGenerator()
-{
- delete this->OSXBundleGenerator;
-}
+cmMakefileLibraryTargetGenerator::~cmMakefileLibraryTargetGenerator() =
+ default;
void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
{
@@ -89,9 +90,6 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
break;
}
- // Write the requires target.
- this->WriteTargetRequiresRules();
-
// Write clean target
this->WriteTargetCleanRules();
@@ -117,7 +115,7 @@ void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules()
this->AppendObjectDepends(depends);
// Write the rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
this->GeneratorTarget->GetName(),
depends, commands, true);
@@ -127,22 +125,11 @@ void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules()
void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
{
- const std::string cuda_lang("CUDA");
- cmGeneratorTarget::LinkClosure const* closure =
- this->GeneratorTarget->GetLinkClosure(this->ConfigName);
-
- const bool hasCUDA =
- (std::find(closure->Languages.begin(), closure->Languages.end(),
- cuda_lang) != closure->Languages.end());
-
- const bool resolveDeviceSymbols =
- this->GeneratorTarget->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
- if (hasCUDA && resolveDeviceSymbols) {
+ const bool requiresDeviceLinking = requireDeviceLinking(
+ *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName);
+ if (requiresDeviceLinking) {
std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
- std::string extraFlags;
- this->LocalGenerator->AppendFlags(
- extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
- this->WriteDeviceLibraryRules(linkRuleVar, extraFlags, false);
+ this->WriteDeviceLibraryRules(linkRuleVar, false);
}
std::string linkLanguage =
@@ -153,7 +140,7 @@ void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
std::string extraFlags;
this->LocalGenerator->GetStaticLibraryFlags(
- extraFlags, cmSystemTools::UpperCase(this->ConfigName),
+ extraFlags, cmSystemTools::UpperCase(this->ConfigName), linkLanguage,
this->GeneratorTarget);
this->WriteLibraryRules(linkRuleVar, extraFlags, false);
}
@@ -166,40 +153,25 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
}
if (!relink) {
- const std::string cuda_lang("CUDA");
- cmGeneratorTarget::LinkClosure const* closure =
- this->GeneratorTarget->GetLinkClosure(this->ConfigName);
-
- const bool hasCUDA =
- (std::find(closure->Languages.begin(), closure->Languages.end(),
- cuda_lang) != closure->Languages.end());
- if (hasCUDA) {
+ const bool requiresDeviceLinking = requireDeviceLinking(
+ *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName);
+ if (requiresDeviceLinking) {
std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
- std::string extraFlags;
- this->LocalGenerator->AppendFlags(
- extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
- this->WriteDeviceLibraryRules(linkRuleVar, extraFlags, relink);
+ this->WriteDeviceLibraryRules(linkRuleVar, relink);
}
}
std::string linkLanguage =
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
- std::string linkRuleVar = "CMAKE_";
- linkRuleVar += linkLanguage;
- linkRuleVar += "_CREATE_SHARED_LIBRARY";
+ std::string linkRuleVar =
+ cmStrCat("CMAKE_", linkLanguage, "_CREATE_SHARED_LIBRARY");
std::string extraFlags;
- this->LocalGenerator->AppendFlags(
- extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
- std::string linkFlagsConfig = "LINK_FLAGS_";
- linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
- this->LocalGenerator->AppendFlags(
- extraFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
-
+ this->GetTargetLinkFlags(extraFlags, linkLanguage);
this->LocalGenerator->AddConfigVariableFlags(
extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->ConfigName);
- CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+ std::unique_ptr<cmLinkLineComputer> linkLineComputer(
this->CreateLinkLineComputer(
this->LocalGenerator,
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
@@ -214,41 +186,26 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
{
-
if (!relink) {
- const std::string cuda_lang("CUDA");
- cmGeneratorTarget::LinkClosure const* closure =
- this->GeneratorTarget->GetLinkClosure(this->ConfigName);
-
- const bool hasCUDA =
- (std::find(closure->Languages.begin(), closure->Languages.end(),
- cuda_lang) != closure->Languages.end());
- if (hasCUDA) {
+ const bool requiresDeviceLinking = requireDeviceLinking(
+ *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName);
+ if (requiresDeviceLinking) {
std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
- std::string extraFlags;
- this->LocalGenerator->AppendFlags(
- extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
- this->WriteDeviceLibraryRules(linkRuleVar, extraFlags, relink);
+ this->WriteDeviceLibraryRules(linkRuleVar, relink);
}
}
std::string linkLanguage =
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
- std::string linkRuleVar = "CMAKE_";
- linkRuleVar += linkLanguage;
- linkRuleVar += "_CREATE_SHARED_MODULE";
+ std::string linkRuleVar =
+ cmStrCat("CMAKE_", linkLanguage, "_CREATE_SHARED_MODULE");
std::string extraFlags;
- this->LocalGenerator->AppendFlags(
- extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
- std::string linkFlagsConfig = "LINK_FLAGS_";
- linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
- this->LocalGenerator->AppendFlags(
- extraFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
+ this->GetTargetLinkFlags(extraFlags, linkLanguage);
this->LocalGenerator->AddConfigVariableFlags(
extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->ConfigName);
- CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+ std::unique_ptr<cmLinkLineComputer> linkLineComputer(
this->CreateLinkLineComputer(
this->LocalGenerator,
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
@@ -262,17 +219,11 @@ void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink)
{
std::string linkLanguage =
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
- std::string linkRuleVar = "CMAKE_";
- linkRuleVar += linkLanguage;
- linkRuleVar += "_CREATE_MACOSX_FRAMEWORK";
+ std::string linkRuleVar =
+ cmStrCat("CMAKE_", linkLanguage, "_CREATE_MACOSX_FRAMEWORK");
std::string extraFlags;
- this->LocalGenerator->AppendFlags(
- extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
- std::string linkFlagsConfig = "LINK_FLAGS_";
- linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
- this->LocalGenerator->AppendFlags(
- extraFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
+ this->GetTargetLinkFlags(extraFlags, linkLanguage);
this->LocalGenerator->AddConfigVariableFlags(
extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->ConfigName);
@@ -280,25 +231,25 @@ void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink)
}
void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules(
- const std::string& linkRuleVar, const std::string& extraFlags, bool relink)
+ const std::string& linkRuleVar, bool relink)
{
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
// TODO: Merge the methods that call this method to avoid
// code duplication.
std::vector<std::string> commands;
- // Build list of dependencies.
- std::vector<std::string> depends;
- this->AppendLinkDepends(depends);
-
// Get the language to use for linking this library.
std::string linkLanguage = "CUDA";
std::string const objExt =
this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION");
+ // Build list of dependencies.
+ std::vector<std::string> depends;
+ this->AppendLinkDepends(depends, linkLanguage);
+
// Create set of linking flags.
std::string linkFlags;
- this->LocalGenerator->AppendFlags(linkFlags, extraFlags);
+ this->GetTargetLinkFlags(linkFlags, linkLanguage);
// Get the name of the device object to generate.
std::string const targetOutputReal =
@@ -310,18 +261,19 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules(
cmLocalUnixMakefileGenerator3::EchoProgress progress;
this->MakeEchoProgress(progress);
// Add the link message.
- std::string buildEcho = "Linking " + linkLanguage + " device code ";
- buildEcho += this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(),
- this->DeviceLinkObject),
- cmOutputConverter::SHELL);
+ std::string buildEcho =
+ cmStrCat("Linking ", linkLanguage, " device code ",
+ this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(),
+ this->DeviceLinkObject),
+ cmOutputConverter::SHELL));
this->LocalGenerator->AppendEcho(
commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
}
// Clean files associated with this library.
- std::vector<std::string> libCleanFiles;
- libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ std::set<std::string> libCleanFiles;
+ libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal));
// Determine whether a link script will be used.
@@ -346,19 +298,16 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules(
// Collect up flags to link in needed libraries.
std::string linkLibs;
- if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY) {
-
- CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
- new cmLinkLineDeviceComputer(
- this->LocalGenerator,
- this->LocalGenerator->GetStateSnapshot().GetDirectory()));
- linkLineComputer->SetForResponse(useResponseFileForLibs);
- linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
- linkLineComputer->SetRelink(relink);
+ std::unique_ptr<cmLinkLineComputer> linkLineComputer(
+ new cmLinkLineDeviceComputer(
+ this->LocalGenerator,
+ this->LocalGenerator->GetStateSnapshot().GetDirectory()));
+ linkLineComputer->SetForResponse(useResponseFileForLibs);
+ linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
+ linkLineComputer->SetRelink(relink);
- this->CreateLinkLibs(linkLineComputer.get(), linkLibs,
- useResponseFileForLibs, depends);
- }
+ this->CreateLinkLibs(linkLineComputer.get(), linkLibs,
+ useResponseFileForLibs, depends);
// Construct object file lists that may be needed to expand the
// rule.
@@ -406,31 +355,28 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules(
const char* val = this->LocalGenerator->GetRuleLauncher(
this->GeneratorTarget, "RULE_LAUNCH_LINK");
if (val && *val) {
- launcher = val;
- launcher += " ";
+ launcher = cmStrCat(val, ' ');
}
- CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+ std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->LocalGenerator->CreateRulePlaceholderExpander());
// Construct the main link rule and expand placeholders.
rulePlaceholderExpander->SetTargetImpLib(targetOutputReal);
std::string linkRule = this->GetLinkRule(linkRuleVar);
- cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
+ cmExpandList(linkRule, real_link_commands);
// Expand placeholders.
- for (std::vector<std::string>::iterator i = real_link_commands.begin();
- i != real_link_commands.end(); ++i) {
- *i = launcher + *i;
- rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, *i,
- vars);
+ for (std::string& real_link_command : real_link_commands) {
+ real_link_command = cmStrCat(launcher, real_link_command);
+ rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+ real_link_command, vars);
}
// Restore path conversion to normal shells.
this->LocalGenerator->SetLinkScriptShell(false);
// Clean all the possible library names and symlinks.
- this->CleanFiles.insert(this->CleanFiles.end(), libCleanFiles.begin(),
- libCleanFiles.end());
+ this->CleanFiles.insert(libCleanFiles.begin(), libCleanFiles.end());
}
std::vector<std::string> commands1;
@@ -447,21 +393,20 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules(
this->LocalGenerator->CreateCDCommand(
commands1, this->Makefile->GetCurrentBinaryDirectory(),
this->LocalGenerator->GetBinaryDirectory());
- commands.insert(commands.end(), commands1.begin(), commands1.end());
+ cmAppend(commands, commands1);
commands1.clear();
// Compute the list of outputs.
std::vector<std::string> outputs(1, targetOutputReal);
// Write the build rule.
- this->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR, outputs, depends,
+ this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs, depends,
commands, false);
// Write the main driver rule to build everything in this target.
this->WriteTargetDriverRule(targetOutputReal, relink);
#else
static_cast<void>(linkRuleVar);
- static_cast<void>(extraFlags);
static_cast<void>(relink);
#endif
}
@@ -473,24 +418,24 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
// code duplication.
std::vector<std::string> commands;
- // Build list of dependencies.
- std::vector<std::string> depends;
- this->AppendLinkDepends(depends);
- if (!this->DeviceLinkObject.empty()) {
- depends.push_back(this->DeviceLinkObject);
- }
-
// Get the language to use for linking this library.
std::string linkLanguage =
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
// Make sure we have a link language.
if (linkLanguage.empty()) {
- cmSystemTools::Error("Cannot determine link language for target \"",
- this->GeneratorTarget->GetName().c_str(), "\".");
+ cmSystemTools::Error("Cannot determine link language for target \"" +
+ this->GeneratorTarget->GetName() + "\".");
return;
}
+ // Build list of dependencies.
+ std::vector<std::string> depends;
+ this->AppendLinkDepends(depends, linkLanguage);
+ if (!this->DeviceLinkObject.empty()) {
+ depends.push_back(this->DeviceLinkObject);
+ }
+
// Create set of linking flags.
std::string linkFlags;
this->LocalGenerator->AppendFlags(linkFlags, extraFlags);
@@ -505,61 +450,56 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
}
// Construct the name of the library.
- std::string targetName;
- std::string targetNameSO;
- std::string targetNameReal;
- std::string targetNameImport;
- std::string targetNamePDB;
- this->GeneratorTarget->GetLibraryNames(targetName, targetNameSO,
- targetNameReal, targetNameImport,
- targetNamePDB, this->ConfigName);
+ this->GeneratorTarget->GetLibraryNames(this->ConfigName);
// Construct the full path version of the names.
std::string outpath;
std::string outpathImp;
if (this->GeneratorTarget->IsFrameworkOnApple()) {
outpath = this->GeneratorTarget->GetDirectory(this->ConfigName);
- this->OSXBundleGenerator->CreateFramework(targetName, outpath);
- outpath += "/";
+ this->OSXBundleGenerator->CreateFramework(this->TargetNames.Output,
+ outpath);
+ outpath += '/';
} else if (this->GeneratorTarget->IsCFBundleOnApple()) {
outpath = this->GeneratorTarget->GetDirectory(this->ConfigName);
- this->OSXBundleGenerator->CreateCFBundle(targetName, outpath);
- outpath += "/";
+ this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output,
+ outpath);
+ outpath += '/';
} else if (relink) {
- outpath = this->Makefile->GetCurrentBinaryDirectory();
- outpath += cmake::GetCMakeFilesDirectory();
- outpath += "/CMakeRelink.dir";
- cmSystemTools::MakeDirectory(outpath.c_str());
- outpath += "/";
- if (!targetNameImport.empty()) {
+ outpath = cmStrCat(this->Makefile->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/CMakeRelink.dir");
+ cmSystemTools::MakeDirectory(outpath);
+ outpath += '/';
+ if (!this->TargetNames.ImportLibrary.empty()) {
outpathImp = outpath;
}
} else {
outpath = this->GeneratorTarget->GetDirectory(this->ConfigName);
- cmSystemTools::MakeDirectory(outpath.c_str());
- outpath += "/";
- if (!targetNameImport.empty()) {
+ cmSystemTools::MakeDirectory(outpath);
+ outpath += '/';
+ if (!this->TargetNames.ImportLibrary.empty()) {
outpathImp = this->GeneratorTarget->GetDirectory(
this->ConfigName, cmStateEnums::ImportLibraryArtifact);
- cmSystemTools::MakeDirectory(outpathImp.c_str());
- outpathImp += "/";
+ 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;
- std::string targetFullPathPDB = pdbOutputPath + targetNamePDB;
- std::string targetFullPathSO = outpath + targetNameSO;
- std::string targetFullPathReal = outpath + targetNameReal;
- std::string targetFullPathImport = outpathImp + targetNameImport;
+ std::string targetFullPath = outpath + this->TargetNames.Output;
+ std::string targetFullPathPDB = pdbOutputPath + this->TargetNames.PDB;
+ std::string targetFullPathSO = outpath + this->TargetNames.SharedObject;
+ std::string targetFullPathReal = outpath + this->TargetNames.Real;
+ std::string targetFullPathImport =
+ outpathImp + this->TargetNames.ImportLibrary;
// Construct the output path version of the names for use in command
// arguments.
@@ -590,8 +530,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
cmLocalUnixMakefileGenerator3::EchoProgress progress;
this->MakeEchoProgress(progress);
// Add the link message.
- std::string buildEcho = "Linking ";
- buildEcho += linkLanguage;
+ std::string buildEcho = cmStrCat("Linking ", linkLanguage);
switch (this->GeneratorTarget->GetType()) {
case cmStateEnums::STATIC_LIBRARY:
buildEcho += " static library ";
@@ -615,8 +554,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
}
// Clean files associated with this library.
- std::vector<std::string> libCleanFiles;
- libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ std::set<std::string> libCleanFiles;
+ libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathReal));
std::vector<std::string> commands1;
@@ -628,26 +567,27 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
this->LocalGenerator->CreateCDCommand(
commands1, this->Makefile->GetCurrentBinaryDirectory(),
this->LocalGenerator->GetBinaryDirectory());
- commands.insert(commands.end(), commands1.begin(), commands1.end());
+ cmAppend(commands, commands1);
commands1.clear();
}
- if (targetName != targetNameReal) {
- libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ if (this->TargetNames.Output != this->TargetNames.Real) {
+ libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPath));
}
- if (targetNameSO != targetNameReal && targetNameSO != targetName) {
- libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ if (this->TargetNames.SharedObject != this->TargetNames.Real &&
+ this->TargetNames.SharedObject != this->TargetNames.Output) {
+ libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathSO));
}
- if (!targetNameImport.empty()) {
- libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ if (!this->TargetNames.ImportLibrary.empty()) {
+ libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(),
targetFullPathImport));
std::string implib;
- if (this->GeneratorTarget->GetImplibGNUtoMS(targetFullPathImport,
- implib)) {
- libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ if (this->GeneratorTarget->GetImplibGNUtoMS(
+ this->ConfigName, targetFullPathImport, implib)) {
+ libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(), implib));
}
}
@@ -655,16 +595,16 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
// List the PDB for cleaning only when the whole target is
// cleaned. We do not want to delete the .pdb file just before
// linking the target.
- this->CleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ this->CleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(), targetFullPathPDB));
#ifdef _WIN32
// There may be a manifest file for this target. Add it to the
// clean set just in case.
if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY) {
- libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
+ libCleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(),
- (targetFullPath + ".manifest").c_str()));
+ targetFullPath + ".manifest"));
}
#endif
@@ -694,35 +634,32 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
std::string::size_type archiveCommandLimit = std::string::npos;
if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
haveStaticLibraryRule = this->Makefile->IsDefinitionSet(linkRuleVar);
- std::string arCreateVar = "CMAKE_";
- arCreateVar += linkLanguage;
- arCreateVar += "_ARCHIVE_CREATE";
+ std::string arCreateVar =
+ cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_CREATE");
arCreateVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
arCreateVar, linkLanguage, this->ConfigName);
if (const char* rule = this->Makefile->GetDefinition(arCreateVar)) {
- cmSystemTools::ExpandListArgument(rule, archiveCreateCommands);
+ cmExpandList(rule, archiveCreateCommands);
}
- std::string arAppendVar = "CMAKE_";
- arAppendVar += linkLanguage;
- arAppendVar += "_ARCHIVE_APPEND";
+ std::string arAppendVar =
+ cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_APPEND");
arAppendVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
arAppendVar, linkLanguage, this->ConfigName);
if (const char* rule = this->Makefile->GetDefinition(arAppendVar)) {
- cmSystemTools::ExpandListArgument(rule, archiveAppendCommands);
+ cmExpandList(rule, archiveAppendCommands);
}
- std::string arFinishVar = "CMAKE_";
- arFinishVar += linkLanguage;
- arFinishVar += "_ARCHIVE_FINISH";
+ std::string arFinishVar =
+ cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_FINISH");
arFinishVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
arFinishVar, linkLanguage, this->ConfigName);
if (const char* rule = this->Makefile->GetDefinition(arFinishVar)) {
- cmSystemTools::ExpandListArgument(rule, archiveFinishCommands);
+ cmExpandList(rule, archiveFinishCommands);
}
}
@@ -736,10 +673,14 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
// Archiving rules never use a response file.
useResponseFileForObjects = false;
- // Limit the length of individual object lists to less than the
- // 32K command line length limit on Windows. We could make this a
- // platform file variable but this should work everywhere.
- archiveCommandLimit = 30000;
+ // Limit the length of individual object lists to less than half of
+ // the command line length limit (leaving half for other flags).
+ // This may result in several calls to the archiver.
+ if (size_t limit = cmSystemTools::CalculateCommandLineLengthLimit()) {
+ archiveCommandLimit = limit / 2;
+ } else {
+ archiveCommandLimit = 8000;
+ }
}
// Expand the rule variables.
@@ -755,7 +696,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
std::string linkLibs;
if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY) {
- CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+ std::unique_ptr<cmLinkLineComputer> linkLineComputer(
this->CreateLinkLineComputer(
this->LocalGenerator,
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
@@ -832,7 +773,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
vars.ObjectsQuoted = buildObjs.c_str();
if (this->GeneratorTarget->HasSOName(this->ConfigName)) {
vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage);
- vars.TargetSOName = targetNameSO.c_str();
+ vars.TargetSOName = this->TargetNames.SharedObject.c_str();
}
vars.LinkFlags = linkFlags.c_str();
@@ -870,11 +811,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
const char* val = this->LocalGenerator->GetRuleLauncher(
this->GeneratorTarget, "RULE_LAUNCH_LINK");
if (val && *val) {
- launcher = val;
- launcher += " ";
+ launcher = cmStrCat(val, ' ');
}
- CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+ std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->LocalGenerator->CreateRulePlaceholderExpander());
// Construct the main link rule and expand placeholders.
rulePlaceholderExpander->SetTargetImpLib(targetOutPathImport);
@@ -894,62 +834,55 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
}
// Create the archive with the first set of objects.
- std::vector<std::string>::iterator osi = object_strings.begin();
+ auto osi = object_strings.begin();
{
vars.Objects = osi->c_str();
- for (std::vector<std::string>::const_iterator i =
- archiveCreateCommands.begin();
- i != archiveCreateCommands.end(); ++i) {
- std::string cmd = launcher + *i;
+ for (std::string const& acc : archiveCreateCommands) {
+ 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.
for (++osi; osi != object_strings.end(); ++osi) {
vars.Objects = osi->c_str();
- for (std::vector<std::string>::const_iterator i =
- archiveAppendCommands.begin();
- i != archiveAppendCommands.end(); ++i) {
- std::string cmd = launcher + *i;
+ for (std::string const& aac : archiveAppendCommands) {
+ 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.
vars.Objects = "";
- for (std::vector<std::string>::const_iterator i =
- archiveFinishCommands.begin();
- i != archiveFinishCommands.end(); ++i) {
- std::string cmd = launcher + *i;
+ for (std::string const& afc : archiveFinishCommands) {
+ std::string cmd = launcher + afc;
rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, cmd,
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 {
// Get the set of commands.
std::string linkRule = this->GetLinkRule(linkRuleVar);
- cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
+ cmExpandList(linkRule, real_link_commands);
if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE") &&
(this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY)) {
- std::string cmakeCommand = this->LocalGenerator->ConvertToOutputFormat(
- cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
- cmakeCommand += " -E __run_iwyu --lwyu=";
- cmakeCommand += targetOutPathReal;
- real_link_commands.push_back(cmakeCommand);
+ std::string cmakeCommand = cmStrCat(
+ this->LocalGenerator->ConvertToOutputFormat(
+ cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
+ " -E __run_co_compile --lwyu=", targetOutPathReal);
+ real_link_commands.push_back(std::move(cmakeCommand));
}
// Expand placeholders.
- for (std::vector<std::string>::iterator i = real_link_commands.begin();
- i != real_link_commands.end(); ++i) {
- *i = launcher + *i;
- rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, *i,
- vars);
+ for (std::string& real_link_command : real_link_commands) {
+ real_link_command = cmStrCat(launcher, real_link_command);
+ rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+ real_link_command, vars);
}
}
@@ -970,24 +903,21 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
this->LocalGenerator->CreateCDCommand(
commands1, this->Makefile->GetCurrentBinaryDirectory(),
this->LocalGenerator->GetBinaryDirectory());
- commands.insert(commands.end(), commands1.begin(), commands1.end());
+ cmAppend(commands, commands1);
commands1.clear();
// Add a rule to create necessary symlinks for the library.
// Frameworks are handled by cmOSXBundleGenerator.
if (targetOutPath != targetOutPathReal &&
!this->GeneratorTarget->IsFrameworkOnApple()) {
- std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library ";
- symlink += targetOutPathReal;
- symlink += " ";
- symlink += targetOutPathSO;
- symlink += " ";
- symlink += targetOutPath;
- commands1.push_back(symlink);
+ std::string symlink =
+ cmStrCat("$(CMAKE_COMMAND) -E cmake_symlink_library ", targetOutPathReal,
+ ' ', targetOutPathSO, ' ', targetOutPath);
+ commands1.push_back(std::move(symlink));
this->LocalGenerator->CreateCDCommand(
commands1, this->Makefile->GetCurrentBinaryDirectory(),
this->LocalGenerator->GetBinaryDirectory());
- commands.insert(commands.end(), commands1.begin(), commands1.end());
+ cmAppend(commands, commands1);
commands1.clear();
}
@@ -1000,21 +930,21 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
// Compute the list of outputs.
std::vector<std::string> outputs(1, targetFullPathReal);
- if (targetNameSO != targetNameReal) {
+ if (this->TargetNames.SharedObject != this->TargetNames.Real) {
outputs.push_back(targetFullPathSO);
}
- if (targetName != targetNameSO && targetName != targetNameReal) {
+ if (this->TargetNames.Output != this->TargetNames.SharedObject &&
+ this->TargetNames.Output != this->TargetNames.Real) {
outputs.push_back(targetFullPath);
}
// Write the build rule.
- this->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR, outputs, depends,
+ this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs, depends,
commands, false);
// Write the main driver rule to build everything in this target.
this->WriteTargetDriverRule(targetFullPath, relink);
// Clean all the possible library names and symlinks.
- this->CleanFiles.insert(this->CleanFiles.end(), libCleanFiles.begin(),
- libCleanFiles.end());
+ this->CleanFiles.insert(libCleanFiles.begin(), libCleanFiles.end());
}
diff --git a/Source/cmMakefileLibraryTargetGenerator.h b/Source/cmMakefileLibraryTargetGenerator.h
index da1d8b65c..ca22b099d 100644
--- a/Source/cmMakefileLibraryTargetGenerator.h
+++ b/Source/cmMakefileLibraryTargetGenerator.h
@@ -3,23 +3,23 @@
#ifndef cmMakefileLibraryTargetGenerator_h
#define cmMakefileLibraryTargetGenerator_h
-#include "cmConfigure.h"
-
-#include "cmMakefileTargetGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
+#include "cmMakefileTargetGenerator.h"
+
class cmGeneratorTarget;
class cmMakefileLibraryTargetGenerator : public cmMakefileTargetGenerator
{
public:
cmMakefileLibraryTargetGenerator(cmGeneratorTarget* target);
- ~cmMakefileLibraryTargetGenerator() CM_OVERRIDE;
+ ~cmMakefileLibraryTargetGenerator() override;
/* the main entry point for this class. Writes the Makefiles associated
with this target */
- void WriteRuleFiles() CM_OVERRIDE;
+ void WriteRuleFiles() override;
protected:
void WriteObjectLibraryRules();
@@ -27,8 +27,7 @@ protected:
void WriteSharedLibraryRules(bool relink);
void WriteModuleLibraryRules(bool relink);
- void WriteDeviceLibraryRules(const std::string& linkRule,
- const std::string& extraFlags, bool relink);
+ void WriteDeviceLibraryRules(const std::string& linkRule, bool relink);
void WriteLibraryRules(const std::string& linkRule,
const std::string& extraFlags, bool relink);
// MacOSX Framework support methods
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index a4511b63b..dd8a389cb 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -2,8 +2,9 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMakefileTargetGenerator.h"
+#include <cstdio>
+#include <memory>
#include <sstream>
-#include <stdio.h>
#include <utility>
#include "cmAlgorithms.h"
@@ -14,30 +15,32 @@
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmLocalCommonGenerator.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmMakefileExecutableTargetGenerator.h"
#include "cmMakefileLibraryTargetGenerator.h"
#include "cmMakefileUtilityTargetGenerator.h"
#include "cmOutputConverter.h"
+#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cm_auto_ptr.hxx"
#include "cmake.h"
cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target)
: cmCommonTargetGenerator(target)
- , OSXBundleGenerator(CM_NULLPTR)
- , MacOSXContentGenerator(CM_NULLPTR)
+ , OSXBundleGenerator(nullptr)
+ , MacOSXContentGenerator(nullptr)
{
- this->BuildFileStream = CM_NULLPTR;
- this->InfoFileStream = CM_NULLPTR;
- this->FlagFileStream = CM_NULLPTR;
+ this->BuildFileStream = nullptr;
+ this->InfoFileStream = nullptr;
+ this->FlagFileStream = nullptr;
this->CustomCommandDriver = OnBuild;
this->LocalGenerator =
static_cast<cmLocalUnixMakefileGenerator3*>(target->GetLocalGenerator());
@@ -47,7 +50,7 @@ cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target)
this->NoRuleMessages = false;
if (const char* ruleStatus =
cm->GetState()->GetGlobalProperty("RULE_MESSAGES")) {
- this->NoRuleMessages = cmSystemTools::IsOff(ruleStatus);
+ this->NoRuleMessages = cmIsOff(ruleStatus);
}
MacOSXContentGenerator = new MacOSXContentGeneratorType(this);
}
@@ -60,7 +63,7 @@ cmMakefileTargetGenerator::~cmMakefileTargetGenerator()
cmMakefileTargetGenerator* cmMakefileTargetGenerator::New(
cmGeneratorTarget* tgt)
{
- cmMakefileTargetGenerator* result = CM_NULLPTR;
+ cmMakefileTargetGenerator* result = nullptr;
switch (tgt->GetType()) {
case cmStateEnums::EXECUTABLE:
@@ -82,6 +85,26 @@ cmMakefileTargetGenerator* cmMakefileTargetGenerator::New(
return result;
}
+void cmMakefileTargetGenerator::GetTargetLinkFlags(
+ std::string& flags, const std::string& linkLanguage)
+{
+ this->LocalGenerator->AppendFlags(
+ flags, this->GeneratorTarget->GetSafeProperty("LINK_FLAGS"));
+
+ std::string linkFlagsConfig =
+ cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(this->ConfigName));
+ this->LocalGenerator->AppendFlags(
+ flags, this->GeneratorTarget->GetSafeProperty(linkFlagsConfig));
+
+ std::vector<std::string> opts;
+ this->GeneratorTarget->GetLinkOptions(opts, this->ConfigName, linkLanguage);
+ // LINK_OPTIONS are escaped.
+ this->LocalGenerator->AppendCompileOptions(flags, opts);
+
+ this->LocalGenerator->AppendPositionIndependentLinkerFlags(
+ flags, this->GeneratorTarget, this->ConfigName, linkLanguage);
+}
+
void cmMakefileTargetGenerator::CreateRuleFile()
{
// Create a directory for this target.
@@ -89,17 +112,16 @@ 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;
- this->BuildFileName += "/build.make";
- this->BuildFileNameFull = this->TargetBuildDirectoryFull;
- this->BuildFileNameFull += "/build.make";
+ this->BuildFileName = cmStrCat(this->TargetBuildDirectory, "/build.make");
+ this->BuildFileNameFull =
+ cmStrCat(this->TargetBuildDirectoryFull, "/build.make");
// Construct the rule file name.
- this->ProgressFileNameFull = this->TargetBuildDirectoryFull;
- this->ProgressFileNameFull += "/progress.make";
+ this->ProgressFileNameFull =
+ cmStrCat(this->TargetBuildDirectoryFull, "/progress.make");
// reset the progress count
this->NumberOfProgressActions = 0;
@@ -107,12 +129,12 @@ void cmMakefileTargetGenerator::CreateRuleFile()
// Open the rule file. This should be copy-if-different because the
// rules may depend on this file itself.
this->BuildFileStream =
- new cmGeneratedFileStream(this->BuildFileNameFull.c_str(), false,
+ new cmGeneratedFileStream(this->BuildFileNameFull, false,
this->GlobalGenerator->GetMakefileEncoding());
- this->BuildFileStream->SetCopyIfDifferent(true);
if (!this->BuildFileStream) {
return;
}
+ this->BuildFileStream->SetCopyIfDifferent(true);
this->LocalGenerator->WriteDisclaimer(*this->BuildFileStream);
if (this->GlobalGenerator->AllowDeleteOnError()) {
std::vector<std::string> no_depends;
@@ -126,70 +148,110 @@ void cmMakefileTargetGenerator::CreateRuleFile()
void cmMakefileTargetGenerator::WriteTargetBuildRules()
{
- const std::string& config =
- this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
-
- // write the custom commands for this target
- // Look for files registered for cleaning in this directory.
- if (const char* additional_clean_files =
+ // -- Write the custom commands for this target
+
+ // Evaluates generator expressions and expands prop_value
+ auto evaluatedFiles =
+ [this](const char* prop_value) -> std::vector<std::string> {
+ std::vector<std::string> files;
+ cmExpandList(
+ cmGeneratorExpression::Evaluate(prop_value, this->LocalGenerator,
+ this->ConfigName, this->GeneratorTarget),
+ files);
+ return files;
+ };
+
+ // Look for additional files registered for cleaning in this directory.
+ if (const char* prop_value =
this->Makefile->GetProperty("ADDITIONAL_MAKE_CLEAN_FILES")) {
- cmGeneratorExpression ge;
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge =
- ge.Parse(additional_clean_files);
-
- cmSystemTools::ExpandListArgument(
- cge->Evaluate(this->LocalGenerator, config, false, this->GeneratorTarget,
- CM_NULLPTR, CM_NULLPTR),
- this->CleanFiles);
+ std::vector<std::string> const files = evaluatedFiles(prop_value);
+ this->CleanFiles.insert(files.begin(), files.end());
+ }
+
+ // Look for additional files registered for cleaning in this target.
+ if (const char* prop_value =
+ this->GeneratorTarget->GetProperty("ADDITIONAL_CLEAN_FILES")) {
+ std::vector<std::string> const files = evaluatedFiles(prop_value);
+ // For relative path support
+ std::string const& binaryDir =
+ this->LocalGenerator->GetCurrentBinaryDirectory();
+ for (std::string const& cfl : files) {
+ this->CleanFiles.insert(cmSystemTools::CollapseFullPath(cfl, binaryDir));
+ }
}
// add custom commands to the clean rules?
const char* clean_no_custom = this->Makefile->GetProperty("CLEAN_NO_CUSTOM");
- bool clean = cmSystemTools::IsOff(clean_no_custom);
+ bool clean = cmIsOff(clean_no_custom);
// First generate the object rule files. Save a list of all object
// files for this target.
std::vector<cmSourceFile const*> customCommands;
- this->GeneratorTarget->GetCustomCommands(customCommands, config);
+ this->GeneratorTarget->GetCustomCommands(customCommands, this->ConfigName);
std::string currentBinDir =
this->LocalGenerator->GetCurrentBinaryDirectory();
- for (std::vector<cmSourceFile const*>::const_iterator si =
- customCommands.begin();
- si != customCommands.end(); ++si) {
- cmCustomCommandGenerator ccg(*(*si)->GetCustomCommand(), this->ConfigName,
+ for (cmSourceFile const* sf : customCommands) {
+ cmCustomCommandGenerator ccg(*sf->GetCustomCommand(), this->ConfigName,
this->LocalGenerator);
this->GenerateCustomRuleFile(ccg);
if (clean) {
const std::vector<std::string>& outputs = ccg.GetOutputs();
- for (std::vector<std::string>::const_iterator o = outputs.begin();
- o != outputs.end(); ++o) {
- this->CleanFiles.push_back(
- this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, *o));
+ for (std::string const& output : outputs) {
+ this->CleanFiles.insert(
+ this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir,
+ output));
+ }
+ const std::vector<std::string>& byproducts = ccg.GetByproducts();
+ for (std::string const& byproduct : byproducts) {
+ this->CleanFiles.insert(
+ this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir,
+ byproduct));
+ }
+ }
+ }
+
+ // Add byproducts from build events to the clean rules
+ if (clean) {
+ std::vector<cmCustomCommand> buildEventCommands =
+ this->GeneratorTarget->GetPreBuildCommands();
+
+ cmAppend(buildEventCommands, this->GeneratorTarget->GetPreLinkCommands());
+ cmAppend(buildEventCommands,
+ this->GeneratorTarget->GetPostBuildCommands());
+
+ for (const auto& be : buildEventCommands) {
+ cmCustomCommandGenerator beg(be, this->ConfigName, this->LocalGenerator);
+ const std::vector<std::string>& byproducts = beg.GetByproducts();
+ for (std::string const& byproduct : byproducts) {
+ this->CleanFiles.insert(
+ this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir,
+ byproduct));
}
}
}
std::vector<cmSourceFile const*> headerSources;
- this->GeneratorTarget->GetHeaderSources(headerSources, config);
+ this->GeneratorTarget->GetHeaderSources(headerSources, this->ConfigName);
this->OSXBundleGenerator->GenerateMacOSXContentStatements(
headerSources, this->MacOSXContentGenerator);
std::vector<cmSourceFile const*> extraSources;
- this->GeneratorTarget->GetExtraSources(extraSources, config);
+ this->GeneratorTarget->GetExtraSources(extraSources, this->ConfigName);
this->OSXBundleGenerator->GenerateMacOSXContentStatements(
extraSources, this->MacOSXContentGenerator);
+ const char* pchExtension =
+ this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
std::vector<cmSourceFile const*> externalObjects;
- this->GeneratorTarget->GetExternalObjects(externalObjects, config);
- for (std::vector<cmSourceFile const*>::const_iterator si =
- externalObjects.begin();
- si != externalObjects.end(); ++si) {
- this->ExternalObjects.push_back((*si)->GetFullPath());
+ this->GeneratorTarget->GetExternalObjects(externalObjects, this->ConfigName);
+ for (cmSourceFile const* sf : externalObjects) {
+ auto const& objectFileName = sf->GetFullPath();
+ if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) {
+ this->ExternalObjects.push_back(objectFileName);
+ }
}
std::vector<cmSourceFile const*> objectSources;
- this->GeneratorTarget->GetObjectSources(objectSources, config);
- for (std::vector<cmSourceFile const*>::const_iterator si =
- objectSources.begin();
- si != objectSources.end(); ++si) {
+ this->GeneratorTarget->GetObjectSources(objectSources, this->ConfigName);
+ for (cmSourceFile const* sf : objectSources) {
// Generate this object file's rule file.
- this->WriteObjectRuleFiles(**si);
+ this->WriteObjectRuleFiles(*sf);
}
}
@@ -200,16 +262,14 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
: "");
// Include the dependencies for the target.
- std::string dependFileNameFull = this->TargetBuildDirectoryFull;
- dependFileNameFull += "/depend.make";
+ std::string dependFileNameFull =
+ cmStrCat(this->TargetBuildDirectoryFull, "/depend.make");
*this->BuildFileStream
<< "# 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) {
@@ -218,20 +278,17 @@ 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,
- this->GlobalGenerator->GetMakefileEncoding());
+ dependFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding());
depFileStream << "# Empty dependencies file for "
<< this->GeneratorTarget->GetName() << ".\n"
<< "# This may be replaced when dependencies are built."
@@ -240,15 +297,15 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
// Open the flags file. This should be copy-if-different because the
// rules may depend on this file itself.
- this->FlagFileNameFull = this->TargetBuildDirectoryFull;
- this->FlagFileNameFull += "/flags.make";
+ this->FlagFileNameFull =
+ cmStrCat(this->TargetBuildDirectoryFull, "/flags.make");
this->FlagFileStream =
- new cmGeneratedFileStream(this->FlagFileNameFull.c_str(), false,
+ new cmGeneratedFileStream(this->FlagFileNameFull, false,
this->GlobalGenerator->GetMakefileEncoding());
- this->FlagFileStream->SetCopyIfDifferent(true);
if (!this->FlagFileStream) {
return;
}
+ this->FlagFileStream->SetCopyIfDifferent(true);
this->LocalGenerator->WriteDisclaimer(*this->FlagFileStream);
// Include the flags for the target.
@@ -256,11 +313,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";
}
@@ -272,28 +326,24 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
languages, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
// put the compiler in the rules.make file so that if it changes
// things rebuild
- for (std::set<std::string>::const_iterator l = languages.begin();
- l != languages.end(); ++l) {
- std::string compiler = "CMAKE_";
- compiler += *l;
- compiler += "_COMPILER";
- *this->FlagFileStream << "# compile " << *l << " with "
+ for (std::string const& language : languages) {
+ std::string compiler = cmStrCat("CMAKE_", language, "_COMPILER");
+ *this->FlagFileStream << "# compile " << language << " with "
<< this->Makefile->GetSafeDefinition(compiler)
<< "\n";
}
- for (std::set<std::string>::const_iterator l = languages.begin();
- l != languages.end(); ++l) {
- std::string flags = this->GetFlags(*l);
- std::string defines = this->GetDefines(*l);
- std::string includes = this->GetIncludes(*l);
+ for (std::string const& language : languages) {
+ std::string flags = this->GetFlags(language);
+ std::string defines = this->GetDefines(language);
+ std::string includes = this->GetIncludes(language);
// Escape comment characters so they do not terminate assignment.
cmSystemTools::ReplaceString(flags, "#", "\\#");
cmSystemTools::ReplaceString(defines, "#", "\\#");
cmSystemTools::ReplaceString(includes, "#", "\\#");
- *this->FlagFileStream << *l << "_FLAGS = " << flags << "\n\n";
- *this->FlagFileStream << *l << "_DEFINES = " << defines << "\n\n";
- *this->FlagFileStream << *l << "_INCLUDES = " << includes << "\n\n";
+ *this->FlagFileStream << language << "_FLAGS = " << flags << "\n\n";
+ *this->FlagFileStream << language << "_DEFINES = " << defines << "\n\n";
+ *this->FlagFileStream << language << "_INCLUDES = " << includes << "\n\n";
}
}
@@ -312,10 +362,9 @@ void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()(
std::string const& input = source.GetFullPath();
// Get the output file location.
- std::string output = macdir;
- output += "/";
- output += cmSystemTools::GetFilenameName(input);
- this->Generator->CleanFiles.push_back(
+ std::string output =
+ cmStrCat(macdir, '/', cmSystemTools::GetFilenameName(input));
+ this->Generator->CleanFiles.insert(
this->Generator->LocalGenerator->MaybeConvertToRelativePath(
this->Generator->LocalGenerator->GetCurrentBinaryDirectory(), output));
output = this->Generator->LocalGenerator->MaybeConvertToRelativePath(
@@ -325,19 +374,19 @@ void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()(
std::vector<std::string> depends;
std::vector<std::string> commands;
depends.push_back(input);
- std::string copyEcho = "Copying OS X content ";
- copyEcho += output;
+ std::string copyEcho = cmStrCat("Copying OS X content ", output);
this->Generator->LocalGenerator->AppendEcho(
commands, copyEcho, cmLocalUnixMakefileGenerator3::EchoBuild);
- std::string copyCommand = "$(CMAKE_COMMAND) -E copy ";
- copyCommand += this->Generator->LocalGenerator->ConvertToOutputFormat(
- input, cmOutputConverter::SHELL);
- copyCommand += " ";
- copyCommand += this->Generator->LocalGenerator->ConvertToOutputFormat(
- output, cmOutputConverter::SHELL);
- commands.push_back(copyCommand);
+ std::string copyCommand =
+ cmStrCat("$(CMAKE_COMMAND) -E copy ",
+ this->Generator->LocalGenerator->ConvertToOutputFormat(
+ input, cmOutputConverter::SHELL),
+ ' ',
+ this->Generator->LocalGenerator->ConvertToOutputFormat(
+ output, cmOutputConverter::SHELL));
+ commands.push_back(std::move(copyCommand));
this->Generator->LocalGenerator->WriteMakeRule(
- *this->Generator->BuildFileStream, CM_NULLPTR, output, depends, commands,
+ *this->Generator->BuildFileStream, nullptr, output, depends, commands,
false);
this->Generator->ExtraFiles.insert(output);
}
@@ -357,9 +406,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
std::string const& objectName =
this->GeneratorTarget->GetObjectName(&source);
std::string obj =
- this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
- obj += "/";
- obj += objectName;
+ cmStrCat(this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget),
+ '/', objectName);
// Avoid generating duplicate rules.
if (this->ObjectFiles.find(obj) == this->ObjectFiles.end()) {
@@ -369,47 +417,32 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
err << "Warning: Source file \"" << source.GetFullPath()
<< "\" is listed multiple times for target \""
<< this->GeneratorTarget->GetName() << "\".";
- cmSystemTools::Message(err.str().c_str(), "Warning");
+ cmSystemTools::Message(err.str(), "Warning");
return;
}
// 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());
+ {
+ std::string dir = cmSystemTools::GetFilenamePath(obj);
+ cmSystemTools::MakeDirectory(this->LocalGenerator->ConvertToFullPath(dir));
+ }
// Save this in the target's list of object files.
this->Objects.push_back(obj);
- this->CleanFiles.push_back(obj);
-
- // TODO: Remove
- // std::string relativeObj
- //= this->LocalGenerator->GetHomeRelativeOutputPath();
- // relativeObj += obj;
+ this->CleanFiles.insert(obj);
- // we compute some depends when writing the depend.make that we will also
- // use in the build.make, same with depMakeFile
std::vector<std::string> depends;
- // generate the build rule file
- this->WriteObjectBuildFile(obj, lang, source, depends);
-
// The object file should be checked for dependency integrity.
- std::string objFullPath = this->LocalGenerator->GetCurrentBinaryDirectory();
- objFullPath += "/";
- objFullPath += obj;
+ std::string objFullPath =
+ cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/', obj);
objFullPath = cmSystemTools::CollapseFullPath(objFullPath);
std::string srcFullPath =
cmSystemTools::CollapseFullPath(source.GetFullPath());
- this->LocalGenerator->AddImplicitDepends(
- this->GeneratorTarget, lang, objFullPath.c_str(), srcFullPath.c_str());
-}
+ this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, lang,
+ objFullPath, srcFullPath);
-void cmMakefileTargetGenerator::WriteObjectBuildFile(
- std::string& obj, const std::string& lang, cmSourceFile const& source,
- std::vector<std::string>& depends)
-{
this->LocalGenerator->AppendRuleDepend(depends,
this->FlagFileNameFull.c_str());
this->LocalGenerator->AppendRuleDepends(depends,
@@ -418,21 +451,36 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
// generate the depend scanning rule
this->WriteObjectDependRules(source, depends);
- std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath();
- relativeObj += obj;
+ std::string config = this->LocalGenerator->GetConfigName();
+ std::string configUpper = cmSystemTools::UpperCase(config);
+
+ // Add precompile headers dependencies
+ const std::string pchSource =
+ this->GeneratorTarget->GetPchSource(config, lang);
+ if (!pchSource.empty() && !source.GetProperty("SKIP_PRECOMPILE_HEADERS")) {
+ std::string const& pchHeader =
+ this->GeneratorTarget->GetPchHeader(config, lang);
+ depends.push_back(pchHeader);
+ if (source.GetFullPath() != pchSource) {
+ depends.push_back(this->GeneratorTarget->GetPchFile(config, lang));
+ }
+ this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, lang,
+ objFullPath, pchHeader);
+ }
+
+ std::string relativeObj =
+ cmStrCat(this->LocalGenerator->GetHomeRelativeOutputPath(), obj);
// Write the build rule.
// Build the set of compiler flags.
std::string flags;
// Add language-specific flags.
- std::string langFlags = "$(";
- langFlags += lang;
- langFlags += "_FLAGS)";
+ std::string langFlags = cmStrCat("$(", lang, "_FLAGS)");
this->LocalGenerator->AppendFlags(flags, langFlags);
- std::string config = this->LocalGenerator->GetConfigName();
- std::string configUpper = cmSystemTools::UpperCase(config);
+ cmGeneratorExpressionInterpreter genexInterpreter(
+ this->LocalGenerator, config, this->GeneratorTarget, lang);
// Add Fortran format flags.
if (lang == "Fortran") {
@@ -440,34 +488,81 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
}
// Add flags from source file properties.
- if (const char* cflags = source.GetProperty("COMPILE_FLAGS")) {
- cmGeneratorExpression ge;
- CM_AUTO_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 std::string& 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 std::string& evaluatedOptions =
+ genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS);
+ this->LocalGenerator->AppendCompileOptions(flags, evaluatedOptions);
+ *this->FlagFileStream << "# Custom options: " << relativeObj
+ << "_OPTIONS = " << evaluatedOptions << "\n"
+ << "\n";
+ }
+
+ // Add precompile headers compile options.
+ if (!pchSource.empty() && !source.GetProperty("SKIP_PRECOMPILE_HEADERS")) {
+ std::string pchOptions;
+ if (source.GetFullPath() == pchSource) {
+ pchOptions =
+ this->GeneratorTarget->GetPchCreateCompileOptions(config, lang);
+ } else {
+ pchOptions =
+ this->GeneratorTarget->GetPchUseCompileOptions(config, lang);
+ }
+
+ const std::string& evaluatedFlags =
+ genexInterpreter.Evaluate(pchOptions, COMPILE_OPTIONS);
+
+ this->LocalGenerator->AppendCompileOptions(flags, evaluatedFlags);
+ *this->FlagFileStream << "# PCH options: " << relativeObj
+ << "_OPTIONS = " << evaluatedFlags << "\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 std::string& 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 std::string& 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;
+ std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper);
if (const char* config_compile_defs = source.GetProperty(defPropName)) {
- this->LocalGenerator->AppendDefines(defines, config_compile_defs);
+ const std::string& 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";
}
@@ -485,10 +580,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
if (!this->NoRuleMessages) {
cmLocalUnixMakefileGenerator3::EchoProgress progress;
this->MakeEchoProgress(progress);
- std::string buildEcho = "Building ";
- buildEcho += lang;
- buildEcho += " object ";
- buildEcho += relativeObj;
+ std::string buildEcho =
+ cmStrCat("Building ", lang, " object ", relativeObj);
this->LocalGenerator->AppendEcho(commands, buildEcho,
cmLocalUnixMakefileGenerator3::EchoBuild,
&progress);
@@ -508,9 +601,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
targetFullPathReal = this->GeneratorTarget->GetFullPath(
this->ConfigName, cmStateEnums::RuntimeBinaryArtifact, true);
targetFullPathPDB =
- this->GeneratorTarget->GetPDBDirectory(this->ConfigName);
- targetFullPathPDB += "/";
- targetFullPathPDB += this->GeneratorTarget->GetPDBName(this->ConfigName);
+ cmStrCat(this->GeneratorTarget->GetPDBDirectory(this->ConfigName), '/',
+ this->GeneratorTarget->GetPDBName(this->ConfigName));
}
targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
@@ -530,7 +622,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
// mingw32-make incorrectly interprets 'a\ b c' as 'a b' and 'c'
// (but 'a\ b "c"' as 'a\', 'b', and 'c'!). Workaround this by
// avoiding a trailing backslash in the argument.
- targetOutPathCompilePDB[targetOutPathCompilePDB.size() - 1] = '/';
+ targetOutPathCompilePDB.back() = '/';
}
}
cmRulePlaceholderExpander::RuleVariables vars;
@@ -559,15 +651,16 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
vars.ObjectFileDir = objectFileDir.c_str();
vars.Flags = flags.c_str();
- std::string definesString = "$(";
- definesString += lang;
- definesString += "_DEFINES)";
+ std::string definesString = cmStrCat("$(", lang, "_DEFINES)");
this->LocalGenerator->JoinDefines(defines, definesString, lang);
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
@@ -578,7 +671,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
bool const lang_has_assembly = lang_has_preprocessor;
bool const lang_can_export_cmds = lang_has_preprocessor;
- CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+ std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->LocalGenerator->CreateRulePlaceholderExpander());
// Construct the compile rules.
@@ -588,20 +681,21 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
std::string cmdVar;
if (this->GeneratorTarget->GetPropertyAsBool(
"CUDA_SEPARABLE_COMPILATION")) {
- cmdVar = std::string("CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION");
+ cmdVar = "CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION";
} else if (this->GeneratorTarget->GetPropertyAsBool(
"CUDA_PTX_COMPILATION")) {
- cmdVar = std::string("CMAKE_CUDA_COMPILE_PTX_COMPILATION");
+ cmdVar = "CMAKE_CUDA_COMPILE_PTX_COMPILATION";
} else {
- cmdVar = std::string("CMAKE_CUDA_COMPILE_WHOLE_COMPILATION");
+ cmdVar = "CMAKE_CUDA_COMPILE_WHOLE_COMPILATION";
}
- std::string compileRule = this->Makefile->GetRequiredDefinition(cmdVar);
- cmSystemTools::ExpandListArgument(compileRule, compileCommands);
+ const std::string& compileRule =
+ this->Makefile->GetRequiredDefinition(cmdVar);
+ cmExpandList(compileRule, compileCommands);
} else {
- const std::string cmdVar =
- std::string("CMAKE_") + lang + "_COMPILE_OBJECT";
- std::string compileRule = this->Makefile->GetRequiredDefinition(cmdVar);
- cmSystemTools::ExpandListArgument(compileRule, compileCommands);
+ const std::string cmdVar = "CMAKE_" + lang + "_COMPILE_OBJECT";
+ const std::string& compileRule =
+ this->Makefile->GetRequiredDefinition(cmdVar);
+ cmExpandList(compileRule, compileCommands);
}
if (this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS") &&
@@ -621,10 +715,34 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
std::string langIncludes = std::string("$(") + lang + "_INCLUDES)";
compileCommand.replace(compileCommand.find(langIncludes),
langIncludes.size(), this->GetIncludes(lang));
+
+ const char* eliminate[] = {
+ this->Makefile->GetDefinition("CMAKE_START_TEMP_FILE"),
+ this->Makefile->GetDefinition("CMAKE_END_TEMP_FILE")
+ };
+ for (const char* el : eliminate) {
+ if (el) {
+ cmSystemTools::ReplaceString(compileCommand, el, "");
+ }
+ }
+
this->GlobalGenerator->AddCXXCompileCommand(
source.GetFullPath(), workingDirectory, compileCommand);
}
+ // See if we need to use a compiler launcher like ccache or distcc
+ std::string compilerLauncher;
+ if (!compileCommands.empty() &&
+ (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" ||
+ lang == "OBJC" || lang == "OBJCXX")) {
+ std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
+ const char* clauncher =
+ this->GeneratorTarget->GetProperty(clauncher_prop);
+ if (clauncher && *clauncher) {
+ compilerLauncher = clauncher;
+ }
+ }
+
// Maybe insert an include-what-you-use runner.
if (!compileCommands.empty() && (lang == "C" || lang == "CXX")) {
std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE";
@@ -633,8 +751,18 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
const char* tidy = this->GeneratorTarget->GetProperty(tidy_prop);
std::string const cpplint_prop = lang + "_CPPLINT";
const char* cpplint = this->GeneratorTarget->GetProperty(cpplint_prop);
- if ((iwyu && *iwyu) || (tidy && *tidy) || (cpplint && *cpplint)) {
- std::string run_iwyu = "$(CMAKE_COMMAND) -E __run_iwyu";
+ std::string const cppcheck_prop = lang + "_CPPCHECK";
+ const char* cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop);
+ if ((iwyu && *iwyu) || (tidy && *tidy) || (cpplint && *cpplint) ||
+ (cppcheck && *cppcheck)) {
+ std::string run_iwyu = "$(CMAKE_COMMAND) -E __run_co_compile";
+ if (!compilerLauncher.empty()) {
+ // In __run_co_compile case the launcher command is supplied
+ // via --launcher=<maybe-list> and consumed
+ run_iwyu += " --launcher=";
+ run_iwyu += this->LocalGenerator->EscapeForShell(compilerLauncher);
+ compilerLauncher.clear();
+ }
if (iwyu && *iwyu) {
run_iwyu += " --iwyu=";
run_iwyu += this->LocalGenerator->EscapeForShell(iwyu);
@@ -647,7 +775,12 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
run_iwyu += " --cpplint=";
run_iwyu += this->LocalGenerator->EscapeForShell(cpplint);
}
- if ((tidy && *tidy) || (cpplint && *cpplint)) {
+ if (cppcheck && *cppcheck) {
+ run_iwyu += " --cppcheck=";
+ run_iwyu += this->LocalGenerator->EscapeForShell(cppcheck);
+ }
+ if ((tidy && *tidy) || (cpplint && *cpplint) ||
+ (cppcheck && *cppcheck)) {
run_iwyu += " --source=";
run_iwyu += sourceFile;
}
@@ -656,22 +789,18 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
}
}
- // Maybe insert a compiler launcher like ccache or distcc
- if (!compileCommands.empty() && (lang == "C" || lang == "CXX")) {
- std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
- const char* clauncher =
- this->GeneratorTarget->GetProperty(clauncher_prop);
- if (clauncher && *clauncher) {
- std::vector<std::string> launcher_cmd;
- cmSystemTools::ExpandListArgument(clauncher, launcher_cmd, true);
- for (std::vector<std::string>::iterator i = launcher_cmd.begin(),
- e = launcher_cmd.end();
- i != e; ++i) {
- *i = this->LocalGenerator->EscapeForShell(*i);
+ // If compiler launcher was specified and not consumed above, it
+ // goes to the beginning of the command line.
+ if (!compileCommands.empty() && !compilerLauncher.empty()) {
+ std::vector<std::string> args = cmExpandedList(compilerLauncher, true);
+ if (!args.empty()) {
+ args[0] = this->LocalGenerator->ConvertToOutputFormat(
+ args[0], cmOutputConverter::SHELL);
+ for (std::string& i : cmMakeRange(args.begin() + 1, args.end())) {
+ i = this->LocalGenerator->EscapeForShell(i);
}
- std::string const& run_launcher = cmJoin(launcher_cmd, " ") + " ";
- compileCommands.front().insert(0, run_launcher);
}
+ compileCommands.front().insert(0, cmJoin(args, " ") + " ");
}
std::string launcher;
@@ -679,38 +808,34 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
const char* val = this->LocalGenerator->GetRuleLauncher(
this->GeneratorTarget, "RULE_LAUNCH_COMPILE");
if (val && *val) {
- launcher = val;
- launcher += " ";
+ launcher = cmStrCat(val, ' ');
}
}
// Expand placeholders in the commands.
- for (std::vector<std::string>::iterator i = compileCommands.begin();
- i != compileCommands.end(); ++i) {
- *i = launcher + *i;
- rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, *i,
- vars);
+ for (std::string& compileCommand : compileCommands) {
+ compileCommand = cmStrCat(launcher, compileCommand);
+ rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
+ compileCommand, vars);
}
// Change the command working directory to the local build tree.
this->LocalGenerator->CreateCDCommand(
compileCommands, this->LocalGenerator->GetCurrentBinaryDirectory(),
this->LocalGenerator->GetBinaryDirectory());
- commands.insert(commands.end(), compileCommands.begin(),
- compileCommands.end());
+ cmAppend(commands, compileCommands);
}
// Check for extra outputs created by the compilation.
std::vector<std::string> outputs(1, relativeObj);
if (const char* extra_outputs_str = source.GetProperty("OBJECT_OUTPUTS")) {
// Register these as extra files to clean.
- cmSystemTools::ExpandListArgument(extra_outputs_str, outputs);
- this->CleanFiles.insert(this->CleanFiles.end(), outputs.begin() + 1,
- outputs.end());
+ cmExpandList(extra_outputs_str, outputs);
+ this->CleanFiles.insert(outputs.begin() + 1, outputs.end());
}
// Write the rule.
- this->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR, outputs, depends,
+ this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs, depends,
commands);
bool do_preprocess_rules = lang_has_preprocessor &&
@@ -719,7 +844,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
lang_has_assembly && this->LocalGenerator->GetCreateAssemblySourceRules();
if (do_preprocess_rules || do_assembly_rules) {
std::vector<std::string> force_depends;
- force_depends.push_back("cmake_force");
+ force_depends.emplace_back("cmake_force");
std::string::size_type dot_pos = relativeObj.rfind('.');
std::string relativeObjBase = relativeObj.substr(0, dot_pos);
dot_pos = obj.rfind('.');
@@ -730,46 +855,42 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
std::string relativeObjI = relativeObjBase + ".i";
std::string objI = objBase + ".i";
- std::string preprocessEcho = "Preprocessing ";
- preprocessEcho += lang;
- preprocessEcho += " source to ";
- preprocessEcho += objI;
+ std::string preprocessEcho =
+ cmStrCat("Preprocessing ", lang, " source to ", objI);
this->LocalGenerator->AppendEcho(
commands, preprocessEcho, cmLocalUnixMakefileGenerator3::EchoBuild);
- std::string preprocessRuleVar = "CMAKE_";
- preprocessRuleVar += lang;
- preprocessRuleVar += "_CREATE_PREPROCESSED_SOURCE";
+ std::string preprocessRuleVar =
+ cmStrCat("CMAKE_", lang, "_CREATE_PREPROCESSED_SOURCE");
if (const char* preprocessRule =
this->Makefile->GetDefinition(preprocessRuleVar)) {
- std::vector<std::string> preprocessCommands;
- cmSystemTools::ExpandListArgument(preprocessRule, preprocessCommands);
+ std::vector<std::string> preprocessCommands =
+ cmExpandedList(preprocessRule);
std::string shellObjI = this->LocalGenerator->ConvertToOutputFormat(
objI, cmOutputConverter::SHELL);
vars.PreprocessedSource = shellObjI.c_str();
// Expand placeholders in the commands.
- for (std::vector<std::string>::iterator i = preprocessCommands.begin();
- i != preprocessCommands.end(); ++i) {
+ for (std::string& preprocessCommand : preprocessCommands) {
// no launcher for preprocessor commands
- rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
- *i, vars);
+ rulePlaceholderExpander->ExpandRuleVariables(
+ this->LocalGenerator, preprocessCommand, vars);
}
this->LocalGenerator->CreateCDCommand(
preprocessCommands,
this->LocalGenerator->GetCurrentBinaryDirectory(),
this->LocalGenerator->GetBinaryDirectory());
- commands.insert(commands.end(), preprocessCommands.begin(),
- preprocessCommands.end());
+ cmAppend(commands, preprocessCommands);
} else {
- std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
- cmd += preprocessRuleVar;
- commands.push_back(cmd);
+ std::string cmd =
+ cmStrCat("$(CMAKE_COMMAND) -E cmake_unimplemented_variable ",
+ preprocessRuleVar);
+ commands.push_back(std::move(cmd));
}
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
relativeObjI, force_depends,
commands, false);
}
@@ -779,109 +900,45 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
std::string relativeObjS = relativeObjBase + ".s";
std::string objS = objBase + ".s";
- std::string assemblyEcho = "Compiling ";
- assemblyEcho += lang;
- assemblyEcho += " source to assembly ";
- assemblyEcho += objS;
+ std::string assemblyEcho =
+ cmStrCat("Compiling ", lang, " source to assembly ", objS);
this->LocalGenerator->AppendEcho(
commands, assemblyEcho, cmLocalUnixMakefileGenerator3::EchoBuild);
- std::string assemblyRuleVar = "CMAKE_";
- assemblyRuleVar += lang;
- assemblyRuleVar += "_CREATE_ASSEMBLY_SOURCE";
+ std::string assemblyRuleVar =
+ cmStrCat("CMAKE_", lang, "_CREATE_ASSEMBLY_SOURCE");
if (const char* assemblyRule =
this->Makefile->GetDefinition(assemblyRuleVar)) {
- std::vector<std::string> assemblyCommands;
- cmSystemTools::ExpandListArgument(assemblyRule, assemblyCommands);
+ std::vector<std::string> assemblyCommands =
+ cmExpandedList(assemblyRule);
std::string shellObjS = this->LocalGenerator->ConvertToOutputFormat(
objS, cmOutputConverter::SHELL);
vars.AssemblySource = shellObjS.c_str();
// Expand placeholders in the commands.
- for (std::vector<std::string>::iterator i = assemblyCommands.begin();
- i != assemblyCommands.end(); ++i) {
+ for (std::string& assemblyCommand : assemblyCommands) {
// no launcher for assembly commands
rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
- *i, vars);
+ assemblyCommand, vars);
}
this->LocalGenerator->CreateCDCommand(
assemblyCommands, this->LocalGenerator->GetCurrentBinaryDirectory(),
this->LocalGenerator->GetBinaryDirectory());
- commands.insert(commands.end(), assemblyCommands.begin(),
- assemblyCommands.end());
+ cmAppend(commands, assemblyCommands);
} else {
- std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
- cmd += assemblyRuleVar;
- commands.push_back(cmd);
+ std::string cmd =
+ cmStrCat("$(CMAKE_COMMAND) -E cmake_unimplemented_variable ",
+ assemblyRuleVar);
+ commands.push_back(std::move(cmd));
}
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
relativeObjS, force_depends,
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, CM_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, CM_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, CM_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::vector<std::string>::const_iterator obj = this->Objects.begin();
- obj != this->Objects.end(); ++obj) {
- objTarget = relPath;
- objTarget += *obj;
- objTarget += ".requires";
- depends.push_back(objTarget);
- }
-
- // Write the rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
- depTarget, depends, no_commands, true);
}
void cmMakefileTargetGenerator::WriteTargetCleanRules()
@@ -890,9 +947,9 @@ void cmMakefileTargetGenerator::WriteTargetCleanRules()
std::vector<std::string> commands;
// Construct the clean target name.
- std::string cleanTarget =
- this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget);
- cleanTarget += "/clean";
+ std::string cleanTarget = cmStrCat(
+ this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget),
+ "/clean");
// Construct the clean command.
this->LocalGenerator->AppendCleanCommand(commands, this->CleanFiles,
@@ -902,7 +959,7 @@ void cmMakefileTargetGenerator::WriteTargetCleanRules()
this->LocalGenerator->GetBinaryDirectory());
// Write the rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
cleanTarget, depends, commands, true);
}
@@ -939,18 +996,17 @@ bool cmMakefileTargetGenerator::WriteMakeRule(
// For multiple outputs, make the extra ones depend on the first one.
std::vector<std::string> const output_depends(1, outputs[0]);
std::string binDir = this->LocalGenerator->GetBinaryDirectory();
- for (std::vector<std::string>::const_iterator o = outputs.begin() + 1;
- o != outputs.end(); ++o) {
+ for (std::string const& output : cmMakeRange(outputs).advance(1)) {
// 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),
+ this->LocalGenerator->MaybeConvertToRelativePath(binDir, output),
cmOutputConverter::SHELL);
std::vector<std::string> output_commands;
bool o_symbolic = false;
if (need_symbolic) {
- if (cmSourceFile* sf = this->Makefile->GetSource(*o)) {
+ if (cmSourceFile* sf = this->Makefile->GetSource(output)) {
o_symbolic = sf->GetPropertyAsBool("SYMBOLIC");
}
}
@@ -959,13 +1015,13 @@ bool cmMakefileTargetGenerator::WriteMakeRule(
if (!o_symbolic) {
output_commands.push_back("@$(CMAKE_COMMAND) -E touch_nocreate " + out);
}
- this->LocalGenerator->WriteMakeRule(os, CM_NULLPTR, *o, output_depends,
+ this->LocalGenerator->WriteMakeRule(os, nullptr, output, output_depends,
output_commands, o_symbolic, in_help);
if (!o_symbolic) {
// At build time, remove the first output if this one does not exist
// so that "make" will rerun the real commands that create this one.
- MultipleOutputPairsType::value_type p(*o, outputs[0]);
+ MultipleOutputPairsType::value_type p(output, outputs[0]);
this->MultipleOutputPairs.insert(p);
}
}
@@ -977,16 +1033,14 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
// must write the targets depend info file
std::string dir =
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
- this->InfoFileNameFull = dir;
- this->InfoFileNameFull += "/DependInfo.cmake";
+ this->InfoFileNameFull = cmStrCat(dir, "/DependInfo.cmake");
this->InfoFileNameFull =
this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull);
- this->InfoFileStream =
- new cmGeneratedFileStream(this->InfoFileNameFull.c_str());
- this->InfoFileStream->SetCopyIfDifferent(true);
- if (!*this->InfoFileStream) {
+ this->InfoFileStream = new cmGeneratedFileStream(this->InfoFileNameFull);
+ if (!this->InfoFileStream) {
return;
}
+ this->InfoFileStream->SetCopyIfDifferent(true);
this->LocalGenerator->WriteDependLanguageInfo(*this->InfoFileStream,
this->GeneratorTarget);
@@ -998,12 +1052,10 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
<< "# Pairs of files generated by the same build rule.\n"
<< "set(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
/* clang-format on */
- for (MultipleOutputPairsType::const_iterator pi =
- this->MultipleOutputPairs.begin();
- pi != this->MultipleOutputPairs.end(); ++pi) {
+ for (auto const& pi : this->MultipleOutputPairs) {
*this->InfoFileStream
- << " " << cmOutputConverter::EscapeForCMake(pi->first) << " "
- << cmOutputConverter::EscapeForCMake(pi->second) << "\n";
+ << " " << cmOutputConverter::EscapeForCMake(pi.first) << " "
+ << cmOutputConverter::EscapeForCMake(pi.second) << "\n";
}
*this->InfoFileStream << " )\n\n";
}
@@ -1017,9 +1069,8 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
<< "set(CMAKE_TARGET_LINKED_INFO_FILES\n";
/* clang-format on */
std::vector<std::string> dirs = this->GetLinkedTargetDirectories();
- for (std::vector<std::string>::iterator i = dirs.begin(); i != dirs.end();
- ++i) {
- *this->InfoFileStream << " \"" << *i << "/DependInfo.cmake\"\n";
+ for (std::string const& d : dirs) {
+ *this->InfoFileStream << " \"" << d << "/DependInfo.cmake\"\n";
}
*this->InfoFileStream << " )\n";
}
@@ -1041,9 +1092,9 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
std::vector<std::string> commands;
// Construct the name of the dependency generation target.
- std::string depTarget =
- this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget);
- depTarget += "/depend";
+ std::string depTarget = cmStrCat(
+ this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget),
+ "/depend");
// Add a command to call CMake to scan dependencies. CMake will
// touch the corresponding depends file after scanning dependencies.
@@ -1055,10 +1106,11 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
// paths. Make sure PWD is set to the original name of the home
// output directory to help cmSystemTools to create the same
// translation table for the dependency scanning process.
- depCmd << "cd " << (this->LocalGenerator->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(
- this->LocalGenerator->GetBinaryDirectory()),
- cmOutputConverter::SHELL))
+ depCmd << "cd "
+ << (this->LocalGenerator->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(
+ this->LocalGenerator->GetBinaryDirectory()),
+ cmOutputConverter::SHELL))
<< " && ";
#endif
// Generate a call this signature:
@@ -1106,7 +1158,7 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
}
// Write the rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
depTarget, depends, commands, true);
}
@@ -1117,13 +1169,11 @@ void cmMakefileTargetGenerator::DriveCustomCommands(
std::vector<cmSourceFile*> sources;
this->GeneratorTarget->GetSourceFiles(
sources, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
- for (std::vector<cmSourceFile*>::const_iterator source = sources.begin();
- source != sources.end(); ++source) {
- if (cmCustomCommand* cc = (*source)->GetCustomCommand()) {
+ for (cmSourceFile* source : sources) {
+ if (cmCustomCommand* cc = source->GetCustomCommand()) {
cmCustomCommandGenerator ccg(*cc, this->ConfigName,
this->LocalGenerator);
- const std::vector<std::string>& outputs = ccg.GetOutputs();
- depends.insert(depends.end(), outputs.begin(), outputs.end());
+ cmAppend(depends, ccg.GetOutputs());
}
}
}
@@ -1135,7 +1185,7 @@ void cmMakefileTargetGenerator::WriteObjectDependRules(
// shared between the object file and dependency scanning rule.
depends.push_back(source.GetFullPath());
if (const char* objectDeps = source.GetProperty("OBJECT_DEPENDS")) {
- cmSystemTools::ExpandListArgument(objectDeps, depends);
+ cmExpandList(objectDeps, depends);
}
}
@@ -1169,8 +1219,8 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile(
// Write the rule.
const std::vector<std::string>& outputs = ccg.GetOutputs();
- bool symbolic = this->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
- outputs, depends, commands);
+ bool symbolic = this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs,
+ depends, commands);
// If the rule has changed make sure the output is rebuilt.
if (!symbolic) {
@@ -1178,22 +1228,19 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile(
}
// Setup implicit dependency scanning.
- for (cmCustomCommand::ImplicitDependsList::const_iterator idi =
- ccg.GetCC().GetImplicitDepends().begin();
- idi != ccg.GetCC().GetImplicitDepends().end(); ++idi) {
+ for (auto const& idi : ccg.GetCC().GetImplicitDepends()) {
std::string objFullPath = cmSystemTools::CollapseFullPath(outputs[0]);
- std::string srcFullPath = cmSystemTools::CollapseFullPath(idi->second);
- this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, idi->first,
- objFullPath.c_str(),
- srcFullPath.c_str());
+ std::string srcFullPath = cmSystemTools::CollapseFullPath(idi.second);
+ this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, idi.first,
+ objFullPath, srcFullPath);
}
}
void cmMakefileTargetGenerator::MakeEchoProgress(
cmLocalUnixMakefileGenerator3::EchoProgress& progress) const
{
- progress.Dir = this->LocalGenerator->GetBinaryDirectory();
- progress.Dir += cmake::GetCMakeFilesDirectory();
+ progress.Dir =
+ cmStrCat(this->LocalGenerator->GetBinaryDirectory(), "/CMakeFiles");
std::ostringstream progressArg;
progressArg << "$(CMAKE_PROGRESS_" << this->NumberOfProgressActions << ")";
progress.Arg = progressArg.str();
@@ -1216,11 +1263,18 @@ void cmMakefileTargetGenerator::WriteObjectsVariable(
if (!lineContinue) {
lineContinue = "\\";
}
- for (std::vector<std::string>::const_iterator i = this->Objects.begin();
- i != this->Objects.end(); ++i) {
+
+ const char* pchExtension =
+ this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
+
+ for (std::string const& obj : this->Objects) {
+ if (cmSystemTools::StringEndsWith(obj, pchExtension)) {
+ continue;
+ }
*this->BuildFileStream << " " << lineContinue << "\n";
- *this->BuildFileStream << this->LocalGenerator->ConvertToQuotedOutputPath(
- i->c_str(), useWatcomQuote);
+ *this->BuildFileStream
+ << cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(
+ obj, useWatcomQuote);
}
*this->BuildFileStream << "\n";
@@ -1237,14 +1291,13 @@ void cmMakefileTargetGenerator::WriteObjectsVariable(
/* clang-format on */
std::string currentBinDir =
this->LocalGenerator->GetCurrentBinaryDirectory();
- for (std::vector<std::string>::const_iterator i =
- this->ExternalObjects.begin();
- i != this->ExternalObjects.end(); ++i) {
+ for (std::string const& obj : this->ExternalObjects) {
object =
- this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, *i);
+ this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, obj);
*this->BuildFileStream << " " << lineContinue << "\n";
- *this->BuildFileStream << this->LocalGenerator->ConvertToQuotedOutputPath(
- i->c_str(), useWatcomQuote);
+ *this->BuildFileStream
+ << cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(
+ obj, useWatcomQuote);
}
*this->BuildFileStream << "\n"
<< "\n";
@@ -1275,7 +1328,7 @@ public:
(this->CurrentString.length() + 1 + this->NextObject.length() >
this->LengthLimit)) {
this->Strings.push_back(this->CurrentString);
- this->CurrentString = "";
+ this->CurrentString.clear();
this->Space = "";
}
@@ -1291,11 +1344,10 @@ public:
private:
std::string MaybeConvertToRelativePath(std::string const& obj)
{
- if (!cmOutputConverter::ContainedInDirectory(
- this->StateDir.GetCurrentBinary(), obj, this->StateDir)) {
+ if (!this->StateDir.ContainsBoth(this->StateDir.GetCurrentBinary(), obj)) {
return obj;
}
- return cmOutputConverter::ForceToRelativePath(
+ return cmSystemTools::ForceToRelativePath(
this->StateDir.GetCurrentBinary(), obj);
}
@@ -1311,17 +1363,20 @@ private:
void cmMakefileTargetGenerator::WriteObjectsStrings(
std::vector<std::string>& objStrings, std::string::size_type limit)
{
+ const char* pchExtension =
+ this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
+
cmMakefileTargetGeneratorObjectStrings helper(
objStrings, this->LocalGenerator,
this->LocalGenerator->GetStateSnapshot().GetDirectory(), limit);
- for (std::vector<std::string>::const_iterator i = this->Objects.begin();
- i != this->Objects.end(); ++i) {
- helper.Feed(*i);
+ for (std::string const& obj : this->Objects) {
+ if (cmSystemTools::StringEndsWith(obj, pchExtension)) {
+ continue;
+ }
+ helper.Feed(obj);
}
- for (std::vector<std::string>::const_iterator i =
- this->ExternalObjects.begin();
- i != this->ExternalObjects.end(); ++i) {
- helper.Feed(*i);
+ for (std::string const& obj : this->ExternalObjects) {
+ helper.Feed(obj);
}
helper.Done();
}
@@ -1332,8 +1387,8 @@ void cmMakefileTargetGenerator::WriteTargetDriverRule(
// Compute the name of the driver target.
std::string dir =
this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget);
- std::string buildTargetRuleName = dir;
- buildTargetRuleName += relink ? "/preinstall" : "/build";
+ std::string buildTargetRuleName =
+ cmStrCat(dir, relink ? "/preinstall" : "/build");
buildTargetRuleName = this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetBinaryDirectory(), buildTargetRuleName);
@@ -1341,7 +1396,7 @@ void cmMakefileTargetGenerator::WriteTargetDriverRule(
std::vector<std::string> depends;
depends.push_back(main_output);
- const char* comment = CM_NULLPTR;
+ const char* comment = nullptr;
if (relink) {
// Setup the comment for the preinstall driver.
comment = "Rule to relink during preinstall.";
@@ -1355,8 +1410,7 @@ void cmMakefileTargetGenerator::WriteTargetDriverRule(
}
// Make sure the extra files are built.
- depends.insert(depends.end(), this->ExtraFiles.begin(),
- this->ExtraFiles.end());
+ cmAppend(depends, this->ExtraFiles);
}
// Write the driver rule.
@@ -1375,11 +1429,10 @@ void cmMakefileTargetGenerator::AppendTargetDepends(
}
// Loop over all library dependencies.
- const char* cfg = this->LocalGenerator->GetConfigName().c_str();
+ const std::string& cfg = this->LocalGenerator->GetConfigName();
if (cmComputeLinkInformation* cli =
this->GeneratorTarget->GetLinkInformation(cfg)) {
- std::vector<std::string> const& libDeps = cli->GetDepends();
- depends.insert(depends.end(), libDeps.begin(), libDeps.end());
+ cmAppend(depends, cli->GetDepends());
}
}
@@ -1387,18 +1440,15 @@ void cmMakefileTargetGenerator::AppendObjectDepends(
std::vector<std::string>& depends)
{
// Add dependencies on the compiled object files.
- std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
- std::string objTarget;
- for (std::vector<std::string>::const_iterator obj = this->Objects.begin();
- obj != this->Objects.end(); ++obj) {
- objTarget = relPath;
- objTarget += *obj;
- depends.push_back(objTarget);
+ std::string const& relPath =
+ this->LocalGenerator->GetHomeRelativeOutputPath();
+ for (std::string const& obj : this->Objects) {
+ std::string objTarget = cmStrCat(relPath, obj);
+ depends.push_back(std::move(objTarget));
}
// Add dependencies on the external object files.
- depends.insert(depends.end(), this->ExternalObjects.begin(),
- this->ExternalObjects.end());
+ cmAppend(depends, this->ExternalObjects);
// Add a dependency on the rule file itself.
this->LocalGenerator->AppendRuleDepend(depends,
@@ -1406,7 +1456,7 @@ void cmMakefileTargetGenerator::AppendObjectDepends(
}
void cmMakefileTargetGenerator::AppendLinkDepends(
- std::vector<std::string>& depends)
+ std::vector<std::string>& depends, const std::string& linkLanguage)
{
this->AppendObjectDepends(depends);
@@ -1417,36 +1467,31 @@ void cmMakefileTargetGenerator::AppendLinkDepends(
if (cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
this->GeneratorTarget->GetModuleDefinitionInfo(
this->GetConfigName())) {
- for (std::vector<cmSourceFile const*>::const_iterator i =
- mdi->Sources.begin();
- i != mdi->Sources.end(); ++i) {
- depends.push_back((*i)->GetFullPath());
+ for (cmSourceFile const* src : mdi->Sources) {
+ depends.push_back(src->GetFullPath());
}
}
// Add a dependency on user-specified manifest files, if any.
std::vector<cmSourceFile const*> manifest_srcs;
this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName);
- for (std::vector<cmSourceFile const*>::iterator mi = manifest_srcs.begin();
- mi != manifest_srcs.end(); ++mi) {
- depends.push_back((*mi)->GetFullPath());
+ for (cmSourceFile const* manifest_src : manifest_srcs) {
+ depends.push_back(manifest_src->GetFullPath());
}
// Add user-specified dependencies.
- if (const char* linkDepends =
- this->GeneratorTarget->GetProperty("LINK_DEPENDS")) {
- cmSystemTools::ExpandListArgument(linkDepends, depends);
- }
+ this->GeneratorTarget->GetLinkDepends(depends, this->ConfigName,
+ linkLanguage);
}
std::string cmMakefileTargetGenerator::GetLinkRule(
const std::string& linkRuleVar)
{
std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
- if (this->GeneratorTarget->HasImplibGNUtoMS()) {
- std::string ruleVar = "CMAKE_";
- ruleVar += this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
- ruleVar += "_GNUtoMS_RULE";
+ if (this->GeneratorTarget->HasImplibGNUtoMS(this->ConfigName)) {
+ std::string ruleVar = cmStrCat(
+ "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName),
+ "_GNUtoMS_RULE");
if (const char* rule = this->Makefile->GetDefinition(ruleVar)) {
linkRule += rule;
}
@@ -1467,29 +1512,28 @@ void cmMakefileTargetGenerator::CreateLinkScript(
std::vector<std::string>& makefile_depends)
{
// Create the link script file.
- std::string linkScriptName = this->TargetBuildDirectoryFull;
- linkScriptName += "/";
- linkScriptName += name;
- cmGeneratedFileStream linkScriptStream(linkScriptName.c_str());
+ std::string linkScriptName =
+ cmStrCat(this->TargetBuildDirectoryFull, '/', name);
+ cmGeneratedFileStream linkScriptStream(linkScriptName);
linkScriptStream.SetCopyIfDifferent(true);
- for (std::vector<std::string>::const_iterator cmd = link_commands.begin();
- cmd != link_commands.end(); ++cmd) {
+ for (std::string const& link_command : link_commands) {
// Do not write out empty commands or commands beginning in the
// shell no-op ":".
- if (!cmd->empty() && (*cmd)[0] != ':') {
- linkScriptStream << *cmd << "\n";
+ if (!link_command.empty() && link_command[0] != ':') {
+ linkScriptStream << link_command << "\n";
}
}
// Create the makefile command to invoke the link script.
- std::string link_command = "$(CMAKE_COMMAND) -E cmake_link_script ";
- link_command += this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), linkScriptName),
- cmOutputConverter::SHELL);
- link_command += " --verbose=$(VERBOSE)";
- makefile_commands.push_back(link_command);
- makefile_depends.push_back(linkScriptName);
+ std::string link_command = cmStrCat(
+ "$(CMAKE_COMMAND) -E cmake_link_script ",
+ this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), linkScriptName),
+ cmOutputConverter::SHELL),
+ " --verbose=$(VERBOSE)");
+ makefile_commands.push_back(std::move(link_command));
+ makefile_depends.push_back(std::move(linkScriptName));
}
bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects(
@@ -1500,7 +1544,7 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects(
"CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_OBJECTS";
if (const char* val = this->Makefile->GetDefinition(responseVar)) {
if (*val) {
- return cmSystemTools::IsOn(val);
+ return cmIsOn(val);
}
}
@@ -1512,14 +1556,11 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects(
// actual list will likely be much shorter than this. However, in the
// worst case all objects will remain as absolute paths.
size_t length = 0;
- for (std::vector<std::string>::const_iterator i = this->Objects.begin();
- i != this->Objects.end(); ++i) {
- length += i->size() + 3;
+ for (std::string const& obj : this->Objects) {
+ length += obj.size() + 3;
}
- for (std::vector<std::string>::const_iterator i =
- this->ExternalObjects.begin();
- i != this->ExternalObjects.end(); ++i) {
- length += i->size() + 3;
+ for (std::string const& ext_obj : this->ExternalObjects) {
+ length += ext_obj.size() + 3;
}
// We need to guarantee room for both objects and libraries, so
@@ -1542,7 +1583,7 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForLibraries(
"CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_LIBRARIES";
if (const char* val = this->Makefile->GetDefinition(responseVar)) {
if (*val) {
- return cmSystemTools::IsOn(val);
+ return cmIsOn(val);
}
}
@@ -1555,21 +1596,19 @@ std::string cmMakefileTargetGenerator::CreateResponseFile(
std::vector<std::string>& makefile_depends)
{
// Create the response file.
- std::string responseFileNameFull = this->TargetBuildDirectoryFull;
- responseFileNameFull += "/";
- responseFileNameFull += name;
- cmGeneratedFileStream responseStream(responseFileNameFull.c_str());
+ std::string responseFileNameFull =
+ cmStrCat(this->TargetBuildDirectoryFull, '/', name);
+ cmGeneratedFileStream responseStream(responseFileNameFull);
responseStream.SetCopyIfDifferent(true);
responseStream << options << "\n";
// 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;
- responseFileName += "/";
- responseFileName += name;
+ std::string responseFileName =
+ cmStrCat(this->TargetBuildDirectory, '/', name);
return responseFileName;
}
@@ -1590,9 +1629,8 @@ void cmMakefileTargetGenerator::CreateLinkLibs(
{
std::string frameworkPath;
std::string linkPath;
- std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
cmComputeLinkInformation* pcli =
- this->GeneratorTarget->GetLinkInformation(config);
+ this->GeneratorTarget->GetLinkInformation(this->ConfigName);
this->LocalGenerator->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
frameworkPath, linkPath);
linkLibs = frameworkPath + linkPath + linkLibs;
@@ -1600,10 +1638,9 @@ void cmMakefileTargetGenerator::CreateLinkLibs(
if (useResponseFile &&
linkLibs.find_first_not_of(' ') != std::string::npos) {
// Lookup the response file reference flag.
- std::string responseFlagVar = "CMAKE_";
- responseFlagVar +=
- this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
- responseFlagVar += "_RESPONSE_FILE_LINK_FLAG";
+ std::string responseFlagVar = cmStrCat(
+ "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName),
+ "_RESPONSE_FILE_LINK_FLAG");
const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar);
if (!responseFlag) {
responseFlag = "@";
@@ -1614,9 +1651,9 @@ void cmMakefileTargetGenerator::CreateLinkLibs(
this->CreateResponseFile("linklibs.rsp", linkLibs, makefile_depends);
// Reference the response file.
- linkLibs = responseFlag;
- linkLibs += this->LocalGenerator->ConvertToOutputFormat(
- link_rsp, cmOutputConverter::SHELL);
+ linkLibs = cmStrCat(responseFlag,
+ this->LocalGenerator->ConvertToOutputFormat(
+ link_rsp, cmOutputConverter::SHELL));
}
}
@@ -1638,10 +1675,9 @@ void cmMakefileTargetGenerator::CreateObjectLists(
this->WriteObjectsStrings(object_strings, responseFileLimit);
// Lookup the response file reference flag.
- std::string responseFlagVar = "CMAKE_";
- responseFlagVar +=
- this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
- responseFlagVar += "_RESPONSE_FILE_LINK_FLAG";
+ std::string responseFlagVar = cmStrCat(
+ "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName),
+ "_RESPONSE_FILE_LINK_FLAG");
const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar);
if (!responseFlag) {
responseFlag = "@";
@@ -1674,39 +1710,39 @@ void cmMakefileTargetGenerator::CreateObjectLists(
buildObjs = objStrings[0];
}
} else {
- buildObjs = "$(";
- buildObjs += variableName;
- buildObjs += ") $(";
- buildObjs += variableNameExternal;
- buildObjs += ")";
+ buildObjs =
+ cmStrCat("$(", variableName, ") $(", variableNameExternal, ')');
}
}
void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
const std::string& lang)
{
- std::string responseVar = "CMAKE_";
- responseVar += lang;
- responseVar += "_USE_RESPONSE_FILE_FOR_INCLUDES";
+ std::string responseVar =
+ cmStrCat("CMAKE_", lang, "_USE_RESPONSE_FILE_FOR_INCLUDES");
bool useResponseFile = this->Makefile->IsOn(responseVar);
std::vector<std::string> includes;
- const std::string& config =
- this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
- lang, config);
+ lang, this->ConfigName);
std::string includeFlags = this->LocalGenerator->GetIncludeFlags(
- includes, this->GeneratorTarget, lang, false, useResponseFile, config);
+ includes, this->GeneratorTarget, lang, false, useResponseFile,
+ this->ConfigName);
if (includeFlags.empty()) {
return;
}
if (useResponseFile) {
- std::string name = "includes_";
- name += lang;
- name += ".rsp";
- std::string arg = "@" +
+ std::string const responseFlagVar =
+ "CMAKE_" + lang + "_RESPONSE_FILE_FLAG";
+ std::string responseFlag =
+ this->Makefile->GetSafeDefinition(responseFlagVar);
+ if (responseFlag.empty()) {
+ responseFlag = "@";
+ }
+ std::string name = cmStrCat("includes_", lang, ".rsp");
+ std::string arg = std::move(responseFlag) +
this->CreateResponseFile(name.c_str(), includeFlags,
this->FlagFileDepends[lang]);
this->LocalGenerator->AppendFlags(flags, arg);
@@ -1724,40 +1760,41 @@ void cmMakefileTargetGenerator::GenDefFile(
return;
}
std::string cmd = cmSystemTools::GetCMakeCommand();
- cmd =
- this->LocalGenerator->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL);
- cmd += " -E __create_def ";
- cmd += this->LocalGenerator->ConvertToOutputFormat(
- this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), mdi->DefFile),
- cmOutputConverter::SHELL);
- cmd += " ";
+ cmd = cmStrCat(
+ this->LocalGenerator->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL),
+ " -E __create_def ",
+ this->LocalGenerator->ConvertToOutputFormat(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), mdi->DefFile),
+ cmOutputConverter::SHELL),
+ ' ');
std::string objlist_file = mdi->DefFile + ".objs";
cmd += this->LocalGenerator->ConvertToOutputFormat(
this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file),
cmOutputConverter::SHELL);
+ const char* nm_executable = this->Makefile->GetDefinition("CMAKE_NM");
+ if (nm_executable && *nm_executable) {
+ cmd += " --nm=";
+ cmd += this->LocalCommonGenerator->ConvertToOutputFormat(
+ nm_executable, cmOutputConverter::SHELL);
+ }
real_link_commands.insert(real_link_commands.begin(), cmd);
// create a list of obj files for the -E __create_def to read
- cmGeneratedFileStream fout(objlist_file.c_str());
+ cmGeneratedFileStream fout(objlist_file);
if (mdi->WindowsExportAllSymbols) {
- for (std::vector<std::string>::const_iterator i = this->Objects.begin();
- i != this->Objects.end(); ++i) {
- if (cmHasLiteralSuffix(*i, ".obj")) {
- fout << *i << "\n";
+ for (std::string const& obj : this->Objects) {
+ if (cmHasLiteralSuffix(obj, ".obj")) {
+ fout << obj << "\n";
}
}
- for (std::vector<std::string>::const_iterator i =
- this->ExternalObjects.begin();
- i != this->ExternalObjects.end(); ++i) {
- fout << *i << "\n";
+ for (std::string const& obj : this->ExternalObjects) {
+ fout << obj << "\n";
}
}
- for (std::vector<cmSourceFile const*>::const_iterator i =
- mdi->Sources.begin();
- i != mdi->Sources.end(); ++i) {
- fout << (*i)->GetFullPath() << "\n";
+ for (cmSourceFile const* src : mdi->Sources) {
+ fout << src->GetFullPath() << "\n";
}
}
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index 92c9f60b0..7b9c7a5ff 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -3,21 +3,22 @@
#ifndef cmMakefileTargetGenerator_h
#define cmMakefileTargetGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <map>
+#include <memory>
#include <set>
#include <string>
#include <vector>
#include "cmCommonTargetGenerator.h"
+#include "cmGeneratorTarget.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmOSXBundleGenerator.h"
class cmCustomCommandGenerator;
class cmGeneratedFileStream;
-class cmGeneratorTarget;
class cmGlobalUnixMakefileGenerator3;
class cmLinkLineComputer;
class cmOutputConverter;
@@ -33,7 +34,7 @@ class cmMakefileTargetGenerator : public cmCommonTargetGenerator
public:
// constructor to set the ivars
cmMakefileTargetGenerator(cmGeneratorTarget* target);
- ~cmMakefileTargetGenerator() CM_OVERRIDE;
+ ~cmMakefileTargetGenerator() override;
// construct using this factory call
static cmMakefileTargetGenerator* New(cmGeneratorTarget* tgt);
@@ -52,6 +53,8 @@ public:
cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; }
protected:
+ void GetTargetLinkFlags(std::string& flags, const std::string& linkLanguage);
+
// create the file and directory etc
void CreateRuleFile();
@@ -63,16 +66,13 @@ protected:
void WriteCommonCodeRules();
void WriteTargetLanguageFlags();
- // write the provide require rules for this target
- void WriteTargetRequiresRules();
-
// write the clean rules for this target
void WriteTargetCleanRules();
// write the depend rules for this target
void WriteTargetDependRules();
- // write rules for Mac OS X Application Bundle content.
+ // write rules for macOS Application Bundle content.
struct MacOSXContentGeneratorType
: cmOSXBundleGenerator::MacOSXContentGeneratorType
{
@@ -81,8 +81,7 @@ protected:
{
}
- void operator()(cmSourceFile const& source,
- const char* pkgloc) CM_OVERRIDE;
+ void operator()(cmSourceFile const& source, const char* pkgloc) override;
private:
cmMakefileTargetGenerator* Generator;
@@ -92,11 +91,6 @@ protected:
// write the rules for an object
void WriteObjectRuleFiles(cmSourceFile const& source);
- // write the build rule for an object
- void WriteObjectBuildFile(std::string& obj, const std::string& lang,
- cmSourceFile const& source,
- std::vector<std::string>& depends);
-
// write the depend.make file for an object
void WriteObjectDependRules(cmSourceFile const& source,
std::vector<std::string>& depends);
@@ -130,7 +124,8 @@ protected:
void AppendObjectDepends(std::vector<std::string>& depends);
// Append link rule dependencies (objects, etc.).
- void AppendLinkDepends(std::vector<std::string>& depends);
+ void AppendLinkDepends(std::vector<std::string>& depends,
+ const std::string& linkLanguage);
// Lookup the link rule for this target.
std::string GetLinkRule(const std::string& linkRuleVar);
@@ -168,8 +163,7 @@ protected:
/** Add commands for generate def files */
void GenDefFile(std::vector<std::string>& real_link_commands);
- void AddIncludeFlags(std::string& flags,
- const std::string& lang) CM_OVERRIDE;
+ void AddIncludeFlags(std::string& flags, const std::string& lang) override;
virtual void CloseFileStreams();
cmLocalUnixMakefileGenerator3* LocalGenerator;
@@ -212,7 +206,7 @@ protected:
cmGeneratedFileStream* InfoFileStream;
// files to clean
- std::vector<std::string> CleanFiles;
+ std::set<std::string> CleanFiles;
// objects used by this target
std::vector<std::string> Objects;
@@ -224,7 +218,7 @@ protected:
// Set of extra output files to be driven by the build.
std::set<std::string> ExtraFiles;
- typedef std::map<std::string, std::string> MultipleOutputPairsType;
+ using MultipleOutputPairsType = std::map<std::string, std::string>;
MultipleOutputPairsType MultipleOutputPairs;
bool WriteMakeRule(std::ostream& os, const char* comment,
const std::vector<std::string>& outputs,
@@ -233,15 +227,11 @@ protected:
bool in_help = false);
// Target name info.
- std::string TargetNameOut;
- std::string TargetNameSO;
- std::string TargetNameReal;
- std::string TargetNameImport;
- std::string TargetNamePDB;
+ cmGeneratorTarget::Names TargetNames;
- // Mac OS X content info.
+ // macOS content info.
std::set<std::string> MacContentFolders;
- cmOSXBundleGenerator* OSXBundleGenerator;
+ std::unique_ptr<cmOSXBundleGenerator> OSXBundleGenerator;
MacOSXContentGeneratorType* MacOSXContentGenerator;
};
diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx
index a7c5d27f2..1625e4fdb 100644
--- a/Source/cmMakefileUtilityTargetGenerator.cxx
+++ b/Source/cmMakefileUtilityTargetGenerator.cxx
@@ -4,8 +4,11 @@
#include <ostream>
#include <string>
+#include <utility>
#include <vector>
+#include <cm/memory>
+
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalUnixMakefileGenerator3.h"
@@ -20,14 +23,12 @@ cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator(
{
this->CustomCommandDriver = OnUtility;
this->OSXBundleGenerator =
- new cmOSXBundleGenerator(target, this->ConfigName);
+ cm::make_unique<cmOSXBundleGenerator>(target, this->ConfigName);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
}
-cmMakefileUtilityTargetGenerator::~cmMakefileUtilityTargetGenerator()
-{
- delete this->OSXBundleGenerator;
-}
+cmMakefileUtilityTargetGenerator::~cmMakefileUtilityTargetGenerator() =
+ default;
void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
{
@@ -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,12 +89,12 @@ 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));
}
}
// Write the rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR,
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
this->GeneratorTarget->GetName(),
depends, commands, true);
diff --git a/Source/cmMakefileUtilityTargetGenerator.h b/Source/cmMakefileUtilityTargetGenerator.h
index 8df5dd46f..be243a7f5 100644
--- a/Source/cmMakefileUtilityTargetGenerator.h
+++ b/Source/cmMakefileUtilityTargetGenerator.h
@@ -3,7 +3,7 @@
#ifndef cmMakefileUtilityTargetGenerator_h
#define cmMakefileUtilityTargetGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include "cmMakefileTargetGenerator.h"
@@ -13,11 +13,11 @@ class cmMakefileUtilityTargetGenerator : public cmMakefileTargetGenerator
{
public:
cmMakefileUtilityTargetGenerator(cmGeneratorTarget* target);
- ~cmMakefileUtilityTargetGenerator() CM_OVERRIDE;
+ ~cmMakefileUtilityTargetGenerator() override;
/* the main entry point for this class. Writes the Makefiles associated
with this target */
- void WriteRuleFiles() CM_OVERRIDE;
+ void WriteRuleFiles() override;
protected:
};
diff --git a/Source/cmMarkAsAdvancedCommand.cxx b/Source/cmMarkAsAdvancedCommand.cxx
index 14fd96f08..ca46e14c2 100644
--- a/Source/cmMarkAsAdvancedCommand.cxx
+++ b/Source/cmMarkAsAdvancedCommand.cxx
@@ -2,20 +2,19 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMarkAsAdvancedCommand.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmake.h"
-class cmExecutionStatus;
-
// cmMarkAsAdvancedCommand
-bool cmMarkAsAdvancedCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmMarkAsAdvancedCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
@@ -31,10 +30,10 @@ bool cmMarkAsAdvancedCommand::InitialPass(std::vector<std::string> const& args,
}
for (; i < args.size(); ++i) {
std::string const& variable = args[i];
- cmState* state = this->Makefile->GetState();
+ cmState* state = status.GetMakefile().GetState();
if (!state->GetCacheEntryValue(variable)) {
- this->Makefile->GetCMakeInstance()->AddCacheEntry(
- variable, CM_NULLPTR, CM_NULLPTR, cmStateEnums::UNINITIALIZED);
+ status.GetMakefile().GetCMakeInstance()->AddCacheEntry(
+ variable, nullptr, nullptr, cmStateEnums::UNINITIALIZED);
overwrite = true;
}
if (!state->GetCacheEntryValue(variable)) {
diff --git a/Source/cmMarkAsAdvancedCommand.h b/Source/cmMarkAsAdvancedCommand.h
index a7791a932..de7bf08b4 100644
--- a/Source/cmMarkAsAdvancedCommand.h
+++ b/Source/cmMarkAsAdvancedCommand.h
@@ -3,34 +3,19 @@
#ifndef cmMarkAsAdvancedCommand_h
#define cmMarkAsAdvancedCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmMarkAsAdvancedCommand
+/**
* \brief mark_as_advanced command
*
* cmMarkAsAdvancedCommand implements the mark_as_advanced CMake command
*/
-class cmMarkAsAdvancedCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmMarkAsAdvancedCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmMarkAsAdvancedCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmMathCommand.cxx b/Source/cmMathCommand.cxx
index c1cd1b6c2..f11b906d4 100644
--- a/Source/cmMathCommand.cxx
+++ b/Source/cmMathCommand.cxx
@@ -2,50 +2,119 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMathCommand.h"
-#include <stdio.h>
+#include <cstdio>
+#include "cm_kwiml.h"
+
+#include "cmExecutionStatus.h"
#include "cmExprParserHelper.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
-class cmExecutionStatus;
+namespace {
+bool HandleExprCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+}
-bool cmMathCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmMathCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("must be called with at least one argument.");
+ status.SetError("must be called with at least one argument.");
return false;
}
const std::string& subCommand = args[0];
if (subCommand == "EXPR") {
- return this->HandleExprCommand(args);
+ return HandleExprCommand(args, status);
}
std::string e = "does not recognize sub-command " + subCommand;
- this->SetError(e);
+ status.SetError(e);
return false;
}
-bool cmMathCommand::HandleExprCommand(std::vector<std::string> const& args)
+namespace {
+bool HandleExprCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- if (args.size() != 3) {
- this->SetError("EXPR called with incorrect arguments.");
+ if ((args.size() != 3) && (args.size() != 5)) {
+ status.SetError("EXPR called with incorrect arguments.");
return false;
}
+ enum class NumericFormat
+ {
+ UNINITIALIZED,
+ DECIMAL,
+ HEXADECIMAL,
+ };
+
const std::string& outputVariable = args[1];
const std::string& expression = args[2];
+ size_t argumentIndex = 3;
+ NumericFormat outputFormat = NumericFormat::UNINITIALIZED;
+
+ status.GetMakefile().AddDefinition(outputVariable, "ERROR");
+
+ if (argumentIndex < args.size()) {
+ const std::string messageHint = "sub-command EXPR ";
+ const std::string option = args[argumentIndex++];
+ if (option == "OUTPUT_FORMAT") {
+ if (argumentIndex < args.size()) {
+ const std::string argument = args[argumentIndex++];
+ if (argument == "DECIMAL") {
+ outputFormat = NumericFormat::DECIMAL;
+ } else if (argument == "HEXADECIMAL") {
+ outputFormat = NumericFormat::HEXADECIMAL;
+ } else {
+ std::string error = messageHint + "value \"" + argument +
+ "\" for option \"" + option + "\" is invalid.";
+ status.SetError(error);
+ return false;
+ }
+ } else {
+ std::string error =
+ messageHint + "missing argument for option \"" + option + "\".";
+ status.SetError(error);
+ return false;
+ }
+ } else {
+ std::string error =
+ messageHint + "option \"" + option + "\" is unknown.";
+ status.SetError(error);
+ return false;
+ }
+ }
+
+ if (outputFormat == NumericFormat::UNINITIALIZED) {
+ outputFormat = NumericFormat::DECIMAL;
+ }
cmExprParserHelper helper;
if (!helper.ParseString(expression.c_str(), 0)) {
- std::string e = "cannot parse the expression: \"" + expression + "\": ";
- e += helper.GetError();
- this->SetError(e);
+ status.SetError(helper.GetError());
return false;
}
char buffer[1024];
- sprintf(buffer, "%d", helper.GetResult());
+ const char* fmt;
+ switch (outputFormat) {
+ case NumericFormat::HEXADECIMAL:
+ fmt = "0x%" KWIML_INT_PRIx64;
+ break;
+ case NumericFormat::DECIMAL:
+ CM_FALLTHROUGH;
+ default:
+ fmt = "%" KWIML_INT_PRId64;
+ break;
+ }
+ sprintf(buffer, fmt, helper.GetResult());
- this->Makefile->AddDefinition(outputVariable, buffer);
+ std::string const& w = helper.GetWarning();
+ if (!w.empty()) {
+ status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, w);
+ }
+
+ status.GetMakefile().AddDefinition(outputVariable, buffer);
return true;
}
+}
diff --git a/Source/cmMathCommand.h b/Source/cmMathCommand.h
index 67dbdda37..ac1957c24 100644
--- a/Source/cmMathCommand.h
+++ b/Source/cmMathCommand.h
@@ -3,33 +3,15 @@
#ifndef cmMathCommand_h
#define cmMathCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
/// Mathematical expressions: math(EXPR ...) command.
-class cmMathCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmMathCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-protected:
- bool HandleExprCommand(std::vector<std::string> const& args);
-};
+bool cmMathCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx
index 43fb5f54c..96a6386bf 100644
--- a/Source/cmMessageCommand.cxx
+++ b/Source/cmMessageCommand.cxx
@@ -2,77 +2,143 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMessageCommand.h"
-#include "cmAlgorithms.h"
+#include <cassert>
+
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmMessenger.h"
+#include "cmRange.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
-class cmExecutionStatus;
-
// cmLibraryCommand
-bool cmMessageCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmMessageCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
- std::vector<std::string>::const_iterator i = args.begin();
+ auto i = args.cbegin();
- cmake::MessageType type = cmake::MESSAGE;
- bool status = false;
- bool fatal = false;
+ auto type = MessageType::MESSAGE;
+ auto fatal = false;
+ auto level = cmake::LogLevel::LOG_UNDEFINED;
if (*i == "SEND_ERROR") {
- type = cmake::FATAL_ERROR;
+ type = MessageType::FATAL_ERROR;
+ level = cmake::LogLevel::LOG_ERROR;
++i;
} else if (*i == "FATAL_ERROR") {
fatal = true;
- type = cmake::FATAL_ERROR;
+ type = MessageType::FATAL_ERROR;
+ level = cmake::LogLevel::LOG_ERROR;
++i;
} else if (*i == "WARNING") {
- type = cmake::WARNING;
+ type = MessageType::WARNING;
+ level = cmake::LogLevel::LOG_WARNING;
++i;
} else if (*i == "AUTHOR_WARNING") {
- if (this->Makefile->IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") &&
- !this->Makefile->IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) {
+ if (status.GetMakefile().IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") &&
+ !status.GetMakefile().IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) {
fatal = true;
- type = cmake::AUTHOR_ERROR;
- } else if (!this->Makefile->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) {
- type = cmake::AUTHOR_WARNING;
+ type = MessageType::AUTHOR_ERROR;
+ level = cmake::LogLevel::LOG_ERROR;
+ } else if (!status.GetMakefile().IsOn(
+ "CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) {
+ type = MessageType::AUTHOR_WARNING;
+ level = cmake::LogLevel::LOG_WARNING;
} else {
return true;
}
++i;
} else if (*i == "STATUS") {
- status = true;
+ level = cmake::LogLevel::LOG_STATUS;
+ ++i;
+ } else if (*i == "VERBOSE") {
+ level = cmake::LogLevel::LOG_VERBOSE;
+ ++i;
+ } else if (*i == "DEBUG") {
+ level = cmake::LogLevel::LOG_DEBUG;
+ ++i;
+ } else if (*i == "TRACE") {
+ level = cmake::LogLevel::LOG_TRACE;
++i;
} else if (*i == "DEPRECATION") {
- if (this->Makefile->IsOn("CMAKE_ERROR_DEPRECATED")) {
+ if (status.GetMakefile().IsOn("CMAKE_ERROR_DEPRECATED")) {
fatal = true;
- type = cmake::DEPRECATION_ERROR;
- } else if ((!this->Makefile->IsSet("CMAKE_WARN_DEPRECATED") ||
- this->Makefile->IsOn("CMAKE_WARN_DEPRECATED"))) {
- type = cmake::DEPRECATION_WARNING;
+ type = MessageType::DEPRECATION_ERROR;
+ level = cmake::LogLevel::LOG_ERROR;
+ } else if (!status.GetMakefile().IsSet("CMAKE_WARN_DEPRECATED") ||
+ status.GetMakefile().IsOn("CMAKE_WARN_DEPRECATED")) {
+ type = MessageType::DEPRECATION_WARNING;
+ level = cmake::LogLevel::LOG_WARNING;
} else {
return true;
}
++i;
+ } else if (*i == "NOTICE") {
+ // `NOTICE` message type is going to be output to stderr
+ level = cmake::LogLevel::LOG_NOTICE;
+ ++i;
+ } else {
+ // Messages w/o any type are `NOTICE`s
+ level = cmake::LogLevel::LOG_NOTICE;
}
+ assert("Message log level expected to be set" &&
+ level != cmake::LogLevel::LOG_UNDEFINED);
- std::string message = cmJoin(cmMakeRange(i, args.end()), std::string());
+ auto desiredLevel = status.GetMakefile().GetCMakeInstance()->GetLogLevel();
+ assert("Expected a valid log level here" &&
+ desiredLevel != cmake::LogLevel::LOG_UNDEFINED);
- if (type != cmake::MESSAGE) {
- // we've overriden the message type, above, so display it directly
- cmMessenger* m = this->Makefile->GetMessenger();
- m->DisplayMessage(type, message, this->Makefile->GetBacktrace());
- } else {
- if (status) {
- this->Makefile->DisplayStatus(message.c_str(), -1);
- } else {
- cmSystemTools::Message(message.c_str());
- }
+ if (desiredLevel < level) {
+ // Suppress the message
+ return true;
}
+
+ auto message = cmJoin(cmMakeRange(i, args.cend()), "");
+
+ if (cmake::LogLevel::LOG_NOTICE <= level) {
+ // Check if any indentation has requested:
+ // `CMAKE_MESSAGE_INDENT` is a list of "padding" pieces
+ // to be joined and prepended to the message lines.
+ auto indent = cmJoin(cmExpandedList(status.GetMakefile().GetSafeDefinition(
+ "CMAKE_MESSAGE_INDENT")),
+ "");
+ // Make every line of the `message` indented
+ // NOTE Can't reuse `cmDocumentationFormatter::PrintPreformatted`
+ // here cuz it appends `\n` to the EOM ;-(
+ cmSystemTools::ReplaceString(message, "\n", "\n" + indent);
+ message = indent + message;
+ }
+
+ switch (level) {
+ case cmake::LogLevel::LOG_ERROR:
+ case cmake::LogLevel::LOG_WARNING:
+ // we've overridden the message type, above, so display it directly
+ status.GetMakefile().GetMessenger()->DisplayMessage(
+ type, message, status.GetMakefile().GetBacktrace());
+ break;
+
+ case cmake::LogLevel::LOG_NOTICE:
+ cmSystemTools::Message(message);
+ break;
+
+ case cmake::LogLevel::LOG_STATUS:
+ case cmake::LogLevel::LOG_VERBOSE:
+ case cmake::LogLevel::LOG_DEBUG:
+ case cmake::LogLevel::LOG_TRACE:
+ status.GetMakefile().DisplayStatus(message, -1);
+ break;
+
+ default:
+ assert("Unexpected log level! Review the `cmMessageCommand.cxx`." &&
+ false);
+ break;
+ }
+
if (fatal) {
cmSystemTools::SetFatalErrorOccured();
}
diff --git a/Source/cmMessageCommand.h b/Source/cmMessageCommand.h
index 96939e514..7d544c408 100644
--- a/Source/cmMessageCommand.h
+++ b/Source/cmMessageCommand.h
@@ -3,33 +3,18 @@
#ifndef cmMessageCommand_h
#define cmMessageCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmMessageCommand
+/**
* \brief Displays a message to the user
*
*/
-class cmMessageCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmMessageCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmMessageCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmMessageType.h b/Source/cmMessageType.h
new file mode 100644
index 000000000..b57b86bee
--- /dev/null
+++ b/Source/cmMessageType.h
@@ -0,0 +1,21 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmMessageType_h
+#define cmMessageType_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+enum class MessageType
+{
+ AUTHOR_WARNING,
+ AUTHOR_ERROR,
+ FATAL_ERROR,
+ INTERNAL_ERROR,
+ MESSAGE,
+ WARNING,
+ LOG,
+ DEPRECATION_ERROR,
+ DEPRECATION_WARNING
+};
+
+#endif
diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx
index 3ae5bc5c2..af83478a6 100644
--- a/Source/cmMessenger.cxx
+++ b/Source/cmMessenger.cxx
@@ -2,58 +2,57 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMessenger.h"
-#include "cmAlgorithms.h"
#include "cmDocumentationFormatter.h"
-#include "cmState.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmsys/SystemInformation.hxx"
+#if !defined(CMAKE_BOOTSTRAP)
+# include "cmsys/SystemInformation.hxx"
#endif
#include <sstream>
-cmake::MessageType cmMessenger::ConvertMessageType(cmake::MessageType t) const
+MessageType cmMessenger::ConvertMessageType(MessageType t) const
{
bool warningsAsErrors;
- if (t == cmake::AUTHOR_WARNING || t == cmake::AUTHOR_ERROR) {
+ if (t == MessageType::AUTHOR_WARNING || t == MessageType::AUTHOR_ERROR) {
warningsAsErrors = this->GetDevWarningsAsErrors();
- if (warningsAsErrors && t == cmake::AUTHOR_WARNING) {
- t = cmake::AUTHOR_ERROR;
- } else if (!warningsAsErrors && t == cmake::AUTHOR_ERROR) {
- t = cmake::AUTHOR_WARNING;
+ if (warningsAsErrors && t == MessageType::AUTHOR_WARNING) {
+ t = MessageType::AUTHOR_ERROR;
+ } else if (!warningsAsErrors && t == MessageType::AUTHOR_ERROR) {
+ t = MessageType::AUTHOR_WARNING;
}
- } else if (t == cmake::DEPRECATION_WARNING ||
- t == cmake::DEPRECATION_ERROR) {
+ } else if (t == MessageType::DEPRECATION_WARNING ||
+ t == MessageType::DEPRECATION_ERROR) {
warningsAsErrors = this->GetDeprecatedWarningsAsErrors();
- if (warningsAsErrors && t == cmake::DEPRECATION_WARNING) {
- t = cmake::DEPRECATION_ERROR;
- } else if (!warningsAsErrors && t == cmake::DEPRECATION_ERROR) {
- t = cmake::DEPRECATION_WARNING;
+ if (warningsAsErrors && t == MessageType::DEPRECATION_WARNING) {
+ t = MessageType::DEPRECATION_ERROR;
+ } else if (!warningsAsErrors && t == MessageType::DEPRECATION_ERROR) {
+ t = MessageType::DEPRECATION_WARNING;
}
}
return t;
}
-bool cmMessenger::IsMessageTypeVisible(cmake::MessageType t) const
+bool cmMessenger::IsMessageTypeVisible(MessageType t) const
{
bool isVisible = true;
- if (t == cmake::DEPRECATION_ERROR) {
+ if (t == MessageType::DEPRECATION_ERROR) {
if (!this->GetDeprecatedWarningsAsErrors()) {
isVisible = false;
}
- } else if (t == cmake::DEPRECATION_WARNING) {
+ } else if (t == MessageType::DEPRECATION_WARNING) {
if (this->GetSuppressDeprecatedWarnings()) {
isVisible = false;
}
- } else if (t == cmake::AUTHOR_ERROR) {
+ } else if (t == MessageType::AUTHOR_ERROR) {
if (!this->GetDevWarningsAsErrors()) {
isVisible = false;
}
- } else if (t == cmake::AUTHOR_WARNING) {
+ } else if (t == MessageType::AUTHOR_WARNING) {
if (this->GetSuppressDevWarnings()) {
isVisible = false;
}
@@ -62,22 +61,22 @@ bool cmMessenger::IsMessageTypeVisible(cmake::MessageType t) const
return isVisible;
}
-static bool printMessagePreamble(cmake::MessageType t, std::ostream& msg)
+static bool printMessagePreamble(MessageType t, std::ostream& msg)
{
// Construct the message header.
- if (t == cmake::FATAL_ERROR) {
+ if (t == MessageType::FATAL_ERROR) {
msg << "CMake Error";
- } else if (t == cmake::INTERNAL_ERROR) {
+ } else if (t == MessageType::INTERNAL_ERROR) {
msg << "CMake Internal Error (please report a bug)";
- } else if (t == cmake::LOG) {
+ } else if (t == MessageType::LOG) {
msg << "CMake Debug Log";
- } else if (t == cmake::DEPRECATION_ERROR) {
+ } else if (t == MessageType::DEPRECATION_ERROR) {
msg << "CMake Deprecation Error";
- } else if (t == cmake::DEPRECATION_WARNING) {
+ } else if (t == MessageType::DEPRECATION_WARNING) {
msg << "CMake Deprecation Warning";
- } else if (t == cmake::AUTHOR_WARNING) {
+ } else if (t == MessageType::AUTHOR_WARNING) {
msg << "CMake Warning (dev)";
- } else if (t == cmake::AUTHOR_ERROR) {
+ } else if (t == MessageType::AUTHOR_ERROR) {
msg << "CMake Error (dev)";
} else {
msg << "CMake Warning";
@@ -93,24 +92,23 @@ void printMessageText(std::ostream& msg, std::string const& text)
formatter.PrintFormatted(msg, text.c_str());
}
-void displayMessage(cmake::MessageType t, std::ostringstream& msg)
+void displayMessage(MessageType t, std::ostringstream& msg)
{
// Add a note about warning suppression.
- if (t == cmake::AUTHOR_WARNING) {
+ if (t == MessageType::AUTHOR_WARNING) {
msg << "This warning is for project developers. Use -Wno-dev to suppress "
"it.";
- } else if (t == cmake::AUTHOR_ERROR) {
+ } else if (t == MessageType::AUTHOR_ERROR) {
msg << "This error is for project developers. Use -Wno-error=dev to "
- "suppress "
- "it.";
+ "suppress it.";
}
// Add a terminating blank line.
msg << "\n";
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
// Add a C++ stack trace to internal errors.
- if (t == cmake::INTERNAL_ERROR) {
+ if (t == MessageType::INTERNAL_ERROR) {
std::string stack = cmsys::SystemInformation::GetProgramStack(0, 0);
if (!stack.empty()) {
if (cmHasLiteralPrefix(stack, "WARNING:")) {
@@ -122,27 +120,22 @@ void displayMessage(cmake::MessageType t, std::ostringstream& msg)
#endif
// Output the message.
- if (t == cmake::FATAL_ERROR || t == cmake::INTERNAL_ERROR ||
- t == cmake::DEPRECATION_ERROR || t == cmake::AUTHOR_ERROR) {
+ if (t == MessageType::FATAL_ERROR || t == MessageType::INTERNAL_ERROR ||
+ t == MessageType::DEPRECATION_ERROR || t == MessageType::AUTHOR_ERROR) {
cmSystemTools::SetErrorOccured();
- cmSystemTools::Message(msg.str().c_str(), "Error");
+ cmSystemTools::Message(msg.str(), "Error");
} else {
- cmSystemTools::Message(msg.str().c_str(), "Warning");
+ cmSystemTools::Message(msg.str(), "Warning");
}
}
-cmMessenger::cmMessenger(cmState* state)
- : State(state)
-{
-}
-
-void cmMessenger::IssueMessage(cmake::MessageType t, const std::string& text,
+void cmMessenger::IssueMessage(MessageType t, const std::string& text,
const cmListFileBacktrace& backtrace) const
{
bool force = false;
if (!force) {
// override the message type, if needed, for warnings and errors
- cmake::MessageType override = this->ConvertMessageType(t);
+ MessageType override = this->ConvertMessageType(t);
if (override != t) {
t = override;
force = true;
@@ -155,7 +148,7 @@ void cmMessenger::IssueMessage(cmake::MessageType t, const std::string& text,
this->DisplayMessage(t, text, backtrace);
}
-void cmMessenger::DisplayMessage(cmake::MessageType t, const std::string& text,
+void cmMessenger::DisplayMessage(MessageType t, const std::string& text,
const cmListFileBacktrace& backtrace) const
{
std::ostringstream msg;
@@ -173,31 +166,3 @@ void cmMessenger::DisplayMessage(cmake::MessageType t, const std::string& text,
displayMessage(t, msg);
}
-
-bool cmMessenger::GetSuppressDevWarnings() const
-{
- const char* cacheEntryValue =
- this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_WARNINGS");
- return cmSystemTools::IsOn(cacheEntryValue);
-}
-
-bool cmMessenger::GetSuppressDeprecatedWarnings() const
-{
- const char* cacheEntryValue =
- this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED");
- return cacheEntryValue && cmSystemTools::IsOff(cacheEntryValue);
-}
-
-bool cmMessenger::GetDevWarningsAsErrors() const
-{
- const char* cacheEntryValue =
- this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_ERRORS");
- return cacheEntryValue && cmSystemTools::IsOff(cacheEntryValue);
-}
-
-bool cmMessenger::GetDeprecatedWarningsAsErrors() const
-{
- const char* cacheEntryValue =
- this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED");
- return cmSystemTools::IsOn(cacheEntryValue);
-}
diff --git a/Source/cmMessenger.h b/Source/cmMessenger.h
index 4aafbd40b..8c097827e 100644
--- a/Source/cmMessenger.h
+++ b/Source/cmMessenger.h
@@ -5,35 +5,57 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmListFileCache.h"
-#include "cmake.h"
-
#include <string>
-class cmState;
+#include "cmListFileCache.h"
+#include "cmMessageType.h"
class cmMessenger
{
public:
- cmMessenger(cmState* state);
-
void IssueMessage(
- cmake::MessageType t, std::string const& text,
+ MessageType t, std::string const& text,
cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const;
- void DisplayMessage(cmake::MessageType t, std::string const& text,
+ void DisplayMessage(MessageType t, std::string const& text,
cmListFileBacktrace const& backtrace) const;
- bool GetSuppressDevWarnings() const;
- bool GetSuppressDeprecatedWarnings() const;
- bool GetDevWarningsAsErrors() const;
- bool GetDeprecatedWarningsAsErrors() const;
+ void SetSuppressDevWarnings(bool suppress)
+ {
+ this->SuppressDevWarnings = suppress;
+ }
+ void SetSuppressDeprecatedWarnings(bool suppress)
+ {
+ this->SuppressDeprecatedWarnings = suppress;
+ }
+ void SetDevWarningsAsErrors(bool error)
+ {
+ this->DevWarningsAsErrors = error;
+ }
+ void SetDeprecatedWarningsAsErrors(bool error)
+ {
+ this->DeprecatedWarningsAsErrors = error;
+ }
+
+ bool GetSuppressDevWarnings() const { return this->SuppressDevWarnings; }
+ bool GetSuppressDeprecatedWarnings() const
+ {
+ return this->SuppressDeprecatedWarnings;
+ }
+ bool GetDevWarningsAsErrors() const { return this->DevWarningsAsErrors; }
+ bool GetDeprecatedWarningsAsErrors() const
+ {
+ return this->DeprecatedWarningsAsErrors;
+ }
private:
- bool IsMessageTypeVisible(cmake::MessageType t) const;
- cmake::MessageType ConvertMessageType(cmake::MessageType t) const;
+ bool IsMessageTypeVisible(MessageType t) const;
+ MessageType ConvertMessageType(MessageType t) const;
- cmState* State;
+ bool SuppressDevWarnings = false;
+ bool SuppressDeprecatedWarnings = false;
+ bool DevWarningsAsErrors = false;
+ bool DeprecatedWarningsAsErrors = false;
};
#endif
diff --git a/Source/cmNewLineStyle.cxx b/Source/cmNewLineStyle.cxx
index 5500eba65..a121332b2 100644
--- a/Source/cmNewLineStyle.cxx
+++ b/Source/cmNewLineStyle.cxx
@@ -2,12 +2,9 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmNewLineStyle.h"
-#include <stddef.h>
+#include <cstddef>
-cmNewLineStyle::cmNewLineStyle()
- : NewLineStyle(Invalid)
-{
-}
+cmNewLineStyle::cmNewLineStyle() = default;
bool cmNewLineStyle::IsValid() const
{
@@ -44,7 +41,7 @@ bool cmNewLineStyle::ReadFromArguments(const std::vector<std::string>& args,
return true;
}
-const std::string cmNewLineStyle::GetCharacters() const
+std::string cmNewLineStyle::GetCharacters() const
{
switch (NewLineStyle) {
case Invalid:
diff --git a/Source/cmNewLineStyle.h b/Source/cmNewLineStyle.h
index 397cd2c50..ab9002e4d 100644
--- a/Source/cmNewLineStyle.h
+++ b/Source/cmNewLineStyle.h
@@ -30,10 +30,10 @@ public:
bool ReadFromArguments(const std::vector<std::string>& args,
std::string& errorString);
- const std::string GetCharacters() const;
+ std::string GetCharacters() const;
private:
- Style NewLineStyle;
+ Style NewLineStyle = Invalid;
};
#endif
diff --git a/Source/cmNinjaLinkLineComputer.h b/Source/cmNinjaLinkLineComputer.h
index 13f05a838..b2b2e84e1 100644
--- a/Source/cmNinjaLinkLineComputer.h
+++ b/Source/cmNinjaLinkLineComputer.h
@@ -4,7 +4,7 @@
#ifndef cmNinjaLinkLineComputer_h
#define cmNinjaLinkLineComputer_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
@@ -16,15 +16,15 @@ class cmStateDirectory;
class cmNinjaLinkLineComputer : public cmLinkLineComputer
{
- CM_DISABLE_COPY(cmNinjaLinkLineComputer)
-
public:
cmNinjaLinkLineComputer(cmOutputConverter* outputConverter,
cmStateDirectory const& stateDir,
cmGlobalNinjaGenerator const* gg);
- std::string ConvertToLinkReference(std::string const& input) const
- CM_OVERRIDE;
+ cmNinjaLinkLineComputer(cmNinjaLinkLineComputer const&) = delete;
+ cmNinjaLinkLineComputer& operator=(cmNinjaLinkLineComputer const&) = delete;
+
+ std::string ConvertToLinkReference(std::string const& input) const override;
private:
cmGlobalNinjaGenerator const* GG;
diff --git a/Source/cmNinjaLinkLineDeviceComputer.cxx b/Source/cmNinjaLinkLineDeviceComputer.cxx
new file mode 100644
index 000000000..84c1b37d3
--- /dev/null
+++ b/Source/cmNinjaLinkLineDeviceComputer.cxx
@@ -0,0 +1,20 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmNinjaLinkLineDeviceComputer.h"
+
+#include "cmGlobalNinjaGenerator.h"
+
+cmNinjaLinkLineDeviceComputer::cmNinjaLinkLineDeviceComputer(
+ cmOutputConverter* outputConverter, cmStateDirectory const& stateDir,
+ cmGlobalNinjaGenerator const* gg)
+ : cmLinkLineDeviceComputer(outputConverter, stateDir)
+ , GG(gg)
+{
+}
+
+std::string cmNinjaLinkLineDeviceComputer::ConvertToLinkReference(
+ std::string const& lib) const
+{
+ return GG->ConvertToNinjaPath(lib);
+}
diff --git a/Source/cmNinjaLinkLineDeviceComputer.h b/Source/cmNinjaLinkLineDeviceComputer.h
new file mode 100644
index 000000000..84ced5b35
--- /dev/null
+++ b/Source/cmNinjaLinkLineDeviceComputer.h
@@ -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. */
+
+#ifndef cmNinjaLinkLineDeviceComputer_h
+#define cmNinjaLinkLineDeviceComputer_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+
+#include "cmLinkLineDeviceComputer.h"
+
+class cmGlobalNinjaGenerator;
+class cmOutputConverter;
+class cmStateDirectory;
+
+class cmNinjaLinkLineDeviceComputer : public cmLinkLineDeviceComputer
+{
+public:
+ cmNinjaLinkLineDeviceComputer(cmOutputConverter* outputConverter,
+ cmStateDirectory const& stateDir,
+ cmGlobalNinjaGenerator const* gg);
+
+ cmNinjaLinkLineDeviceComputer(cmNinjaLinkLineDeviceComputer const&) = delete;
+ cmNinjaLinkLineDeviceComputer& operator=(
+ cmNinjaLinkLineDeviceComputer const&) = delete;
+
+ std::string ConvertToLinkReference(std::string const& input) const override;
+
+private:
+ cmGlobalNinjaGenerator const* GG;
+};
+
+#endif
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 14a4ef824..beedef4c2 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -3,23 +3,29 @@
#include "cmNinjaNormalTargetGenerator.h"
#include <algorithm>
-#include <assert.h>
+#include <cassert>
#include <iterator>
#include <map>
#include <set>
#include <sstream>
+#include <utility>
+
+#include <cm/memory>
#include "cmAlgorithms.h"
-#include "cmCustomCommand.h"
+#include "cmComputeLinkInformation.h"
+#include "cmCustomCommand.h" // IWYU pragma: keep
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalNinjaGenerator.h"
#include "cmLinkLineComputer.h"
#include "cmLinkLineDeviceComputer.h"
+#include "cmLocalCommonGenerator.h"
#include "cmLocalGenerator.h"
#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
+#include "cmNinjaLinkLineDeviceComputer.h"
#include "cmNinjaTypes.h"
#include "cmOSXBundleGenerator.h"
#include "cmOutputConverter.h"
@@ -29,30 +35,20 @@
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cm_auto_ptr.hxx"
-#include "cmake.h"
cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator(
cmGeneratorTarget* target)
: cmNinjaTargetGenerator(target)
- , TargetNameOut()
- , TargetNameSO()
- , TargetNameReal()
- , TargetNameImport()
- , TargetNamePDB()
, TargetLinkLanguage("")
- , DeviceLinkObject()
{
this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName());
if (target->GetType() == cmStateEnums::EXECUTABLE) {
- this->GetGeneratorTarget()->GetExecutableNames(
- this->TargetNameOut, this->TargetNameReal, this->TargetNameImport,
- this->TargetNamePDB, GetLocalGenerator()->GetConfigName());
+ this->TargetNames = this->GetGeneratorTarget()->GetExecutableNames(
+ GetLocalGenerator()->GetConfigName());
} else {
- this->GetGeneratorTarget()->GetLibraryNames(
- this->TargetNameOut, this->TargetNameSO, this->TargetNameReal,
- this->TargetNameImport, this->TargetNamePDB,
+ this->TargetNames = this->GetGeneratorTarget()->GetLibraryNames(
GetLocalGenerator()->GetConfigName());
}
@@ -63,21 +59,18 @@ cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator(
}
this->OSXBundleGenerator =
- new cmOSXBundleGenerator(target, this->GetConfigName());
+ cm::make_unique<cmOSXBundleGenerator>(target, this->GetConfigName());
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
}
-cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator()
-{
- delete this->OSXBundleGenerator;
-}
+cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator() = default;
void cmNinjaNormalTargetGenerator::Generate()
{
if (this->TargetLinkLanguage.empty()) {
cmSystemTools::Error("CMake can not determine linker language for "
- "target: ",
- this->GetGeneratorTarget()->GetName().c_str());
+ "target: " +
+ this->GetGeneratorTarget()->GetName());
return;
}
@@ -95,6 +88,9 @@ void cmNinjaNormalTargetGenerator::Generate()
this->WriteDeviceLinkStatement();
this->WriteLinkStatement();
}
+
+ // Find ADDITIONAL_CLEAN_FILES
+ this->AdditionalCleanFiles();
}
void cmNinjaNormalTargetGenerator::WriteLanguagesRules()
@@ -112,17 +108,14 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules()
std::vector<cmSourceFile const*> sourceFiles;
this->GetGeneratorTarget()->GetObjectSources(
sourceFiles, this->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"));
- for (std::vector<cmSourceFile const*>::const_iterator i =
- sourceFiles.begin();
- i != sourceFiles.end(); ++i) {
- const std::string& lang = (*i)->GetLanguage();
+ for (cmSourceFile const* sf : sourceFiles) {
+ std::string const lang = sf->GetLanguage();
if (!lang.empty()) {
languages.insert(lang);
}
}
- for (std::set<std::string>::const_iterator l = languages.begin();
- l != languages.end(); ++l) {
- this->WriteLanguageRules(*l);
+ for (std::string const& language : languages) {
+ this->WriteLanguageRules(language);
}
}
@@ -142,7 +135,7 @@ const char* cmNinjaNormalTargetGenerator::GetVisibleTypeName() const
case cmStateEnums::EXECUTABLE:
return "executable";
default:
- return CM_NULLPTR;
+ return nullptr;
}
}
@@ -150,16 +143,18 @@ std::string cmNinjaNormalTargetGenerator::LanguageLinkerRule() const
{
return this->TargetLinkLanguage + "_" +
cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) +
- "_LINKER__" + cmGlobalNinjaGenerator::EncodeRuleName(
- this->GetGeneratorTarget()->GetName());
+ "_LINKER__" +
+ cmGlobalNinjaGenerator::EncodeRuleName(
+ this->GetGeneratorTarget()->GetName());
}
std::string cmNinjaNormalTargetGenerator::LanguageLinkerDeviceRule() const
{
return this->TargetLinkLanguage + "_" +
cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) +
- "_DEVICE_LINKER__" + cmGlobalNinjaGenerator::EncodeRuleName(
- this->GetGeneratorTarget()->GetName());
+ "_DEVICE_LINKER__" +
+ cmGlobalNinjaGenerator::EncodeRuleName(
+ this->GetGeneratorTarget()->GetName());
}
struct cmNinjaRemoveNoOpCommands
@@ -172,13 +167,8 @@ struct cmNinjaRemoveNoOpCommands
void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile)
{
- cmStateEnums::TargetType targetType = this->GetGeneratorTarget()->GetType();
- std::string ruleName = this->LanguageLinkerDeviceRule();
- // Select whether to use a response file for objects.
- std::string rspfile;
- std::string rspcontent;
-
- if (!this->GetGlobalGenerator()->HasRule(ruleName)) {
+ cmNinjaRule rule(this->LanguageLinkerDeviceRule());
+ if (!this->GetGlobalGenerator()->HasRule(rule.Name)) {
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
vars.CMTargetType =
@@ -186,32 +176,24 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile)
vars.Language = "CUDA";
- std::string responseFlag;
- if (!useResponseFile) {
+ // build response file name
+ std::string responseFlag = this->GetMakefile()->GetSafeDefinition(
+ "CMAKE_CUDA_RESPONSE_FILE_LINK_FLAG");
+
+ if (!useResponseFile || responseFlag.empty()) {
vars.Objects = "$in";
- vars.LinkLibraries = "$LINK_LIBRARIES";
+ vars.LinkLibraries = "$LINK_PATH $LINK_LIBRARIES";
} else {
- std::string cmakeVarLang = "CMAKE_";
- cmakeVarLang += this->TargetLinkLanguage;
-
- // build response file name
- std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG";
- const char* flag = GetMakefile()->GetDefinition(cmakeLinkVar);
- if (flag) {
- responseFlag = flag;
- } else {
- responseFlag = "@";
- }
- rspfile = "$RSP_FILE";
- responseFlag += rspfile;
+ rule.RspFile = "$RSP_FILE";
+ responseFlag += rule.RspFile;
// build response file content
if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
- rspcontent = "$in";
+ rule.RspContent = "$in";
} else {
- rspcontent = "$in_newline";
+ rule.RspContent = "$in_newline";
}
- rspcontent += " $LINK_LIBRARIES";
+ rule.RspContent += " $LINK_LIBRARIES";
vars.Objects = responseFlag.c_str();
vars.LinkLibraries = "";
}
@@ -230,7 +212,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile)
vars.Manifests = "$MANIFESTS";
std::string langFlags;
- if (targetType != cmStateEnums::EXECUTABLE) {
+ if (this->GetGeneratorTarget()->GetType() != cmStateEnums::EXECUTABLE) {
langFlags += "$LANGUAGE_COMPILE_FLAGS $ARCH_FLAGS";
vars.LanguageCompileFlags = langFlags.c_str();
}
@@ -239,88 +221,94 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile)
const char* val = this->GetLocalGenerator()->GetRuleLauncher(
this->GetGeneratorTarget(), "RULE_LAUNCH_LINK");
if (val && *val) {
- launcher = val;
- launcher += " ";
+ launcher = cmStrCat(val, ' ');
}
- CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+ std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->GetLocalGenerator()->CreateRulePlaceholderExpander());
// Rule for linking library/executable.
std::vector<std::string> linkCmds = this->ComputeDeviceLinkCmd();
- for (std::vector<std::string>::iterator i = linkCmds.begin();
- i != linkCmds.end(); ++i) {
- *i = launcher + *i;
+ for (std::string& linkCmd : linkCmds) {
+ linkCmd = cmStrCat(launcher, linkCmd);
rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
- *i, vars);
+ linkCmd, vars);
}
// If there is no ranlib the command will be ":". Skip it.
cmEraseIf(linkCmds, cmNinjaRemoveNoOpCommands());
- std::string linkCmd =
- this->GetLocalGenerator()->BuildCommandLine(linkCmds);
+ rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds);
// Write the linker rule with response file if needed.
- std::ostringstream comment;
- comment << "Rule for linking " << this->TargetLinkLanguage << " "
- << this->GetVisibleTypeName() << ".";
- std::ostringstream description;
- description << "Linking " << this->TargetLinkLanguage << " "
- << this->GetVisibleTypeName() << " $TARGET_FILE";
- this->GetGlobalGenerator()->AddRule(ruleName, linkCmd, description.str(),
- comment.str(),
- /*depfile*/ "",
- /*deptype*/ "", rspfile, rspcontent,
- /*restat*/ "$RESTAT",
- /*generator*/ false);
+ rule.Comment = cmStrCat("Rule for linking ", this->TargetLinkLanguage, ' ',
+ this->GetVisibleTypeName(), '.');
+ rule.Description = cmStrCat("Linking ", this->TargetLinkLanguage, ' ',
+ this->GetVisibleTypeName(), " $TARGET_FILE");
+ rule.Restat = "$RESTAT";
+
+ this->GetGlobalGenerator()->AddRule(rule);
}
}
void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
{
cmStateEnums::TargetType targetType = this->GetGeneratorTarget()->GetType();
- std::string ruleName = this->LanguageLinkerRule();
-
- // Select whether to use a response file for objects.
- std::string rspfile;
- std::string rspcontent;
- if (!this->GetGlobalGenerator()->HasRule(ruleName)) {
+ std::string linkRuleName = this->LanguageLinkerRule();
+ if (!this->GetGlobalGenerator()->HasRule(linkRuleName)) {
+ cmNinjaRule rule(std::move(linkRuleName));
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
- vars.CMTargetType =
- cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType());
+ vars.CMTargetType = cmState::GetTargetTypeName(targetType);
vars.Language = this->TargetLinkLanguage.c_str();
+ if (this->TargetLinkLanguage == "Swift") {
+ vars.SwiftLibraryName = "$SWIFT_LIBRARY_NAME";
+ vars.SwiftModule = "$SWIFT_MODULE";
+ vars.SwiftModuleName = "$SWIFT_MODULE_NAME";
+ vars.SwiftOutputFileMap = "$SWIFT_OUTPUT_FILE_MAP";
+ vars.SwiftSources = "$SWIFT_SOURCES";
+
+ vars.Defines = "$DEFINES";
+ vars.Flags = "$FLAGS";
+ vars.Includes = "$INCLUDES";
+ }
+
std::string responseFlag;
- if (!useResponseFile) {
+
+ std::string cmakeVarLang = cmStrCat("CMAKE_", this->TargetLinkLanguage);
+
+ // build response file name
+ std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG";
+ const char* flag = GetMakefile()->GetDefinition(cmakeLinkVar);
+
+ if (flag) {
+ responseFlag = flag;
+ } else if (this->TargetLinkLanguage != "CUDA") {
+ responseFlag = "@";
+ }
+
+ if (!useResponseFile || responseFlag.empty()) {
vars.Objects = "$in";
vars.LinkLibraries = "$LINK_PATH $LINK_LIBRARIES";
} else {
- std::string cmakeVarLang = "CMAKE_";
- cmakeVarLang += this->TargetLinkLanguage;
-
- // build response file name
- std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG";
- const char* flag = GetMakefile()->GetDefinition(cmakeLinkVar);
- if (flag) {
- responseFlag = flag;
- } else {
- responseFlag = "@";
- }
- rspfile = "$RSP_FILE";
- responseFlag += rspfile;
+ rule.RspFile = "$RSP_FILE";
+ responseFlag += rule.RspFile;
// build response file content
if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
- rspcontent = "$in";
+ rule.RspContent = "$in";
} else {
- rspcontent = "$in_newline";
+ rule.RspContent = "$in_newline";
+ }
+ rule.RspContent += " $LINK_PATH $LINK_LIBRARIES";
+ if (this->TargetLinkLanguage == "Swift") {
+ vars.SwiftSources = responseFlag.c_str();
+ } else {
+ vars.Objects = responseFlag.c_str();
}
- rspcontent += " $LINK_PATH $LINK_LIBRARIES";
- vars.Objects = responseFlag.c_str();
vars.LinkLibraries = "";
}
@@ -364,76 +352,64 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
const char* val = this->GetLocalGenerator()->GetRuleLauncher(
this->GetGeneratorTarget(), "RULE_LAUNCH_LINK");
if (val && *val) {
- launcher = val;
- launcher += " ";
+ launcher = cmStrCat(val, ' ');
}
- CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+ std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->GetLocalGenerator()->CreateRulePlaceholderExpander());
// Rule for linking library/executable.
std::vector<std::string> linkCmds = this->ComputeLinkCmd();
- for (std::vector<std::string>::iterator i = linkCmds.begin();
- i != linkCmds.end(); ++i) {
- *i = launcher + *i;
+ for (std::string& linkCmd : linkCmds) {
+ linkCmd = cmStrCat(launcher, linkCmd);
rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
- *i, vars);
+ linkCmd, vars);
}
// If there is no ranlib the command will be ":". Skip it.
cmEraseIf(linkCmds, cmNinjaRemoveNoOpCommands());
linkCmds.insert(linkCmds.begin(), "$PRE_LINK");
- linkCmds.push_back("$POST_BUILD");
- std::string linkCmd =
- this->GetLocalGenerator()->BuildCommandLine(linkCmds);
+ linkCmds.emplace_back("$POST_BUILD");
+ rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds);
// Write the linker rule with response file if needed.
- std::ostringstream comment;
- comment << "Rule for linking " << this->TargetLinkLanguage << " "
- << this->GetVisibleTypeName() << ".";
- std::ostringstream description;
- description << "Linking " << this->TargetLinkLanguage << " "
- << this->GetVisibleTypeName() << " $TARGET_FILE";
- this->GetGlobalGenerator()->AddRule(ruleName, linkCmd, description.str(),
- comment.str(),
- /*depfile*/ "",
- /*deptype*/ "", rspfile, rspcontent,
- /*restat*/ "$RESTAT",
- /*generator*/ false);
+ rule.Comment = cmStrCat("Rule for linking ", this->TargetLinkLanguage, ' ',
+ this->GetVisibleTypeName(), '.');
+ rule.Description = cmStrCat("Linking ", this->TargetLinkLanguage, ' ',
+ this->GetVisibleTypeName(), " $TARGET_FILE");
+ rule.Restat = "$RESTAT";
+ this->GetGlobalGenerator()->AddRule(rule);
}
- if (this->TargetNameOut != this->TargetNameReal &&
+ if (this->TargetNames.Output != this->TargetNames.Real &&
!this->GetGeneratorTarget()->IsFrameworkOnApple()) {
std::string cmakeCommand =
this->GetLocalGenerator()->ConvertToOutputFormat(
cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
if (targetType == cmStateEnums::EXECUTABLE) {
- this->GetGlobalGenerator()->AddRule(
- "CMAKE_SYMLINK_EXECUTABLE",
- cmakeCommand + " -E cmake_symlink_executable"
- " $in $out && $POST_BUILD",
- "Creating executable symlink $out", "Rule for creating "
- "executable symlink.",
- /*depfile*/ "",
- /*deptype*/ "",
- /*rspfile*/ "",
- /*rspcontent*/ "",
- /*restat*/ "",
- /*generator*/ false);
+ cmNinjaRule rule("CMAKE_SYMLINK_EXECUTABLE");
+ {
+ std::vector<std::string> cmd;
+ cmd.push_back(cmakeCommand + " -E cmake_symlink_executable $in $out");
+ cmd.emplace_back("$POST_BUILD");
+ rule.Command = this->GetLocalGenerator()->BuildCommandLine(cmd);
+ }
+ rule.Description = "Creating executable symlink $out";
+ rule.Comment = "Rule for creating executable symlink.";
+ this->GetGlobalGenerator()->AddRule(rule);
} else {
- this->GetGlobalGenerator()->AddRule(
- "CMAKE_SYMLINK_LIBRARY",
- cmakeCommand + " -E cmake_symlink_library"
- " $in $SONAME $out && $POST_BUILD",
- "Creating library symlink $out", "Rule for creating "
- "library symlink.",
- /*depfile*/ "",
- /*deptype*/ "",
- /*rspfile*/ "",
- /*rspcontent*/ "",
- /*restat*/ "",
- /*generator*/ false);
+ cmNinjaRule rule("CMAKE_SYMLINK_LIBRARY");
+ {
+ std::vector<std::string> cmd;
+ cmd.push_back(cmakeCommand +
+ " -E cmake_symlink_library $in $SONAME $out");
+ cmd.emplace_back("$POST_BUILD");
+ rule.Command = this->GetLocalGenerator()->BuildCommandLine(cmd);
+ }
+ rule.Description = "Creating library symlink $out";
+ rule.Comment = "Rule for creating library symlink.";
+ this->GetGlobalGenerator()->AddRule(rule);
}
}
}
@@ -452,12 +428,12 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeDeviceLinkCmd()
case cmStateEnums::MODULE_LIBRARY: {
const std::string cudaLinkCmd(
this->GetMakefile()->GetDefinition("CMAKE_CUDA_DEVICE_LINK_LIBRARY"));
- cmSystemTools::ExpandListArgument(cudaLinkCmd, linkCmds);
+ cmExpandList(cudaLinkCmd, linkCmds);
} break;
case cmStateEnums::EXECUTABLE: {
const std::string cudaLinkCmd(this->GetMakefile()->GetDefinition(
"CMAKE_CUDA_DEVICE_LINK_EXECUTABLE"));
- cmSystemTools::ExpandListArgument(cudaLinkCmd, linkCmds);
+ cmExpandList(cudaLinkCmd, linkCmds);
} break;
default:
break;
@@ -477,21 +453,28 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
this->TargetLinkLanguage, this->GetConfigName());
const char* linkCmd = mf->GetDefinition(linkCmdVar);
if (linkCmd) {
- cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
+ std::string linkCmdStr = linkCmd;
+ if (this->GetGeneratorTarget()->HasImplibGNUtoMS(this->ConfigName)) {
+ std::string ruleVar = cmStrCat(
+ "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName),
+ "_GNUtoMS_RULE");
+ if (const char* rule = this->Makefile->GetDefinition(ruleVar)) {
+ linkCmdStr += rule;
+ }
+ }
+ cmExpandList(linkCmdStr, linkCmds);
if (this->GetGeneratorTarget()->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
- std::string cmakeCommand =
+ std::string cmakeCommand = cmStrCat(
this->GetLocalGenerator()->ConvertToOutputFormat(
- cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
- cmakeCommand += " -E __run_iwyu --lwyu=";
+ cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
+ " -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;
}
@@ -507,27 +490,39 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
}
// TODO: Use ARCHIVE_APPEND for archives over a certain size.
{
- std::string linkCmdVar = "CMAKE_";
- linkCmdVar += this->TargetLinkLanguage;
- linkCmdVar += "_ARCHIVE_CREATE";
+ std::string linkCmdVar =
+ cmStrCat("CMAKE_", this->TargetLinkLanguage, "_ARCHIVE_CREATE");
linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
linkCmdVar, this->TargetLinkLanguage, this->GetConfigName());
- const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar);
- cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
+ std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar);
+ cmExpandList(linkCmd, linkCmds);
}
{
- std::string linkCmdVar = "CMAKE_";
- linkCmdVar += this->TargetLinkLanguage;
- linkCmdVar += "_ARCHIVE_FINISH";
+ std::string linkCmdVar =
+ cmStrCat("CMAKE_", this->TargetLinkLanguage, "_ARCHIVE_FINISH");
linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
linkCmdVar, this->TargetLinkLanguage, this->GetConfigName());
- const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar);
- cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
+ std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar);
+ cmExpandList(linkCmd, linkCmds);
}
+#ifdef __APPLE__
+ // On macOS ranlib truncates the fractional part of the static archive
+ // file modification time. If the archive and at least one contained
+ // object file were created within the same second this will make look
+ // the archive older than the object file. On subsequent ninja runs this
+ // leads to re-achiving and updating dependent targets.
+ // As a work-around we touch the archive after ranlib (see #19222).
+ {
+ std::string cmakeCommand =
+ this->GetLocalGenerator()->ConvertToOutputFormat(
+ cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
+ linkCmds.push_back(cmakeCommand + " -E touch $TARGET_FILE");
+ }
+#endif
return linkCmds;
}
case cmStateEnums::SHARED_LIBRARY:
@@ -542,33 +537,16 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
{
- cmGeneratorTarget& genTarget = *this->GetGeneratorTarget();
-
- // determine if we need to do any device linking for this target
- const std::string cuda_lang("CUDA");
- cmGeneratorTarget::LinkClosure const* closure =
- genTarget.GetLinkClosure(this->GetConfigName());
-
- const bool hasCUDA =
- (std::find(closure->Languages.begin(), closure->Languages.end(),
- cuda_lang) != closure->Languages.end());
-
- bool shouldHaveDeviceLinking = false;
- switch (genTarget.GetType()) {
- case cmStateEnums::SHARED_LIBRARY:
- case cmStateEnums::MODULE_LIBRARY:
- case cmStateEnums::EXECUTABLE:
- shouldHaveDeviceLinking = true;
- break;
- case cmStateEnums::STATIC_LIBRARY:
- shouldHaveDeviceLinking =
- genTarget.GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
- break;
- default:
- break;
+ cmGlobalNinjaGenerator* globalGen = this->GetGlobalGenerator();
+ if (!globalGen->GetLanguageEnabled("CUDA")) {
+ return;
}
- if (!(shouldHaveDeviceLinking && hasCUDA)) {
+ cmGeneratorTarget* genTarget = this->GetGeneratorTarget();
+
+ bool requiresDeviceLinking = requireDeviceLinking(
+ *this->GeneratorTarget, *this->GetLocalGenerator(), this->ConfigName);
+ if (!requiresDeviceLinking) {
return;
}
@@ -577,44 +555,42 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
// First and very important step is to make sure while inside this
// step our link language is set to CUDA
std::string cudaLinkLanguage = "CUDA";
- std::string const objExt =
+ std::string const& objExt =
this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION");
std::string const cfgName = this->GetConfigName();
std::string const targetOutputReal = ConvertToNinjaPath(
- genTarget.ObjectDirectory + "cmake_device_link" + objExt);
+ genTarget->ObjectDirectory + "cmake_device_link" + objExt);
std::string const targetOutputImplib = ConvertToNinjaPath(
- genTarget.GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact));
+ genTarget->GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact));
this->DeviceLinkObject = targetOutputReal;
// Write comments.
cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
- const cmStateEnums::TargetType targetType = genTarget.GetType();
+ const cmStateEnums::TargetType targetType = genTarget->GetType();
this->GetBuildFileStream() << "# Device Link build statements for "
<< cmState::GetTargetTypeName(targetType)
<< " target " << this->GetTargetName() << "\n\n";
// Compute the comment.
- std::ostringstream comment;
- comment << "Link the " << this->GetVisibleTypeName() << " "
- << targetOutputReal;
+ cmNinjaBuild build(this->LanguageLinkerDeviceRule());
+ build.Comment =
+ cmStrCat("Link the ", this->GetVisibleTypeName(), ' ', targetOutputReal);
- cmNinjaDeps emptyDeps;
- cmNinjaVars vars;
+ cmNinjaVars& vars = build.Variables;
// Compute outputs.
- cmNinjaDeps outputs;
- outputs.push_back(targetOutputReal);
+ build.Outputs.push_back(targetOutputReal);
// Compute specific libraries to link with.
- cmNinjaDeps explicitDeps = this->GetObjects();
- cmNinjaDeps implicitDeps = this->ComputeLinkDeps();
+ build.ExplicitDeps = this->GetObjects();
+ build.ImplicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage);
std::string frameworkPath;
std::string linkPath;
- std::string createRule = genTarget.GetCreateRuleVariable(
+ std::string createRule = genTarget->GetCreateRuleVariable(
this->TargetLinkLanguage, this->GetConfigName());
const bool useWatcomQuote =
this->GetMakefile()->IsOn(createRule + "_USE_WATCOM_QUOTE");
@@ -623,18 +599,18 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
vars["TARGET_FILE"] =
localGen.ConvertToOutputFormat(targetOutputReal, cmOutputConverter::SHELL);
- CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+ std::unique_ptr<cmLinkLineComputer> linkLineComputer(
new cmNinjaLinkLineDeviceComputer(
this->GetLocalGenerator(),
this->GetLocalGenerator()->GetStateSnapshot().GetDirectory(),
- this->GetGlobalGenerator()));
+ globalGen));
linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
localGen.GetTargetFlags(
linkLineComputer.get(), this->GetConfigName(), vars["LINK_LIBRARIES"],
- vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, &genTarget);
+ vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, genTarget);
- this->addPoolNinjaVariable("JOB_POOL_LINK", &genTarget, vars);
+ this->addPoolNinjaVariable("JOB_POOL_LINK", genTarget, vars);
vars["LINK_FLAGS"] =
cmGlobalNinjaGenerator::EncodeLiteral(vars["LINK_FLAGS"]);
@@ -648,21 +624,21 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
// code between the Makefile executable and library generators.
if (targetType == cmStateEnums::EXECUTABLE) {
std::string t = vars["FLAGS"];
- localGen.AddArchitectureFlags(t, &genTarget, cudaLinkLanguage, cfgName);
+ localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, cfgName);
vars["FLAGS"] = t;
} else {
std::string t = vars["ARCH_FLAGS"];
- localGen.AddArchitectureFlags(t, &genTarget, cudaLinkLanguage, cfgName);
+ localGen.AddArchitectureFlags(t, genTarget, cudaLinkLanguage, cfgName);
vars["ARCH_FLAGS"] = t;
- t = "";
- localGen.AddLanguageFlagsForLinking(t, &genTarget, cudaLinkLanguage,
+ t.clear();
+ localGen.AddLanguageFlagsForLinking(t, genTarget, cudaLinkLanguage,
cfgName);
vars["LANGUAGE_COMPILE_FLAGS"] = t;
}
- if (this->GetGeneratorTarget()->HasSOName(cfgName)) {
+ if (genTarget->HasSOName(cfgName)) {
vars["SONAME_FLAG"] =
this->GetMakefile()->GetSONameFlag(this->TargetLinkLanguage);
- vars["SONAME"] = this->TargetNameSO;
+ vars["SONAME"] = this->TargetNames.SharedObject;
if (targetType == cmStateEnums::SHARED_LIBRARY) {
std::string install_dir =
this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(cfgName);
@@ -673,16 +649,11 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
}
}
- cmNinjaDeps byproducts;
-
- if (!this->TargetNameImport.empty()) {
+ if (!this->TargetNames.ImportLibrary.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();
@@ -692,7 +663,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
this->SetMsvcTargetPdbVariable(vars);
- if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
+ if (globalGen->IsGCCOnWindows()) {
// ar.exe can't handle backslashes in rsp files (implicitly used by gcc)
std::string& linkLibraries = vars["LINK_LIBRARIES"];
std::replace(linkLibraries.begin(), linkLibraries.end(), '\\', '/');
@@ -700,143 +671,182 @@ 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 (std::vector<cmCustomCommand>::const_iterator ci =
- cmdLists[i]->begin();
- ci != cmdLists[i]->end(); ++ci) {
- cmCustomCommandGenerator ccg(*ci, 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
// do not check if the user has explicitly forced a response file.
int const commandLineLengthLimit =
static_cast<int>(cmSystemTools::CalculateCommandLineLengthLimit()) -
- globalGen.GetRuleCmdLength(this->LanguageLinkerDeviceRule());
+ globalGen->GetRuleCmdLength(this->LanguageLinkerDeviceRule());
- const std::string rspfile =
- std::string(cmake::GetCMakeFilesDirectoryPostSlash()) +
- genTarget.GetName() + ".rsp";
+ build.RspFile = this->ConvertToNinjaPath(std::string("CMakeFiles/") +
+ genTarget->GetName() + ".rsp");
// Gather order-only dependencies.
- cmNinjaDeps orderOnlyDeps;
this->GetLocalGenerator()->AppendTargetDepends(this->GetGeneratorTarget(),
- orderOnlyDeps);
+ build.OrderOnlyDeps);
// Write the build statement for this target.
bool usedResponseFile = false;
- globalGen.WriteBuild(this->GetBuildFileStream(), comment.str(),
- this->LanguageLinkerDeviceRule(), outputs,
- /*implicitOuts=*/cmNinjaDeps(), explicitDeps,
- implicitDeps, orderOnlyDeps, vars, rspfile,
- commandLineLengthLimit, &usedResponseFile);
+ globalGen->WriteBuild(this->GetBuildFileStream(), build,
+ commandLineLengthLimit, &usedResponseFile);
this->WriteDeviceLinkRule(usedResponseFile);
}
void cmNinjaNormalTargetGenerator::WriteLinkStatement()
{
- cmGeneratorTarget& gt = *this->GetGeneratorTarget();
+ cmMakefile* mf = this->GetMakefile();
+ cmGlobalNinjaGenerator* globalGen = this->GetGlobalGenerator();
+ cmGeneratorTarget* gt = this->GetGeneratorTarget();
+
const std::string cfgName = this->GetConfigName();
- std::string targetOutput = ConvertToNinjaPath(gt.GetFullPath(cfgName));
+ std::string targetOutput = ConvertToNinjaPath(gt->GetFullPath(cfgName));
std::string targetOutputReal = ConvertToNinjaPath(
- gt.GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact,
- /*realname=*/true));
+ gt->GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact,
+ /*realname=*/true));
std::string targetOutputImplib = ConvertToNinjaPath(
- gt.GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact));
+ gt->GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact));
- if (gt.IsAppBundleOnApple()) {
+ if (gt->IsAppBundleOnApple()) {
// Create the app bundle
- std::string outpath = gt.GetDirectory(cfgName);
- this->OSXBundleGenerator->CreateAppBundle(this->TargetNameOut, outpath);
+ std::string outpath = gt->GetDirectory(cfgName);
+ this->OSXBundleGenerator->CreateAppBundle(this->TargetNames.Output,
+ outpath);
// Calculate the output path
- targetOutput = outpath;
- targetOutput += "/";
- targetOutput += this->TargetNameOut;
+ targetOutput = cmStrCat(outpath, '/', this->TargetNames.Output);
targetOutput = this->ConvertToNinjaPath(targetOutput);
- targetOutputReal = outpath;
- targetOutputReal += "/";
- targetOutputReal += this->TargetNameReal;
+ targetOutputReal = cmStrCat(outpath, '/', this->TargetNames.Real);
targetOutputReal = this->ConvertToNinjaPath(targetOutputReal);
- } else if (gt.IsFrameworkOnApple()) {
+ } else if (gt->IsFrameworkOnApple()) {
// Create the library framework.
- this->OSXBundleGenerator->CreateFramework(this->TargetNameOut,
- gt.GetDirectory(cfgName));
- } else if (gt.IsCFBundleOnApple()) {
+ this->OSXBundleGenerator->CreateFramework(this->TargetNames.Output,
+ gt->GetDirectory(cfgName));
+ } else if (gt->IsCFBundleOnApple()) {
// Create the core foundation bundle.
- this->OSXBundleGenerator->CreateCFBundle(this->TargetNameOut,
- gt.GetDirectory(cfgName));
+ this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output,
+ gt->GetDirectory(cfgName));
}
// Write comments.
cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
- const cmStateEnums::TargetType targetType = gt.GetType();
- this->GetBuildFileStream() << "# Link build statements for "
- << cmState::GetTargetTypeName(targetType)
- << " target " << this->GetTargetName() << "\n\n";
+ const cmStateEnums::TargetType targetType = gt->GetType();
+ this->GetBuildFileStream()
+ << "# Link build statements for " << cmState::GetTargetTypeName(targetType)
+ << " target " << this->GetTargetName() << "\n\n";
- cmNinjaDeps emptyDeps;
- cmNinjaVars vars;
+ cmNinjaBuild linkBuild(this->LanguageLinkerRule());
+ cmNinjaVars& vars = linkBuild.Variables;
// Compute the comment.
- std::ostringstream comment;
- comment << "Link the " << this->GetVisibleTypeName() << " "
- << targetOutputReal;
+ linkBuild.Comment =
+ cmStrCat("Link the ", this->GetVisibleTypeName(), ' ', targetOutputReal);
// Compute outputs.
- cmNinjaDeps outputs;
- outputs.push_back(targetOutputReal);
+ linkBuild.Outputs.push_back(targetOutputReal);
+
+ if (this->TargetLinkLanguage == "Swift") {
+ vars["SWIFT_LIBRARY_NAME"] = [this]() -> std::string {
+ cmGeneratorTarget::Names targetNames =
+ this->GetGeneratorTarget()->GetLibraryNames(this->GetConfigName());
+ return targetNames.Base;
+ }();
+
+ vars["SWIFT_MODULE_NAME"] = [gt]() -> std::string {
+ if (const char* name = gt->GetProperty("Swift_MODULE_NAME")) {
+ return name;
+ }
+ return gt->GetName();
+ }();
+
+ vars["SWIFT_MODULE"] = [this](const std::string& module) -> std::string {
+ std::string directory =
+ this->GetLocalGenerator()->GetCurrentBinaryDirectory();
+ if (const char* prop = this->GetGeneratorTarget()->GetProperty(
+ "Swift_MODULE_DIRECTORY")) {
+ directory = prop;
+ }
+
+ std::string name = module + ".swiftmodule";
+ if (const char* prop =
+ this->GetGeneratorTarget()->GetProperty("Swift_MODULE")) {
+ name = prop;
+ }
+
+ return this->GetLocalGenerator()->ConvertToOutputFormat(
+ this->ConvertToNinjaPath(directory + "/" + name),
+ cmOutputConverter::SHELL);
+ }(vars["SWIFT_MODULE_NAME"]);
+
+ vars["SWIFT_OUTPUT_FILE_MAP"] =
+ this->GetLocalGenerator()->ConvertToOutputFormat(
+ this->ConvertToNinjaPath(gt->GetSupportDirectory() +
+ "/output-file-map.json"),
+ cmOutputConverter::SHELL);
+
+ vars["SWIFT_SOURCES"] = [this]() -> std::string {
+ std::vector<cmSourceFile const*> sources;
+ std::stringstream oss;
+
+ this->GetGeneratorTarget()->GetObjectSources(sources,
+ this->GetConfigName());
+ cmLocalGenerator const* LocalGen = this->GetLocalGenerator();
+ for (const auto& source : sources) {
+ oss << " "
+ << LocalGen->ConvertToOutputFormat(
+ this->ConvertToNinjaPath(this->GetSourceFilePath(source)),
+ cmOutputConverter::SHELL);
+ }
+ return oss.str();
+ }();
+
+ // Since we do not perform object builds, compute the
+ // defines/flags/includes here so that they can be passed along
+ // appropriately.
+ vars["DEFINES"] = this->GetDefines("Swift");
+ vars["FLAGS"] = this->GetFlags("Swift");
+ vars["INCLUDES"] = this->GetIncludes("Swift");
+ }
// Compute specific libraries to link with.
- cmNinjaDeps explicitDeps = this->GetObjects();
- cmNinjaDeps implicitDeps = this->ComputeLinkDeps();
+ if (this->TargetLinkLanguage == "Swift") {
+ std::vector<cmSourceFile const*> sources;
+ gt->GetObjectSources(sources, this->GetConfigName());
+ for (const auto& source : sources) {
+ linkBuild.Outputs.push_back(
+ this->ConvertToNinjaPath(this->GetObjectFilePath(source)));
+ linkBuild.ExplicitDeps.push_back(
+ this->ConvertToNinjaPath(this->GetSourceFilePath(source)));
+ }
- if (!this->DeviceLinkObject.empty()) {
- explicitDeps.push_back(this->DeviceLinkObject);
+ linkBuild.Outputs.push_back(vars["SWIFT_MODULE"]);
+ } else {
+ linkBuild.ExplicitDeps = this->GetObjects();
}
+ linkBuild.ImplicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage);
- cmMakefile* mf = this->GetMakefile();
+ if (!this->DeviceLinkObject.empty()) {
+ linkBuild.ExplicitDeps.push_back(this->DeviceLinkObject);
+ }
std::string frameworkPath;
std::string linkPath;
- cmGeneratorTarget& genTarget = *this->GetGeneratorTarget();
- std::string createRule = genTarget.GetCreateRuleVariable(
- this->TargetLinkLanguage, this->GetConfigName());
+ std::string createRule =
+ gt->GetCreateRuleVariable(this->TargetLinkLanguage, this->GetConfigName());
bool useWatcomQuote = mf->IsOn(createRule + "_USE_WATCOM_QUOTE");
cmLocalNinjaGenerator& localGen = *this->GetLocalGenerator();
vars["TARGET_FILE"] =
localGen.ConvertToOutputFormat(targetOutputReal, cmOutputConverter::SHELL);
- CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
- this->GetGlobalGenerator()->CreateLinkLineComputer(
+ std::unique_ptr<cmLinkLineComputer> linkLineComputer(
+ globalGen->CreateLinkLineComputer(
this->GetLocalGenerator(),
this->GetLocalGenerator()->GetStateSnapshot().GetDirectory()));
linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
- localGen.GetTargetFlags(
- linkLineComputer.get(), this->GetConfigName(), vars["LINK_LIBRARIES"],
- vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, &genTarget);
+ localGen.GetTargetFlags(linkLineComputer.get(), this->GetConfigName(),
+ vars["LINK_LIBRARIES"], vars["FLAGS"],
+ vars["LINK_FLAGS"], frameworkPath, linkPath, gt);
// Add OS X version flags, if any.
if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
@@ -847,7 +857,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
"CURRENT", false);
}
- this->addPoolNinjaVariable("JOB_POOL_LINK", &gt, vars);
+ this->addPoolNinjaVariable("JOB_POOL_LINK", gt, vars);
this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"]);
vars["LINK_FLAGS"] =
@@ -857,7 +867,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
vars["LINK_PATH"] = frameworkPath + linkPath;
std::string lwyuFlags;
- if (genTarget.GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
+ if (gt->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
lwyuFlags = " -Wl,--no-as-needed";
}
@@ -866,25 +876,23 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
// code between the Makefile executable and library generators.
if (targetType == cmStateEnums::EXECUTABLE) {
std::string t = vars["FLAGS"];
- localGen.AddArchitectureFlags(t, &genTarget, TargetLinkLanguage, cfgName);
+ localGen.AddArchitectureFlags(t, gt, TargetLinkLanguage, cfgName);
t += lwyuFlags;
vars["FLAGS"] = t;
} else {
std::string t = vars["ARCH_FLAGS"];
- localGen.AddArchitectureFlags(t, &genTarget, TargetLinkLanguage, cfgName);
+ localGen.AddArchitectureFlags(t, gt, TargetLinkLanguage, cfgName);
vars["ARCH_FLAGS"] = t;
- t = "";
+ t.clear();
t += lwyuFlags;
- localGen.AddLanguageFlagsForLinking(t, &genTarget, TargetLinkLanguage,
- cfgName);
+ localGen.AddLanguageFlagsForLinking(t, gt, TargetLinkLanguage, cfgName);
vars["LANGUAGE_COMPILE_FLAGS"] = t;
}
- if (this->GetGeneratorTarget()->HasSOName(cfgName)) {
+ if (gt->HasSOName(cfgName)) {
vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage);
- vars["SONAME"] = this->TargetNameSO;
+ vars["SONAME"] = this->TargetNames.SharedObject;
if (targetType == cmStateEnums::SHARED_LIBRARY) {
- std::string install_dir =
- this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(cfgName);
+ std::string install_dir = gt->GetInstallNameDirForBuildTree(cfgName);
if (!install_dir.empty()) {
vars["INSTALLNAME_DIR"] = localGen.ConvertToOutputFormat(
install_dir, cmOutputConverter::SHELL);
@@ -894,12 +902,12 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
cmNinjaDeps byproducts;
- if (!this->TargetNameImport.empty()) {
+ if (!this->TargetNames.ImportLibrary.empty()) {
const std::string impLibPath = localGen.ConvertToOutputFormat(
targetOutputImplib, cmOutputConverter::SHELL);
vars["TARGET_IMPLIB"] = impLibPath;
EnsureParentDirectoryExists(impLibPath);
- if (genTarget.HasImportLibrary()) {
+ if (gt->HasImportLibrary(cfgName)) {
byproducts.push_back(targetOutputImplib);
}
}
@@ -910,7 +918,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
std::string prefix;
std::string base;
std::string suffix;
- this->GetGeneratorTarget()->GetFullNameComponents(prefix, base, suffix);
+ gt->GetFullNameComponents(prefix, base, suffix);
std::string dbg_suffix = ".dbg";
// TODO: Where to document?
if (mf->GetDefinition("CMAKE_DEBUG_SYMBOL_SUFFIX")) {
@@ -919,12 +927,12 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
vars["TARGET_PDB"] = base + suffix + dbg_suffix;
}
- const std::string objPath = GetGeneratorTarget()->GetSupportDirectory();
+ const std::string objPath = gt->GetSupportDirectory();
vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat(
this->ConvertToNinjaPath(objPath), cmOutputConverter::SHELL);
EnsureDirectoryExists(objPath);
- if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
+ if (globalGen->IsGCCOnWindows()) {
// ar.exe can't handle backslashes in rsp files (implicitly used by gcc)
std::string& linkLibraries = vars["LINK_LIBRARIES"];
std::replace(linkLibraries.begin(), linkLibraries.end(), '\\', '/');
@@ -933,20 +941,19 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
}
const std::vector<cmCustomCommand>* cmdLists[3] = {
- &gt.GetPreBuildCommands(), &gt.GetPreLinkCommands(),
- &gt.GetPostBuildCommands()
+ &gt->GetPreBuildCommands(), &gt->GetPreLinkCommands(),
+ &gt->GetPostBuildCommands()
};
- std::vector<std::string> preLinkCmdLines, postBuildCmdLines;
+ std::vector<std::string> preLinkCmdLines;
+ std::vector<std::string> postBuildCmdLines;
std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines,
&preLinkCmdLines,
&postBuildCmdLines };
for (unsigned i = 0; i != 3; ++i) {
- for (std::vector<cmCustomCommand>::const_iterator ci =
- cmdLists[i]->begin();
- ci != cmdLists[i]->end(); ++ci) {
- cmCustomCommandGenerator ccg(*ci, cfgName, this->GetLocalGenerator());
+ 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(),
@@ -956,142 +963,171 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
// maybe create .def file from list of objects
cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
- gt.GetModuleDefinitionInfo(this->GetConfigName());
+ gt->GetModuleDefinitionInfo(this->GetConfigName());
if (mdi && mdi->DefFileGenerated) {
std::string cmakeCommand =
this->GetLocalGenerator()->ConvertToOutputFormat(
cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
- std::string cmd = cmakeCommand;
- cmd += " -E __create_def ";
- cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
- mdi->DefFile, cmOutputConverter::SHELL);
- cmd += " ";
+ std::string cmd =
+ cmStrCat(cmakeCommand, " -E __create_def ",
+ this->GetLocalGenerator()->ConvertToOutputFormat(
+ mdi->DefFile, cmOutputConverter::SHELL),
+ ' ');
std::string obj_list_file = mdi->DefFile + ".objs";
cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
obj_list_file, cmOutputConverter::SHELL);
- preLinkCmdLines.push_back(cmd);
+
+ const char* nm_executable = GetMakefile()->GetDefinition("CMAKE_NM");
+ if (nm_executable && *nm_executable) {
+ cmd += " --nm=";
+ cmd += this->LocalCommonGenerator->ConvertToOutputFormat(
+ nm_executable, cmOutputConverter::SHELL);
+ }
+ 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());
+ cmGeneratedFileStream fout(obj_list_file);
if (mdi->WindowsExportAllSymbols) {
cmNinjaDeps objs = this->GetObjects();
- for (cmNinjaDeps::iterator i = objs.begin(); i != objs.end(); ++i) {
- if (cmHasLiteralSuffix(*i, ".obj")) {
- fout << *i << "\n";
+ for (std::string const& obj : objs) {
+ if (cmHasLiteralSuffix(obj, ".obj")) {
+ fout << obj << "\n";
}
}
}
- for (std::vector<cmSourceFile const*>::const_iterator i =
- mdi->Sources.begin();
- i != mdi->Sources.end(); ++i) {
- fout << (*i)->GetFullPath() << "\n";
+ for (cmSourceFile const* src : mdi->Sources) {
+ fout << src->GetFullPath() << "\n";
}
}
// If we have any PRE_LINK commands, we need to go back to CMAKE_BINARY_DIR
- // for
- // the link commands.
+ // for the link commands.
if (!preLinkCmdLines.empty()) {
const std::string homeOutDir = localGen.ConvertToOutputFormat(
localGen.GetBinaryDirectory(), cmOutputConverter::SHELL);
preLinkCmdLines.push_back("cd " + homeOutDir);
}
- vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines);
- std::string postBuildCmdLine = localGen.BuildCommandLine(postBuildCmdLines);
+ vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines, "pre-link",
+ this->GeneratorTarget);
+ std::string postBuildCmdLine = localGen.BuildCommandLine(
+ postBuildCmdLines, "post-build", this->GeneratorTarget);
cmNinjaVars symlinkVars;
bool const symlinkNeeded =
- (targetOutput != targetOutputReal && !gt.IsFrameworkOnApple());
+ (targetOutput != targetOutputReal && !gt->IsFrameworkOnApple());
if (!symlinkNeeded) {
vars["POST_BUILD"] = postBuildCmdLine;
} else {
vars["POST_BUILD"] = cmGlobalNinjaGenerator::SHELL_NOOP;
symlinkVars["POST_BUILD"] = postBuildCmdLine;
}
- cmGlobalNinjaGenerator& globalGen = *this->GetGlobalGenerator();
+
+ std::string cmakeVarLang = cmStrCat("CMAKE_", this->TargetLinkLanguage);
+
+ // build response file name
+ std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG";
+
+ const char* flag = GetMakefile()->GetDefinition(cmakeLinkVar);
bool const lang_supports_response =
- !(this->TargetLinkLanguage == "RC" || this->TargetLinkLanguage == "CUDA");
+ !(this->TargetLinkLanguage == "RC" ||
+ (this->TargetLinkLanguage == "CUDA" && !flag));
int commandLineLengthLimit = -1;
if (!lang_supports_response || !this->ForceResponseFile()) {
commandLineLengthLimit =
static_cast<int>(cmSystemTools::CalculateCommandLineLengthLimit()) -
- globalGen.GetRuleCmdLength(this->LanguageLinkerRule());
+ globalGen->GetRuleCmdLength(linkBuild.Rule);
}
- const std::string rspfile =
- std::string(cmake::GetCMakeFilesDirectoryPostSlash()) + gt.GetName() +
- ".rsp";
+ linkBuild.RspFile = this->ConvertToNinjaPath(std::string("CMakeFiles/") +
+ gt->GetName() + ".rsp");
// Gather order-only dependencies.
- cmNinjaDeps orderOnlyDeps;
- this->GetLocalGenerator()->AppendTargetDepends(this->GetGeneratorTarget(),
- orderOnlyDeps);
+ this->GetLocalGenerator()->AppendTargetDepends(gt, linkBuild.OrderOnlyDeps);
+
+ // Add order-only dependencies on versioning symlinks of shared libs we link.
+ if (!this->GeneratorTarget->IsDLLPlatform()) {
+ if (cmComputeLinkInformation* cli =
+ this->GeneratorTarget->GetLinkInformation(this->GetConfigName())) {
+ for (auto const& item : cli->GetItems()) {
+ if (item.Target &&
+ item.Target->GetType() == cmStateEnums::SHARED_LIBRARY &&
+ !item.Target->IsFrameworkOnApple()) {
+ std::string const& lib = this->ConvertToNinjaPath(
+ item.Target->GetFullPath(this->GetConfigName()));
+ if (std::find(linkBuild.ImplicitDeps.begin(),
+ linkBuild.ImplicitDeps.end(),
+ lib) == linkBuild.ImplicitDeps.end()) {
+ linkBuild.OrderOnlyDeps.emplace_back(lib);
+ }
+ }
+ }
+ }
+ }
// Ninja should restat after linking if and only if there are byproducts.
vars["RESTAT"] = byproducts.empty() ? "" : "1";
- for (cmNinjaDeps::const_iterator oi = byproducts.begin(),
- oe = byproducts.end();
- oi != oe; ++oi) {
- this->GetGlobalGenerator()->SeenCustomCommandOutput(*oi);
- outputs.push_back(*oi);
+ for (std::string const& o : byproducts) {
+ globalGen->SeenCustomCommandOutput(o);
+ linkBuild.Outputs.push_back(o);
}
// Write the build statement for this target.
bool usedResponseFile = false;
- globalGen.WriteBuild(this->GetBuildFileStream(), comment.str(),
- this->LanguageLinkerRule(), outputs,
- /*implicitOuts=*/cmNinjaDeps(), explicitDeps,
- implicitDeps, orderOnlyDeps, vars, rspfile,
- commandLineLengthLimit, &usedResponseFile);
+ globalGen->WriteBuild(this->GetBuildFileStream(), linkBuild,
+ commandLineLengthLimit, &usedResponseFile);
this->WriteLinkRule(usedResponseFile);
if (symlinkNeeded) {
if (targetType == cmStateEnums::EXECUTABLE) {
- globalGen.WriteBuild(
- this->GetBuildFileStream(),
- "Create executable symlink " + targetOutput,
- "CMAKE_SYMLINK_EXECUTABLE", cmNinjaDeps(1, targetOutput),
- /*implicitOuts=*/cmNinjaDeps(), cmNinjaDeps(1, targetOutputReal),
- emptyDeps, emptyDeps, symlinkVars);
+ cmNinjaBuild build("CMAKE_SYMLINK_EXECUTABLE");
+ build.Comment = "Create executable symlink " + targetOutput;
+ build.Outputs.push_back(targetOutput);
+ build.ExplicitDeps.push_back(targetOutputReal);
+ build.Variables = std::move(symlinkVars);
+ globalGen->WriteBuild(this->GetBuildFileStream(), build);
} else {
- cmNinjaDeps symlinks;
- std::string const soName =
- this->ConvertToNinjaPath(this->GetTargetFilePath(this->TargetNameSO));
+ cmNinjaBuild build("CMAKE_SYMLINK_LIBRARY");
+ build.Comment = "Create library symlink " + targetOutput;
+
+ std::string const soName = this->ConvertToNinjaPath(
+ this->GetTargetFilePath(this->TargetNames.SharedObject));
// If one link has to be created.
if (targetOutputReal == soName || targetOutput == soName) {
- symlinkVars["SONAME"] = soName;
+ symlinkVars["SONAME"] =
+ this->GetLocalGenerator()->ConvertToOutputFormat(
+ soName, cmOutputConverter::SHELL);
} else {
- symlinkVars["SONAME"] = "";
- symlinks.push_back(soName);
+ symlinkVars["SONAME"].clear();
+ build.Outputs.push_back(soName);
}
- symlinks.push_back(targetOutput);
- globalGen.WriteBuild(
- this->GetBuildFileStream(), "Create library symlink " + targetOutput,
- "CMAKE_SYMLINK_LIBRARY", symlinks,
- /*implicitOuts=*/cmNinjaDeps(), cmNinjaDeps(1, targetOutputReal),
- emptyDeps, emptyDeps, symlinkVars);
+ build.Outputs.push_back(targetOutput);
+ build.ExplicitDeps.push_back(targetOutputReal);
+ build.Variables = std::move(symlinkVars);
+
+ globalGen->WriteBuild(this->GetBuildFileStream(), build);
}
}
// Add aliases for the file name and the target name.
- globalGen.AddTargetAlias(this->TargetNameOut, &gt);
- globalGen.AddTargetAlias(this->GetTargetName(), &gt);
+ globalGen->AddTargetAlias(this->TargetNames.Output, gt);
+ globalGen->AddTargetAlias(this->GetTargetName(), gt);
}
void cmNinjaNormalTargetGenerator::WriteObjectLibStatement()
{
// Write a phony output that depends on all object files.
- cmNinjaDeps outputs;
- this->GetLocalGenerator()->AppendTargetOutputs(this->GetGeneratorTarget(),
- outputs);
- cmNinjaDeps depends = this->GetObjects();
- this->GetGlobalGenerator()->WritePhonyBuild(
- this->GetBuildFileStream(), "Object library " + this->GetTargetName(),
- outputs, depends);
+ {
+ cmNinjaBuild build("phony");
+ build.Comment = "Object library " + this->GetTargetName();
+ this->GetLocalGenerator()->AppendTargetOutputs(this->GetGeneratorTarget(),
+ build.Outputs);
+ build.ExplicitDeps = this->GetObjects();
+ this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build);
+ }
// Add aliases for the target name.
this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h
index 677b1c666..ebc126823 100644
--- a/Source/cmNinjaNormalTargetGenerator.h
+++ b/Source/cmNinjaNormalTargetGenerator.h
@@ -3,22 +3,21 @@
#ifndef cmNinjaNormalTargetGenerator_h
#define cmNinjaNormalTargetGenerator_h
-#include "cmConfigure.h"
-
-#include "cmNinjaTargetGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-class cmGeneratorTarget;
+#include "cmGeneratorTarget.h"
+#include "cmNinjaTargetGenerator.h"
class cmNinjaNormalTargetGenerator : public cmNinjaTargetGenerator
{
public:
cmNinjaNormalTargetGenerator(cmGeneratorTarget* target);
- ~cmNinjaNormalTargetGenerator() CM_OVERRIDE;
+ ~cmNinjaNormalTargetGenerator() override;
- void Generate() CM_OVERRIDE;
+ void Generate() override;
private:
std::string LanguageLinkerRule() const;
@@ -40,11 +39,7 @@ private:
private:
// Target name info.
- std::string TargetNameOut;
- std::string TargetNameSO;
- std::string TargetNameReal;
- std::string TargetNameImport;
- std::string TargetNamePDB;
+ cmGeneratorTarget::Names TargetNames;
std::string TargetLinkLanguage;
std::string DeviceLinkObject;
};
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index d38dbcb09..0aab9127b 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -2,14 +2,17 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmNinjaTargetGenerator.h"
-#include "cm_jsoncpp_value.h"
-#include "cm_jsoncpp_writer.h"
#include <algorithm>
-#include <assert.h>
+#include <cassert>
#include <iterator>
#include <map>
-#include <sstream>
-#include <string.h>
+#include <ostream>
+#include <utility>
+
+#include <cm/memory>
+
+#include "cm_jsoncpp_value.h"
+#include "cm_jsoncpp_writer.h"
#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
@@ -24,15 +27,17 @@
#include "cmNinjaNormalTargetGenerator.h"
#include "cmNinjaUtilityTargetGenerator.h"
#include "cmOutputConverter.h"
+#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cm_auto_ptr.hxx"
#include "cmake.h"
-cmNinjaTargetGenerator* cmNinjaTargetGenerator::New(cmGeneratorTarget* target)
+std::unique_ptr<cmNinjaTargetGenerator> cmNinjaTargetGenerator::New(
+ cmGeneratorTarget* target)
{
switch (target->GetType()) {
case cmStateEnums::EXECUTABLE:
@@ -40,33 +45,28 @@ cmNinjaTargetGenerator* cmNinjaTargetGenerator::New(cmGeneratorTarget* target)
case cmStateEnums::STATIC_LIBRARY:
case cmStateEnums::MODULE_LIBRARY:
case cmStateEnums::OBJECT_LIBRARY:
- return new cmNinjaNormalTargetGenerator(target);
+ return cm::make_unique<cmNinjaNormalTargetGenerator>(target);
case cmStateEnums::UTILITY:
case cmStateEnums::GLOBAL_TARGET:
- return new cmNinjaUtilityTargetGenerator(target);
+ return cm::make_unique<cmNinjaUtilityTargetGenerator>(target);
default:
- return CM_NULLPTR;
+ return std::unique_ptr<cmNinjaTargetGenerator>();
}
}
cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmGeneratorTarget* target)
: cmCommonTargetGenerator(target)
- , MacOSXContentGenerator(CM_NULLPTR)
- , OSXBundleGenerator(CM_NULLPTR)
- , MacContentFolders()
+ , MacOSXContentGenerator(nullptr)
+ , OSXBundleGenerator(nullptr)
, LocalGenerator(
static_cast<cmLocalNinjaGenerator*>(target->GetLocalGenerator()))
- , Objects()
{
- MacOSXContentGenerator = new MacOSXContentGeneratorType(this);
+ MacOSXContentGenerator = cm::make_unique<MacOSXContentGeneratorType>(this);
}
-cmNinjaTargetGenerator::~cmNinjaTargetGenerator()
-{
- delete this->MacOSXContentGenerator;
-}
+cmNinjaTargetGenerator::~cmNinjaTargetGenerator() = default;
cmGeneratedFileStream& cmNinjaTargetGenerator::GetBuildFileStream() const
{
@@ -103,6 +103,19 @@ bool cmNinjaTargetGenerator::NeedExplicitPreprocessing(
return lang == "Fortran";
}
+bool cmNinjaTargetGenerator::UsePreprocessedSource(
+ std::string const& lang) const
+{
+ return lang == "Fortran";
+}
+
+bool cmNinjaTargetGenerator::CompilePreprocessedSourceWithDefines(
+ std::string const& lang) const
+{
+ return this->Makefile->IsOn(
+ cmStrCat("CMAKE_", lang, "_COMPILE_WITH_DEFINES"));
+}
+
std::string cmNinjaTargetGenerator::LanguageDyndepRule(
const std::string& lang) const
{
@@ -128,6 +141,7 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
cmSourceFile const* source, const std::string& language)
{
std::string flags = this->GetFlags(language);
+ const std::string configName = this->LocalGenerator->GetConfigName();
// Add Fortran format flags.
if (language == "Fortran") {
@@ -135,13 +149,37 @@ 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;
- CM_AUTO_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, configName, this->GeneratorTarget, 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));
+ }
+
+ // Add precompile headers compile options.
+ const std::string pchSource =
+ this->GeneratorTarget->GetPchSource(configName, language);
+
+ if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) {
+ std::string pchOptions;
+ if (source->GetFullPath() == pchSource) {
+ pchOptions = this->GeneratorTarget->GetPchCreateCompileOptions(
+ configName, language);
+ } else {
+ pchOptions =
+ this->GeneratorTarget->GetPchUseCompileOptions(configName, language);
+ }
+
+ this->LocalGenerator->AppendCompileOptions(
+ flags, genexInterpreter.Evaluate(pchOptions, COMPILE_OPTIONS));
}
return flags;
@@ -167,9 +205,28 @@ void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags,
bool cmNinjaTargetGenerator::NeedDepTypeMSVC(const std::string& lang) const
{
- return strcmp(this->GetMakefile()->GetSafeDefinition("CMAKE_NINJA_DEPTYPE_" +
- lang),
- "msvc") == 0;
+ std::string const& deptype =
+ this->GetMakefile()->GetSafeDefinition("CMAKE_NINJA_DEPTYPE_" + lang);
+ if (deptype == "msvc") {
+ return true;
+ }
+ if (deptype == "intel") {
+ // Ninja does not really define "intel", but we use it to switch based
+ // on whether this environment supports "gcc" or "msvc" deptype.
+ if (!this->GetGlobalGenerator()->SupportsMultilineDepfile()) {
+ // This ninja version is too old to support the Intel depfile format.
+ // Fall back to msvc deptype.
+ return true;
+ }
+ if ((this->Makefile->GetHomeDirectory().find(' ') != std::string::npos) ||
+ (this->Makefile->GetHomeOutputDirectory().find(' ') !=
+ std::string::npos)) {
+ // The Intel compiler does not properly escape spaces in a depfile.
+ // Fall back to msvc deptype.
+ return true;
+ }
+ }
+ return false;
}
// TODO: Refactor with
@@ -178,13 +235,22 @@ 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, config, this->GeneratorTarget, 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 =
+ cmStrCat("COMPILE_DEFINITIONS_", 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,7 +259,31 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source,
return definesString;
}
-cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
+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, config, this->GeneratorTarget, 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 std::string& linkLanguage) const
{
// Static libraries never depend on other targets for linking.
if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
@@ -215,29 +305,24 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
if (cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
this->GeneratorTarget->GetModuleDefinitionInfo(
this->GetConfigName())) {
- for (std::vector<cmSourceFile const*>::const_iterator i =
- mdi->Sources.begin();
- i != mdi->Sources.end(); ++i) {
- result.push_back(this->ConvertToNinjaPath((*i)->GetFullPath()));
+ for (cmSourceFile const* src : mdi->Sources) {
+ result.push_back(this->ConvertToNinjaPath(src->GetFullPath()));
}
}
// Add a dependency on user-specified manifest files, if any.
std::vector<cmSourceFile const*> manifest_srcs;
this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName);
- for (std::vector<cmSourceFile const*>::iterator mi = manifest_srcs.begin();
- mi != manifest_srcs.end(); ++mi) {
- result.push_back(this->ConvertToNinjaPath((*mi)->GetFullPath()));
+ for (cmSourceFile const* manifest_src : manifest_srcs) {
+ result.push_back(this->ConvertToNinjaPath(manifest_src->GetFullPath()));
}
// Add user-specified dependencies.
- if (const char* linkDepends =
- this->GeneratorTarget->GetProperty("LINK_DEPENDS")) {
- std::vector<std::string> linkDeps;
- cmSystemTools::ExpandListArgument(linkDepends, linkDeps);
- std::transform(linkDeps.begin(), linkDeps.end(),
- std::back_inserter(result), MapToNinjaPath());
- }
+ std::vector<std::string> linkDeps;
+ this->GeneratorTarget->GetLinkDepends(linkDeps, this->ConfigName,
+ linkLanguage);
+ std::transform(linkDeps.begin(), linkDeps.end(), std::back_inserter(result),
+ MapToNinjaPath());
return result;
}
@@ -315,10 +400,10 @@ std::string cmNinjaTargetGenerator::GetDyndepFilePath(
std::string cmNinjaTargetGenerator::GetTargetDependInfoPath(
std::string const& lang) const
{
- std::string path = this->Makefile->GetCurrentBinaryDirectory();
- path += "/";
- path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
- path += "/" + lang + "DependInfo.json";
+ std::string path =
+ cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/',
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget),
+ '/', lang, "DependInfo.json");
return path;
}
@@ -357,9 +442,9 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const
this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
- pdbPath = this->GeneratorTarget->GetPDBDirectory(this->GetConfigName());
- pdbPath += "/";
- pdbPath += this->GeneratorTarget->GetPDBName(this->GetConfigName());
+ pdbPath = cmStrCat(
+ this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()), '/',
+ this->GeneratorTarget->GetPDBName(this->GetConfigName()));
}
vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
@@ -399,74 +484,28 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
vars.ObjectDir = "$OBJECT_DIR";
vars.ObjectFileDir = "$OBJECT_FILE_DIR";
+ cmMakefile* mf = this->GetMakefile();
+
// For some cases we do an explicit preprocessor invocation.
bool const explicitPP = this->NeedExplicitPreprocessing(lang);
+ bool const compilePPWithDefines = this->UsePreprocessedSource(lang) &&
+ this->CompilePreprocessedSourceWithDefines(lang);
bool const needDyndep = this->NeedDyndep(lang);
- cmMakefile* mf = this->GetMakefile();
-
std::string flags = "$FLAGS";
- std::string rspfile;
- std::string rspcontent;
- std::string responseFlag;
- bool const lang_supports_response = !(lang == "RC" || lang == "CUDA");
+ std::string responseFlag;
+ bool const lang_supports_response = lang != "RC";
if (lang_supports_response && this->ForceResponseFile()) {
- rspfile = "$RSP_FILE";
- responseFlag = "@" + rspfile;
- rspcontent = " $DEFINES $INCLUDES $FLAGS";
- flags = responseFlag;
- vars.Defines = "";
- vars.Includes = "";
- }
-
- // Tell ninja dependency format so all deps can be loaded into a database
- std::string deptype;
- std::string depfile;
- std::string cldeps;
- if (explicitPP) {
- // The explicit preprocessing step will handle dependency scanning.
- } else if (this->NeedDepTypeMSVC(lang)) {
- deptype = "msvc";
- depfile = "";
- flags += " /showIncludes";
- } else if (mf->IsOn("CMAKE_NINJA_CMCLDEPS_" + lang)) {
- // For the MS resource compiler we need cmcldeps, but skip dependencies
- // for source-file try_compile cases because they are always fresh.
- if (!mf->GetIsSourceFileTryCompile()) {
- deptype = "gcc";
- depfile = "$DEP_FILE";
- const std::string cl = mf->GetDefinition("CMAKE_C_COMPILER")
- ? mf->GetSafeDefinition("CMAKE_C_COMPILER")
- : mf->GetSafeDefinition("CMAKE_CXX_COMPILER");
- cldeps = "\"";
- cldeps += cmSystemTools::GetCMClDepsCommand();
- cldeps += "\" " + lang + " " + vars.Source + " \"$DEP_FILE\" $out \"";
- cldeps += mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX");
- cldeps += "\" \"" + cl + "\" ";
- }
- } else {
- deptype = "gcc";
- const char* langdeptype = mf->GetDefinition("CMAKE_NINJA_DEPTYPE_" + lang);
- if (langdeptype) {
- deptype = langdeptype;
- }
- depfile = "$DEP_FILE";
- const std::string flagsName = "CMAKE_DEPFILE_FLAGS_" + lang;
- std::string depfileFlags = mf->GetSafeDefinition(flagsName);
- if (!depfileFlags.empty()) {
- cmSystemTools::ReplaceString(depfileFlags, "<DEPFILE>", "$DEP_FILE");
- cmSystemTools::ReplaceString(depfileFlags, "<OBJECT>", "$out");
- cmSystemTools::ReplaceString(depfileFlags, "<CMAKE_C_COMPILER>",
- mf->GetDefinition("CMAKE_C_COMPILER"));
- flags += " " + depfileFlags;
+ std::string const responseFlagVar =
+ "CMAKE_" + lang + "_RESPONSE_FILE_FLAG";
+ responseFlag = this->Makefile->GetSafeDefinition(responseFlagVar);
+ if (responseFlag.empty() && lang != "CUDA") {
+ responseFlag = "@";
}
}
- vars.Flags = flags.c_str();
- vars.DependencyFile = depfile.c_str();
-
- CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+ std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->GetLocalGenerator()->CreateRulePlaceholderExpander());
std::string const tdi = this->GetLocalGenerator()->ConvertToOutputFormat(
@@ -477,19 +516,18 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
const char* val = this->GetLocalGenerator()->GetRuleLauncher(
this->GetGeneratorTarget(), "RULE_LAUNCH_COMPILE");
if (val && *val) {
- launcher = val;
- launcher += " ";
+ launcher = cmStrCat(val, ' ');
}
- if (explicitPP) {
- // Lookup the explicit preprocessing rule.
- std::string const ppVar = "CMAKE_" + lang + "_PREPROCESS_SOURCE";
- std::string const ppCmd =
- this->GetMakefile()->GetRequiredDefinition(ppVar);
+ std::string const cmakeCmd =
+ this->GetLocalGenerator()->ConvertToOutputFormat(
+ cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
+ if (explicitPP) {
+ cmNinjaRule rule(this->LanguagePreprocessRule(lang));
// Explicit preprocessing always uses a depfile.
- std::string const ppDeptype; // no deps= for multiple outputs
- std::string const ppDepfile = "$DEP_FILE";
+ rule.DepType = ""; // no deps= for multiple outputs
+ rule.DepFile = "$DEP_FILE";
cmRulePlaceholderExpander::RuleVariables ppVars;
ppVars.CMTargetName = vars.CMTargetName;
@@ -497,7 +535,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
ppVars.Language = vars.Language;
ppVars.Object = "$out"; // for RULE_LAUNCH_COMPILE
ppVars.PreprocessedSource = "$out";
- ppVars.DependencyFile = ppDepfile.c_str();
+ ppVars.DependencyFile = rule.DepFile.c_str();
// Preprocessing uses the original source,
// compilation uses preprocessed output.
@@ -505,114 +543,172 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
vars.Source = "$in";
// Preprocessing and compilation use the same flags.
- ppVars.Flags = vars.Flags;
+ std::string ppFlags = flags;
- // Move preprocessor definitions to the preprocessor rule.
- ppVars.Defines = vars.Defines;
- vars.Defines = "";
+ if (!compilePPWithDefines) {
+ // Move preprocessor definitions to the preprocessor rule.
+ ppVars.Defines = vars.Defines;
+ vars.Defines = "";
+ } else {
+ // Copy preprocessor definitions to the preprocessor rule.
+ ppVars.Defines = vars.Defines;
+ }
// Copy include directories to the preprocessor rule. The Fortran
// compilation rule still needs them for the INCLUDE directive.
ppVars.Includes = vars.Includes;
+ // If using a response file, move defines, includes, and flags into it.
+ if (!responseFlag.empty()) {
+ rule.RspFile = "$RSP_FILE";
+ rule.RspContent =
+ cmStrCat(' ', ppVars.Defines, ' ', ppVars.Includes, ' ', ppFlags);
+ ppFlags = responseFlag + rule.RspFile;
+ ppVars.Defines = "";
+ ppVars.Includes = "";
+ }
+
+ ppVars.Flags = ppFlags.c_str();
+
// Rule for preprocessing source file.
std::vector<std::string> ppCmds;
- cmSystemTools::ExpandListArgument(ppCmd, ppCmds);
+ {
+ // Lookup the explicit preprocessing rule.
+ std::string ppVar = cmStrCat("CMAKE_", lang, "_PREPROCESS_SOURCE");
+ cmExpandList(this->GetMakefile()->GetRequiredDefinition(ppVar), ppCmds);
+ }
- for (std::vector<std::string>::iterator i = ppCmds.begin();
- i != ppCmds.end(); ++i) {
- *i = launcher + *i;
+ for (std::string& i : ppCmds) {
+ i = cmStrCat(launcher, i);
rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
- *i, ppVars);
+ i, ppVars);
}
// Run CMake dependency scanner on preprocessed output.
- std::string const cmake = this->GetLocalGenerator()->ConvertToOutputFormat(
- cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
- ppCmds.push_back(
- cmake + " -E cmake_ninja_depends"
- " --tdi=" +
- tdi + " --pp=$out"
- " --dep=$DEP_FILE" +
- (needDyndep ? " --obj=$OBJ_FILE --ddi=$DYNDEP_INTERMEDIATE_FILE" : ""));
-
- std::string const ppCmdLine =
- this->GetLocalGenerator()->BuildCommandLine(ppCmds);
+ {
+ std::string ccmd =
+ cmStrCat(cmakeCmd, " -E cmake_ninja_depends --tdi=", tdi,
+ " --lang=", lang, " --pp=$out --dep=$DEP_FILE");
+ if (needDyndep) {
+ ccmd += " --obj=$OBJ_FILE --ddi=$DYNDEP_INTERMEDIATE_FILE";
+ }
+ ppCmds.emplace_back(std::move(ccmd));
+ }
+ rule.Command = this->GetLocalGenerator()->BuildCommandLine(ppCmds);
// Write the rule for preprocessing file of the given language.
- std::ostringstream ppComment;
- ppComment << "Rule for preprocessing " << lang << " files.";
- std::ostringstream ppDesc;
- ppDesc << "Building " << lang << " preprocessed $out";
- this->GetGlobalGenerator()->AddRule(this->LanguagePreprocessRule(lang),
- ppCmdLine, ppDesc.str(),
- ppComment.str(), ppDepfile, ppDeptype,
- /*rspfile*/ "",
- /*rspcontent*/ "",
- /*restat*/ "",
- /*generator*/ false);
+ rule.Comment = cmStrCat("Rule for preprocessing ", lang, " files.");
+ rule.Description = cmStrCat("Building ", lang, " preprocessed $out");
+ this->GetGlobalGenerator()->AddRule(rule);
}
if (needDyndep) {
// Write the rule for ninja dyndep file generation.
- std::vector<std::string> ddCmds;
-
-#ifdef _WIN32
- // Windows command line length is limited -> use response file for dyndep
- // rules
- std::string ddRspFile = "$out.rsp";
- std::string ddRspContent = "$in";
- std::string ddInput = "@" + ddRspFile;
-#else
- std::string ddRspFile;
- std::string ddRspContent;
- std::string ddInput = "$in";
-#endif
+ cmNinjaRule rule(this->LanguageDyndepRule(lang));
+ // Command line length is almost always limited -> use response file for
+ // dyndep rules
+ rule.RspFile = "$out.rsp";
+ rule.RspContent = "$in";
+
+ // Run CMake dependency scanner on the source file (using the preprocessed
+ // source if that was performed).
+ {
+ std::vector<std::string> ddCmds;
+ {
+ std::string ccmd =
+ cmStrCat(cmakeCmd, " -E cmake_ninja_dyndep --tdi=", tdi,
+ " --lang=", lang, " --dd=$out @", rule.RspFile);
+ ddCmds.emplace_back(std::move(ccmd));
+ }
+ rule.Command = this->GetLocalGenerator()->BuildCommandLine(ddCmds);
+ }
+ rule.Comment =
+ cmStrCat("Rule to generate ninja dyndep files for ", lang, '.');
+ rule.Description = cmStrCat("Generating ", lang, " dyndep file $out");
+ this->GetGlobalGenerator()->AddRule(rule);
+ }
- // Run CMake dependency scanner on preprocessed output.
- std::string const cmake = this->GetLocalGenerator()->ConvertToOutputFormat(
- cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
- ddCmds.push_back(cmake + " -E cmake_ninja_dyndep"
- " --tdi=" +
- tdi + " --dd=$out"
- " " +
- ddInput);
-
- std::string const ddCmdLine =
- this->GetLocalGenerator()->BuildCommandLine(ddCmds);
-
- std::ostringstream ddComment;
- ddComment << "Rule to generate ninja dyndep files for " << lang << ".";
- std::ostringstream ddDesc;
- ddDesc << "Generating " << lang << " dyndep file $out";
- this->GetGlobalGenerator()->AddRule(
- this->LanguageDyndepRule(lang), ddCmdLine, ddDesc.str(), ddComment.str(),
- /*depfile*/ "",
- /*deps*/ "", ddRspFile, ddRspContent,
- /*restat*/ "",
- /*generator*/ false);
+ cmNinjaRule rule(this->LanguageCompilerRule(lang));
+ // If using a response file, move defines, includes, and flags into it.
+ if (!responseFlag.empty()) {
+ rule.RspFile = "$RSP_FILE";
+ rule.RspContent =
+ cmStrCat(' ', vars.Defines, ' ', vars.Includes, ' ', flags);
+ flags = responseFlag + rule.RspFile;
+ vars.Defines = "";
+ vars.Includes = "";
}
+ // Tell ninja dependency format so all deps can be loaded into a database
+ std::string cldeps;
+ if (explicitPP) {
+ // The explicit preprocessing step will handle dependency scanning.
+ } else if (this->NeedDepTypeMSVC(lang)) {
+ rule.DepType = "msvc";
+ rule.DepFile.clear();
+ flags += " /showIncludes";
+ } else if (mf->IsOn("CMAKE_NINJA_CMCLDEPS_" + lang)) {
+ // For the MS resource compiler we need cmcldeps, but skip dependencies
+ // for source-file try_compile cases because they are always fresh.
+ if (!mf->GetIsSourceFileTryCompile()) {
+ rule.DepType = "gcc";
+ rule.DepFile = "$DEP_FILE";
+ const std::string cl = mf->GetDefinition("CMAKE_C_COMPILER")
+ ? mf->GetSafeDefinition("CMAKE_C_COMPILER")
+ : mf->GetSafeDefinition("CMAKE_CXX_COMPILER");
+ cldeps = cmStrCat('"', cmSystemTools::GetCMClDepsCommand(), "\" ", lang,
+ ' ', vars.Source, " $DEP_FILE $out \"",
+ mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX"),
+ "\" \"", cl, "\" ");
+ }
+ } else {
+ rule.DepType = "gcc";
+ rule.DepFile = "$DEP_FILE";
+ const std::string flagsName = "CMAKE_DEPFILE_FLAGS_" + lang;
+ std::string depfileFlags = mf->GetSafeDefinition(flagsName);
+ if (!depfileFlags.empty()) {
+ cmSystemTools::ReplaceString(depfileFlags, "<DEPFILE>", "$DEP_FILE");
+ cmSystemTools::ReplaceString(depfileFlags, "<OBJECT>", "$out");
+ cmSystemTools::ReplaceString(depfileFlags, "<CMAKE_C_COMPILER>",
+ mf->GetDefinition("CMAKE_C_COMPILER"));
+ flags += " " + depfileFlags;
+ }
+ }
+
+ vars.Flags = flags.c_str();
+ vars.DependencyFile = rule.DepFile.c_str();
+
// Rule for compiling object file.
std::vector<std::string> compileCmds;
if (lang == "CUDA") {
std::string cmdVar;
if (this->GeneratorTarget->GetPropertyAsBool(
"CUDA_SEPARABLE_COMPILATION")) {
- cmdVar = std::string("CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION");
+ cmdVar = "CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION";
} else if (this->GeneratorTarget->GetPropertyAsBool(
"CUDA_PTX_COMPILATION")) {
- cmdVar = std::string("CMAKE_CUDA_COMPILE_PTX_COMPILATION");
+ cmdVar = "CMAKE_CUDA_COMPILE_PTX_COMPILATION";
} else {
- cmdVar = std::string("CMAKE_CUDA_COMPILE_WHOLE_COMPILATION");
+ cmdVar = "CMAKE_CUDA_COMPILE_WHOLE_COMPILATION";
}
- std::string compileCmd = mf->GetRequiredDefinition(cmdVar);
- cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
+ const std::string& compileCmd = mf->GetRequiredDefinition(cmdVar);
+ cmExpandList(compileCmd, compileCmds);
} else {
- const std::string cmdVar =
- std::string("CMAKE_") + lang + "_COMPILE_OBJECT";
- std::string compileCmd = mf->GetRequiredDefinition(cmdVar);
- cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
+ const std::string cmdVar = "CMAKE_" + lang + "_COMPILE_OBJECT";
+ const std::string& compileCmd = mf->GetRequiredDefinition(cmdVar);
+ cmExpandList(compileCmd, compileCmds);
+ }
+
+ // See if we need to use a compiler launcher like ccache or distcc
+ std::string compilerLauncher;
+ if (!compileCmds.empty() &&
+ (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" ||
+ lang == "OBJC" || lang == "OBJCXX")) {
+ std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
+ const char* clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
+ if (clauncher && *clauncher) {
+ compilerLauncher = clauncher;
+ }
}
// Maybe insert an include-what-you-use runner.
@@ -623,10 +719,18 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
const char* tidy = this->GeneratorTarget->GetProperty(tidy_prop);
std::string const cpplint_prop = lang + "_CPPLINT";
const char* cpplint = this->GeneratorTarget->GetProperty(cpplint_prop);
- if ((iwyu && *iwyu) || (tidy && *tidy) || (cpplint && *cpplint)) {
- std::string run_iwyu = this->GetLocalGenerator()->ConvertToOutputFormat(
- cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
- run_iwyu += " -E __run_iwyu";
+ std::string const cppcheck_prop = lang + "_CPPCHECK";
+ const char* cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop);
+ if ((iwyu && *iwyu) || (tidy && *tidy) || (cpplint && *cpplint) ||
+ (cppcheck && *cppcheck)) {
+ std::string run_iwyu = cmStrCat(cmakeCmd, " -E __run_co_compile");
+ if (!compilerLauncher.empty()) {
+ // In __run_co_compile case the launcher command is supplied
+ // via --launcher=<maybe-list> and consumed
+ run_iwyu += " --launcher=";
+ run_iwyu += this->LocalGenerator->EscapeForShell(compilerLauncher);
+ compilerLauncher.clear();
+ }
if (iwyu && *iwyu) {
run_iwyu += " --iwyu=";
run_iwyu += this->GetLocalGenerator()->EscapeForShell(iwyu);
@@ -639,7 +743,12 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
run_iwyu += " --cpplint=";
run_iwyu += this->GetLocalGenerator()->EscapeForShell(cpplint);
}
- if ((tidy && *tidy) || (cpplint && *cpplint)) {
+ if (cppcheck && *cppcheck) {
+ run_iwyu += " --cppcheck=";
+ run_iwyu += this->GetLocalGenerator()->EscapeForShell(cppcheck);
+ }
+ if ((tidy && *tidy) || (cpplint && *cpplint) ||
+ (cppcheck && *cppcheck)) {
run_iwyu += " --source=$in";
}
run_iwyu += " -- ";
@@ -647,47 +756,36 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
}
}
- // Maybe insert a compiler launcher like ccache or distcc
- if (!compileCmds.empty() && (lang == "C" || lang == "CXX")) {
- std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
- const char* clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
- if (clauncher && *clauncher) {
- std::vector<std::string> launcher_cmd;
- cmSystemTools::ExpandListArgument(clauncher, launcher_cmd, true);
- for (std::vector<std::string>::iterator i = launcher_cmd.begin(),
- e = launcher_cmd.end();
- i != e; ++i) {
- *i = this->LocalGenerator->EscapeForShell(*i);
+ // If compiler launcher was specified and not consumed above, it
+ // goes to the beginning of the command line.
+ if (!compileCmds.empty() && !compilerLauncher.empty()) {
+ std::vector<std::string> args = cmExpandedList(compilerLauncher, true);
+ if (!args.empty()) {
+ args[0] = this->LocalGenerator->ConvertToOutputFormat(
+ args[0], cmOutputConverter::SHELL);
+ for (std::string& i : cmMakeRange(args.begin() + 1, args.end())) {
+ i = this->LocalGenerator->EscapeForShell(i);
}
- std::string const& run_launcher = cmJoin(launcher_cmd, " ") + " ";
- compileCmds.front().insert(0, run_launcher);
}
+ compileCmds.front().insert(0, cmJoin(args, " ") + " ");
}
if (!compileCmds.empty()) {
compileCmds.front().insert(0, cldeps);
}
- for (std::vector<std::string>::iterator i = compileCmds.begin();
- i != compileCmds.end(); ++i) {
- *i = launcher + *i;
- rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), *i,
+ for (std::string& i : compileCmds) {
+ i = cmStrCat(launcher, i);
+ rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), i,
vars);
}
- std::string cmdLine =
- this->GetLocalGenerator()->BuildCommandLine(compileCmds);
+ rule.Command = this->GetLocalGenerator()->BuildCommandLine(compileCmds);
// Write the rule for compiling file of the given language.
- std::ostringstream comment;
- comment << "Rule for compiling " << lang << " files.";
- std::ostringstream description;
- description << "Building " << lang << " object $out";
- this->GetGlobalGenerator()->AddRule(
- this->LanguageCompilerRule(lang), cmdLine, description.str(),
- comment.str(), depfile, deptype, rspfile, rspcontent,
- /*restat*/ "",
- /*generator*/ false);
+ rule.Comment = cmStrCat("Rule for compiling ", lang, " files.");
+ rule.Description = cmStrCat("Building ", lang, " object $out");
+ this->GetGlobalGenerator()->AddRule(rule);
}
void cmNinjaTargetGenerator::WriteObjectBuildStatements()
@@ -699,109 +797,144 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
<< cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType())
<< " target " << this->GetTargetName() << "\n\n";
- std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
- std::vector<cmSourceFile const*> customCommands;
- this->GeneratorTarget->GetCustomCommands(customCommands, config);
- for (std::vector<cmSourceFile const*>::const_iterator si =
- customCommands.begin();
- si != customCommands.end(); ++si) {
- cmCustomCommand const* cc = (*si)->GetCustomCommand();
- this->GetLocalGenerator()->AddCustomCommandTarget(
- cc, this->GetGeneratorTarget());
- // Record the custom commands for this target. The container is used
- // in WriteObjectBuildStatement when called in a loop below.
- this->CustomCommands.push_back(cc);
+ {
+ std::vector<cmSourceFile const*> customCommands;
+ this->GeneratorTarget->GetCustomCommands(customCommands, this->ConfigName);
+ for (cmSourceFile const* sf : customCommands) {
+ cmCustomCommand const* cc = sf->GetCustomCommand();
+ this->GetLocalGenerator()->AddCustomCommandTarget(
+ cc, this->GetGeneratorTarget());
+ // Record the custom commands for this target. The container is used
+ // in WriteObjectBuildStatement when called in a loop below.
+ this->CustomCommands.push_back(cc);
+ }
}
- std::vector<cmSourceFile const*> headerSources;
- this->GeneratorTarget->GetHeaderSources(headerSources, config);
- this->OSXBundleGenerator->GenerateMacOSXContentStatements(
- headerSources, this->MacOSXContentGenerator);
- std::vector<cmSourceFile const*> extraSources;
- this->GeneratorTarget->GetExtraSources(extraSources, config);
- this->OSXBundleGenerator->GenerateMacOSXContentStatements(
- extraSources, this->MacOSXContentGenerator);
- std::vector<cmSourceFile const*> externalObjects;
- this->GeneratorTarget->GetExternalObjects(externalObjects, config);
- for (std::vector<cmSourceFile const*>::const_iterator si =
- externalObjects.begin();
- si != externalObjects.end(); ++si) {
- this->Objects.push_back(this->GetSourceFilePath(*si));
+ {
+ std::vector<cmSourceFile const*> headerSources;
+ this->GeneratorTarget->GetHeaderSources(headerSources, this->ConfigName);
+ this->OSXBundleGenerator->GenerateMacOSXContentStatements(
+ headerSources, this->MacOSXContentGenerator.get());
}
-
- cmNinjaDeps orderOnlyDeps;
- this->GetLocalGenerator()->AppendTargetDepends(
- this->GeneratorTarget, orderOnlyDeps, DependOnTargetOrdering);
-
- // Add order-only dependencies on other files associated with the target.
- orderOnlyDeps.insert(orderOnlyDeps.end(), this->ExtraFiles.begin(),
- this->ExtraFiles.end());
-
- // Add order-only dependencies on custom command outputs.
- for (std::vector<cmCustomCommand const*>::const_iterator cci =
- this->CustomCommands.begin();
- cci != this->CustomCommands.end(); ++cci) {
- cmCustomCommand const* cc = *cci;
- cmCustomCommandGenerator ccg(*cc, this->GetConfigName(),
- this->GetLocalGenerator());
- const std::vector<std::string>& ccoutputs = ccg.GetOutputs();
- const std::vector<std::string>& ccbyproducts = ccg.GetByproducts();
- std::transform(ccoutputs.begin(), ccoutputs.end(),
- std::back_inserter(orderOnlyDeps), MapToNinjaPath());
- std::transform(ccbyproducts.begin(), ccbyproducts.end(),
- std::back_inserter(orderOnlyDeps), MapToNinjaPath());
+ {
+ std::vector<cmSourceFile const*> extraSources;
+ this->GeneratorTarget->GetExtraSources(extraSources, this->ConfigName);
+ this->OSXBundleGenerator->GenerateMacOSXContentStatements(
+ extraSources, this->MacOSXContentGenerator.get());
+ }
+ {
+ const char* pchExtension =
+ GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION");
+
+ std::vector<cmSourceFile const*> externalObjects;
+ this->GeneratorTarget->GetExternalObjects(externalObjects,
+ this->ConfigName);
+ for (cmSourceFile const* sf : externalObjects) {
+ const auto objectFileName = this->GetSourceFilePath(sf);
+ if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) {
+ this->Objects.push_back(objectFileName);
+ }
+ }
}
-
- std::sort(orderOnlyDeps.begin(), orderOnlyDeps.end());
- orderOnlyDeps.erase(std::unique(orderOnlyDeps.begin(), orderOnlyDeps.end()),
- orderOnlyDeps.end());
{
- cmNinjaDeps orderOnlyTarget;
- orderOnlyTarget.push_back(this->OrderDependsTargetForTarget());
- this->GetGlobalGenerator()->WritePhonyBuild(
- this->GetBuildFileStream(),
- "Order-only phony target for " + this->GetTargetName(), orderOnlyTarget,
- cmNinjaDeps(), cmNinjaDeps(), orderOnlyDeps);
+ cmNinjaBuild build("phony");
+ build.Comment = "Order-only phony target for " + this->GetTargetName();
+ build.Outputs.push_back(this->OrderDependsTargetForTarget());
+
+ cmNinjaDeps& orderOnlyDeps = build.OrderOnlyDeps;
+ this->GetLocalGenerator()->AppendTargetDepends(
+ this->GeneratorTarget, orderOnlyDeps, DependOnTargetOrdering);
+
+ // Add order-only dependencies on other files associated with the target.
+ cmAppend(orderOnlyDeps, this->ExtraFiles);
+
+ // Add order-only dependencies on custom command outputs.
+ for (cmCustomCommand const* cc : this->CustomCommands) {
+ cmCustomCommandGenerator ccg(*cc, this->GetConfigName(),
+ this->GetLocalGenerator());
+ const std::vector<std::string>& ccoutputs = ccg.GetOutputs();
+ const std::vector<std::string>& ccbyproducts = ccg.GetByproducts();
+ std::transform(ccoutputs.begin(), ccoutputs.end(),
+ std::back_inserter(orderOnlyDeps), MapToNinjaPath());
+ std::transform(ccbyproducts.begin(), ccbyproducts.end(),
+ std::back_inserter(orderOnlyDeps), MapToNinjaPath());
+ }
+
+ std::sort(orderOnlyDeps.begin(), orderOnlyDeps.end());
+ orderOnlyDeps.erase(
+ std::unique(orderOnlyDeps.begin(), orderOnlyDeps.end()),
+ orderOnlyDeps.end());
+
+ // The phony target must depend on at least one input or ninja will explain
+ // that "output ... of phony edge with no inputs doesn't exist" and
+ // consider the phony output "dirty".
+ if (orderOnlyDeps.empty()) {
+ // Any path that always exists will work here. It would be nice to
+ // use just "." but that is not supported by Ninja < 1.7.
+ std::string tgtDir = cmStrCat(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget));
+ orderOnlyDeps.push_back(this->ConvertToNinjaPath(tgtDir));
+ }
+
+ this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build);
}
- std::vector<cmSourceFile const*> objectSources;
- this->GeneratorTarget->GetObjectSources(objectSources, config);
- for (std::vector<cmSourceFile const*>::const_iterator si =
- objectSources.begin();
- si != objectSources.end(); ++si) {
- this->WriteObjectBuildStatement(*si);
+
+ {
+ std::vector<cmSourceFile const*> objectSources;
+ this->GeneratorTarget->GetObjectSources(objectSources, this->ConfigName);
+ for (cmSourceFile const* sf : objectSources) {
+ this->WriteObjectBuildStatement(sf);
+ }
}
- if (!this->DDIFiles.empty()) {
- std::string const ddComment;
- std::string const ddRule = this->LanguageDyndepRule("Fortran");
- cmNinjaDeps ddOutputs;
- cmNinjaDeps ddImplicitOuts;
- cmNinjaDeps const& ddExplicitDeps = this->DDIFiles;
- cmNinjaDeps ddImplicitDeps;
- cmNinjaDeps ddOrderOnlyDeps;
- cmNinjaVars ddVars;
+ for (auto const& langDDIFiles : this->DDIFiles) {
+ std::string const& language = langDDIFiles.first;
+ cmNinjaDeps const& ddiFiles = langDDIFiles.second;
- this->WriteTargetDependInfo("Fortran");
+ cmNinjaBuild build(this->LanguageDyndepRule(language));
+ build.Outputs.push_back(this->GetDyndepFilePath(language));
+ build.ExplicitDeps = ddiFiles;
- ddOutputs.push_back(this->GetDyndepFilePath("Fortran"));
+ this->WriteTargetDependInfo(language);
// Make sure dyndep files for all our dependencies have already
- // been generated so that the 'FortranModules.json' files they
+ // been generated so that the '<LANG>Modules.json' files they
// produced as side-effects are available for us to read.
- // Ideally we should depend on the 'FortranModules.json' files
+ // Ideally we should depend on the '<LANG>Modules.json' files
// from our dependencies directly, but we don't know which of
// our dependencies produces them. Fixing this will require
// refactoring the Ninja generator to generate targets in
// dependency order so that we can collect the needed information.
this->GetLocalGenerator()->AppendTargetDepends(
- this->GeneratorTarget, ddOrderOnlyDeps, DependOnTargetArtifact);
+ this->GeneratorTarget, build.OrderOnlyDeps, DependOnTargetArtifact);
- this->GetGlobalGenerator()->WriteBuild(
- this->GetBuildFileStream(), ddComment, ddRule, ddOutputs, ddImplicitOuts,
- ddExplicitDeps, ddImplicitDeps, ddOrderOnlyDeps, ddVars);
+ this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build);
}
this->GetBuildFileStream() << "\n";
+
+ if (!this->SwiftOutputMap.empty()) {
+ std::string const mapFilePath =
+ this->GeneratorTarget->GetSupportDirectory() + "/output-file-map.json";
+ std::string const targetSwiftDepsPath = [this]() -> std::string {
+ cmGeneratorTarget const* target = this->GeneratorTarget;
+ if (const char* name = target->GetProperty("Swift_DEPENDENCIES_FILE")) {
+ return name;
+ }
+ return this->ConvertToNinjaPath(target->GetSupportDirectory() + "/" +
+ target->GetName() + ".swiftdeps");
+ }();
+
+ // build the global target dependencies
+ // https://github.com/apple/swift/blob/master/docs/Driver.md#output-file-maps
+ Json::Value deps(Json::objectValue);
+ deps["swift-dependencies"] = targetSwiftDepsPath;
+ this->SwiftOutputMap[""] = deps;
+
+ cmGeneratedFileStream output(mapFilePath);
+ output << this->SwiftOutputMap;
+ }
}
void cmNinjaTargetGenerator::WriteObjectBuildStatement(
@@ -817,55 +950,102 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
std::string const objectFileDir =
cmSystemTools::GetFilenamePath(objectFileName);
- cmNinjaVars vars;
+ std::string cmakeVarLang = cmStrCat("CMAKE_", language);
+
+ // build response file name
+ std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_FLAG";
+
+ const char* flag = GetMakefile()->GetDefinition(cmakeLinkVar);
+
+ bool const lang_supports_response =
+ !(language == "RC" || (language == "CUDA" && !flag));
+ int const commandLineLengthLimit =
+ ((lang_supports_response && this->ForceResponseFile())) ? -1 : 0;
+
+ cmNinjaBuild objBuild(this->LanguageCompilerRule(language));
+ cmNinjaVars& vars = objBuild.Variables;
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);
+ bool replaceExt(false);
+ if (!language.empty()) {
+ std::string repVar =
+ cmStrCat("CMAKE_", language, "_DEPFILE_EXTENSION_REPLACE");
+ replaceExt = this->Makefile->IsOn(repVar);
+ }
+ if (!replaceExt) {
+ // use original code
+ vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ objectFileName + ".d", cmOutputConverter::SHELL);
+ } else {
+ // Replace the original source file extension with the
+ // depend file extension.
+ std::string dependFileName =
+ cmSystemTools::GetFilenameWithoutLastExtension(objectFileName) + ".d";
+ vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ objectFileDir + "/" + dependFileName, cmOutputConverter::SHELL);
+ }
}
this->ExportObjectCompileCommand(
language, sourceFileName, objectDir, objectFileName, objectFileDir,
vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"]);
- std::string comment;
- std::string rule = this->LanguageCompilerRule(language);
+ objBuild.Outputs.push_back(objectFileName);
+ const char* pchExtension =
+ this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION");
+ if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) {
+ // Add this object to the list of object files.
+ this->Objects.push_back(objectFileName);
+ }
- cmNinjaDeps outputs;
- outputs.push_back(objectFileName);
- // Add this object to the list of object files.
- this->Objects.push_back(objectFileName);
+ objBuild.ExplicitDeps.push_back(sourceFileName);
- cmNinjaDeps explicitDeps;
- explicitDeps.push_back(sourceFileName);
+ // Add precompile headers dependencies
+ std::vector<std::string> depList;
+
+ const std::string pchSource =
+ this->GeneratorTarget->GetPchSource(this->GetConfigName(), language);
+ if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) {
+ depList.push_back(
+ this->GeneratorTarget->GetPchHeader(this->GetConfigName(), language));
+ if (source->GetFullPath() != pchSource) {
+ depList.push_back(
+ this->GeneratorTarget->GetPchFile(this->GetConfigName(), language));
+ }
+ }
- cmNinjaDeps implicitDeps;
if (const char* objectDeps = source->GetProperty("OBJECT_DEPENDS")) {
- std::vector<std::string> depList;
- cmSystemTools::ExpandListArgument(objectDeps, depList);
- for (std::vector<std::string>::iterator odi = depList.begin();
- odi != depList.end(); ++odi) {
- if (cmSystemTools::FileIsFullPath(*odi)) {
- *odi = cmSystemTools::CollapseFullPath(*odi);
+ std::vector<std::string> objDepList = cmExpandedList(objectDeps);
+ std::copy(objDepList.begin(), objDepList.end(),
+ std::back_inserter(depList));
+ }
+
+ if (!depList.empty()) {
+ for (std::string& odi : depList) {
+ if (cmSystemTools::FileIsFullPath(odi)) {
+ odi = cmSystemTools::CollapseFullPath(odi);
}
}
std::transform(depList.begin(), depList.end(),
- std::back_inserter(implicitDeps), MapToNinjaPath());
+ std::back_inserter(objBuild.ImplicitDeps),
+ MapToNinjaPath());
}
- cmNinjaDeps orderOnlyDeps;
- orderOnlyDeps.push_back(this->OrderDependsTargetForTarget());
+ objBuild.OrderOnlyDeps.push_back(this->OrderDependsTargetForTarget());
// If the source file is GENERATED and does not have a custom command
// (either attached to this source file or another one), assume that one of
// the target dependencies, OBJECT_DEPENDS or header file custom commands
// will rebuild the file.
- if (source->GetPropertyAsBool("GENERATED") && !source->GetCustomCommand() &&
+ if (source->GetIsGenerated() &&
+ !source->GetPropertyAsBool("__CMAKE_GENERATED_BY_CMAKE") &&
+ !source->GetCustomCommand() &&
!this->GetGlobalGenerator()->HasCustomCommandOutput(sourceFileName)) {
- this->GetGlobalGenerator()->AddAssumedSourceDependencies(sourceFileName,
- orderOnlyDeps);
+ this->GetGlobalGenerator()->AddAssumedSourceDependencies(
+ sourceFileName, objBuild.OrderOnlyDeps);
}
// For some cases we need to generate a ninja dyndep file.
@@ -874,80 +1054,103 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
// For some cases we do an explicit preprocessor invocation.
bool const explicitPP = this->NeedExplicitPreprocessing(language);
if (explicitPP) {
- std::string const ppComment;
- std::string const ppRule = this->LanguagePreprocessRule(language);
- cmNinjaDeps ppOutputs;
- cmNinjaDeps ppImplicitOuts;
- cmNinjaDeps ppExplicitDeps;
- cmNinjaDeps ppImplicitDeps;
- cmNinjaDeps ppOrderOnlyDeps;
- cmNinjaVars ppVars;
+ cmNinjaBuild ppBuild(this->LanguagePreprocessRule(language));
std::string const ppFileName =
this->ConvertToNinjaPath(this->GetPreprocessedFilePath(source));
- ppOutputs.push_back(ppFileName);
-
- // Move compilation dependencies to the preprocessing build statement.
- std::swap(ppExplicitDeps, explicitDeps);
- std::swap(ppImplicitDeps, implicitDeps);
- std::swap(ppOrderOnlyDeps, orderOnlyDeps);
- std::swap(ppVars["IN_ABS"], vars["IN_ABS"]);
+ ppBuild.Outputs.push_back(ppFileName);
+
+ ppBuild.RspFile = ppFileName + ".rsp";
+
+ bool const compilePP = this->UsePreprocessedSource(language);
+ bool const compilePPWithDefines =
+ compilePP && this->CompilePreprocessedSourceWithDefines(language);
+ if (compilePP) {
+ // Move compilation dependencies to the preprocessing build statement.
+ std::swap(ppBuild.ExplicitDeps, objBuild.ExplicitDeps);
+ std::swap(ppBuild.ImplicitDeps, objBuild.ImplicitDeps);
+ std::swap(ppBuild.OrderOnlyDeps, objBuild.OrderOnlyDeps);
+ std::swap(ppBuild.Variables["IN_ABS"], vars["IN_ABS"]);
+
+ // The actual compilation will now use the preprocessed source.
+ objBuild.ExplicitDeps.push_back(ppFileName);
+ } else {
+ // Copy compilation dependencies to the preprocessing build statement.
+ ppBuild.ExplicitDeps = objBuild.ExplicitDeps;
+ ppBuild.ImplicitDeps = objBuild.ImplicitDeps;
+ ppBuild.OrderOnlyDeps = objBuild.OrderOnlyDeps;
+ ppBuild.Variables["IN_ABS"] = vars["IN_ABS"];
+ }
- // The actual compilation will now use the preprocessed source.
- explicitDeps.push_back(ppFileName);
+ // Preprocessing and compilation generally use the same flags.
+ ppBuild.Variables["FLAGS"] = vars["FLAGS"];
- // Preprocessing and compilation use the same flags.
- ppVars["FLAGS"] = vars["FLAGS"];
+ if (compilePP) {
+ // In case compilation requires flags that are incompatible with
+ // preprocessing, include them here.
+ std::string const& postFlag = this->Makefile->GetSafeDefinition(
+ "CMAKE_" + language + "_POSTPROCESS_FLAG");
+ this->LocalGenerator->AppendFlags(vars["FLAGS"], postFlag);
+ }
- // Move preprocessor definitions to the preprocessor build statement.
- std::swap(ppVars["DEFINES"], vars["DEFINES"]);
+ if (compilePP && !compilePPWithDefines) {
+ // Move preprocessor definitions to the preprocessor build statement.
+ std::swap(ppBuild.Variables["DEFINES"], vars["DEFINES"]);
+ } else {
+ // Copy preprocessor definitions to the preprocessor build statement.
+ ppBuild.Variables["DEFINES"] = vars["DEFINES"];
+ }
// Copy include directories to the preprocessor build statement. The
// Fortran compilation build statement still needs them for the INCLUDE
// directive.
- ppVars["INCLUDES"] = vars["INCLUDES"];
+ ppBuild.Variables["INCLUDES"] = vars["INCLUDES"];
- // Prepend source file's original directory as an include directory
- // so e.g. Fortran INCLUDE statements can look for files in it.
- std::vector<std::string> sourceDirectory;
- sourceDirectory.push_back(
- cmSystemTools::GetParentDirectory(source->GetFullPath()));
+ if (compilePP) {
+ // Prepend source file's original directory as an include directory
+ // so e.g. Fortran INCLUDE statements can look for files in it.
+ std::vector<std::string> sourceDirectory;
+ sourceDirectory.push_back(
+ cmSystemTools::GetParentDirectory(source->GetFullPath()));
- std::string sourceDirectoryFlag = this->LocalGenerator->GetIncludeFlags(
- sourceDirectory, this->GeneratorTarget, language, false, false,
- this->GetConfigName());
+ std::string sourceDirectoryFlag = this->LocalGenerator->GetIncludeFlags(
+ sourceDirectory, this->GeneratorTarget, language, false, false,
+ this->GetConfigName());
- vars["INCLUDES"] = sourceDirectoryFlag + " " + vars["INCLUDES"];
+ vars["INCLUDES"] = sourceDirectoryFlag + " " + vars["INCLUDES"];
+ }
// Explicit preprocessing always uses a depfile.
- ppVars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
- ppFileName + ".d", cmOutputConverter::SHELL);
- // The actual compilation does not need a depfile because it
- // depends on the already-preprocessed source.
- vars.erase("DEP_FILE");
+ ppBuild.Variables["DEP_FILE"] =
+ this->GetLocalGenerator()->ConvertToOutputFormat(
+ objectFileName + ".pp.d", cmOutputConverter::SHELL);
+ if (compilePP) {
+ // The actual compilation does not need a depfile because it
+ // depends on the already-preprocessed source.
+ vars.erase("DEP_FILE");
+ }
if (needDyndep) {
// Tell dependency scanner the object file that will result from
- // compiling the preprocessed source.
- ppVars["OBJ_FILE"] = objectFileName;
+ // compiling the source.
+ ppBuild.Variables["OBJ_FILE"] = objectFileName;
// Tell dependency scanner where to store dyndep intermediate results.
- std::string const ddiFile = ppFileName + ".ddi";
- ppVars["DYNDEP_INTERMEDIATE_FILE"] = ddiFile;
- ppImplicitOuts.push_back(ddiFile);
- this->DDIFiles.push_back(ddiFile);
+ std::string const ddiFile = objectFileName + ".ddi";
+ ppBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFile;
+ ppBuild.ImplicitOuts.push_back(ddiFile);
+ this->DDIFiles[language].push_back(ddiFile);
}
this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(),
- ppVars);
+ ppBuild.Variables);
- this->GetGlobalGenerator()->WriteBuild(
- this->GetBuildFileStream(), ppComment, ppRule, ppOutputs, ppImplicitOuts,
- ppExplicitDeps, ppImplicitDeps, ppOrderOnlyDeps, ppVars);
+ this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), ppBuild,
+ commandLineLengthLimit);
}
if (needDyndep) {
std::string const dyndep = this->GetDyndepFilePath(language);
- orderOnlyDeps.push_back(dyndep);
+ objBuild.OrderOnlyDeps.push_back(dyndep);
vars["dyndep"] = dyndep;
}
@@ -963,25 +1166,23 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
this->SetMsvcTargetPdbVariable(vars);
- bool const lang_supports_response =
- !(language == "RC" || language == "CUDA");
- int const commandLineLengthLimit =
- ((lang_supports_response && this->ForceResponseFile())) ? -1 : 0;
- std::string const rspfile = objectFileName + ".rsp";
+ objBuild.RspFile = objectFileName + ".rsp";
- this->GetGlobalGenerator()->WriteBuild(
- this->GetBuildFileStream(), comment, rule, outputs,
- /*implicitOuts=*/cmNinjaDeps(), explicitDeps, implicitDeps, orderOnlyDeps,
- vars, rspfile, commandLineLengthLimit);
+ if (language == "Swift") {
+ this->EmitSwiftDependencyInfo(source);
+ } else {
+ this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(),
+ objBuild, commandLineLengthLimit);
+ }
if (const char* objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) {
- std::vector<std::string> outputList;
- cmSystemTools::ExpandListArgument(objectOutputs, outputList);
- std::transform(outputList.begin(), outputList.end(), outputList.begin(),
- MapToNinjaPath());
- this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(),
- "Additional output files.",
- outputList, outputs);
+ cmNinjaBuild build("phony");
+ build.Comment = "Additional output files.";
+ build.Outputs = cmExpandedList(objectOutputs);
+ std::transform(build.Outputs.begin(), build.Outputs.end(),
+ build.Outputs.begin(), MapToNinjaPath());
+ build.ExplicitDeps = objBuild.Outputs;
+ this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(), build);
}
}
@@ -999,6 +1200,10 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang)
mod_dir = this->Makefile->GetCurrentBinaryDirectory();
}
tdi["module-dir"] = mod_dir;
+ tdi["submodule-sep"] =
+ this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_SEP");
+ tdi["submodule-ext"] =
+ this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_EXT");
}
tdi["dir-cur-bld"] = this->Makefile->GetCurrentBinaryDirectory();
@@ -1010,26 +1215,69 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang)
std::vector<std::string> includes;
this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
lang, this->GetConfigName());
- for (std::vector<std::string>::iterator i = includes.begin();
- i != includes.end(); ++i) {
+ for (std::string const& i : includes) {
// Convert the include directories the same way we do for -I flags.
// See upstream ninja issue 1251.
- tdi_include_dirs.append(this->ConvertToNinjaPath(*i));
+ tdi_include_dirs.append(this->ConvertToNinjaPath(i));
}
Json::Value& tdi_linked_target_dirs = tdi["linked-target-dirs"] =
Json::arrayValue;
- std::vector<std::string> linked = this->GetLinkedTargetDirectories();
- for (std::vector<std::string>::iterator i = linked.begin();
- i != linked.end(); ++i) {
- tdi_linked_target_dirs.append(*i);
+ for (std::string const& l : this->GetLinkedTargetDirectories()) {
+ tdi_linked_target_dirs.append(l);
}
std::string const tdin = this->GetTargetDependInfoPath(lang);
- cmGeneratedFileStream tdif(tdin.c_str());
+ cmGeneratedFileStream tdif(tdin);
tdif << tdi;
}
+void cmNinjaTargetGenerator::EmitSwiftDependencyInfo(
+ cmSourceFile const* source)
+{
+ std::string const sourceFilePath =
+ this->ConvertToNinjaPath(this->GetSourceFilePath(source));
+ std::string const objectFilePath =
+ this->ConvertToNinjaPath(this->GetObjectFilePath(source));
+ std::string const swiftDepsPath = [source, objectFilePath]() -> std::string {
+ if (const char* name = source->GetProperty("Swift_DEPENDENCIES_FILE")) {
+ return name;
+ }
+ return objectFilePath + ".swiftdeps";
+ }();
+ std::string const swiftDiaPath = [source, objectFilePath]() -> std::string {
+ if (const char* name = source->GetProperty("Swift_DIAGNOSTICS_FILE")) {
+ return name;
+ }
+ return objectFilePath + ".dia";
+ }();
+ std::string const makeDepsPath = [this, source]() -> std::string {
+ cmLocalNinjaGenerator const* local = this->GetLocalGenerator();
+ std::string const objectFileName =
+ this->ConvertToNinjaPath(this->GetObjectFilePath(source));
+ std::string const objectFileDir =
+ cmSystemTools::GetFilenamePath(objectFileName);
+
+ if (this->Makefile->IsOn("CMAKE_Swift_DEPFLE_EXTNSION_REPLACE")) {
+ std::string dependFileName =
+ cmSystemTools::GetFilenameWithoutLastExtension(objectFileName) + ".d";
+ return local->ConvertToOutputFormat(objectFileDir + "/" + dependFileName,
+ cmOutputConverter::SHELL);
+ }
+ return local->ConvertToOutputFormat(objectFileName + ".d",
+ cmOutputConverter::SHELL);
+ }();
+
+ // build the source file mapping
+ // https://github.com/apple/swift/blob/master/docs/Driver.md#output-file-maps
+ Json::Value entry = Json::Value(Json::objectValue);
+ entry["object"] = objectFilePath;
+ entry["dependencies"] = makeDepsPath;
+ entry["swift-dependencies"] = swiftDepsPath;
+ entry["diagnostics"] = swiftDiaPath;
+ SwiftOutputMap[sourceFilePath] = entry;
+}
+
void cmNinjaTargetGenerator::ExportObjectCompileCommand(
std::string const& language, std::string const& sourceFileName,
std::string const& objectDir, std::string const& objectFileName,
@@ -1045,11 +1293,12 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
std::string escapedSourceFileName = sourceFileName;
- if (!cmSystemTools::FileIsFullPath(sourceFileName.c_str())) {
- escapedSourceFileName = cmSystemTools::CollapseFullPath(
- escapedSourceFileName, this->GetGlobalGenerator()
- ->GetCMakeInstance()
- ->GetHomeOutputDirectory());
+ if (!cmSystemTools::FileIsFullPath(sourceFileName)) {
+ escapedSourceFileName =
+ cmSystemTools::CollapseFullPath(escapedSourceFileName,
+ this->GetGlobalGenerator()
+ ->GetCMakeInstance()
+ ->GetHomeOutputDirectory());
}
escapedSourceFileName = this->LocalGenerator->ConvertToOutputFormat(
@@ -1069,31 +1318,29 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
std::string cmdVar;
if (this->GeneratorTarget->GetPropertyAsBool(
"CUDA_SEPARABLE_COMPILATION")) {
- cmdVar = std::string("CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION");
+ cmdVar = "CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION";
} else if (this->GeneratorTarget->GetPropertyAsBool(
"CUDA_PTX_COMPILATION")) {
- cmdVar = std::string("CMAKE_CUDA_COMPILE_PTX_COMPILATION");
+ cmdVar = "CMAKE_CUDA_COMPILE_PTX_COMPILATION";
} else {
- cmdVar = std::string("CMAKE_CUDA_COMPILE_WHOLE_COMPILATION");
+ cmdVar = "CMAKE_CUDA_COMPILE_WHOLE_COMPILATION";
}
- std::string compileCmd =
+ const std::string& compileCmd =
this->GetMakefile()->GetRequiredDefinition(cmdVar);
- cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
+ cmExpandList(compileCmd, compileCmds);
} else {
- const std::string cmdVar =
- std::string("CMAKE_") + language + "_COMPILE_OBJECT";
- std::string compileCmd =
+ const std::string cmdVar = "CMAKE_" + language + "_COMPILE_OBJECT";
+ const std::string& compileCmd =
this->GetMakefile()->GetRequiredDefinition(cmdVar);
- cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
+ cmExpandList(compileCmd, compileCmds);
}
- CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander(
+ std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->GetLocalGenerator()->CreateRulePlaceholderExpander());
- for (std::vector<std::string>::iterator i = compileCmds.begin();
- i != compileCmds.end(); ++i) {
+ for (std::string& i : compileCmds) {
// no launcher for CMAKE_EXPORT_COMPILE_COMMANDS
- rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), *i,
+ rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), i,
compileObjectVars);
}
@@ -1103,19 +1350,39 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine, sourceFileName);
}
+void cmNinjaTargetGenerator::AdditionalCleanFiles()
+{
+ if (const char* prop_value =
+ this->GeneratorTarget->GetProperty("ADDITIONAL_CLEAN_FILES")) {
+ cmLocalNinjaGenerator* lg = this->LocalGenerator;
+ std::vector<std::string> cleanFiles;
+ cmExpandList(cmGeneratorExpression::Evaluate(
+ prop_value, lg,
+ this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"),
+ this->GeneratorTarget),
+ cleanFiles);
+ std::string const& binaryDir = lg->GetCurrentBinaryDirectory();
+ cmGlobalNinjaGenerator* gg = lg->GetGlobalNinjaGenerator();
+ for (std::string const& cleanFile : cleanFiles) {
+ // Support relative paths
+ gg->AddAdditionalCleanFile(
+ cmSystemTools::CollapseFullPath(cleanFile, binaryDir));
+ }
+ }
+}
+
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 =
- std::string(gg->GetCMakeInstance()->GetHomeOutputDirectory());
+ std::string fullPath = gg->GetCMakeInstance()->GetHomeOutputDirectory();
// Also ensures their is a trailing slash.
gg->StripNinjaOutputPathPrefixAsSuffix(fullPath);
fullPath += path;
- cmSystemTools::MakeDirectory(fullPath.c_str());
+ cmSystemTools::MakeDirectory(fullPath);
}
}
@@ -1141,9 +1408,8 @@ void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()(
input = this->Generator->GetGlobalGenerator()->ConvertToNinjaPath(input);
// Get the output file location.
- std::string output = macdir;
- output += "/";
- output += cmSystemTools::GetFilenameName(input);
+ std::string output =
+ cmStrCat(macdir, '/', cmSystemTools::GetFilenameName(input));
output = this->Generator->GetGlobalGenerator()->ConvertToNinjaPath(output);
// Write a build statement to copy the content into the bundle.
@@ -1151,7 +1417,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 5eb7a9a49..4627bcdc6 100644
--- a/Source/cmNinjaTargetGenerator.h
+++ b/Source/cmNinjaTargetGenerator.h
@@ -3,17 +3,21 @@
#ifndef cmNinjaTargetGenerator_h
#define cmNinjaTargetGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "cm_jsoncpp_value.h"
#include "cmCommonTargetGenerator.h"
#include "cmGlobalNinjaGenerator.h"
#include "cmNinjaTypes.h"
#include "cmOSXBundleGenerator.h"
-#include <set>
-#include <string>
-#include <vector>
-
class cmCustomCommand;
class cmGeneratedFileStream;
class cmGeneratorTarget;
@@ -25,13 +29,14 @@ class cmNinjaTargetGenerator : public cmCommonTargetGenerator
{
public:
/// Create a cmNinjaTargetGenerator according to the @a target's type.
- static cmNinjaTargetGenerator* New(cmGeneratorTarget* target);
+ static std::unique_ptr<cmNinjaTargetGenerator> New(
+ cmGeneratorTarget* target);
/// Build a NinjaTargetGenerator.
cmNinjaTargetGenerator(cmGeneratorTarget* target);
/// Destructor.
- ~cmNinjaTargetGenerator() CM_OVERRIDE;
+ ~cmNinjaTargetGenerator() override;
virtual void Generate() = 0;
@@ -64,6 +69,8 @@ protected:
bool NeedExplicitPreprocessing(std::string const& lang) const;
std::string LanguageDyndepRule(std::string const& lang) const;
bool NeedDyndep(std::string const& lang) const;
+ bool UsePreprocessedSource(std::string const& lang) const;
+ bool CompilePreprocessedSourceWithDefines(std::string const& lang) const;
std::string OrderDependsTargetForTarget();
@@ -77,12 +84,14 @@ protected:
std::string ComputeFlagsForObject(cmSourceFile const* source,
const std::string& language);
- void AddIncludeFlags(std::string& flags,
- std::string const& lang) CM_OVERRIDE;
+ void AddIncludeFlags(std::string& flags, std::string const& lang) override;
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);
@@ -93,7 +102,7 @@ protected:
}
/// @return the list of link dependency for the given target @a target.
- cmNinjaDeps ComputeLinkDeps() const;
+ cmNinjaDeps ComputeLinkDeps(const std::string& linkLanguage) const;
/// @return the source file path for the given @a source.
std::string GetSourceFilePath(cmSourceFile const* source) const;
@@ -122,18 +131,22 @@ protected:
void WriteObjectBuildStatement(cmSourceFile const* source);
void WriteTargetDependInfo(std::string const& lang);
+ void EmitSwiftDependencyInfo(cmSourceFile const* source);
+
void ExportObjectCompileCommand(
std::string const& language, std::string const& sourceFileName,
std::string const& objectDir, std::string const& objectFileName,
std::string const& objectFileDir, std::string const& flags,
std::string const& defines, std::string const& includes);
+ void AdditionalCleanFiles();
+
cmNinjaDeps GetObjects() const { return this->Objects; }
void EnsureDirectoryExists(const std::string& dir) const;
void EnsureParentDirectoryExists(const std::string& path) const;
- // write rules for Mac OS X Application Bundle content.
+ // write rules for macOS Application Bundle content.
struct MacOSXContentGeneratorType
: cmOSXBundleGenerator::MacOSXContentGeneratorType
{
@@ -142,17 +155,16 @@ protected:
{
}
- void operator()(cmSourceFile const& source,
- const char* pkgloc) CM_OVERRIDE;
+ void operator()(cmSourceFile const& source, const char* pkgloc) override;
private:
cmNinjaTargetGenerator* Generator;
};
friend struct MacOSXContentGeneratorType;
- MacOSXContentGeneratorType* MacOSXContentGenerator;
+ std::unique_ptr<MacOSXContentGeneratorType> MacOSXContentGenerator;
// Properly initialized by sub-classes.
- cmOSXBundleGenerator* OSXBundleGenerator;
+ std::unique_ptr<cmOSXBundleGenerator> OSXBundleGenerator;
std::set<std::string> MacContentFolders;
void addPoolNinjaVariable(const std::string& pool_property,
@@ -164,7 +176,10 @@ private:
cmLocalNinjaGenerator* LocalGenerator;
/// List of object files for this target.
cmNinjaDeps Objects;
- cmNinjaDeps DDIFiles; // TODO: Make per-language.
+ // Fortran Support
+ std::map<std::string, cmNinjaDeps> DDIFiles;
+ // Swift Support
+ Json::Value SwiftOutputMap;
std::vector<cmCustomCommand const*> CustomCommands;
cmNinjaDeps ExtraFiles;
};
diff --git a/Source/cmNinjaTypes.h b/Source/cmNinjaTypes.h
index ec435d9dd..bd0e83fa1 100644
--- a/Source/cmNinjaTypes.h
+++ b/Source/cmNinjaTypes.h
@@ -6,7 +6,9 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
+#include <set>
#include <string>
+#include <utility>
#include <vector>
enum cmNinjaTargetDepends
@@ -15,7 +17,48 @@ enum cmNinjaTargetDepends
DependOnTargetOrdering
};
-typedef std::vector<std::string> cmNinjaDeps;
-typedef std::map<std::string, std::string> cmNinjaVars;
+using cmNinjaDeps = std::vector<std::string>;
+using cmNinjaOuts = std::set<std::string>;
+using cmNinjaVars = std::map<std::string, std::string>;
+
+class cmNinjaRule
+{
+public:
+ cmNinjaRule(std::string name)
+ : Name(std::move(name))
+ {
+ }
+
+ std::string Name;
+ std::string Command;
+ std::string Description;
+ std::string Comment;
+ std::string DepFile;
+ std::string DepType;
+ std::string RspFile;
+ std::string RspContent;
+ std::string Restat;
+ bool Generator = false;
+};
+
+class cmNinjaBuild
+{
+public:
+ cmNinjaBuild() = default;
+ cmNinjaBuild(std::string rule)
+ : Rule(std::move(rule))
+ {
+ }
+
+ std::string Comment;
+ std::string Rule;
+ cmNinjaDeps Outputs;
+ cmNinjaDeps ImplicitOuts;
+ cmNinjaDeps ExplicitDeps;
+ cmNinjaDeps ImplicitDeps;
+ cmNinjaDeps OrderOnlyDeps;
+ cmNinjaVars Variables;
+ std::string RspFile;
+};
#endif // ! cmNinjaTypes_h
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index 500ff4a45..5259037bf 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -2,6 +2,13 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmNinjaUtilityTargetGenerator.h"
+#include <algorithm>
+#include <array>
+#include <iterator>
+#include <string>
+#include <utility>
+#include <vector>
+
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
@@ -13,13 +20,8 @@
#include "cmOutputConverter.h"
#include "cmSourceFile.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmake.h"
-
-#include <algorithm>
-#include <iterator>
-#include <string>
-#include <vector>
cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator(
cmGeneratorTarget* target)
@@ -27,83 +29,78 @@ cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator(
{
}
-cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator()
-{
-}
+cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() = default;
void cmNinjaUtilityTargetGenerator::Generate()
{
+ cmGlobalNinjaGenerator* gg = this->GetGlobalGenerator();
+ cmLocalNinjaGenerator* lg = this->GetLocalGenerator();
+ cmGeneratorTarget* genTarget = this->GetGeneratorTarget();
+
std::string utilCommandName =
- this->GetLocalGenerator()->GetCurrentBinaryDirectory();
- utilCommandName += cmake::GetCMakeFilesDirectory();
- utilCommandName += "/";
- utilCommandName += this->GetTargetName() + ".util";
+ cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles/",
+ this->GetTargetName(), ".util");
utilCommandName = this->ConvertToNinjaPath(utilCommandName);
+ cmNinjaBuild phonyBuild("phony");
std::vector<std::string> commands;
- cmNinjaDeps deps, outputs, util_outputs(1, utilCommandName);
-
- const std::vector<cmCustomCommand>* cmdLists[2] = {
- &this->GetGeneratorTarget()->GetPreBuildCommands(),
- &this->GetGeneratorTarget()->GetPostBuildCommands()
- };
+ cmNinjaDeps deps;
+ cmNinjaDeps util_outputs(1, utilCommandName);
bool uses_terminal = false;
-
- for (unsigned i = 0; i != 2; ++i) {
- for (std::vector<cmCustomCommand>::const_iterator ci =
- cmdLists[i]->begin();
- ci != cmdLists[i]->end(); ++ci) {
- cmCustomCommandGenerator ccg(*ci, this->GetConfigName(),
- this->GetLocalGenerator());
- this->GetLocalGenerator()->AppendCustomCommandDeps(ccg, deps);
- this->GetLocalGenerator()->AppendCustomCommandLines(ccg, commands);
- std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
- std::transform(ccByproducts.begin(), ccByproducts.end(),
- std::back_inserter(util_outputs), MapToNinjaPath());
- if (ci->GetUsesTerminal()) {
- uses_terminal = true;
+ {
+ std::array<std::vector<cmCustomCommand> const*, 2> const cmdLists = {
+ { &genTarget->GetPreBuildCommands(), &genTarget->GetPostBuildCommands() }
+ };
+
+ for (std::vector<cmCustomCommand> const* cmdList : cmdLists) {
+ for (cmCustomCommand const& ci : *cmdList) {
+ cmCustomCommandGenerator ccg(ci, this->GetConfigName(), lg);
+ lg->AppendCustomCommandDeps(ccg, deps);
+ lg->AppendCustomCommandLines(ccg, commands);
+ std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
+ std::transform(ccByproducts.begin(), ccByproducts.end(),
+ std::back_inserter(util_outputs), MapToNinjaPath());
+ if (ci.GetUsesTerminal()) {
+ uses_terminal = true;
+ }
}
}
}
- std::vector<cmSourceFile*> sources;
- std::string config =
- this->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
- this->GetGeneratorTarget()->GetSourceFiles(sources, config);
- for (std::vector<cmSourceFile*>::const_iterator source = sources.begin();
- source != sources.end(); ++source) {
- if (cmCustomCommand* cc = (*source)->GetCustomCommand()) {
- cmCustomCommandGenerator ccg(*cc, this->GetConfigName(),
- this->GetLocalGenerator());
- this->GetLocalGenerator()->AddCustomCommandTarget(
- cc, this->GetGeneratorTarget());
-
- // Depend on all custom command outputs.
- const std::vector<std::string>& ccOutputs = ccg.GetOutputs();
- const std::vector<std::string>& ccByproducts = ccg.GetByproducts();
- std::transform(ccOutputs.begin(), ccOutputs.end(),
- std::back_inserter(deps), MapToNinjaPath());
- std::transform(ccByproducts.begin(), ccByproducts.end(),
- std::back_inserter(deps), MapToNinjaPath());
+ {
+ std::string const& config =
+ this->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ std::vector<cmSourceFile*> sources;
+ genTarget->GetSourceFiles(sources, config);
+ for (cmSourceFile const* source : sources) {
+ if (cmCustomCommand const* cc = source->GetCustomCommand()) {
+ cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), lg);
+ lg->AddCustomCommandTarget(cc, genTarget);
+
+ // Depend on all custom command outputs.
+ const std::vector<std::string>& ccOutputs = ccg.GetOutputs();
+ const std::vector<std::string>& ccByproducts = ccg.GetByproducts();
+ std::transform(ccOutputs.begin(), ccOutputs.end(),
+ std::back_inserter(deps), MapToNinjaPath());
+ std::transform(ccByproducts.begin(), ccByproducts.end(),
+ std::back_inserter(deps), MapToNinjaPath());
+ }
}
}
- this->GetLocalGenerator()->AppendTargetOutputs(this->GetGeneratorTarget(),
- outputs);
- this->GetLocalGenerator()->AppendTargetDepends(this->GetGeneratorTarget(),
- deps);
+ lg->AppendTargetOutputs(genTarget, phonyBuild.Outputs);
+ lg->AppendTargetDepends(genTarget, deps);
if (commands.empty()) {
- this->GetGlobalGenerator()->WritePhonyBuild(
- this->GetBuildFileStream(),
- "Utility command for " + this->GetTargetName(), outputs, deps);
+ phonyBuild.Comment = "Utility command for " + this->GetTargetName();
+ phonyBuild.ExplicitDeps = std::move(deps);
+ gg->WriteBuild(this->GetBuildFileStream(), phonyBuild);
} else {
std::string command =
- this->GetLocalGenerator()->BuildCommandLine(commands);
- const char* echoStr =
- this->GetGeneratorTarget()->GetProperty("EchoString");
+ lg->BuildCommandLine(commands, "utility", this->GeneratorTarget);
std::string desc;
+ const char* echoStr = genTarget->GetProperty("EchoString");
if (echoStr) {
desc = echoStr;
} else {
@@ -114,45 +111,38 @@ void cmNinjaUtilityTargetGenerator::Generate()
// makefile vars.
cmSystemTools::ReplaceString(
command, "$(CMAKE_SOURCE_DIR)",
- this->GetLocalGenerator()
- ->ConvertToOutputFormat(
- this->GetLocalGenerator()->GetSourceDirectory(),
- cmOutputConverter::SHELL)
- .c_str());
+ lg->ConvertToOutputFormat(lg->GetSourceDirectory(),
+ cmOutputConverter::SHELL));
cmSystemTools::ReplaceString(
command, "$(CMAKE_BINARY_DIR)",
- this->GetLocalGenerator()
- ->ConvertToOutputFormat(
- this->GetLocalGenerator()->GetBinaryDirectory(),
- cmOutputConverter::SHELL)
- .c_str());
+ lg->ConvertToOutputFormat(lg->GetBinaryDirectory(),
+ cmOutputConverter::SHELL));
cmSystemTools::ReplaceString(command, "$(ARGS)", "");
if (command.find('$') != std::string::npos) {
return;
}
- for (cmNinjaDeps::const_iterator oi = util_outputs.begin(),
- oe = util_outputs.end();
- oi != oe; ++oi) {
- this->GetGlobalGenerator()->SeenCustomCommandOutput(*oi);
+ for (std::string const& util_output : util_outputs) {
+ gg->SeenCustomCommandOutput(util_output);
}
- this->GetGlobalGenerator()->WriteCustomCommandBuild(
- command, desc, "Utility command for " + this->GetTargetName(),
- /*depfile*/ "", uses_terminal,
- /*restat*/ true, util_outputs, deps);
+ gg->WriteCustomCommandBuild(command, desc,
+ "Utility command for " + this->GetTargetName(),
+ /*depfile*/ "", /*job_pool*/ "", uses_terminal,
+ /*restat*/ true, util_outputs, deps);
- this->GetGlobalGenerator()->WritePhonyBuild(
- this->GetBuildFileStream(), "", outputs,
- cmNinjaDeps(1, utilCommandName));
+ phonyBuild.ExplicitDeps.push_back(utilCommandName);
+ gg->WriteBuild(this->GetBuildFileStream(), phonyBuild);
}
+ // Find ADDITIONAL_CLEAN_FILES
+ this->AdditionalCleanFiles();
+
// Add an alias for the logical target name regardless of what directory
// contains it. Skip this for GLOBAL_TARGET because they are meant to
// be per-directory and have one at the top-level anyway.
- if (this->GetGeneratorTarget()->GetType() != cmStateEnums::GLOBAL_TARGET) {
- this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
- this->GetGeneratorTarget());
+ if (genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) {
+ gg->AddTargetAlias(this->GetTargetName(), genTarget);
}
}
diff --git a/Source/cmNinjaUtilityTargetGenerator.h b/Source/cmNinjaUtilityTargetGenerator.h
index 9256e369c..01cc4595f 100644
--- a/Source/cmNinjaUtilityTargetGenerator.h
+++ b/Source/cmNinjaUtilityTargetGenerator.h
@@ -3,7 +3,7 @@
#ifndef cmNinjaUtilityTargetGenerator_h
#define cmNinjaUtilityTargetGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include "cmNinjaTargetGenerator.h"
@@ -13,9 +13,9 @@ class cmNinjaUtilityTargetGenerator : public cmNinjaTargetGenerator
{
public:
cmNinjaUtilityTargetGenerator(cmGeneratorTarget* target);
- ~cmNinjaUtilityTargetGenerator() CM_OVERRIDE;
+ ~cmNinjaUtilityTargetGenerator() override;
- void Generate() CM_OVERRIDE;
+ void Generate() override;
};
#endif // ! cmNinjaUtilityTargetGenerator_h
diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx
index beddc6e6d..a6f4e512e 100644
--- a/Source/cmOSXBundleGenerator.cxx
+++ b/Source/cmOSXBundleGenerator.cxx
@@ -2,26 +2,26 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmOSXBundleGenerator.h"
-#include "cmConfigure.h"
+#include <cassert>
+#include <utility>
#include "cmGeneratorTarget.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
-#include <cassert>
-
class cmSourceFile;
cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target,
- const std::string& configName)
+ std::string configName)
: GT(target)
, Makefile(target->Target->GetMakefile())
, LocalGenerator(target->GetLocalGenerator())
- , ConfigName(configName)
- , MacContentFolders(CM_NULLPTR)
+ , ConfigName(std::move(configName))
+ , MacContentFolders(nullptr)
{
if (this->MustSkip()) {
return;
@@ -41,22 +41,21 @@ void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName,
}
// Compute bundle directory names.
- std::string out = outpath;
- out += "/";
- out += this->GT->GetAppBundleDirectory(this->ConfigName,
- cmGeneratorTarget::FullLevel);
- cmSystemTools::MakeDirectory(out.c_str());
+ std::string out =
+ cmStrCat(outpath, '/',
+ this->GT->GetAppBundleDirectory(this->ConfigName,
+ cmGeneratorTarget::FullLevel));
+ cmSystemTools::MakeDirectory(out);
this->Makefile->AddCMakeOutputFile(out);
// Configure the Info.plist file. Note that it needs the executable name
// to be set.
- std::string plist = outpath;
- plist += "/";
- plist += this->GT->GetAppBundleDirectory(this->ConfigName,
- cmGeneratorTarget::ContentLevel);
- plist += "/Info.plist";
- this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName,
- plist.c_str());
+ std::string plist =
+ cmStrCat(outpath, '/',
+ this->GT->GetAppBundleDirectory(this->ConfigName,
+ cmGeneratorTarget::ContentLevel),
+ "/Info.plist");
+ this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName, plist);
this->Makefile->AddCMakeOutputFile(plist);
outpath = out;
}
@@ -71,10 +70,11 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
assert(this->MacContentFolders);
// Compute the location of the top-level foo.framework directory.
- std::string contentdir = outpath + "/" +
- this->GT->GetFrameworkDirectory(this->ConfigName,
- cmGeneratorTarget::ContentLevel);
- contentdir += "/";
+ std::string contentdir =
+ cmStrCat(outpath, '/',
+ this->GT->GetFrameworkDirectory(this->ConfigName,
+ cmGeneratorTarget::ContentLevel),
+ '/');
std::string newoutpath = outpath + "/" +
this->GT->GetFrameworkDirectory(this->ConfigName,
@@ -84,18 +84,17 @@ 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";
}
plist += "/Info.plist";
std::string name = cmSystemTools::GetFilenameName(targetName);
- this->LocalGenerator->GenerateFrameworkInfoPList(this->GT, name,
- plist.c_str());
+ this->LocalGenerator->GenerateFrameworkInfoPList(this->GT, name, plist);
// Generate Versions directory only for MacOSX frameworks
- if (this->Makefile->PlatformIsAppleIos()) {
+ if (this->Makefile->PlatformIsAppleEmbedded()) {
return;
}
@@ -105,26 +104,22 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
std::string newName;
// Make foo.framework/Versions
- std::string versions = contentdir;
- versions += "Versions";
- cmSystemTools::MakeDirectory(versions.c_str());
+ std::string versions = cmStrCat(contentdir, "Versions");
+ cmSystemTools::MakeDirectory(versions);
// Make foo.framework/Versions/version
- cmSystemTools::MakeDirectory(newoutpath.c_str());
+ cmSystemTools::MakeDirectory(newoutpath);
// Current -> version
oldName = frameworkVersion;
- newName = versions;
- newName += "/Current";
+ newName = cmStrCat(versions, "/Current");
cmSystemTools::RemoveFile(newName);
cmSystemTools::CreateSymlink(oldName, newName);
this->Makefile->AddCMakeOutputFile(newName);
// foo -> Versions/Current/foo
- oldName = "Versions/Current/";
- oldName += name;
- newName = contentdir;
- newName += name;
+ oldName = cmStrCat("Versions/Current/", name);
+ newName = cmStrCat(contentdir, name);
cmSystemTools::RemoveFile(newName);
cmSystemTools::CreateSymlink(oldName, newName);
this->Makefile->AddCMakeOutputFile(newName);
@@ -133,8 +128,7 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
if (this->MacContentFolders->find("Resources") !=
this->MacContentFolders->end()) {
oldName = "Versions/Current/Resources";
- newName = contentdir;
- newName += "Resources";
+ newName = cmStrCat(contentdir, "Resources");
cmSystemTools::RemoveFile(newName);
cmSystemTools::CreateSymlink(oldName, newName);
this->Makefile->AddCMakeOutputFile(newName);
@@ -144,8 +138,7 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
if (this->MacContentFolders->find("Headers") !=
this->MacContentFolders->end()) {
oldName = "Versions/Current/Headers";
- newName = contentdir;
- newName += "Headers";
+ newName = cmStrCat(contentdir, "Headers");
cmSystemTools::RemoveFile(newName);
cmSystemTools::CreateSymlink(oldName, newName);
this->Makefile->AddCMakeOutputFile(newName);
@@ -155,8 +148,7 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
if (this->MacContentFolders->find("PrivateHeaders") !=
this->MacContentFolders->end()) {
oldName = "Versions/Current/PrivateHeaders";
- newName = contentdir;
- newName += "PrivateHeaders";
+ newName = cmStrCat(contentdir, "PrivateHeaders");
cmSystemTools::RemoveFile(newName);
cmSystemTools::CreateSymlink(oldName, newName);
this->Makefile->AddCMakeOutputFile(newName);
@@ -171,21 +163,22 @@ void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName,
}
// Compute bundle directory names.
- std::string out = root;
- out += "/";
- out += this->GT->GetCFBundleDirectory(this->ConfigName,
- cmGeneratorTarget::FullLevel);
- cmSystemTools::MakeDirectory(out.c_str());
+ std::string out =
+ cmStrCat(root, '/',
+ this->GT->GetCFBundleDirectory(this->ConfigName,
+ cmGeneratorTarget::FullLevel));
+ cmSystemTools::MakeDirectory(out);
this->Makefile->AddCMakeOutputFile(out);
// Configure the Info.plist file. Note that it needs the executable name
// to be set.
- std::string plist = root + "/" +
- this->GT->GetCFBundleDirectory(this->ConfigName,
- cmGeneratorTarget::ContentLevel);
- plist += "/Info.plist";
+ std::string plist =
+ cmStrCat(root, '/',
+ this->GT->GetCFBundleDirectory(this->ConfigName,
+ cmGeneratorTarget::ContentLevel),
+ "/Info.plist");
std::string name = cmSystemTools::GetFilenameName(targetName);
- this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist.c_str());
+ this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist);
this->Makefile->AddCMakeOutputFile(plist);
}
@@ -197,12 +190,11 @@ void cmOSXBundleGenerator::GenerateMacOSXContentStatements(
return;
}
- for (std::vector<cmSourceFile const*>::const_iterator si = sources.begin();
- si != sources.end(); ++si) {
+ for (cmSourceFile const* source : sources) {
cmGeneratorTarget::SourceFileFlags tsFlags =
- this->GT->GetTargetSourceFileFlags(*si);
+ this->GT->GetTargetSourceFileFlags(source);
if (tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) {
- (*generator)(**si, tsFlags.MacFolder);
+ (*generator)(*source, tsFlags.MacFolder);
}
}
}
@@ -212,11 +204,11 @@ std::string cmOSXBundleGenerator::InitMacOSXContentDirectory(
{
// Construct the full path to the content subdirectory.
- std::string macdir = this->GT->GetMacContentDirectory(
- this->ConfigName, cmStateEnums::RuntimeBinaryArtifact);
- macdir += "/";
- macdir += pkgloc;
- cmSystemTools::MakeDirectory(macdir.c_str());
+ std::string macdir =
+ cmStrCat(this->GT->GetMacContentDirectory(
+ this->ConfigName, cmStateEnums::RuntimeBinaryArtifact),
+ '/', pkgloc);
+ cmSystemTools::MakeDirectory(macdir);
// Record use of this content location. Only the first level
// directory is needed.
diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h
index be7e932f9..3dea6cc8a 100644
--- a/Source/cmOSXBundleGenerator.h
+++ b/Source/cmOSXBundleGenerator.h
@@ -17,8 +17,7 @@ class cmSourceFile;
class cmOSXBundleGenerator
{
public:
- cmOSXBundleGenerator(cmGeneratorTarget* target,
- const std::string& configName);
+ cmOSXBundleGenerator(cmGeneratorTarget* target, std::string configName);
// create an app bundle at a given root, and return
// the directory within the bundle that contains the executable
@@ -32,7 +31,7 @@ public:
struct MacOSXContentGeneratorType
{
- virtual ~MacOSXContentGeneratorType() {}
+ virtual ~MacOSXContentGeneratorType() = default;
virtual void operator()(cmSourceFile const& source,
const char* pkgloc) = 0;
};
diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx
index 00a2d2bce..22e59ac43 100644
--- a/Source/cmOptionCommand.cxx
+++ b/Source/cmOptionCommand.cxx
@@ -2,55 +2,84 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmOptionCommand.h"
-#include "cmAlgorithms.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmPolicies.h"
#include "cmState.h"
+#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
-#include "cmSystemTools.h"
-
-class cmExecutionStatus;
+#include "cmStringAlgorithms.h"
// cmOptionCommand
-bool cmOptionCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmOptionCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- bool argError = false;
- if (args.size() < 2) {
- argError = true;
- }
- // for VTK 4.0 we have to support the option command with more than 3
- // arguments if CMAKE_MINIMUM_REQUIRED_VERSION is not defined, if
- // CMAKE_MINIMUM_REQUIRED_VERSION is defined, then we can have stricter
- // checking.
- if (this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
- if (args.size() > 3) {
- argError = true;
- }
- }
+ const bool argError = (args.size() < 2) || (args.size() > 3);
if (argError) {
- std::string m = "called with incorrect number of arguments: ";
- m += cmJoin(args, " ");
- this->SetError(m);
+ std::string m = cmStrCat("called with incorrect number of arguments: ",
+ cmJoin(args, " "));
+ status.SetError(m);
return false;
}
- std::string initialValue = "Off";
- // Now check and see if the value has been stored in the cache
- // already, if so use that value and don't look for the program
- cmState* state = this->Makefile->GetState();
- const char* existingValue = state->GetCacheEntryValue(args[0]);
- if (existingValue) {
- if (state->GetCacheEntryType(args[0]) != cmStateEnums::UNINITIALIZED) {
- state->SetCacheEntryProperty(args[0], "HELPSTRING", args[1]);
- return true;
+ // Determine the state of the option policy
+ bool checkAndWarn = false;
+ {
+ auto policyStatus =
+ status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0077);
+ const auto* existsBeforeSet =
+ status.GetMakefile().GetStateSnapshot().GetDefinition(args[0]);
+ switch (policyStatus) {
+ case cmPolicies::WARN:
+ checkAndWarn = (existsBeforeSet != nullptr);
+ break;
+ case cmPolicies::OLD:
+ // OLD behavior does not warn.
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW: {
+ // See if a local variable with this name already exists.
+ // If so we ignore the option command.
+ if (existsBeforeSet) {
+ return true;
+ }
+ } break;
}
- initialValue = existingValue;
}
+
+ // See if a cache variable with this name already exists
+ // If so just make sure the doc state is correct
+ cmState* state = status.GetMakefile().GetState();
+ const char* existingValue = state->GetCacheEntryValue(args[0]);
+ if (existingValue &&
+ (state->GetCacheEntryType(args[0]) != cmStateEnums::UNINITIALIZED)) {
+ state->SetCacheEntryProperty(args[0], "HELPSTRING", args[1]);
+ return true;
+ }
+
+ // Nothing in the cache so add it
+ std::string initialValue = existingValue ? existingValue : "Off";
if (args.size() == 3) {
initialValue = args[2];
}
- bool init = cmSystemTools::IsOn(initialValue.c_str());
- this->Makefile->AddCacheDefinition(args[0], init ? "ON" : "OFF",
- args[1].c_str(), cmStateEnums::BOOL);
+ bool init = cmIsOn(initialValue);
+ status.GetMakefile().AddCacheDefinition(args[0], init ? "ON" : "OFF",
+ args[1].c_str(), cmStateEnums::BOOL);
+
+ if (checkAndWarn) {
+ const auto* existsAfterSet =
+ status.GetMakefile().GetStateSnapshot().GetDefinition(args[0]);
+ if (!existsAfterSet) {
+ status.GetMakefile().IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0077),
+ "\n"
+ "For compatibility with older versions of CMake, option "
+ "is clearing the normal variable '",
+ args[0], "'."));
+ }
+ }
return true;
}
diff --git a/Source/cmOptionCommand.h b/Source/cmOptionCommand.h
index 634e3a824..cbd1cb864 100644
--- a/Source/cmOptionCommand.h
+++ b/Source/cmOptionCommand.h
@@ -3,34 +3,18 @@
#ifndef cmOptionCommand_h
#define cmOptionCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmOptionCommand
+/**
* \brief Provide an option to the user
*
* cmOptionCommand provides an option for the user to select
*/
-class cmOptionCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmOptionCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
-
+bool cmOptionCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx
index 333e3134c..073222cd8 100644
--- a/Source/cmOrderDirectories.cxx
+++ b/Source/cmOrderDirectories.cxx
@@ -2,17 +2,20 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmOrderDirectories.h"
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <sstream>
+#include <vector>
+
#include "cmAlgorithms.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
-#include <algorithm>
-#include <assert.h>
-#include <functional>
-#include <sstream>
-
/*
Directory ordering computation.
- Useful to compute a safe runtime library path order
@@ -47,7 +50,7 @@ public:
this->FileName = cmSystemTools::GetFilenameName(file);
}
}
- virtual ~cmOrderDirectoriesConstraint() {}
+ virtual ~cmOrderDirectoriesConstraint() = default;
void AddDirectory()
{
@@ -75,9 +78,8 @@ public:
void FindImplicitConflicts(std::ostringstream& w)
{
bool first = true;
- for (unsigned int i = 0; i < this->OD->OriginalDirectories.size(); ++i) {
+ for (std::string const& dir : this->OD->OriginalDirectories) {
// Check if this directory conflicts with the entry.
- std::string const& dir = this->OD->OriginalDirectories[i];
if (dir != this->Directory &&
cmSystemTools::GetRealPath(dir) !=
cmSystemTools::GetRealPath(this->Directory) &&
@@ -116,10 +118,8 @@ bool cmOrderDirectoriesConstraint::FileMayConflict(std::string const& dir,
std::string const& name)
{
// Check if the file exists on disk.
- std::string file = dir;
- file += "/";
- file += name;
- if (cmSystemTools::FileExists(file.c_str(), true)) {
+ std::string file = cmStrCat(dir, '/', name);
+ 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);
@@ -128,7 +128,7 @@ bool cmOrderDirectoriesConstraint::FileMayConflict(std::string const& dir,
// Check if the file will be built by cmake.
std::set<std::string> const& files =
(this->GlobalGenerator->GetDirectoryContent(dir, false));
- std::set<std::string>::const_iterator fi = files.find(name);
+ auto fi = files.find(name);
return fi != files.end();
}
@@ -150,7 +150,7 @@ public:
}
}
- void Report(std::ostream& e) CM_OVERRIDE
+ void Report(std::ostream& e) override
{
e << "runtime library [";
if (this->SOName.empty()) {
@@ -161,7 +161,7 @@ public:
e << "]";
}
- bool FindConflict(std::string const& dir) CM_OVERRIDE;
+ bool FindConflict(std::string const& dir) override;
private:
// The soname of the shared library if it is known.
@@ -186,9 +186,9 @@ bool cmOrderDirectoriesConstraintSOName::FindConflict(std::string const& dir)
// know the soname just look at all files that start with the
// file name. Usually the soname starts with the library name.
std::string base = this->FileName;
- std::set<std::string>::const_iterator first = files.lower_bound(base);
- ++base[base.size() - 1];
- std::set<std::string>::const_iterator last = files.upper_bound(base);
+ auto first = files.lower_bound(base);
+ ++base.back();
+ auto last = files.upper_bound(base);
if (first != last) {
return true;
}
@@ -205,12 +205,12 @@ public:
{
}
- void Report(std::ostream& e) CM_OVERRIDE
+ void Report(std::ostream& e) override
{
e << "link library [" << this->FileName << "]";
}
- bool FindConflict(std::string const& dir) CM_OVERRIDE;
+ bool FindConflict(std::string const& dir) override;
};
bool cmOrderDirectoriesConstraintLibrary::FindConflict(std::string const& dir)
@@ -226,12 +226,9 @@ bool cmOrderDirectoriesConstraintLibrary::FindConflict(std::string const& dir)
this->OD->RemoveLibraryExtension.find(this->FileName)) {
std::string lib = this->OD->RemoveLibraryExtension.match(1);
std::string ext = this->OD->RemoveLibraryExtension.match(2);
- for (std::vector<std::string>::iterator i =
- this->OD->LinkExtensions.begin();
- i != this->OD->LinkExtensions.end(); ++i) {
- if (*i != ext) {
- std::string fname = lib;
- fname += *i;
+ for (std::string const& LinkExtension : this->OD->LinkExtensions) {
+ if (LinkExtension != ext) {
+ std::string fname = cmStrCat(lib, LinkExtension);
if (this->FileMayConflict(dir, fname)) {
return true;
}
@@ -331,24 +328,21 @@ void cmOrderDirectories::AddLinkLibrary(std::string const& fullPath)
void cmOrderDirectories::AddUserDirectories(
std::vector<std::string> const& extra)
{
- this->UserDirectories.insert(this->UserDirectories.end(), extra.begin(),
- extra.end());
+ cmAppend(this->UserDirectories, extra);
}
void cmOrderDirectories::AddLanguageDirectories(
std::vector<std::string> const& dirs)
{
- this->LanguageDirectories.insert(this->LanguageDirectories.end(),
- dirs.begin(), dirs.end());
+ cmAppend(this->LanguageDirectories, dirs);
}
void cmOrderDirectories::SetImplicitDirectories(
std::set<std::string> const& implicitDirs)
{
this->ImplicitDirectories.clear();
- for (std::set<std::string>::const_iterator i = implicitDirs.begin();
- i != implicitDirs.end(); ++i) {
- this->ImplicitDirectories.insert(this->GetRealPath(*i));
+ for (std::string const& implicitDir : implicitDirs) {
+ this->ImplicitDirectories.insert(this->GetRealPath(implicitDir));
}
}
@@ -375,8 +369,8 @@ void cmOrderDirectories::CollectOriginalDirectories()
this->AddOriginalDirectories(this->UserDirectories);
// Add directories containing constraints.
- for (unsigned int i = 0; i < this->ConstraintEntries.size(); ++i) {
- this->ConstraintEntries[i]->AddDirectory();
+ for (cmOrderDirectoriesConstraint* entry : this->ConstraintEntries) {
+ entry->AddDirectory();
}
// Add language runtime directories last.
@@ -386,7 +380,7 @@ void cmOrderDirectories::CollectOriginalDirectories()
int cmOrderDirectories::AddOriginalDirectory(std::string const& dir)
{
// Add the runtime directory with a unique index.
- std::map<std::string, int>::iterator i = this->DirectoryIndex.find(dir);
+ auto i = this->DirectoryIndex.find(dir);
if (i == this->DirectoryIndex.end()) {
std::map<std::string, int>::value_type entry(
dir, static_cast<int>(this->OriginalDirectories.size()));
@@ -400,26 +394,25 @@ int cmOrderDirectories::AddOriginalDirectory(std::string const& dir)
void cmOrderDirectories::AddOriginalDirectories(
std::vector<std::string> const& dirs)
{
- for (std::vector<std::string>::const_iterator di = dirs.begin();
- di != dirs.end(); ++di) {
+ for (std::string const& dir : dirs) {
// We never explicitly specify implicit link directories.
- if (this->IsImplicitDirectory(*di)) {
+ if (this->IsImplicitDirectory(dir)) {
continue;
}
// Skip the empty string.
- if (di->empty()) {
+ if (dir.empty()) {
continue;
}
// Add this directory.
- this->AddOriginalDirectory(*di);
+ this->AddOriginalDirectory(dir);
}
}
struct cmOrderDirectoriesCompare
{
- typedef std::pair<int, int> ConflictPair;
+ using ConflictPair = std::pair<int, int>;
// The conflict pair is unique based on just the directory
// (first). The second element is only used for displaying
@@ -442,16 +435,14 @@ void cmOrderDirectories::FindConflicts()
}
// Clean up the conflict graph representation.
- for (std::vector<ConflictList>::iterator i = this->ConflictGraph.begin();
- i != this->ConflictGraph.end(); ++i) {
+ for (ConflictList& cl : this->ConflictGraph) {
// Sort the outgoing edges for each graph node so that the
// original order will be preserved as much as possible.
- std::sort(i->begin(), i->end());
+ std::sort(cl.begin(), cl.end());
// Make the edge list unique so cycle detection will be reliable.
- ConflictList::iterator last =
- std::unique(i->begin(), i->end(), cmOrderDirectoriesCompare());
- i->erase(last, i->end());
+ auto last = std::unique(cl.begin(), cl.end(), cmOrderDirectoriesCompare());
+ cl.erase(last, cl.end());
}
// Check items in implicit link directories.
@@ -463,25 +454,25 @@ void cmOrderDirectories::FindImplicitConflicts()
// Check for items in implicit link directories that have conflicts
// in the explicit directories.
std::ostringstream conflicts;
- for (unsigned int i = 0; i < this->ImplicitDirEntries.size(); ++i) {
- this->ImplicitDirEntries[i]->FindImplicitConflicts(conflicts);
+ for (cmOrderDirectoriesConstraint* entry : this->ImplicitDirEntries) {
+ entry->FindImplicitConflicts(conflicts);
}
// Skip warning if there were no conflicts.
- std::string text = conflicts.str();
+ std::string const text = conflicts.str();
if (text.empty()) {
return;
}
// Warn about the conflicts.
- std::ostringstream w;
- w << "Cannot generate a safe " << this->Purpose << " for target "
- << this->Target->GetName()
- << " because files in some directories may conflict with "
- << " libraries in implicit directories:\n"
- << text << "Some of these libraries may not be found correctly.";
this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
- cmake::WARNING, w.str(), this->Target->GetBacktrace());
+ MessageType::WARNING,
+ cmStrCat("Cannot generate a safe ", this->Purpose, " for target ",
+ this->Target->GetName(),
+ " because files in some directories may "
+ "conflict with libraries in implicit directories:\n",
+ text, "Some of these libraries may not be found correctly."),
+ this->Target->GetBacktrace());
}
void cmOrderDirectories::OrderDirectories()
@@ -515,8 +506,8 @@ void cmOrderDirectories::VisitDirectory(unsigned int i)
// Visit the neighbors of the node first.
ConflictList const& clist = this->ConflictGraph[i];
- for (ConflictList::const_iterator j = clist.begin(); j != clist.end(); ++j) {
- this->VisitDirectory(j->first);
+ for (ConflictPair const& j : clist) {
+ this->VisitDirectory(j.first);
}
// Now that all directories required to come before this one have
@@ -542,16 +533,15 @@ void cmOrderDirectories::DiagnoseCycle()
for (unsigned int i = 0; i < this->ConflictGraph.size(); ++i) {
ConflictList const& clist = this->ConflictGraph[i];
e << " dir " << i << " is [" << this->OriginalDirectories[i] << "]\n";
- for (ConflictList::const_iterator j = clist.begin(); j != clist.end();
- ++j) {
- e << " dir " << j->first << " must precede it due to ";
- this->ConstraintEntries[j->second]->Report(e);
+ for (ConflictPair const& j : clist) {
+ e << " dir " << j.first << " must precede it due to ";
+ this->ConstraintEntries[j.second]->Report(e);
e << "\n";
}
}
e << "Some of these libraries may not be found correctly.";
this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
- cmake::WARNING, e.str(), this->Target->GetBacktrace());
+ MessageType::WARNING, e.str(), this->Target->GetBacktrace());
}
bool cmOrderDirectories::IsSameDirectory(std::string const& l,
@@ -562,11 +552,10 @@ bool cmOrderDirectories::IsSameDirectory(std::string const& l,
std::string const& cmOrderDirectories::GetRealPath(std::string const& dir)
{
- std::map<std::string, std::string>::iterator i =
- this->RealPaths.lower_bound(dir);
+ auto i = this->RealPaths.lower_bound(dir);
if (i == this->RealPaths.end() ||
this->RealPaths.key_comp()(dir, i->first)) {
- typedef std::map<std::string, std::string>::value_type value_type;
+ using value_type = std::map<std::string, std::string>::value_type;
i = this->RealPaths.insert(
i, value_type(dir, cmSystemTools::GetRealPath(dir)));
}
diff --git a/Source/cmOrderDirectories.h b/Source/cmOrderDirectories.h
index 3a0637afb..23c514500 100644
--- a/Source/cmOrderDirectories.h
+++ b/Source/cmOrderDirectories.h
@@ -3,15 +3,16 @@
#ifndef cmOrderDirectories_h
#define cmOrderDirectories_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmsys/RegularExpression.hxx"
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>
+#include "cmsys/RegularExpression.hxx"
+
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmOrderDirectoriesConstraint;
@@ -25,8 +26,10 @@ public:
cmOrderDirectories(cmGlobalGenerator* gg, cmGeneratorTarget const* target,
const char* purpose);
~cmOrderDirectories();
+ cmOrderDirectories(const cmOrderDirectories&) = delete;
+ cmOrderDirectories& operator=(const cmOrderDirectories&) = delete;
void AddRuntimeLibrary(std::string const& fullPath,
- const char* soname = CM_NULLPTR);
+ const char* soname = nullptr);
void AddLinkLibrary(std::string const& fullPath);
void AddUserDirectories(std::vector<std::string> const& extra);
void AddLanguageDirectories(std::vector<std::string> const& dirs);
@@ -73,7 +76,7 @@ private:
// the index of the directory that must come first. The second
// element is the index of the runtime library that added the
// constraint.
- typedef std::pair<int, int> ConflictPair;
+ using ConflictPair = std::pair<int, int>;
struct ConflictList : public std::vector<ConflictPair>
{
};
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index 14c986dd8..e602a6d0a 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -3,15 +3,13 @@
#include "cmOutputConverter.h"
#include <algorithm>
-#include <assert.h>
-#include <ctype.h>
+#include <cassert>
+#include <cctype>
#include <set>
-#include <sstream>
#include <vector>
-#include "cmAlgorithms.h"
#include "cmState.h"
-#include "cmStateDirectory.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
cmOutputConverter::cmOutputConverter(cmStateSnapshot const& snapshot)
@@ -29,7 +27,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);
@@ -40,10 +38,10 @@ std::string cmOutputConverter::ConvertToOutputForExisting(
return this->ConvertToOutputFormat(remote, format);
}
-std::string cmOutputConverter::ConvertToOutputFormat(const std::string& source,
+std::string cmOutputConverter::ConvertToOutputFormat(cm::string_view source,
OutputFormat output) const
{
- std::string result = source;
+ std::string result(source);
// Convert it to an output path.
if (output == SHELL || output == WATCOMQUOTE) {
result = this->ConvertDirectorySeparatorsForShell(source);
@@ -55,9 +53,9 @@ std::string cmOutputConverter::ConvertToOutputFormat(const std::string& source,
}
std::string cmOutputConverter::ConvertDirectorySeparatorsForShell(
- const std::string& source) const
+ cm::string_view source) const
{
- std::string result = source;
+ std::string result(source);
// For the MSYS shell convert drive letters to posix paths, so
// that c:/some/path becomes /c/some/path. This is needed to
// avoid problems with the shell path translation.
@@ -73,148 +71,21 @@ std::string cmOutputConverter::ConvertDirectorySeparatorsForShell(
return result;
}
-static bool cmOutputConverterNotAbove(const char* a, const char* b)
+static bool cmOutputConverterIsShellOperator(cm::string_view str)
{
- return (cmSystemTools::ComparePath(a, b) ||
- cmSystemTools::IsSubDirectory(a, b));
+ static std::set<cm::string_view> const shellOperators{
+ "<", ">", "<<", ">>", "|", "||", "&&", "&>", "1>", "2>", "2>&1", "1>&2"
+ };
+ return (shellOperators.count(str) != 0);
}
-bool cmOutputConverter::ContainedInDirectory(std::string const& local_path,
- std::string const& remote_path,
- cmStateDirectory const& directory)
-{
- const std::string relativePathTopBinary =
- directory.GetRelativePathTopBinary();
- const std::string relativePathTopSource =
- directory.GetRelativePathTopSource();
-
- const bool bothInBinary =
- cmOutputConverterNotAbove(local_path.c_str(),
- relativePathTopBinary.c_str()) &&
- cmOutputConverterNotAbove(remote_path.c_str(),
- relativePathTopBinary.c_str());
-
- const bool bothInSource =
- cmOutputConverterNotAbove(local_path.c_str(),
- relativePathTopSource.c_str()) &&
- cmOutputConverterNotAbove(remote_path.c_str(),
- relativePathTopSource.c_str());
-
- return bothInSource || bothInBinary;
-}
-
-std::string cmOutputConverter::ConvertToRelativePath(
- std::string const& local_path, std::string const& remote_path) const
-{
- if (!ContainedInDirectory(local_path, remote_path,
- this->StateSnapshot.GetDirectory())) {
- return remote_path;
- }
-
- return this->ForceToRelativePath(local_path, remote_path);
-}
-
-std::string cmOutputConverter::ForceToRelativePath(
- std::string const& local_path, std::string const& remote_path)
-{
- // The paths should never be quoted.
- assert(local_path[0] != '\"');
- assert(remote_path[0] != '\"');
-
- // The local path should never have a trailing slash.
- 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())) {
- return remote_path;
- }
-
- // Identify the longest shared path component between the remote
- // path and the local path.
- std::vector<std::string> local;
- cmSystemTools::SplitPath(local_path, local);
- std::vector<std::string> remote;
- cmSystemTools::SplitPath(remote_path, remote);
- unsigned int common = 0;
- while (common < remote.size() && common < local.size() &&
- cmSystemTools::ComparePath(remote[common], local[common])) {
- ++common;
- }
-
- // If no part of the path is in common then return the full path.
- if (common == 0) {
- return remote_path;
- }
-
- // If the entire path is in common then just return a ".".
- if (common == remote.size() && common == local.size()) {
- return ".";
- }
-
- // If the entire path is in common except for a trailing slash then
- // just return a "./".
- if (common + 1 == remote.size() && remote[common].empty() &&
- common == local.size()) {
- return "./";
- }
-
- // Construct the relative path.
- std::string relative;
-
- // First add enough ../ to get up to the level of the shared portion
- // of the path. Leave off the trailing slash. Note that the last
- // component of local will never be empty because local should never
- // have a trailing slash.
- for (unsigned int i = common; i < local.size(); ++i) {
- relative += "..";
- if (i < local.size() - 1) {
- relative += "/";
- }
- }
-
- // Now add the portion of the destination path that is not included
- // in the shared portion of the path. Add a slash the first time
- // only if there was already something in the path. If there was a
- // trailing slash in the input then the last iteration of the loop
- // will add a slash followed by an empty string which will preserve
- // the trailing slash in the output.
-
- if (!relative.empty() && !remote.empty()) {
- relative += "/";
- }
- relative += cmJoin(cmMakeRange(remote).advance(common), "/");
-
- // Finally return the path.
- return relative;
-}
-
-static bool cmOutputConverterIsShellOperator(const std::string& str)
-{
- static std::set<std::string> shellOperators;
- if (shellOperators.empty()) {
- shellOperators.insert("<");
- shellOperators.insert(">");
- shellOperators.insert("<<");
- shellOperators.insert(">>");
- shellOperators.insert("|");
- shellOperators.insert("||");
- shellOperators.insert("&&");
- shellOperators.insert("&>");
- shellOperators.insert("1>");
- shellOperators.insert("2>");
- shellOperators.insert("2>&1");
- shellOperators.insert("1>&2");
- }
- return shellOperators.count(str) > 0;
-}
-
-std::string cmOutputConverter::EscapeForShell(const std::string& str,
+std::string cmOutputConverter::EscapeForShell(cm::string_view str,
bool makeVars, bool forEcho,
bool useWatcomQuote) const
{
// Do not escape shell operators.
if (cmOutputConverterIsShellOperator(str)) {
- return str;
+ return std::string(str);
}
// Compute the flags for the target shell environment.
@@ -246,51 +117,48 @@ std::string cmOutputConverter::EscapeForShell(const std::string& str,
flags |= Shell_Flag_IsUnix;
}
- return Shell__GetArgument(str.c_str(), flags);
+ return Shell__GetArgument(str, flags);
}
-std::string cmOutputConverter::EscapeForCMake(const std::string& str)
+std::string cmOutputConverter::EscapeForCMake(cm::string_view str)
{
// Always double-quote the argument to take care of most escapes.
std::string result = "\"";
- for (const char* c = str.c_str(); *c; ++c) {
- if (*c == '"') {
+ for (const char c : str) {
+ if (c == '"') {
// Escape the double quote to avoid ending the argument.
result += "\\\"";
- } else if (*c == '$') {
+ } else if (c == '$') {
// Escape the dollar to avoid expanding variables.
result += "\\$";
- } else if (*c == '\\') {
+ } else if (c == '\\') {
// Escape the backslash to avoid other escapes.
result += "\\\\";
} else {
// Other characters will be parsed correctly.
- result += *c;
+ result += c;
}
}
result += "\"";
return result;
}
-std::string cmOutputConverter::EscapeWindowsShellArgument(const char* arg,
+std::string cmOutputConverter::EscapeWindowsShellArgument(cm::string_view arg,
int shell_flags)
{
return Shell__GetArgument(arg, shell_flags);
}
cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat(
- const char* value)
+ cm::string_view value)
{
FortranFormat format = FortranFormatNone;
- if (value && *value) {
- std::vector<std::string> fmt;
- cmSystemTools::ExpandListArgument(value, fmt);
- for (std::vector<std::string>::iterator fi = fmt.begin(); fi != fmt.end();
- ++fi) {
- if (*fi == "FIXED") {
+ if (!value.empty()) {
+ for (std::string const& fi : cmExpandedList(value)) {
+ if (fi == "FIXED") {
format = FortranFormatFixed;
}
- if (*fi == "FREE") {
+ if (fi == "FREE") {
format = FortranFormatFree;
}
}
@@ -298,6 +166,15 @@ cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat(
return format;
}
+cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat(
+ const char* value)
+{
+ if (!value) {
+ return FortranFormatNone;
+ }
+ return GetFortranFormat(cm::string_view(value));
+}
+
void cmOutputConverter::SetLinkScriptShell(bool linkScriptShell)
{
this->LinkScriptShell = linkScriptShell;
@@ -342,12 +219,13 @@ redirection character (for example, ^>, ^<, or ^| ). If you need to
use the caret character itself (^), use two in a row (^^).
*/
-int cmOutputConverter::Shell__CharIsWhitespace(char c)
+/* Some helpers to identify character classes */
+static bool Shell__CharIsWhitespace(char c)
{
return ((c == ' ') || (c == '\t'));
}
-int cmOutputConverter::Shell__CharNeedsQuotesOnUnix(char c)
+static bool Shell__CharNeedsQuotesOnUnix(char c)
{
return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') ||
(c == '&') || (c == '$') || (c == '(') || (c == ')') || (c == '~') ||
@@ -355,51 +233,52 @@ int cmOutputConverter::Shell__CharNeedsQuotesOnUnix(char c)
(c == '\\'));
}
-int cmOutputConverter::Shell__CharNeedsQuotesOnWindows(char c)
+static bool Shell__CharNeedsQuotesOnWindows(char c)
{
return ((c == '\'') || (c == '#') || (c == '&') || (c == '<') ||
(c == '>') || (c == '|') || (c == '^'));
}
-int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
+static bool Shell__CharIsMakeVariableName(char c)
+{
+ return c && (c == '_' || isalpha((static_cast<int>(c))));
+}
+
+bool cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
{
/* On Windows the built-in command shell echo never needs quotes. */
if (!(flags & Shell_Flag_IsUnix) && (flags & Shell_Flag_EchoWindows)) {
- return 0;
+ return false;
}
/* On all platforms quotes are needed to preserve whitespace. */
if (Shell__CharIsWhitespace(c)) {
- return 1;
+ return true;
}
if (flags & Shell_Flag_IsUnix) {
/* On UNIX several special characters need quotes to preserve them. */
if (Shell__CharNeedsQuotesOnUnix(c)) {
- return 1;
+ return true;
}
} else {
/* On Windows several special characters need quotes to preserve them. */
if (Shell__CharNeedsQuotesOnWindows(c)) {
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
-int cmOutputConverter::Shell__CharIsMakeVariableName(char c)
+cm::string_view::iterator cmOutputConverter::Shell__SkipMakeVariables(
+ cm::string_view::iterator c, cm::string_view::iterator end)
{
- return c && (c == '_' || isalpha(((int)c)));
-}
-
-const char* cmOutputConverter::Shell__SkipMakeVariables(const char* c)
-{
- while (*c == '$' && *(c + 1) == '(') {
- const char* skip = c + 2;
- while (Shell__CharIsMakeVariableName(*skip)) {
+ while ((c != end && (c + 1) != end) && (*c == '$' && *(c + 1) == '(')) {
+ cm::string_view::iterator skip = c + 2;
+ while ((skip != end) && Shell__CharIsMakeVariableName(*skip)) {
++skip;
}
- if (*skip == ')') {
+ if ((skip != end) && *skip == ')') {
c = skip + 1;
} else {
break;
@@ -431,61 +310,60 @@ flag later when we understand applications of this better.
*/
#define KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES 0
-int cmOutputConverter::Shell__ArgumentNeedsQuotes(const char* in, int flags)
+bool cmOutputConverter::Shell__ArgumentNeedsQuotes(cm::string_view in,
+ int flags)
{
/* The empty string needs quotes. */
- if (!*in) {
- return 1;
+ if (in.empty()) {
+ return true;
}
/* Scan the string for characters that require quoting. */
- {
- const char* c;
- for (c = in; *c; ++c) {
- /* Look for $(MAKEVAR) syntax if requested. */
- if (flags & Shell_Flag_AllowMakeVariables) {
+ for (cm::string_view::iterator cit = in.begin(), cend = in.end();
+ cit != cend; ++cit) {
+ /* Look for $(MAKEVAR) syntax if requested. */
+ if (flags & Shell_Flag_AllowMakeVariables) {
#if KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES
- const char* skip = Shell__SkipMakeVariables(c);
- if (skip != c) {
- /* We need to quote make variable references to preserve the
- string with contents substituted in its place. */
- return 1;
- }
+ cm::string_view::iterator skip = Shell__SkipMakeVariables(cit, cend);
+ if (skip != cit) {
+ /* We need to quote make variable references to preserve the
+ string with contents substituted in its place. */
+ return true;
+ }
#else
- /* Skip over the make variable references if any are present. */
- c = Shell__SkipMakeVariables(c);
+ /* Skip over the make variable references if any are present. */
+ cit = Shell__SkipMakeVariables(cit, cend);
- /* Stop if we have reached the end of the string. */
- if (!*c) {
- break;
- }
-#endif
+ /* Stop if we have reached the end of the string. */
+ if (cit == cend) {
+ break;
}
+#endif
+ }
- /* Check whether this character needs quotes. */
- if (Shell__CharNeedsQuotes(*c, flags)) {
- return 1;
- }
+ /* Check whether this character needs quotes. */
+ if (Shell__CharNeedsQuotes(*cit, flags)) {
+ return true;
}
}
/* On Windows some single character arguments need quotes. */
- if (flags & Shell_Flag_IsUnix && *in && !*(in + 1)) {
- char c = *in;
+ if (flags & Shell_Flag_IsUnix && in.size() == 1) {
+ char c = in[0];
if ((c == '?') || (c == '&') || (c == '^') || (c == '|') || (c == '#')) {
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
-std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
+std::string cmOutputConverter::Shell__GetArgument(cm::string_view in,
+ int flags)
{
- std::ostringstream out;
-
- /* String iterator. */
- const char* c;
+ /* Output will be at least as long as input string. */
+ std::string out;
+ out.reserve(in.size());
/* Keep track of how many backslashes have been encountered in a row. */
int windows_backslashes = 0;
@@ -496,23 +374,24 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
/* Add the opening quote for this argument. */
if (flags & Shell_Flag_WatcomQuote) {
if (flags & Shell_Flag_IsUnix) {
- out << '"';
+ out += '"';
}
- out << '\'';
+ out += '\'';
} else {
- out << '"';
+ out += '"';
}
}
/* Scan the string for characters that require escaping or quoting. */
- for (c = in; *c; ++c) {
+ for (cm::string_view::iterator cit = in.begin(), cend = in.end();
+ cit != cend; ++cit) {
/* Look for $(MAKEVAR) syntax if requested. */
if (flags & Shell_Flag_AllowMakeVariables) {
- const char* skip = Shell__SkipMakeVariables(c);
- if (skip != c) {
+ cm::string_view::iterator skip = Shell__SkipMakeVariables(cit, cend);
+ if (skip != cit) {
/* Copy to the end of the make variable references. */
- while (c != skip) {
- out << *c++;
+ while (cit != skip) {
+ out += *cit++;
}
/* The make variable reference eliminates any escaping needed
@@ -520,7 +399,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
windows_backslashes = 0;
/* Stop if we have reached the end of the string. */
- if (!*c) {
+ if (cit == cend) {
break;
}
}
@@ -530,27 +409,27 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
if (flags & Shell_Flag_IsUnix) {
/* On Unix a few special characters need escaping even inside a
quoted argument. */
- if (*c == '\\' || *c == '"' || *c == '`' || *c == '$') {
+ if (*cit == '\\' || *cit == '"' || *cit == '`' || *cit == '$') {
/* This character needs a backslash to escape it. */
- out << '\\';
+ out += '\\';
}
} else if (flags & Shell_Flag_EchoWindows) {
/* On Windows the built-in command shell echo never needs escaping. */
} else {
/* On Windows only backslashes and double-quotes need escaping. */
- if (*c == '\\') {
+ if (*cit == '\\') {
/* Found a backslash. It may need to be escaped later. */
++windows_backslashes;
- } else if (*c == '"') {
+ } else if (*cit == '"') {
/* Found a double-quote. Escape all immediately preceding
backslashes. */
while (windows_backslashes > 0) {
--windows_backslashes;
- out << '\\';
+ out += '\\';
}
/* Add the backslash to escape the double-quote. */
- out << '\\';
+ out += '\\';
} else {
/* We encountered a normal character. This eliminates any
escaping needed for preceding backslashes. */
@@ -559,11 +438,11 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
}
/* Check whether this character needs escaping for a make tool. */
- if (*c == '$') {
+ if (*cit == '$') {
if (flags & Shell_Flag_Make) {
/* In Makefiles a dollar is written $$. The make tool will
replace it with just $ before passing it to the shell. */
- out << "$$";
+ out += "$$";
} else if (flags & Shell_Flag_VSIDE) {
/* In a VS IDE a dollar is written "$". If this is written in
an un-quoted argument it starts a quoted segment, inserts
@@ -571,46 +450,46 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
argument it ends quoting, inserts the $ and restarts
quoting. Either way the $ is isolated from surrounding
text to avoid looking like a variable reference. */
- out << "\"$\"";
+ out += "\"$\"";
} else {
/* Otherwise a dollar is written just $. */
- out << '$';
+ out += '$';
}
- } else if (*c == '#') {
+ } else if (*cit == '#') {
if ((flags & Shell_Flag_Make) && (flags & Shell_Flag_WatcomWMake)) {
/* In Watcom WMake makefiles a pound is written $#. The make
tool will replace it with just # before passing it to the
shell. */
- out << "$#";
+ out += "$#";
} else {
/* Otherwise a pound is written just #. */
- out << '#';
+ out += '#';
}
- } else if (*c == '%') {
+ } else if (*cit == '%') {
if ((flags & Shell_Flag_VSIDE) ||
((flags & Shell_Flag_Make) &&
((flags & Shell_Flag_MinGWMake) || (flags & Shell_Flag_NMake)))) {
/* In the VS IDE, NMake, or MinGW make a percent is written %%. */
- out << "%%";
+ out += "%%";
} else {
/* Otherwise a percent is written just %. */
- out << '%';
+ out += '%';
}
- } else if (*c == ';') {
+ } else if (*cit == ';') {
if (flags & Shell_Flag_VSIDE) {
/* In a VS IDE a semicolon is written ";". If this is written
in an un-quoted argument it starts a quoted segment,
inserts the ; and ends the segment. If it is written in a
quoted argument it ends quoting, inserts the ; and restarts
quoting. Either way the ; is isolated. */
- out << "\";\"";
+ out += "\";\"";
} else {
/* Otherwise a semicolon is written just ;. */
- out << ';';
+ out += ';';
}
} else {
/* Store this character. */
- out << *c;
+ out += *cit;
}
}
@@ -618,19 +497,19 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
/* Add enough backslashes to escape any trailing ones. */
while (windows_backslashes > 0) {
--windows_backslashes;
- out << '\\';
+ out += '\\';
}
/* Add the closing quote for this argument. */
if (flags & Shell_Flag_WatcomQuote) {
- out << '\'';
+ out += '\'';
if (flags & Shell_Flag_IsUnix) {
- out << '"';
+ out += '"';
}
} else {
- out << '"';
+ out += '"';
}
}
- return out.str();
+ return out;
}
diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h
index ae15055ed..349a069d6 100644
--- a/Source/cmOutputConverter.h
+++ b/Source/cmOutputConverter.h
@@ -7,10 +7,11 @@
#include <string>
+#include <cm/string_view>
+
#include "cmStateSnapshot.h"
class cmState;
-class cmStateDirectory;
class cmOutputConverter
{
@@ -23,12 +24,11 @@ public:
WATCOMQUOTE,
RESPONSE
};
- std::string ConvertToOutputFormat(const std::string& source,
+ std::string ConvertToOutputFormat(cm::string_view source,
OutputFormat output) const;
- std::string ConvertDirectorySeparatorsForShell(
- const std::string& source) const;
+ std::string ConvertDirectorySeparatorsForShell(cm::string_view source) const;
- ///! for existing files convert to output path and short path if spaces
+ //! for existing files convert to output path and short path if spaces
std::string ConvertToOutputForExisting(const std::string& remote,
OutputFormat format = SHELL) const;
@@ -73,15 +73,15 @@ public:
Shell_Flag_IsUnix = (1 << 8)
};
- std::string EscapeForShell(const std::string& str, bool makeVars = false,
+ std::string EscapeForShell(cm::string_view str, bool makeVars = false,
bool forEcho = false,
bool useWatcomQuote = false) const;
- static std::string EscapeForCMake(const std::string& str);
+ static std::string EscapeForCMake(cm::string_view str);
/** Compute an escaped version of the given argument for use in a
windows shell. */
- static std::string EscapeWindowsShellArgument(const char* arg,
+ static std::string EscapeWindowsShellArgument(cm::string_view arg,
int shell_flags);
enum FortranFormat
@@ -90,41 +90,17 @@ public:
FortranFormatFixed,
FortranFormatFree
};
+ static FortranFormat GetFortranFormat(cm::string_view value);
static FortranFormat GetFortranFormat(const char* value);
- static bool ContainedInDirectory(std::string const& local_path,
- std::string const& remote_path,
- cmStateDirectory const& directory);
-
- /**
- * Convert the given remote path to a relative path with respect to
- * the given local path. Both paths must use forward slashes and not
- * already be escaped or quoted.
- * The conversion is skipped if the paths are not both in the source
- * or both in the binary tree.
- */
- std::string ConvertToRelativePath(std::string const& local_path,
- std::string const& remote_path) const;
-
- /**
- * Convert the given remote path to a relative path with respect to
- * the given local path. Both paths must use forward slashes and not
- * already be escaped or quoted.
- */
- static std::string ForceToRelativePath(std::string const& local_path,
- std::string const& remote_path);
-
private:
cmState* GetState() const;
- static int Shell__CharIsWhitespace(char c);
- static int Shell__CharNeedsQuotesOnUnix(char c);
- static int Shell__CharNeedsQuotesOnWindows(char c);
- static int Shell__CharNeedsQuotes(char c, int flags);
- static int Shell__CharIsMakeVariableName(char c);
- static const char* Shell__SkipMakeVariables(const char* c);
- static int Shell__ArgumentNeedsQuotes(const char* in, int flags);
- static std::string Shell__GetArgument(const char* in, int flags);
+ static bool Shell__CharNeedsQuotes(char c, int flags);
+ static cm::string_view::iterator Shell__SkipMakeVariables(
+ cm::string_view::iterator begin, cm::string_view::iterator end);
+ static bool Shell__ArgumentNeedsQuotes(cm::string_view in, int flags);
+ static std::string Shell__GetArgument(cm::string_view in, int flags);
private:
cmStateSnapshot StateSnapshot;
diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx
index 2339d6876..e093be019 100644
--- a/Source/cmOutputRequiredFilesCommand.cxx
+++ b/Source/cmOutputRequiredFilesCommand.cxx
@@ -2,21 +2,24 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmOutputRequiredFilesCommand.h"
-#include "cmsys/FStream.hxx"
-#include "cmsys/RegularExpression.hxx"
+#include <cstdio>
#include <map>
+#include <set>
#include <utility>
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+
#include "cmAlgorithms.h"
+#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
-#include "cm_unordered_map.hxx"
-
-class cmExecutionStatus;
+namespace {
/** \class cmDependInformation
* \brief Store dependency information for a single source file.
*
@@ -29,29 +32,25 @@ public:
* Construct with dependency generation marked not done; instance
* not placed in cmMakefile's list.
*/
- cmDependInformation()
- : DependDone(false)
- , SourceFile(CM_NULLPTR)
- {
- }
+ cmDependInformation() = default;
/**
* The set of files on which this one depends.
*/
- typedef std::set<cmDependInformation*> DependencySetType;
+ using DependencySetType = std::set<cmDependInformation*>;
DependencySetType DependencySet;
/**
* This flag indicates whether dependency checking has been
* performed for this file.
*/
- bool DependDone;
+ bool DependDone = false;
/**
* If this object corresponds to a cmSourceFile instance, this points
* to it.
*/
- const cmSourceFile* SourceFile;
+ const cmSourceFile* SourceFile = nullptr;
/**
* Full path to this file.
@@ -97,6 +96,9 @@ public:
*/
~cmLBDepend() { cmDeleteAll(this->DependInformationMap); }
+ cmLBDepend(const cmLBDepend&) = delete;
+ cmLBDepend& operator=(const cmLBDepend&) = delete;
+
/**
* Set the makefile that is used as a source of classes.
*/
@@ -113,9 +115,9 @@ public:
// Now extract any include paths from the targets
std::set<std::string> uniqueIncludes;
std::vector<std::string> orderedAndUniqueIncludes;
- cmTargets& targets = this->Makefile->GetTargets();
- for (cmTargets::iterator l = targets.begin(); l != targets.end(); ++l) {
- const char* incDirProp = l->second.GetProperty("INCLUDE_DIRECTORIES");
+ for (auto const& target : this->Makefile->GetTargets()) {
+ const char* incDirProp =
+ target.second.GetProperty("INCLUDE_DIRECTORIES");
if (!incDirProp) {
continue;
}
@@ -123,12 +125,9 @@ public:
std::string incDirs = cmGeneratorExpression::Preprocess(
incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions);
- std::vector<std::string> includes;
- cmSystemTools::ExpandListArgument(incDirs, includes);
+ std::vector<std::string> includes = cmExpandedList(incDirs);
- for (std::vector<std::string>::const_iterator j = includes.begin();
- j != includes.end(); ++j) {
- std::string path = *j;
+ for (std::string& path : includes) {
this->Makefile->ExpandVariablesInString(path);
if (uniqueIncludes.insert(path).second) {
orderedAndUniqueIncludes.push_back(path);
@@ -136,10 +135,8 @@ public:
}
}
- for (std::vector<std::string>::const_iterator it =
- orderedAndUniqueIncludes.begin();
- it != orderedAndUniqueIncludes.end(); ++it) {
- this->AddSearchPath(*it);
+ for (std::string const& inc : orderedAndUniqueIncludes) {
+ this->AddSearchPath(inc);
}
}
@@ -157,7 +154,7 @@ public:
*/
const cmDependInformation* FindDependencies(const char* file)
{
- cmDependInformation* info = this->GetDependInformation(file, CM_NULLPTR);
+ cmDependInformation* info = this->GetDependInformation(file, nullptr);
this->GenerateDependInformation(info);
return info;
}
@@ -171,13 +168,13 @@ protected:
{
cmsys::ifstream fin(info->FullPath.c_str());
if (!fin) {
- cmSystemTools::Error("error can not open ", info->FullPath.c_str());
+ cmSystemTools::Error("error can not open " + info->FullPath);
return;
}
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;
@@ -186,7 +183,7 @@ protected:
qstart = line.find('<', 8);
// if a < is not found then move on
if (qstart == std::string::npos) {
- cmSystemTools::Error("unknown include directive ", line.c_str());
+ cmSystemTools::Error("unknown include directive " + line);
continue;
}
qend = line.find('>', qstart + 1);
@@ -198,11 +195,9 @@ protected:
// see if the include matches the regular expression
if (!this->IncludeFileRegularExpression.find(includeFile)) {
if (this->Verbose) {
- std::string message = "Skipping ";
- message += includeFile;
- message += " for file ";
- message += info->FullPath;
- cmSystemTools::Error(message.c_str(), CM_NULLPTR);
+ std::string message =
+ cmStrCat("Skipping ", includeFile, " for file ", info->FullPath);
+ cmSystemTools::Error(message);
}
continue;
}
@@ -217,63 +212,43 @@ 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::vector<std::string>::iterator i =
- this->IncludeDirectories.begin();
- i != this->IncludeDirectories.end(); ++i) {
- std::string path = *i;
- path = path + "/";
- path = path + cxxFile;
- if (cmSystemTools::FileExists(path.c_str())) {
+ for (std::string const& path : this->IncludeDirectories) {
+ if (cmSystemTools::FileExists(cmStrCat(path, "/", cxxFile))) {
found = true;
}
}
if (!found) {
cxxFile = root + ".cpp";
- if (cmSystemTools::FileExists(cxxFile.c_str())) {
+ if (cmSystemTools::FileExists(cxxFile)) {
found = true;
}
- for (std::vector<std::string>::iterator i =
- this->IncludeDirectories.begin();
- i != this->IncludeDirectories.end(); ++i) {
- std::string path = *i;
- path = path + "/";
- path = path + cxxFile;
- if (cmSystemTools::FileExists(path.c_str())) {
+ for (std::string const& path : this->IncludeDirectories) {
+ if (cmSystemTools::FileExists(cmStrCat(path, "/", cxxFile))) {
found = true;
}
}
}
if (!found) {
cxxFile = root + ".c";
- if (cmSystemTools::FileExists(cxxFile.c_str())) {
+ if (cmSystemTools::FileExists(cxxFile)) {
found = true;
}
- for (std::vector<std::string>::iterator i =
- this->IncludeDirectories.begin();
- i != this->IncludeDirectories.end(); ++i) {
- std::string path = *i;
- path = path + "/";
- path = path + cxxFile;
- if (cmSystemTools::FileExists(path.c_str())) {
+ for (std::string const& path : this->IncludeDirectories) {
+ if (cmSystemTools::FileExists(cmStrCat(path, "/", cxxFile))) {
found = true;
}
}
}
if (!found) {
cxxFile = root + ".txx";
- if (cmSystemTools::FileExists(cxxFile.c_str())) {
+ if (cmSystemTools::FileExists(cxxFile)) {
found = true;
}
- for (std::vector<std::string>::iterator i =
- this->IncludeDirectories.begin();
- i != this->IncludeDirectories.end(); ++i) {
- std::string path = *i;
- path = path + "/";
- path = path + cxxFile;
- if (cmSystemTools::FileExists(path.c_str())) {
+ for (std::string const& path : this->IncludeDirectories) {
+ if (cmSystemTools::FileExists(cmStrCat(path, "/", cxxFile))) {
found = true;
}
}
@@ -310,8 +285,8 @@ protected:
// Make sure we don't visit the same file more than once.
info->DependDone = true;
- const char* path = info->FullPath.c_str();
- if (!path) {
+ const std::string& path = info->FullPath;
+ if (path.empty()) {
cmSystemTools::Error(
"Attempt to find dependencies for file without path!");
return;
@@ -328,7 +303,7 @@ protected:
// See if the cmSourceFile for it has any files specified as
// dependency hints.
- if (info->SourceFile != CM_NULLPTR) {
+ if (info->SourceFile != nullptr) {
// Get the cmSourceFile corresponding to this.
const cmSourceFile& cFile = *(info->SourceFile);
@@ -337,10 +312,8 @@ protected:
if (!cFile.GetDepends().empty()) {
// Dependency hints have been given. Use them to begin the
// recursion.
- for (std::vector<std::string>::const_iterator file =
- cFile.GetDepends().begin();
- file != cFile.GetDepends().end(); ++file) {
- this->AddDependency(info, file->c_str());
+ for (std::string const& file : cFile.GetDepends()) {
+ this->AddDependency(info, file.c_str());
}
// Found dependency information. We are done.
@@ -353,19 +326,16 @@ protected:
cmSourceFile* srcFile = this->Makefile->GetSource(
cmSystemTools::GetFilenameWithoutExtension(path));
if (srcFile) {
- if (srcFile->GetFullPath() == path) {
+ if (srcFile->ResolveFullPath() == path) {
found = true;
} else {
// try to guess which include path to use
- for (std::vector<std::string>::iterator t =
- this->IncludeDirectories.begin();
- t != this->IncludeDirectories.end(); ++t) {
- std::string incpath = *t;
- if (!incpath.empty() && incpath[incpath.size() - 1] != '/') {
- incpath = incpath + "/";
+ for (std::string incpath : this->IncludeDirectories) {
+ if (!incpath.empty() && incpath.back() != '/') {
+ incpath += "/";
}
- incpath = incpath + path;
- if (srcFile->GetFullPath() == incpath) {
+ incpath += path;
+ if (srcFile->ResolveFullPath() == incpath) {
// set the path to the guessed path
info->FullPath = incpath;
found = true;
@@ -377,13 +347,12 @@ protected:
if (!found) {
// Couldn't find any dependency information.
- if (this->ComplainFileRegularExpression.find(
- info->IncludeName.c_str())) {
- cmSystemTools::Error("error cannot find dependencies for ", path);
+ if (this->ComplainFileRegularExpression.find(info->IncludeName)) {
+ cmSystemTools::Error("error cannot find dependencies for " + path);
} else {
// Destroy the name of the file so that it won't be output as a
// dependency.
- info->FullPath = "";
+ info->FullPath.clear();
}
}
}
@@ -399,8 +368,7 @@ protected:
std::string fullPath = this->FullPath(file, extraPath);
// Try to find the file's instance of cmDependInformation.
- DependInformationMapType::const_iterator result =
- this->DependInformationMap.find(fullPath);
+ auto result = this->DependInformationMap.find(fullPath);
if (result != this->DependInformationMap.end()) {
// Found an instance, return it.
return result->second;
@@ -430,7 +398,7 @@ protected:
if (m != this->DirectoryToFileToPathMap.end()) {
FileToPathMapType& map = m->second;
- FileToPathMapType::iterator p = map.find(fname);
+ auto p = map.find(fname);
if (p != map.end()) {
return p->second;
}
@@ -442,15 +410,12 @@ protected:
return fp;
}
- for (std::vector<std::string>::iterator i =
- this->IncludeDirectories.begin();
- i != this->IncludeDirectories.end(); ++i) {
- std::string path = *i;
- if (!path.empty() && path[path.size() - 1] != '/') {
- path = path + "/";
+ for (std::string path : this->IncludeDirectories) {
+ if (!path.empty() && path.back() != '/') {
+ path += "/";
}
- path = path + fname;
- if (cmSystemTools::FileExists(path.c_str(), true) &&
+ path += fname;
+ if (cmSystemTools::FileExists(path, true) &&
!cmSystemTools::FileIsDirectory(path)) {
std::string fp = cmSystemTools::CollapseFullPath(path);
this->DirectoryToFileToPathMap[extraPath ? extraPath : ""][fname] = fp;
@@ -460,11 +425,11 @@ protected:
if (extraPath) {
std::string path = extraPath;
- if (!path.empty() && path[path.size() - 1] != '/') {
+ if (!path.empty() && path.back() != '/') {
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;
@@ -481,70 +446,71 @@ protected:
cmsys::RegularExpression IncludeFileRegularExpression;
cmsys::RegularExpression ComplainFileRegularExpression;
std::vector<std::string> IncludeDirectories;
- typedef std::map<std::string, std::string> FileToPathMapType;
- typedef std::map<std::string, FileToPathMapType>
- DirectoryToFileToPathMapType;
- typedef std::map<std::string, cmDependInformation*> DependInformationMapType;
+ using FileToPathMapType = std::map<std::string, std::string>;
+ using DirectoryToFileToPathMapType =
+ std::map<std::string, FileToPathMapType>;
+ using DependInformationMapType = std::map<std::string, cmDependInformation*>;
DependInformationMapType DependInformationMap;
DirectoryToFileToPathMapType DirectoryToFileToPathMap;
};
+void ListDependencies(cmDependInformation const* info, FILE* fout,
+ std::set<cmDependInformation const*>* visited);
+}
+
// cmOutputRequiredFilesCommand
-bool cmOutputRequiredFilesCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmOutputRequiredFilesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() != 2) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
// store the arg for final pass
- this->File = args[0];
- this->OutputFile = args[1];
+ const std::string& file = args[0];
+ const std::string& outputFile = args[1];
// compute the list of files
cmLBDepend md;
- md.SetMakefile(this->Makefile);
- md.AddSearchPath(this->Makefile->GetCurrentSourceDirectory());
+ md.SetMakefile(&status.GetMakefile());
+ md.AddSearchPath(status.GetMakefile().GetCurrentSourceDirectory());
// find the depends for a file
- const cmDependInformation* info = md.FindDependencies(this->File.c_str());
+ const cmDependInformation* info = md.FindDependencies(file.c_str());
if (info) {
// write them out
- FILE* fout = cmsys::SystemTools::Fopen(this->OutputFile, "w");
+ FILE* fout = cmsys::SystemTools::Fopen(outputFile, "w");
if (!fout) {
- std::string err = "Can not open output file: ";
- err += this->OutputFile;
- this->SetError(err);
+ status.SetError(cmStrCat("Can not open output file: ", outputFile));
return false;
}
std::set<cmDependInformation const*> visited;
- this->ListDependencies(info, fout, &visited);
+ ListDependencies(info, fout, &visited);
fclose(fout);
}
return true;
}
-void cmOutputRequiredFilesCommand::ListDependencies(
- cmDependInformation const* info, FILE* fout,
- std::set<cmDependInformation const*>* visited)
+namespace {
+void ListDependencies(cmDependInformation const* info, FILE* fout,
+ std::set<cmDependInformation const*>* visited)
{
// add info to the visited set
visited->insert(info);
// now recurse with info's dependencies
- for (cmDependInformation::DependencySetType::const_iterator d =
- info->DependencySet.begin();
- d != info->DependencySet.end(); ++d) {
- if (visited->find(*d) == visited->end()) {
- if (info->FullPath != "") {
- std::string tmp = (*d)->FullPath;
+ for (cmDependInformation* d : info->DependencySet) {
+ if (visited->find(d) == visited->end()) {
+ if (!info->FullPath.empty()) {
+ std::string tmp = d->FullPath;
std::string::size_type pos = tmp.rfind('.');
if (pos != std::string::npos && (tmp.substr(pos) != ".h")) {
tmp = tmp.substr(0, pos);
- fprintf(fout, "%s\n", (*d)->FullPath.c_str());
+ fprintf(fout, "%s\n", d->FullPath.c_str());
}
}
- this->ListDependencies(*d, fout, visited);
+ ListDependencies(d, fout, visited);
}
}
}
+}
diff --git a/Source/cmOutputRequiredFilesCommand.h b/Source/cmOutputRequiredFilesCommand.h
index d20bfbdc1..4c1189457 100644
--- a/Source/cmOutputRequiredFilesCommand.h
+++ b/Source/cmOutputRequiredFilesCommand.h
@@ -3,31 +3,14 @@
#ifndef cmOutputRequiredFilesCommand_h
#define cmOutputRequiredFilesCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include <set>
-#include <stdio.h>
#include <string>
#include <vector>
-#include "cmCommand.h"
-
-class cmDependInformation;
class cmExecutionStatus;
-class cmOutputRequiredFilesCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE { return new cmOutputRequiredFilesCommand; }
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
- void ListDependencies(cmDependInformation const* info, FILE* fout,
- std::set<cmDependInformation const*>* visited);
-
-private:
- std::string File;
- std::string OutputFile;
-};
+bool cmOutputRequiredFilesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx
index d75ee8e86..d712edb81 100644
--- a/Source/cmParseArgumentsCommand.cxx
+++ b/Source/cmParseArgumentsCommand.cxx
@@ -5,59 +5,136 @@
#include <map>
#include <set>
#include <sstream>
-#include <stddef.h>
#include <utility>
-#include "cmAlgorithms.h"
+#include <cm/string_view>
+
+#include "cmArgumentParser.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmRange.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmake.h"
-
-class cmExecutionStatus;
-static std::string escape_arg(const std::string& arg)
+static std::string EscapeArg(const std::string& arg)
{
// replace ";" with "\;" so output argument lists will split correctly
std::string escapedArg;
- for (size_t i = 0; i < arg.size(); ++i) {
- if (arg[i] == ';') {
+ for (char i : arg) {
+ if (i == ';') {
escapedArg += '\\';
}
- escapedArg += arg[i];
+ escapedArg += i;
}
return escapedArg;
}
-bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+static std::string JoinList(std::vector<std::string> const& arg, bool escape)
+{
+ return escape ? cmJoin(cmMakeRange(arg).transform(EscapeArg), ";")
+ : cmJoin(cmMakeRange(arg), ";");
+}
+
+namespace {
+
+using options_map = std::map<std::string, bool>;
+using single_map = std::map<std::string, std::string>;
+using multi_map = std::map<std::string, std::vector<std::string>>;
+using options_set = std::set<std::string>;
+
+struct UserArgumentParser : public cmArgumentParser<void>
+{
+ template <typename T, typename H>
+ void Bind(std::vector<std::string> const& names,
+ std::map<std::string, T>& ref, H duplicateKey)
+ {
+ for (std::string const& key : names) {
+ auto const it = ref.emplace(key, T{}).first;
+ bool const inserted = this->cmArgumentParser<void>::Bind(
+ cm::string_view(it->first), it->second);
+ if (!inserted) {
+ duplicateKey(key);
+ }
+ }
+ }
+};
+
+} // namespace
+
+static void PassParsedArguments(
+ const std::string& prefix, cmMakefile& makefile, const options_map& options,
+ const single_map& singleValArgs, const multi_map& multiValArgs,
+ const std::vector<std::string>& unparsed,
+ const options_set& keywordsMissingValues, bool parseFromArgV)
+{
+ for (auto const& iter : options) {
+ makefile.AddDefinition(prefix + iter.first,
+ iter.second ? "TRUE" : "FALSE");
+ }
+
+ for (auto const& iter : singleValArgs) {
+ if (!iter.second.empty()) {
+ makefile.AddDefinition(prefix + iter.first, iter.second);
+ } else {
+ makefile.RemoveDefinition(prefix + iter.first);
+ }
+ }
+
+ for (auto const& iter : multiValArgs) {
+ if (!iter.second.empty()) {
+ makefile.AddDefinition(prefix + iter.first,
+ JoinList(iter.second, parseFromArgV));
+ } else {
+ makefile.RemoveDefinition(prefix + iter.first);
+ }
+ }
+
+ if (!unparsed.empty()) {
+ makefile.AddDefinition(prefix + "UNPARSED_ARGUMENTS",
+ JoinList(unparsed, parseFromArgV));
+ } else {
+ makefile.RemoveDefinition(prefix + "UNPARSED_ARGUMENTS");
+ }
+
+ if (!keywordsMissingValues.empty()) {
+ makefile.AddDefinition(prefix + "KEYWORDS_MISSING_VALUES",
+ cmJoin(cmMakeRange(keywordsMissingValues), ";"));
+ } else {
+ makefile.RemoveDefinition(prefix + "KEYWORDS_MISSING_VALUES");
+ }
+}
+
+bool cmParseArgumentsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
// cmake_parse_arguments(prefix options single multi <ARGN>)
// 1 2 3 4
// or
// cmake_parse_arguments(PARSE_ARGV N prefix options single multi)
if (args.size() < 4) {
- this->SetError("must be called with at least 4 arguments.");
+ status.SetError("must be called with at least 4 arguments.");
return false;
}
- std::vector<std::string>::const_iterator argIter = args.begin(),
- argEnd = args.end();
+ auto argIter = args.begin();
+ auto argEnd = args.end();
bool parseFromArgV = false;
unsigned long argvStart = 0;
if (*argIter == "PARSE_ARGV") {
if (args.size() != 6) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ status.GetMakefile().IssueMessage(
+ MessageType::FATAL_ERROR,
"PARSE_ARGV must be called with exactly 6 arguments.");
cmSystemTools::SetFatalErrorOccured();
return true;
}
parseFromArgV = true;
argIter++; // move past PARSE_ARGV
- if (!cmSystemTools::StringToULong(argIter->c_str(), &argvStart)) {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, "PARSE_ARGV index '" +
- *argIter +
- "' is not an unsigned integer");
+ if (!cmStrToULong(*argIter, &argvStart)) {
+ status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR,
+ "PARSE_ARGV index '" + *argIter +
+ "' is not an unsigned integer");
cmSystemTools::SetFatalErrorOccured();
return true;
}
@@ -66,179 +143,79 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
// the first argument is the prefix
const std::string prefix = (*argIter++) + "_";
+ UserArgumentParser parser;
+
// define the result maps holding key/value pairs for
// options, single values and multi values
- typedef std::map<std::string, bool> options_map;
- 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;
- // remember already defined keywords
- std::set<std::string> used_keywords;
- const std::string dup_warning = "keyword defined more than once: ";
+ auto const duplicateKey = [&status](std::string const& key) {
+ status.GetMakefile().IssueMessage(
+ MessageType::WARNING, "keyword defined more than once: " + key);
+ };
// the second argument is a (cmake) list of options without argument
- std::vector<std::string> list;
- cmSystemTools::ExpandListArgument(*argIter++, list);
- for (std::vector<std::string>::const_iterator iter = list.begin(),
- end = list.end();
- iter != end; ++iter) {
- if (!used_keywords.insert(*iter).second) {
- this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter);
- }
- options[*iter]; // default initialize
- }
+ std::vector<std::string> list = cmExpandedList(*argIter++);
+ parser.Bind(list, options, duplicateKey);
// the third argument is a (cmake) list of single argument options
list.clear();
- cmSystemTools::ExpandListArgument(*argIter++, list);
- for (std::vector<std::string>::const_iterator iter = list.begin(),
- end = list.end();
- iter != end; ++iter) {
- if (!used_keywords.insert(*iter).second) {
- this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter);
- }
- single[*iter]; // default initialize
- }
+ cmExpandList(*argIter++, list);
+ parser.Bind(list, singleValArgs, duplicateKey);
// the fourth argument is a (cmake) list of multi argument options
list.clear();
- cmSystemTools::ExpandListArgument(*argIter++, list);
- for (std::vector<std::string>::const_iterator iter = list.begin(),
- end = list.end();
- iter != end; ++iter) {
- if (!used_keywords.insert(*iter).second) {
- this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter);
- }
- multi[*iter]; // default initialize
- }
-
- enum insideValues
- {
- NONE,
- SINGLE,
- MULTI
- } insideValues = NONE;
- std::string currentArgName;
+ cmExpandList(*argIter++, list);
+ parser.Bind(list, multiValArgs, duplicateKey);
list.clear();
if (!parseFromArgV) {
// Flatten ;-lists in the arguments into a single list as was done
// by the original function(CMAKE_PARSE_ARGUMENTS).
for (; argIter != argEnd; ++argIter) {
- cmSystemTools::ExpandListArgument(*argIter, list);
+ cmExpandList(*argIter, list);
}
} else {
// in the PARSE_ARGV move read the arguments from ARGC and ARGV#
- std::string argc = this->Makefile->GetSafeDefinition("ARGC");
+ std::string argc = status.GetMakefile().GetSafeDefinition("ARGC");
unsigned long count;
- if (!cmSystemTools::StringToULong(argc.c_str(), &count)) {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
- "PARSE_ARGV called with ARGC='" + argc +
- "' that is not an unsigned integer");
+ if (!cmStrToULong(argc, &count)) {
+ status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR,
+ "PARSE_ARGV called with ARGC='" +
+ argc +
+ "' that is not an unsigned integer");
cmSystemTools::SetFatalErrorOccured();
return true;
}
for (unsigned long i = argvStart; i < count; ++i) {
std::ostringstream argName;
argName << "ARGV" << i;
- const char* arg = this->Makefile->GetDefinition(argName.str());
+ const char* arg = status.GetMakefile().GetDefinition(argName.str());
if (!arg) {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
- "PARSE_ARGV called with " +
- argName.str() + " not set");
+ status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR,
+ "PARSE_ARGV called with " +
+ argName.str() + " not set");
cmSystemTools::SetFatalErrorOccured();
return true;
}
- list.push_back(arg);
+ list.emplace_back(arg);
}
}
- // iterate over the arguments list and fill in the values where applicable
- for (argIter = list.begin(), argEnd = list.end(); argIter != argEnd;
- ++argIter) {
- const options_map::iterator optIter = options.find(*argIter);
- if (optIter != options.end()) {
- insideValues = NONE;
- optIter->second = true;
- continue;
- }
-
- const single_map::iterator singleIter = single.find(*argIter);
- if (singleIter != single.end()) {
- insideValues = SINGLE;
- currentArgName = *argIter;
- continue;
- }
+ std::vector<std::string> keywordsMissingValues;
- const multi_map::iterator multiIter = multi.find(*argIter);
- if (multiIter != multi.end()) {
- insideValues = MULTI;
- currentArgName = *argIter;
- continue;
- }
+ parser.Parse(list, &unparsed, &keywordsMissingValues);
- switch (insideValues) {
- case SINGLE:
- single[currentArgName] = *argIter;
- insideValues = NONE;
- break;
- case MULTI:
- if (parseFromArgV) {
- multi[currentArgName].push_back(escape_arg(*argIter));
- } else {
- multi[currentArgName].push_back(*argIter);
- }
- break;
- default:
- if (parseFromArgV) {
- unparsed.push_back(escape_arg(*argIter));
- } else {
- unparsed.push_back(*argIter);
- }
- break;
- }
- }
-
- // now iterate over the collected values and update their definition
- // within the current scope. undefine if necessary.
-
- for (options_map::const_iterator iter = options.begin(), end = options.end();
- iter != end; ++iter) {
- this->Makefile->AddDefinition(prefix + iter->first,
- iter->second ? "TRUE" : "FALSE");
- }
- for (single_map::const_iterator iter = single.begin(), end = single.end();
- iter != end; ++iter) {
- if (!iter->second.empty()) {
- this->Makefile->AddDefinition(prefix + iter->first,
- iter->second.c_str());
- } else {
- this->Makefile->RemoveDefinition(prefix + iter->first);
- }
- }
-
- for (multi_map::const_iterator iter = multi.begin(), end = multi.end();
- iter != end; ++iter) {
- if (!iter->second.empty()) {
- this->Makefile->AddDefinition(
- prefix + iter->first, cmJoin(cmMakeRange(iter->second), ";").c_str());
- } else {
- this->Makefile->RemoveDefinition(prefix + iter->first);
- }
- }
-
- if (!unparsed.empty()) {
- this->Makefile->AddDefinition(prefix + "UNPARSED_ARGUMENTS",
- cmJoin(cmMakeRange(unparsed), ";").c_str());
- } else {
- this->Makefile->RemoveDefinition(prefix + "UNPARSED_ARGUMENTS");
- }
+ PassParsedArguments(
+ prefix, status.GetMakefile(), options, singleValArgs, multiValArgs,
+ unparsed,
+ options_set(keywordsMissingValues.begin(), keywordsMissingValues.end()),
+ parseFromArgV);
return true;
}
diff --git a/Source/cmParseArgumentsCommand.h b/Source/cmParseArgumentsCommand.h
index 359fb85b9..b2e436d89 100644
--- a/Source/cmParseArgumentsCommand.h
+++ b/Source/cmParseArgumentsCommand.h
@@ -3,32 +3,14 @@
#ifndef cmParseArgumentsCommand_h
#define cmParseArgumentsCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmParseArgumentsCommand
- *
- */
-class cmParseArgumentsCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmParseArgumentsCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmParseArgumentsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmPathLabel.cxx b/Source/cmPathLabel.cxx
index 30ba08151..fb8135101 100644
--- a/Source/cmPathLabel.cxx
+++ b/Source/cmPathLabel.cxx
@@ -2,15 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmPathLabel.h"
-#include <stddef.h>
+#include <utility>
-cmPathLabel::cmPathLabel(const std::string& label)
- : Label(label)
+cmPathLabel::cmPathLabel(std::string label)
+ : Label(std::move(label))
, Hash(0)
{
// Use a Jenkins one-at-a-time hash with under/over-flow protection
- for (size_t i = 0; i < this->Label.size(); ++i) {
- this->Hash += this->Label[i];
+ for (char i : this->Label) {
+ this->Hash += i;
this->Hash += ((this->Hash & 0x003FFFFF) << 10);
this->Hash ^= ((this->Hash & 0xFFFFFFC0) >> 6);
}
diff --git a/Source/cmPathLabel.h b/Source/cmPathLabel.h
index 97551fb46..55dffabe0 100644
--- a/Source/cmPathLabel.h
+++ b/Source/cmPathLabel.h
@@ -17,7 +17,7 @@
class cmPathLabel
{
public:
- cmPathLabel(const std::string& label);
+ cmPathLabel(std::string label);
// The comparison operators are only for quick sorting and searching and
// in no way imply any lexicographical order of the label
diff --git a/Source/cmPipeConnection.cxx b/Source/cmPipeConnection.cxx
new file mode 100644
index 000000000..1eede13e0
--- /dev/null
+++ b/Source/cmPipeConnection.cxx
@@ -0,0 +1,71 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmPipeConnection.h"
+
+#include <utility>
+
+#include "cmServer.h"
+
+cmPipeConnection::cmPipeConnection(std::string name,
+ cmConnectionBufferStrategy* bufferStrategy)
+ : cmEventBasedConnection(bufferStrategy)
+ , PipeName(std::move(name))
+{
+}
+
+void cmPipeConnection::Connect(uv_stream_t* server)
+{
+ if (this->WriteStream.get()) {
+ // Accept and close all pipes but the first:
+ cm::uv_pipe_ptr rejectPipe;
+
+ rejectPipe.init(*this->Server->GetLoop(), 0);
+ uv_accept(server, rejectPipe);
+
+ return;
+ }
+
+ cm::uv_pipe_ptr ClientPipe;
+ ClientPipe.init(*this->Server->GetLoop(), 0,
+ static_cast<cmEventBasedConnection*>(this));
+
+ if (uv_accept(server, ClientPipe) != 0) {
+ return;
+ }
+
+ uv_read_start(ClientPipe, on_alloc_buffer, on_read);
+ WriteStream = std::move(ClientPipe);
+ Server->OnConnected(this);
+}
+
+bool cmPipeConnection::OnServeStart(std::string* errorMessage)
+{
+ 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) {
+ *errorMessage = std::string("Internal Error with ") + this->PipeName +
+ ": " + uv_err_name(r);
+ return false;
+ }
+
+ 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;
+ }
+
+ return cmConnection::OnServeStart(errorMessage);
+}
+
+bool cmPipeConnection::OnConnectionShuttingDown()
+{
+ if (this->WriteStream.get()) {
+ this->WriteStream->data = nullptr;
+ }
+
+ this->ServerPipe.reset();
+
+ return cmEventBasedConnection::OnConnectionShuttingDown();
+}
diff --git a/Source/cmPipeConnection.h b/Source/cmPipeConnection.h
new file mode 100644
index 000000000..81f8a49f6
--- /dev/null
+++ b/Source/cmPipeConnection.h
@@ -0,0 +1,29 @@
+/* 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 <string>
+
+#include "cm_uv.h"
+
+#include "cmConnection.h"
+#include "cmUVHandlePtr.h"
+
+class cmPipeConnection : public cmEventBasedConnection
+{
+public:
+ cmPipeConnection(std::string name,
+ cmConnectionBufferStrategy* bufferStrategy = nullptr);
+
+ bool OnServeStart(std::string* pString) override;
+
+ bool OnConnectionShuttingDown() override;
+
+ void Connect(uv_stream_t* server) override;
+
+private:
+ const std::string PipeName;
+ cm::uv_pipe_ptr ServerPipe;
+};
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index da3edd427..5c8bc98b2 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -1,20 +1,19 @@
#include "cmPolicies.h"
-#include "cmAlgorithms.h"
+#include <cassert>
+#include <cctype>
+#include <cstdio>
+#include <cstring>
+#include <sstream>
+#include <vector>
+
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmState.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
-#include "cmake.h"
-
-#include "cmConfigure.h"
-#include <assert.h>
-#include <ctype.h>
-#include <sstream>
-#include <stdio.h>
-#include <string.h>
-#include <vector>
static bool stringToId(const char* input, cmPolicies::PolicyID& pid)
{
@@ -35,7 +34,7 @@ static bool stringToId(const char* input, cmPolicies::PolicyID& pid)
}
}
long id;
- if (!cmSystemTools::StringToLong(input + 3, &id)) {
+ if (!cmStrToLong(input + 3, &id)) {
return false;
}
if (id >= cmPolicies::CMPCOUNT) {
@@ -62,9 +61,9 @@ static const char* idToString(cmPolicies::PolicyID id)
CM_FOR_EACH_POLICY_ID(POLICY_CASE)
#undef POLICY_CASE
case cmPolicies::CMPCOUNT:
- return CM_NULLPTR;
+ return nullptr;
}
- return CM_NULLPTR;
+ return nullptr;
}
static const char* idToVersion(cmPolicies::PolicyID id)
@@ -76,9 +75,9 @@ static const char* idToVersion(cmPolicies::PolicyID id)
CM_FOR_EACH_POLICY_ID_VERSION(POLICY_CASE)
#undef POLICY_CASE
case cmPolicies::CMPCOUNT:
- return CM_NULLPTR;
+ return nullptr;
}
- return CM_NULLPTR;
+ return nullptr;
}
static bool isPolicyNewerThan(cmPolicies::PolicyID id, unsigned int majorV,
@@ -108,9 +107,9 @@ const char* idToShortDescription(cmPolicies::PolicyID id)
CM_FOR_EACH_POLICY_ID_DOC(POLICY_CASE)
#undef POLICY_CASE
case cmPolicies::CMPCOUNT:
- return CM_NULLPTR;
+ return nullptr;
}
- return CM_NULLPTR;
+ return nullptr;
}
static void DiagnoseAncientPolicies(
@@ -121,67 +120,61 @@ static void DiagnoseAncientPolicies(
e << "The project requests behavior compatible with CMake version \""
<< majorVer << "." << minorVer << "." << patchVer
<< "\", which requires the OLD behavior for some policies:\n";
- for (std::vector<cmPolicies::PolicyID>::const_iterator i = ancient.begin();
- i != ancient.end(); ++i) {
- e << " " << idToString(*i) << ": " << idToShortDescription(*i) << "\n";
+ for (cmPolicies::PolicyID i : ancient) {
+ e << " " << idToString(i) << ": " << idToShortDescription(i) << "\n";
}
e << "However, this version of CMake no longer supports the OLD "
<< "behavior for these policies. "
<< "Please either update your CMakeLists.txt files to conform to "
<< "the new behavior or use an older version of CMake that still "
<< "supports the old behavior.";
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
}
static bool GetPolicyDefault(cmMakefile* mf, std::string const& policy,
cmPolicies::PolicyStatus* defaultSetting)
{
std::string defaultVar = "CMAKE_POLICY_DEFAULT_" + policy;
- std::string defaultValue = mf->GetSafeDefinition(defaultVar);
+ std::string const& defaultValue = mf->GetSafeDefinition(defaultVar);
if (defaultValue == "NEW") {
*defaultSetting = cmPolicies::NEW;
} else if (defaultValue == "OLD") {
*defaultSetting = cmPolicies::OLD;
- } else if (defaultValue == "") {
+ } else if (defaultValue.empty()) {
*defaultSetting = cmPolicies::WARN;
} else {
std::ostringstream e;
e << defaultVar << " has value \"" << defaultValue
- << "\" but must be \"OLD\", \"NEW\", or \"\" (empty).";
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ << R"(" but must be "OLD", "NEW", or "" (empty).)";
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
return true;
}
-bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, const char* version)
+bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf,
+ std::string const& version_min,
+ std::string const& version_max)
{
- std::string ver = "2.4.0";
-
- if (version && strlen(version) > 0) {
- ver = version;
- }
-
- unsigned int majorVer = 2;
- unsigned int minorVer = 0;
- unsigned int patchVer = 0;
- unsigned int tweakVer = 0;
-
- // parse the string
- if (sscanf(ver.c_str(), "%u.%u.%u.%u", &majorVer, &minorVer, &patchVer,
- &tweakVer) < 2) {
+ // Parse components of the minimum version.
+ unsigned int minMajor = 2;
+ unsigned int minMinor = 0;
+ unsigned int minPatch = 0;
+ unsigned int minTweak = 0;
+ if (sscanf(version_min.c_str(), "%u.%u.%u.%u", &minMajor, &minMinor,
+ &minPatch, &minTweak) < 2) {
std::ostringstream e;
- e << "Invalid policy version value \"" << ver << "\". "
+ e << "Invalid policy version value \"" << version_min << "\". "
<< "A numeric major.minor[.patch[.tweak]] must be given.";
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
// it is an error if the policy version is less than 2.4
- if (majorVer < 2 || (majorVer == 2 && minorVer < 4)) {
+ if (minMajor < 2 || (minMajor == 2 && minMinor < 4)) {
mf->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"Compatibility with CMake < 2.4 is not supported by CMake >= 3.0. "
"For compatibility with older versions please use any CMake 2.8.x "
"release or lower.");
@@ -190,26 +183,72 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, const char* version)
// It is an error if the policy version is greater than the running
// CMake.
- if (majorVer > cmVersion::GetMajorVersion() ||
- (majorVer == cmVersion::GetMajorVersion() &&
- minorVer > cmVersion::GetMinorVersion()) ||
- (majorVer == cmVersion::GetMajorVersion() &&
- minorVer == cmVersion::GetMinorVersion() &&
- patchVer > cmVersion::GetPatchVersion()) ||
- (majorVer == cmVersion::GetMajorVersion() &&
- minorVer == cmVersion::GetMinorVersion() &&
- patchVer == cmVersion::GetPatchVersion() &&
- tweakVer > cmVersion::GetTweakVersion())) {
+ if (minMajor > cmVersion::GetMajorVersion() ||
+ (minMajor == cmVersion::GetMajorVersion() &&
+ minMinor > cmVersion::GetMinorVersion()) ||
+ (minMajor == cmVersion::GetMajorVersion() &&
+ minMinor == cmVersion::GetMinorVersion() &&
+ minPatch > cmVersion::GetPatchVersion()) ||
+ (minMajor == cmVersion::GetMajorVersion() &&
+ minMinor == cmVersion::GetMinorVersion() &&
+ minPatch == cmVersion::GetPatchVersion() &&
+ minTweak > cmVersion::GetTweakVersion())) {
std::ostringstream e;
e << "An attempt was made to set the policy version of CMake to \""
- << version << "\" which is greater than this version of CMake. "
+ << version_min << "\" which is greater than this version of CMake. "
<< "This is not allowed because the greater version may have new "
<< "policies not known to this CMake. "
<< "You may need a newer CMake version to build this project.";
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
+ unsigned int polMajor = minMajor;
+ unsigned int polMinor = minMinor;
+ unsigned int polPatch = minPatch;
+
+ if (!version_max.empty()) {
+ // Parse components of the maximum version.
+ unsigned int maxMajor = 0;
+ unsigned int maxMinor = 0;
+ unsigned int maxPatch = 0;
+ unsigned int maxTweak = 0;
+ if (sscanf(version_max.c_str(), "%u.%u.%u.%u", &maxMajor, &maxMinor,
+ &maxPatch, &maxTweak) < 2) {
+ std::ostringstream e;
+ e << "Invalid policy max version value \"" << version_max << "\". "
+ << "A numeric major.minor[.patch[.tweak]] must be given.";
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return false;
+ }
+
+ // It is an error if the min version is greater than the max version.
+ if (minMajor > maxMajor || (minMajor == maxMajor && minMinor > maxMinor) ||
+ (minMajor == maxMajor && minMinor == maxMinor &&
+ minPatch > maxPatch) ||
+ (minMajor == maxMajor && minMinor == maxMinor &&
+ minPatch == maxPatch && minTweak > maxTweak)) {
+ std::ostringstream e;
+ e << "Policy VERSION range \"" << version_min << "..." << version_max
+ << "\""
+ << " specifies a larger minimum than maximum.";
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return false;
+ }
+
+ // Use the max version as the policy version.
+ polMajor = maxMajor;
+ polMinor = maxMinor;
+ polPatch = maxPatch;
+ }
+
+ return cmPolicies::ApplyPolicyVersion(mf, polMajor, polMinor, polPatch);
+}
+
+bool cmPolicies::ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer,
+ unsigned int minorVer,
+ unsigned int patchVer)
+{
// now loop over all the policies and set them as appropriate
std::vector<cmPolicies::PolicyID> ancientPolicies;
for (PolicyID pid = cmPolicies::CMP0000; pid != cmPolicies::CMPCOUNT;
@@ -260,18 +299,21 @@ bool cmPolicies::GetPolicyID(const char* id, cmPolicies::PolicyID& pid)
return stringToId(id, pid);
}
-///! return a warning string for a given policy
+//! return a warning string for a given policy
std::string cmPolicies::GetPolicyWarning(cmPolicies::PolicyID id)
{
std::ostringstream msg;
- msg << "Policy " << idToString(id) << " is not set: "
- ""
- << idToShortDescription(id) << " "
- "Run \"cmake --help-policy "
- << idToString(id) << "\" for "
- "policy details. "
- "Use the cmake_policy command to set the policy "
- "and suppress this warning.";
+ msg << "Policy " << idToString(id)
+ << " is not set: "
+ ""
+ << idToShortDescription(id)
+ << " "
+ "Run \"cmake --help-policy "
+ << idToString(id)
+ << "\" for "
+ "policy details. "
+ "Use the cmake_policy command to set the policy "
+ "and suppress this warning.";
return msg.str();
}
@@ -291,30 +333,33 @@ std::string cmPolicies::GetPolicyDeprecatedWarning(cmPolicies::PolicyID id)
return msg.str();
}
-///! return an error string for when a required policy is unspecified
+//! return an error string for when a required policy is unspecified
std::string cmPolicies::GetRequiredPolicyError(cmPolicies::PolicyID id)
{
std::ostringstream error;
- error << "Policy " << idToString(id) << " is not set to NEW: "
- ""
- << idToShortDescription(id) << " "
- "Run \"cmake --help-policy "
+ error << "Policy " << idToString(id)
+ << " is not set to NEW: "
+ ""
+ << idToShortDescription(id)
+ << " "
+ "Run \"cmake --help-policy "
<< idToString(id)
<< "\" for "
"policy details. "
"CMake now requires this policy to be set to NEW by the project. "
"The policy may be set explicitly using the code\n"
" cmake_policy(SET "
- << idToString(id) << " NEW)\n"
- "or by upgrading all policies with the code\n"
- " cmake_policy(VERSION "
+ << idToString(id)
+ << " NEW)\n"
+ "or by upgrading all policies with the code\n"
+ " cmake_policy(VERSION "
<< idToVersion(id)
<< ") # or later\n"
"Run \"cmake --help-command cmake_policy\" for more information.";
return error.str();
}
-///! Get the default status for a policy
+//! Get the default status for a policy
cmPolicies::PolicyStatus cmPolicies::GetPolicyStatus(
cmPolicies::PolicyID /*unused*/)
{
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 69cbc1844..92c80bb4c 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -126,7 +126,7 @@ class cmMakefile;
3, 0, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0040, \
"The target in the TARGET signature of add_custom_command() must " \
- "exist.", \
+ "exist and must be defined in the current directory.", \
3, 0, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0041, \
"Error on relative include with generator expression.", 3, 0, 0, \
@@ -155,8 +155,9 @@ class cmMakefile;
3, 0, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0051, "List TARGET_OBJECTS in SOURCES target property.", \
3, 1, 0, cmPolicies::WARN) \
- SELECT(POLICY, CMP0052, "Reject source and build dirs in installed " \
- "INTERFACE_INCLUDE_DIRECTORIES.", \
+ SELECT(POLICY, CMP0052, \
+ "Reject source and build dirs in installed " \
+ "INTERFACE_INCLUDE_DIRECTORIES.", \
3, 1, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0053, \
"Simplify variable reference and escape sequence evaluation.", 3, 1, \
@@ -206,7 +207,90 @@ class cmMakefile;
cmPolicies::WARN) \
SELECT(POLICY, CMP0069, \
"INTERPROCEDURAL_OPTIMIZATION is enforced when enabled.", 3, 9, 0, \
- cmPolicies::WARN)
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0070, \
+ "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) \
+ SELECT(POLICY, CMP0072, \
+ "FindOpenGL prefers GLVND by default when available.", 3, 11, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0073, \
+ "Do not produce legacy _LIB_DEPENDS cache entries.", 3, 12, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0074, "find_package uses <PackageName>_ROOT variables.", \
+ 3, 12, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0075, \
+ "Include file check macros honor CMAKE_REQUIRED_LIBRARIES.", 3, 12, \
+ 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0076, \
+ "target_sources() command converts relative paths to absolute.", 3, \
+ 13, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0077, "option() honors normal variables.", 3, 13, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0078, "UseSWIG generates standard target names.", 3, 13, \
+ 0, cmPolicies::WARN) \
+ SELECT( \
+ POLICY, CMP0079, \
+ "target_link_libraries allows use with targets in other directories.", 3, \
+ 13, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0080, \
+ "BundleUtilities cannot be included at configure time.", 3, 13, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0081, \
+ "Relative paths not allowed in LINK_DIRECTORIES target property.", \
+ 3, 13, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0082, \
+ "Install rules from add_subdirectory() are interleaved with those " \
+ "in caller.", \
+ 3, 14, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0083, "Add PIE options when linking executable.", 3, 14, \
+ 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0084, \
+ "The FindQt module does not exist for find_package().", 3, 14, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0085, "$<IN_LIST:...> handles empty list items.", 3, 14, \
+ 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0086, \
+ "UseSWIG honors SWIG_MODULE_NAME via -module flag.", 3, 14, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0087, \
+ "Install CODE|SCRIPT allow the use of generator " \
+ "expressions.", \
+ 3, 14, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0088, \
+ "FindBISON runs bison in CMAKE_CURRENT_BINARY_DIR when executing.", \
+ 3, 14, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0089, \
+ "Compiler id for IBM Clang-based XL compilers is now XLClang.", 3, \
+ 15, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0090, \
+ "export(PACKAGE) does not populate package registry by default.", 3, \
+ 15, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0091, \
+ "MSVC runtime library flags are selected by an abstraction.", 3, 15, \
+ 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0092, \
+ "MSVC warning flags are not in CMAKE_<LANG>_FLAGS by default.", 3, \
+ 15, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0093, "FindBoost reports Boost_VERSION in x.y.z format.", \
+ 3, 15, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0094, \
+ "FindPython3, FindPython2 and FindPyton use " \
+ "LOCATION for lookup strategy.", \
+ 3, 15, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0095, \
+ "RPATH entries are properly escaped in the intermediary CMake " \
+ "install script.", \
+ 3, 16, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0096, \
+ "project() preserves leading zeros in version components.", 3, 16, \
+ 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0097, \
+ "ExternalProject_Add with GIT_SUBMODULES \"\" initializes no " \
+ "submodules.", \
+ 3, 16, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
@@ -220,6 +304,7 @@ class cmMakefile;
F(CMP0021) \
F(CMP0022) \
F(CMP0027) \
+ F(CMP0037) \
F(CMP0038) \
F(CMP0041) \
F(CMP0042) \
@@ -229,14 +314,17 @@ class cmMakefile;
F(CMP0063) \
F(CMP0065) \
F(CMP0068) \
- F(CMP0069)
+ F(CMP0069) \
+ F(CMP0073) \
+ F(CMP0076) \
+ F(CMP0081) \
+ F(CMP0083) \
+ F(CMP0095)
/** \class cmPolicies
* \brief Handles changes in CMake behavior and policies
*
- * See the cmake wiki section on
- * <a href="https://cmake.org/Wiki/CMake/Policies">policies</a>
- * for an overview of this class's purpose
+ * See the cmake-policies(7) manual for an overview of this class's purpose.
*/
class cmPolicies
{
@@ -268,23 +356,27 @@ public:
CMPCOUNT
};
- ///! convert a string policy ID into a number
+ //! convert a string policy ID into a number
static bool GetPolicyID(const char* id, /* out */ cmPolicies::PolicyID& pid);
- ///! Get the default status for a policy
+ //! Get the default status for a policy
static cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id);
- ///! Set a policy level for this listfile
- static bool ApplyPolicyVersion(cmMakefile* mf, const char* version);
+ //! Set a policy level for this listfile
+ static bool ApplyPolicyVersion(cmMakefile* mf,
+ std::string const& version_min,
+ std::string const& version_max);
+ static bool ApplyPolicyVersion(cmMakefile* mf, unsigned int majorVer,
+ unsigned int minorVer, unsigned int patchVer);
- ///! return a warning string for a given policy
+ //! return a warning string for a given policy
static std::string GetPolicyWarning(cmPolicies::PolicyID id);
static std::string GetPolicyDeprecatedWarning(cmPolicies::PolicyID id);
- ///! return an error string for when a required policy is unspecified
+ //! return an error string for when a required policy is unspecified
static std::string GetRequiredPolicyError(cmPolicies::PolicyID id);
- ///! return an error string for when a required policy is unspecified
+ //! return an error string for when a required policy is unspecified
static std::string GetRequiredAlwaysPolicyError(cmPolicies::PolicyID id);
/** Represent a set of policy values. */
diff --git a/Source/cmProcessOutput.cxx b/Source/cmProcessOutput.cxx
index 617e1ca7d..e80ea5c8d 100644
--- a/Source/cmProcessOutput.cxx
+++ b/Source/cmProcessOutput.cxx
@@ -4,7 +4,7 @@
#include "cmProcessOutput.h"
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
unsigned int cmProcessOutput::defaultCodepage =
KWSYS_ENCODING_DEFAULT_CODEPAGE;
#endif
@@ -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;
@@ -48,9 +48,7 @@ cmProcessOutput::cmProcessOutput(Encoding encoding, unsigned int maxSize)
#endif
}
-cmProcessOutput::~cmProcessOutput()
-{
-}
+cmProcessOutput::~cmProcessOutput() = default;
bool cmProcessOutput::DecodeText(std::string raw, std::string& decoded,
size_t id)
diff --git a/Source/cmProcessOutput.h b/Source/cmProcessOutput.h
index b5ec4a8be..3db47a4b4 100644
--- a/Source/cmProcessOutput.h
+++ b/Source/cmProcessOutput.h
@@ -5,7 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include <stddef.h>
+#include <cstddef>
#include <string>
#include <vector>
@@ -28,10 +28,10 @@ public:
};
/**
- * Find encoding enum value for given encoding \a name.
- * \param name a encoding name.
- * \return encoding enum value or Auto if \a name was not found.
- */
+ * Find encoding enum value for given encoding \a name.
+ * \param name a encoding name.
+ * \return encoding enum value or Auto if \a name was not found.
+ */
static Encoding FindEncoding(std::string const& name);
/// The code page that is used as internal encoding to which we will encode.
diff --git a/Source/cmProcessTools.cxx b/Source/cmProcessTools.cxx
index de7b06126..9ebf5b771 100644
--- a/Source/cmProcessTools.cxx
+++ b/Source/cmProcessTools.cxx
@@ -1,31 +1,33 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmProcessTools.h"
-#include "cmProcessOutput.h"
-#include "cmsys/Process.h"
#include <ostream>
+#include "cmsys/Process.h"
+
+#include "cmProcessOutput.h"
+
void cmProcessTools::RunProcess(struct cmsysProcess_s* cp, OutputParser* out,
OutputParser* err, Encoding encoding)
{
cmsysProcess_Execute(cp);
- char* data = CM_NULLPTR;
+ char* data = nullptr;
int length = 0;
int p;
cmProcessOutput processOutput(encoding);
std::string strdata;
while ((out || err) &&
- (p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) {
+ (p = cmsysProcess_WaitForData(cp, &data, &length, nullptr))) {
if (out && p == cmsysProcess_Pipe_STDOUT) {
processOutput.DecodeText(data, length, strdata, 1);
if (!out->Process(strdata.c_str(), int(strdata.size()))) {
- out = CM_NULLPTR;
+ out = nullptr;
}
} else if (err && p == cmsysProcess_Pipe_STDERR) {
processOutput.DecodeText(data, length, strdata, 2);
if (!err->Process(strdata.c_str(), int(strdata.size()))) {
- err = CM_NULLPTR;
+ err = nullptr;
}
}
}
@@ -38,17 +40,14 @@ void cmProcessTools::RunProcess(struct cmsysProcess_s* cp, OutputParser* out,
if (err) {
processOutput.DecodeText(std::string(), strdata, 2);
if (!strdata.empty()) {
- out->Process(strdata.c_str(), int(strdata.size()));
+ err->Process(strdata.c_str(), int(strdata.size()));
}
}
- cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+ cmsysProcess_WaitForExit(cp, nullptr);
}
cmProcessTools::LineParser::LineParser(char sep, bool ignoreCR)
- : Log(CM_NULLPTR)
- , Prefix(CM_NULLPTR)
- , Separator(sep)
- , LineEnd('\0')
+ : Separator(sep)
, IgnoreCR(ignoreCR)
{
}
@@ -73,11 +72,11 @@ bool cmProcessTools::LineParser::ProcessChunk(const char* first, int length)
// Hand this line to the subclass implementation.
if (!this->ProcessLine()) {
- this->Line = "";
+ this->Line.clear();
return false;
}
- this->Line = "";
+ this->Line.clear();
} else if (*c != '\r' || !this->IgnoreCR) {
// Append this character to the line under construction.
this->Line.append(1, *c);
diff --git a/Source/cmProcessTools.h b/Source/cmProcessTools.h
index e7d9a10eb..21d59c463 100644
--- a/Source/cmProcessTools.h
+++ b/Source/cmProcessTools.h
@@ -3,13 +3,14 @@
#ifndef cmProcessTools_h
#define cmProcessTools_h
-#include "cmConfigure.h"
-#include "cmProcessOutput.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstring>
#include <iosfwd>
-#include <string.h>
#include <string>
+#include "cmProcessOutput.h"
+
/** \class cmProcessTools
* \brief Helper classes for process output parsing
*
@@ -17,7 +18,7 @@
class cmProcessTools
{
public:
- typedef cmProcessOutput::Encoding Encoding;
+ using Encoding = cmProcessOutput::Encoding;
/** Abstract interface for process output parsers. */
class OutputParser
{
@@ -34,7 +35,8 @@ public:
return this->Process(data, static_cast<int>(strlen(data)));
}
- virtual ~OutputParser() {}
+ virtual ~OutputParser() = default;
+
protected:
/** Implement in a subclass to process a chunk of data. It should
return true only if it is interested in more data. */
@@ -53,13 +55,13 @@ public:
void SetLog(std::ostream* log, const char* prefix);
protected:
- std::ostream* Log;
- const char* Prefix;
+ std::ostream* Log = nullptr;
+ const char* Prefix = nullptr;
std::string Line;
char Separator;
- char LineEnd;
+ char LineEnd = '\0';
bool IgnoreCR;
- bool ProcessChunk(const char* data, int length) CM_OVERRIDE;
+ bool ProcessChunk(const char* data, int length) override;
/** Implement in a subclass to process one line of input. It
should return true only if it is interested in more data. */
@@ -70,18 +72,18 @@ public:
class OutputLogger : public LineParser
{
public:
- OutputLogger(std::ostream& log, const char* prefix = CM_NULLPTR)
+ OutputLogger(std::ostream& log, const char* prefix = nullptr)
{
this->SetLog(&log, prefix);
}
private:
- bool ProcessLine() CM_OVERRIDE { return true; }
+ bool ProcessLine() override { return true; }
};
/** Run a process and send output to given parsers. */
static void RunProcess(struct cmsysProcess_s* cp, OutputParser* out,
- OutputParser* err = CM_NULLPTR,
+ OutputParser* err = nullptr,
Encoding encoding = cmProcessOutput::Auto);
};
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index d72c7909c..7bb5209da 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -2,52 +2,56 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmProjectCommand.h"
+#include <array>
+#include <cstddef>
+#include <cstdio>
+#include <functional>
+#include <limits>
+#include <utility>
+
#include "cmsys/RegularExpression.hxx"
-#include <sstream>
-#include <stdio.h>
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmake.h"
-class cmExecutionStatus;
+static bool IncludeByVariable(cmExecutionStatus& status,
+ const std::string& variable);
+static void TopLevelCMakeVarCondSet(cmMakefile& mf, std::string const& name,
+ std::string const& value);
-// cmProjectCommand
-bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmProjectCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("PROJECT called with incorrect number of arguments");
+ status.SetError("PROJECT called with incorrect number of arguments");
return false;
}
- std::string const& projectName = args[0];
-
- this->Makefile->SetProjectName(projectName);
+ cmMakefile& mf = status.GetMakefile();
+ if (!IncludeByVariable(status, "CMAKE_PROJECT_INCLUDE_BEFORE")) {
+ return false;
+ }
- std::string bindir = projectName;
- bindir += "_BINARY_DIR";
- std::string srcdir = projectName;
- srcdir += "_SOURCE_DIR";
+ std::string const& projectName = args[0];
- this->Makefile->AddCacheDefinition(
- bindir, this->Makefile->GetCurrentBinaryDirectory(),
- "Value Computed by CMake", cmStateEnums::STATIC);
- this->Makefile->AddCacheDefinition(
- srcdir, this->Makefile->GetCurrentSourceDirectory(),
- "Value Computed by CMake", cmStateEnums::STATIC);
+ mf.SetProjectName(projectName);
- bindir = "PROJECT_BINARY_DIR";
- srcdir = "PROJECT_SOURCE_DIR";
+ mf.AddCacheDefinition(projectName + "_BINARY_DIR",
+ mf.GetCurrentBinaryDirectory().c_str(),
+ "Value Computed by CMake", cmStateEnums::STATIC);
+ mf.AddCacheDefinition(projectName + "_SOURCE_DIR",
+ mf.GetCurrentSourceDirectory().c_str(),
+ "Value Computed by CMake", cmStateEnums::STATIC);
- this->Makefile->AddDefinition(bindir,
- this->Makefile->GetCurrentBinaryDirectory());
- this->Makefile->AddDefinition(srcdir,
- this->Makefile->GetCurrentSourceDirectory());
+ mf.AddDefinition("PROJECT_BINARY_DIR", mf.GetCurrentBinaryDirectory());
+ mf.AddDefinition("PROJECT_SOURCE_DIR", mf.GetCurrentSourceDirectory());
- this->Makefile->AddDefinition("PROJECT_NAME", projectName.c_str());
+ mf.AddDefinition("PROJECT_NAME", projectName);
// Set the CMAKE_PROJECT_NAME variable to be the highest-level
// project name in the tree. If there are two project commands
@@ -55,23 +59,29 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
// CMakeLists.txt file, then go with the last one, so that
// CMAKE_PROJECT_NAME will match PROJECT_NAME, and cmake --build
// will work.
- if (!this->Makefile->GetDefinition("CMAKE_PROJECT_NAME") ||
- (this->Makefile->IsRootMakefile())) {
- this->Makefile->AddDefinition("CMAKE_PROJECT_NAME", projectName.c_str());
- this->Makefile->AddCacheDefinition(
- "CMAKE_PROJECT_NAME", projectName.c_str(), "Value Computed by CMake",
- cmStateEnums::STATIC);
+ if (!mf.GetDefinition("CMAKE_PROJECT_NAME") || mf.IsRootMakefile()) {
+ mf.AddDefinition("CMAKE_PROJECT_NAME", projectName);
+ mf.AddCacheDefinition("CMAKE_PROJECT_NAME", projectName.c_str(),
+ "Value Computed by CMake", cmStateEnums::STATIC);
}
bool haveVersion = false;
bool haveLanguages = false;
bool haveDescription = false;
+ bool haveHomepage = false;
+ bool injectedProjectCommand = false;
std::string version;
std::string description;
+ std::string homepage;
std::vector<std::string> languages;
+ std::function<void()> missedValueReporter;
+ auto resetReporter = [&missedValueReporter]() {
+ missedValueReporter = std::function<void()>();
+ };
enum Doing
{
DoingDescription,
+ DoingHomepage,
DoingLanguages,
DoingVersion
};
@@ -79,175 +89,292 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
for (size_t i = 1; i < args.size(); ++i) {
if (args[i] == "LANGUAGES") {
if (haveLanguages) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR, "LANGUAGES may be specified at most once.");
+ mf.IssueMessage(MessageType::FATAL_ERROR,
+ "LANGUAGES may be specified at most once.");
cmSystemTools::SetFatalErrorOccured();
return true;
}
haveLanguages = true;
+ if (missedValueReporter) {
+ missedValueReporter();
+ }
doing = DoingLanguages;
+ if (!languages.empty()) {
+ std::string msg = cmStrCat(
+ "the following parameters must be specified after LANGUAGES "
+ "keyword: ",
+ cmJoin(languages, ", "), '.');
+ mf.IssueMessage(MessageType::WARNING, msg);
+ }
} else if (args[i] == "VERSION") {
if (haveVersion) {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
- "VERSION may be specified at most once.");
+ mf.IssueMessage(MessageType::FATAL_ERROR,
+ "VERSION may be specified at most once.");
cmSystemTools::SetFatalErrorOccured();
return true;
}
haveVersion = true;
+ if (missedValueReporter) {
+ missedValueReporter();
+ }
doing = DoingVersion;
+ missedValueReporter = [&mf, &resetReporter]() {
+ mf.IssueMessage(
+ MessageType::WARNING,
+ "VERSION keyword not followed by a value or was followed by a "
+ "value that expanded to nothing.");
+ resetReporter();
+ };
} else if (args[i] == "DESCRIPTION") {
if (haveDescription) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR, "DESCRITPION may be specified at most once.");
+ mf.IssueMessage(MessageType::FATAL_ERROR,
+ "DESCRIPTION may be specified at most once.");
cmSystemTools::SetFatalErrorOccured();
return true;
}
haveDescription = true;
+ if (missedValueReporter) {
+ missedValueReporter();
+ }
doing = DoingDescription;
+ missedValueReporter = [&mf, &resetReporter]() {
+ mf.IssueMessage(
+ MessageType::WARNING,
+ "DESCRIPTION keyword not followed by a value or was followed "
+ "by a value that expanded to nothing.");
+ resetReporter();
+ };
+ } else if (args[i] == "HOMEPAGE_URL") {
+ if (haveHomepage) {
+ mf.IssueMessage(MessageType::FATAL_ERROR,
+ "HOMEPAGE_URL may be specified at most once.");
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+ haveHomepage = true;
+ doing = DoingHomepage;
+ missedValueReporter = [&mf, &resetReporter]() {
+ mf.IssueMessage(
+ MessageType::WARNING,
+ "HOMEPAGE_URL keyword not followed by a value or was followed "
+ "by a value that expanded to nothing.");
+ resetReporter();
+ };
+ } else if (i == 1 && args[i] == "__CMAKE_INJECTED_PROJECT_COMMAND__") {
+ injectedProjectCommand = true;
} else if (doing == DoingVersion) {
doing = DoingLanguages;
version = args[i];
+ resetReporter();
} else if (doing == DoingDescription) {
doing = DoingLanguages;
description = args[i];
+ resetReporter();
+ } else if (doing == DoingHomepage) {
+ doing = DoingLanguages;
+ homepage = args[i];
+ resetReporter();
} else // doing == DoingLanguages
{
languages.push_back(args[i]);
}
}
- if (haveVersion && !haveLanguages && !languages.empty()) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
- "project with VERSION must use LANGUAGES before language names.");
+ if (missedValueReporter) {
+ missedValueReporter();
+ }
+
+ if ((haveVersion || haveDescription || haveHomepage) && !haveLanguages &&
+ !languages.empty()) {
+ mf.IssueMessage(MessageType::FATAL_ERROR,
+ "project with VERSION, DESCRIPTION or HOMEPAGE_URL must "
+ "use LANGUAGES before language names.");
cmSystemTools::SetFatalErrorOccured();
return true;
}
if (haveLanguages && languages.empty()) {
- languages.push_back("NONE");
+ languages.emplace_back("NONE");
}
- cmPolicies::PolicyStatus cmp0048 =
- this->Makefile->GetPolicyStatus(cmPolicies::CMP0048);
+ cmPolicies::PolicyStatus const cmp0048 =
+ mf.GetPolicyStatus(cmPolicies::CMP0048);
if (haveVersion) {
// Set project VERSION variables to given values
if (cmp0048 == cmPolicies::OLD || cmp0048 == cmPolicies::WARN) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
- "VERSION not allowed unless CMP0048 is set to NEW");
+ mf.IssueMessage(MessageType::FATAL_ERROR,
+ "VERSION not allowed unless CMP0048 is set to NEW");
cmSystemTools::SetFatalErrorOccured();
return true;
}
cmsys::RegularExpression vx(
- "^([0-9]+(\\.[0-9]+(\\.[0-9]+(\\.[0-9]+)?)?)?)?$");
+ R"(^([0-9]+(\.[0-9]+(\.[0-9]+(\.[0-9]+)?)?)?)?$)");
if (!vx.find(version)) {
- std::string e = "VERSION \"" + version + "\" format invalid.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e);
+ std::string e = R"(VERSION ")" + version + R"(" format invalid.)";
+ mf.IssueMessage(MessageType::FATAL_ERROR, e);
cmSystemTools::SetFatalErrorOccured();
return true;
}
- std::string vs;
- const char* sep = "";
- char vb[4][64];
- unsigned int v[4] = { 0, 0, 0, 0 };
- int vc =
- sscanf(version.c_str(), "%u.%u.%u.%u", &v[0], &v[1], &v[2], &v[3]);
- for (int i = 0; i < 4; ++i) {
- if (i < vc) {
- sprintf(vb[i], "%u", v[i]);
- vs += sep;
- vs += vb[i];
- sep = ".";
- } else {
- vb[i][0] = 0;
+ cmPolicies::PolicyStatus const cmp0096 =
+ mf.GetPolicyStatus(cmPolicies::CMP0096);
+
+ constexpr std::size_t MAX_VERSION_COMPONENTS = 4u;
+ std::string version_string;
+ std::array<std::string, MAX_VERSION_COMPONENTS> version_components;
+
+ if (cmp0096 == cmPolicies::OLD || cmp0096 == cmPolicies::WARN) {
+ char vb[MAX_VERSION_COMPONENTS]
+ [std::numeric_limits<unsigned>::digits10 + 2];
+ unsigned v[MAX_VERSION_COMPONENTS] = { 0, 0, 0, 0 };
+ const int vc = std::sscanf(version.c_str(), "%u.%u.%u.%u", &v[0], &v[1],
+ &v[2], &v[3]);
+ for (auto i = 0u; i < MAX_VERSION_COMPONENTS; ++i) {
+ if (int(i) < vc) {
+ std::sprintf(vb[i], "%u", v[i]);
+ version_string += &"."[std::size_t(i == 0)];
+ version_string += vb[i];
+ version_components[i] = vb[i];
+ } else {
+ vb[i][0] = '\x00';
+ }
+ }
+ } else {
+ // The regex above verified that we have a .-separated string of
+ // non-negative integer components. Keep the original string.
+ version_string = std::move(version);
+ // Split the integer components.
+ auto components = cmSystemTools::SplitString(version_string, '.');
+ for (auto i = 0u; i < components.size(); ++i) {
+ version_components[i] = std::move(components[i]);
}
}
std::string vv;
vv = projectName + "_VERSION";
- this->Makefile->AddDefinition("PROJECT_VERSION", vs.c_str());
- this->Makefile->AddDefinition(vv, vs.c_str());
+ mf.AddDefinition("PROJECT_VERSION", version_string);
+ mf.AddDefinition(vv, version_string);
vv = projectName + "_VERSION_MAJOR";
- this->Makefile->AddDefinition("PROJECT_VERSION_MAJOR", vb[0]);
- this->Makefile->AddDefinition(vv, vb[0]);
+ mf.AddDefinition("PROJECT_VERSION_MAJOR", version_components[0]);
+ mf.AddDefinition(vv, version_components[0]);
vv = projectName + "_VERSION_MINOR";
- this->Makefile->AddDefinition("PROJECT_VERSION_MINOR", vb[1]);
- this->Makefile->AddDefinition(vv, vb[1]);
+ mf.AddDefinition("PROJECT_VERSION_MINOR", version_components[1]);
+ mf.AddDefinition(vv, version_components[1]);
vv = projectName + "_VERSION_PATCH";
- this->Makefile->AddDefinition("PROJECT_VERSION_PATCH", vb[2]);
- this->Makefile->AddDefinition(vv, vb[2]);
+ mf.AddDefinition("PROJECT_VERSION_PATCH", version_components[2]);
+ mf.AddDefinition(vv, version_components[2]);
vv = projectName + "_VERSION_TWEAK";
- this->Makefile->AddDefinition("PROJECT_VERSION_TWEAK", vb[3]);
- this->Makefile->AddDefinition(vv, vb[3]);
+ mf.AddDefinition("PROJECT_VERSION_TWEAK", version_components[3]);
+ mf.AddDefinition(vv, version_components[3]);
+ // Also, try set top level variables
+ TopLevelCMakeVarCondSet(mf, "CMAKE_PROJECT_VERSION", version_string);
+ TopLevelCMakeVarCondSet(mf, "CMAKE_PROJECT_VERSION_MAJOR",
+ version_components[0]);
+ TopLevelCMakeVarCondSet(mf, "CMAKE_PROJECT_VERSION_MINOR",
+ version_components[1]);
+ TopLevelCMakeVarCondSet(mf, "CMAKE_PROJECT_VERSION_PATCH",
+ version_components[2]);
+ TopLevelCMakeVarCondSet(mf, "CMAKE_PROJECT_VERSION_TWEAK",
+ version_components[3]);
} else if (cmp0048 != cmPolicies::OLD) {
// Set project VERSION variables to empty
- std::vector<std::string> vv;
- vv.push_back("PROJECT_VERSION");
- vv.push_back("PROJECT_VERSION_MAJOR");
- vv.push_back("PROJECT_VERSION_MINOR");
- vv.push_back("PROJECT_VERSION_PATCH");
- vv.push_back("PROJECT_VERSION_TWEAK");
- vv.push_back(projectName + "_VERSION");
- vv.push_back(projectName + "_VERSION_MAJOR");
- vv.push_back(projectName + "_VERSION_MINOR");
- vv.push_back(projectName + "_VERSION_PATCH");
- vv.push_back(projectName + "_VERSION_TWEAK");
+ std::vector<std::string> vv = { "PROJECT_VERSION",
+ "PROJECT_VERSION_MAJOR",
+ "PROJECT_VERSION_MINOR",
+ "PROJECT_VERSION_PATCH",
+ "PROJECT_VERSION_TWEAK",
+ projectName + "_VERSION",
+ projectName + "_VERSION_MAJOR",
+ projectName + "_VERSION_MINOR",
+ projectName + "_VERSION_PATCH",
+ projectName + "_VERSION_TWEAK" };
+ if (mf.IsRootMakefile()) {
+ vv.emplace_back("CMAKE_PROJECT_VERSION");
+ vv.emplace_back("CMAKE_PROJECT_VERSION_MAJOR");
+ vv.emplace_back("CMAKE_PROJECT_VERSION_MINOR");
+ vv.emplace_back("CMAKE_PROJECT_VERSION_PATCH");
+ vv.emplace_back("CMAKE_PROJECT_VERSION_TWEAK");
+ }
std::string vw;
- for (std::vector<std::string>::iterator i = vv.begin(); i != vv.end();
- ++i) {
- const char* v = this->Makefile->GetDefinition(*i);
+ for (std::string const& i : vv) {
+ const char* const v = mf.GetDefinition(i);
if (v && *v) {
if (cmp0048 == cmPolicies::WARN) {
- vw += "\n ";
- vw += *i;
+ if (!injectedProjectCommand) {
+ vw += "\n ";
+ vw += i;
+ }
} else {
- this->Makefile->AddDefinition(*i, "");
+ mf.AddDefinition(i, "");
}
}
}
if (!vw.empty()) {
- std::ostringstream w;
- w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0048)
- << "\nThe following variable(s) would be set to empty:" << vw;
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ mf.IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0048),
+ "\nThe following variable(s) would be set to empty:", vw));
}
}
- if (haveDescription) {
- this->Makefile->AddDefinition("PROJECT_DESCRIPTION", description.c_str());
- // Set the CMAKE_PROJECT_DESCRIPTION variable to be the highest-level
- // project name in the tree. If there are two project commands
- // in the same CMakeLists.txt file, and it is the top level
- // CMakeLists.txt file, then go with the last one.
- if (!this->Makefile->GetDefinition("CMAKE_PROJECT_DESCRIPTION") ||
- (this->Makefile->IsRootMakefile())) {
- this->Makefile->AddDefinition("CMAKE_PROJECT_DESCRIPTION",
- description.c_str());
- this->Makefile->AddCacheDefinition(
- "CMAKE_PROJECT_DESCRIPTION", description.c_str(),
- "Value Computed by CMake", cmStateEnums::STATIC);
- }
- }
+ mf.AddDefinition("PROJECT_DESCRIPTION", description);
+ mf.AddDefinition(projectName + "_DESCRIPTION", description);
+ TopLevelCMakeVarCondSet(mf, "CMAKE_PROJECT_DESCRIPTION", description);
+
+ mf.AddDefinition("PROJECT_HOMEPAGE_URL", homepage);
+ mf.AddDefinition(projectName + "_HOMEPAGE_URL", homepage);
+ TopLevelCMakeVarCondSet(mf, "CMAKE_PROJECT_HOMEPAGE_URL", homepage);
if (languages.empty()) {
// if no language is specified do c and c++
- languages.push_back("C");
- languages.push_back("CXX");
+ languages = { "C", "CXX" };
}
- this->Makefile->EnableLanguage(languages, false);
- std::string extraInclude = "CMAKE_PROJECT_" + projectName + "_INCLUDE";
- const char* include = this->Makefile->GetDefinition(extraInclude);
- if (include) {
- bool readit = this->Makefile->ReadDependentFile(include);
- if (!readit && !cmSystemTools::GetFatalErrorOccured()) {
- std::string m = "could not find file:\n"
- " ";
- m += include;
- this->SetError(m);
- return false;
- }
+ mf.EnableLanguage(languages, false);
+
+ if (!IncludeByVariable(status, "CMAKE_PROJECT_INCLUDE")) {
+ return false;
}
+
+ if (!IncludeByVariable(status,
+ "CMAKE_PROJECT_" + projectName + "_INCLUDE")) {
+ return false;
+ }
+
return true;
}
+
+static bool IncludeByVariable(cmExecutionStatus& status,
+ const std::string& variable)
+{
+ cmMakefile& mf = status.GetMakefile();
+ const char* const include = mf.GetDefinition(variable);
+ if (!include) {
+ return true;
+ }
+
+ const bool readit = mf.ReadDependentFile(include);
+ if (readit) {
+ return true;
+ }
+
+ if (cmSystemTools::GetFatalErrorOccured()) {
+ return true;
+ }
+
+ status.SetError(cmStrCat("could not find file:\n ", include));
+ return false;
+}
+
+static void TopLevelCMakeVarCondSet(cmMakefile& mf, std::string const& name,
+ std::string const& value)
+{
+ // Set the CMAKE_PROJECT_XXX variable to be the highest-level
+ // project name in the tree. If there are two project commands
+ // in the same CMakeLists.txt file, and it is the top level
+ // CMakeLists.txt file, then go with the last one.
+ if (!mf.GetDefinition(name) || mf.IsRootMakefile()) {
+ mf.AddDefinition(name, value);
+ mf.AddCacheDefinition(name, value.c_str(), "Value Computed by CMake",
+ cmStateEnums::STATIC);
+ }
+}
diff --git a/Source/cmProjectCommand.h b/Source/cmProjectCommand.h
index 3c579ac9d..c06b4594c 100644
--- a/Source/cmProjectCommand.h
+++ b/Source/cmProjectCommand.h
@@ -3,37 +3,14 @@
#ifndef cmProjectCommand_h
#define cmProjectCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmProjectCommand
- * \brief Specify the name for this build project.
- *
- * cmProjectCommand is used to specify a name for this build project.
- * It is defined once per set of CMakeList.txt files (including
- * all subdirectories). Currently it just sets the name of the workspace
- * file for Microsoft Visual C++
- */
-class cmProjectCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmProjectCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmProjectCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmProperty.cxx b/Source/cmProperty.cxx
deleted file mode 100644
index 222afb497..000000000
--- a/Source/cmProperty.cxx
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmProperty.h"
-
-#include "cmConfigure.h"
-
-void cmProperty::Set(const char* value)
-{
- this->Value = value;
- this->ValueHasBeenSet = true;
-}
-
-void cmProperty::Append(const char* value, bool asString)
-{
- if (!this->Value.empty() && *value && !asString) {
- this->Value += ";";
- }
- this->Value += value;
- this->ValueHasBeenSet = true;
-}
-
-const char* cmProperty::GetValue() const
-{
- if (this->ValueHasBeenSet) {
- return this->Value.c_str();
- }
- return CM_NULLPTR;
-}
diff --git a/Source/cmProperty.h b/Source/cmProperty.h
index d11c5efbb..80f131a76 100644
--- a/Source/cmProperty.h
+++ b/Source/cmProperty.h
@@ -5,8 +5,6 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include <string>
-
class cmProperty
{
public:
@@ -22,22 +20,6 @@ public:
CACHED_VARIABLE,
INSTALL
};
-
- // set this property
- void Set(const char* value);
-
- // append to this property
- void Append(const char* value, bool asString = false);
-
- // get the value
- const char* GetValue() const;
-
- // construct with the value not set
- cmProperty() { this->ValueHasBeenSet = false; }
-
-protected:
- std::string Value;
- bool ValueHasBeenSet;
};
#endif
diff --git a/Source/cmPropertyDefinition.h b/Source/cmPropertyDefinition.h
index 9adff4902..0d68c328b 100644
--- a/Source/cmPropertyDefinition.h
+++ b/Source/cmPropertyDefinition.h
@@ -5,10 +5,10 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmProperty.h"
-
#include <string>
+#include "cmProperty.h"
+
/** \class cmPropertyDefinition
* \brief Property meta-information
*
diff --git a/Source/cmPropertyDefinitionMap.cxx b/Source/cmPropertyDefinitionMap.cxx
index 5daaf9ba3..f752ed7c6 100644
--- a/Source/cmPropertyDefinitionMap.cxx
+++ b/Source/cmPropertyDefinitionMap.cxx
@@ -10,7 +10,7 @@ void cmPropertyDefinitionMap::DefineProperty(const std::string& name,
const char* FullDescription,
bool chain)
{
- cmPropertyDefinitionMap::iterator it = this->find(name);
+ auto it = this->find(name);
cmPropertyDefinition* prop;
if (it == this->end()) {
prop = &(*this)[name];
@@ -26,7 +26,7 @@ bool cmPropertyDefinitionMap::IsPropertyDefined(const std::string& name) const
bool cmPropertyDefinitionMap::IsPropertyChained(const std::string& name) const
{
- cmPropertyDefinitionMap::const_iterator it = this->find(name);
+ auto it = this->find(name);
if (it == this->end()) {
return false;
}
diff --git a/Source/cmPropertyDefinitionMap.h b/Source/cmPropertyDefinitionMap.h
index 97ba55391..8ec791033 100644
--- a/Source/cmPropertyDefinitionMap.h
+++ b/Source/cmPropertyDefinitionMap.h
@@ -5,12 +5,12 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmProperty.h"
-#include "cmPropertyDefinition.h"
-
#include <map>
#include <string>
+#include "cmProperty.h"
+#include "cmPropertyDefinition.h"
+
class cmPropertyDefinitionMap
: public std::map<std::string, cmPropertyDefinition>
{
diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx
index 1e089d1c8..a3d49460b 100644
--- a/Source/cmPropertyMap.cxx
+++ b/Source/cmPropertyMap.cxx
@@ -2,43 +2,22 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmPropertyMap.h"
-#include "cmConfigure.h"
#include <algorithm>
-#include <assert.h>
#include <utility>
-cmProperty* cmPropertyMap::GetOrCreateProperty(const std::string& name)
+void cmPropertyMap::Clear()
{
- cmPropertyMap::iterator it = this->find(name);
- cmProperty* prop;
- if (it == this->end()) {
- prop = &(*this)[name];
- } else {
- prop = &(it->second);
- }
- return prop;
-}
-
-std::vector<std::string> cmPropertyMap::GetPropertyList() const
-{
- std::vector<std::string> keyList;
- for (cmPropertyMap::const_iterator i = this->begin(), e = this->end();
- i != e; ++i) {
- keyList.push_back(i->first);
- }
- std::sort(keyList.begin(), keyList.end());
- return keyList;
+ Map_.clear();
}
void cmPropertyMap::SetProperty(const std::string& name, const char* value)
{
if (!value) {
- this->erase(name);
+ Map_.erase(name);
return;
}
- cmProperty* prop = this->GetOrCreateProperty(name);
- prop->Set(value);
+ Map_[name] = value;
}
void cmPropertyMap::AppendProperty(const std::string& name, const char* value,
@@ -49,17 +28,53 @@ void cmPropertyMap::AppendProperty(const std::string& name, const char* value,
return;
}
- cmProperty* prop = this->GetOrCreateProperty(name);
- prop->Append(value, asString);
+ {
+ std::string& pVal = Map_[name];
+ if (!pVal.empty() && !asString) {
+ pVal += ';';
+ }
+ pVal += value;
+ }
+}
+
+void cmPropertyMap::RemoveProperty(const std::string& name)
+{
+ Map_.erase(name);
}
const char* cmPropertyMap::GetPropertyValue(const std::string& name) const
{
- assert(!name.empty());
+ {
+ auto it = Map_.find(name);
+ if (it != Map_.end()) {
+ return it->second.c_str();
+ }
+ }
+ return nullptr;
+}
- cmPropertyMap::const_iterator it = this->find(name);
- if (it == this->end()) {
- return CM_NULLPTR;
+std::vector<std::string> cmPropertyMap::GetKeys() const
+{
+ std::vector<std::string> keyList;
+ keyList.reserve(Map_.size());
+ for (auto const& item : Map_) {
+ keyList.push_back(item.first);
+ }
+ std::sort(keyList.begin(), keyList.end());
+ return keyList;
+}
+
+std::vector<std::pair<std::string, std::string>> cmPropertyMap::GetList() const
+{
+ using StringPair = std::pair<std::string, std::string>;
+ std::vector<StringPair> kvList;
+ kvList.reserve(Map_.size());
+ for (auto const& item : Map_) {
+ kvList.emplace_back(item.first, item.second);
}
- return it->second.GetValue();
+ std::sort(kvList.begin(), kvList.end(),
+ [](StringPair const& a, StringPair const& b) {
+ return a.first < b.first;
+ });
+ return kvList;
}
diff --git a/Source/cmPropertyMap.h b/Source/cmPropertyMap.h
index 5a0515076..9aed34960 100644
--- a/Source/cmPropertyMap.h
+++ b/Source/cmPropertyMap.h
@@ -5,25 +5,47 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmProperty.h"
-
-#include <map>
#include <string>
+#include <unordered_map>
+#include <utility>
#include <vector>
-class cmPropertyMap : public std::map<std::string, cmProperty>
+/** \class cmPropertyMap
+ * \brief String property map.
+ */
+class cmPropertyMap
{
public:
- cmProperty* GetOrCreateProperty(const std::string& name);
+ // -- General
+
+ //! Clear property list
+ void Clear();
- std::vector<std::string> GetPropertyList() const;
+ // -- Properties
+ //! Set the property value
void SetProperty(const std::string& name, const char* value);
+ //! Append to the property value
void AppendProperty(const std::string& name, const char* value,
bool asString = false);
+ //! Get the property value
const char* GetPropertyValue(const std::string& name) const;
+
+ //! Remove the property @a name from the map
+ void RemoveProperty(const std::string& name);
+
+ // -- Lists
+
+ //! Get a sorted list of property keys
+ std::vector<std::string> GetKeys() const;
+
+ //! Get a sorted by key list of property key,value pairs
+ std::vector<std::pair<std::string, std::string>> GetList() const;
+
+private:
+ std::unordered_map<std::string, std::string> Map_;
};
#endif
diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx
index de9e54505..cc4df8f89 100644
--- a/Source/cmQTWrapCPPCommand.cxx
+++ b/Source/cmQTWrapCPPCommand.cxx
@@ -3,58 +3,57 @@
#include "cmQTWrapCPPCommand.h"
#include "cmCustomCommandLines.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
-
-// cmQTWrapCPPCommand
-bool cmQTWrapCPPCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmQTWrapCPPCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 3) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
+ cmMakefile& mf = status.GetMakefile();
+
// Get the moc executable to run in the custom command.
- const char* moc_exe =
- this->Makefile->GetRequiredDefinition("QT_MOC_EXECUTABLE");
+ std::string const& moc_exe = mf.GetRequiredDefinition("QT_MOC_EXECUTABLE");
// Get the variable holding the list of sources.
std::string const& sourceList = args[1];
- std::string sourceListValue = this->Makefile->GetSafeDefinition(sourceList);
+ std::string sourceListValue = mf.GetSafeDefinition(sourceList);
// Create a rule for all sources listed.
- for (std::vector<std::string>::const_iterator j = (args.begin() + 2);
- j != args.end(); ++j) {
- cmSourceFile* curr = this->Makefile->GetSource(*j);
+ for (std::string const& arg : cmMakeRange(args).advance(2)) {
+ cmSourceFile* curr = mf.GetSource(arg);
// if we should wrap the class
if (!(curr && curr->GetPropertyAsBool("WRAP_EXCLUDE"))) {
// Compute the name of the file to generate.
- std::string srcName = cmSystemTools::GetFilenameWithoutLastExtension(*j);
- std::string newName = this->Makefile->GetCurrentBinaryDirectory();
- newName += "/moc_";
- newName += srcName;
- newName += ".cxx";
- cmSourceFile* sf = this->Makefile->GetOrCreateSource(newName, true);
+ std::string srcName =
+ cmSystemTools::GetFilenameWithoutLastExtension(arg);
+ std::string newName =
+ cmStrCat(mf.GetCurrentBinaryDirectory(), "/moc_", srcName, ".cxx");
+ cmSourceFile* sf = mf.GetOrCreateSource(newName, true);
if (curr) {
sf->SetProperty("ABSTRACT", curr->GetProperty("ABSTRACT"));
}
// Compute the name of the header from which to generate the file.
std::string hname;
- if (cmSystemTools::FileIsFullPath(j->c_str())) {
- hname = *j;
+ if (cmSystemTools::FileIsFullPath(arg)) {
+ hname = arg;
} else {
- if (curr && curr->GetPropertyAsBool("GENERATED")) {
- hname = this->Makefile->GetCurrentBinaryDirectory();
+ if (curr && curr->GetIsGenerated()) {
+ hname = mf.GetCurrentBinaryDirectory();
} else {
- hname = this->Makefile->GetCurrentSourceDirectory();
+ hname = mf.GetCurrentSourceDirectory();
}
hname += "/";
- hname += *j;
+ hname += arg;
}
// Append the generated source file to the list.
@@ -64,28 +63,22 @@ bool cmQTWrapCPPCommand::InitialPass(std::vector<std::string> const& args,
sourceListValue += newName;
// Create the custom command to generate the file.
- cmCustomCommandLine commandLine;
- commandLine.push_back(moc_exe);
- commandLine.push_back("-o");
- commandLine.push_back(newName);
- commandLine.push_back(hname);
-
- cmCustomCommandLines commandLines;
- commandLines.push_back(commandLine);
+ cmCustomCommandLines commandLines =
+ cmMakeSingleCommandLine({ moc_exe, "-o", newName, hname });
std::vector<std::string> depends;
depends.push_back(moc_exe);
depends.push_back(hname);
std::string no_main_dependency;
- const char* no_working_dir = CM_NULLPTR;
- this->Makefile->AddCustomCommandToOutput(
- newName, depends, no_main_dependency, commandLines, "Qt Wrapped File",
- no_working_dir);
+ const char* no_working_dir = nullptr;
+ mf.AddCustomCommandToOutput(newName, depends, no_main_dependency,
+ commandLines, "Qt Wrapped File",
+ no_working_dir);
}
}
// Store the final list of source files.
- this->Makefile->AddDefinition(sourceList, sourceListValue.c_str());
+ mf.AddDefinition(sourceList, sourceListValue);
return true;
}
diff --git a/Source/cmQTWrapCPPCommand.h b/Source/cmQTWrapCPPCommand.h
index ad1ccf38d..75fa18028 100644
--- a/Source/cmQTWrapCPPCommand.h
+++ b/Source/cmQTWrapCPPCommand.h
@@ -3,35 +3,14 @@
#ifndef cmQTWrapCPPCommand_h
#define cmQTWrapCPPCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmQTWrapCPPCommand
- * \brief Create moc file rules for Qt classes
- *
- * cmQTWrapCPPCommand is used to create wrappers for Qt classes into
- * normal C++
- */
-class cmQTWrapCPPCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmQTWrapCPPCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmQTWrapCPPCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmQTWrapUICommand.cxx b/Source/cmQTWrapUICommand.cxx
index d3c663176..66c0228fc 100644
--- a/Source/cmQTWrapUICommand.cxx
+++ b/Source/cmQTWrapUICommand.cxx
@@ -3,66 +3,60 @@
#include "cmQTWrapUICommand.h"
#include "cmCustomCommandLines.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
-
-// cmQTWrapUICommand
-bool cmQTWrapUICommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmQTWrapUICommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 4) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
+ cmMakefile& mf = status.GetMakefile();
+
// Get the uic and moc executables to run in the custom commands.
- const char* uic_exe =
- this->Makefile->GetRequiredDefinition("QT_UIC_EXECUTABLE");
- const char* moc_exe =
- this->Makefile->GetRequiredDefinition("QT_MOC_EXECUTABLE");
+ std::string const& uic_exe = mf.GetRequiredDefinition("QT_UIC_EXECUTABLE");
+ std::string const& moc_exe = mf.GetRequiredDefinition("QT_MOC_EXECUTABLE");
// Get the variable holding the list of sources.
std::string const& headerList = args[1];
std::string const& sourceList = args[2];
- std::string headerListValue = this->Makefile->GetSafeDefinition(headerList);
- std::string sourceListValue = this->Makefile->GetSafeDefinition(sourceList);
+ std::string headerListValue = mf.GetSafeDefinition(headerList);
+ std::string sourceListValue = mf.GetSafeDefinition(sourceList);
// Create rules for all sources listed.
- for (std::vector<std::string>::const_iterator j = (args.begin() + 3);
- j != args.end(); ++j) {
- cmSourceFile* curr = this->Makefile->GetSource(*j);
+ for (std::string const& arg : cmMakeRange(args).advance(3)) {
+ cmSourceFile* curr = mf.GetSource(arg);
// if we should wrap the class
if (!(curr && curr->GetPropertyAsBool("WRAP_EXCLUDE"))) {
// Compute the name of the files to generate.
- std::string srcName = cmSystemTools::GetFilenameWithoutLastExtension(*j);
- std::string hName = this->Makefile->GetCurrentBinaryDirectory();
- hName += "/";
- hName += srcName;
- hName += ".h";
- std::string cxxName = this->Makefile->GetCurrentBinaryDirectory();
- cxxName += "/";
- cxxName += srcName;
- cxxName += ".cxx";
- std::string mocName = this->Makefile->GetCurrentBinaryDirectory();
- mocName += "/moc_";
- mocName += srcName;
- mocName += ".cxx";
+ std::string srcName =
+ cmSystemTools::GetFilenameWithoutLastExtension(arg);
+ std::string hName =
+ cmStrCat(mf.GetCurrentBinaryDirectory(), '/', srcName, ".h");
+ std::string cxxName =
+ cmStrCat(mf.GetCurrentBinaryDirectory(), '/', srcName, ".cxx");
+ std::string mocName =
+ cmStrCat(mf.GetCurrentBinaryDirectory(), "/moc_", srcName, ".cxx");
// Compute the name of the ui file from which to generate others.
std::string uiName;
- if (cmSystemTools::FileIsFullPath(j->c_str())) {
- uiName = *j;
+ if (cmSystemTools::FileIsFullPath(arg)) {
+ uiName = arg;
} else {
- if (curr && curr->GetPropertyAsBool("GENERATED")) {
- uiName = this->Makefile->GetCurrentBinaryDirectory();
+ if (curr && curr->GetIsGenerated()) {
+ uiName = mf.GetCurrentBinaryDirectory();
} else {
- uiName = this->Makefile->GetCurrentSourceDirectory();
+ uiName = mf.GetCurrentSourceDirectory();
}
uiName += "/";
- uiName += *j;
+ uiName += arg;
}
// create the list of headers
@@ -80,56 +74,34 @@ bool cmQTWrapUICommand::InitialPass(std::vector<std::string> const& args,
sourceListValue += mocName;
// set up .ui to .h and .cxx command
- cmCustomCommandLine hCommand;
- hCommand.push_back(uic_exe);
- hCommand.push_back("-o");
- hCommand.push_back(hName);
- hCommand.push_back(uiName);
- cmCustomCommandLines hCommandLines;
- hCommandLines.push_back(hCommand);
-
- cmCustomCommandLine cxxCommand;
- cxxCommand.push_back(uic_exe);
- cxxCommand.push_back("-impl");
- cxxCommand.push_back(hName);
- cxxCommand.push_back("-o");
- cxxCommand.push_back(cxxName);
- cxxCommand.push_back(uiName);
- cmCustomCommandLines cxxCommandLines;
- cxxCommandLines.push_back(cxxCommand);
-
- cmCustomCommandLine mocCommand;
- mocCommand.push_back(moc_exe);
- mocCommand.push_back("-o");
- mocCommand.push_back(mocName);
- mocCommand.push_back(hName);
- cmCustomCommandLines mocCommandLines;
- mocCommandLines.push_back(mocCommand);
+ cmCustomCommandLines hCommandLines =
+ cmMakeSingleCommandLine({ uic_exe, "-o", hName, uiName });
+ cmCustomCommandLines cxxCommandLines = cmMakeSingleCommandLine(
+ { uic_exe, "-impl", hName, "-o", cxxName, uiName });
+ cmCustomCommandLines mocCommandLines =
+ cmMakeSingleCommandLine({ moc_exe, "-o", mocName, hName });
std::vector<std::string> depends;
depends.push_back(uiName);
std::string no_main_dependency;
- const char* no_comment = CM_NULLPTR;
- const char* no_working_dir = CM_NULLPTR;
- this->Makefile->AddCustomCommandToOutput(
- hName, depends, no_main_dependency, hCommandLines, no_comment,
- no_working_dir);
+ const char* no_comment = nullptr;
+ const char* no_working_dir = nullptr;
+ mf.AddCustomCommandToOutput(hName, depends, no_main_dependency,
+ hCommandLines, no_comment, no_working_dir);
depends.push_back(hName);
- this->Makefile->AddCustomCommandToOutput(
- cxxName, depends, no_main_dependency, cxxCommandLines, no_comment,
- no_working_dir);
+ mf.AddCustomCommandToOutput(cxxName, depends, no_main_dependency,
+ cxxCommandLines, no_comment, no_working_dir);
depends.clear();
depends.push_back(hName);
- this->Makefile->AddCustomCommandToOutput(
- mocName, depends, no_main_dependency, mocCommandLines, no_comment,
- no_working_dir);
+ mf.AddCustomCommandToOutput(mocName, depends, no_main_dependency,
+ mocCommandLines, no_comment, no_working_dir);
}
}
// Store the final list of source files and headers.
- this->Makefile->AddDefinition(sourceList, sourceListValue.c_str());
- this->Makefile->AddDefinition(headerList, headerListValue.c_str());
+ mf.AddDefinition(sourceList, sourceListValue);
+ mf.AddDefinition(headerList, headerListValue);
return true;
}
diff --git a/Source/cmQTWrapUICommand.h b/Source/cmQTWrapUICommand.h
index ac7ab01c7..a17ef547d 100644
--- a/Source/cmQTWrapUICommand.h
+++ b/Source/cmQTWrapUICommand.h
@@ -3,34 +3,14 @@
#ifndef cmQTWrapUICommand_h
#define cmQTWrapUICommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmQTWrapUICommand
- * \brief Create .h and .cxx files rules for Qt user interfaces files
- *
- * cmQTWrapUICommand is used to create wrappers for Qt classes into normal C++
- */
-class cmQTWrapUICommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmQTWrapUICommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmQTWrapUICommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
new file mode 100644
index 000000000..eb7c900c3
--- /dev/null
+++ b/Source/cmQtAutoGen.cxx
@@ -0,0 +1,385 @@
+/* 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 <algorithm>
+#include <array>
+#include <initializer_list>
+#include <sstream>
+#include <utility>
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmAlgorithms.h"
+#include "cmDuration.h"
+#include "cmProcessOutput.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+// - Static functions
+
+/// @brief Merges newOpts into baseOpts
+/// @arg valueOpts list of options that accept a value
+void MergeOptions(std::vector<std::string>& baseOpts,
+ std::vector<std::string> const& newOpts,
+ std::initializer_list<cm::string_view> valueOpts, bool isQt5)
+{
+ if (newOpts.empty()) {
+ return;
+ }
+ if (baseOpts.empty()) {
+ baseOpts = newOpts;
+ return;
+ }
+
+ std::vector<std::string> extraOpts;
+ for (auto fit = newOpts.begin(), fitEnd = newOpts.end(); fit != fitEnd;
+ ++fit) {
+ std::string const& newOpt = *fit;
+ auto existIt = std::find(baseOpts.begin(), baseOpts.end(), newOpt);
+ if (existIt != baseOpts.end()) {
+ if (newOpt.size() >= 2) {
+ // Acquire the option name
+ std::string optName;
+ {
+ auto oit = newOpt.begin();
+ if (*oit == '-') {
+ ++oit;
+ if (isQt5 && (*oit == '-')) {
+ ++oit;
+ }
+ optName.assign(oit, newOpt.end());
+ }
+ }
+ // Test if this is a value option and change the existing value
+ if (!optName.empty() && cmContains(valueOpts, optName)) {
+ const auto existItNext(existIt + 1);
+ const auto fitNext(fit + 1);
+ if ((existItNext != baseOpts.end()) && (fitNext != fitEnd)) {
+ *existItNext = *fitNext;
+ ++fit;
+ }
+ }
+ }
+ } else {
+ extraOpts.push_back(newOpt);
+ }
+ }
+ // Append options
+ cmAppend(baseOpts, extraOpts);
+}
+
+// - Class definitions
+
+unsigned int const cmQtAutoGen::ParallelMax = 64;
+
+cm::string_view cmQtAutoGen::GeneratorName(GenT genType)
+{
+ switch (genType) {
+ case GenT::GEN:
+ return "AutoGen";
+ case GenT::MOC:
+ return "AutoMoc";
+ case GenT::UIC:
+ return "AutoUic";
+ case GenT::RCC:
+ return "AutoRcc";
+ }
+ return "AutoGen";
+}
+
+cm::string_view cmQtAutoGen::GeneratorNameUpper(GenT genType)
+{
+ switch (genType) {
+ case GenT::GEN:
+ return "AUTOGEN";
+ case GenT::MOC:
+ return "AUTOMOC";
+ case GenT::UIC:
+ return "AUTOUIC";
+ case GenT::RCC:
+ return "AUTORCC";
+ }
+ return "AUTOGEN";
+}
+
+std::string cmQtAutoGen::Tools(bool moc, bool uic, bool rcc)
+{
+ std::array<cm::string_view, 3> lst;
+ decltype(lst)::size_type num = 0;
+ if (moc) {
+ lst.at(num++) = "AUTOMOC";
+ }
+ if (uic) {
+ lst.at(num++) = "AUTOUIC";
+ }
+ if (rcc) {
+ lst.at(num++) = "AUTORCC";
+ }
+ switch (num) {
+ case 1:
+ return std::string(lst[0]);
+ case 2:
+ return cmStrCat(lst[0], " and ", lst[1]);
+ case 3:
+ return cmStrCat(lst[0], ", ", lst[1], " and ", lst[2]);
+ default:
+ break;
+ }
+ return std::string();
+}
+
+std::string cmQtAutoGen::Quoted(cm::string_view text)
+{
+ static std::initializer_list<std::pair<const char*, const char*>> const
+ replacements = { { "\\", "\\\\" }, { "\"", "\\\"" }, { "\a", "\\a" },
+ { "\b", "\\b" }, { "\f", "\\f" }, { "\n", "\\n" },
+ { "\r", "\\r" }, { "\t", "\\t" }, { "\v", "\\v" } };
+
+ std::string res(text);
+ for (auto const& pair : replacements) {
+ cmSystemTools::ReplaceString(res, pair.first, pair.second);
+ }
+ return cmStrCat('"', 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::FileNameWithoutLastExtension(cm::string_view filename)
+{
+ auto slashPos = filename.rfind('/');
+ if (slashPos != cm::string_view::npos) {
+ filename.remove_prefix(slashPos + 1);
+ }
+ auto dotPos = filename.rfind('.');
+ return std::string(filename.substr(0, dotPos));
+}
+
+std::string cmQtAutoGen::ParentDir(cm::string_view filename)
+{
+ auto slashPos = filename.rfind('/');
+ if (slashPos == cm::string_view::npos) {
+ return std::string();
+ }
+ return std::string(filename.substr(0, slashPos));
+}
+
+std::string cmQtAutoGen::SubDirPrefix(cm::string_view filename)
+{
+ auto slashPos = filename.rfind('/');
+ if (slashPos == cm::string_view::npos) {
+ return std::string();
+ }
+ return std::string(filename.substr(0, slashPos + 1));
+}
+
+std::string cmQtAutoGen::AppendFilenameSuffix(cm::string_view filename,
+ cm::string_view suffix)
+{
+ auto dotPos = filename.rfind('.');
+ if (dotPos == cm::string_view::npos) {
+ return cmStrCat(filename, suffix);
+ }
+ return cmStrCat(filename.substr(0, dotPos), suffix,
+ filename.substr(dotPos, filename.size() - dotPos));
+}
+
+void cmQtAutoGen::UicMergeOptions(std::vector<std::string>& baseOpts,
+ std::vector<std::string> const& newOpts,
+ bool isQt5)
+{
+ static std::initializer_list<cm::string_view> const valueOpts = {
+ "tr", "translate", "postfix", "generator",
+ "include", // Since Qt 5.3
+ "g"
+ };
+ MergeOptions(baseOpts, newOpts, valueOpts, isQt5);
+}
+
+void cmQtAutoGen::RccMergeOptions(std::vector<std::string>& baseOpts,
+ std::vector<std::string> const& newOpts,
+ bool isQt5)
+{
+ static std::initializer_list<cm::string_view> const valueOpts = {
+ "name", "root", "compress", "threshold"
+ };
+ MergeOptions(baseOpts, newOpts, valueOpts, isQt5);
+}
+
+static void RccListParseContent(std::string const& content,
+ std::vector<std::string>& files)
+{
+ 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()));
+ }
+ }
+}
+
+static bool 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 = cmStrCat("rcc lists unparsable output:\n",
+ cmQtAutoGen::Quoted(eline), '\n');
+ return false;
+ }
+ pos += searchString.length();
+ std::string::size_type sz = eline.size() - pos - 1;
+ files.push_back(eline.substr(pos, sz));
+ }
+ }
+ }
+
+ return true;
+}
+
+cmQtAutoGen::RccLister::RccLister() = default;
+
+cmQtAutoGen::RccLister::RccLister(std::string rccExecutable,
+ std::vector<std::string> listOptions)
+ : RccExcutable_(std::move(rccExecutable))
+ , ListOptions_(std::move(listOptions))
+{
+}
+
+bool cmQtAutoGen::RccLister::list(std::string const& qrcFile,
+ std::vector<std::string>& files,
+ std::string& error, bool verbose) const
+{
+ error.clear();
+
+ if (!cmSystemTools::FileExists(qrcFile, true)) {
+ error =
+ cmStrCat("The resource file ", Quoted(qrcFile), " does not exist.");
+ 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(qrcFile);
+
+ if (!this->RccExcutable_.empty() &&
+ cmSystemTools::FileExists(this->RccExcutable_, true) &&
+ !this->ListOptions_.empty()) {
+
+ bool result = false;
+ int retVal = 0;
+ std::string rccStdOut;
+ std::string rccStdErr;
+ {
+ std::vector<std::string> cmd;
+ cmd.emplace_back(this->RccExcutable_);
+ cmAppend(cmd, this->ListOptions_);
+ cmd.emplace_back(cmSystemTools::GetFilenameName(qrcFile));
+
+ // Log command
+ if (verbose) {
+ cmSystemTools::Stdout(
+ cmStrCat("Running command:\n", QuotedCommand(cmd), '\n'));
+ }
+
+ result = cmSystemTools::RunSingleCommand(
+ cmd, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(),
+ cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
+ }
+ if (!result || retVal) {
+ error =
+ cmStrCat("The rcc list process failed for ", Quoted(qrcFile), '\n');
+ if (!rccStdOut.empty()) {
+ error += cmStrCat(rccStdOut, '\n');
+ }
+ if (!rccStdErr.empty()) {
+ error += cmStrCat(rccStdErr, '\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(qrcFile.c_str());
+ if (ifs) {
+ std::ostringstream osst;
+ osst << ifs.rdbuf();
+ qrcContents = osst.str();
+ } else {
+ error = cmStrCat("The resource file ", Quoted(qrcFile),
+ " is not readable\n");
+ return false;
+ }
+ }
+ // Parse string content
+ RccListParseContent(qrcContents, files);
+ }
+ }
+
+ // Convert relative paths to absolute paths
+ for (std::string& entry : files) {
+ entry = cmSystemTools::CollapseFullPath(entry, fileDir);
+ }
+ return true;
+}
diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h
new file mode 100644
index 000000000..a740ba30a
--- /dev/null
+++ b/Source/cmQtAutoGen.h
@@ -0,0 +1,145 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmQtAutoGen_h
+#define cmQtAutoGen_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <cm/string_view>
+
+/** \class cmQtAutoGen
+ * \brief Common base class for QtAutoGen classes
+ */
+class cmQtAutoGen
+{
+public:
+ /** Integer version. */
+ struct IntegerVersion
+ {
+ unsigned int Major = 0;
+ unsigned int Minor = 0;
+
+ IntegerVersion() = default;
+ IntegerVersion(unsigned int major, unsigned int minor)
+ : Major(major)
+ , Minor(minor)
+ {
+ }
+
+ bool operator>(IntegerVersion const version)
+ {
+ return (this->Major > version.Major) ||
+ ((this->Major == version.Major) && (this->Minor > version.Minor));
+ }
+
+ bool operator>=(IntegerVersion const version)
+ {
+ return (this->Major > version.Major) ||
+ ((this->Major == version.Major) && (this->Minor >= version.Minor));
+ }
+ };
+
+ /** Compiler features. */
+ class CompilerFeatures
+ {
+ public:
+ bool Evaluated = false;
+ std::string HelpOutput;
+ std::vector<std::string> ListOptions;
+ };
+ using CompilerFeaturesHandle = std::shared_ptr<CompilerFeatures>;
+
+ /** AutoGen generator type. */
+ enum class GenT
+ {
+ GEN, // AUTOGEN
+ MOC, // AUTOMOC
+ UIC, // AUTOUIC
+ RCC // AUTORCC
+ };
+
+ /// @brief Maximum number of parallel threads/processes in a generator
+ static unsigned int const ParallelMax;
+
+public:
+ /// @brief Returns the generator name
+ static cm::string_view GeneratorName(GenT genType);
+ /// @brief Returns the generator name in upper case
+ static cm::string_view GeneratorNameUpper(GenT genType);
+
+ /// @brief Returns a string with the requested tool names
+ static std::string Tools(bool moc, bool uic, bool rcc);
+
+ /// @brief Returns the string escaped and enclosed in quotes
+ static std::string Quoted(cm::string_view text);
+
+ static std::string QuotedCommand(std::vector<std::string> const& command);
+
+ /// @brief Returns the file name without path and extension (thread safe)
+ static std::string FileNameWithoutLastExtension(cm::string_view filename);
+
+ /// @brief Returns the parent directory of the file (thread safe)
+ static std::string ParentDir(cm::string_view filename);
+
+ /// @brief Returns the parent directory of the file with a "/" suffix
+ static std::string SubDirPrefix(cm::string_view filename);
+
+ /// @brief Appends the suffix to the filename before the last dot
+ static std::string AppendFilenameSuffix(cm::string_view filename,
+ cm::string_view suffix);
+
+ /// @brief Merges newOpts into baseOpts
+ static void UicMergeOptions(std::vector<std::string>& baseOpts,
+ std::vector<std::string> const& newOpts,
+ bool isQt5);
+
+ /// @brief Merges newOpts into baseOpts
+ static void RccMergeOptions(std::vector<std::string>& baseOpts,
+ std::vector<std::string> const& newOpts,
+ bool isQt5);
+
+ /** @class RccLister
+ * @brief Lists files in qrc resource files
+ */
+ class RccLister
+ {
+ public:
+ RccLister();
+ RccLister(std::string rccExecutable, std::vector<std::string> listOptions);
+
+ //! The rcc executable
+ std::string const& RccExcutable() const { return RccExcutable_; }
+ void SetRccExecutable(std::string const& rccExecutable)
+ {
+ RccExcutable_ = rccExecutable;
+ }
+
+ //! The rcc executable list options
+ std::vector<std::string> const& ListOptions() const
+ {
+ return ListOptions_;
+ }
+ void SetListOptions(std::vector<std::string> const& listOptions)
+ {
+ ListOptions_ = listOptions;
+ }
+
+ /**
+ * @brief Lists a files in the qrcFile
+ * @arg files The file names are appended to this list
+ * @arg error contains the error message when the function fails
+ */
+ bool list(std::string const& qrcFile, std::vector<std::string>& files,
+ std::string& error, bool verbose = false) const;
+
+ private:
+ std::string RccExcutable_;
+ std::vector<std::string> ListOptions_;
+ };
+};
+
+#endif
diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx
new file mode 100644
index 000000000..ef6b88636
--- /dev/null
+++ b/Source/cmQtAutoGenGlobalInitializer.cxx
@@ -0,0 +1,289 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmQtAutoGenGlobalInitializer.h"
+
+#include <utility>
+
+#include <cm/memory>
+
+#include "cmCustomCommandLines.h"
+#include "cmCustomCommandTypes.h"
+#include "cmDuration.h"
+#include "cmGeneratorTarget.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmProcessOutput.h"
+#include "cmQtAutoGen.h"
+#include "cmQtAutoGenInitializer.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+
+cmQtAutoGenGlobalInitializer::Keywords::Keywords()
+ : AUTOMOC("AUTOMOC")
+ , AUTOUIC("AUTOUIC")
+ , AUTORCC("AUTORCC")
+ , AUTOMOC_EXECUTABLE("AUTOMOC_EXECUTABLE")
+ , AUTOUIC_EXECUTABLE("AUTOUIC_EXECUTABLE")
+ , AUTORCC_EXECUTABLE("AUTORCC_EXECUTABLE")
+ , SKIP_AUTOGEN("SKIP_AUTOGEN")
+ , SKIP_AUTOMOC("SKIP_AUTOMOC")
+ , SKIP_AUTOUIC("SKIP_AUTOUIC")
+ , SKIP_AUTORCC("SKIP_AUTORCC")
+ , AUTOUIC_OPTIONS("AUTOUIC_OPTIONS")
+ , AUTORCC_OPTIONS("AUTORCC_OPTIONS")
+ , qrc("qrc")
+ , ui("ui")
+{
+}
+
+cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer(
+ std::vector<cmLocalGenerator*> const& localGenerators)
+{
+ for (cmLocalGenerator* localGen : localGenerators) {
+ // Detect global autogen and autorcc target names
+ bool globalAutoGenTarget = false;
+ bool globalAutoRccTarget = false;
+ {
+ cmMakefile* makefile = localGen->GetMakefile();
+ // Detect global autogen target name
+ if (cmIsOn(makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTOGEN_TARGET"))) {
+ std::string targetName =
+ makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTOGEN_TARGET_NAME");
+ if (targetName.empty()) {
+ targetName = "autogen";
+ }
+ GlobalAutoGenTargets_.emplace(localGen, std::move(targetName));
+ globalAutoGenTarget = true;
+ }
+
+ // Detect global autorcc target name
+ if (cmIsOn(makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTORCC_TARGET"))) {
+ std::string targetName =
+ makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTORCC_TARGET_NAME");
+ if (targetName.empty()) {
+ targetName = "autorcc";
+ }
+ GlobalAutoRccTargets_.emplace(localGen, std::move(targetName));
+ globalAutoRccTarget = true;
+ }
+ }
+
+ // Find targets that require AUTOMOC/UIC/RCC processing
+ for (cmGeneratorTarget* target : localGen->GetGeneratorTargets()) {
+ // Process only certain target types
+ switch (target->GetType()) {
+ case cmStateEnums::EXECUTABLE:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::OBJECT_LIBRARY:
+ // Process target
+ break;
+ default:
+ // Don't process target
+ continue;
+ }
+ if (target->IsImported()) {
+ // Don't process target
+ continue;
+ }
+
+ bool const moc = target->GetPropertyAsBool(kw().AUTOMOC);
+ bool const uic = target->GetPropertyAsBool(kw().AUTOUIC);
+ bool const rcc = target->GetPropertyAsBool(kw().AUTORCC);
+ if (moc || uic || rcc) {
+ std::string const mocExec =
+ target->GetSafeProperty(kw().AUTOMOC_EXECUTABLE);
+ std::string const uicExec =
+ target->GetSafeProperty(kw().AUTOUIC_EXECUTABLE);
+ std::string const rccExec =
+ target->GetSafeProperty(kw().AUTORCC_EXECUTABLE);
+
+ // We support Qt4, Qt5 and Qt6
+ auto qtVersion = cmQtAutoGenInitializer::GetQtVersion(target);
+ bool const validQt = (qtVersion.first.Major == 4) ||
+ (qtVersion.first.Major == 5) || (qtVersion.first.Major == 6);
+
+ bool const mocAvailable = (validQt || !mocExec.empty());
+ bool const uicAvailable = (validQt || !uicExec.empty());
+ bool const rccAvailable = (validQt || !rccExec.empty());
+ bool const mocIsValid = (moc && mocAvailable);
+ bool const uicIsValid = (uic && uicAvailable);
+ bool const rccIsValid = (rcc && rccAvailable);
+ // Disabled AUTOMOC/UIC/RCC warning
+ bool const mocDisabled = (moc && !mocAvailable);
+ bool const uicDisabled = (uic && !uicAvailable);
+ bool const rccDisabled = (rcc && !rccAvailable);
+ if (mocDisabled || uicDisabled || rccDisabled) {
+ cmAlphaNum version = (qtVersion.second == 0)
+ ? cmAlphaNum("<QTVERSION>")
+ : cmAlphaNum(qtVersion.second);
+ cmAlphaNum component = uicDisabled ? "Widgets" : "Core";
+
+ std::string const msg = cmStrCat(
+ "AUTOGEN: No valid Qt version found for target ",
+ target->GetName(), ". ",
+ cmQtAutoGen::Tools(mocDisabled, uicDisabled, rccDisabled),
+ " disabled. Consider adding:\n", " find_package(Qt", version,
+ " COMPONENTS ", component, ")\n", "to your CMakeLists.txt file.");
+ target->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, msg);
+ }
+ if (mocIsValid || uicIsValid || rccIsValid) {
+ // Create autogen target initializer
+ Initializers_.emplace_back(cm::make_unique<cmQtAutoGenInitializer>(
+ this, target, qtVersion.first, mocIsValid, uicIsValid, rccIsValid,
+ globalAutoGenTarget, globalAutoRccTarget));
+ }
+ }
+ }
+ }
+}
+
+cmQtAutoGenGlobalInitializer::~cmQtAutoGenGlobalInitializer() = default;
+
+void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget(
+ cmLocalGenerator* localGen, std::string const& name,
+ std::string const& comment)
+{
+ // Test if the target already exists
+ if (localGen->FindGeneratorTargetToUse(name) == nullptr) {
+ cmMakefile* makefile = localGen->GetMakefile();
+
+ // Create utility target
+ cmTarget* target = makefile->AddUtilityCommand(
+ name, cmCommandOrigin::Generator, true,
+ makefile->GetHomeOutputDirectory().c_str() /*work dir*/,
+ std::vector<std::string>() /*output*/,
+ std::vector<std::string>() /*depends*/, cmCustomCommandLines(), false,
+ comment.c_str());
+ localGen->AddGeneratorTarget(new cmGeneratorTarget(target, localGen));
+
+ // Set FOLDER property in the target
+ {
+ char const* folder =
+ makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
+ if (folder != nullptr) {
+ target->SetProperty("FOLDER", folder);
+ }
+ }
+ }
+}
+
+void cmQtAutoGenGlobalInitializer::AddToGlobalAutoGen(
+ cmLocalGenerator* localGen, std::string const& targetName)
+{
+ auto it = GlobalAutoGenTargets_.find(localGen);
+ if (it != GlobalAutoGenTargets_.end()) {
+ cmGeneratorTarget* target = localGen->FindGeneratorTargetToUse(it->second);
+ if (target != nullptr) {
+ target->Target->AddUtility(targetName, localGen->GetMakefile());
+ }
+ }
+}
+
+void cmQtAutoGenGlobalInitializer::AddToGlobalAutoRcc(
+ cmLocalGenerator* localGen, std::string const& targetName)
+{
+ auto it = GlobalAutoRccTargets_.find(localGen);
+ if (it != GlobalAutoRccTargets_.end()) {
+ cmGeneratorTarget* target = localGen->FindGeneratorTargetToUse(it->second);
+ if (target != nullptr) {
+ target->Target->AddUtility(targetName, localGen->GetMakefile());
+ }
+ }
+}
+
+cmQtAutoGen::CompilerFeaturesHandle
+cmQtAutoGenGlobalInitializer::GetCompilerFeatures(
+ std::string const& generator, std::string const& executable,
+ std::string& error)
+{
+ // Check if we have cached features
+ {
+ auto it = this->CompilerFeatures_.find(executable);
+ if (it != this->CompilerFeatures_.end()) {
+ return it->second;
+ }
+ }
+
+ // Check if the executable exists
+ if (!cmSystemTools::FileExists(executable, true)) {
+ error = cmStrCat("The \"", generator, "\" executable ",
+ cmQtAutoGen::Quoted(executable), " does not exist.");
+ return cmQtAutoGen::CompilerFeaturesHandle();
+ }
+
+ // Test the executable
+ std::string stdOut;
+ {
+ std::string stdErr;
+ std::vector<std::string> command;
+ command.emplace_back(executable);
+ command.emplace_back("-h");
+ int retVal = 0;
+ const bool runResult = cmSystemTools::RunSingleCommand(
+ command, &stdOut, &stdErr, &retVal, nullptr, cmSystemTools::OUTPUT_NONE,
+ cmDuration::zero(), cmProcessOutput::Auto);
+ if (!runResult) {
+ error = cmStrCat("Test run of \"", generator, "\" executable ",
+ cmQtAutoGen::Quoted(executable), " failed.\n",
+ cmQtAutoGen::QuotedCommand(command), '\n', stdOut, '\n',
+ stdErr);
+ return cmQtAutoGen::CompilerFeaturesHandle();
+ }
+ }
+
+ // Create valid handle
+ cmQtAutoGen::CompilerFeaturesHandle res =
+ std::make_shared<cmQtAutoGen::CompilerFeatures>();
+ res->HelpOutput = std::move(stdOut);
+
+ // Register compiler features
+ this->CompilerFeatures_.emplace(executable, res);
+
+ return res;
+}
+
+bool cmQtAutoGenGlobalInitializer::generate()
+{
+ return (InitializeCustomTargets() && SetupCustomTargets());
+}
+
+bool cmQtAutoGenGlobalInitializer::InitializeCustomTargets()
+{
+ // Initialize global autogen targets
+ {
+ std::string const comment = "Global AUTOGEN target";
+ for (auto const& pair : GlobalAutoGenTargets_) {
+ GetOrCreateGlobalTarget(pair.first, pair.second, comment);
+ }
+ }
+ // Initialize global autorcc targets
+ {
+ std::string const comment = "Global AUTORCC target";
+ for (auto const& pair : GlobalAutoRccTargets_) {
+ GetOrCreateGlobalTarget(pair.first, pair.second, comment);
+ }
+ }
+ // Initialize per target autogen targets
+ for (auto& initializer : Initializers_) {
+ if (!initializer->InitCustomTargets()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool cmQtAutoGenGlobalInitializer::SetupCustomTargets()
+{
+ for (auto& initializer : Initializers_) {
+ if (!initializer->SetupCustomTargets()) {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/Source/cmQtAutoGenGlobalInitializer.h b/Source/cmQtAutoGenGlobalInitializer.h
new file mode 100644
index 000000000..806725a01
--- /dev/null
+++ b/Source/cmQtAutoGenGlobalInitializer.h
@@ -0,0 +1,86 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmQtAutoGenGlobalInitializer_h
+#define cmQtAutoGenGlobalInitializer_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <map>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "cmQtAutoGen.h"
+
+class cmLocalGenerator;
+class cmQtAutoGenInitializer;
+
+/// @brief Initializes the QtAutoGen generators
+class cmQtAutoGenGlobalInitializer
+{
+public:
+ /// @brief Collection of QtAutogen related keywords
+ class Keywords
+ {
+ public:
+ Keywords();
+
+ std::string AUTOMOC;
+ std::string AUTOUIC;
+ std::string AUTORCC;
+
+ std::string AUTOMOC_EXECUTABLE;
+ std::string AUTOUIC_EXECUTABLE;
+ std::string AUTORCC_EXECUTABLE;
+
+ std::string SKIP_AUTOGEN;
+ std::string SKIP_AUTOMOC;
+ std::string SKIP_AUTOUIC;
+ std::string SKIP_AUTORCC;
+
+ std::string AUTOUIC_OPTIONS;
+ std::string AUTORCC_OPTIONS;
+
+ std::string qrc;
+ std::string ui;
+ };
+
+public:
+ cmQtAutoGenGlobalInitializer(
+ std::vector<cmLocalGenerator*> const& localGenerators);
+ ~cmQtAutoGenGlobalInitializer();
+
+ Keywords const& kw() const { return Keywords_; };
+
+ bool generate();
+
+private:
+ friend class cmQtAutoGenInitializer;
+
+ bool InitializeCustomTargets();
+ bool SetupCustomTargets();
+
+ void GetOrCreateGlobalTarget(cmLocalGenerator* localGen,
+ std::string const& name,
+ std::string const& comment);
+
+ void AddToGlobalAutoGen(cmLocalGenerator* localGen,
+ std::string const& targetName);
+ void AddToGlobalAutoRcc(cmLocalGenerator* localGen,
+ std::string const& targetName);
+
+ cmQtAutoGen::CompilerFeaturesHandle GetCompilerFeatures(
+ std::string const& generator, std::string const& executable,
+ std::string& error);
+
+private:
+ std::vector<std::unique_ptr<cmQtAutoGenInitializer>> Initializers_;
+ std::map<cmLocalGenerator*, std::string> GlobalAutoGenTargets_;
+ std::map<cmLocalGenerator*, std::string> GlobalAutoRccTargets_;
+ std::unordered_map<std::string, cmQtAutoGen::CompilerFeaturesHandle>
+ CompilerFeatures_;
+ Keywords const Keywords_;
+};
+
+#endif
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
new file mode 100644
index 000000000..5eb04f704
--- /dev/null
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -0,0 +1,1735 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmQtAutoGenInitializer.h"
+
+#include <cstddef>
+#include <deque>
+#include <initializer_list>
+#include <map>
+#include <ostream>
+#include <set>
+#include <string>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+#include <cm/algorithm>
+#include <cm/iterator>
+#include <cm/memory>
+
+#include "cmsys/SystemInformation.hxx"
+
+#include "cm_jsoncpp_value.h"
+#include "cm_jsoncpp_writer.h"
+
+#include "cmAlgorithms.h"
+#include "cmCustomCommand.h"
+#include "cmCustomCommandLines.h"
+#include "cmCustomCommandTypes.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmLinkItem.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmPolicies.h"
+#include "cmQtAutoGen.h"
+#include "cmQtAutoGenGlobalInitializer.h"
+#include "cmSourceFile.h"
+#include "cmSourceFileLocationKind.h"
+#include "cmSourceGroup.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmake.h"
+
+namespace {
+
+unsigned int GetParallelCPUCount()
+{
+ static unsigned int count = 0;
+ // Detect only on the first call
+ if (count == 0) {
+ cmsys::SystemInformation info;
+ info.RunCPUCheck();
+ count =
+ cm::clamp(info.GetNumberOfPhysicalCPU(), 1u, cmQtAutoGen::ParallelMax);
+ }
+ return count;
+}
+
+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;
+}
+
+/**
+ * Tests if targetDepend is a STATIC_LIBRARY and if any of its
+ * recursive STATIC_LIBRARY dependencies depends on targetOrigin
+ * (STATIC_LIBRARY cycle).
+ */
+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;
+}
+
+/** Sanitizes file search paths. */
+class SearchPathSanitizer
+{
+public:
+ SearchPathSanitizer(cmMakefile* makefile)
+ : SourcePath_(makefile->GetCurrentSourceDirectory())
+ {
+ }
+ std::vector<std::string> operator()(
+ std::vector<std::string> const& paths) const;
+
+private:
+ std::string SourcePath_;
+};
+
+std::vector<std::string> SearchPathSanitizer::operator()(
+ std::vector<std::string> const& paths) const
+{
+ std::vector<std::string> res;
+ res.reserve(paths.size());
+ for (std::string const& srcPath : paths) {
+ // Collapse relative paths
+ std::string path = cmSystemTools::CollapseFullPath(srcPath, SourcePath_);
+ // Remove suffix slashes
+ while (cmHasSuffix(path, '/')) {
+ path.pop_back();
+ }
+ // Accept only non empty paths
+ if (!path.empty()) {
+ res.emplace_back(std::move(path));
+ }
+ }
+ return res;
+}
+
+/** @brief Writes a CMake info file. */
+class InfoWriter
+{
+public:
+ // -- Single value
+ void Set(std::string const& key, std::string const& value)
+ {
+ Value_[key] = value;
+ }
+ void SetConfig(std::string const& key,
+ cmQtAutoGenInitializer::ConfigString const& cfgStr);
+ void SetBool(std::string const& key, bool value) { Value_[key] = value; }
+ void SetUInt(std::string const& key, unsigned int value)
+ {
+ Value_[key] = value;
+ }
+
+ // -- Array utility
+ template <typename CONT>
+ static bool MakeArray(Json::Value& jval, CONT const& container);
+
+ template <typename CONT>
+ static void MakeStringArray(Json::Value& jval, CONT const& container);
+
+ // -- Array value
+ template <typename CONT>
+ void SetArray(std::string const& key, CONT const& container);
+ template <typename CONT>
+ void SetConfigArray(
+ std::string const& key,
+ cmQtAutoGenInitializer::ConfigStrings<CONT> const& cfgStr);
+
+ // -- Array of arrays
+ template <typename CONT, typename FUNC>
+ void SetArrayArray(std::string const& key, CONT const& container, FUNC func);
+
+ // -- Save to json file
+ bool Save(std::string const& filename);
+
+private:
+ Json::Value Value_;
+};
+
+void InfoWriter::SetConfig(std::string const& key,
+ cmQtAutoGenInitializer::ConfigString const& cfgStr)
+{
+ Set(key, cfgStr.Default);
+ for (auto const& item : cfgStr.Config) {
+ Set(cmStrCat(key, '_', item.first), item.second);
+ }
+}
+
+template <typename CONT>
+bool InfoWriter::MakeArray(Json::Value& jval, CONT const& container)
+{
+ jval = Json::arrayValue;
+ std::size_t const listSize = cm::size(container);
+ if (listSize == 0) {
+ return false;
+ }
+ jval.resize(static_cast<unsigned int>(listSize));
+ return true;
+}
+
+template <typename CONT>
+void InfoWriter::MakeStringArray(Json::Value& jval, CONT const& container)
+{
+ if (MakeArray(jval, container)) {
+ Json::ArrayIndex ii = 0;
+ for (std::string const& item : container) {
+ jval[ii++] = item;
+ }
+ }
+}
+
+template <typename CONT>
+void InfoWriter::SetArray(std::string const& key, CONT const& container)
+{
+ MakeStringArray(Value_[key], container);
+}
+
+template <typename CONT, typename FUNC>
+void InfoWriter::SetArrayArray(std::string const& key, CONT const& container,
+ FUNC func)
+{
+ Json::Value& jval = Value_[key];
+ if (MakeArray(jval, container)) {
+ Json::ArrayIndex ii = 0;
+ for (auto const& citem : container) {
+ Json::Value& aval = jval[ii++];
+ aval = Json::arrayValue;
+ func(aval, citem);
+ }
+ }
+}
+
+template <typename CONT>
+void InfoWriter::SetConfigArray(
+ std::string const& key,
+ cmQtAutoGenInitializer::ConfigStrings<CONT> const& cfgStr)
+{
+ SetArray(key, cfgStr.Default);
+ for (auto const& item : cfgStr.Config) {
+ SetArray(cmStrCat(key, '_', item.first), item.second);
+ }
+}
+
+bool InfoWriter::Save(std::string const& filename)
+{
+ cmGeneratedFileStream fileStream;
+ fileStream.SetCopyIfDifferent(true);
+ fileStream.Open(filename, false, true);
+ if (!fileStream) {
+ return false;
+ }
+
+ Json::StyledStreamWriter jsonWriter;
+ try {
+ jsonWriter.write(fileStream, Value_);
+ } catch (...) {
+ return false;
+ }
+
+ return fileStream.Close();
+}
+
+} // End of unnamed namespace
+
+cmQtAutoGenInitializer::cmQtAutoGenInitializer(
+ cmQtAutoGenGlobalInitializer* globalInitializer,
+ cmGeneratorTarget* genTarget, IntegerVersion const& qtVersion,
+ bool mocEnabled, bool uicEnabled, bool rccEnabled, bool globalAutogenTarget,
+ bool globalAutoRccTarget)
+ : GlobalInitializer(globalInitializer)
+ , GenTarget(genTarget)
+ , GlobalGen(genTarget->GetGlobalGenerator())
+ , LocalGen(genTarget->GetLocalGenerator())
+ , Makefile(genTarget->Makefile)
+ , PathCheckSum(genTarget->Makefile)
+ , QtVersion(qtVersion)
+{
+ AutogenTarget.GlobalTarget = globalAutogenTarget;
+ Moc.Enabled = mocEnabled;
+ Uic.Enabled = uicEnabled;
+ Rcc.Enabled = rccEnabled;
+ Rcc.GlobalTarget = globalAutoRccTarget;
+}
+
+bool cmQtAutoGenInitializer::InitCustomTargets()
+{
+ // Configurations
+ this->MultiConfig = this->GlobalGen->IsMultiConfig();
+ this->ConfigDefault = this->Makefile->GetConfigurations(this->ConfigsList);
+ if (this->ConfigsList.empty()) {
+ this->ConfigsList.push_back(this->ConfigDefault);
+ }
+
+ // Verbosity
+ {
+ std::string def =
+ this->Makefile->GetSafeDefinition("CMAKE_AUTOGEN_VERBOSE");
+ if (!def.empty()) {
+ unsigned long iVerb = 0;
+ if (cmStrToULong(def, &iVerb)) {
+ // Numeric verbosity
+ this->Verbosity = static_cast<unsigned int>(iVerb);
+ } else {
+ // Non numeric verbosity
+ if (cmIsOn(def)) {
+ this->Verbosity = 1;
+ }
+ }
+ }
+ }
+
+ // Targets FOLDER
+ {
+ const char* folder =
+ this->Makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
+ if (folder == nullptr) {
+ folder = this->Makefile->GetState()->GetGlobalProperty(
+ "AUTOGEN_TARGETS_FOLDER");
+ }
+ // Inherit FOLDER property from target (#13688)
+ if (folder == nullptr) {
+ folder = this->GenTarget->GetProperty("FOLDER");
+ }
+ if (folder != nullptr) {
+ this->TargetsFolder = folder;
+ }
+ }
+
+ // Check status of policy CMP0071
+ {
+ cmPolicies::PolicyStatus const CMP0071_status =
+ this->Makefile->GetPolicyStatus(cmPolicies::CMP0071);
+ switch (CMP0071_status) {
+ case cmPolicies::WARN:
+ this->CMP0071Warn = 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
+ this->CMP0071Accept = true;
+ break;
+ }
+ }
+
+ // Common directories
+ {
+ // Collapsed current binary directory
+ std::string const cbd = cmSystemTools::CollapseFullPath(
+ std::string(), this->Makefile->GetCurrentBinaryDirectory());
+
+ // Info directory
+ this->Dir.Info = cmStrCat(cbd, "/CMakeFiles/", this->GenTarget->GetName(),
+ "_autogen.dir");
+ cmSystemTools::ConvertToUnixSlashes(this->Dir.Info);
+
+ // Build directory
+ this->Dir.Build = this->GenTarget->GetSafeProperty("AUTOGEN_BUILD_DIR");
+ if (this->Dir.Build.empty()) {
+ this->Dir.Build =
+ cmStrCat(cbd, '/', this->GenTarget->GetName(), "_autogen");
+ }
+ cmSystemTools::ConvertToUnixSlashes(this->Dir.Build);
+ // Cleanup build directory
+ this->AddCleanFile(this->Dir.Build);
+
+ // Working directory
+ this->Dir.Work = cbd;
+ cmSystemTools::ConvertToUnixSlashes(this->Dir.Work);
+
+ // Include directory
+ ConfigFileNames(this->Dir.Include, cmStrCat(this->Dir.Build, "/include"),
+ "");
+ this->Dir.IncludeGenExp = this->Dir.Include.Default;
+ if (this->MultiConfig) {
+ this->Dir.IncludeGenExp += "_$<CONFIG>";
+ }
+ }
+
+ // Moc, Uic and _autogen target settings
+ if (this->MocOrUicEnabled()) {
+ // Init moc specific settings
+ if (this->Moc.Enabled && !InitMoc()) {
+ return false;
+ }
+
+ // Init uic specific settings
+ if (this->Uic.Enabled && !InitUic()) {
+ return false;
+ }
+
+ // Autogen target name
+ this->AutogenTarget.Name =
+ cmStrCat(this->GenTarget->GetName(), "_autogen");
+
+ // Autogen target parallel processing
+ {
+ std::string prop = this->GenTarget->GetSafeProperty("AUTOGEN_PARALLEL");
+ if (prop.empty() || (prop == "AUTO")) {
+ // Autodetect number of CPUs
+ this->AutogenTarget.Parallel = GetParallelCPUCount();
+ } else {
+ this->AutogenTarget.Parallel = 1;
+ }
+ }
+
+ // Autogen target info and settings files
+ {
+ // Info file
+ this->AutogenTarget.InfoFile =
+ cmStrCat(this->Dir.Info, "/AutogenInfo.json");
+
+ // Used settings file
+ ConfigFileNames(this->AutogenTarget.SettingsFile,
+ cmStrCat(this->Dir.Info, "/AutogenUsed"), ".txt");
+ ConfigFileClean(this->AutogenTarget.SettingsFile);
+
+ // Parse cache file
+ ConfigFileNames(this->AutogenTarget.ParseCacheFile,
+ cmStrCat(this->Dir.Info, "/ParseCache"), ".txt");
+ ConfigFileClean(this->AutogenTarget.ParseCacheFile);
+ }
+
+ // Autogen target: Compute user defined dependencies
+ {
+ this->AutogenTarget.DependOrigin =
+ this->GenTarget->GetPropertyAsBool("AUTOGEN_ORIGIN_DEPENDS");
+
+ std::string const deps =
+ this->GenTarget->GetSafeProperty("AUTOGEN_TARGET_DEPENDS");
+ if (!deps.empty()) {
+ for (std::string const& depName : cmExpandedList(deps)) {
+ // Allow target and file dependencies
+ auto* depTarget = this->Makefile->FindTargetToUse(depName);
+ if (depTarget != nullptr) {
+ this->AutogenTarget.DependTargets.insert(depTarget);
+ } else {
+ this->AutogenTarget.DependFiles.insert(depName);
+ }
+ }
+ }
+ }
+
+ if (this->Moc.Enabled) {
+ // Path prefix
+ if (cmIsOn(this->GenTarget->GetSafeProperty("AUTOMOC_PATH_PREFIX"))) {
+ this->Moc.PathPrefix = true;
+ }
+
+ // CMAKE_AUTOMOC_RELAXED_MODE
+ if (this->Makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE")) {
+ this->Moc.RelaxedMode = true;
+ this->Makefile->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat("AUTOMOC: CMAKE_AUTOMOC_RELAXED_MODE is "
+ "deprecated an will be removed in the future. Consider "
+ "disabling it and converting the target ",
+ this->GenTarget->GetName(), " to regular mode."));
+ }
+
+ // Options
+ cmExpandList(this->GenTarget->GetSafeProperty("AUTOMOC_MOC_OPTIONS"),
+ this->Moc.Options);
+ // Filters
+ cmExpandList(this->GenTarget->GetSafeProperty("AUTOMOC_MACRO_NAMES"),
+ this->Moc.MacroNames);
+ {
+ auto filterList = cmExpandedList(
+ this->GenTarget->GetSafeProperty("AUTOMOC_DEPEND_FILTERS"));
+ if ((filterList.size() % 2) != 0) {
+ cmSystemTools::Error(
+ cmStrCat("AutoMoc: AUTOMOC_DEPEND_FILTERS predefs size ",
+ filterList.size(), " is not a multiple of 2."));
+ return false;
+ }
+ this->Moc.DependFilters.reserve(1 + (filterList.size() / 2));
+ this->Moc.DependFilters.emplace_back(
+ "Q_PLUGIN_METADATA",
+ "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
+ "[^\\)]*FILE[ \t]*\"([^\"]+)\"");
+ for (std::size_t ii = 0; ii != filterList.size(); ii += 2) {
+ this->Moc.DependFilters.emplace_back(filterList[ii],
+ filterList[ii + 1]);
+ }
+ }
+ }
+ }
+
+ // Init rcc specific settings
+ if (this->Rcc.Enabled && !InitRcc()) {
+ return false;
+ }
+
+ // Add autogen include directory to the origin target INCLUDE_DIRECTORIES
+ if (this->MocOrUicEnabled() || (this->Rcc.Enabled && this->MultiConfig)) {
+ this->GenTarget->AddIncludeDirectory(this->Dir.IncludeGenExp, true);
+ }
+
+ // Scan files
+ if (!this->InitScanFiles()) {
+ return false;
+ }
+
+ // Create autogen target
+ if (this->MocOrUicEnabled() && !this->InitAutogenTarget()) {
+ return false;
+ }
+
+ // Create rcc targets
+ if (this->Rcc.Enabled && !this->InitRccTargets()) {
+ return false;
+ }
+
+ return true;
+}
+
+bool cmQtAutoGenInitializer::InitMoc()
+{
+ // Mocs compilation file
+ this->Moc.CompilationFile =
+ cmStrCat(this->Dir.Build, "/mocs_compilation.cpp");
+
+ // Moc predefs
+ if (this->GenTarget->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
+ (this->QtVersion >= IntegerVersion(5, 8))) {
+ // Command
+ cmExpandList(this->Makefile->GetSafeDefinition(
+ "CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"),
+ this->Moc.PredefsCmd);
+ // Header
+ if (!this->Moc.PredefsCmd.empty()) {
+ ConfigFileNames(this->Moc.PredefsFile,
+ cmStrCat(this->Dir.Build, "/moc_predefs"), ".h");
+ }
+ }
+
+ // Moc includes
+ {
+ SearchPathSanitizer sanitizer(this->Makefile);
+ auto getDirs =
+ [this, &sanitizer](std::string const& cfg) -> std::vector<std::string> {
+ // Get the include dirs for this target, without stripping the implicit
+ // include dirs off, see issue #13667.
+ std::vector<std::string> dirs;
+ bool const appendImplicit = (this->QtVersion.Major >= 5);
+ this->LocalGen->GetIncludeDirectoriesImplicit(
+ dirs, this->GenTarget, "CXX", cfg, false, appendImplicit);
+ return sanitizer(dirs);
+ };
+
+ // Default configuration include directories
+ this->Moc.Includes.Default = getDirs(this->ConfigDefault);
+ // Other configuration settings
+ if (this->MultiConfig) {
+ for (std::string const& cfg : this->ConfigsList) {
+ std::vector<std::string> dirs = getDirs(cfg);
+ if (dirs == this->Moc.Includes.Default) {
+ continue;
+ }
+ this->Moc.Includes.Config[cfg] = std::move(dirs);
+ }
+ }
+ }
+
+ // Moc compile definitions
+ {
+ auto getDefs = [this](std::string const& cfg) -> std::set<std::string> {
+ std::set<std::string> defines;
+ this->LocalGen->GetTargetDefines(this->GenTarget, cfg, "CXX", defines);
+#ifdef _WIN32
+ if (this->Moc.PredefsCmd.empty()) {
+ // Add WIN32 definition if we don't have a moc_predefs.h
+ defines.insert("WIN32");
+ }
+#endif
+ return defines;
+ };
+
+ // Default configuration defines
+ this->Moc.Defines.Default = getDefs(this->ConfigDefault);
+ // Other configuration defines
+ if (this->MultiConfig) {
+ for (std::string const& cfg : this->ConfigsList) {
+ std::set<std::string> defines = getDefs(cfg);
+ if (defines == this->Moc.Defines.Default) {
+ continue;
+ }
+ this->Moc.Defines.Config[cfg] = std::move(defines);
+ }
+ }
+ }
+
+ // Moc executable
+ {
+ if (!this->GetQtExecutable(this->Moc, "moc", false)) {
+ return false;
+ }
+ // Let the _autogen target depend on the moc executable
+ if (this->Moc.ExecutableTarget != nullptr) {
+ this->AutogenTarget.DependTargets.insert(
+ this->Moc.ExecutableTarget->Target);
+ }
+ }
+
+ return true;
+}
+
+bool cmQtAutoGenInitializer::InitUic()
+{
+ // Uic search paths
+ {
+ std::string const usp =
+ this->GenTarget->GetSafeProperty("AUTOUIC_SEARCH_PATHS");
+ if (!usp.empty()) {
+ this->Uic.SearchPaths =
+ SearchPathSanitizer(this->Makefile)(cmExpandedList(usp));
+ }
+ }
+ // Uic target options
+ {
+ auto getOpts = [this](std::string const& cfg) -> std::vector<std::string> {
+ std::vector<std::string> opts;
+ this->GenTarget->GetAutoUicOptions(opts, cfg);
+ return opts;
+ };
+
+ // Default options
+ this->Uic.Options.Default = getOpts(this->ConfigDefault);
+ // Configuration specific options
+ if (this->MultiConfig) {
+ for (std::string const& cfg : this->ConfigsList) {
+ std::vector<std::string> options = getOpts(cfg);
+ if (options == this->Uic.Options.Default) {
+ continue;
+ }
+ this->Uic.Options.Config[cfg] = std::move(options);
+ }
+ }
+ }
+
+ // Uic executable
+ {
+ if (!this->GetQtExecutable(this->Uic, "uic", true)) {
+ return false;
+ }
+ // Let the _autogen target depend on the uic executable
+ if (this->Uic.ExecutableTarget != nullptr) {
+ this->AutogenTarget.DependTargets.insert(
+ this->Uic.ExecutableTarget->Target);
+ }
+ }
+
+ return true;
+}
+
+bool cmQtAutoGenInitializer::InitRcc()
+{
+ // Rcc executable
+ {
+ if (!this->GetQtExecutable(this->Rcc, "rcc", false)) {
+ return false;
+ }
+ // Evaluate test output on demand
+ CompilerFeatures& features = *this->Rcc.ExecutableFeatures;
+ if (!features.Evaluated) {
+ // Look for list options
+ if (this->QtVersion.Major == 5 || this->QtVersion.Major == 6) {
+ if (features.HelpOutput.find("--list") != std::string::npos) {
+ features.ListOptions.emplace_back("--list");
+ } else if (features.HelpOutput.find("-list") != std::string::npos) {
+ features.ListOptions.emplace_back("-list");
+ }
+ }
+ // Evaluation finished
+ features.Evaluated = true;
+ }
+ }
+
+ return true;
+}
+
+bool cmQtAutoGenInitializer::InitScanFiles()
+{
+ cmake const* cm = this->Makefile->GetCMakeInstance();
+ auto const& kw = this->GlobalInitializer->kw();
+
+ auto makeMUFile = [this, &kw](cmSourceFile* sf, std::string const& fullPath,
+ bool muIt) -> MUFileHandle {
+ MUFileHandle muf = cm::make_unique<MUFile>();
+ muf->FullPath = fullPath;
+ muf->SF = sf;
+ muf->Generated = sf->GetIsGenerated();
+ bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN);
+ muf->SkipMoc = this->Moc.Enabled &&
+ (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOMOC));
+ muf->SkipUic = this->Uic.Enabled &&
+ (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC));
+ if (muIt) {
+ muf->MocIt = this->Moc.Enabled && !muf->SkipMoc;
+ muf->UicIt = this->Uic.Enabled && !muf->SkipUic;
+ }
+ return muf;
+ };
+
+ auto addMUFile = [&](MUFileHandle&& muf, bool isHeader) {
+ if ((muf->MocIt || muf->UicIt) && muf->Generated) {
+ this->AutogenTarget.FilesGenerated.emplace_back(muf.get());
+ }
+ if (isHeader) {
+ this->AutogenTarget.Headers.emplace(muf->SF, std::move(muf));
+ } else {
+ this->AutogenTarget.Sources.emplace(muf->SF, std::move(muf));
+ }
+ };
+
+ // Scan through target files
+ {
+ // Scan through target files
+ std::vector<cmSourceFile*> srcFiles;
+ this->GenTarget->GetConfigCommonSourceFiles(srcFiles);
+ for (cmSourceFile* sf : srcFiles) {
+ // sf->GetExtension() is only valid after sf->ResolveFullPath() ...
+ // 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 pathError;
+ std::string const& fullPath = sf->ResolveFullPath(&pathError);
+ if (!pathError.empty() || fullPath.empty()) {
+ continue;
+ }
+ std::string const& extLower =
+ cmSystemTools::LowerCase(sf->GetExtension());
+
+ // Register files that will be scanned by moc or uic
+ if (this->MocOrUicEnabled()) {
+ // FIXME: Add a policy to include .hh files.
+ if (cm->IsHeaderExtension(extLower) && extLower != "hh") {
+ addMUFile(makeMUFile(sf, fullPath, true), true);
+ } else if (cm->IsSourceExtension(extLower)) {
+ addMUFile(makeMUFile(sf, fullPath, true), false);
+ }
+ }
+
+ // Register rcc enabled files
+ if (this->Rcc.Enabled) {
+ if ((extLower == kw.qrc) && !sf->GetPropertyAsBool(kw.SKIP_AUTOGEN) &&
+ !sf->GetPropertyAsBool(kw.SKIP_AUTORCC)) {
+ // Register qrc file
+ Qrc qrc;
+ qrc.QrcFile = fullPath;
+ qrc.QrcName =
+ cmSystemTools::GetFilenameWithoutLastExtension(qrc.QrcFile);
+ qrc.Generated = sf->GetIsGenerated();
+ // RCC options
+ {
+ std::string const opts = sf->GetSafeProperty(kw.AUTORCC_OPTIONS);
+ if (!opts.empty()) {
+ cmExpandList(opts, qrc.Options);
+ }
+ }
+ this->Rcc.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->GenTarget->ClearSourcesCache();
+
+ // For source files find additional headers and private headers
+ if (this->MocOrUicEnabled()) {
+ std::vector<MUFileHandle> extraHeaders;
+ extraHeaders.reserve(this->AutogenTarget.Sources.size() * 2);
+ // Header search suffixes and extensions
+ static std::initializer_list<cm::string_view> const suffixes{ "", "_p" };
+ auto const& exts = cm->GetHeaderExtensions();
+ // Scan through sources
+ for (auto const& pair : this->AutogenTarget.Sources) {
+ MUFile const& muf = *pair.second;
+ if (muf.MocIt || muf.UicIt) {
+ // Search for the default header file and a private header
+ std::string const& srcFullPath = muf.SF->ResolveFullPath();
+ std::string basePath = cmStrCat(
+ cmQtAutoGen::SubDirPrefix(srcFullPath),
+ cmSystemTools::GetFilenameWithoutLastExtension(srcFullPath));
+ for (auto const& suffix : suffixes) {
+ std::string const suffixedPath = cmStrCat(basePath, suffix);
+ for (auto const& ext : exts) {
+ std::string fullPath = cmStrCat(suffixedPath, '.', ext);
+
+ auto constexpr locationKind = cmSourceFileLocationKind::Known;
+ cmSourceFile* sf =
+ this->Makefile->GetSource(fullPath, locationKind);
+ if (sf != nullptr) {
+ // Check if we know about this header already
+ if (cmContains(this->AutogenTarget.Headers, sf)) {
+ continue;
+ }
+ // We only accept not-GENERATED files that do exist.
+ if (!sf->GetIsGenerated() &&
+ !cmSystemTools::FileExists(fullPath)) {
+ continue;
+ }
+ } else if (cmSystemTools::FileExists(fullPath)) {
+ // Create a new source file for the existing file
+ sf = this->Makefile->CreateSource(fullPath, false, locationKind);
+ }
+
+ if (sf != nullptr) {
+ auto eMuf = makeMUFile(sf, fullPath, true);
+ // Ony process moc/uic when the parent is processed as well
+ if (!muf.MocIt) {
+ eMuf->MocIt = false;
+ }
+ if (!muf.UicIt) {
+ eMuf->UicIt = false;
+ }
+ extraHeaders.emplace_back(std::move(eMuf));
+ }
+ }
+ }
+ }
+ }
+ // Move generated files to main headers list
+ for (auto& eMuf : extraHeaders) {
+ addMUFile(std::move(eMuf), true);
+ }
+ }
+
+ // Scan through all source files in the makefile to extract moc and uic
+ // parameters. Historically we support non target source file parameters.
+ // The reason is that their file names might be discovered from source files
+ // at generation time.
+ if (this->MocOrUicEnabled()) {
+ for (cmSourceFile* sf : this->Makefile->GetSourceFiles()) {
+ // sf->GetExtension() is only valid after sf->ResolveFullPath() ...
+ // 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 pathError;
+ std::string const& fullPath = sf->ResolveFullPath(&pathError);
+ if (!pathError.empty() || fullPath.empty()) {
+ continue;
+ }
+ std::string const& extLower =
+ cmSystemTools::LowerCase(sf->GetExtension());
+
+ // FIXME: Add a policy to include .hh files.
+ if (cm->IsHeaderExtension(extLower) && extLower != "hh") {
+ if (!cmContains(this->AutogenTarget.Headers, sf)) {
+ auto muf = makeMUFile(sf, fullPath, false);
+ if (muf->SkipMoc || muf->SkipUic) {
+ this->AutogenTarget.Headers.emplace(sf, std::move(muf));
+ }
+ }
+ } else if (cm->IsSourceExtension(extLower)) {
+ if (!cmContains(this->AutogenTarget.Headers, sf)) {
+ auto muf = makeMUFile(sf, fullPath, false);
+ if (muf->SkipMoc || muf->SkipUic) {
+ this->AutogenTarget.Sources.emplace(sf, std::move(muf));
+ }
+ }
+ } else if (this->Uic.Enabled && (extLower == kw.ui)) {
+ // .ui file
+ bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN);
+ bool const skipUic =
+ (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC));
+ if (!skipUic) {
+ // Check if the .ui file has uic options
+ std::string const uicOpts = sf->GetSafeProperty(kw.AUTOUIC_OPTIONS);
+ if (!uicOpts.empty()) {
+ this->Uic.UiFiles.emplace_back(fullPath, cmExpandedList(uicOpts));
+ }
+ } else {
+ // Register skipped .ui file
+ this->Uic.SkipUi.insert(fullPath);
+ }
+ }
+ }
+ }
+
+ // Process GENERATED sources and headers
+ if (this->MocOrUicEnabled() && !this->AutogenTarget.FilesGenerated.empty()) {
+ if (this->CMP0071Accept) {
+ // Let the autogen target depend on the GENERATED files
+ for (MUFile* muf : this->AutogenTarget.FilesGenerated) {
+ this->AutogenTarget.DependFiles.insert(muf->FullPath);
+ }
+ } else if (this->CMP0071Warn) {
+ cm::string_view property;
+ if (this->Moc.Enabled && this->Uic.Enabled) {
+ property = "SKIP_AUTOGEN";
+ } else if (this->Moc.Enabled) {
+ property = "SKIP_AUTOMOC";
+ } else if (this->Uic.Enabled) {
+ property = "SKIP_AUTOUIC";
+ }
+ std::string files;
+ for (MUFile* muf : this->AutogenTarget.FilesGenerated) {
+ files += cmStrCat(" ", Quoted(muf->FullPath), '\n');
+ }
+ this->Makefile->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0071), '\n',
+ "For compatibility, CMake is excluding the GENERATED source "
+ "file(s):\n",
+ files, "from processing by ",
+ cmQtAutoGen::Tools(this->Moc.Enabled, this->Uic.Enabled, false),
+ ". 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 ",
+ property, ":\n set_property(SOURCE file.h PROPERTY ", property,
+ " ON)\n"));
+ }
+ }
+
+ // Process qrc files
+ if (!this->Rcc.Qrcs.empty()) {
+ const bool modernQt = (this->QtVersion.Major >= 5);
+ // Target rcc options
+ std::vector<std::string> optionsTarget =
+ cmExpandedList(this->GenTarget->GetSafeProperty(kw.AUTORCC_OPTIONS));
+
+ // Check if file name is unique
+ for (Qrc& qrc : this->Rcc.Qrcs) {
+ qrc.Unique = true;
+ for (Qrc const& qrc2 : this->Rcc.Qrcs) {
+ if ((&qrc != &qrc2) && (qrc.QrcName == qrc2.QrcName)) {
+ qrc.Unique = false;
+ break;
+ }
+ }
+ }
+ // Path checksum and file names
+ for (Qrc& qrc : this->Rcc.Qrcs) {
+ // Path checksum
+ qrc.QrcPathChecksum = this->PathCheckSum.getPart(qrc.QrcFile);
+ // Output file name
+ qrc.OutputFile = cmStrCat(this->Dir.Build, '/', qrc.QrcPathChecksum,
+ "/qrc_", qrc.QrcName, ".cpp");
+ std::string const base = cmStrCat(this->Dir.Info, "/AutoRcc_",
+ qrc.QrcName, '_', qrc.QrcPathChecksum);
+ qrc.LockFile = cmStrCat(base, "_Lock.lock");
+ qrc.InfoFile = cmStrCat(base, "_Info.json");
+ ConfigFileNames(qrc.SettingsFile, cmStrCat(base, "_Used"), ".txt");
+ }
+ // rcc options
+ for (Qrc& qrc : this->Rcc.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 += cmStrCat('_', qrc.QrcPathChecksum);
+ }
+ std::vector<std::string> nameOpts;
+ nameOpts.emplace_back("-name");
+ nameOpts.emplace_back(std::move(name));
+ RccMergeOptions(opts, nameOpts, modernQt);
+ }
+ // Merge file option
+ RccMergeOptions(opts, qrc.Options, modernQt);
+ qrc.Options = std::move(opts);
+ }
+ // rcc resources
+ for (Qrc& qrc : this->Rcc.Qrcs) {
+ if (!qrc.Generated) {
+ std::string error;
+ RccLister const lister(this->Rcc.Executable,
+ this->Rcc.ExecutableFeatures->ListOptions);
+ if (!lister.list(qrc.QrcFile, qrc.Resources, error)) {
+ cmSystemTools::Error(error);
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool cmQtAutoGenInitializer::InitAutogenTarget()
+{
+ // Register info file as generated by CMake
+ this->Makefile->AddCMakeOutputFile(this->AutogenTarget.InfoFile);
+
+ // Files provided by the autogen target
+ std::vector<std::string> autogenProvides;
+ if (this->Moc.Enabled) {
+ this->AddGeneratedSource(this->Moc.CompilationFile, this->Moc, true);
+ autogenProvides.push_back(this->Moc.CompilationFile);
+ }
+
+ // Compose target comment
+ std::string autogenComment;
+ {
+ std::string tools;
+ if (this->Moc.Enabled) {
+ tools += "MOC";
+ }
+ if (this->Uic.Enabled) {
+ if (!tools.empty()) {
+ tools += " and ";
+ }
+ tools += "UIC";
+ }
+ autogenComment = cmStrCat("Automatic ", tools, " for target ",
+ this->GenTarget->GetName());
+ }
+
+ // Compose command lines
+ cmCustomCommandLines commandLines = cmMakeSingleCommandLine(
+ { cmSystemTools::GetCMakeCommand(), "-E", "cmake_autogen",
+ this->AutogenTarget.InfoFile, "$<CONFIGURATION>" });
+
+ // Use PRE_BUILD on demand
+ bool usePRE_BUILD = false;
+ if (this->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 (!this->AutogenTarget.DependFiles.empty()) {
+ usePRE_BUILD = false;
+ }
+ // Cannot use PRE_BUILD when a global autogen target is in place
+ if (AutogenTarget.GlobalTarget) {
+ usePRE_BUILD = false;
+ }
+ }
+ // Create the autogen target/command
+ if (usePRE_BUILD) {
+ // Add additional autogen target dependencies to origin target
+ for (cmTarget* depTarget : this->AutogenTarget.DependTargets) {
+ this->GenTarget->Target->AddUtility(depTarget->GetName(),
+ this->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(this->Makefile, no_output, autogenProvides, no_deps,
+ commandLines, autogenComment.c_str(),
+ this->Dir.Work.c_str());
+ cc.SetEscapeOldStyle(false);
+ cc.SetEscapeAllowMakeVars(true);
+ this->GenTarget->Target->AddPreBuildCommand(std::move(cc));
+ } else {
+
+ // Add link library target dependencies to the autogen target
+ // dependencies
+ if (this->AutogenTarget.DependOrigin) {
+ // 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->GenTarget->GetLinkImplementationLibraries(config);
+ if (libs != nullptr) {
+ for (cmLinkItem const& item : libs->Libraries) {
+ cmGeneratorTarget const* libTarget = item.Target;
+ if ((libTarget != nullptr) &&
+ !StaticLibraryCycle(this->GenTarget, libTarget, config)) {
+ // Increment target config count
+ commonTargets[libTarget]++;
+ }
+ }
+ }
+ }
+ for (auto const& item : commonTargets) {
+ if (item.second == this->ConfigsList.size()) {
+ this->AutogenTarget.DependTargets.insert(item.first->Target);
+ }
+ }
+ }
+
+ // Create autogen target
+ cmTarget* autogenTarget = this->Makefile->AddUtilityCommand(
+ this->AutogenTarget.Name, cmCommandOrigin::Generator, true,
+ this->Dir.Work.c_str(), /*byproducts=*/autogenProvides,
+ std::vector<std::string>(this->AutogenTarget.DependFiles.begin(),
+ this->AutogenTarget.DependFiles.end()),
+ commandLines, false, autogenComment.c_str());
+ // Create autogen generator target
+ this->LocalGen->AddGeneratorTarget(
+ new cmGeneratorTarget(autogenTarget, this->LocalGen));
+
+ // Forward origin utilities to autogen target
+ if (this->AutogenTarget.DependOrigin) {
+ for (BT<std::string> const& depName : this->GenTarget->GetUtilities()) {
+ autogenTarget->AddUtility(depName.Value, this->Makefile);
+ }
+ }
+ // Add additional autogen target dependencies to autogen target
+ for (cmTarget* depTarget : this->AutogenTarget.DependTargets) {
+ autogenTarget->AddUtility(depTarget->GetName(), this->Makefile);
+ }
+
+ // Set FOLDER property in autogen target
+ if (!this->TargetsFolder.empty()) {
+ autogenTarget->SetProperty("FOLDER", this->TargetsFolder.c_str());
+ }
+
+ // Add autogen target to the origin target dependencies
+ this->GenTarget->Target->AddUtility(this->AutogenTarget.Name,
+ this->Makefile);
+
+ // Add autogen target to the global autogen target dependencies
+ if (this->AutogenTarget.GlobalTarget) {
+ this->GlobalInitializer->AddToGlobalAutoGen(this->LocalGen,
+ this->AutogenTarget.Name);
+ }
+ }
+
+ return true;
+}
+
+bool cmQtAutoGenInitializer::InitRccTargets()
+{
+ for (Qrc const& qrc : this->Rcc.Qrcs) {
+ // Register info file as generated by CMake
+ this->Makefile->AddCMakeOutputFile(qrc.InfoFile);
+ // Register file at target
+ {
+ cmSourceFile* sf = this->AddGeneratedSource(qrc.OutputFile, this->Rcc);
+ sf->SetProperty("SKIP_UNITY_BUILD_INCLUSION", "On");
+ }
+
+ std::vector<std::string> ccOutput;
+ ccOutput.push_back(qrc.OutputFile);
+
+ 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);
+
+ cmCustomCommandLines commandLines;
+ if (this->MultiConfig) {
+ // Build for all configurations
+ for (std::string const& config : this->ConfigsList) {
+ commandLines.push_back(
+ cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E",
+ "cmake_autorcc", qrc.InfoFile, config }));
+ }
+ } else {
+ commandLines.push_back(
+ cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E",
+ "cmake_autorcc", qrc.InfoFile, "$<CONFIG>" }));
+ }
+ std::string ccComment =
+ cmStrCat("Automatic RCC for ",
+ FileProjectRelativePath(this->Makefile, qrc.QrcFile));
+
+ if (qrc.Generated || this->Rcc.GlobalTarget) {
+ // Create custom rcc target
+ std::string ccName;
+ {
+ ccName = cmStrCat(this->GenTarget->GetName(), "_arcc_", qrc.QrcName);
+ if (!qrc.Unique) {
+ ccName += cmStrCat('_', qrc.QrcPathChecksum);
+ }
+
+ cmTarget* autoRccTarget = this->Makefile->AddUtilityCommand(
+ ccName, cmCommandOrigin::Generator, true, this->Dir.Work.c_str(),
+ ccOutput, ccDepends, commandLines, false, ccComment.c_str());
+
+ // Create autogen generator target
+ this->LocalGen->AddGeneratorTarget(
+ new cmGeneratorTarget(autoRccTarget, this->LocalGen));
+
+ // Set FOLDER property in autogen target
+ if (!this->TargetsFolder.empty()) {
+ autoRccTarget->SetProperty("FOLDER", this->TargetsFolder.c_str());
+ }
+ if (!this->Rcc.ExecutableTargetName.empty()) {
+ autoRccTarget->AddUtility(this->Rcc.ExecutableTargetName,
+ this->Makefile);
+ }
+ }
+ // Add autogen target to the origin target dependencies
+ this->GenTarget->Target->AddUtility(ccName, this->Makefile);
+
+ // Add autogen target to the global autogen target dependencies
+ if (this->Rcc.GlobalTarget) {
+ this->GlobalInitializer->AddToGlobalAutoRcc(this->LocalGen, ccName);
+ }
+ } else {
+ // Create custom rcc command
+ {
+ std::vector<std::string> ccByproducts;
+
+ // Add the resource files to the dependencies
+ for (std::string const& fileName : qrc.Resources) {
+ // Add resource file to the custom command dependencies
+ ccDepends.push_back(fileName);
+ }
+ if (!this->Rcc.ExecutableTargetName.empty()) {
+ ccDepends.push_back(this->Rcc.ExecutableTargetName);
+ }
+ std::string no_main_dependency;
+ cmImplicitDependsList no_implicit_depends;
+ this->Makefile->AddCustomCommandToOutput(
+ ccOutput, ccByproducts, ccDepends, no_main_dependency,
+ no_implicit_depends, commandLines, ccComment.c_str(),
+ this->Dir.Work.c_str());
+ }
+ // Reconfigure when .qrc file changes
+ this->Makefile->AddCMakeDependFile(qrc.QrcFile);
+ }
+ }
+
+ return true;
+}
+
+bool cmQtAutoGenInitializer::SetupCustomTargets()
+{
+ // Create info directory on demand
+ if (!cmSystemTools::MakeDirectory(this->Dir.Info)) {
+ cmSystemTools::Error(cmStrCat("AutoGen: Could not create directory: ",
+ Quoted(this->Dir.Info)));
+ return false;
+ }
+
+ // Generate autogen target info file
+ if (this->MocOrUicEnabled()) {
+ // Write autogen target info files
+ if (!this->SetupWriteAutogenInfo()) {
+ return false;
+ }
+ }
+
+ // Write AUTORCC info files
+ return !this->Rcc.Enabled || this->SetupWriteRccInfo();
+}
+
+bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
+{
+ // Utility lambdas
+ auto MfDef = [this](std::string const& key) {
+ return this->Makefile->GetSafeDefinition(key);
+ };
+
+ // Filtered headers and sources
+ std::set<std::string> moc_skip;
+ std::set<std::string> uic_skip;
+ std::vector<MUFile const*> headers;
+ std::vector<MUFile const*> sources;
+
+ // Filter headers
+ {
+ headers.reserve(this->AutogenTarget.Headers.size());
+ for (auto const& pair : this->AutogenTarget.Headers) {
+ MUFile const* const muf = pair.second.get();
+ if (muf->Generated && !this->CMP0071Accept) {
+ continue;
+ }
+ if (muf->SkipMoc) {
+ moc_skip.insert(muf->FullPath);
+ }
+ if (muf->SkipUic) {
+ uic_skip.insert(muf->FullPath);
+ }
+ if (muf->MocIt || muf->UicIt) {
+ headers.emplace_back(muf);
+ }
+ }
+ std::sort(headers.begin(), headers.end(),
+ [](MUFile const* a, MUFile const* b) {
+ return (a->FullPath < b->FullPath);
+ });
+ }
+
+ // Filter sources
+ {
+ sources.reserve(this->AutogenTarget.Sources.size());
+ for (auto const& pair : this->AutogenTarget.Sources) {
+ MUFile const* const muf = pair.second.get();
+ if (muf->Generated && !this->CMP0071Accept) {
+ continue;
+ }
+ if (muf->SkipMoc) {
+ moc_skip.insert(muf->FullPath);
+ }
+ if (muf->SkipUic) {
+ uic_skip.insert(muf->FullPath);
+ }
+ if (muf->MocIt || muf->UicIt) {
+ sources.emplace_back(muf);
+ }
+ }
+ std::sort(sources.begin(), sources.end(),
+ [](MUFile const* a, MUFile const* b) {
+ return (a->FullPath < b->FullPath);
+ });
+ }
+
+ // Info writer
+ InfoWriter info;
+
+ // General
+ info.SetBool("MULTI_CONFIG", this->MultiConfig);
+ info.SetUInt("PARALLEL", this->AutogenTarget.Parallel);
+ info.SetUInt("VERBOSITY", this->Verbosity);
+
+ // Directories
+ info.Set("CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
+ info.Set("CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
+ info.Set("CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));
+ info.Set("CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));
+ info.Set("BUILD_DIR", this->Dir.Build);
+ info.SetConfig("INCLUDE_DIR", this->Dir.Include);
+
+ info.SetUInt("QT_VERSION_MAJOR", this->QtVersion.Major);
+ info.Set("QT_MOC_EXECUTABLE", this->Moc.Executable);
+ info.Set("QT_UIC_EXECUTABLE", this->Uic.Executable);
+
+ info.Set("CMAKE_EXECUTABLE", cmSystemTools::GetCMakeCommand());
+ info.SetConfig("SETTINGS_FILE", this->AutogenTarget.SettingsFile);
+ info.SetConfig("PARSE_CACHE_FILE", this->AutogenTarget.ParseCacheFile);
+ info.SetArray("HEADER_EXTENSIONS",
+ this->Makefile->GetCMakeInstance()->GetHeaderExtensions());
+ info.SetArrayArray(
+ "HEADERS", headers, [this](Json::Value& jval, MUFile const* muf) {
+ jval.resize(3u);
+ jval[0u] = muf->FullPath;
+ jval[1u] = cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u');
+ jval[2u] = this->GetMocBuildPath(*muf);
+ });
+ info.SetArrayArray(
+ "SOURCES", sources, [](Json::Value& jval, MUFile const* muf) {
+ jval.resize(2u);
+ jval[0u] = muf->FullPath;
+ jval[1u] = cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u');
+ });
+
+ // Write moc settings
+ if (this->Moc.Enabled) {
+ info.SetArray("MOC_SKIP", moc_skip);
+ info.SetConfigArray("MOC_DEFINITIONS", this->Moc.Defines);
+ info.SetConfigArray("MOC_INCLUDES", this->Moc.Includes);
+ info.SetArray("MOC_OPTIONS", this->Moc.Options);
+ info.SetBool("MOC_RELAXED_MODE", this->Moc.RelaxedMode);
+ info.SetBool("MOC_PATH_PREFIX", this->Moc.PathPrefix);
+ info.SetArray("MOC_MACRO_NAMES", this->Moc.MacroNames);
+ info.SetArrayArray(
+ "MOC_DEPEND_FILTERS", this->Moc.DependFilters,
+ [](Json::Value& jval, std::pair<std::string, std::string> const& pair) {
+ jval.resize(2u);
+ jval[0u] = pair.first;
+ jval[1u] = pair.second;
+ });
+ info.Set("MOC_COMPILATION_FILE", this->Moc.CompilationFile);
+ info.SetArray("MOC_PREDEFS_CMD", this->Moc.PredefsCmd);
+ info.SetConfig("MOC_PREDEFS_FILE", this->Moc.PredefsFile);
+ }
+
+ // Write uic settings
+ if (this->Uic.Enabled) {
+ // Add skipped .ui files
+ uic_skip.insert(this->Uic.SkipUi.begin(), this->Uic.SkipUi.end());
+
+ info.SetArray("UIC_SKIP", uic_skip);
+ info.SetArrayArray("UIC_UI_FILES", this->Uic.UiFiles,
+ [](Json::Value& jval, UicT::UiFileT const& uiFile) {
+ jval.resize(2u);
+ jval[0u] = uiFile.first;
+ InfoWriter::MakeStringArray(jval[1u], uiFile.second);
+ });
+ info.SetConfigArray("UIC_OPTIONS", this->Uic.Options);
+ info.SetArray("UIC_SEARCH_PATHS", this->Uic.SearchPaths);
+ }
+
+ info.Save(this->AutogenTarget.InfoFile);
+
+ return true;
+}
+
+bool cmQtAutoGenInitializer::SetupWriteRccInfo()
+{
+ for (Qrc const& qrc : this->Rcc.Qrcs) {
+ // Utility lambdas
+ auto MfDef = [this](std::string const& key) {
+ return this->Makefile->GetSafeDefinition(key);
+ };
+
+ InfoWriter info;
+
+ // General
+ info.SetBool("MULTI_CONFIG", this->MultiConfig);
+ info.SetUInt("VERBOSITY", this->Verbosity);
+
+ // Files
+ info.Set("LOCK_FILE", qrc.LockFile);
+ info.SetConfig("SETTINGS_FILE", qrc.SettingsFile);
+
+ // Directories
+ info.Set("CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
+ info.Set("CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
+ info.Set("CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));
+ info.Set("CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));
+ info.Set("BUILD_DIR", this->Dir.Build);
+ info.SetConfig("INCLUDE_DIR", this->Dir.Include);
+
+ // rcc executable
+ info.Set("RCC_EXECUTABLE", this->Rcc.Executable);
+ info.SetArray("RCC_LIST_OPTIONS",
+ this->Rcc.ExecutableFeatures->ListOptions);
+
+ // qrc file
+ info.Set("SOURCE", qrc.QrcFile);
+ info.Set("OUTPUT_CHECKSUM", qrc.QrcPathChecksum);
+ info.Set("OUTPUT_NAME", cmSystemTools::GetFilenameName(qrc.OutputFile));
+ info.SetArray("OPTIONS", qrc.Options);
+ info.SetArray("INPUTS", qrc.Resources);
+
+ info.Save(qrc.InfoFile);
+ }
+
+ return true;
+}
+
+cmSourceFile* cmQtAutoGenInitializer::RegisterGeneratedSource(
+ std::string const& filename)
+{
+ cmSourceFile* gFile = this->Makefile->GetOrCreateSource(filename, true);
+ gFile->SetProperty("GENERATED", "1");
+ gFile->SetProperty("SKIP_AUTOGEN", "1");
+ return gFile;
+}
+
+cmSourceFile* cmQtAutoGenInitializer::AddGeneratedSource(
+ std::string const& filename, GenVarsT const& genVars, bool prepend)
+{
+ // Register source at makefile
+ cmSourceFile* gFile = this->RegisterGeneratedSource(filename);
+ // Add source file to target
+ this->GenTarget->AddSource(filename, prepend);
+
+ // Add source file to source group
+ this->AddToSourceGroup(filename, genVars.GenNameUpper);
+
+ return gFile;
+}
+
+void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName,
+ cm::string_view genNameUpper)
+{
+ cmSourceGroup* sourceGroup = nullptr;
+ // Acquire source group
+ {
+ std::string property;
+ std::string groupName;
+ {
+ // Prefer generator specific source group name
+ std::initializer_list<std::string> const props{
+ cmStrCat(genNameUpper, "_SOURCE_GROUP"), "AUTOGEN_SOURCE_GROUP"
+ };
+ for (std::string const& prop : props) {
+ const char* propName =
+ this->Makefile->GetState()->GetGlobalProperty(prop);
+ if ((propName != nullptr) && (*propName != '\0')) {
+ groupName = propName;
+ property = prop;
+ break;
+ }
+ }
+ }
+ // Generate a source group on demand
+ if (!groupName.empty()) {
+ sourceGroup = this->Makefile->GetOrCreateSourceGroup(groupName);
+ if (sourceGroup == nullptr) {
+ cmSystemTools::Error(
+ cmStrCat(genNameUpper, " error in ", property,
+ ": Could not find or create the source group ",
+ cmQtAutoGen::Quoted(groupName)));
+ }
+ }
+ }
+ if (sourceGroup != nullptr) {
+ sourceGroup->AddGroupFile(fileName);
+ }
+}
+
+void cmQtAutoGenInitializer::AddCleanFile(std::string const& fileName)
+{
+ this->GenTarget->Target->AppendProperty("ADDITIONAL_CLEAN_FILES",
+ fileName.c_str(), false);
+}
+
+void cmQtAutoGenInitializer::ConfigFileNames(ConfigString& configString,
+ cm::string_view prefix,
+ cm::string_view suffix)
+{
+ configString.Default = cmStrCat(prefix, suffix);
+ if (this->MultiConfig) {
+ for (auto const& cfg : this->ConfigsList) {
+ configString.Config[cfg] = cmStrCat(prefix, '_', cfg, suffix);
+ }
+ }
+}
+
+void cmQtAutoGenInitializer::ConfigFileClean(ConfigString& configString)
+{
+ this->AddCleanFile(configString.Default);
+ if (this->MultiConfig) {
+ for (auto const& pair : configString.Config) {
+ this->AddCleanFile(pair.second);
+ }
+ }
+}
+
+std::pair<cmQtAutoGen::IntegerVersion, unsigned int>
+cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target)
+{
+ // Converts a char ptr to an unsigned int value
+ auto toUInt = [](const char* const input) -> unsigned int {
+ unsigned long tmp = 0;
+ if (input != nullptr && cmStrToULong(input, &tmp)) {
+ return static_cast<unsigned int>(tmp);
+ }
+ return 0u;
+ };
+
+ // Initialize return value to a default
+ std::pair<IntegerVersion, unsigned int> res(
+ IntegerVersion(),
+ toUInt(target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION",
+ "")));
+
+ // Acquire known Qt versions
+ std::vector<cmQtAutoGen::IntegerVersion> knownQtVersions;
+ {
+ // Qt version variable prefixes
+ static std::initializer_list<
+ std::pair<cm::string_view, cm::string_view>> const keys{
+ { "Qt6Core_VERSION_MAJOR", "Qt6Core_VERSION_MINOR" },
+ { "Qt5Core_VERSION_MAJOR", "Qt5Core_VERSION_MINOR" },
+ { "QT_VERSION_MAJOR", "QT_VERSION_MINOR" },
+ };
+
+ knownQtVersions.reserve(keys.size() * 2);
+
+ // Adds a version to the result (nullptr safe)
+ auto addVersion = [&knownQtVersions, &toUInt](const char* major,
+ const char* minor) {
+ cmQtAutoGen::IntegerVersion ver(toUInt(major), toUInt(minor));
+ if (ver.Major != 0) {
+ knownQtVersions.emplace_back(ver);
+ }
+ };
+
+ // Read versions from variables
+ for (auto const& keyPair : keys) {
+ addVersion(target->Makefile->GetDefinition(std::string(keyPair.first)),
+ target->Makefile->GetDefinition(std::string(keyPair.second)));
+ }
+
+ // Read versions from directory properties
+ for (auto const& keyPair : keys) {
+ addVersion(target->Makefile->GetProperty(std::string(keyPair.first)),
+ target->Makefile->GetProperty(std::string(keyPair.second)));
+ }
+ }
+
+ // Evaluate known Qt versions
+ if (!knownQtVersions.empty()) {
+ if (res.second == 0) {
+ // No specific version was requested by the target:
+ // Use highest known Qt version.
+ res.first = knownQtVersions.at(0);
+ } else {
+ // Pick a version from the known versions:
+ for (auto it : knownQtVersions) {
+ if (it.Major == res.second) {
+ res.first = it;
+ break;
+ }
+ }
+ }
+ }
+ return res;
+}
+
+std::string cmQtAutoGenInitializer::GetMocBuildPath(MUFile const& muf)
+{
+ std::string res;
+ if (!muf.MocIt) {
+ return res;
+ }
+ {
+ std::string const basePath =
+ cmStrCat(this->PathCheckSum.getPart(muf.FullPath), "/moc_",
+ FileNameWithoutLastExtension(muf.FullPath));
+ std::string suffix;
+ constexpr std::size_t num_tries_max = 256;
+ for (std::size_t ii = 0; ii != num_tries_max; ++ii) {
+ res = cmStrCat(basePath, suffix, ".cpp");
+ if (this->Moc.EmittedBuildPaths.emplace(res).second) {
+ break;
+ }
+ // Compute new suffix
+ suffix = cmStrCat('_', ii + 1);
+ }
+ }
+ return res;
+}
+
+bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars,
+ const std::string& executable,
+ bool ignoreMissingTarget) const
+{
+ auto print_err = [this, &genVars](std::string const& err) {
+ cmSystemTools::Error(cmStrCat(genVars.GenNameUpper, " for target ",
+ this->GenTarget->GetName(), ": ", err));
+ };
+
+ // Custom executable
+ {
+ std::string const prop = cmStrCat(genVars.GenNameUpper, "_EXECUTABLE");
+ std::string const val = this->GenTarget->Target->GetSafeProperty(prop);
+ if (!val.empty()) {
+ // Evaluate generator expression
+ {
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ cmGeneratorExpression ge(lfbt);
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(val);
+ genVars.Executable = cge->Evaluate(this->LocalGen, "");
+ }
+ if (genVars.Executable.empty() && !ignoreMissingTarget) {
+ print_err(prop + " evaluates to an empty value");
+ return false;
+ }
+
+ // Create empty compiler features.
+ genVars.ExecutableFeatures =
+ std::make_shared<cmQtAutoGen::CompilerFeatures>();
+ return true;
+ }
+ }
+
+ // Find executable target
+ {
+ // Find executable target name
+ cm::string_view prefix;
+ if (this->QtVersion.Major == 4) {
+ prefix = "Qt4::";
+ } else if (this->QtVersion.Major == 5) {
+ prefix = "Qt5::";
+ } else if (this->QtVersion.Major == 6) {
+ prefix = "Qt6::";
+ }
+ std::string const targetName = cmStrCat(prefix, executable);
+
+ // Find target
+ cmGeneratorTarget* genTarget =
+ this->LocalGen->FindGeneratorTargetToUse(targetName);
+ if (genTarget != nullptr) {
+ genVars.ExecutableTargetName = targetName;
+ genVars.ExecutableTarget = genTarget;
+ if (genTarget->IsImported()) {
+ genVars.Executable = genTarget->ImportedGetLocation("");
+ } else {
+ genVars.Executable = genTarget->GetLocation("");
+ }
+ } else {
+ if (ignoreMissingTarget) {
+ // Create empty compiler features.
+ genVars.ExecutableFeatures =
+ std::make_shared<cmQtAutoGen::CompilerFeatures>();
+ return true;
+ }
+ print_err(cmStrCat("Could not find ", executable, " executable target ",
+ targetName));
+ return false;
+ }
+ }
+
+ // Get executable features
+ {
+ std::string err;
+ genVars.ExecutableFeatures = this->GlobalInitializer->GetCompilerFeatures(
+ executable, genVars.Executable, err);
+ if (!genVars.ExecutableFeatures) {
+ print_err(err);
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h
new file mode 100644
index 000000000..d55259c5e
--- /dev/null
+++ b/Source/cmQtAutoGenInitializer.h
@@ -0,0 +1,248 @@
+/* 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 <memory>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+#include <cm/string_view>
+
+#include "cmFilePathChecksum.h"
+#include "cmQtAutoGen.h"
+
+class cmGeneratorTarget;
+class cmGlobalGenerator;
+class cmLocalGenerator;
+class cmMakefile;
+class cmQtAutoGenGlobalInitializer;
+class cmSourceFile;
+class cmTarget;
+
+/** \class cmQtAutoGenerator
+ * \brief Initializes the QtAutoGen generators
+ */
+class cmQtAutoGenInitializer : public cmQtAutoGen
+{
+public:
+ /** String value with per configuration variants. */
+ class ConfigString
+ {
+ public:
+ std::string Default;
+ std::unordered_map<std::string, std::string> Config;
+ };
+
+ /** String values with per configuration variants. */
+ template <typename C>
+ class ConfigStrings
+ {
+ public:
+ C Default;
+ std::unordered_map<std::string, C> Config;
+ };
+
+ /** rcc job. */
+ class Qrc
+ {
+ public:
+ std::string LockFile;
+ std::string QrcFile;
+ std::string QrcName;
+ std::string QrcPathChecksum;
+ std::string InfoFile;
+ ConfigString SettingsFile;
+ std::string OutputFile;
+ bool Generated = false;
+ bool Unique = false;
+ std::vector<std::string> Options;
+ std::vector<std::string> Resources;
+ };
+
+ /** moc and/or uic file. */
+ struct MUFile
+ {
+ std::string FullPath;
+ cmSourceFile* SF = nullptr;
+ bool Generated = false;
+ bool SkipMoc = false;
+ bool SkipUic = false;
+ bool MocIt = false;
+ bool UicIt = false;
+ };
+ using MUFileHandle = std::unique_ptr<MUFile>;
+
+ /** Abstract moc/uic/rcc generator variables base class. */
+ struct GenVarsT
+ {
+ bool Enabled = false;
+ // Generator type/name
+ GenT Gen;
+ cm::string_view GenNameUpper;
+ // Executable
+ std::string ExecutableTargetName;
+ cmGeneratorTarget* ExecutableTarget = nullptr;
+ std::string Executable;
+ CompilerFeaturesHandle ExecutableFeatures;
+
+ GenVarsT(GenT gen)
+ : Gen(gen)
+ , GenNameUpper(cmQtAutoGen::GeneratorNameUpper(gen)){};
+ };
+
+public:
+ /** @return The detected Qt version and the required Qt major version. */
+ static std::pair<IntegerVersion, unsigned int> GetQtVersion(
+ cmGeneratorTarget const* genTarget);
+
+ cmQtAutoGenInitializer(cmQtAutoGenGlobalInitializer* globalInitializer,
+ cmGeneratorTarget* genTarget,
+ IntegerVersion const& qtVersion, bool mocEnabled,
+ bool uicEnabled, bool rccEnabled,
+ bool globalAutogenTarget, bool globalAutoRccTarget);
+
+ bool InitCustomTargets();
+ bool SetupCustomTargets();
+
+private:
+ /** If moc or uic is enabled, the autogen target will be generated. */
+ bool MocOrUicEnabled() const
+ {
+ return (this->Moc.Enabled || this->Uic.Enabled);
+ }
+
+ bool InitMoc();
+ bool InitUic();
+ bool InitRcc();
+
+ bool InitScanFiles();
+ bool InitAutogenTarget();
+ bool InitRccTargets();
+
+ bool SetupWriteAutogenInfo();
+ bool SetupWriteRccInfo();
+
+ cmSourceFile* RegisterGeneratedSource(std::string const& filename);
+ cmSourceFile* AddGeneratedSource(std::string const& filename,
+ GenVarsT const& genVars,
+ bool prepend = false);
+ void AddToSourceGroup(std::string const& fileName,
+ cm::string_view genNameUpper);
+ void AddCleanFile(std::string const& fileName);
+
+ void ConfigFileNames(ConfigString& configString, cm::string_view prefix,
+ cm::string_view suffix);
+ void ConfigFileClean(ConfigString& configString);
+
+ std::string GetMocBuildPath(MUFile const& muf);
+
+ bool GetQtExecutable(GenVarsT& genVars, const std::string& executable,
+ bool ignoreMissingTarget) const;
+
+private:
+ cmQtAutoGenGlobalInitializer* GlobalInitializer = nullptr;
+ cmGeneratorTarget* GenTarget = nullptr;
+ cmGlobalGenerator* GlobalGen = nullptr;
+ cmLocalGenerator* LocalGen = nullptr;
+ cmMakefile* Makefile = nullptr;
+ cmFilePathChecksum const PathCheckSum;
+
+ // -- Configuration
+ IntegerVersion QtVersion;
+ unsigned int Verbosity = 0;
+ bool MultiConfig = false;
+ bool CMP0071Accept = false;
+ bool CMP0071Warn = false;
+ std::string ConfigDefault;
+ std::vector<std::string> ConfigsList;
+ std::string TargetsFolder;
+
+ /** Common directories. */
+ struct
+ {
+ std::string Info;
+ std::string Build;
+ std::string Work;
+ ConfigString Include;
+ std::string IncludeGenExp;
+ } Dir;
+
+ /** Autogen target variables. */
+ struct
+ {
+ std::string Name;
+ bool GlobalTarget = false;
+ // Settings
+ unsigned int Parallel = 1;
+ // Configuration files
+ std::string InfoFile;
+ ConfigString SettingsFile;
+ ConfigString ParseCacheFile;
+ // Dependencies
+ bool DependOrigin = false;
+ std::set<std::string> DependFiles;
+ std::set<cmTarget*> DependTargets;
+ // Sources to process
+ std::unordered_map<cmSourceFile*, MUFileHandle> Headers;
+ std::unordered_map<cmSourceFile*, MUFileHandle> Sources;
+ std::vector<MUFile*> FilesGenerated;
+ } AutogenTarget;
+
+ /** moc variables. */
+ struct MocT : public GenVarsT
+ {
+ MocT()
+ : GenVarsT(GenT::MOC){};
+
+ bool RelaxedMode = false;
+ bool PathPrefix = false;
+ std::string CompilationFile;
+ // Compiler implicit pre defines
+ std::vector<std::string> PredefsCmd;
+ ConfigString PredefsFile;
+ // Defines
+ ConfigStrings<std::set<std::string>> Defines;
+ // Includes
+ ConfigStrings<std::vector<std::string>> Includes;
+ // Options
+ std::vector<std::string> Options;
+ // Filters
+ std::vector<std::string> MacroNames;
+ std::vector<std::pair<std::string, std::string>> DependFilters;
+ // Utility
+ std::unordered_set<std::string> EmittedBuildPaths;
+ } Moc;
+
+ /** uic variables. */
+ struct UicT : public GenVarsT
+ {
+ using UiFileT = std::pair<std::string, std::vector<std::string>>;
+
+ UicT()
+ : GenVarsT(GenT::UIC){};
+
+ std::set<std::string> SkipUi;
+ std::vector<UiFileT> UiFiles;
+ ConfigStrings<std::vector<std::string>> Options;
+ std::vector<std::string> SearchPaths;
+ } Uic;
+
+ /** rcc variables. */
+ struct RccT : public GenVarsT
+ {
+ RccT()
+ : GenVarsT(GenT::RCC){};
+
+ bool GlobalTarget = false;
+ std::vector<Qrc> Qrcs;
+ } Rcc;
+};
+
+#endif
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
new file mode 100644
index 000000000..da963052f
--- /dev/null
+++ b/Source/cmQtAutoGenerator.cxx
@@ -0,0 +1,492 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmQtAutoGenerator.h"
+
+#include "cmsys/FStream.hxx"
+
+#include "cm_jsoncpp_reader.h"
+
+#include "cmQtAutoGen.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+cmQtAutoGenerator::Logger::Logger()
+{
+ // Initialize logger
+ {
+ std::string verbose;
+ if (cmSystemTools::GetEnv("VERBOSE", verbose) && !verbose.empty()) {
+ unsigned long iVerbose = 0;
+ if (cmStrToULong(verbose, &iVerbose)) {
+ SetVerbosity(static_cast<unsigned int>(iVerbose));
+ } else {
+ // Non numeric verbosity
+ SetVerbose(cmIsOn(verbose));
+ }
+ }
+ }
+ {
+ std::string colorEnv;
+ cmSystemTools::GetEnv("COLOR", colorEnv);
+ if (!colorEnv.empty()) {
+ SetColorOutput(cmIsOn(colorEnv));
+ } else {
+ SetColorOutput(true);
+ }
+ }
+}
+
+cmQtAutoGenerator::Logger::~Logger() = default;
+
+void cmQtAutoGenerator::Logger::RaiseVerbosity(unsigned int value)
+{
+ if (this->Verbosity_ < value) {
+ this->Verbosity_ = value;
+ }
+}
+
+void cmQtAutoGenerator::Logger::SetColorOutput(bool value)
+{
+ ColorOutput_ = value;
+}
+
+std::string cmQtAutoGenerator::Logger::HeadLine(cm::string_view title)
+{
+ return cmStrCat(title, '\n', std::string(title.size(), '-'), '\n');
+}
+
+void cmQtAutoGenerator::Logger::Info(GenT genType,
+ cm::string_view message) const
+{
+ std::string msg = cmStrCat(GeneratorName(genType), ": ", message,
+ cmHasSuffix(message, '\n') ? "" : "\n");
+ {
+ std::lock_guard<std::mutex> lock(Mutex_);
+ cmSystemTools::Stdout(msg);
+ }
+}
+
+void cmQtAutoGenerator::Logger::Warning(GenT genType,
+ cm::string_view message) const
+{
+ std::string msg;
+ if (message.find('\n') == std::string::npos) {
+ // Single line message
+ msg = cmStrCat(GeneratorName(genType), " warning: ", message,
+ cmHasSuffix(message, '\n') ? "\n" : "\n\n");
+ } else {
+ // Multi line message
+ msg = cmStrCat(HeadLine(cmStrCat(GeneratorName(genType), " warning")),
+ message, cmHasSuffix(message, '\n') ? "\n" : "\n\n");
+ }
+ {
+ std::lock_guard<std::mutex> lock(Mutex_);
+ cmSystemTools::Stdout(msg);
+ }
+}
+
+void cmQtAutoGenerator::Logger::Error(GenT genType,
+ cm::string_view message) const
+{
+ std::string msg =
+ cmStrCat('\n', HeadLine(cmStrCat(GeneratorName(genType), " error")),
+ message, cmHasSuffix(message, '\n') ? "\n" : "\n\n");
+ {
+ std::lock_guard<std::mutex> lock(Mutex_);
+ cmSystemTools::Stderr(msg);
+ }
+}
+
+void cmQtAutoGenerator::Logger::ErrorCommand(
+ GenT genType, cm::string_view message,
+ std::vector<std::string> const& command, std::string const& output) const
+{
+ std::string msg = cmStrCat(
+ '\n', HeadLine(cmStrCat(GeneratorName(genType), " subprocess error")),
+ message, cmHasSuffix(message, '\n') ? "\n" : "\n\n");
+ msg += cmStrCat(HeadLine("Command"), QuotedCommand(command), "\n\n");
+ msg += cmStrCat(HeadLine("Output"), output,
+ cmHasSuffix(output, '\n') ? "\n" : "\n\n");
+ {
+ std::lock_guard<std::mutex> lock(Mutex_);
+ cmSystemTools::Stderr(msg);
+ }
+}
+
+bool cmQtAutoGenerator::MakeParentDirectory(std::string const& filename)
+{
+ bool success = true;
+ std::string const dirName = cmSystemTools::GetFilenamePath(filename);
+ if (!dirName.empty()) {
+ success = cmSystemTools::MakeDirectory(dirName);
+ }
+ return success;
+}
+
+bool cmQtAutoGenerator::FileRead(std::string& content,
+ std::string const& filename,
+ std::string* error)
+{
+ content.clear();
+ if (!cmSystemTools::FileExists(filename, true)) {
+ if (error != nullptr) {
+ *error = "Not a file.";
+ }
+ return false;
+ }
+
+ unsigned long const length = cmSystemTools::FileLength(filename);
+ cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
+
+ // Use lambda to save destructor calls of ifs
+ return [&ifs, length, &content, error]() -> bool {
+ if (!ifs) {
+ if (error != nullptr) {
+ *error = "Opening the file for reading failed.";
+ }
+ return false;
+ }
+ content.reserve(length);
+ using IsIt = std::istreambuf_iterator<char>;
+ content.assign(IsIt{ ifs }, IsIt{});
+ if (!ifs) {
+ content.clear();
+ if (error != nullptr) {
+ *error = "Reading from the file failed.";
+ }
+ return false;
+ }
+ return true;
+ }();
+}
+
+bool cmQtAutoGenerator::FileWrite(std::string const& filename,
+ std::string const& content,
+ std::string* error)
+{
+ // Make sure the parent directory exists
+ if (!cmQtAutoGenerator::MakeParentDirectory(filename)) {
+ if (error != nullptr) {
+ *error = "Could not create parent directory.";
+ }
+ return false;
+ }
+ cmsys::ofstream ofs;
+ ofs.open(filename.c_str(),
+ (std::ios::out | std::ios::binary | std::ios::trunc));
+
+ // Use lambda to save destructor calls of ofs
+ return [&ofs, &content, error]() -> bool {
+ if (!ofs) {
+ if (error != nullptr) {
+ *error = "Opening file for writing failed.";
+ }
+ return false;
+ }
+ ofs << content;
+ if (!ofs.good()) {
+ if (error != nullptr) {
+ *error = "File writing failed.";
+ }
+ return false;
+ }
+ return true;
+ }();
+}
+
+bool cmQtAutoGenerator::FileDiffers(std::string const& filename,
+ std::string const& content)
+{
+ bool differs = true;
+ std::string oldContents;
+ if (FileRead(oldContents, filename) && (oldContents == content)) {
+ differs = false;
+ }
+ return differs;
+}
+
+cmQtAutoGenerator::cmQtAutoGenerator(GenT genType)
+ : GenType_(genType)
+{
+}
+
+cmQtAutoGenerator::~cmQtAutoGenerator() = default;
+
+bool cmQtAutoGenerator::InfoT::Read(std::istream& istr)
+{
+ try {
+ istr >> Json_;
+ } catch (...) {
+ return false;
+ }
+ return true;
+}
+
+bool cmQtAutoGenerator::InfoT::GetJsonArray(std::vector<std::string>& list,
+ Json::Value const& jval)
+{
+ Json::ArrayIndex const arraySize = jval.size();
+ if (arraySize == 0) {
+ return false;
+ }
+
+ bool picked = false;
+ list.reserve(list.size() + arraySize);
+ for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
+ Json::Value const& ival = jval[ii];
+ if (ival.isString()) {
+ list.emplace_back(ival.asString());
+ picked = true;
+ }
+ }
+ return picked;
+}
+
+bool cmQtAutoGenerator::InfoT::GetJsonArray(
+ std::unordered_set<std::string>& list, Json::Value const& jval)
+{
+ Json::ArrayIndex const arraySize = jval.size();
+ if (arraySize == 0) {
+ return false;
+ }
+
+ bool picked = false;
+ list.reserve(list.size() + arraySize);
+ for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
+ Json::Value const& ival = jval[ii];
+ if (ival.isString()) {
+ list.emplace(ival.asString());
+ picked = true;
+ }
+ }
+ return picked;
+}
+
+std::string cmQtAutoGenerator::InfoT::ConfigKey(cm::string_view key) const
+{
+ return cmStrCat(key, '_', Gen_.InfoConfig());
+}
+
+bool cmQtAutoGenerator::InfoT::GetString(std::string const& key,
+ std::string& value,
+ bool required) const
+{
+ Json::Value const& jval = Json_[key];
+ if (!jval.isString()) {
+ if (!jval.isNull() || required) {
+ return LogError(cmStrCat(key, " is not a string."));
+ }
+ } else {
+ value = jval.asString();
+ if (value.empty() && required) {
+ return LogError(cmStrCat(key, " is empty."));
+ }
+ }
+ return true;
+}
+
+bool cmQtAutoGenerator::InfoT::GetStringConfig(std::string const& key,
+ std::string& value,
+ bool required) const
+{
+ { // Try config
+ std::string const configKey = ConfigKey(key);
+ Json::Value const& jval = Json_[configKey];
+ if (!jval.isNull()) {
+ if (!jval.isString()) {
+ return LogError(cmStrCat(configKey, " is not a string."));
+ }
+ value = jval.asString();
+ if (required && value.empty()) {
+ return LogError(cmStrCat(configKey, " is empty."));
+ }
+ return true;
+ }
+ }
+ // Try plain
+ return GetString(key, value, required);
+}
+
+bool cmQtAutoGenerator::InfoT::GetBool(std::string const& key, bool& value,
+ bool required) const
+{
+ Json::Value const& jval = Json_[key];
+ if (jval.isBool()) {
+ value = jval.asBool();
+ } else {
+ if (!jval.isNull() || required) {
+ return LogError(cmStrCat(key, " is not a boolean."));
+ }
+ }
+ return true;
+}
+
+bool cmQtAutoGenerator::InfoT::GetUInt(std::string const& key,
+ unsigned int& value,
+ bool required) const
+{
+ Json::Value const& jval = Json_[key];
+ if (jval.isUInt()) {
+ value = jval.asUInt();
+ } else {
+ if (!jval.isNull() || required) {
+ return LogError(cmStrCat(key, " is not an unsigned integer."));
+ }
+ }
+ return true;
+}
+
+bool cmQtAutoGenerator::InfoT::GetArray(std::string const& key,
+ std::vector<std::string>& list,
+ bool required) const
+{
+ Json::Value const& jval = Json_[key];
+ if (!jval.isArray()) {
+ if (!jval.isNull() || required) {
+ return LogError(cmStrCat(key, " is not an array."));
+ }
+ }
+ return GetJsonArray(list, jval) || !required;
+}
+
+bool cmQtAutoGenerator::InfoT::GetArray(std::string const& key,
+ std::unordered_set<std::string>& list,
+ bool required) const
+{
+ Json::Value const& jval = Json_[key];
+ if (!jval.isArray()) {
+ if (!jval.isNull() || required) {
+ return LogError(cmStrCat(key, " is not an array."));
+ }
+ }
+ return GetJsonArray(list, jval) || !required;
+}
+
+bool cmQtAutoGenerator::InfoT::GetArrayConfig(std::string const& key,
+ std::vector<std::string>& list,
+ bool required) const
+{
+ { // Try config
+ std::string const configKey = ConfigKey(key);
+ Json::Value const& jval = Json_[configKey];
+ if (!jval.isNull()) {
+ if (!jval.isArray()) {
+ return LogError(cmStrCat(configKey, " is not an array string."));
+ }
+ if (!GetJsonArray(list, jval) && required) {
+ return LogError(cmStrCat(configKey, " is empty."));
+ }
+ return true;
+ }
+ }
+ // Try plain
+ return GetArray(key, list, required);
+}
+
+bool cmQtAutoGenerator::InfoT::LogError(GenT genType,
+ cm::string_view message) const
+{
+ Gen_.Log().Error(genType,
+ cmStrCat("Info error in info file\n",
+ Quoted(Gen_.InfoFile()), ":\n", message));
+ return false;
+}
+
+bool cmQtAutoGenerator::InfoT::LogError(cm::string_view message) const
+{
+ return LogError(Gen_.GenType_, message);
+}
+
+std::string cmQtAutoGenerator::SettingsFind(cm::string_view content,
+ cm::string_view key)
+{
+ cm::string_view res;
+ std::string const prefix = cmStrCat(key, ':');
+ cm::string_view::size_type pos = content.find(prefix);
+ if (pos != cm::string_view::npos) {
+ pos += prefix.size();
+ if (pos < content.size()) {
+ cm::string_view::size_type posE = content.find('\n', pos);
+ if ((posE != cm::string_view::npos) && (posE != pos)) {
+ res = content.substr(pos, posE - pos);
+ }
+ }
+ }
+ return std::string(res);
+}
+
+std::string cmQtAutoGenerator::MessagePath(cm::string_view path) const
+{
+ std::string res;
+ if (cmHasPrefix(path, ProjectDirs().Source)) {
+ res = cmStrCat("SRC:", path.substr(ProjectDirs().Source.size()));
+ } else if (cmHasPrefix(path, ProjectDirs().Binary)) {
+ res = cmStrCat("BIN:", path.substr(ProjectDirs().Binary.size()));
+ } else {
+ res = std::string(path);
+ }
+ return cmQtAutoGen::Quoted(res);
+}
+
+bool cmQtAutoGenerator::Run(cm::string_view infoFile, cm::string_view config)
+{
+ // Info config
+ InfoConfig_ = std::string(config);
+
+ // Info file
+ InfoFile_ = std::string(infoFile);
+ cmSystemTools::CollapseFullPath(InfoFile_);
+ InfoDir_ = cmSystemTools::GetFilenamePath(InfoFile_);
+
+ // Load info file time
+ if (!InfoFileTime_.Load(InfoFile_)) {
+ cmSystemTools::Stderr(cmStrCat("AutoGen: The info file ",
+ Quoted(InfoFile_), " is not readable\n"));
+ return false;
+ }
+
+ {
+ InfoT info(*this);
+
+ // Read info file
+ {
+ cmsys::ifstream ifs(InfoFile_.c_str(),
+ (std::ios::in | std::ios::binary));
+ if (!ifs) {
+ Log().Error(
+ GenType_,
+ cmStrCat("Could not to open info file ", Quoted(InfoFile_)));
+ return false;
+ }
+ if (!info.Read(ifs)) {
+ Log().Error(GenType_,
+ cmStrCat("Could not read info file ", Quoted(InfoFile_)));
+ return false;
+ }
+ }
+
+ // -- Read common info settings
+ {
+ unsigned int verbosity = 0;
+ // Info: setup project directories
+ if (!info.GetUInt("VERBOSITY", verbosity, false) ||
+ !info.GetString("CMAKE_SOURCE_DIR", ProjectDirs_.Source, true) ||
+ !info.GetString("CMAKE_BINARY_DIR", ProjectDirs_.Binary, true) ||
+ !info.GetString("CMAKE_CURRENT_SOURCE_DIR",
+ ProjectDirs_.CurrentSource, true) ||
+ !info.GetString("CMAKE_CURRENT_BINARY_DIR",
+ ProjectDirs_.CurrentBinary, true)) {
+ return false;
+ }
+ Logger_.RaiseVerbosity(verbosity);
+ }
+
+ // -- Call virtual init from info method.
+ if (!this->InitFromInfo(info)) {
+ return false;
+ }
+ }
+
+ // Call virtual process method.
+ return this->Process();
+}
diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h
new file mode 100644
index 000000000..bbe6dd015
--- /dev/null
+++ b/Source/cmQtAutoGenerator.h
@@ -0,0 +1,181 @@
+/* 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 <istream>
+#include <mutex>
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+#include <cm/string_view>
+
+#include "cm_jsoncpp_value.h"
+
+#include "cmFileTime.h"
+#include "cmQtAutoGen.h"
+
+/** \class cmQtAutoGenerator
+ * \brief Base class for QtAutoGen generators
+ */
+class cmQtAutoGenerator : public cmQtAutoGen
+{
+public:
+ // -- Types
+
+ /** Thread safe logger. */
+ class Logger
+ {
+ public:
+ // -- Construction
+ Logger();
+ ~Logger();
+ // -- Verbosity
+ unsigned int Verbosity() const { return this->Verbosity_; }
+ void SetVerbosity(unsigned int value) { this->Verbosity_ = value; }
+ void RaiseVerbosity(unsigned int value);
+ bool Verbose() const { return (this->Verbosity_ != 0); }
+ void SetVerbose(bool value) { this->Verbosity_ = value ? 1 : 0; }
+ // -- Color output
+ bool ColorOutput() const { return this->ColorOutput_; }
+ void SetColorOutput(bool value);
+ // -- Log info
+ void Info(GenT genType, cm::string_view message) const;
+ // -- Log warning
+ void Warning(GenT genType, cm::string_view message) const;
+ // -- Log error
+ void Error(GenT genType, cm::string_view message) const;
+ void ErrorCommand(GenT genType, cm::string_view message,
+ std::vector<std::string> const& command,
+ std::string const& output) const;
+
+ private:
+ static std::string HeadLine(cm::string_view title);
+
+ private:
+ mutable std::mutex Mutex_;
+ unsigned int Verbosity_ = 0;
+ bool ColorOutput_ = false;
+ };
+
+ /** Project directories. */
+ struct ProjectDirsT
+ {
+ std::string Source;
+ std::string Binary;
+ std::string CurrentSource;
+ std::string CurrentBinary;
+ };
+
+ // -- File system methods
+ static bool MakeParentDirectory(std::string const& filename);
+ static bool FileRead(std::string& content, std::string const& filename,
+ std::string* error = nullptr);
+ static bool FileWrite(std::string const& filename,
+ std::string const& content,
+ std::string* error = nullptr);
+ static bool FileDiffers(std::string const& filename,
+ std::string const& content);
+
+public:
+ // -- Constructors
+ cmQtAutoGenerator(GenT genType);
+ virtual ~cmQtAutoGenerator();
+
+ cmQtAutoGenerator(cmQtAutoGenerator const&) = delete;
+ cmQtAutoGenerator& operator=(cmQtAutoGenerator const&) = delete;
+
+ // -- Info options
+ std::string const& InfoFile() const { return InfoFile_; }
+ std::string const& InfoDir() const { return InfoDir_; }
+ cmFileTime const& InfoFileTime() const { return InfoFileTime_; }
+ std::string const& InfoConfig() const { return InfoConfig_; }
+
+ // -- Info file parsing
+ /** Info file reader class. */
+ class InfoT
+ {
+ public:
+ InfoT(cmQtAutoGenerator& gen)
+ : Gen_(gen)
+ {
+ }
+
+ /** Read json data from a stream. */
+ bool Read(std::istream& istr);
+
+ /** Returns false if the JSON value isn't a string. */
+ bool GetString(std::string const& key, std::string& value,
+ bool required) const;
+ bool GetStringConfig(std::string const& key, std::string& value,
+ bool required) const;
+ bool GetBool(std::string const& key, bool& value, bool required) const;
+ bool GetUInt(std::string const& key, unsigned int& value,
+ bool required) const;
+ /** Returns false if the JSON value isn't an array. */
+ bool GetArray(std::string const& key, std::vector<std::string>& list,
+ bool required) const;
+ bool GetArray(std::string const& key,
+ std::unordered_set<std::string>& list, bool required) const;
+ bool GetArrayConfig(std::string const& key, std::vector<std::string>& list,
+ bool required) const;
+
+ Json::Value const& GetValue(std::string const& key) const
+ {
+ return Json_[key];
+ }
+
+ /** Returns true if strings were appended to the list. */
+ static bool GetJsonArray(std::vector<std::string>& list,
+ Json::Value const& jval);
+ /** Returns true if strings were found in the JSON array. */
+ static bool GetJsonArray(std::unordered_set<std::string>& list,
+ Json::Value const& jval);
+
+ bool LogError(GenT genType, cm::string_view message) const;
+ bool LogError(cm::string_view message) const;
+
+ private:
+ std::string ConfigKey(cm::string_view key) const;
+
+ private:
+ Json::Value Json_;
+ cmQtAutoGenerator& Gen_;
+ };
+
+ // -- Settings file
+ static std::string SettingsFind(cm::string_view content,
+ cm::string_view key);
+
+ // -- Directories
+ ProjectDirsT const& ProjectDirs() const { return ProjectDirs_; }
+ std::string MessagePath(cm::string_view path) const;
+
+ // -- Run
+ bool Run(cm::string_view infoFile, cm::string_view config);
+
+protected:
+ // -- Abstract processing interface
+ virtual bool InitFromInfo(InfoT const& info) = 0;
+ virtual bool Process() = 0;
+ // - Utility classes
+ Logger const& Log() const { return Logger_; }
+
+private:
+ // -- Generator type
+ GenT GenType_;
+ // -- Logging
+ Logger Logger_;
+ // -- Info file
+ std::string InfoFile_;
+ std::string InfoDir_;
+ cmFileTime InfoFileTime_;
+ std::string InfoConfig_;
+ // -- Directories
+ ProjectDirsT ProjectDirs_;
+};
+
+#endif
diff --git a/Source/cmQtAutoGeneratorCommon.cxx b/Source/cmQtAutoGeneratorCommon.cxx
deleted file mode 100644
index 3e1b58caa..000000000
--- a/Source/cmQtAutoGeneratorCommon.cxx
+++ /dev/null
@@ -1,216 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmQtAutoGeneratorCommon.h"
-#include "cmAlgorithms.h"
-#include "cmSystemTools.h"
-
-#include "cmsys/FStream.hxx"
-#include "cmsys/RegularExpression.hxx"
-
-#include <sstream>
-#include <stddef.h>
-
-// - Static functions
-
-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(const std::string& 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 != CM_NULLPTR) {
- std::ostringstream ost;
- ost << "AutoRcc: Error: Rcc file not readable:\n"
- << cmQtAutoGeneratorCommon::Quoted(fileName) << "\n";
- *errorMessage = ost.str();
- }
- allGood = false;
- }
- }
- if (allGood) {
- // qrc file directory
- std::string qrcDir(cmsys::SystemTools::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(const std::string& rccCommand,
- const std::string& fileName,
- std::vector<std::string>& files,
- std::string* errorMessage)
-{
- if (rccCommand.empty()) {
- cmSystemTools::Error("AutoRcc: Error: rcc executable not available\n");
- 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,
- CM_NULLPTR, cmSystemTools::OUTPUT_NONE);
- if (result && retVal == 0 &&
- rccStdOut.find("--list") != std::string::npos) {
- hasDashDashList = true;
- }
- }
-
- // 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(fileName);
- result =
- cmSystemTools::RunSingleCommand(command, &rccStdOut, &rccStdErr, &retVal,
- CM_NULLPTR, cmSystemTools::OUTPUT_NONE);
- }
- if (!result || retVal) {
- if (errorMessage != CM_NULLPTR) {
- std::ostringstream ost;
- ost << "AutoRcc: Error: Rcc list process for " << fileName
- << " failed:\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 != CM_NULLPTR) {
- std::ostringstream ost;
- ost << "AutoRcc: Error: Rcc lists unparsable output:\n"
- << cmQtAutoGeneratorCommon::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));
- }
- }
- }
-
- return true;
-}
-
-// - Class definitions
-
-const char* cmQtAutoGeneratorCommon::listSep = "@LSEP@";
-
-std::string cmQtAutoGeneratorCommon::Quoted(const std::string& text)
-{
- static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a",
- "\b", "\\b", "\f", "\\f", "\n", "\\n",
- "\r", "\\r", "\t", "\\t", "\v", "\\v" };
-
- std::string res = text;
- for (const char* const* it = cmArrayBegin(rep); it != cmArrayEnd(rep);
- it += 2) {
- cmSystemTools::ReplaceString(res, *it, *(it + 1));
- }
- res = '"' + res;
- res += '"';
- return res;
-}
-
-bool cmQtAutoGeneratorCommon::RccListInputs(const std::string& qtMajorVersion,
- const std::string& rccCommand,
- const std::string& fileName,
- std::vector<std::string>& files,
- std::string* errorMessage)
-{
- bool allGood = false;
- if (cmsys::SystemTools::FileExists(fileName.c_str())) {
- if (qtMajorVersion == "4") {
- allGood = RccListInputsQt4(fileName, files, errorMessage);
- } else {
- allGood = RccListInputsQt5(rccCommand, fileName, files, errorMessage);
- }
- } else {
- if (errorMessage != CM_NULLPTR) {
- std::ostringstream ost;
- ost << "AutoRcc: Error: Rcc file does not exist:\n"
- << cmQtAutoGeneratorCommon::Quoted(fileName) << "\n";
- *errorMessage = ost.str();
- }
- }
- return allGood;
-}
diff --git a/Source/cmQtAutoGeneratorCommon.h b/Source/cmQtAutoGeneratorCommon.h
deleted file mode 100644
index a131baf20..000000000
--- a/Source/cmQtAutoGeneratorCommon.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmQtAutoGeneratorCommon_h
-#define cmQtAutoGeneratorCommon_h
-
-#include "cmConfigure.h"
-
-#include <string>
-#include <vector>
-
-class cmQtAutoGeneratorCommon
-{
- // - Types and statics
-public:
- static const char* listSep;
-
- enum GeneratorType
- {
- MOC,
- UIC,
- RCC
- };
-
-public:
- /// @brief Returns a the string escaped and enclosed in quotes
- ///
- static std::string Quoted(const std::string& text);
-
- /// @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(const std::string& qtMajorVersion,
- const std::string& rccCommand,
- const std::string& fileName,
- std::vector<std::string>& files,
- std::string* errorMessage = CM_NULLPTR);
-};
-
-#endif
diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
deleted file mode 100644
index 3e3be54d1..000000000
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ /dev/null
@@ -1,1131 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmQtAutoGeneratorInitializer.h"
-#include "cmQtAutoGeneratorCommon.h"
-
-#include "cmAlgorithms.h"
-#include "cmCustomCommandLines.h"
-#include "cmFilePathChecksum.h"
-#include "cmGeneratorTarget.h"
-#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmMakefile.h"
-#include "cmOutputConverter.h"
-#include "cmSourceFile.h"
-#include "cmSourceGroup.h"
-#include "cmState.h"
-#include "cmSystemTools.h"
-#include "cmTarget.h"
-#include "cm_sys_stat.h"
-#include "cmake.h"
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#include "cmGlobalVisualStudioGenerator.h"
-#endif
-
-#include "cmConfigure.h"
-#include "cmsys/FStream.hxx"
-#include <algorithm>
-#include <map>
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
-static void utilCopyTargetProperty(cmTarget* destinationTarget,
- cmTarget* sourceTarget,
- const std::string& propertyName)
-{
- const char* propertyValue = sourceTarget->GetProperty(propertyName);
- if (propertyValue) {
- destinationTarget->SetProperty(propertyName, propertyValue);
- }
-}
-
-inline static bool PropertyEnabled(cmSourceFile* sourceFile, const char* key)
-{
- return cmSystemTools::IsOn(sourceFile->GetPropertyForUser(key));
-}
-
-static std::string GetSafeProperty(cmGeneratorTarget const* target,
- const char* key)
-{
- const char* tmp = target->GetProperty(key);
- return std::string((tmp != CM_NULLPTR) ? tmp : "");
-}
-
-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;
-}
-
-static std::string GetQtMajorVersion(cmGeneratorTarget const* target)
-{
- cmMakefile* makefile = target->Target->GetMakefile();
- std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
- if (qtMajorVersion.empty()) {
- qtMajorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
- }
- const char* targetQtVersion =
- target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "");
- if (targetQtVersion != CM_NULLPTR) {
- qtMajorVersion = targetQtVersion;
- }
- return qtMajorVersion;
-}
-
-static std::string GetQtMinorVersion(cmGeneratorTarget const* target,
- const std::string& qtMajorVersion)
-{
- cmMakefile* makefile = target->Target->GetMakefile();
- std::string qtMinorVersion;
- if (qtMajorVersion == "5") {
- qtMinorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR");
- }
- if (qtMinorVersion.empty()) {
- qtMinorVersion = makefile->GetSafeDefinition("QT_VERSION_MINOR");
- }
-
- const char* targetQtVersion =
- target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", "");
- if (targetQtVersion != CM_NULLPTR) {
- qtMinorVersion = targetQtVersion;
- }
- return qtMinorVersion;
-}
-
-static bool QtVersionGreaterOrEqual(const std::string& major,
- const std::string& 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 GetCompileDefinitionsAndDirectories(
- cmGeneratorTarget const* target, const std::string& config,
- std::string& incs, std::string& defs)
-{
- cmLocalGenerator* localGen = target->GetLocalGenerator();
- {
- std::vector<std::string> includeDirs;
- // Get the include dirs for this target, without stripping the implicit
- // include dirs off, see
- // https://gitlab.kitware.com/cmake/cmake/issues/13667
- localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false);
- incs = cmJoin(includeDirs, ";");
- }
- {
- std::set<std::string> defines;
- localGen->AddCompileDefinitions(defines, target, config, "CXX");
- defs += cmJoin(defines, ";");
- }
-}
-
-static bool IsMultiConfig(cmGlobalGenerator* globalGen)
-{
- // FIXME: Xcode does not support per-config sources, yet.
- // (EXCLUDED_SOURCE_FILE_NAMES)
- // Treat it as a single configuration generator meanwhile.
- if (globalGen->GetName().find("Xcode") != std::string::npos) {
- return false;
- }
- // FIXME: Visual Studio does not fully support per-config sources yet.
- if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
- return false;
- }
- return globalGen->IsMultiConfig();
-}
-
-static std::vector<std::string> GetConfigurations(
- cmMakefile* makefile, std::string* config = CM_NULLPTR)
-{
- std::vector<std::string> configs;
- {
- std::string cfg = makefile->GetConfigurations(configs);
- if (config != CM_NULLPTR) {
- *config = cfg;
- }
- }
- // Add empty configuration on demand
- if (configs.empty()) {
- configs.push_back("");
- }
- return configs;
-}
-
-static std::vector<std::string> GetConfigurationSuffixes(cmMakefile* makefile)
-{
- std::vector<std::string> suffixes;
- if (IsMultiConfig(makefile->GetGlobalGenerator())) {
- makefile->GetConfigurations(suffixes);
- for (std::vector<std::string>::iterator it = suffixes.begin();
- it != suffixes.end(); ++it) {
- it->insert(0, "_");
- }
- }
- if (suffixes.empty()) {
- suffixes.push_back("");
- }
- return suffixes;
-}
-
-static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
- const std::string& 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 bool AddToSourceGroup(cmMakefile* makefile, const std::string& fileName,
- cmQtAutoGeneratorCommon::GeneratorType genType)
-{
- cmSourceGroup* sourceGroup = CM_NULLPTR;
- // Acquire source group
- {
- const char* groupName = CM_NULLPTR;
- // Use generator specific group name
- switch (genType) {
- case cmQtAutoGeneratorCommon::MOC:
- groupName =
- makefile->GetState()->GetGlobalProperty("AUTOMOC_SOURCE_GROUP");
- break;
- case cmQtAutoGeneratorCommon::RCC:
- groupName =
- makefile->GetState()->GetGlobalProperty("AUTORCC_SOURCE_GROUP");
- break;
- default:
- break;
- }
- // Use default group name on demand
- if ((groupName == CM_NULLPTR) || (*groupName == 0)) {
- groupName =
- makefile->GetState()->GetGlobalProperty("AUTOGEN_SOURCE_GROUP");
- }
- // Generate a source group on demand
- if ((groupName != CM_NULLPTR) && (*groupName != 0)) {
- {
- const char* delimiter =
- makefile->GetDefinition("SOURCE_GROUP_DELIMITER");
- if (delimiter == CM_NULLPTR) {
- delimiter = "\\";
- }
- std::vector<std::string> folders =
- cmSystemTools::tokenize(groupName, delimiter);
- sourceGroup = makefile->GetSourceGroup(folders);
- if (sourceGroup == CM_NULLPTR) {
- makefile->AddSourceGroup(folders);
- sourceGroup = makefile->GetSourceGroup(folders);
- }
- }
- if (sourceGroup == CM_NULLPTR) {
- cmSystemTools::Error(
- "Autogen: Could not create or find source group: ",
- cmQtAutoGeneratorCommon::Quoted(groupName).c_str());
- return false;
- }
- }
- }
- if (sourceGroup != CM_NULLPTR) {
- sourceGroup->AddGroupFile(fileName);
- }
- return true;
-}
-
-static void AddGeneratedSource(cmMakefile* makefile,
- const std::string& filename,
- cmQtAutoGeneratorCommon::GeneratorType genType)
-{
- cmSourceFile* gFile = makefile->GetOrCreateSource(filename, true);
- gFile->SetProperty("GENERATED", "1");
- gFile->SetProperty("SKIP_AUTOGEN", "On");
-
- AddToSourceGroup(makefile, filename, genType);
-}
-
-static void AcquireScanFiles(cmGeneratorTarget const* target,
- std::vector<std::string>& mocUicSources,
- std::vector<std::string>& mocUicHeaders,
- std::vector<std::string>& mocSkipList,
- std::vector<std::string>& uicSkipList)
-{
- const bool mocTarget = target->GetPropertyAsBool("AUTOMOC");
- const bool uicTarget = target->GetPropertyAsBool("AUTOUIC");
-
- std::vector<cmSourceFile*> srcFiles;
- target->GetConfigCommonSourceFiles(srcFiles);
- for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
- fileIt != srcFiles.end(); ++fileIt) {
- cmSourceFile* sf = *fileIt;
- const cmSystemTools::FileFormat fileType =
- cmSystemTools::GetFileFormat(sf->GetExtension().c_str());
-
- if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) &&
- !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
- continue;
- }
- if (PropertyEnabled(sf, "GENERATED") &&
- !target->GetPropertyAsBool("__UNDOCUMENTED_AUTOGEN_GENERATED_FILES")) {
- // FIXME: Add a policy whose NEW behavior allows generated files.
- // The implementation already works. We disable it here to avoid
- // changing behavior for existing projects that do not expect it.
- continue;
- }
- const std::string absFile =
- cmsys::SystemTools::GetRealPath(sf->GetFullPath());
- // Skip flags
- const bool skipAll = PropertyEnabled(sf, "SKIP_AUTOGEN");
- const bool mocSkip = skipAll || PropertyEnabled(sf, "SKIP_AUTOMOC");
- const bool uicSkip = skipAll || PropertyEnabled(sf, "SKIP_AUTOUIC");
- // Add file name to skip lists.
- // Do this even when the file is not added to the sources/headers lists
- // because the file name may be extracted from an other file when
- // processing
- if (mocSkip) {
- mocSkipList.push_back(absFile);
- }
- if (uicSkip) {
- uicSkipList.push_back(absFile);
- }
-
- if ((mocTarget && !mocSkip) || (uicTarget && !uicSkip)) {
- // Add file name to sources or headers list
- switch (fileType) {
- case cmSystemTools::CXX_FILE_FORMAT:
- mocUicSources.push_back(absFile);
- break;
- case cmSystemTools::HEADER_FILE_FORMAT:
- mocUicHeaders.push_back(absFile);
- break;
- default:
- break;
- }
- }
- }
-}
-
-static void MocSetupAutoTarget(
- cmGeneratorTarget const* target, const std::string& autogenTargetName,
- std::string const& qtMajorVersion, std::string const& config,
- std::vector<std::string> const& configs,
- std::vector<std::string> const& mocSkipList,
- std::map<std::string, std::string>& configMocIncludes,
- std::map<std::string, std::string>& configMocDefines)
-{
- cmLocalGenerator* lg = target->GetLocalGenerator();
- cmMakefile* makefile = target->Target->GetMakefile();
-
- AddDefinitionEscaped(makefile, "_moc_options",
- GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS"));
- AddDefinitionEscaped(makefile, "_moc_skip", mocSkipList);
- AddDefinitionEscaped(makefile, "_moc_relaxed_mode",
- makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE"
- : "FALSE");
- AddDefinitionEscaped(makefile, "_moc_depend_filters",
- GetSafeProperty(target, "AUTOMOC_DEPEND_FILTERS"));
-
- if (QtVersionGreaterOrEqual(
- qtMajorVersion, GetQtMinorVersion(target, qtMajorVersion), 5, 8)) {
- AddDefinitionEscaped(
- makefile, "_moc_predefs_cmd",
- makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));
- }
- // Moc includes and compile definitions
- {
- // Default settings
- std::string incs;
- std::string compileDefs;
- GetCompileDefinitionsAndDirectories(target, config, incs, compileDefs);
- AddDefinitionEscaped(makefile, "_moc_incs", incs);
- AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs);
-
- // Configuration specific settings
- for (std::vector<std::string>::const_iterator li = configs.begin();
- li != configs.end(); ++li) {
- std::string configIncs;
- std::string configCompileDefs;
- GetCompileDefinitionsAndDirectories(target, *li, configIncs,
- configCompileDefs);
- if (configIncs != incs) {
- configMocIncludes[*li] = cmOutputConverter::EscapeForCMake(configIncs);
- }
- if (configCompileDefs != compileDefs) {
- configMocDefines[*li] =
- cmOutputConverter::EscapeForCMake(configCompileDefs);
- }
- }
- }
-
- // Moc executable
- {
- std::string err;
- const char* mocExec = CM_NULLPTR;
- if (qtMajorVersion == "5") {
- cmGeneratorTarget* qt5Moc = lg->FindGeneratorTargetToUse("Qt5::moc");
- if (qt5Moc != CM_NULLPTR) {
- mocExec = qt5Moc->ImportedGetLocation("");
- } else {
- err = "Qt5::moc target not found " + autogenTargetName;
- }
- } else if (qtMajorVersion == "4") {
- cmGeneratorTarget* qt4Moc = lg->FindGeneratorTargetToUse("Qt4::moc");
- if (qt4Moc != CM_NULLPTR) {
- mocExec = qt4Moc->ImportedGetLocation("");
- } else {
- err = "Qt4::moc target not found " + autogenTargetName;
- }
- } else {
- err = "The CMAKE_AUTOMOC feature supports only Qt 4 and Qt 5 ";
- err += autogenTargetName;
- }
- // Add definition or error
- if (err.empty()) {
- AddDefinitionEscaped(makefile, "_qt_moc_executable",
- mocExec ? mocExec : "");
- } else {
- cmSystemTools::Error(err.c_str());
- }
- }
-}
-
-static void UicGetOpts(cmGeneratorTarget const* target,
- const std::string& config, std::string& optString)
-{
- std::vector<std::string> opts;
- target->GetAutoUicOptions(opts, config);
- optString = cmJoin(opts, ";");
-}
-
-static void UicSetupAutoTarget(
- cmGeneratorTarget const* target, std::string const& qtMajorVersion,
- std::string const& config, std::vector<std::string> const& configs,
- std::vector<std::string> const& uicSkipList,
- std::map<std::string, std::string>& configUicOptions)
-{
- cmLocalGenerator* lg = target->GetLocalGenerator();
- cmMakefile* makefile = target->Target->GetMakefile();
-
- AddDefinitionEscaped(makefile, "_uic_skip", uicSkipList);
-
- // Uic search paths
- {
- std::vector<std::string> uicSearchPaths;
- cmSystemTools::ExpandListArgument(
- GetSafeProperty(target, "AUTOUIC_SEARCH_PATHS"), uicSearchPaths);
- const std::string srcDir = makefile->GetCurrentSourceDirectory();
- for (std::vector<std::string>::iterator it = uicSearchPaths.begin();
- it != uicSearchPaths.end(); ++it) {
- *it = cmSystemTools::CollapseFullPath(*it, srcDir);
- }
- AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths);
- }
- // Uic target options
- {
- // Default settings
- std::string uicOpts;
- UicGetOpts(target, config, uicOpts);
- AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts);
-
- // Configuration specific settings
- for (std::vector<std::string>::const_iterator li = configs.begin();
- li != configs.end(); ++li) {
- std::string configUicOpts;
- UicGetOpts(target, *li, configUicOpts);
- if (configUicOpts != uicOpts) {
- configUicOptions[*li] =
- cmOutputConverter::EscapeForCMake(configUicOpts);
- }
- }
- }
- // Uic files options
- {
- std::vector<std::string> uiFileFiles;
- std::vector<std::string> uiFileOptions;
- {
- std::set<std::string> skipped;
- skipped.insert(uicSkipList.begin(), uicSkipList.end());
-
- const std::vector<cmSourceFile*> uiFilesWithOptions =
- makefile->GetQtUiFilesWithOptions();
- for (std::vector<cmSourceFile*>::const_iterator fileIt =
- uiFilesWithOptions.begin();
- fileIt != uiFilesWithOptions.end(); ++fileIt) {
- cmSourceFile* sf = *fileIt;
- const std::string absFile =
- cmsys::SystemTools::GetRealPath(sf->GetFullPath());
- if (skipped.insert(absFile).second) {
- // The file wasn't skipped
- uiFileFiles.push_back(absFile);
- {
- std::string opts = sf->GetProperty("AUTOUIC_OPTIONS");
- cmSystemTools::ReplaceString(opts, ";",
- cmQtAutoGeneratorCommon::listSep);
- uiFileOptions.push_back(opts);
- }
- }
- }
- }
- AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles);
- AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions);
- }
-
- // Uic executable
- {
- std::string err;
- const char* uicExec = CM_NULLPTR;
- if (qtMajorVersion == "5") {
- cmGeneratorTarget* qt5Uic = lg->FindGeneratorTargetToUse("Qt5::uic");
- if (qt5Uic != CM_NULLPTR) {
- uicExec = qt5Uic->ImportedGetLocation("");
- } else {
- // Project does not use Qt5Widgets, but has AUTOUIC ON anyway
- }
- } else if (qtMajorVersion == "4") {
- cmGeneratorTarget* qt4Uic = lg->FindGeneratorTargetToUse("Qt4::uic");
- if (qt4Uic != CM_NULLPTR) {
- uicExec = qt4Uic->ImportedGetLocation("");
- } else {
- err = "Qt4::uic target not found " + target->GetName();
- }
- } else {
- err = "The CMAKE_AUTOUIC feature supports only Qt 4 and Qt 5 ";
- err += target->GetName();
- }
- // Add definition or error
- if (err.empty()) {
- AddDefinitionEscaped(makefile, "_qt_uic_executable",
- uicExec ? uicExec : "");
- } else {
- cmSystemTools::Error(err.c_str());
- }
- }
-}
-
-static std::string RccGetExecutable(cmGeneratorTarget const* target,
- const std::string& qtMajorVersion)
-{
- std::string rccExec;
- cmLocalGenerator* lg = target->GetLocalGenerator();
- if (qtMajorVersion == "5") {
- cmGeneratorTarget* qt5Rcc = lg->FindGeneratorTargetToUse("Qt5::rcc");
- if (qt5Rcc != CM_NULLPTR) {
- rccExec = qt5Rcc->ImportedGetLocation("");
- } else {
- cmSystemTools::Error("Qt5::rcc target not found ",
- target->GetName().c_str());
- }
- } else if (qtMajorVersion == "4") {
- cmGeneratorTarget* qt4Rcc = lg->FindGeneratorTargetToUse("Qt4::rcc");
- if (qt4Rcc != CM_NULLPTR) {
- rccExec = qt4Rcc->ImportedGetLocation("");
- } else {
- cmSystemTools::Error("Qt4::rcc target not found ",
- target->GetName().c_str());
- }
- } else {
- cmSystemTools::Error(
- "The CMAKE_AUTORCC feature supports only Qt 4 and Qt 5 ",
- target->GetName().c_str());
- }
- return rccExec;
-}
-
-static void RccMergeOptions(std::vector<std::string>& opts,
- const std::vector<std::string>& fileOpts,
- bool isQt5)
-{
- static const char* valueOptions[] = { "name", "root", "compress",
- "threshold" };
- std::vector<std::string> extraOpts;
- for (std::vector<std::string>::const_iterator fit = fileOpts.begin();
- fit != fileOpts.end(); ++fit) {
- std::vector<std::string>::iterator existingIt =
- std::find(opts.begin(), opts.end(), *fit);
- if (existingIt != opts.end()) {
- const char* optName = fit->c_str();
- if (*optName == '-') {
- ++optName;
- if (isQt5 && *optName == '-') {
- ++optName;
- }
- }
- // Test if this is a value option and change the existing value
- if ((optName != fit->c_str()) &&
- std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions),
- cmStrCmp(optName)) != cmArrayEnd(valueOptions)) {
- const std::vector<std::string>::iterator existValueIt(existingIt + 1);
- const std::vector<std::string>::const_iterator fileValueIt(fit + 1);
- if ((existValueIt != opts.end()) && (fileValueIt != fileOpts.end())) {
- *existValueIt = *fileValueIt;
- ++fit;
- }
- }
- } else {
- extraOpts.push_back(*fit);
- }
- }
- opts.insert(opts.end(), extraOpts.begin(), extraOpts.end());
-}
-
-static void RccSetupAutoTarget(cmGeneratorTarget const* target,
- const std::string& qtMajorVersion)
-{
- cmMakefile* makefile = target->Target->GetMakefile();
- const bool qtMajorVersion5 = (qtMajorVersion == "5");
- const std::string rccCommand = RccGetExecutable(target, qtMajorVersion);
- std::vector<std::string> _rcc_files;
- std::vector<std::string> _rcc_inputs;
- std::vector<std::string> rccFileFiles;
- std::vector<std::string> rccFileOptions;
- std::vector<std::string> rccOptionsTarget;
- if (const char* opts = target->GetProperty("AUTORCC_OPTIONS")) {
- cmSystemTools::ExpandListArgument(opts, rccOptionsTarget);
- }
-
- std::vector<cmSourceFile*> srcFiles;
- target->GetConfigCommonSourceFiles(srcFiles);
- for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
- fileIt != srcFiles.end(); ++fileIt) {
- cmSourceFile* sf = *fileIt;
- if ((sf->GetExtension() == "qrc") &&
- !PropertyEnabled(sf, "SKIP_AUTOGEN") &&
- !PropertyEnabled(sf, "SKIP_AUTORCC")) {
- const std::string absFile =
- cmsys::SystemTools::GetRealPath(sf->GetFullPath());
- // qrc file
- _rcc_files.push_back(absFile);
- // qrc file entries
- {
- std::string entriesList = "{";
- // Read input file list only for non generated .qrc files.
- if (!PropertyEnabled(sf, "GENERATED")) {
- std::string error;
- std::vector<std::string> files;
- if (cmQtAutoGeneratorCommon::RccListInputs(
- qtMajorVersion, rccCommand, absFile, files, &error)) {
- entriesList += cmJoin(files, cmQtAutoGeneratorCommon::listSep);
- } else {
- cmSystemTools::Error(error.c_str());
- }
- }
- entriesList += "}";
- _rcc_inputs.push_back(entriesList);
- }
- // rcc options for this qrc file
- {
- // Merged target and file options
- std::vector<std::string> rccOptions(rccOptionsTarget);
- if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) {
- std::vector<std::string> optsVec;
- cmSystemTools::ExpandListArgument(prop, optsVec);
- RccMergeOptions(rccOptions, optsVec, qtMajorVersion5);
- }
- // Only store non empty options lists
- if (!rccOptions.empty()) {
- rccFileFiles.push_back(absFile);
- rccFileOptions.push_back(
- cmJoin(rccOptions, cmQtAutoGeneratorCommon::listSep));
- }
- }
- }
- }
-
- AddDefinitionEscaped(makefile, "_qt_rcc_executable", rccCommand);
- AddDefinitionEscaped(makefile, "_rcc_files", _rcc_files);
- AddDefinitionEscaped(makefile, "_rcc_inputs", _rcc_inputs);
- AddDefinitionEscaped(makefile, "_rcc_options_files", rccFileFiles);
- AddDefinitionEscaped(makefile, "_rcc_options_options", rccFileOptions);
-}
-
-void cmQtAutoGeneratorInitializer::InitializeAutogenSources(
- cmGeneratorTarget* target)
-{
- if (target->GetPropertyAsBool("AUTOMOC")) {
- cmMakefile* makefile = target->Target->GetMakefile();
- const std::vector<std::string> suffixes =
- GetConfigurationSuffixes(makefile);
- // Get build directory
- const std::string autogenBuildDir = GetAutogenTargetBuildDir(target);
- // Register all compilation files as generated
- for (std::vector<std::string>::const_iterator it = suffixes.begin();
- it != suffixes.end(); ++it) {
- std::string mcFile = autogenBuildDir + "/mocs_compilation";
- mcFile += *it;
- mcFile += ".cpp";
- AddGeneratedSource(makefile, mcFile, cmQtAutoGeneratorCommon::MOC);
- }
- // Mocs compilation file
- if (IsMultiConfig(target->GetGlobalGenerator())) {
- target->AddSource(autogenBuildDir + "/mocs_compilation_$<CONFIG>.cpp");
- } else {
- target->AddSource(autogenBuildDir + "/mocs_compilation.cpp");
- }
- }
-}
-
-void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
- cmLocalGenerator* lg, cmGeneratorTarget* target)
-{
- cmMakefile* makefile = target->Target->GetMakefile();
-
- // Create a custom target for running generators at buildtime
- const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC");
- const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC");
- const bool rccEnabled = target->GetPropertyAsBool("AUTORCC");
- const bool multiConfig = IsMultiConfig(target->GetGlobalGenerator());
- const std::string autogenTargetName = GetAutogenTargetName(target);
- const std::string autogenBuildDir = GetAutogenTargetBuildDir(target);
- const std::string workingDirectory =
- cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory());
- const std::string qtMajorVersion = GetQtMajorVersion(target);
- const std::string rccCommand = RccGetExecutable(target, qtMajorVersion);
- const std::vector<std::string> suffixes = GetConfigurationSuffixes(makefile);
- std::vector<std::string> autogenDependFiles;
- std::vector<std::string> autogenDependTargets;
- std::vector<std::string> autogenProvides;
-
- // Remove build directories on cleanup
- makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
- autogenBuildDir.c_str(), false);
-
- // Remove old settings on cleanup
- {
- std::string base = GetAutogenTargetFilesDir(target);
- for (std::vector<std::string>::const_iterator it = suffixes.begin();
- it != suffixes.end(); ++it) {
- std::string fname = base + "/AutogenOldSettings" + *it + ".cmake";
- makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", fname.c_str(),
- false);
- }
- }
-
- // Compose command lines
- cmCustomCommandLines commandLines;
- {
- cmCustomCommandLine currentLine;
- currentLine.push_back(cmSystemTools::GetCMakeCommand());
- currentLine.push_back("-E");
- currentLine.push_back("cmake_autogen");
- currentLine.push_back(GetAutogenTargetFilesDir(target));
- currentLine.push_back("$<CONFIGURATION>");
- commandLines.push_back(currentLine);
- }
-
- // Compose target comment
- std::string autogenComment;
- {
- std::vector<std::string> toolNames;
- if (mocEnabled) {
- toolNames.push_back("MOC");
- }
- if (uicEnabled) {
- toolNames.push_back("UIC");
- }
- if (rccEnabled) {
- toolNames.push_back("RCC");
- }
-
- std::string tools = toolNames[0];
- toolNames.erase(toolNames.begin());
- while (toolNames.size() > 1) {
- tools += ", " + toolNames[0];
- toolNames.erase(toolNames.begin());
- }
- if (toolNames.size() == 1) {
- tools += " and " + toolNames[0];
- }
- autogenComment = "Automatic " + tools + " for target " + target->GetName();
- }
-
- // Add moc compilation to generated files list
- if (mocEnabled) {
- for (std::vector<std::string>::const_iterator it = suffixes.begin();
- it != suffixes.end(); ++it) {
- std::string mcFile = autogenBuildDir + "/mocs_compilation";
- mcFile += *it;
- mcFile += ".cpp";
- autogenProvides.push_back(mcFile);
- }
- }
-
- // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES
- if (mocEnabled || uicEnabled) {
- if (multiConfig) {
- target->AddIncludeDirectory(autogenBuildDir + "/include_$<CONFIG>",
- true);
-
- } else {
- target->AddIncludeDirectory(autogenBuildDir + "/include", true);
- }
- }
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- bool usePRE_BUILD = false;
- cmGlobalGenerator* gg = lg->GetGlobalGenerator();
- if (gg->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;
- }
-#endif
-
- // Initialize autogen target dependencies
- if (const char* extraDeps = target->GetProperty("AUTOGEN_TARGET_DEPENDS")) {
- std::vector<std::string> deps;
- cmSystemTools::ExpandListArgument(extraDeps, deps);
- for (std::vector<std::string>::const_iterator itC = deps.begin(),
- itE = deps.end();
- itC != itE; ++itC) {
- if (makefile->FindTargetToUse(*itC) != CM_NULLPTR) {
- autogenDependTargets.push_back(*itC);
- } else {
- autogenDependFiles.push_back(*itC);
- }
- }
- }
- {
- cmFilePathChecksum fpathCheckSum(makefile);
- // Iterate over all source files
- std::vector<cmSourceFile*> srcFiles;
- target->GetConfigCommonSourceFiles(srcFiles);
- for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
- fileIt != srcFiles.end(); ++fileIt) {
- cmSourceFile* sf = *fileIt;
- if (!PropertyEnabled(sf, "SKIP_AUTOGEN")) {
- std::string const& ext = sf->GetExtension();
- // Add generated file that will be scanned by moc or uic to
- // the dependencies
- if (mocEnabled || uicEnabled) {
- const cmSystemTools::FileFormat fileType =
- cmSystemTools::GetFileFormat(ext.c_str());
- if ((fileType == cmSystemTools::CXX_FILE_FORMAT) ||
- (fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
- if (PropertyEnabled(sf, "GENERATED")) {
- if ((mocEnabled && !PropertyEnabled(sf, "SKIP_AUTOMOC")) ||
- (uicEnabled && !PropertyEnabled(sf, "SKIP_AUTOUIC"))) {
- autogenDependFiles.push_back(
- cmsys::SystemTools::GetRealPath(sf->GetFullPath()));
-#if defined(_WIN32) && !defined(__CYGWIN__)
- // Cannot use PRE_BUILD with generated files
- usePRE_BUILD = false;
-#endif
- }
- }
- }
- }
- // Process rcc enabled files
- if (rccEnabled && (ext == "qrc") &&
- !PropertyEnabled(sf, "SKIP_AUTORCC")) {
- const std::string absFile =
- cmsys::SystemTools::GetRealPath(sf->GetFullPath());
-
- // Compose rcc output file name
- {
- std::string rccOutBase = autogenBuildDir + "/";
- rccOutBase += fpathCheckSum.getPart(absFile);
- rccOutBase += "/qrc_";
- rccOutBase +=
- cmsys::SystemTools::GetFilenameWithoutLastExtension(absFile);
-
- // Register rcc ouput file as generated
- for (std::vector<std::string>::const_iterator it =
- suffixes.begin();
- it != suffixes.end(); ++it) {
- std::string rccOutCfg = rccOutBase;
- rccOutCfg += *it;
- rccOutCfg += ".cpp";
- AddGeneratedSource(makefile, rccOutCfg,
- cmQtAutoGeneratorCommon::RCC);
- autogenProvides.push_back(rccOutCfg);
- }
- // Add rcc output file to origin target sources
- if (multiConfig) {
- target->AddSource(rccOutBase + "_$<CONFIG>.cpp");
- } else {
- target->AddSource(rccOutBase + ".cpp");
- }
- }
-
- if (PropertyEnabled(sf, "GENERATED")) {
- // Add generated qrc file to the dependencies
- autogenDependFiles.push_back(absFile);
- } else {
- // Run cmake again when .qrc file changes
- makefile->AddCMakeDependFile(absFile);
-
- // Add the qrc input files to the dependencies
- std::string error;
- if (!cmQtAutoGeneratorCommon::RccListInputs(
- qtMajorVersion, rccCommand, absFile, autogenDependFiles,
- &error)) {
- cmSystemTools::Error(error.c_str());
- }
- }
-#if defined(_WIN32) && !defined(__CYGWIN__)
- // Cannot use PRE_BUILD because the resource files themselves
- // may not be sources within the target so VS may not know the
- // target needs to re-build at all.
- usePRE_BUILD = false;
-#endif
- }
- }
- }
- }
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (usePRE_BUILD) {
- // We can't use pre-build if we depend on additional files
- if (!autogenDependFiles.empty()) {
- usePRE_BUILD = false;
- }
- }
- if (usePRE_BUILD) {
- // 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.
- std::vector<std::string> no_output;
- std::vector<std::string> no_depends;
- cmCustomCommand cc(makefile, no_output, autogenProvides, no_depends,
- commandLines, autogenComment.c_str(),
- workingDirectory.c_str());
- cc.SetEscapeOldStyle(false);
- cc.SetEscapeAllowMakeVars(true);
- target->Target->AddPreBuildCommand(cc);
-
- // Add additional target dependencies to the origin target
- for (std::vector<std::string>::const_iterator
- itC = autogenDependTargets.begin(),
- itE = autogenDependTargets.end();
- itC != itE; ++itC) {
- target->Target->AddUtility(*itC);
- }
- } else
-#endif
- {
- cmTarget* autogenTarget = makefile->AddUtilityCommand(
- autogenTargetName, true, workingDirectory.c_str(),
- /*byproducts=*/autogenProvides, autogenDependFiles, commandLines, false,
- autogenComment.c_str());
-
- cmGeneratorTarget* gt = new cmGeneratorTarget(autogenTarget, lg);
- lg->AddGeneratorTarget(gt);
-
- // Add origin link library targets to the autogen target dependencies
- {
- const cmTarget::LinkLibraryVectorType& libVec =
- target->Target->GetOriginalLinkLibraries();
- for (cmTarget::LinkLibraryVectorType::const_iterator
- itC = libVec.begin(),
- itE = libVec.end();
- itC != itE; ++itC) {
- const std::string& libName = itC->first;
- if (makefile->FindTargetToUse(libName) != CM_NULLPTR) {
- autogenDependTargets.push_back(libName);
- }
- }
- }
- // Add origin utility targets to the autogen target dependencies
- {
- const std::set<std::string>& utils = target->Target->GetUtilities();
- for (std::set<std::string>::const_iterator itC = utils.begin(),
- itE = utils.end();
- itC != itE; ++itC) {
- autogenDependTargets.push_back(*itC);
- }
- }
- // Add additional target dependencies to the autogen target
- for (std::vector<std::string>::const_iterator
- itC = autogenDependTargets.begin(),
- itE = autogenDependTargets.end();
- itC != itE; ++itC) {
- autogenTarget->AddUtility(*itC);
- }
-
- // Set target folder
- const char* autogenFolder =
- makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
- if (!autogenFolder) {
- autogenFolder =
- makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
- }
- if (autogenFolder && *autogenFolder) {
- autogenTarget->SetProperty("FOLDER", autogenFolder);
- } else {
- // inherit FOLDER property from target (#13688)
- utilCopyTargetProperty(gt->Target, target->Target, "FOLDER");
- }
-
- target->Target->AddUtility(autogenTargetName);
- }
-}
-
-void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
- cmGeneratorTarget const* target)
-{
- cmMakefile* makefile = target->Target->GetMakefile();
-
- // forget the variables added here afterwards again:
- cmMakefile::ScopePushPop varScope(makefile);
- static_cast<void>(varScope);
-
- // Get configurations
- std::string config;
- const std::vector<std::string> configs(GetConfigurations(makefile, &config));
-
- // Configurations settings buffers
- std::map<std::string, std::string> configSuffix;
- std::map<std::string, std::string> configMocIncludes;
- std::map<std::string, std::string> configMocDefines;
- std::map<std::string, std::string> configUicOptions;
-
- // Configuration suffix
- if (IsMultiConfig(target->GetGlobalGenerator())) {
- for (std::vector<std::string>::const_iterator it = configs.begin();
- it != configs.end(); ++it) {
- configSuffix[*it] = "_" + *it;
- }
- }
-
- // Basic setup
- {
- const bool mocEnabled = target->GetPropertyAsBool("AUTOMOC");
- const bool uicEnabled = target->GetPropertyAsBool("AUTOUIC");
- const bool rccEnabled = target->GetPropertyAsBool("AUTORCC");
- const std::string autogenTargetName = GetAutogenTargetName(target);
- const std::string qtMajorVersion = GetQtMajorVersion(target);
-
- std::vector<std::string> sources;
- std::vector<std::string> headers;
-
- if (mocEnabled || uicEnabled || rccEnabled) {
- std::vector<std::string> mocSkipList;
- std::vector<std::string> uicSkipList;
- AcquireScanFiles(target, sources, headers, mocSkipList, uicSkipList);
- if (mocEnabled) {
- MocSetupAutoTarget(target, autogenTargetName, qtMajorVersion, config,
- configs, mocSkipList, configMocIncludes,
- configMocDefines);
- }
- if (uicEnabled) {
- UicSetupAutoTarget(target, qtMajorVersion, config, configs,
- uicSkipList, configUicOptions);
- }
- if (rccEnabled) {
- RccSetupAutoTarget(target, qtMajorVersion);
- }
- }
-
- AddDefinitionEscaped(makefile, "_autogen_build_dir",
- GetAutogenTargetBuildDir(target));
- AddDefinitionEscaped(makefile, "_qt_version_major", qtMajorVersion);
- AddDefinitionEscaped(makefile, "_sources", sources);
- AddDefinitionEscaped(makefile, "_headers", headers);
- }
-
- // Generate info file
- std::string infoFile = GetAutogenTargetFilesDir(target);
- infoFile += "/AutogenInfo.cmake";
- {
- std::string inf = cmSystemTools::GetCMakeRoot();
- inf += "/Modules/AutogenInfo.cmake.in";
- makefile->ConfigureFile(inf.c_str(), infoFile.c_str(), false, true, false);
- }
-
- // Append custom definitions to info file on demand
- if (!configSuffix.empty() || !configMocDefines.empty() ||
- !configMocIncludes.empty() || !configUicOptions.empty()) {
-
- // 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) {
- ofs << "# Configuration specific options\n";
- for (std::map<std::string, std::string>::iterator
- it = configSuffix.begin(),
- end = configSuffix.end();
- it != end; ++it) {
- ofs << "set(AM_CONFIG_SUFFIX_" << it->first << " " << it->second
- << ")\n";
- }
- for (std::map<std::string, std::string>::iterator
- it = configMocDefines.begin(),
- end = configMocDefines.end();
- it != end; ++it) {
- ofs << "set(AM_MOC_DEFINITIONS_" << it->first << " " << it->second
- << ")\n";
- }
- for (std::map<std::string, std::string>::iterator
- it = configMocIncludes.begin(),
- end = configMocIncludes.end();
- it != end; ++it) {
- ofs << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second
- << ")\n";
- }
- for (std::map<std::string, std::string>::iterator
- it = configUicOptions.begin(),
- end = configUicOptions.end();
- it != end; ++it) {
- ofs << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " " << it->second
- << ")\n";
- }
- } else {
- // File open error
- std::string error = "Internal CMake error when trying to open file: ";
- error += cmQtAutoGeneratorCommon::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 ca806f5a9..000000000
--- a/Source/cmQtAutoGeneratorInitializer.h
+++ /dev/null
@@ -1,20 +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
-
-class cmGeneratorTarget;
-class cmLocalGenerator;
-
-class cmQtAutoGeneratorInitializer
-{
-public:
- static void InitializeAutogenSources(cmGeneratorTarget* target);
- static void InitializeAutogenTarget(cmLocalGenerator* lg,
- cmGeneratorTarget* target);
- static void SetupAutoGenerateTarget(cmGeneratorTarget const* target);
-};
-
-#endif
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
deleted file mode 100644
index d12d96dcb..000000000
--- a/Source/cmQtAutoGenerators.cxx
+++ /dev/null
@@ -1,2066 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmQtAutoGenerators.h"
-#include "cmQtAutoGeneratorCommon.h"
-
-#include "cmConfigure.h"
-#include "cmsys/FStream.hxx"
-#include "cmsys/Terminal.h"
-#include <algorithm>
-#include <assert.h>
-#include <list>
-#include <sstream>
-#include <stdlib.h>
-#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 "cm_auto_ptr.hxx"
-#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
-
-inline static std::string Quoted(const std::string& text)
-{
- return cmQtAutoGeneratorCommon::Quoted(text);
-}
-
-static std::string QuotedCommand(const std::vector<std::string>& command)
-{
- std::string res;
- for (std::vector<std::string>::const_iterator cit = command.begin();
- cit != command.end(); ++cit) {
- if (!res.empty()) {
- res.push_back(' ');
- }
- const std::string cesc = Quoted(*cit);
- if (cit->empty() || (cesc.size() > (cit->size() + 2)) ||
- (cesc.find(' ') != std::string::npos)) {
- res += cesc;
- } else {
- res += *cit;
- }
- }
- return res;
-}
-
-static void InfoGet(cmMakefile* makefile, const char* key, std::string& value)
-{
- value = makefile->GetSafeDefinition(key);
-}
-
-static void InfoGet(cmMakefile* makefile, const char* key, bool& value)
-{
- value = makefile->IsOn(key);
-}
-
-static void InfoGet(cmMakefile* makefile, const char* key,
- std::vector<std::string>& list)
-{
- cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list);
-}
-
-static void InfoGetConfig(cmMakefile* makefile, const char* key,
- const std::string& config, std::string& value)
-{
- const char* valueConf = CM_NULLPTR;
- {
- std::string keyConf = key;
- if (!config.empty()) {
- keyConf += "_";
- keyConf += config;
- }
- valueConf = makefile->GetDefinition(keyConf);
- }
- if (valueConf == CM_NULLPTR) {
- valueConf = makefile->GetSafeDefinition(key);
- }
- value = valueConf;
-}
-
-static void InfoGetConfig(cmMakefile* makefile, const char* key,
- const std::string& config,
- std::vector<std::string>& list)
-{
- std::string value;
- InfoGetConfig(makefile, key, config, value);
- cmSystemTools::ExpandListArgument(value, list);
-}
-
-inline static bool SettingsMatch(cmMakefile* makefile, const char* key,
- const std::string& value)
-{
- return (value == makefile->GetSafeDefinition(key));
-}
-
-static void SettingAppend(std::string& str, const char* key,
- const std::string& value)
-{
- if (!value.empty()) {
- str += "set(";
- str += key;
- str += " ";
- str += cmOutputConverter::EscapeForCMake(value);
- str += ")\n";
- }
-}
-
-static std::string SubDirPrefix(const std::string& fileName)
-{
- std::string res(cmsys::SystemTools::GetFilenamePath(fileName));
- if (!res.empty()) {
- res += '/';
- }
- return res;
-}
-
-static bool FileNameIsUnique(const std::string& filePath,
- const std::map<std::string, std::string>& fileMap)
-{
- size_t count(0);
- const std::string fileName = cmsys::SystemTools::GetFilenameName(filePath);
- for (std::map<std::string, std::string>::const_iterator si = fileMap.begin();
- si != fileMap.end(); ++si) {
- if (cmsys::SystemTools::GetFilenameName(si->first) == fileName) {
- ++count;
- if (count > 1) {
- return false;
- }
- }
- }
- return true;
-}
-
-static bool ReadAll(std::string& content, const std::string& filename)
-{
- bool success = false;
- {
- cmsys::ifstream ifs(filename.c_str());
- if (ifs) {
- std::ostringstream osst;
- osst << ifs.rdbuf();
- content = osst.str();
- success = true;
- }
- }
- return success;
-}
-
-/**
- * @brief Tests if buildFile doesn't exist or is older than sourceFile
- * @return True if buildFile doesn't exist or is older than sourceFile
- */
-static bool FileAbsentOrOlder(const std::string& buildFile,
- const std::string& sourceFile)
-{
- int result = 0;
- bool success =
- cmsys::SystemTools::FileTimeCompare(buildFile, sourceFile, &result);
- return (!success || (result <= 0));
-}
-
-static bool ListContains(const std::vector<std::string>& list,
- const std::string& entry)
-{
- return (std::find(list.begin(), list.end(), entry) != list.end());
-}
-
-static std::string JoinOptionsList(const std::vector<std::string>& opts)
-{
- return cmOutputConverter::EscapeForCMake(cmJoin(opts, ";"));
-}
-
-static std::string JoinOptionsMap(
- const std::map<std::string, std::string>& opts)
-{
- std::string result;
- for (std::map<std::string, std::string>::const_iterator it = opts.begin();
- it != opts.end(); ++it) {
- if (it != opts.begin()) {
- result += cmQtAutoGeneratorCommon::listSep;
- }
- result += it->first;
- result += "===";
- result += it->second;
- }
- return result;
-}
-
-static std::string JoinExts(const std::vector<std::string>& lst)
-{
- std::string result;
- if (!lst.empty()) {
- const std::string separator = ",";
- for (std::vector<std::string>::const_iterator it = lst.begin();
- it != lst.end(); ++it) {
- if (it != lst.begin()) {
- result += separator;
- }
- result += '.';
- result += *it;
- }
- }
- return result;
-}
-
-static void UicMergeOptions(std::vector<std::string>& opts,
- const std::vector<std::string>& fileOpts,
- bool isQt5)
-{
- static const char* valueOptions[] = { "tr", "translate",
- "postfix", "generator",
- "include", // Since Qt 5.3
- "g" };
- std::vector<std::string> extraOpts;
- for (std::vector<std::string>::const_iterator it = fileOpts.begin();
- it != fileOpts.end(); ++it) {
- std::vector<std::string>::iterator existingIt =
- std::find(opts.begin(), opts.end(), *it);
- if (existingIt != opts.end()) {
- const char* o = it->c_str();
- if (*o == '-') {
- ++o;
- }
- if (isQt5 && *o == '-') {
- ++o;
- }
- if (std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions),
- cmStrCmp(*it)) != cmArrayEnd(valueOptions)) {
- assert(existingIt + 1 != opts.end());
- *(existingIt + 1) = *(it + 1);
- ++it;
- }
- } else {
- extraOpts.push_back(*it);
- }
- }
- opts.insert(opts.end(), extraOpts.begin(), extraOpts.end());
-}
-
-// -- Class methods
-
-cmQtAutoGenerators::cmQtAutoGenerators()
- : Verbose(cmsys::SystemTools::HasEnv("VERBOSE"))
- , ColorOutput(true)
- , MocSettingsChanged(false)
- , MocPredefsChanged(false)
- , MocRunFailed(false)
- , UicSettingsChanged(false)
- , UicRunFailed(false)
- , RccSettingsChanged(false)
- , RccRunFailed(false)
-{
-
- std::string colorEnv;
- cmsys::SystemTools::GetEnv("COLOR", colorEnv);
- if (!colorEnv.empty()) {
- if (cmSystemTools::IsOn(colorEnv.c_str())) {
- this->ColorOutput = true;
- } else {
- this->ColorOutput = false;
- }
- }
-
- // Moc macro filters
- this->MocMacroFilters[0].first = "Q_OBJECT";
- this->MocMacroFilters[0].second.compile("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]");
- this->MocMacroFilters[1].first = "Q_GADGET";
- this->MocMacroFilters[1].second.compile("[\n][ \t]*Q_GADGET[^a-zA-Z0-9_]");
-
- // 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(const std::string& targetDirectory,
- const std::string& 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);
-
- CM_AUTO_PTR<cmMakefile> mf(new cmMakefile(&gg, snapshot));
- gg.SetCurrentMakefile(mf.get());
-
- bool success = false;
- if (this->ReadAutogenInfoFile(mf.get(), targetDirectory, config)) {
- // Read old settings
- this->SettingsFileRead(mf.get());
- // Init and run
- this->Init(mf.get());
- if (this->RunAutogen()) {
- // Write current settings
- if (this->SettingsFileWrite()) {
- success = true;
- }
- }
- }
- return success;
-}
-
-bool cmQtAutoGenerators::MocDependFilterPush(const std::string& key,
- const std::string& regExp)
-{
- bool success = false;
- if (!key.empty()) {
- if (!regExp.empty()) {
- MocDependFilter filter;
- filter.key = key;
- if (filter.regExp.compile(regExp)) {
- this->MocDependFilters.push_back(filter);
- success = true;
- } else {
- this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Compiling "
- "regular expression failed.\nKey: " +
- Quoted(key) + "\nExp.: " + Quoted(regExp));
- }
- } else {
- this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Regular "
- "expression is empty");
- }
- } else {
- this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Key is empty");
- }
- return success;
-}
-
-bool cmQtAutoGenerators::ReadAutogenInfoFile(
- cmMakefile* makefile, const std::string& targetDirectory,
- const std::string& config)
-{
- std::string filename(cmSystemTools::CollapseFullPath(targetDirectory));
- cmSystemTools::ConvertToUnixSlashes(filename);
- filename += "/AutogenInfo.cmake";
-
- if (!makefile->ReadListFile(filename.c_str())) {
- this->LogError("AutoGen: Error processing file: " + filename);
- return false;
- }
-
- // - Old settings file
- {
- this->SettingsFile = cmSystemTools::CollapseFullPath(targetDirectory);
- cmSystemTools::ConvertToUnixSlashes(this->SettingsFile);
- this->SettingsFile += "/AutogenOldSettings";
- this->SettingsFile += this->ConfigSuffix;
- this->SettingsFile += ".cmake";
- }
-
- // -- Meta
- InfoGetConfig(makefile, "AM_CONFIG_SUFFIX", config, this->ConfigSuffix);
-
- // - Files and directories
- InfoGet(makefile, "AM_CMAKE_SOURCE_DIR", this->ProjectSourceDir);
- InfoGet(makefile, "AM_CMAKE_BINARY_DIR", this->ProjectBinaryDir);
- InfoGet(makefile, "AM_CMAKE_CURRENT_SOURCE_DIR", this->CurrentSourceDir);
- InfoGet(makefile, "AM_CMAKE_CURRENT_BINARY_DIR", this->CurrentBinaryDir);
- InfoGet(makefile, "AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE",
- this->IncludeProjectDirsBefore);
- InfoGet(makefile, "AM_BUILD_DIR", this->AutogenBuildDir);
- if (this->AutogenBuildDir.empty()) {
- this->LogError("AutoGen: Error: Missing autogen build directory ");
- return false;
- }
- InfoGet(makefile, "AM_SOURCES", this->Sources);
- InfoGet(makefile, "AM_HEADERS", this->Headers);
-
- // - Qt environment
- InfoGet(makefile, "AM_QT_VERSION_MAJOR", this->QtMajorVersion);
- if (this->QtMajorVersion.empty()) {
- InfoGet(makefile, "AM_Qt5Core_VERSION_MAJOR", this->QtMajorVersion);
- }
- InfoGet(makefile, "AM_QT_MOC_EXECUTABLE", this->MocExecutable);
- InfoGet(makefile, "AM_QT_UIC_EXECUTABLE", this->UicExecutable);
- InfoGet(makefile, "AM_QT_RCC_EXECUTABLE", this->RccExecutable);
-
- InfoGet(makefile, "AM_MOC_PREDEFS_CMD", this->MocPredefsCmd);
- // Check Qt version
- if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) {
- this->LogError("AutoGen: Error: Unsupported Qt version: " +
- Quoted(this->QtMajorVersion));
- return false;
- }
-
- // - Moc
- if (this->MocEnabled()) {
- InfoGet(makefile, "AM_MOC_SKIP", this->MocSkipList);
- InfoGetConfig(makefile, "AM_MOC_DEFINITIONS", config,
- this->MocDefinitions);
-#ifdef _WIN32
- {
- const std::string win32("WIN32");
- if (!ListContains(this->MocDefinitions, win32)) {
- this->MocDefinitions.push_back(win32);
- }
- }
-#endif
- InfoGetConfig(makefile, "AM_MOC_INCLUDES", config, this->MocIncludePaths);
- InfoGet(makefile, "AM_MOC_OPTIONS", this->MocOptions);
- InfoGet(makefile, "AM_MOC_RELAXED_MODE", this->MocRelaxedMode);
- {
- std::vector<std::string> mocDependFilters;
- InfoGet(makefile, "AM_MOC_DEPEND_FILTERS", mocDependFilters);
- // 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();
- dit != mocDependFilters.end(); dit += 2) {
- if (!this->MocDependFilterPush(*dit, *(dit + 1))) {
- return false;
- }
- }
- } else {
- this->LogError(
- "AutoMoc: Error: AUTOMOC_DEPEND_FILTERS list size is not "
- "a multiple of 2 in:\n" +
- Quoted(filename));
- return false;
- }
- }
- }
-
- // - Uic
- if (this->UicEnabled()) {
- InfoGet(makefile, "AM_UIC_SKIP", this->UicSkipList);
- InfoGet(makefile, "AM_UIC_SEARCH_PATHS", this->UicSearchPaths);
- InfoGetConfig(makefile, "AM_UIC_TARGET_OPTIONS", config,
- this->UicTargetOptions);
- {
- std::vector<std::string> uicFilesVec;
- std::vector<std::string> uicOptionsVec;
- InfoGet(makefile, "AM_UIC_OPTIONS_FILES", uicFilesVec);
- InfoGet(makefile, "AM_UIC_OPTIONS_OPTIONS", uicOptionsVec);
- // Compare list sizes
- if (uicFilesVec.size() == uicOptionsVec.size()) {
- for (std::vector<std::string>::iterator
- fileIt = uicFilesVec.begin(),
- optionIt = uicOptionsVec.begin();
- fileIt != uicFilesVec.end(); ++fileIt, ++optionIt) {
- cmSystemTools::ReplaceString(*optionIt,
- cmQtAutoGeneratorCommon::listSep, ";");
- this->UicOptions[*fileIt] = *optionIt;
- }
- } else {
- this->LogError(
- "AutoGen: Error: Uic files/options lists size missmatch in:\n" +
- Quoted(filename));
- return false;
- }
- }
- }
-
- // - Rcc
- if (this->RccEnabled()) {
- InfoGet(makefile, "AM_RCC_SOURCES", this->RccSources);
- // File options
- {
- std::vector<std::string> rccFilesVec;
- std::vector<std::string> rccOptionsVec;
- InfoGet(makefile, "AM_RCC_OPTIONS_FILES", rccFilesVec);
- InfoGet(makefile, "AM_RCC_OPTIONS_OPTIONS", rccOptionsVec);
- if (rccFilesVec.size() == rccOptionsVec.size()) {
- for (std::vector<std::string>::iterator
- fileIt = rccFilesVec.begin(),
- optionIt = rccOptionsVec.begin();
- fileIt != rccFilesVec.end(); ++fileIt, ++optionIt) {
- // Replace item separator
- cmSystemTools::ReplaceString(*optionIt,
- cmQtAutoGeneratorCommon::listSep, ";");
- this->RccOptions[*fileIt] = *optionIt;
- }
- } else {
- this->LogError(
- "AutoGen: Error: RCC files/options lists size missmatch in:\n" +
- Quoted(filename));
- return false;
- }
- }
- // File lists
- {
- std::vector<std::string> rccInputLists;
- InfoGet(makefile, "AM_RCC_INPUTS", rccInputLists);
- if (this->RccSources.size() == rccInputLists.size()) {
- for (std::vector<std::string>::iterator
- fileIt = this->RccSources.begin(),
- inputIt = rccInputLists.begin();
- fileIt != this->RccSources.end(); ++fileIt, ++inputIt) {
- // Remove braces
- *inputIt = inputIt->substr(1, inputIt->size() - 2);
- // Replace item separator
- cmSystemTools::ReplaceString(*inputIt,
- cmQtAutoGeneratorCommon::listSep, ";");
- std::vector<std::string> rccInputFiles;
- cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles);
- this->RccInputs[*fileIt] = rccInputFiles;
- }
- } else {
- this->LogError(
- "AutoGen: Error: RCC sources/inputs lists size missmatch in:\n" +
- Quoted(filename));
- return false;
- }
- }
- }
-
- return true;
-}
-
-void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
-{
- // Compose current settings strings
- {
- cmCryptoHash crypt(cmCryptoHash::AlgoSHA256);
- const std::string sep(" ~~~ ");
- if (this->MocEnabled()) {
- std::string str;
- str += this->MocExecutable;
- str += sep;
- str += JoinOptionsList(this->MocDefinitions);
- str += sep;
- str += JoinOptionsList(this->MocIncludePaths);
- str += sep;
- str += JoinOptionsList(this->MocOptions);
- str += sep;
- str += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE";
- str += sep;
- str += JoinOptionsList(this->MocPredefsCmd);
- str += sep;
- this->SettingsStringMoc = crypt.HashString(str);
- }
- if (this->UicEnabled()) {
- std::string str;
- str += this->UicExecutable;
- str += sep;
- str += JoinOptionsList(this->UicTargetOptions);
- str += sep;
- str += JoinOptionsMap(this->UicOptions);
- str += sep;
- this->SettingsStringUic = crypt.HashString(str);
- }
- if (this->RccEnabled()) {
- std::string str;
- str += this->RccExecutable;
- str += sep;
- str += JoinOptionsMap(this->RccOptions);
- str += sep;
- this->SettingsStringRcc = crypt.HashString(str);
- }
- }
-
- // Read old settings
- if (makefile->ReadListFile(this->SettingsFile.c_str())) {
- if (!SettingsMatch(makefile, SettingsKeyMoc, this->SettingsStringMoc)) {
- this->MocSettingsChanged = true;
- }
- if (!SettingsMatch(makefile, SettingsKeyUic, this->SettingsStringUic)) {
- this->UicSettingsChanged = true;
- }
- if (!SettingsMatch(makefile, 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->AnySettingsChanged()) {
- 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->AnySettingsChanged()) {
- if (this->Verbose) {
- this->LogInfo("AutoGen: Writing settings file " +
- Quoted(this->SettingsFile));
- }
- // Compose settings file content
- std::string settings;
- SettingAppend(settings, SettingsKeyMoc, this->SettingsStringMoc);
- SettingAppend(settings, SettingsKeyUic, this->SettingsStringUic);
- SettingAppend(settings, SettingsKeyRcc, this->SettingsStringRcc);
- // Write settings file
- if (!this->FileWrite("AutoGen", this->SettingsFile, settings)) {
- this->LogError("AutoGen: Error: Could not write old settings file " +
- Quoted(this->SettingsFile));
- // Remove old settings file to trigger a full rebuild on the next run
- cmSystemTools::RemoveFile(this->SettingsFile);
- success = false;
- }
- }
- return success;
-}
-
-void cmQtAutoGenerators::Init(cmMakefile* makefile)
-{
- // Mocs compilation file
- this->MocCompFileRel = "mocs_compilation";
- this->MocCompFileRel += this->ConfigSuffix;
- this->MocCompFileRel += ".cpp";
- this->MocCompFileAbs = cmSystemTools::CollapseCombinedPath(
- this->AutogenBuildDir, this->MocCompFileRel);
-
- // Mocs include directory
- this->AutogenIncludeDir = "include";
- this->AutogenIncludeDir += this->ConfigSuffix;
- this->AutogenIncludeDir += "/";
-
- // Moc predefs file
- if (!this->MocPredefsCmd.empty()) {
- this->MocPredefsFileRel = "moc_predefs.h";
- this->MocPredefsFileAbs = cmSystemTools::CollapseCombinedPath(
- this->AutogenBuildDir, this->MocPredefsFileRel);
- }
-
- // Init file path checksum generator
- FPathChecksum.setupParentDirs(this->CurrentSourceDir, this->CurrentBinaryDir,
- this->ProjectSourceDir,
- this->ProjectBinaryDir);
-
- // Acquire header extensions
- this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions();
-
- // 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
- {
- const char* movePaths[2] = { this->ProjectBinaryDir.c_str(),
- this->ProjectSourceDir.c_str() };
- for (const char* const* mpit = cmArrayBegin(movePaths);
- mpit != cmArrayEnd(movePaths); ++mpit) {
- std::list<std::string>::iterator it = includes.begin();
- while (it != includes.end()) {
- const std::string& path = *it;
- if (cmsys::SystemTools::StringStartsWith(path, *mpit)) {
- 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::vector<std::string>::const_iterator it =
- this->MocIncludePaths.begin();
- it != this->MocIncludePaths.end(); ++it) {
- const std::string& path = *it;
- 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;
- cmsys::SystemTools::SplitPath(path, pathComponents);
- std::string frameworkPath = cmsys::SystemTools::JoinPath(
- pathComponents.begin(), pathComponents.end() - 2);
- frameworkPaths.insert(frameworkPath);
- }
- }
- // Append framework includes
- for (std::set<std::string>::const_iterator it = frameworkPaths.begin();
- it != frameworkPaths.end(); ++it) {
- this->MocIncludes.push_back("-F");
- this->MocIncludes.push_back(*it);
- }
- }
-}
-
-bool cmQtAutoGenerators::RunAutogen()
-{
- // 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_$<CONFIG>.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_$<CONFIG>.cpp file.
-
- // Create AUTOGEN include directory
- {
- const std::string incDirAbs = cmSystemTools::CollapseCombinedPath(
- this->AutogenBuildDir, this->AutogenIncludeDir);
- if (!cmsys::SystemTools::MakeDirectory(incDirAbs)) {
- this->LogError("AutoGen: Error: Could not create include directory " +
- Quoted(incDirAbs));
- return false;
- }
- }
-
- // key = moc source filepath, value = moc output filepath
- std::map<std::string, std::string> mocsIncluded;
- std::map<std::string, std::string> mocsNotIncluded;
- std::map<std::string, std::set<std::string> > mocDepends;
- std::map<std::string, std::vector<std::string> > uisIncluded;
- // collects all headers which may need to be mocced
- std::set<std::string> mocHeaderFiles;
- std::set<std::string> uicHeaderFiles;
-
- // Parse sources
- for (std::vector<std::string>::const_iterator it = this->Sources.begin();
- it != this->Sources.end(); ++it) {
- const std::string& absFilename = cmsys::SystemTools::GetRealPath(*it);
- // Parse source file for MOC/UIC
- if (!this->ParseSourceFile(absFilename, mocsIncluded, mocDepends,
- uisIncluded, this->MocRelaxedMode)) {
- return false;
- }
- // Find additional headers
- this->SearchHeadersForSourceFile(absFilename, mocHeaderFiles,
- uicHeaderFiles);
- }
-
- // Parse headers
- for (std::vector<std::string>::const_iterator it = this->Headers.begin();
- it != this->Headers.end(); ++it) {
- const std::string& headerName = cmsys::SystemTools::GetRealPath(*it);
- if (!this->MocSkip(headerName)) {
- mocHeaderFiles.insert(headerName);
- }
- if (!this->UicSkip(headerName)) {
- uicHeaderFiles.insert(headerName);
- }
- }
- if (!this->ParseHeaders(mocHeaderFiles, uicHeaderFiles, mocsIncluded,
- mocsNotIncluded, mocDepends, uisIncluded)) {
- return false;
- };
-
- // Generate files
- if (!this->MocGenerateAll(mocsIncluded, mocsNotIncluded, mocDepends)) {
- return false;
- }
- if (!this->UicGenerateAll(uisIncluded)) {
- return false;
- }
- if (!this->RccGenerateAll()) {
- return false;
- }
-
- return true;
-}
-
-/**
- * @brief Tests if the C++ content requires moc processing
- * @return True if moc is required
- */
-bool cmQtAutoGenerators::MocRequired(const std::string& contentText,
- std::string* macroName)
-{
- for (unsigned int ii = 0; ii != cmArraySize(this->MocMacroFilters); ++ii) {
- MocMacroFilter& filter = this->MocMacroFilters[ii];
- // Run a simple find string operation before the expensive
- // regular expression check
- if (contentText.find(filter.first) != std::string::npos) {
- if (filter.second.find(contentText)) {
- // Return macro name on demand
- if (macroName != CM_NULLPTR) {
- *macroName = filter.first;
- }
- return true;
- }
- }
- }
- return false;
-}
-
-void cmQtAutoGenerators::MocFindDepends(
- const std::string& absFilename, const std::string& contentText,
- std::map<std::string, std::set<std::string> >& mocDepends)
-{
- for (std::vector<MocDependFilter>::iterator fit =
- this->MocDependFilters.begin();
- fit != this->MocDependFilters.end(); ++fit) {
- MocDependFilter& filter = *fit;
- // Run a simple find string operation before the expensive
- // regular expression check
- if (contentText.find(filter.key) != std::string::npos) {
- // Run regular expression check loop
- const std::string sourcePath = SubDirPrefix(absFilename);
- const char* contentChars = contentText.c_str();
- while (filter.regExp.find(contentChars)) {
- // Evaluate match
- const std::string match = filter.regExp.match(1);
- if (!match.empty()) {
- // Find the dependency file
- std::string incFile;
- if (this->MocFindIncludedFile(incFile, sourcePath, match)) {
- mocDepends[absFilename].insert(incFile);
- if (this->Verbose) {
- this->LogInfo("AutoMoc: Found dependency:\n " +
- Quoted(absFilename) + "\n " + Quoted(incFile));
- }
- } else {
- this->LogWarning("AutoMoc: Warning: " + Quoted(absFilename) +
- "\n" + "Could not find dependency file " +
- Quoted(match));
- }
- }
- contentChars += filter.regExp.end();
- }
- }
- }
-}
-
-/**
- * @brief Tests if the file should be ignored for moc scanning
- * @return True if the file should be ignored
- */
-bool cmQtAutoGenerators::MocSkip(const std::string& 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 file name is in the skip list
- */
-bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) const
-{
- if (this->UicEnabled()) {
- // Test if the file name is on the skip list
- if (!ListContains(this->UicSkipList, absFilename)) {
- return false;
- }
- }
- return true;
-}
-
-/**
- * @return True on success
- */
-bool cmQtAutoGenerators::ParseSourceFile(
- const std::string& absFilename,
- std::map<std::string, std::string>& mocsIncluded,
- std::map<std::string, std::set<std::string> >& mocDepends,
- std::map<std::string, std::vector<std::string> >& uisIncluded, bool relaxed)
-{
- std::string contentText;
- bool success = ReadAll(contentText, absFilename);
- if (success) {
- if (!contentText.empty()) {
- // Parse source contents for MOC
- if (success && !this->MocSkip(absFilename)) {
- success = this->MocParseSourceContent(
- absFilename, contentText, mocsIncluded, mocDepends, relaxed);
- }
- // Parse source contents for UIC
- if (success && !this->UicSkip(absFilename)) {
- this->UicParseContent(absFilename, contentText, uisIncluded);
- }
- } else {
- std::ostringstream ost;
- ost << "AutoGen: Warning: The file is empty:\n"
- << Quoted(absFilename) << "\n";
- this->LogWarning(ost.str());
- }
- } else {
- std::ostringstream ost;
- ost << "AutoGen: Error: Could not read file:\n" << Quoted(absFilename);
- this->LogError(ost.str());
- }
- return success;
-}
-
-void cmQtAutoGenerators::UicParseContent(
- const std::string& absFilename, const std::string& contentText,
- std::map<std::string, std::vector<std::string> >& uisIncluded)
-{
- if (this->Verbose) {
- this->LogInfo("AutoUic: Checking " + absFilename);
- }
-
- const char* contentChars = contentText.c_str();
- if (strstr(contentChars, "ui_") != CM_NULLPTR) {
- while (this->UicRegExpInclude.find(contentChars)) {
- uisIncluded[absFilename].push_back(this->UicRegExpInclude.match(1));
- contentChars += this->UicRegExpInclude.end();
- }
- }
-}
-
-/**
- * @return True on success
- */
-bool cmQtAutoGenerators::MocParseSourceContent(
- const std::string& absFilename, const std::string& contentText,
- std::map<std::string, std::string>& mocsIncluded,
- std::map<std::string, std::set<std::string> >& mocDepends, bool relaxed)
-{
- if (this->Verbose) {
- this->LogInfo("AutoMoc: Checking " + absFilename);
- }
-
- const std::string scannedFileAbsPath = SubDirPrefix(absFilename);
- const std::string scannedFileBasename =
- cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
-
- std::string macroName;
- const bool requiresMoc = this->MocRequired(contentText, &macroName);
- bool ownDotMocIncluded = false;
- std::string ownMocUnderscoreInclude;
- std::string ownMocUnderscoreHeader;
-
- // first a simple string check for "moc" is *much* faster than the regexp,
- // and if the string search already fails, we don't have to try the
- // expensive regexp
- const char* contentChars = contentText.c_str();
- if (strstr(contentChars, "moc") != CM_NULLPTR) {
- // Iterate over all included moc files
- while (this->MocRegExpInclude.find(contentChars)) {
- const std::string incString = this->MocRegExpInclude.match(1);
- // Basename of the moc include
- const std::string incSubDir(SubDirPrefix(incString));
- const std::string incBasename =
- cmsys::SystemTools::GetFilenameWithoutLastExtension(incString);
-
- // If the moc include is of the moc_foo.cpp style we expect
- // the Q_OBJECT class declaration in a header file.
- // If the moc include is of the foo.moc style we need to look for
- // a Q_OBJECT macro in the current source file, if it contains the
- // macro we generate the moc file from the source file.
- if (cmHasLiteralPrefix(incBasename, "moc_")) {
- // Include: moc_FOO.cxx
- // Remove the moc_ part
- const std::string incRealBasename = incBasename.substr(4);
- const std::string headerToMoc =
- this->MocFindHeader(scannedFileAbsPath, incSubDir + incRealBasename);
- if (!headerToMoc.empty()) {
- if (!this->MocSkip(headerToMoc)) {
- // Register moc job
- mocsIncluded[headerToMoc] = incString;
- this->MocFindDepends(headerToMoc, contentText, mocDepends);
- // Store meta information for relaxed mode
- if (relaxed && (incRealBasename == scannedFileBasename)) {
- ownMocUnderscoreInclude = incString;
- ownMocUnderscoreHeader = headerToMoc;
- }
- }
- } else {
- std::ostringstream ost;
- ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
- << "The file includes the moc file " << Quoted(incString)
- << ", but could not find header "
- << Quoted(incRealBasename + "{" +
- JoinExts(this->HeaderExtensions) + "}");
- ;
- this->LogError(ost.str());
- return false;
- }
- } else {
- // Include: FOO.moc
- std::string fileToMoc;
- if (relaxed) {
- // Mode: Relaxed
- if (requiresMoc && (incBasename == scannedFileBasename)) {
- // Include self
- fileToMoc = absFilename;
- ownDotMocIncluded = true;
- } else {
- // In relaxed mode try to find a header instead but issue a warning
- const std::string headerToMoc =
- this->MocFindHeader(scannedFileAbsPath, incSubDir + incBasename);
- if (!headerToMoc.empty()) {
- if (!this->MocSkip(headerToMoc)) {
- // This is for KDE4 compatibility:
- fileToMoc = headerToMoc;
- if (!requiresMoc && (incBasename == scannedFileBasename)) {
- std::ostringstream ost;
- ost
- << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
- << "The file includes the moc file " << Quoted(incString)
- << ", but does not contain a Q_OBJECT or Q_GADGET macro.\n"
- << "Running moc on " << Quoted(headerToMoc) << "!\n"
- << "Include " << Quoted("moc_" + incBasename + ".cpp")
- << " for a compatibility with strict mode (see "
- "CMAKE_AUTOMOC_RELAXED_MODE).\n";
- this->LogWarning(ost.str());
- } else {
- std::ostringstream ost;
- ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
- << "The file includes the moc file " << Quoted(incString)
- << " instead of "
- << Quoted("moc_" + incBasename + ".cpp") << ".\n"
- << "Running moc on " << Quoted(headerToMoc) << "!\n"
- << "Include " << Quoted("moc_" + incBasename + ".cpp")
- << " for compatibility with strict mode (see "
- "CMAKE_AUTOMOC_RELAXED_MODE).\n";
- this->LogWarning(ost.str());
- }
- }
- } else {
- std::ostringstream ost;
- ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
- << "The file includes the moc file " << Quoted(incString)
- << ", which seems to be the moc file from a different "
- "source file. CMake also could not find a matching "
- "header.";
- this->LogError(ost.str());
- return false;
- }
- }
- } else {
- // Mode: Strict
- if (incBasename == scannedFileBasename) {
- // Include self
- fileToMoc = absFilename;
- ownDotMocIncluded = true;
- // Accept but issue a warning if moc isn't required
- if (!requiresMoc) {
- std::ostringstream ost;
- ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
- << "The file includes the moc file " << Quoted(incString)
- << ", but does not contain a Q_OBJECT or Q_GADGET "
- "macro.";
- this->LogWarning(ost.str());
- }
- } else {
- // Don't allow FOO.moc include other than self in strict mode
- std::ostringstream ost;
- ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
- << "The file includes the moc file " << Quoted(incString)
- << ", which seems to be the moc file from a different "
- "source file. This is not supported. Include "
- << Quoted(scannedFileBasename + ".moc")
- << " to run moc on this source file.";
- this->LogError(ost.str());
- return false;
- }
- }
- if (!fileToMoc.empty()) {
- mocsIncluded[fileToMoc] = incString;
- this->MocFindDepends(fileToMoc, contentText, mocDepends);
- }
- }
- // Forward content pointer
- contentChars += this->MocRegExpInclude.end();
- }
- }
-
- if (requiresMoc && !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 (relaxed && !ownMocUnderscoreInclude.empty()) {
- // This is for KDE4 compatibility:
- std::ostringstream ost;
- ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
- << "The file contains a " << macroName
- << " macro, but does not include "
- << Quoted(scannedFileBasename + ".moc") << ", but instead includes "
- << Quoted(ownMocUnderscoreInclude) << ".\n"
- << "Running moc on " << Quoted(absFilename) << "!\n"
- << "Better include " << Quoted(scannedFileBasename + ".moc")
- << " for compatibility with strict mode (see "
- "CMAKE_AUTOMOC_RELAXED_MODE).";
- this->LogWarning(ost.str());
-
- // Use scanned source file instead of scanned header file as moc source
- mocsIncluded[absFilename] = ownMocUnderscoreInclude;
- this->MocFindDepends(absFilename, contentText, mocDepends);
- // Remove
- mocsIncluded.erase(ownMocUnderscoreHeader);
- } else {
- // Otherwise always error out since it will not compile:
- std::ostringstream ost;
- ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
- << "The file contains a " << macroName
- << " macro, but does not include "
- << Quoted(scannedFileBasename + ".moc") << "!\n"
- << "Consider adding the include or enabling SKIP_AUTOMOC for this "
- "file.";
- this->LogError(ost.str());
- return false;
- }
- }
-
- return true;
-}
-
-void cmQtAutoGenerators::MocParseHeaderContent(
- const std::string& absFilename, const std::string& contentText,
- std::map<std::string, std::string>& mocsNotIncluded,
- std::map<std::string, std::set<std::string> >& mocDepends)
-{
- // Log
- if (this->Verbose) {
- this->LogInfo("AutoMoc: Checking " + absFilename);
- }
- if (this->MocRequired(contentText)) {
- // Register moc job
- mocsNotIncluded[absFilename] =
- this->ChecksumedPath(absFilename, "moc_", this->ConfigSuffix + ".cpp");
- this->MocFindDepends(absFilename, contentText, mocDepends);
- }
-}
-
-void cmQtAutoGenerators::SearchHeadersForSourceFile(
- const std::string& absFilename, std::set<std::string>& mocHeaderFiles,
- std::set<std::string>& uicHeaderFiles) const
-{
- std::string basepaths[2];
- {
- std::string bpath = SubDirPrefix(absFilename);
- bpath += cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
- // search for default header files and private header files
- basepaths[0] = bpath;
- basepaths[1] = bpath + "_p";
- }
-
- for (const std::string* bpit = cmArrayBegin(basepaths);
- bpit != cmArrayEnd(basepaths); ++bpit) {
- std::string headerName;
- if (this->FindHeader(headerName, *bpit)) {
- // Moc headers
- if (!this->MocSkip(absFilename) && !this->MocSkip(headerName)) {
- mocHeaderFiles.insert(headerName);
- }
- // Uic headers
- if (!this->UicSkip(absFilename) && !this->UicSkip(headerName)) {
- uicHeaderFiles.insert(headerName);
- }
- }
- }
-}
-
-bool cmQtAutoGenerators::ParseHeaders(
- const std::set<std::string>& mocHeaderFiles,
- const std::set<std::string>& uicHeaderFiles,
- const std::map<std::string, std::string>& mocsIncluded,
- std::map<std::string, std::string>& mocsNotIncluded,
- std::map<std::string, std::set<std::string> >& mocDepends,
- std::map<std::string, std::vector<std::string> >& uisIncluded)
-{
- bool success = true;
- // Merged header files list to read files only once
- std::set<std::string> headerFiles;
- headerFiles.insert(mocHeaderFiles.begin(), mocHeaderFiles.end());
- headerFiles.insert(uicHeaderFiles.begin(), uicHeaderFiles.end());
-
- for (std::set<std::string>::const_iterator hIt = headerFiles.begin();
- hIt != headerFiles.end(); ++hIt) {
- const std::string& headerName = *hIt;
- std::string contentText;
- if (ReadAll(contentText, headerName)) {
- // Parse header content for MOC
- if ((mocHeaderFiles.find(headerName) != mocHeaderFiles.end()) &&
- (mocsIncluded.find(headerName) == mocsIncluded.end())) {
- this->MocParseHeaderContent(headerName, contentText, mocsNotIncluded,
- mocDepends);
- }
- // Parse header content for UIC
- if (uicHeaderFiles.find(headerName) != uicHeaderFiles.end()) {
- this->UicParseContent(headerName, contentText, uisIncluded);
- }
- } else {
- std::ostringstream ost;
- ost << "AutoGen: Error: Could not read header file:\n"
- << Quoted(headerName);
- this->LogError(ost.str());
- success = false;
- break;
- }
- }
- return success;
-}
-
-bool cmQtAutoGenerators::MocGenerateAll(
- const std::map<std::string, std::string>& mocsIncluded,
- const std::map<std::string, std::string>& mocsNotIncluded,
- const std::map<std::string, std::set<std::string> >& mocDepends)
-{
- if (!this->MocEnabled()) {
- return true;
- }
-
- // Look for name collisions
- {
- std::multimap<std::string, std::string> collisions;
- // Test merged map of included and notIncluded
- std::map<std::string, std::string> mergedMocs(mocsIncluded);
- mergedMocs.insert(mocsNotIncluded.begin(), mocsNotIncluded.end());
- if (this->NameCollisionTest(mergedMocs, collisions)) {
- std::ostringstream ost;
- ost << "AutoMoc: Error: "
- "The same moc file will be generated "
- "from different sources.\n"
- "To avoid this error either\n"
- "- rename the source files or\n"
- "- do not include the (moc_NAME.cpp|NAME.moc) file";
- this->LogErrorNameCollision(ost.str(), collisions);
- return false;
- }
- }
-
- // Generate moc_predefs
- if (!this->MocPredefsCmd.empty()) {
- if (this->MocSettingsChanged ||
- FileAbsentOrOlder(this->MocPredefsFileAbs, this->SettingsFile)) {
- 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::vector<std::string>::const_iterator it =
- this->MocDefinitions.begin();
- it != this->MocDefinitions.end(); ++it) {
- cmd.push_back("-D" + (*it));
- }
- // Add options
- cmd.insert(cmd.end(), this->MocOptions.begin(),
- this->MocOptions.end());
- // Execute command
- if (!this->RunCommand(cmd, output, false)) {
- {
- std::ostringstream ost;
- ost << "AutoMoc: Error: moc predefs generation command failed\n";
- ost << "AutoMoc: Command:\n" << QuotedCommand(cmd) << "\n";
- ost << "AutoMoc: Command output:\n" << output << "\n";
- this->LogError(ost.str());
- }
- return false;
- }
- }
- // (Re)write predefs file only on demand
- if (this->FileDiffers(this->MocPredefsFileAbs, output)) {
- if (this->FileWrite("AutoMoc", this->MocPredefsFileAbs, output)) {
- this->MocPredefsChanged = true;
- } else {
- return false;
- }
- }
- }
- }
-
- // Generate moc files that are included by source files.
- for (std::map<std::string, std::string>::const_iterator it =
- mocsIncluded.begin();
- it != mocsIncluded.end(); ++it) {
- if (!this->MocGenerateFile(it->first, it->second, mocDepends, true)) {
- if (this->MocRunFailed) {
- return false;
- }
- }
- }
-
- // Generate moc files that are _not_ included by source files.
- bool mocCompFileGenerated = false;
- for (std::map<std::string, std::string>::const_iterator it =
- mocsNotIncluded.begin();
- it != mocsNotIncluded.end(); ++it) {
- if (this->MocGenerateFile(it->first, it->second, mocDepends, false)) {
- mocCompFileGenerated = true;
- } else {
- if (this->MocRunFailed) {
- return false;
- }
- }
- }
-
- // Compose mocs compilation file content
- std::string automocSource;
- {
- std::ostringstream ost;
- ost << "/* This file is autogenerated, do not edit*/\n";
- if (mocsNotIncluded.empty()) {
- // Dummy content
- ost << "enum some_compilers { need_more_than_nothing };\n";
- } else {
- // Valid content
- for (std::map<std::string, std::string>::const_iterator it =
- mocsNotIncluded.begin();
- it != mocsNotIncluded.end(); ++it) {
- ost << "#include \"" << it->second << "\"\n";
- }
- }
- automocSource = ost.str();
- }
-
- if (this->FileDiffers(this->MocCompFileAbs, automocSource)) {
- // Actually write mocs compilation file
- this->LogBold("Generating MOC compilation " + this->MocCompFileRel);
- if (!this->FileWrite("AutoMoc", this->MocCompFileAbs, automocSource)) {
- return false;
- }
- } else if (mocCompFileGenerated) {
- // Only touch mocs compilation file
- if (this->Verbose) {
- this->LogInfo("Touching MOC compilation " + this->MocCompFileRel);
- }
- cmSystemTools::Touch(this->MocCompFileAbs, false);
- }
-
- return true;
-}
-
-/**
- * @return True if a moc file was created. False may indicate an error.
- */
-bool cmQtAutoGenerators::MocGenerateFile(
- const std::string& sourceFile, const std::string& mocFileName,
- const std::map<std::string, std::set<std::string> >& mocDepends,
- bool included)
-{
- bool mocGenerated = false;
- bool generateMoc = this->MocSettingsChanged || this->MocPredefsChanged;
-
- const std::string mocFileRel =
- included ? (this->AutogenIncludeDir + mocFileName) : mocFileName;
- const std::string mocFileAbs =
- cmSystemTools::CollapseCombinedPath(this->AutogenBuildDir, mocFileRel);
-
- if (!generateMoc) {
- // Test if the source file is newer that the build file
- generateMoc = FileAbsentOrOlder(mocFileAbs, sourceFile);
- if (!generateMoc) {
- // Test if a dependency file changed
- std::map<std::string, std::set<std::string> >::const_iterator dit =
- mocDepends.find(sourceFile);
- if (dit != mocDepends.end()) {
- for (std::set<std::string>::const_iterator fit = dit->second.begin();
- fit != dit->second.end(); ++fit) {
- if (FileAbsentOrOlder(mocFileAbs, *fit)) {
- generateMoc = true;
- break;
- }
- }
- }
- }
- }
- if (generateMoc) {
- // Log
- this->LogBold("Generating MOC source " + mocFileRel);
-
- // Make sure the parent directory exists
- if (this->MakeParentDirectory("AutoMoc", mocFileAbs)) {
- // Compose moc command
- std::vector<std::string> cmd;
- cmd.push_back(this->MocExecutable);
- // Add includes
- cmd.insert(cmd.end(), this->MocIncludes.begin(),
- this->MocIncludes.end());
- // Add definitions
- for (std::vector<std::string>::const_iterator it =
- this->MocDefinitions.begin();
- it != this->MocDefinitions.end(); ++it) {
- cmd.push_back("-D" + (*it));
- }
- // Add options
- cmd.insert(cmd.end(), this->MocOptions.begin(), this->MocOptions.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(sourceFile);
-
- // Execute moc command
- std::string output;
- if (this->RunCommand(cmd, output)) {
- // Success
- mocGenerated = true;
- } else {
- // Command failed
- {
- std::ostringstream ost;
- ost << "AutoMoc: Error: moc process failed for\n";
- ost << Quoted(mocFileRel) << "\n";
- ost << "AutoMoc: Command:\n" << QuotedCommand(cmd) << "\n";
- ost << "AutoMoc: Command output:\n" << output << "\n";
- this->LogError(ost.str());
- }
- cmSystemTools::RemoveFile(mocFileAbs);
- this->MocRunFailed = true;
- }
- } else {
- // Parent directory creation failed
- this->MocRunFailed = true;
- }
- }
- return mocGenerated;
-}
-
-bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile,
- const std::string& sourceFile,
- const std::string& searchPath,
- const std::string& searchFile)
-{
- bool success = false;
- std::vector<std::string> testFiles;
- // Collect search paths list
- {
- const std::string searchFileFull = searchPath + searchFile;
- // Vicinity of the source
- {
- const std::string 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::vector<std::string>::const_iterator iit =
- this->UicSearchPaths.begin();
- iit != this->UicSearchPaths.end(); ++iit) {
- testFiles.push_back(*iit + "/" + searchFile);
- }
- if (!searchPath.empty()) {
- for (std::vector<std::string>::const_iterator iit =
- this->UicSearchPaths.begin();
- iit != this->UicSearchPaths.end(); ++iit) {
- testFiles.push_back(*iit + "/" + searchFileFull);
- }
- }
- }
- }
-
- // Search for the .ui file!
- for (std::vector<std::string>::const_iterator iit = testFiles.begin();
- iit != testFiles.end(); ++iit) {
- const std::string& testFile = *iit;
- if (cmsys::SystemTools::FileExists(testFile.c_str())) {
- absFile = cmsys::SystemTools::GetRealPath(testFile);
- success = true;
- break;
- }
- }
-
- // Log error
- if (!success) {
- std::ostringstream ost;
- ost << "AutoUic: Error: " << Quoted(sourceFile) << "\n";
- ost << "Could not find " << Quoted(searchFile) << " in\n";
- for (std::vector<std::string>::const_iterator iit = testFiles.begin();
- iit != testFiles.end(); ++iit) {
- ost << " " << Quoted(*iit) << "\n";
- }
- this->LogError(ost.str());
- }
-
- return success;
-}
-
-bool cmQtAutoGenerators::UicGenerateAll(
- const std::map<std::string, std::vector<std::string> >& uisIncluded)
-{
- if (!this->UicEnabled()) {
- return true;
- }
-
- // single map with input / output names
- std::map<std::string, std::map<std::string, std::string> > sourceGenMap;
- {
- // Collision lookup map
- std::map<std::string, std::string> testMap;
- // Compile maps
- for (std::map<std::string, std::vector<std::string> >::const_iterator sit =
- uisIncluded.begin();
- sit != uisIncluded.end(); ++sit) {
- const std::string& source(sit->first);
- const std::vector<std::string>& sourceIncs(sit->second);
- // insert new source/destination map
- std::map<std::string, std::string>& uiGenMap = sourceGenMap[source];
- for (std::vector<std::string>::const_iterator uit = sourceIncs.begin();
- uit != sourceIncs.end(); ++uit) {
- // Remove ui_ from the begin filename by substr()
- const std::string uiBasePath = SubDirPrefix(*uit);
- const std::string uiBaseName =
- cmsys::SystemTools::GetFilenameWithoutLastExtension(*uit).substr(3);
- const std::string uiFileName = uiBaseName + ".ui";
- std::string uiInputFile;
- if (UicFindIncludedFile(uiInputFile, source, uiBasePath, uiFileName)) {
- std::string uiOutputFile = uiBasePath + "ui_" + uiBaseName + ".h";
- cmSystemTools::ReplaceString(uiOutputFile, "..", "__");
- uiGenMap[uiInputFile] = uiOutputFile;
- testMap[uiInputFile] = uiOutputFile;
- } else {
- return false;
- }
- }
- }
- // look for name collisions
- {
- std::multimap<std::string, std::string> collisions;
- if (this->NameCollisionTest(testMap, collisions)) {
- std::ostringstream ost;
- ost << "AutoUic: Error: The same ui_NAME.h file will be generated "
- "from different sources.\n"
- "To avoid this error rename the source files.\n";
- this->LogErrorNameCollision(ost.str(), collisions);
- return false;
- }
- }
- }
-
- // generate ui files
- for (std::map<std::string,
- std::map<std::string, std::string> >::const_iterator it =
- sourceGenMap.begin();
- it != sourceGenMap.end(); ++it) {
- for (std::map<std::string, std::string>::const_iterator sit =
- it->second.begin();
- sit != it->second.end(); ++sit) {
- if (!this->UicGenerateFile(it->first, sit->first, sit->second)) {
- if (this->UicRunFailed) {
- return false;
- }
- }
- }
- }
-
- return true;
-}
-
-/**
- * @return True if a uic file was created. False may indicate an error.
- */
-bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName,
- const std::string& uiInputFile,
- const std::string& uiOutputFile)
-{
- bool uicGenerated = false;
- bool generateUic = this->UicSettingsChanged;
-
- const std::string uicFileRel = this->AutogenIncludeDir + uiOutputFile;
- const std::string uicFileAbs =
- cmSystemTools::CollapseCombinedPath(this->AutogenBuildDir, uicFileRel);
-
- if (!generateUic) {
- // Test if the source file is newer that the build file
- generateUic = FileAbsentOrOlder(uicFileAbs, uiInputFile);
- }
- if (generateUic) {
- // Log
- this->LogBold("Generating UIC header " + uicFileRel);
-
- // Make sure the parent directory exists
- if (this->MakeParentDirectory("AutoUic", uicFileAbs)) {
- // Compose uic command
- std::vector<std::string> cmd;
- cmd.push_back(this->UicExecutable);
- {
- std::vector<std::string> allOpts = this->UicTargetOptions;
- std::map<std::string, std::string>::const_iterator optionIt =
- this->UicOptions.find(uiInputFile);
- if (optionIt != this->UicOptions.end()) {
- std::vector<std::string> fileOpts;
- cmSystemTools::ExpandListArgument(optionIt->second, fileOpts);
- UicMergeOptions(allOpts, fileOpts, (this->QtMajorVersion == "5"));
- }
- cmd.insert(cmd.end(), allOpts.begin(), allOpts.end());
- }
- cmd.push_back("-o");
- cmd.push_back(uicFileAbs);
- cmd.push_back(uiInputFile);
-
- std::string output;
- if (this->RunCommand(cmd, output)) {
- // Success
- uicGenerated = true;
- } else {
- // Command failed
- {
- std::ostringstream ost;
- ost << "AutoUic: Error: uic process failed for\n";
- ost << Quoted(uicFileRel) << " needed by\n";
- ost << Quoted(realName) << "\n";
- ost << "AutoUic: Command:\n" << QuotedCommand(cmd) << "\n";
- ost << "AutoUic: Command output:\n" << output << "\n";
- this->LogError(ost.str());
- }
- cmSystemTools::RemoveFile(uicFileAbs);
- this->UicRunFailed = true;
- }
- } else {
- // Parent directory creation failed
- this->UicRunFailed = true;
- }
- }
- return uicGenerated;
-}
-
-bool cmQtAutoGenerators::RccGenerateAll()
-{
- if (!this->RccEnabled()) {
- return true;
- }
-
- // generate single map with input / output names
- std::map<std::string, std::string> qrcGenMap;
- {
- const std::string qrcPrefix = "qrc_";
- const std::string qrcSuffix = this->ConfigSuffix + ".cpp";
- for (std::vector<std::string>::const_iterator si =
- this->RccSources.begin();
- si != this->RccSources.end(); ++si) {
- const std::string ext =
- cmsys::SystemTools::GetFilenameLastExtension(*si);
- if (ext == ".qrc") {
- qrcGenMap[*si] = this->ChecksumedPath(*si, qrcPrefix, qrcSuffix);
- }
- }
- }
-
- // look for name collisions
- {
- std::multimap<std::string, std::string> collisions;
- if (this->NameCollisionTest(qrcGenMap, collisions)) {
- std::ostringstream ost;
- ost << "AutoRcc: Error: The same qrc_NAME.cpp file"
- " will be generated from different sources.\n"
- "To avoid this error rename the source .qrc files.\n";
- this->LogErrorNameCollision(ost.str(), collisions);
- return false;
- }
- }
-
- // generate qrc files
- for (std::map<std::string, std::string>::const_iterator si =
- qrcGenMap.begin();
- si != qrcGenMap.end(); ++si) {
- bool unique = FileNameIsUnique(si->first, qrcGenMap);
- if (!this->RccGenerateFile(si->first, si->second, unique)) {
- if (this->RccRunFailed) {
- return false;
- }
- }
- }
- return true;
-}
-
-/**
- * @return True if a rcc file was created. False may indicate an error.
- */
-bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
- const std::string& rccOutputFile,
- bool unique_n)
-{
- bool rccGenerated = false;
- bool generateRcc = this->RccSettingsChanged;
-
- const std::string rccBuildFile =
- cmSystemTools::CollapseCombinedPath(this->AutogenBuildDir, rccOutputFile);
-
- if (!generateRcc) {
- // Test if the resources list file is newer than build file
- generateRcc = FileAbsentOrOlder(rccBuildFile, rccInputFile);
- if (!generateRcc) {
- // Acquire input file list
- std::vector<std::string> readFiles;
- const std::vector<std::string>* files = &this->RccInputs[rccInputFile];
- if (files->empty()) {
- // Read input file list from qrc file
- std::string error;
- if (cmQtAutoGeneratorCommon::RccListInputs(
- this->QtMajorVersion, this->RccExecutable, rccInputFile,
- readFiles, &error)) {
- files = &readFiles;
- } else {
- files = CM_NULLPTR;
- this->LogError(error);
- this->RccRunFailed = true;
- }
- }
- // Test if any input file is newer than the build file
- if (files != CM_NULLPTR) {
- for (std::vector<std::string>::const_iterator it = files->begin();
- it != files->end(); ++it) {
- if (FileAbsentOrOlder(rccBuildFile, *it)) {
- generateRcc = true;
- break;
- }
- }
- }
- }
- }
- if (generateRcc) {
- // Log
- this->LogBold("Generating RCC source " + rccOutputFile);
-
- // Make sure the parent directory exists
- if (this->MakeParentDirectory("AutoRcc", rccBuildFile)) {
- // Compose symbol name
- std::string symbolName =
- cmsys::SystemTools::GetFilenameWithoutLastExtension(rccInputFile);
- if (!unique_n) {
- symbolName += "_";
- symbolName += FPathChecksum.getPart(rccInputFile);
- }
- // Replace '-' with '_'. The former is valid for
- // file names but not for symbol names.
- std::replace(symbolName.begin(), symbolName.end(), '-', '_');
-
- // Compose rcc command
- std::vector<std::string> cmd;
- cmd.push_back(this->RccExecutable);
- {
- std::map<std::string, std::string>::const_iterator optionIt =
- this->RccOptions.find(rccInputFile);
- if (optionIt != this->RccOptions.end()) {
- cmSystemTools::ExpandListArgument(optionIt->second, cmd);
- }
- }
- cmd.push_back("-name");
- cmd.push_back(symbolName);
- cmd.push_back("-o");
- cmd.push_back(rccBuildFile);
- cmd.push_back(rccInputFile);
-
- std::string output;
- if (this->RunCommand(cmd, output)) {
- // Success
- rccGenerated = true;
- } else {
- // Command failed
- {
- std::ostringstream ost;
- ost << "AutoRcc: Error: rcc process failed for\n";
- ost << Quoted(rccOutputFile) << "\n";
- ost << "AutoRcc: Command:\n" << QuotedCommand(cmd) << "\n";
- ost << "AutoRcc: Command output:\n" << output << "\n";
- this->LogError(ost.str());
- }
- cmSystemTools::RemoveFile(rccBuildFile);
- this->RccRunFailed = true;
- }
- } else {
- // Parent directory creation failed
- this->RccRunFailed = true;
- }
- }
- return rccGenerated;
-}
-
-void cmQtAutoGenerators::LogErrorNameCollision(
- const std::string& message,
- const std::multimap<std::string, std::string>& collisions) const
-{
- typedef std::multimap<std::string, std::string>::const_iterator Iter;
-
- std::ostringstream ost;
- // Add message
- if (!message.empty()) {
- ost << message;
- if (message[message.size() - 1] != '\n') {
- ost << '\n';
- }
- }
- // Append collision list
- for (Iter it = collisions.begin(); it != collisions.end(); ++it) {
- ost << it->first << " : " << it->second << '\n';
- }
- this->LogError(ost.str());
-}
-
-void cmQtAutoGenerators::LogBold(const std::string& message) const
-{
- cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
- cmsysTerminal_Color_ForegroundBold,
- message.c_str(), true, this->ColorOutput);
-}
-
-void cmQtAutoGenerators::LogInfo(const std::string& message) const
-{
- std::string msg(message);
- if (!msg.empty()) {
- if (msg[msg.size() - 1] != '\n') {
- msg.push_back('\n');
- }
- cmSystemTools::Stdout(msg.c_str(), msg.size());
- }
-}
-
-void cmQtAutoGenerators::LogWarning(const std::string& message) const
-{
- std::string msg(message);
- if (!msg.empty()) {
- if (msg[msg.size() - 1] != '\n') {
- msg.push_back('\n');
- }
- // Append empty line
- msg.push_back('\n');
- cmSystemTools::Stdout(msg.c_str(), msg.size());
- }
-}
-
-void cmQtAutoGenerators::LogError(const std::string& message) const
-{
- std::string msg(message);
- if (!msg.empty()) {
- if (msg[msg.size() - 1] != '\n') {
- msg.push_back('\n');
- }
- // Append empty line
- msg.push_back('\n');
- cmSystemTools::Stderr(msg.c_str(), msg.size());
- }
-}
-
-/**
- * @brief Collects name collisions as output/input pairs
- * @return True if there were collisions
- */
-bool cmQtAutoGenerators::NameCollisionTest(
- const std::map<std::string, std::string>& genFiles,
- std::multimap<std::string, std::string>& collisions) const
-{
- typedef std::map<std::string, std::string>::const_iterator Iter;
- typedef std::map<std::string, std::string>::value_type VType;
- for (Iter ait = genFiles.begin(); ait != genFiles.end(); ++ait) {
- bool first_match(true);
- for (Iter bit = (++Iter(ait)); bit != genFiles.end(); ++bit) {
- if (ait->second == bit->second) {
- if (first_match) {
- if (collisions.find(ait->second) != collisions.end()) {
- // We already know of this collision from before
- break;
- }
- collisions.insert(VType(ait->second, ait->first));
- first_match = false;
- }
- collisions.insert(VType(bit->second, bit->first));
- }
- }
- }
-
- return !collisions.empty();
-}
-
-/**
- * @brief Generates a file path based on the checksum of the source file path
- * @return The path
- */
-std::string cmQtAutoGenerators::ChecksumedPath(
- const std::string& sourceFile, const std::string& basePrefix,
- const std::string& baseSuffix) const
-{
- std::string res = FPathChecksum.getPart(sourceFile);
- res += "/";
- res += basePrefix;
- res += cmsys::SystemTools::GetFilenameWithoutLastExtension(sourceFile);
- res += baseSuffix;
- return res;
-}
-
-/**
- * @brief Generates the parent directory of the given file on demand
- * @return True on success
- */
-bool cmQtAutoGenerators::MakeParentDirectory(const char* logPrefix,
- const std::string& filename) const
-{
- bool success = true;
- const std::string dirName = cmSystemTools::GetFilenamePath(filename);
- if (!dirName.empty()) {
- success = cmsys::SystemTools::MakeDirectory(dirName);
- if (!success) {
- std::string error = logPrefix;
- error += ": Error: Parent directory creation failed for ";
- error += Quoted(filename);
- this->LogError(error);
- }
- }
- return success;
-}
-
-bool cmQtAutoGenerators::FileDiffers(const std::string& filename,
- const std::string& content)
-{
- bool differs = true;
- {
- std::string oldContents;
- if (ReadAll(oldContents, filename)) {
- differs = (oldContents != content);
- }
- }
- return differs;
-}
-
-bool cmQtAutoGenerators::FileWrite(const char* logPrefix,
- const std::string& filename,
- const std::string& content)
-{
- std::string error;
- // Make sure the parent directory exists
- if (this->MakeParentDirectory(logPrefix, filename)) {
- cmsys::ofstream outfile;
- outfile.open(filename.c_str(), std::ios::trunc);
- if (outfile) {
- outfile << content;
- // Check for write errors
- if (!outfile.good()) {
- error = logPrefix;
- error += ": Error writing ";
- error += Quoted(filename);
- }
- } else {
- error = logPrefix;
- error = ": Error opening ";
- error += Quoted(filename);
- }
- }
- if (!error.empty()) {
- this->LogError(error);
- return false;
- }
- return true;
-}
-
-/**
- * @brief Runs a command and returns true on success
- * @return True on success
- */
-bool cmQtAutoGenerators::RunCommand(const std::vector<std::string>& command,
- std::string& output, bool verbose) const
-{
- // Log command
- if (this->Verbose) {
- this->LogInfo(QuotedCommand(command));
- }
- // Execute command
- int retVal = 0;
- bool res = cmSystemTools::RunSingleCommand(
- command, &output, &output, &retVal, CM_NULLPTR,
- verbose ? cmSystemTools::OUTPUT_MERGE : 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,
- const std::string& testBasePath) const
-{
- for (std::vector<std::string>::const_iterator ext =
- this->HeaderExtensions.begin();
- ext != this->HeaderExtensions.end(); ++ext) {
- std::string testFilePath(testBasePath);
- testFilePath += '.';
- testFilePath += (*ext);
- if (cmsys::SystemTools::FileExists(testFilePath.c_str())) {
- header = testFilePath;
- return true;
- }
- }
- return false;
-}
-
-std::string cmQtAutoGenerators::MocFindHeader(
- const std::string& sourcePath, const std::string& includeBase) const
-{
- std::string header;
- // Search in vicinity of the source
- if (!this->FindHeader(header, sourcePath + includeBase)) {
- // Search in include directories
- for (std::vector<std::string>::const_iterator iit =
- this->MocIncludePaths.begin();
- iit != this->MocIncludePaths.end(); ++iit) {
- const std::string fullPath = ((*iit) + '/' + includeBase);
- if (FindHeader(header, fullPath)) {
- break;
- }
- }
- }
- // Sanitize
- if (!header.empty()) {
- header = cmsys::SystemTools::GetRealPath(header);
- }
- return header;
-}
-
-bool cmQtAutoGenerators::MocFindIncludedFile(
- std::string& absFile, const std::string& sourcePath,
- const std::string& includeString) const
-{
- bool success = false;
- // Search in vicinity of the source
- {
- std::string testPath = sourcePath;
- testPath += includeString;
- if (cmsys::SystemTools::FileExists(testPath.c_str())) {
- absFile = cmsys::SystemTools::GetRealPath(testPath);
- success = true;
- }
- }
- // Search in include directories
- if (!success) {
- for (std::vector<std::string>::const_iterator iit =
- this->MocIncludePaths.begin();
- iit != this->MocIncludePaths.end(); ++iit) {
- const std::string fullPath = ((*iit) + '/' + includeString);
- if (cmsys::SystemTools::FileExists(fullPath.c_str())) {
- absFile = cmsys::SystemTools::GetRealPath(fullPath);
- success = true;
- break;
- }
- }
- }
- return success;
-}
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
deleted file mode 100644
index 337aa17fd..000000000
--- a/Source/cmQtAutoGenerators.h
+++ /dev/null
@@ -1,222 +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 "cmsys/RegularExpression.hxx"
-
-#include <map>
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
-class cmMakefile;
-
-class cmQtAutoGenerators
-{
-public:
- cmQtAutoGenerators();
- bool Run(const std::string& targetDirectory, const std::string& config);
-
-private:
- // -- Types
-
- /// @brief Used to extract additional dependencies from content text
- struct MocDependFilter
- {
- std::string key;
- cmsys::RegularExpression regExp;
- };
- typedef std::pair<std::string, cmsys::RegularExpression> MocMacroFilter;
-
- // -- Configuration
- bool MocDependFilterPush(const std::string& key, const std::string& regExp);
- bool ReadAutogenInfoFile(cmMakefile* makefile,
- const std::string& targetDirectory,
- const std::string& config);
-
- bool MocEnabled() const { return !this->MocExecutable.empty(); }
- bool UicEnabled() const { return !this->UicExecutable.empty(); }
- bool RccEnabled() const { return !this->RccExecutable.empty(); }
-
- // -- Settings file
- void SettingsFileRead(cmMakefile* makefile);
- bool SettingsFileWrite();
-
- bool AnySettingsChanged() const
- {
- return (this->MocSettingsChanged || this->RccSettingsChanged ||
- this->UicSettingsChanged);
- }
-
- // -- Init and run
- void Init(cmMakefile* makefile);
- bool RunAutogen();
-
- // -- Content analysis
- bool MocRequired(const std::string& contentText,
- std::string* macroName = CM_NULLPTR);
- void MocFindDepends(
- const std::string& absFilename, const std::string& contentText,
- std::map<std::string, std::set<std::string> >& mocDepends);
-
- bool MocSkip(const std::string& absFilename) const;
- bool UicSkip(const std::string& absFilename) const;
-
- bool ParseSourceFile(
- const std::string& absFilename,
- std::map<std::string, std::string>& mocsIncluded,
- std::map<std::string, std::set<std::string> >& mocDepends,
- std::map<std::string, std::vector<std::string> >& includedUis,
- bool relaxed);
-
- void SearchHeadersForSourceFile(const std::string& absFilename,
- std::set<std::string>& mocHeaderFiles,
- std::set<std::string>& uicHeaderFiles) const;
-
- bool ParseHeaders(
- const std::set<std::string>& mocHeaderFiles,
- const std::set<std::string>& uicHeaderFiles,
- const std::map<std::string, std::string>& mocsIncluded,
- std::map<std::string, std::string>& mocsNotIncluded,
- std::map<std::string, std::set<std::string> >& mocDepends,
- std::map<std::string, std::vector<std::string> >& includedUis);
-
- void UicParseContent(
- const std::string& fileName, const std::string& contentText,
- std::map<std::string, std::vector<std::string> >& includedUis);
-
- bool MocParseSourceContent(
- const std::string& absFilename, const std::string& contentText,
- std::map<std::string, std::string>& mocsIncluded,
- std::map<std::string, std::set<std::string> >& mocDepends, bool relaxed);
-
- void MocParseHeaderContent(
- const std::string& absFilename, const std::string& contentText,
- std::map<std::string, std::string>& mocsNotIncluded,
- std::map<std::string, std::set<std::string> >& mocDepends);
-
- // -- Moc file generation
- bool MocGenerateAll(
- const std::map<std::string, std::string>& mocsIncluded,
- const std::map<std::string, std::string>& mocsNotIncluded,
- const std::map<std::string, std::set<std::string> >& mocDepends);
- bool MocGenerateFile(
- const std::string& sourceFile, const std::string& mocFileName,
- const std::map<std::string, std::set<std::string> >& mocDepends,
- bool included);
-
- // -- Uic file generation
- bool UicFindIncludedFile(std::string& absFile, const std::string& sourceFile,
- const std::string& searchPath,
- const std::string& searchFile);
- bool UicGenerateAll(
- const std::map<std::string, std::vector<std::string> >& includedUis);
- bool UicGenerateFile(const std::string& realName,
- const std::string& uiInputFile,
- const std::string& uiOutputFile);
-
- // -- Rcc file generation
- bool RccGenerateAll();
- bool RccGenerateFile(const std::string& qrcInputFile,
- const std::string& qrcOutputFile, bool unique_n);
-
- // -- Logging
- void LogErrorNameCollision(
- const std::string& message,
- const std::multimap<std::string, std::string>& collisions) const;
- void LogBold(const std::string& message) const;
- void LogInfo(const std::string& message) const;
- void LogWarning(const std::string& message) const;
- void LogError(const std::string& message) const;
- void LogCommand(const std::vector<std::string>& command) const;
-
- // -- Utility
- bool NameCollisionTest(
- const std::map<std::string, std::string>& genFiles,
- std::multimap<std::string, std::string>& collisions) const;
- std::string ChecksumedPath(const std::string& sourceFile,
- const std::string& basePrefix,
- const std::string& baseSuffix) const;
- bool MakeParentDirectory(const char* logPrefix,
- const std::string& filename) const;
- bool FileDiffers(const std::string& filename, const std::string& content);
- bool FileWrite(const char* logPrefix, const std::string& filename,
- const std::string& content);
-
- bool RunCommand(const std::vector<std::string>& command, std::string& output,
- bool verbose = true) const;
-
- bool FindHeader(std::string& header, const std::string& testBasePath) const;
-
- std::string MocFindHeader(const std::string& sourcePath,
- const std::string& includeBase) const;
- bool MocFindIncludedFile(std::string& absFile, const std::string& sourceFile,
- const std::string& includeString) const;
-
- // -- Meta
- std::string ConfigSuffix;
- // -- 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 MocExecutable;
- std::string UicExecutable;
- std::string RccExecutable;
- // -- File lists
- std::vector<std::string> Sources;
- std::vector<std::string> Headers;
- std::vector<std::string> HeaderExtensions;
- cmFilePathChecksum FPathChecksum;
- // -- Settings
- bool IncludeProjectDirsBefore;
- bool Verbose;
- bool ColorOutput;
- std::string SettingsFile;
- std::string SettingsStringMoc;
- std::string SettingsStringUic;
- std::string SettingsStringRcc;
- // -- Moc
- bool MocSettingsChanged;
- bool MocPredefsChanged;
- bool MocRelaxedMode;
- bool MocRunFailed;
- 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> MocPredefsCmd;
- std::vector<MocDependFilter> MocDependFilters;
- MocMacroFilter MocMacroFilters[2];
- cmsys::RegularExpression MocRegExpInclude;
- // -- Uic
- bool UicSettingsChanged;
- bool UicRunFailed;
- std::vector<std::string> UicSkipList;
- std::vector<std::string> UicTargetOptions;
- std::map<std::string, std::string> UicOptions;
- std::vector<std::string> UicSearchPaths;
- cmsys::RegularExpression UicRegExpInclude;
- // -- Rcc
- bool RccSettingsChanged;
- bool RccRunFailed;
- std::vector<std::string> RccSources;
- std::map<std::string, std::string> RccOptions;
- std::map<std::string, std::vector<std::string> > RccInputs;
-};
-
-#endif
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
new file mode 100644
index 000000000..f8b898152
--- /dev/null
+++ b/Source/cmQtAutoMocUic.cxx
@@ -0,0 +1,2688 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmQtAutoMocUic.h"
+
+#include <algorithm>
+#include <atomic>
+#include <cstddef>
+#include <map>
+#include <mutex>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+#include <cm/memory>
+#include <cm/string_view>
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+
+#include "cm_jsoncpp_value.h"
+
+#include "cmAlgorithms.h"
+#include "cmCryptoHash.h"
+#include "cmFileTime.h"
+#include "cmGeneratedFileStream.h"
+#include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmWorkerPool.h"
+
+#if defined(__APPLE__)
+# include <unistd.h>
+#endif
+
+namespace {
+
+constexpr std::size_t MocUnderscoreLength = 4; // Length of "moc_"
+constexpr std::size_t UiUnderscoreLength = 3; // Length of "ui_"
+
+/** \class cmQtAutoMocUicT
+ * \brief AUTOMOC and AUTOUIC generator
+ */
+class cmQtAutoMocUicT : public cmQtAutoGenerator
+{
+public:
+ cmQtAutoMocUicT();
+ ~cmQtAutoMocUicT() override;
+
+ cmQtAutoMocUicT(cmQtAutoMocUicT const&) = delete;
+ cmQtAutoMocUicT& operator=(cmQtAutoMocUicT const&) = delete;
+
+public:
+ // -- Types
+
+ /** Include string with sub parts. */
+ struct IncludeKeyT
+ {
+ IncludeKeyT(std::string const& key, std::size_t basePrefixLength);
+
+ std::string Key; // Full include string
+ std::string Dir; // Include directory
+ std::string Base; // Base part of the include file name
+ };
+
+ /** Search key plus regular expression pair. */
+ struct KeyExpT
+ {
+ KeyExpT(std::string key, std::string const& exp)
+ : Key(std::move(key))
+ , Exp(exp)
+ {
+ }
+
+ std::string Key;
+ cmsys::RegularExpression Exp;
+ };
+
+ /** Source file parsing cache. */
+ class ParseCacheT
+ {
+ public:
+ // -- Types
+
+ /** Entry of the file parsing cache. */
+ struct FileT
+ {
+ void Clear();
+
+ struct MocT
+ {
+ std::string Macro;
+ struct IncludeT
+ {
+ std::vector<IncludeKeyT> Underscore;
+ std::vector<IncludeKeyT> Dot;
+ } Include;
+ std::vector<std::string> Depends;
+ } Moc;
+
+ struct UicT
+ {
+ std::vector<IncludeKeyT> Include;
+ std::vector<std::string> Depends;
+ } Uic;
+ };
+ using FileHandleT = std::shared_ptr<FileT>;
+ using GetOrInsertT = std::pair<FileHandleT, bool>;
+
+ public:
+ ParseCacheT();
+ ~ParseCacheT();
+
+ bool ReadFromFile(std::string const& fileName);
+ bool WriteToFile(std::string const& fileName);
+
+ //! Always returns a valid handle
+ GetOrInsertT GetOrInsert(std::string const& fileName);
+
+ private:
+ std::unordered_map<std::string, FileHandleT> Map_;
+ };
+
+ /** Source file data. */
+ class SourceFileT
+ {
+ public:
+ SourceFileT(std::string fileName)
+ : FileName(std::move(fileName))
+ {
+ }
+
+ public:
+ std::string FileName;
+ cmFileTime FileTime;
+ ParseCacheT::FileHandleT ParseData;
+ std::string BuildPath;
+ bool IsHeader = false;
+ bool Moc = false;
+ bool Uic = false;
+ };
+ using SourceFileHandleT = std::shared_ptr<SourceFileT>;
+ using SourceFileMapT = std::map<std::string, SourceFileHandleT>;
+
+ /** Meta compiler file mapping information. */
+ struct MappingT
+ {
+ SourceFileHandleT SourceFile;
+ std::string OutputFile;
+ std::string IncludeString;
+ std::vector<SourceFileHandleT> IncluderFiles;
+ };
+ using MappingHandleT = std::shared_ptr<MappingT>;
+ using MappingMapT = std::map<std::string, MappingHandleT>;
+
+ /** Common settings. */
+ class BaseSettingsT
+ {
+ public:
+ // -- Constructors
+ BaseSettingsT();
+ ~BaseSettingsT();
+
+ BaseSettingsT(BaseSettingsT const&) = delete;
+ BaseSettingsT& operator=(BaseSettingsT const&) = delete;
+
+ // -- Attributes
+ // - Config
+ bool MultiConfig = false;
+ unsigned int QtVersionMajor = 4;
+ unsigned int ThreadCount = 0;
+ // - Directories
+ std::string AutogenBuildDir;
+ std::string AutogenIncludeDir;
+ // - Files
+ std::string CMakeExecutable;
+ cmFileTime CMakeExecutableTime;
+ std::string ParseCacheFile;
+ std::vector<std::string> HeaderExtensions;
+ };
+
+ /** Shared common variables. */
+ class BaseEvalT
+ {
+ public:
+ // -- Parse Cache
+ bool ParseCacheChanged = false;
+ cmFileTime ParseCacheTime;
+ ParseCacheT ParseCache;
+
+ // -- Sources
+ SourceFileMapT Headers;
+ SourceFileMapT Sources;
+ };
+
+ /** Moc settings. */
+ class MocSettingsT
+ {
+ public:
+ // -- Constructors
+ MocSettingsT();
+ ~MocSettingsT();
+
+ MocSettingsT(MocSettingsT const&) = delete;
+ MocSettingsT& operator=(MocSettingsT const&) = delete;
+
+ // -- Const methods
+ bool skipped(std::string const& fileName) const;
+ std::string MacrosString() const;
+
+ // -- Attributes
+ bool Enabled = false;
+ bool SettingsChanged = false;
+ bool RelaxedMode = false;
+ bool PathPrefix = false;
+ cmFileTime ExecutableTime;
+ std::string Executable;
+ std::string CompFileAbs;
+ std::string PredefsFileAbs;
+ std::unordered_set<std::string> SkipList;
+ std::vector<std::string> IncludePaths;
+ std::vector<std::string> Definitions;
+ std::vector<std::string> OptionsIncludes;
+ std::vector<std::string> OptionsDefinitions;
+ std::vector<std::string> OptionsExtra;
+ std::vector<std::string> PredefsCmd;
+ std::vector<KeyExpT> DependFilters;
+ std::vector<KeyExpT> MacroFilters;
+ cmsys::RegularExpression RegExpInclude;
+ };
+
+ /** Moc shared variables. */
+ class MocEvalT
+ {
+ public:
+ // -- predefines file
+ cmFileTime PredefsTime;
+ // -- Mappings
+ MappingMapT HeaderMappings;
+ MappingMapT SourceMappings;
+ MappingMapT Includes;
+ // -- Discovered files
+ SourceFileMapT HeadersDiscovered;
+ // -- Output directories
+ std::unordered_set<std::string> OutputDirs;
+ // -- Mocs compilation
+ bool CompUpdated = false;
+ std::vector<std::string> CompFiles;
+ };
+
+ /** Uic settings. */
+ class UicSettingsT
+ {
+ public:
+ struct UiFile
+ {
+ std::vector<std::string> Options;
+ };
+
+ public:
+ UicSettingsT();
+ ~UicSettingsT();
+
+ UicSettingsT(UicSettingsT const&) = delete;
+ UicSettingsT& operator=(UicSettingsT const&) = delete;
+
+ // -- Const methods
+ bool skipped(std::string const& fileName) const;
+
+ // -- Attributes
+ bool Enabled = false;
+ bool SettingsChanged = false;
+ cmFileTime ExecutableTime;
+ std::string Executable;
+ std::unordered_set<std::string> SkipList;
+ std::vector<std::string> Options;
+ std::unordered_map<std::string, UiFile> UiFiles;
+ std::vector<std::string> SearchPaths;
+ cmsys::RegularExpression RegExpInclude;
+ };
+
+ /** Uic shared variables. */
+ class UicEvalT
+ {
+ public:
+ // -- Discovered files
+ SourceFileMapT UiFiles;
+ // -- Mappings
+ MappingMapT Includes;
+ // -- Output directories
+ std::unordered_set<std::string> OutputDirs;
+ };
+
+ /** Abstract job class for concurrent job processing. */
+ class JobT : public cmWorkerPool::JobT
+ {
+ protected:
+ /** Protected default constructor. */
+ JobT(bool fence = false)
+ : cmWorkerPool::JobT(fence)
+ {
+ }
+
+ //! Get the generator. Only valid during Process() call!
+ cmQtAutoMocUicT* Gen() const
+ {
+ return static_cast<cmQtAutoMocUicT*>(UserData());
+ };
+
+ // -- Accessors. Only valid during Process() call!
+ Logger const& Log() const { return Gen()->Log(); }
+ BaseSettingsT const& BaseConst() const { return Gen()->BaseConst(); }
+ BaseEvalT& BaseEval() const { return Gen()->BaseEval(); }
+ MocSettingsT const& MocConst() const { return Gen()->MocConst(); }
+ MocEvalT& MocEval() const { return Gen()->MocEval(); }
+ UicSettingsT const& UicConst() const { return Gen()->UicConst(); }
+ UicEvalT& UicEval() const { return Gen()->UicEval(); }
+
+ // -- Logging
+ std::string MessagePath(cm::string_view path) const
+ {
+ return Gen()->MessagePath(path);
+ }
+ // - Error logging with automatic abort
+ void LogError(GenT genType, cm::string_view message) const;
+ void LogCommandError(GenT genType, cm::string_view message,
+ std::vector<std::string> const& command,
+ std::string const& output) const;
+
+ /** @brief Run an external process. Use only during Process() call! */
+ bool RunProcess(GenT genType, cmWorkerPool::ProcessResultT& result,
+ std::vector<std::string> const& command,
+ std::string* infoMessage = nullptr);
+ };
+
+ /** Fence job utility class. */
+ class JobFenceT : public JobT
+ {
+ public:
+ JobFenceT()
+ : JobT(true)
+ {
+ }
+ void Process() override{};
+ };
+
+ /** Generate moc_predefs.h. */
+ class JobMocPredefsT : public JobFenceT
+ {
+ void Process() override;
+ bool Update(std::string* reason) const;
+ };
+
+ /** File parse job base class. */
+ class JobParseT : public JobT
+ {
+ public:
+ JobParseT(SourceFileHandleT fileHandle)
+ : FileHandle(std::move(fileHandle))
+ {
+ }
+
+ protected:
+ bool ReadFile();
+ void CreateKeys(std::vector<IncludeKeyT>& container,
+ std::set<std::string> const& source,
+ std::size_t basePrefixLength);
+ void MocMacro();
+ void MocDependecies();
+ void MocIncludes();
+ void UicIncludes();
+
+ protected:
+ SourceFileHandleT FileHandle;
+ std::string Content;
+ };
+
+ /** Header file parse job. */
+ class JobParseHeaderT : public JobParseT
+ {
+ public:
+ using JobParseT::JobParseT;
+ void Process() override;
+ };
+
+ /** Source file parse job. */
+ class JobParseSourceT : public JobParseT
+ {
+ public:
+ using JobParseT::JobParseT;
+ void Process() override;
+ };
+
+ /** Evaluate cached file parse data - moc. */
+ class JobEvalCacheT : public JobT
+ {
+ protected:
+ std::string MessageSearchLocations() const;
+ std::vector<std::string> SearchLocations;
+ };
+
+ /** Evaluate cached file parse data - moc. */
+ class JobEvalCacheMocT : public JobEvalCacheT
+ {
+ void Process() override;
+ bool EvalHeader(SourceFileHandleT source);
+ bool EvalSource(SourceFileHandleT const& source);
+ bool FindIncludedHeader(SourceFileHandleT& headerHandle,
+ cm::string_view includerDir,
+ cm::string_view includeBase);
+ bool RegisterIncluded(std::string const& includeString,
+ SourceFileHandleT includerFileHandle,
+ SourceFileHandleT sourceFileHandle) const;
+ void RegisterMapping(MappingHandleT mappingHandle) const;
+ std::string MessageHeader(cm::string_view headerBase) const;
+ };
+
+ /** Evaluate cached file parse data - uic. */
+ class JobEvalCacheUicT : public JobEvalCacheT
+ {
+ void Process() override;
+ bool EvalFile(SourceFileHandleT const& sourceFileHandle);
+ bool FindIncludedUi(cm::string_view sourceDirPrefix,
+ cm::string_view includePrefix);
+ bool RegisterMapping(std::string const& includeString,
+ SourceFileHandleT includerFileHandle);
+
+ std::string UiName;
+ SourceFileHandleT UiFileHandle;
+ };
+
+ /** Evaluate cached file parse data - finish */
+ class JobEvalCacheFinishT : public JobFenceT
+ {
+ void Process() override;
+ };
+
+ /** Dependency probing base job. */
+ class JobProbeDepsT : public JobT
+ {
+ };
+
+ /** Probes file dependencies and generates moc compile jobs. */
+ class JobProbeDepsMocT : public JobProbeDepsT
+ {
+ void Process() override;
+ bool Generate(MappingHandleT const& mapping, bool compFile) const;
+ bool Probe(MappingT const& mapping, std::string* reason) const;
+ std::pair<std::string, cmFileTime> FindDependency(
+ std::string const& sourceDir, std::string const& includeString) const;
+ };
+
+ /** Probes file dependencies and generates uic compile jobs. */
+ class JobProbeDepsUicT : public JobProbeDepsT
+ {
+ void Process() override;
+ bool Probe(MappingT const& mapping, std::string* reason) const;
+ };
+
+ /** Dependency probing finish job. */
+ class JobProbeDepsFinishT : public JobFenceT
+ {
+ void Process() override;
+ };
+
+ /** Meta compiler base job. */
+ class JobCompileT : public JobT
+ {
+ public:
+ JobCompileT(MappingHandleT uicMapping, std::unique_ptr<std::string> reason)
+ : Mapping(std::move(uicMapping))
+ , Reason(std::move(reason))
+ {
+ }
+
+ protected:
+ MappingHandleT Mapping;
+ std::unique_ptr<std::string> Reason;
+ };
+
+ /** moc compiles a file. */
+ class JobCompileMocT : public JobCompileT
+ {
+ public:
+ using JobCompileT::JobCompileT;
+ void Process() override;
+ };
+
+ /** uic compiles a file. */
+ class JobCompileUicT : public JobCompileT
+ {
+ public:
+ using JobCompileT::JobCompileT;
+ void Process() override;
+ };
+
+ /** Generate mocs_compilation.cpp. */
+ class JobMocsCompilationT : public JobFenceT
+ {
+ private:
+ void Process() override;
+ };
+
+ /** @brief The last job. */
+ class JobFinishT : public JobFenceT
+ {
+ private:
+ void Process() override;
+ };
+
+ // -- Const settings interface
+ BaseSettingsT const& BaseConst() const { return this->BaseConst_; }
+ BaseEvalT& BaseEval() { return this->BaseEval_; }
+ MocSettingsT const& MocConst() const { return this->MocConst_; }
+ MocEvalT& MocEval() { return this->MocEval_; }
+ UicSettingsT const& UicConst() const { return this->UicConst_; }
+ UicEvalT& UicEval() { return this->UicEval_; }
+
+ // -- Parallel job processing interface
+ cmWorkerPool& WorkerPool() { return WorkerPool_; }
+ void AbortError() { Abort(true); }
+ void AbortSuccess() { Abort(false); }
+
+ // -- Utility
+ std::string AbsoluteBuildPath(cm::string_view relativePath) const;
+ std::string AbsoluteIncludePath(cm::string_view relativePath) const;
+ template <class JOBTYPE>
+ void CreateParseJobs(SourceFileMapT const& sourceMap);
+ std::string CollapseFullPathTS(std::string const& path) const;
+
+private:
+ // -- Abstract processing interface
+ bool InitFromInfo(InfoT const& info) override;
+ void InitJobs();
+ bool Process() override;
+ // -- Settings file
+ void SettingsFileRead();
+ bool SettingsFileWrite();
+ // -- Parse cache
+ void ParseCacheRead();
+ bool ParseCacheWrite();
+ // -- Thread processing
+ void Abort(bool error);
+ // -- Generation
+ bool CreateDirectories();
+
+private:
+ // -- Settings
+ BaseSettingsT BaseConst_;
+ BaseEvalT BaseEval_;
+ MocSettingsT MocConst_;
+ MocEvalT MocEval_;
+ UicSettingsT UicConst_;
+ UicEvalT UicEval_;
+ // -- Settings file
+ std::string SettingsFile_;
+ std::string SettingsStringMoc_;
+ std::string SettingsStringUic_;
+ // -- Worker thread pool
+ std::atomic<bool> JobError_ = ATOMIC_VAR_INIT(false);
+ cmWorkerPool WorkerPool_;
+ // -- Concurrent processing
+ mutable std::mutex CMakeLibMutex_;
+};
+
+cmQtAutoMocUicT::IncludeKeyT::IncludeKeyT(std::string const& key,
+ std::size_t basePrefixLength)
+ : Key(key)
+ , Dir(SubDirPrefix(key))
+ , Base(cmSystemTools::GetFilenameWithoutLastExtension(key))
+{
+ if (basePrefixLength != 0) {
+ Base = Base.substr(basePrefixLength);
+ }
+}
+
+void cmQtAutoMocUicT::ParseCacheT::FileT::Clear()
+{
+ Moc.Macro.clear();
+ Moc.Include.Underscore.clear();
+ Moc.Include.Dot.clear();
+ Moc.Depends.clear();
+
+ Uic.Include.clear();
+ Uic.Depends.clear();
+}
+
+cmQtAutoMocUicT::ParseCacheT::GetOrInsertT
+cmQtAutoMocUicT::ParseCacheT::GetOrInsert(std::string const& fileName)
+{
+ // Find existing entry
+ {
+ auto it = Map_.find(fileName);
+ if (it != Map_.end()) {
+ return GetOrInsertT{ it->second, false };
+ }
+ }
+
+ // Insert new entry
+ return GetOrInsertT{
+ Map_.emplace(fileName, std::make_shared<FileT>()).first->second, true
+ };
+}
+
+cmQtAutoMocUicT::ParseCacheT::ParseCacheT() = default;
+cmQtAutoMocUicT::ParseCacheT::~ParseCacheT() = default;
+
+bool cmQtAutoMocUicT::ParseCacheT::ReadFromFile(std::string const& fileName)
+{
+ cmsys::ifstream fin(fileName.c_str());
+ if (!fin) {
+ return false;
+ }
+ FileHandleT fileHandle;
+
+ std::string line;
+ while (std::getline(fin, line)) {
+ // Check if this an empty or a comment line
+ if (line.empty() || line.front() == '#') {
+ continue;
+ }
+ // Drop carriage return character at the end
+ if (line.back() == '\r') {
+ line.pop_back();
+ if (line.empty()) {
+ continue;
+ }
+ }
+ // Check if this a file name line
+ if (line.front() != ' ') {
+ fileHandle = GetOrInsert(line).first;
+ continue;
+ }
+
+ // Bad line or bad file handle
+ if (!fileHandle || (line.size() < 6)) {
+ continue;
+ }
+
+ constexpr std::size_t offset = 5;
+ if (cmHasLiteralPrefix(line, " mmc:")) {
+ fileHandle->Moc.Macro = line.substr(offset);
+ continue;
+ }
+ if (cmHasLiteralPrefix(line, " miu:")) {
+ fileHandle->Moc.Include.Underscore.emplace_back(line.substr(offset),
+ MocUnderscoreLength);
+ continue;
+ }
+ if (cmHasLiteralPrefix(line, " mid:")) {
+ fileHandle->Moc.Include.Dot.emplace_back(line.substr(offset), 0);
+ continue;
+ }
+ if (cmHasLiteralPrefix(line, " mdp:")) {
+ fileHandle->Moc.Depends.emplace_back(line.substr(offset));
+ continue;
+ }
+ if (cmHasLiteralPrefix(line, " uic:")) {
+ fileHandle->Uic.Include.emplace_back(line.substr(offset),
+ UiUnderscoreLength);
+ continue;
+ }
+ if (cmHasLiteralPrefix(line, " udp:")) {
+ fileHandle->Uic.Depends.emplace_back(line.substr(offset));
+ continue;
+ }
+ }
+ return true;
+}
+
+bool cmQtAutoMocUicT::ParseCacheT::WriteToFile(std::string const& fileName)
+{
+ cmGeneratedFileStream ofs(fileName);
+ if (!ofs) {
+ return false;
+ }
+ ofs << "# Generated by CMake. Changes will be overwritten." << std::endl;
+ for (auto const& pair : Map_) {
+ ofs << pair.first << std::endl;
+ FileT const& file = *pair.second;
+ if (!file.Moc.Macro.empty()) {
+ ofs << " mmc:" << file.Moc.Macro << std::endl;
+ }
+ for (IncludeKeyT const& item : file.Moc.Include.Underscore) {
+ ofs << " miu:" << item.Key << std::endl;
+ }
+ for (IncludeKeyT const& item : file.Moc.Include.Dot) {
+ ofs << " mid:" << item.Key << std::endl;
+ }
+ for (std::string const& item : file.Moc.Depends) {
+ ofs << " mdp:" << item << std::endl;
+ }
+ for (IncludeKeyT const& item : file.Uic.Include) {
+ ofs << " uic:" << item.Key << std::endl;
+ }
+ for (std::string const& item : file.Uic.Depends) {
+ ofs << " udp:" << item << std::endl;
+ }
+ }
+ return ofs.Close();
+}
+
+cmQtAutoMocUicT::BaseSettingsT::BaseSettingsT() = default;
+cmQtAutoMocUicT::BaseSettingsT::~BaseSettingsT() = default;
+
+cmQtAutoMocUicT::MocSettingsT::MocSettingsT()
+{
+ RegExpInclude.compile(
+ "(^|\n)[ \t]*#[ \t]*include[ \t]+"
+ "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
+}
+
+cmQtAutoMocUicT::MocSettingsT::~MocSettingsT() = default;
+
+bool cmQtAutoMocUicT::MocSettingsT::skipped(std::string const& fileName) const
+{
+ return (!Enabled || (SkipList.find(fileName) != SkipList.end()));
+}
+
+std::string cmQtAutoMocUicT::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;
+}
+
+cmQtAutoMocUicT::UicSettingsT::UicSettingsT()
+{
+ RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+"
+ "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
+}
+
+cmQtAutoMocUicT::UicSettingsT::~UicSettingsT() = default;
+
+bool cmQtAutoMocUicT::UicSettingsT::skipped(std::string const& fileName) const
+{
+ return (!Enabled || (SkipList.find(fileName) != SkipList.end()));
+}
+
+void cmQtAutoMocUicT::JobT::LogError(GenT genType,
+ cm::string_view message) const
+{
+ Gen()->AbortError();
+ Gen()->Log().Error(genType, message);
+}
+
+void cmQtAutoMocUicT::JobT::LogCommandError(
+ GenT genType, cm::string_view message,
+ std::vector<std::string> const& command, std::string const& output) const
+{
+ Gen()->AbortError();
+ Gen()->Log().ErrorCommand(genType, message, command, output);
+}
+
+bool cmQtAutoMocUicT::JobT::RunProcess(GenT genType,
+ cmWorkerPool::ProcessResultT& result,
+ std::vector<std::string> const& command,
+ std::string* infoMessage)
+{
+ // Log command
+ if (Log().Verbose()) {
+ cm::string_view info;
+ if (infoMessage != nullptr) {
+ info = *infoMessage;
+ }
+ Log().Info(genType,
+ cmStrCat(info,
+ info.empty() || cmHasSuffix(info, '\n') ? "" : "\n",
+ QuotedCommand(command), '\n'));
+ }
+ // Run command
+ return cmWorkerPool::JobT::RunProcess(result, command,
+ BaseConst().AutogenBuildDir);
+}
+
+void cmQtAutoMocUicT::JobMocPredefsT::Process()
+{
+ // (Re)generate moc_predefs.h on demand
+ std::unique_ptr<std::string> reason;
+ if (Log().Verbose()) {
+ reason = cm::make_unique<std::string>();
+ }
+ if (!Update(reason.get())) {
+ return;
+ }
+ std::string const& predefsFileAbs = MocConst().PredefsFileAbs;
+ {
+ cmWorkerPool::ProcessResultT result;
+ {
+ // Compose command
+ std::vector<std::string> cmd = MocConst().PredefsCmd;
+ // Add definitions
+ cmAppend(cmd, MocConst().OptionsDefinitions);
+ // Add includes
+ cmAppend(cmd, MocConst().OptionsIncludes);
+ // Execute command
+ if (!RunProcess(GenT::MOC, result, cmd, reason.get())) {
+ LogCommandError(GenT::MOC,
+ cmStrCat("The content generation command for ",
+ MessagePath(predefsFileAbs), " failed.\n",
+ result.ErrorMessage),
+ cmd, result.StdOut);
+ return;
+ }
+ }
+
+ // (Re)write predefs file only on demand
+ if (cmQtAutoGenerator::FileDiffers(predefsFileAbs, result.StdOut)) {
+ if (!cmQtAutoGenerator::FileWrite(predefsFileAbs, result.StdOut)) {
+ LogError(
+ GenT::MOC,
+ cmStrCat("Writing ", MessagePath(predefsFileAbs), " failed."));
+ return;
+ }
+ } else {
+ // Touch to update the time stamp
+ if (Log().Verbose()) {
+ Log().Info(GenT::MOC, "Touching " + MessagePath(predefsFileAbs));
+ }
+ if (!cmSystemTools::Touch(predefsFileAbs, false)) {
+ LogError(
+ GenT::MOC,
+ cmStrCat("Touching ", MessagePath(predefsFileAbs), " failed."));
+ return;
+ }
+ }
+ }
+
+ // Read file time afterwards
+ if (!MocEval().PredefsTime.Load(predefsFileAbs)) {
+ LogError(GenT::MOC,
+ cmStrCat("Reading the file time of ", MessagePath(predefsFileAbs),
+ " failed."));
+ return;
+ }
+}
+
+bool cmQtAutoMocUicT::JobMocPredefsT::Update(std::string* reason) const
+{
+ // Test if the file exists
+ if (!MocEval().PredefsTime.Load(MocConst().PredefsFileAbs)) {
+ if (reason != nullptr) {
+ *reason = cmStrCat("Generating ", MessagePath(MocConst().PredefsFileAbs),
+ ", because it doesn't exist.");
+ }
+ return true;
+ }
+
+ // Test if the settings changed
+ if (MocConst().SettingsChanged) {
+ if (reason != nullptr) {
+ *reason = cmStrCat("Generating ", MessagePath(MocConst().PredefsFileAbs),
+ ", because the moc settings changed.");
+ }
+ return true;
+ }
+
+ // Test if the executable is newer
+ {
+ std::string const& exec = MocConst().PredefsCmd.at(0);
+ cmFileTime execTime;
+ if (execTime.Load(exec)) {
+ if (MocEval().PredefsTime.Older(execTime)) {
+ if (reason != nullptr) {
+ *reason =
+ cmStrCat("Generating ", MessagePath(MocConst().PredefsFileAbs),
+ " because it is older than ", MessagePath(exec), '.');
+ }
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool cmQtAutoMocUicT::JobParseT::ReadFile()
+{
+ // Clear old parse information
+ FileHandle->ParseData->Clear();
+ std::string const& fileName = FileHandle->FileName;
+ // Write info
+ if (Log().Verbose()) {
+ Log().Info(GenT::GEN, cmStrCat("Parsing ", MessagePath(fileName)));
+ }
+ // Read file content
+ {
+ std::string error;
+ if (!cmQtAutoGenerator::FileRead(Content, fileName, &error)) {
+ LogError(
+ GenT::GEN,
+ cmStrCat("Could not read ", MessagePath(fileName), ".\n", error));
+ return false;
+ }
+ }
+ // Warn if empty
+ if (Content.empty()) {
+ Log().Warning(GenT::GEN, cmStrCat(MessagePath(fileName), " is empty."));
+ return false;
+ }
+ return true;
+}
+
+void cmQtAutoMocUicT::JobParseT::CreateKeys(
+ std::vector<IncludeKeyT>& container, std::set<std::string> const& source,
+ std::size_t basePrefixLength)
+{
+ if (source.empty()) {
+ return;
+ }
+ container.reserve(source.size());
+ for (std::string const& src : source) {
+ container.emplace_back(src, basePrefixLength);
+ }
+}
+
+void cmQtAutoMocUicT::JobParseT::MocMacro()
+{
+ for (KeyExpT const& filter : MocConst().MacroFilters) {
+ // Run a simple find string check
+ if (Content.find(filter.Key) == std::string::npos) {
+ continue;
+ }
+ // Run the expensive regular expression check loop
+ cmsys::RegularExpressionMatch match;
+ if (filter.Exp.find(Content.c_str(), match)) {
+ // Keep detected macro name
+ FileHandle->ParseData->Moc.Macro = filter.Key;
+ return;
+ }
+ }
+}
+
+void cmQtAutoMocUicT::JobParseT::MocDependecies()
+{
+ if (MocConst().DependFilters.empty()) {
+ return;
+ }
+
+ // Find dependency strings
+ std::set<std::string> parseDepends;
+ for (KeyExpT const& filter : MocConst().DependFilters) {
+ // Run a simple find string check
+ if (Content.find(filter.Key) == std::string::npos) {
+ continue;
+ }
+ // 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()) {
+ parseDepends.emplace(std::move(dep));
+ }
+ }
+ contentChars += match.end();
+ }
+ }
+
+ // Store dependency strings
+ {
+ auto& Depends = FileHandle->ParseData->Moc.Depends;
+ Depends.reserve(parseDepends.size());
+ for (std::string const& item : parseDepends) {
+ Depends.emplace_back(item);
+ // Replace end of line characters in filenames
+ std::string& path = Depends.back();
+ std::replace(path.begin(), path.end(), '\n', ' ');
+ std::replace(path.begin(), path.end(), '\r', ' ');
+ }
+ }
+}
+
+void cmQtAutoMocUicT::JobParseT::MocIncludes()
+{
+ if (Content.find("moc") == std::string::npos) {
+ return;
+ }
+
+ std::set<std::string> underscore;
+ std::set<std::string> dot;
+ {
+ const char* contentChars = Content.c_str();
+ cmsys::RegularExpression const& regExp = MocConst().RegExpInclude;
+ cmsys::RegularExpressionMatch match;
+ while (regExp.find(contentChars, match)) {
+ std::string incString = match.match(2);
+ std::string const incBase =
+ cmSystemTools::GetFilenameWithoutLastExtension(incString);
+ if (cmHasLiteralPrefix(incBase, "moc_")) {
+ // moc_<BASE>.cpp
+ // Remove the moc_ part from the base name
+ underscore.emplace(std::move(incString));
+ } else {
+ // <BASE>.moc
+ dot.emplace(std::move(incString));
+ }
+ // Forward content pointer
+ contentChars += match.end();
+ }
+ }
+ auto& Include = FileHandle->ParseData->Moc.Include;
+ CreateKeys(Include.Underscore, underscore, MocUnderscoreLength);
+ CreateKeys(Include.Dot, dot, 0);
+}
+
+void cmQtAutoMocUicT::JobParseT::UicIncludes()
+{
+ if (Content.find("ui_") == std::string::npos) {
+ return;
+ }
+
+ std::set<std::string> includes;
+ {
+ const char* contentChars = Content.c_str();
+ cmsys::RegularExpression const& regExp = UicConst().RegExpInclude;
+ cmsys::RegularExpressionMatch match;
+ while (regExp.find(contentChars, match)) {
+ includes.emplace(match.match(2));
+ // Forward content pointer
+ contentChars += match.end();
+ }
+ }
+ CreateKeys(FileHandle->ParseData->Uic.Include, includes, UiUnderscoreLength);
+}
+
+void cmQtAutoMocUicT::JobParseHeaderT::Process()
+{
+ if (!ReadFile()) {
+ return;
+ }
+ // Moc parsing
+ if (FileHandle->Moc) {
+ MocMacro();
+ MocDependecies();
+ }
+ // Uic parsing
+ if (FileHandle->Uic) {
+ UicIncludes();
+ }
+}
+
+void cmQtAutoMocUicT::JobParseSourceT::Process()
+{
+ if (!ReadFile()) {
+ return;
+ }
+ // Moc parsing
+ if (FileHandle->Moc) {
+ MocMacro();
+ MocDependecies();
+ MocIncludes();
+ }
+ // Uic parsing
+ if (FileHandle->Uic) {
+ UicIncludes();
+ }
+}
+
+std::string cmQtAutoMocUicT::JobEvalCacheT::MessageSearchLocations() const
+{
+ std::string res;
+ res.reserve(512);
+ for (std::string const& path : SearchLocations) {
+ res += " ";
+ res += MessagePath(path);
+ res += '\n';
+ }
+ return res;
+}
+
+void cmQtAutoMocUicT::JobEvalCacheMocT::Process()
+{
+ // Evaluate headers
+ for (auto const& pair : BaseEval().Headers) {
+ if (!EvalHeader(pair.second)) {
+ return;
+ }
+ }
+ // Evaluate sources
+ for (auto const& pair : BaseEval().Sources) {
+ if (!EvalSource(pair.second)) {
+ return;
+ }
+ }
+}
+
+bool cmQtAutoMocUicT::JobEvalCacheMocT::EvalHeader(SourceFileHandleT source)
+{
+ SourceFileT const& sourceFile = *source;
+ auto const& parseData = sourceFile.ParseData->Moc;
+ if (!source->Moc) {
+ return true;
+ }
+
+ if (!parseData.Macro.empty()) {
+ // Create a new mapping
+ MappingHandleT handle = std::make_shared<MappingT>();
+ handle->SourceFile = std::move(source);
+
+ // Absolute build path
+ if (BaseConst().MultiConfig) {
+ handle->OutputFile = Gen()->AbsoluteIncludePath(sourceFile.BuildPath);
+ } else {
+ handle->OutputFile = Gen()->AbsoluteBuildPath(sourceFile.BuildPath);
+ }
+
+ // Register mapping in headers map
+ RegisterMapping(handle);
+ }
+
+ return true;
+}
+
+bool cmQtAutoMocUicT::JobEvalCacheMocT::EvalSource(
+ SourceFileHandleT const& source)
+{
+ SourceFileT const& sourceFile = *source;
+ auto const& parseData = sourceFile.ParseData->Moc;
+ if (!sourceFile.Moc ||
+ (parseData.Macro.empty() && parseData.Include.Underscore.empty() &&
+ parseData.Include.Dot.empty())) {
+ return true;
+ }
+
+ std::string const sourceDirPrefix = SubDirPrefix(sourceFile.FileName);
+ std::string const sourceBase =
+ cmSystemTools::GetFilenameWithoutLastExtension(sourceFile.FileName);
+
+ // For relaxed mode check if the own "moc_" or ".moc" file is included
+ bool const relaxedMode = MocConst().RelaxedMode;
+ bool sourceIncludesMocUnderscore = false;
+ bool sourceIncludesDotMoc = false;
+ // Check if the sources own "moc_" or ".moc" file is included
+ if (relaxedMode) {
+ for (IncludeKeyT const& incKey : parseData.Include.Underscore) {
+ if (incKey.Base == sourceBase) {
+ sourceIncludesMocUnderscore = true;
+ break;
+ }
+ }
+ }
+ for (IncludeKeyT const& incKey : parseData.Include.Dot) {
+ if (incKey.Base == sourceBase) {
+ sourceIncludesDotMoc = true;
+ break;
+ }
+ }
+
+ // Check if this source needs to be moc processed but doesn't.
+ if (!sourceIncludesDotMoc && !parseData.Macro.empty() &&
+ !(relaxedMode && sourceIncludesMocUnderscore)) {
+ LogError(GenT::MOC,
+ cmStrCat(MessagePath(sourceFile.FileName), "\ncontains a ",
+ Quoted(parseData.Macro), " macro, but does not include ",
+ MessagePath(sourceBase + ".moc"),
+ "!\nConsider to\n - add #include \"", sourceBase,
+ ".moc\"\n - enable SKIP_AUTOMOC for this file"));
+ return false;
+ }
+
+ // Evaluate "moc_" includes
+ for (IncludeKeyT const& incKey : parseData.Include.Underscore) {
+ SourceFileHandleT headerHandle;
+ {
+ std::string const headerBase = cmStrCat(incKey.Dir, incKey.Base);
+ if (!FindIncludedHeader(headerHandle, sourceDirPrefix, headerBase)) {
+ LogError(GenT::MOC,
+ cmStrCat(MessagePath(sourceFile.FileName),
+ "\nincludes the moc file ", MessagePath(incKey.Key),
+ ",\nbut a header ", MessageHeader(headerBase),
+ "\ncould not be found "
+ "in the following directories\n",
+ MessageSearchLocations()));
+ return false;
+ }
+ }
+ // The include might be handled differently in relaxed mode
+ if (relaxedMode && !sourceIncludesDotMoc && !parseData.Macro.empty() &&
+ (incKey.Base == sourceBase)) {
+ // The <BASE>.cpp file includes a Qt macro but does not include the
+ // <BASE>.moc file. In this case, the moc_<BASE>.cpp should probably
+ // be generated from <BASE>.cpp instead of <BASE>.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.
+
+ // Issue a warning
+ Log().Warning(
+ GenT::MOC,
+ cmStrCat(MessagePath(sourceFile.FileName), "\ncontains a ",
+ Quoted(parseData.Macro), " macro, but does not include ",
+ MessagePath(sourceBase + ".moc"), ".\nInstead it includes ",
+ MessagePath(incKey.Key), ".\nRunning moc on the source\n ",
+ MessagePath(sourceFile.FileName), "!\nBetter include ",
+ MessagePath(sourceBase + ".moc"),
+ " for compatibility with regular mode.\n",
+ "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));
+
+ // Create mapping
+ if (!RegisterIncluded(incKey.Key, source, source)) {
+ return false;
+ }
+ continue;
+ }
+
+ // Check if header is skipped
+ if (MocConst().skipped(headerHandle->FileName)) {
+ continue;
+ }
+ // Create mapping
+ if (!RegisterIncluded(incKey.Key, source, std::move(headerHandle))) {
+ return false;
+ }
+ }
+
+ // Evaluate ".moc" includes
+ if (relaxedMode) {
+ // Relaxed mode
+ for (IncludeKeyT const& incKey : parseData.Include.Dot) {
+ // Check if this is the sources own .moc file
+ bool const ownMoc = (incKey.Base == sourceBase);
+ if (ownMoc && !parseData.Macro.empty()) {
+ // Create mapping for the regular use case
+ if (!RegisterIncluded(incKey.Key, source, source)) {
+ return false;
+ }
+ continue;
+ }
+ // Try to find a header instead but issue a warning.
+ // This is for KDE4 compatibility.
+ SourceFileHandleT headerHandle;
+ {
+ std::string const headerBase = cmStrCat(incKey.Dir, incKey.Base);
+ if (!FindIncludedHeader(headerHandle, sourceDirPrefix, headerBase)) {
+ LogError(
+ GenT::MOC,
+ cmStrCat(
+ MessagePath(sourceFile.FileName), "\nincludes the moc file ",
+ MessagePath(incKey.Key),
+ ",\nwhich seems to be the moc file from a different source "
+ "file.\nCMAKE_AUTOMOC_RELAXED_MODE:\nAlso a matching header ",
+ MessageHeader(headerBase),
+ "\ncould not be found in the following directories\n",
+ MessageSearchLocations()));
+ return false;
+ }
+ }
+ // Check if header is skipped
+ if (MocConst().skipped(headerHandle->FileName)) {
+ continue;
+ }
+ // Issue a warning
+ if (ownMoc && parseData.Macro.empty()) {
+ Log().Warning(
+ GenT::MOC,
+ cmStrCat(MessagePath(sourceFile.FileName),
+ "\nincludes the moc file ", MessagePath(incKey.Key),
+ ", but does not contain a\n", MocConst().MacrosString(),
+ " macro.\nRunning moc on the header\n ",
+ MessagePath(headerHandle->FileName), "!\nBetter include ",
+ MessagePath("moc_" + incKey.Base + ".cpp"),
+ " for a compatibility with regular mode.\n",
+ "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));
+ } else {
+ Log().Warning(
+ GenT::MOC,
+ cmStrCat(MessagePath(sourceFile.FileName),
+ "\nincludes the moc file ", MessagePath(incKey.Key),
+ " instead of ", MessagePath("moc_" + incKey.Base + ".cpp"),
+ ".\nRunning moc on the header\n ",
+ MessagePath(headerHandle->FileName), "!\nBetter include ",
+ MessagePath("moc_" + incKey.Base + ".cpp"),
+ " for compatibility with regular mode.\n",
+ "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));
+ }
+ // Create mapping
+ if (!RegisterIncluded(incKey.Key, source, std::move(headerHandle))) {
+ return false;
+ }
+ }
+ } else {
+ // Strict mode
+ for (IncludeKeyT const& incKey : parseData.Include.Dot) {
+ // Check if this is the sources own .moc file
+ bool const ownMoc = (incKey.Base == sourceBase);
+ if (!ownMoc) {
+ // Don't allow <BASE>.moc include other than own in regular mode
+ LogError(GenT::MOC,
+ cmStrCat(MessagePath(sourceFile.FileName),
+ "\nincludes the moc file ", MessagePath(incKey.Key),
+ ",\nwhich seems to be the moc file from a different "
+ "source file.\nThis is not supported. Include ",
+ MessagePath(sourceBase + ".moc"),
+ " to run moc on this source file."));
+ return false;
+ }
+ // Accept but issue a warning if moc isn't required
+ if (parseData.Macro.empty()) {
+ Log().Warning(GenT::MOC,
+ cmStrCat(MessagePath(sourceFile.FileName),
+ "\nincludes the moc file ",
+ MessagePath(incKey.Key),
+ ", but does not contain a ",
+ MocConst().MacrosString(), " macro."));
+ }
+ // Create mapping
+ if (!RegisterIncluded(incKey.Key, source, source)) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool cmQtAutoMocUicT::JobEvalCacheMocT::FindIncludedHeader(
+ SourceFileHandleT& headerHandle, cm::string_view includerDir,
+ cm::string_view includeBase)
+{
+ // Clear search locations
+ SearchLocations.clear();
+
+ auto findHeader = [this,
+ &headerHandle](std::string const& basePath) -> bool {
+ bool found = false;
+ for (std::string const& ext : this->BaseConst().HeaderExtensions) {
+ std::string const testPath =
+ this->Gen()->CollapseFullPathTS(cmStrCat(basePath, '.', ext));
+ cmFileTime fileTime;
+ if (!fileTime.Load(testPath)) {
+ // File not found
+ continue;
+ }
+
+ // Return a known file if it exists already
+ {
+ auto it = BaseEval().Headers.find(testPath);
+ if (it != BaseEval().Headers.end()) {
+ headerHandle = it->second;
+ found = true;
+ break;
+ }
+ }
+
+ // Created and return discovered file entry
+ {
+ SourceFileHandleT& handle = MocEval().HeadersDiscovered[testPath];
+ if (!handle) {
+ handle = std::make_shared<SourceFileT>(testPath);
+ handle->FileTime = fileTime;
+ handle->IsHeader = true;
+ handle->Moc = true;
+ }
+ headerHandle = handle;
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ this->SearchLocations.emplace_back(cmQtAutoGen::ParentDir(basePath));
+ }
+ return found;
+ };
+
+ // Search in vicinity of the source
+ if (findHeader(cmStrCat(includerDir, includeBase))) {
+ return true;
+ }
+ // Search in include directories
+ for (std::string const& path : MocConst().IncludePaths) {
+ if (findHeader(cmStrCat(path, '/', includeBase))) {
+ return true;
+ }
+ }
+ // Return without success
+ return false;
+}
+
+bool cmQtAutoMocUicT::JobEvalCacheMocT::RegisterIncluded(
+ std::string const& includeString, SourceFileHandleT includerFileHandle,
+ SourceFileHandleT sourceFileHandle) const
+{
+ // Check if this file is already included
+ MappingHandleT& handle = MocEval().Includes[includeString];
+ if (handle) {
+ // Check if the output file would be generated from different source files
+ if (handle->SourceFile != sourceFileHandle) {
+ std::string files =
+ cmStrCat(" ", MessagePath(includerFileHandle->FileName), '\n');
+ for (auto const& item : handle->IncluderFiles) {
+ files += cmStrCat(" ", MessagePath(item->FileName), '\n');
+ }
+ LogError(
+ GenT::MOC,
+ cmStrCat("The source files\n", files,
+ "contain the same include string ",
+ MessagePath(includeString),
+ ", but\nthe moc file would be generated from different "
+ "source files\n ",
+ MessagePath(sourceFileHandle->FileName), " and\n ",
+ MessagePath(handle->SourceFile->FileName),
+ ".\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"));
+ return false;
+ }
+
+ // The same mapping already exists. Just add to the includers list.
+ handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
+ return true;
+ }
+
+ // Create a new mapping
+ handle = std::make_shared<MappingT>();
+ handle->IncludeString = includeString;
+ handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
+ handle->SourceFile = std::move(sourceFileHandle);
+ handle->OutputFile = Gen()->AbsoluteIncludePath(includeString);
+
+ // Register mapping in sources/headers map
+ RegisterMapping(handle);
+ return true;
+}
+
+void cmQtAutoMocUicT::JobEvalCacheMocT::RegisterMapping(
+ MappingHandleT mappingHandle) const
+{
+ auto& regMap = mappingHandle->SourceFile->IsHeader
+ ? MocEval().HeaderMappings
+ : MocEval().SourceMappings;
+ // Check if source file already gets mapped
+ auto& regHandle = regMap[mappingHandle->SourceFile->FileName];
+ if (!regHandle) {
+ // Yet unknown mapping
+ regHandle = std::move(mappingHandle);
+ } else {
+ // Mappings with include string override those without
+ if (!mappingHandle->IncludeString.empty()) {
+ regHandle = std::move(mappingHandle);
+ }
+ }
+}
+
+std::string cmQtAutoMocUicT::JobEvalCacheMocT::MessageHeader(
+ cm::string_view headerBase) const
+{
+ return MessagePath(cmStrCat(
+ headerBase, ".{", cmJoin(this->BaseConst().HeaderExtensions, ","), '}'));
+}
+
+void cmQtAutoMocUicT::JobEvalCacheUicT::Process()
+{
+ // Prepare buffers
+ SearchLocations.reserve((UicConst().SearchPaths.size() + 1) * 2);
+
+ // Evaluate headers
+ for (auto const& pair : BaseEval().Headers) {
+ if (!EvalFile(pair.second)) {
+ return;
+ }
+ }
+ // Evaluate sources
+ for (auto const& pair : BaseEval().Sources) {
+ if (!EvalFile(pair.second)) {
+ return;
+ }
+ }
+}
+
+bool cmQtAutoMocUicT::JobEvalCacheUicT::EvalFile(
+ SourceFileHandleT const& sourceFileHandle)
+{
+ SourceFileT const& sourceFile = *sourceFileHandle;
+ auto const& Include = sourceFile.ParseData->Uic.Include;
+ if (!sourceFile.Uic || Include.empty()) {
+ return true;
+ }
+
+ std::string const sourceDirPrefix = SubDirPrefix(sourceFile.FileName);
+ for (IncludeKeyT const& incKey : Include) {
+ // Find .ui file
+ UiName = cmStrCat(incKey.Base, ".ui");
+ if (!FindIncludedUi(sourceDirPrefix, incKey.Dir)) {
+ LogError(GenT::UIC,
+ cmStrCat(MessagePath(sourceFile.FileName),
+ "\nincludes the uic file ", MessagePath(incKey.Key),
+ ",\nbut the user interface file ", MessagePath(UiName),
+ "\ncould not be found in the following directories\n",
+ MessageSearchLocations()));
+ return false;
+ }
+ // Check if the file is skipped
+ if (UicConst().skipped(UiFileHandle->FileName)) {
+ continue;
+ }
+ // Register mapping
+ if (!RegisterMapping(incKey.Key, sourceFileHandle)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool cmQtAutoMocUicT::JobEvalCacheUicT::FindIncludedUi(
+ cm::string_view sourceDirPrefix, cm::string_view includePrefix)
+{
+ // Clear locations buffer
+ SearchLocations.clear();
+
+ auto findUi = [this](std::string const& testPath) -> bool {
+ std::string const fullPath = this->Gen()->CollapseFullPathTS(testPath);
+ cmFileTime fileTime;
+ if (!fileTime.Load(fullPath)) {
+ this->SearchLocations.emplace_back(cmQtAutoGen::ParentDir(fullPath));
+ return false;
+ }
+ // .ui file found in files system!
+ // Get or create .ui file handle
+ SourceFileHandleT& handle = this->UicEval().UiFiles[fullPath];
+ if (!handle) {
+ // The file wasn't registered, yet
+ handle = std::make_shared<SourceFileT>(fullPath);
+ handle->FileTime = fileTime;
+ }
+ this->UiFileHandle = handle;
+ return true;
+ };
+
+ // Vicinity of the source
+ if (findUi(cmStrCat(sourceDirPrefix, UiName))) {
+ return true;
+ }
+ if (!includePrefix.empty()) {
+ if (findUi(cmStrCat(sourceDirPrefix, includePrefix, UiName))) {
+ return true;
+ }
+ }
+ // Additional AUTOUIC search paths
+ auto const& searchPaths = UicConst().SearchPaths;
+ if (!searchPaths.empty()) {
+ for (std::string const& sPath : searchPaths) {
+ if (findUi(cmStrCat(sPath, '/', UiName))) {
+ return true;
+ }
+ }
+ if (!includePrefix.empty()) {
+ for (std::string const& sPath : searchPaths) {
+ if (findUi(cmStrCat(sPath, '/', includePrefix, UiName))) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+bool cmQtAutoMocUicT::JobEvalCacheUicT::RegisterMapping(
+ std::string const& includeString, SourceFileHandleT includerFileHandle)
+{
+ auto& Includes = Gen()->UicEval().Includes;
+ auto it = Includes.find(includeString);
+ if (it != Includes.end()) {
+ MappingHandleT const& handle = it->second;
+ if (handle->SourceFile != UiFileHandle) {
+ // The output file already gets generated - from a different .ui file!
+ std::string files =
+ cmStrCat(" ", MessagePath(includerFileHandle->FileName), '\n');
+ for (auto const& item : handle->IncluderFiles) {
+ files += cmStrCat(" ", MessagePath(item->FileName), '\n');
+ }
+ LogError(
+ GenT::UIC,
+ cmStrCat(
+ "The source files\n", files, "contain the same include string ",
+ Quoted(includeString),
+ ", but\nthe uic file would be generated from different "
+ "user interface files\n ",
+ MessagePath(UiFileHandle->FileName), " and\n ",
+ MessagePath(handle->SourceFile->FileName),
+ ".\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"));
+ return false;
+ }
+ // Add includer file to existing mapping
+ handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
+ } else {
+ // New mapping handle
+ MappingHandleT handle = std::make_shared<MappingT>();
+ handle->IncludeString = includeString;
+ handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
+ handle->SourceFile = UiFileHandle;
+ handle->OutputFile = Gen()->AbsoluteIncludePath(includeString);
+ // Register mapping
+ Includes.emplace(includeString, std::move(handle));
+ }
+ return true;
+}
+
+void cmQtAutoMocUicT::JobEvalCacheFinishT::Process()
+{
+ // Add discovered header parse jobs
+ Gen()->CreateParseJobs<JobParseHeaderT>(MocEval().HeadersDiscovered);
+
+ // Add dependency probing jobs
+ {
+ // Add fence job to ensure all parsing has finished
+ Gen()->WorkerPool().EmplaceJob<JobFenceT>();
+ if (MocConst().Enabled) {
+ Gen()->WorkerPool().EmplaceJob<JobProbeDepsMocT>();
+ }
+ if (UicConst().Enabled) {
+ Gen()->WorkerPool().EmplaceJob<JobProbeDepsUicT>();
+ }
+ // Add probe finish job
+ Gen()->WorkerPool().EmplaceJob<JobProbeDepsFinishT>();
+ }
+}
+
+void cmQtAutoMocUicT::JobProbeDepsMocT::Process()
+{
+ // Create moc header jobs
+ for (auto const& pair : MocEval().HeaderMappings) {
+ // Register if this mapping is a candidate for mocs_compilation.cpp
+ bool const compFile = pair.second->IncludeString.empty();
+ if (compFile) {
+ MocEval().CompFiles.emplace_back(pair.second->SourceFile->BuildPath);
+ }
+ if (!Generate(pair.second, compFile)) {
+ return;
+ }
+ }
+
+ // Create moc source jobs
+ for (auto const& pair : MocEval().SourceMappings) {
+ if (!Generate(pair.second, false)) {
+ return;
+ }
+ }
+}
+
+bool cmQtAutoMocUicT::JobProbeDepsMocT::Generate(MappingHandleT const& mapping,
+ bool compFile) const
+{
+ std::unique_ptr<std::string> reason;
+ if (Log().Verbose()) {
+ reason = cm::make_unique<std::string>();
+ }
+ if (Probe(*mapping, reason.get())) {
+ // Register the parent directory for creation
+ MocEval().OutputDirs.emplace(cmQtAutoGen::ParentDir(mapping->OutputFile));
+ // Add moc job
+ Gen()->WorkerPool().EmplaceJob<JobCompileMocT>(mapping, std::move(reason));
+ // Check if a moc job for a mocs_compilation.cpp entry was generated
+ if (compFile) {
+ MocEval().CompUpdated = true;
+ }
+ }
+ return true;
+}
+
+bool cmQtAutoMocUicT::JobProbeDepsMocT::Probe(MappingT const& mapping,
+ std::string* reason) const
+{
+ std::string const& sourceFile = mapping.SourceFile->FileName;
+ std::string const& outputFile = mapping.OutputFile;
+
+ // Test if the output file exists
+ cmFileTime outputFileTime;
+ if (!outputFileTime.Load(outputFile)) {
+ if (reason != nullptr) {
+ *reason =
+ cmStrCat("Generating ", MessagePath(outputFile),
+ ", because it doesn't exist, from ", MessagePath(sourceFile));
+ }
+ return true;
+ }
+
+ // Test if any setting changed
+ if (MocConst().SettingsChanged) {
+ if (reason != nullptr) {
+ *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ ", because the uic settings changed, from ",
+ MessagePath(sourceFile));
+ }
+ return true;
+ }
+
+ // Test if the source file is newer
+ if (outputFileTime.Older(mapping.SourceFile->FileTime)) {
+ if (reason != nullptr) {
+ *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ ", because it's older than its source file, from ",
+ MessagePath(sourceFile));
+ }
+ return true;
+ }
+
+ // Test if the moc_predefs file is newer
+ if (!MocConst().PredefsFileAbs.empty()) {
+ if (outputFileTime.Older(MocEval().PredefsTime)) {
+ if (reason != nullptr) {
+ *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ ", because it's older than ",
+ MessagePath(MocConst().PredefsFileAbs), ", from ",
+ MessagePath(sourceFile));
+ }
+ return true;
+ }
+ }
+
+ // Test if the moc executable is newer
+ if (outputFileTime.Older(MocConst().ExecutableTime)) {
+ if (reason != nullptr) {
+ *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ ", because it's older than the moc executable, from ",
+ MessagePath(sourceFile));
+ }
+ return true;
+ }
+
+ // Test if a dependency file is newer
+ {
+ // Check dependency timestamps
+ std::string const sourceDir = SubDirPrefix(sourceFile);
+ for (std::string const& dep : mapping.SourceFile->ParseData->Moc.Depends) {
+ // Find dependency file
+ auto const depMatch = FindDependency(sourceDir, dep);
+ if (depMatch.first.empty()) {
+ Log().Warning(GenT::MOC,
+ cmStrCat(MessagePath(sourceFile), " depends on ",
+ MessagePath(dep),
+ " but the file does not exist."));
+ continue;
+ }
+ // Test if dependency file is older
+ if (outputFileTime.Older(depMatch.second)) {
+ if (reason != nullptr) {
+ *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ ", because it's older than its dependency file ",
+ MessagePath(depMatch.first), ", from ",
+ MessagePath(sourceFile));
+ }
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+std::pair<std::string, cmFileTime>
+cmQtAutoMocUicT::JobProbeDepsMocT::FindDependency(
+ std::string const& sourceDir, std::string const& includeString) const
+{
+ using ResPair = std::pair<std::string, cmFileTime>;
+ // Search in vicinity of the source
+ {
+ ResPair res{ sourceDir + includeString, {} };
+ if (res.second.Load(res.first)) {
+ return res;
+ }
+ }
+ // Search in include directories
+ for (std::string const& includePath : MocConst().IncludePaths) {
+ ResPair res{ cmStrCat(includePath, '/', includeString), {} };
+ if (res.second.Load(res.first)) {
+ return res;
+ }
+ }
+ // Return empty
+ return ResPair();
+}
+
+void cmQtAutoMocUicT::JobProbeDepsUicT::Process()
+{
+ for (auto const& pair : Gen()->UicEval().Includes) {
+ MappingHandleT const& mapping = pair.second;
+ std::unique_ptr<std::string> reason;
+ if (Log().Verbose()) {
+ reason = cm::make_unique<std::string>();
+ }
+ if (!Probe(*mapping, reason.get())) {
+ continue;
+ }
+
+ // Register the parent directory for creation
+ UicEval().OutputDirs.emplace(cmQtAutoGen::ParentDir(mapping->OutputFile));
+ // Add uic job
+ Gen()->WorkerPool().EmplaceJob<JobCompileUicT>(mapping, std::move(reason));
+ }
+}
+
+bool cmQtAutoMocUicT::JobProbeDepsUicT::Probe(MappingT const& mapping,
+ std::string* reason) const
+{
+ std::string const& sourceFile = mapping.SourceFile->FileName;
+ std::string const& outputFile = mapping.OutputFile;
+
+ // Test if the build file exists
+ cmFileTime outputFileTime;
+ if (!outputFileTime.Load(outputFile)) {
+ if (reason != nullptr) {
+ *reason =
+ cmStrCat("Generating ", MessagePath(outputFile),
+ ", because it doesn't exist, from ", MessagePath(sourceFile));
+ }
+ return true;
+ }
+
+ // Test if the uic settings changed
+ if (UicConst().SettingsChanged) {
+ if (reason != nullptr) {
+ *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ ", because the uic settings changed, from ",
+ MessagePath(sourceFile));
+ }
+ return true;
+ }
+
+ // Test if the source file is newer
+ if (outputFileTime.Older(mapping.SourceFile->FileTime)) {
+ if (reason != nullptr) {
+ *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ " because it's older than the source file ",
+ MessagePath(sourceFile));
+ }
+ return true;
+ }
+
+ // Test if the uic executable is newer
+ if (outputFileTime.Older(UicConst().ExecutableTime)) {
+ if (reason != nullptr) {
+ *reason = cmStrCat("Generating ", MessagePath(outputFile),
+ ", because it's older than the uic executable, from ",
+ MessagePath(sourceFile));
+ }
+ return true;
+ }
+
+ return false;
+}
+
+void cmQtAutoMocUicT::JobProbeDepsFinishT::Process()
+{
+ // Create output directories
+ {
+ using StringSet = std::unordered_set<std::string>;
+ auto createDirs = [this](GenT genType, StringSet const& dirSet) {
+ for (std::string const& dirName : dirSet) {
+ if (!cmSystemTools::MakeDirectory(dirName)) {
+ this->LogError(
+ genType,
+ cmStrCat("Creating directory ", MessagePath(dirName), " failed."));
+ return;
+ }
+ }
+ };
+ if (MocConst().Enabled && UicConst().Enabled) {
+ StringSet outputDirs = MocEval().OutputDirs;
+ outputDirs.insert(UicEval().OutputDirs.begin(),
+ UicEval().OutputDirs.end());
+ createDirs(GenT::GEN, outputDirs);
+ } else if (MocConst().Enabled) {
+ createDirs(GenT::MOC, MocEval().OutputDirs);
+ } else if (UicConst().Enabled) {
+ createDirs(GenT::UIC, UicEval().OutputDirs);
+ }
+ }
+
+ if (MocConst().Enabled) {
+ // Add mocs compilations job
+ Gen()->WorkerPool().EmplaceJob<JobMocsCompilationT>();
+ }
+
+ // Add finish job
+ Gen()->WorkerPool().EmplaceJob<JobFinishT>();
+}
+
+void cmQtAutoMocUicT::JobCompileMocT::Process()
+{
+ std::string const& sourceFile = Mapping->SourceFile->FileName;
+ std::string const& outputFile = Mapping->OutputFile;
+
+ // Compose moc command
+ std::vector<std::string> cmd;
+ {
+ // Reserve large enough
+ cmd.reserve(MocConst().OptionsDefinitions.size() +
+ MocConst().OptionsIncludes.size() +
+ MocConst().OptionsExtra.size() + 16);
+ cmd.push_back(MocConst().Executable);
+ // Add definitions
+ cmAppend(cmd, MocConst().OptionsDefinitions);
+ // Add includes
+ cmAppend(cmd, MocConst().OptionsIncludes);
+ // Add predefs include
+ if (!MocConst().PredefsFileAbs.empty()) {
+ cmd.emplace_back("--include");
+ cmd.push_back(MocConst().PredefsFileAbs);
+ }
+ // Add path prefix on demand
+ if (MocConst().PathPrefix && Mapping->SourceFile->IsHeader) {
+ for (std::string const& dir : MocConst().IncludePaths) {
+ cm::string_view prefix = sourceFile;
+ if (cmHasPrefix(prefix, dir)) {
+ prefix.remove_prefix(dir.size());
+ if (cmHasPrefix(prefix, '/')) {
+ prefix.remove_prefix(1);
+ auto slashPos = prefix.rfind('/');
+ if (slashPos != cm::string_view::npos) {
+ cmd.emplace_back("-p");
+ cmd.emplace_back(prefix.substr(0, slashPos));
+ } else {
+ cmd.emplace_back("-p");
+ cmd.emplace_back("./");
+ }
+ break;
+ }
+ }
+ }
+ }
+ // Add extra options
+ cmAppend(cmd, MocConst().OptionsExtra);
+ // Add output file
+ cmd.emplace_back("-o");
+ cmd.push_back(outputFile);
+ // Add source file
+ cmd.push_back(sourceFile);
+ }
+
+ // Execute moc command
+ cmWorkerPool::ProcessResultT result;
+ if (RunProcess(GenT::MOC, result, cmd, Reason.get())) {
+ // Moc command success. Print moc output.
+ if (!result.StdOut.empty()) {
+ Log().Info(GenT::MOC, result.StdOut);
+ }
+ } else {
+ // Moc command failed
+ std::string includers;
+ if (!Mapping->IncluderFiles.empty()) {
+ includers = "included by\n";
+ for (auto const& item : Mapping->IncluderFiles) {
+ includers += cmStrCat(" ", MessagePath(item->FileName), '\n');
+ }
+ }
+ LogCommandError(GenT::MOC,
+ cmStrCat("The moc process failed to compile\n ",
+ MessagePath(sourceFile), "\ninto\n ",
+ MessagePath(outputFile), '\n', includers,
+ result.ErrorMessage),
+ cmd, result.StdOut);
+ }
+}
+
+void cmQtAutoMocUicT::JobCompileUicT::Process()
+{
+ std::string const& sourceFile = Mapping->SourceFile->FileName;
+ std::string const& outputFile = Mapping->OutputFile;
+
+ // Compose uic command
+ std::vector<std::string> cmd;
+ cmd.push_back(UicConst().Executable);
+ {
+ std::vector<std::string> allOpts = UicConst().Options;
+ auto optionIt = UicConst().UiFiles.find(sourceFile);
+ if (optionIt != UicConst().UiFiles.end()) {
+ UicMergeOptions(allOpts, optionIt->second.Options,
+ (BaseConst().QtVersionMajor == 5));
+ }
+ cmAppend(cmd, allOpts);
+ }
+ cmd.emplace_back("-o");
+ cmd.emplace_back(outputFile);
+ cmd.emplace_back(sourceFile);
+
+ cmWorkerPool::ProcessResultT result;
+ if (RunProcess(GenT::UIC, result, cmd, Reason.get())) {
+ // Uic command success
+ // Print uic output
+ if (!result.StdOut.empty()) {
+ Log().Info(GenT::UIC, result.StdOut);
+ }
+ } else {
+ // Uic command failed
+ std::string includers;
+ for (auto const& item : Mapping->IncluderFiles) {
+ includers += cmStrCat(" ", MessagePath(item->FileName), '\n');
+ }
+ LogCommandError(GenT::UIC,
+ cmStrCat("The uic process failed to compile\n ",
+ MessagePath(sourceFile), "\ninto\n ",
+ MessagePath(outputFile), "\nincluded by\n",
+ includers, result.ErrorMessage),
+ cmd, result.StdOut);
+ }
+}
+
+void cmQtAutoMocUicT::JobMocsCompilationT::Process()
+{
+ // Compose mocs compilation file content
+ std::string content =
+ "// This file is autogenerated. Changes will be overwritten.\n";
+
+ if (MocEval().CompFiles.empty()) {
+ // Placeholder content
+ content += "// No files found that require moc or the moc files are "
+ "included\n"
+ "enum some_compilers { need_more_than_nothing };\n";
+ } else {
+ // Valid content
+ const bool mc = BaseConst().MultiConfig;
+ cm::string_view const wrapFront = mc ? "#include <" : "#include \"";
+ cm::string_view const wrapBack = mc ? ">\n" : "\"\n";
+ content += cmWrap(wrapFront, MocEval().CompFiles, wrapBack, "");
+ }
+
+ std::string const& compAbs = MocConst().CompFileAbs;
+ if (cmQtAutoGenerator::FileDiffers(compAbs, content)) {
+ // Actually write mocs compilation file
+ if (Log().Verbose()) {
+ Log().Info(GenT::MOC,
+ "Generating MOC compilation " + MessagePath(compAbs));
+ }
+ if (!FileWrite(compAbs, content)) {
+ LogError(GenT::MOC,
+ cmStrCat("Writing MOC compilation ", MessagePath(compAbs),
+ " failed."));
+ }
+ } else if (MocEval().CompUpdated) {
+ // Only touch mocs compilation file
+ if (Log().Verbose()) {
+ Log().Info(GenT::MOC,
+ "Touching MOC compilation " + MessagePath(compAbs));
+ }
+ if (!cmSystemTools::Touch(compAbs, false)) {
+ LogError(GenT::MOC,
+ cmStrCat("Touching MOC compilation ", MessagePath(compAbs),
+ " failed."));
+ }
+ }
+}
+
+void cmQtAutoMocUicT::JobFinishT::Process()
+{
+ Gen()->AbortSuccess();
+}
+
+cmQtAutoMocUicT::cmQtAutoMocUicT()
+ : cmQtAutoGenerator(GenT::GEN)
+{
+}
+cmQtAutoMocUicT::~cmQtAutoMocUicT() = default;
+
+bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
+{
+ // -- Required settings
+ if (!info.GetBool("MULTI_CONFIG", BaseConst_.MultiConfig, true) ||
+ !info.GetUInt("QT_VERSION_MAJOR", BaseConst_.QtVersionMajor, true) ||
+ !info.GetUInt("PARALLEL", BaseConst_.ThreadCount, false) ||
+ !info.GetString("BUILD_DIR", BaseConst_.AutogenBuildDir, true) ||
+ !info.GetStringConfig("INCLUDE_DIR", BaseConst_.AutogenIncludeDir,
+ true) ||
+ !info.GetString("CMAKE_EXECUTABLE", BaseConst_.CMakeExecutable, true) ||
+ !info.GetStringConfig("PARSE_CACHE_FILE", BaseConst_.ParseCacheFile,
+ true) ||
+ !info.GetStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
+ !info.GetArray("HEADER_EXTENSIONS", BaseConst_.HeaderExtensions, true) ||
+ !info.GetString("QT_MOC_EXECUTABLE", MocConst_.Executable, false) ||
+ !info.GetString("QT_UIC_EXECUTABLE", UicConst_.Executable, false)) {
+ return false;
+ }
+
+ // -- Checks
+ if (!BaseConst_.CMakeExecutableTime.Load(BaseConst_.CMakeExecutable)) {
+ return info.LogError(cmStrCat("The CMake executable ",
+ MessagePath(BaseConst_.CMakeExecutable),
+ " does not exist."));
+ }
+
+ // -- Evaluate values
+ BaseConst_.ThreadCount = std::min(BaseConst_.ThreadCount, ParallelMax);
+ WorkerPool_.SetThreadCount(BaseConst_.ThreadCount);
+
+ // -- Moc
+ if (!MocConst_.Executable.empty()) {
+ // -- Moc is enabled
+ MocConst_.Enabled = true;
+
+ // -- Temporary buffers
+ struct
+ {
+ std::vector<std::string> MacroNames;
+ std::vector<std::string> DependFilters;
+ } tmp;
+
+ // -- Required settings
+ if (!info.GetBool("MOC_RELAXED_MODE", MocConst_.RelaxedMode, false) ||
+ !info.GetBool("MOC_PATH_PREFIX", MocConst_.PathPrefix, true) ||
+ !info.GetArray("MOC_SKIP", MocConst_.SkipList, false) ||
+ !info.GetArrayConfig("MOC_DEFINITIONS", MocConst_.Definitions,
+ false) ||
+ !info.GetArrayConfig("MOC_INCLUDES", MocConst_.IncludePaths, false) ||
+ !info.GetArray("MOC_OPTIONS", MocConst_.OptionsExtra, false) ||
+ !info.GetStringConfig("MOC_COMPILATION_FILE", MocConst_.CompFileAbs,
+ true) ||
+ !info.GetArray("MOC_PREDEFS_CMD", MocConst_.PredefsCmd, false) ||
+ !info.GetStringConfig("MOC_PREDEFS_FILE", MocConst_.PredefsFileAbs,
+ !MocConst_.PredefsCmd.empty()) ||
+ !info.GetArray("MOC_MACRO_NAMES", tmp.MacroNames, true) ||
+ !info.GetArray("MOC_DEPEND_FILTERS", tmp.DependFilters, false)) {
+ return false;
+ }
+
+ // -- Evaluate settings
+ for (std::string const& item : tmp.MacroNames) {
+ MocConst_.MacroFilters.emplace_back(
+ item, ("[\n][ \t]*{?[ \t]*" + item).append("[^a-zA-Z0-9_]"));
+ }
+ // Dependency filters
+ {
+ Json::Value const& val = info.GetValue("MOC_DEPEND_FILTERS");
+ if (!val.isArray()) {
+ return info.LogError("MOC_DEPEND_FILTERS JSON value is not an array.");
+ }
+ Json::ArrayIndex const arraySize = val.size();
+ for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
+ // Test entry closure
+ auto testEntry = [&info, ii](bool test, cm::string_view msg) -> bool {
+ if (!test) {
+ info.LogError(
+ cmStrCat("MOC_DEPEND_FILTERS filter ", ii, ": ", msg));
+ }
+ return !test;
+ };
+
+ Json::Value const& pairVal = val[ii];
+
+ if (testEntry(pairVal.isArray(), "JSON value is not an array.") ||
+ testEntry(pairVal.size() == 2, "JSON array size invalid.")) {
+ return false;
+ }
+
+ Json::Value const& keyVal = pairVal[0u];
+ Json::Value const& expVal = pairVal[1u];
+ if (testEntry(keyVal.isString(),
+ "JSON value for keyword is not a string.") ||
+ testEntry(expVal.isString(),
+ "JSON value for regular expression is not a string.")) {
+ return false;
+ }
+
+ std::string const key = keyVal.asString();
+ std::string const exp = expVal.asString();
+ if (testEntry(!key.empty(), "Keyword is empty.") ||
+ testEntry(!exp.empty(), "Regular expression is empty.")) {
+ return false;
+ }
+
+ this->MocConst_.DependFilters.emplace_back(key, exp);
+ if (testEntry(
+ this->MocConst_.DependFilters.back().Exp.is_valid(),
+ cmStrCat("Regular expression compilation failed.\nKeyword: ",
+ Quoted(key), "\nExpression: ", Quoted(exp)))) {
+ return false;
+ }
+ }
+ }
+ // Check if moc executable exists (by reading the file time)
+ if (!MocConst_.ExecutableTime.Load(MocConst_.Executable)) {
+ return info.LogError(cmStrCat("The moc executable ",
+ MessagePath(MocConst_.Executable),
+ " does not exist."));
+ }
+ }
+
+ // -- Uic
+ if (!UicConst_.Executable.empty()) {
+ // Uic is enabled
+ UicConst_.Enabled = true;
+
+ // -- Required settings
+ if (!info.GetArray("UIC_SKIP", UicConst_.SkipList, false) ||
+ !info.GetArray("UIC_SEARCH_PATHS", UicConst_.SearchPaths, false) ||
+ !info.GetArrayConfig("UIC_OPTIONS", UicConst_.Options, false)) {
+ return false;
+ }
+ // .ui files
+ {
+ Json::Value const& val = info.GetValue("UIC_UI_FILES");
+ if (!val.isArray()) {
+ return info.LogError("UIC_UI_FILES JSON value is not an array.");
+ }
+ Json::ArrayIndex const arraySize = val.size();
+ for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
+ // Test entry closure
+ auto testEntry = [&info, ii](bool test, cm::string_view msg) -> bool {
+ if (!test) {
+ info.LogError(cmStrCat("UIC_UI_FILES entry ", ii, ": ", msg));
+ }
+ return !test;
+ };
+
+ Json::Value const& entry = val[ii];
+ if (testEntry(entry.isArray(), "JSON value is not an array.") ||
+ testEntry(entry.size() == 2, "JSON array size invalid.")) {
+ return false;
+ }
+
+ Json::Value const& entryName = entry[0u];
+ Json::Value const& entryOptions = entry[1u];
+ if (testEntry(entryName.isString(),
+ "JSON value for name is not a string.") ||
+ testEntry(entryOptions.isArray(),
+ "JSON value for options is not an array.")) {
+ return false;
+ }
+
+ auto& uiFile = UicConst_.UiFiles[entryName.asString()];
+ InfoT::GetJsonArray(uiFile.Options, entryOptions);
+ }
+ }
+
+ // -- Evaluate settings
+ // Check if uic executable exists (by reading the file time)
+ if (!UicConst_.ExecutableTime.Load(UicConst_.Executable)) {
+ return info.LogError(cmStrCat("The uic executable ",
+ MessagePath(UicConst_.Executable),
+ " does not exist."));
+ }
+ }
+
+ // -- Headers
+ {
+ Json::Value const& val = info.GetValue("HEADERS");
+ if (!val.isArray()) {
+ return info.LogError("HEADERS JSON value is not an array.");
+ }
+ Json::ArrayIndex const arraySize = val.size();
+ for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
+ // Test entry closure
+ auto testEntry = [&info, ii](bool test, cm::string_view msg) -> bool {
+ if (!test) {
+ info.LogError(cmStrCat("HEADERS entry ", ii, ": ", msg));
+ }
+ return !test;
+ };
+
+ Json::Value const& entry = val[ii];
+ if (testEntry(entry.isArray(), "JSON value is not an array.") ||
+ testEntry(entry.size() == 3, "JSON array size invalid.")) {
+ return false;
+ }
+
+ Json::Value const& entryName = entry[0u];
+ Json::Value const& entryFlags = entry[1u];
+ Json::Value const& entryBuild = entry[2u];
+ if (testEntry(entryName.isString(),
+ "JSON value for name is not a string.") ||
+ testEntry(entryFlags.isString(),
+ "JSON value for flags is not a string.") ||
+ testEntry(entryBuild.isString(),
+ "JSON value for build path is not a string.")) {
+ return false;
+ }
+
+ std::string name = entryName.asString();
+ std::string flags = entryFlags.asString();
+ std::string build = entryBuild.asString();
+ if (testEntry(flags.size() == 2, "Invalid flags string size")) {
+ return false;
+ }
+
+ cmFileTime fileTime;
+ if (!fileTime.Load(name)) {
+ return info.LogError(cmStrCat(
+ "The header file ", this->MessagePath(name), " does not exist."));
+ }
+
+ SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(name);
+ sourceHandle->FileTime = fileTime;
+ sourceHandle->IsHeader = true;
+ sourceHandle->Moc = (flags[0] == 'M');
+ sourceHandle->Uic = (flags[1] == 'U');
+ if (sourceHandle->Moc && MocConst().Enabled) {
+ if (build.empty()) {
+ return info.LogError(
+ cmStrCat("Header file ", ii, " build path is empty"));
+ }
+ sourceHandle->BuildPath = std::move(build);
+ }
+ BaseEval().Headers.emplace(std::move(name), std::move(sourceHandle));
+ }
+ }
+
+ // -- Sources
+ {
+ Json::Value const& val = info.GetValue("SOURCES");
+ if (!val.isArray()) {
+ return info.LogError("SOURCES JSON value is not an array.");
+ }
+ Json::ArrayIndex const arraySize = val.size();
+ for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
+ // Test entry closure
+ auto testEntry = [&info, ii](bool test, cm::string_view msg) -> bool {
+ if (!test) {
+ info.LogError(cmStrCat("SOURCES entry ", ii, ": ", msg));
+ }
+ return !test;
+ };
+
+ Json::Value const& entry = val[ii];
+ if (testEntry(entry.isArray(), "JSON value is not an array.") ||
+ testEntry(entry.size() == 2, "JSON array size invalid.")) {
+ return false;
+ }
+
+ Json::Value const& entryName = entry[0u];
+ Json::Value const& entryFlags = entry[1u];
+ if (testEntry(entryName.isString(),
+ "JSON value for name is not a string.") ||
+ testEntry(entryFlags.isString(),
+ "JSON value for flags is not a string.")) {
+ return false;
+ }
+
+ std::string name = entryName.asString();
+ std::string flags = entryFlags.asString();
+ if (testEntry(flags.size() == 2, "Invalid flags string size")) {
+ return false;
+ }
+
+ cmFileTime fileTime;
+ if (!fileTime.Load(name)) {
+ return info.LogError(cmStrCat(
+ "The source file ", this->MessagePath(name), " does not exist."));
+ }
+
+ SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(name);
+ sourceHandle->FileTime = fileTime;
+ sourceHandle->IsHeader = false;
+ sourceHandle->Moc = (flags[0] == 'M');
+ sourceHandle->Uic = (flags[1] == 'U');
+ BaseEval().Sources.emplace(std::move(name), std::move(sourceHandle));
+ }
+ }
+
+ // -- Init derived information
+ // Moc variables
+ if (MocConst().Enabled) {
+ // Compose moc includes list
+ {
+ // Compute framework paths
+ std::set<std::string> frameworkPaths;
+ for (std::string const& path : MocConst().IncludePaths) {
+ // 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);
+ frameworkPaths.emplace(cmSystemTools::JoinPath(
+ pathComponents.begin(), pathComponents.end() - 2));
+ }
+ }
+ // Reserve options
+ MocConst_.OptionsIncludes.reserve(MocConst().IncludePaths.size() +
+ frameworkPaths.size() * 2);
+ // Append includes
+ for (std::string const& path : MocConst().IncludePaths) {
+ MocConst_.OptionsIncludes.emplace_back("-I" + path);
+ }
+ // Append framework includes
+ for (std::string const& path : frameworkPaths) {
+ MocConst_.OptionsIncludes.emplace_back("-F");
+ MocConst_.OptionsIncludes.push_back(path);
+ }
+ }
+
+ // Compose moc definitions list
+ {
+ MocConst_.OptionsDefinitions.reserve(MocConst().Definitions.size());
+ for (std::string const& def : MocConst().Definitions) {
+ MocConst_.OptionsDefinitions.emplace_back("-D" + def);
+ }
+ }
+ }
+
+ return true;
+}
+
+template <class JOBTYPE>
+void cmQtAutoMocUicT::CreateParseJobs(SourceFileMapT const& sourceMap)
+{
+ cmFileTime const parseCacheTime = BaseEval().ParseCacheTime;
+ ParseCacheT& parseCache = BaseEval().ParseCache;
+ for (auto& src : sourceMap) {
+ // Get or create the file parse data reference
+ ParseCacheT::GetOrInsertT cacheEntry = parseCache.GetOrInsert(src.first);
+ src.second->ParseData = std::move(cacheEntry.first);
+ // Create a parse job if the cache file was missing or is older
+ if (cacheEntry.second || src.second->FileTime.Newer(parseCacheTime)) {
+ BaseEval().ParseCacheChanged = true;
+ WorkerPool().EmplaceJob<JOBTYPE>(src.second);
+ }
+ }
+}
+
+/** Concurrently callable implementation of cmSystemTools::CollapseFullPath */
+std::string cmQtAutoMocUicT::CollapseFullPathTS(std::string const& path) const
+{
+ std::lock_guard<std::mutex> guard(CMakeLibMutex_);
+ return cmSystemTools::CollapseFullPath(path, ProjectDirs().CurrentSource);
+}
+
+void cmQtAutoMocUicT::InitJobs()
+{
+ // Add moc_predefs.h job
+ if (MocConst().Enabled && !MocConst().PredefsCmd.empty()) {
+ WorkerPool().EmplaceJob<JobMocPredefsT>();
+ }
+
+ // Add header parse jobs
+ CreateParseJobs<JobParseHeaderT>(BaseEval().Headers);
+ // Add source parse jobs
+ CreateParseJobs<JobParseSourceT>(BaseEval().Sources);
+
+ // Add parse cache evaluations jobs
+ {
+ // Add a fence job to ensure all parsing has finished
+ WorkerPool().EmplaceJob<JobFenceT>();
+ if (MocConst().Enabled) {
+ WorkerPool().EmplaceJob<JobEvalCacheMocT>();
+ }
+ if (UicConst().Enabled) {
+ WorkerPool().EmplaceJob<JobEvalCacheUicT>();
+ }
+ // Add evaluate job
+ WorkerPool().EmplaceJob<JobEvalCacheFinishT>();
+ }
+}
+
+bool cmQtAutoMocUicT::Process()
+{
+ SettingsFileRead();
+ ParseCacheRead();
+ if (!CreateDirectories()) {
+ return false;
+ }
+ InitJobs();
+ if (!WorkerPool_.Process(this)) {
+ return false;
+ }
+ if (JobError_) {
+ return false;
+ }
+ if (!ParseCacheWrite()) {
+ return false;
+ }
+ if (!SettingsFileWrite()) {
+ return false;
+ }
+ return true;
+}
+
+void cmQtAutoMocUicT::SettingsFileRead()
+{
+ // Compose current settings strings
+ {
+ cmCryptoHash cryptoHash(cmCryptoHash::AlgoSHA256);
+ auto cha = [&cryptoHash](cm::string_view value) {
+ cryptoHash.Append(value);
+ cryptoHash.Append(";");
+ };
+
+ if (MocConst_.Enabled) {
+ cryptoHash.Initialize();
+ cha(MocConst().Executable);
+ for (auto const& item : MocConst().OptionsDefinitions) {
+ cha(item);
+ }
+ for (auto const& item : MocConst().OptionsIncludes) {
+ cha(item);
+ }
+ for (auto const& item : MocConst().OptionsExtra) {
+ cha(item);
+ }
+ for (auto const& item : MocConst().PredefsCmd) {
+ cha(item);
+ }
+ for (auto const& filter : MocConst().DependFilters) {
+ cha(filter.Key);
+ }
+ for (auto const& filter : MocConst().MacroFilters) {
+ cha(filter.Key);
+ }
+ SettingsStringMoc_ = cryptoHash.FinalizeHex();
+ }
+
+ if (UicConst().Enabled) {
+ cryptoHash.Initialize();
+ cha(UicConst().Executable);
+ std::for_each(UicConst().Options.begin(), UicConst().Options.end(), cha);
+ for (const auto& item : UicConst().UiFiles) {
+ cha(item.first);
+ auto const& opts = item.second.Options;
+ std::for_each(opts.begin(), opts.end(), cha);
+ }
+ SettingsStringUic_ = cryptoHash.FinalizeHex();
+ }
+ }
+
+ // Read old settings and compare
+ {
+ std::string content;
+ if (cmQtAutoGenerator::FileRead(content, SettingsFile_)) {
+ if (MocConst().Enabled) {
+ if (SettingsStringMoc_ != SettingsFind(content, "moc")) {
+ MocConst_.SettingsChanged = true;
+ }
+ }
+ if (UicConst().Enabled) {
+ if (SettingsStringUic_ != SettingsFind(content, "uic")) {
+ UicConst_.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 (MocConst().SettingsChanged || UicConst().SettingsChanged) {
+ cmSystemTools::RemoveFile(SettingsFile_);
+ }
+ } else {
+ // Settings file read failed
+ if (MocConst().Enabled) {
+ MocConst_.SettingsChanged = true;
+ }
+ if (UicConst().Enabled) {
+ UicConst_.SettingsChanged = true;
+ }
+ }
+ }
+}
+
+bool cmQtAutoMocUicT::SettingsFileWrite()
+{
+ // Only write if any setting changed
+ if (MocConst().SettingsChanged || UicConst().SettingsChanged) {
+ if (Log().Verbose()) {
+ Log().Info(
+ GenT::GEN,
+ cmStrCat("Writing the settings file ", MessagePath(SettingsFile_)));
+ }
+ // Compose settings file content
+ std::string content;
+ {
+ auto SettingAppend = [&content](cm::string_view key,
+ cm::string_view value) {
+ if (!value.empty()) {
+ content += cmStrCat(key, ':', value, '\n');
+ }
+ };
+ SettingAppend("moc", SettingsStringMoc_);
+ SettingAppend("uic", SettingsStringUic_);
+ }
+ // Write settings file
+ std::string error;
+ if (!cmQtAutoGenerator::FileWrite(SettingsFile_, content, &error)) {
+ Log().Error(GenT::GEN,
+ cmStrCat("Writing the settings file ",
+ MessagePath(SettingsFile_), " failed.\n", error));
+ // Remove old settings file to trigger a full rebuild on the next run
+ cmSystemTools::RemoveFile(SettingsFile_);
+ return false;
+ }
+ }
+ return true;
+}
+
+void cmQtAutoMocUicT::ParseCacheRead()
+{
+ cm::string_view reason;
+ // Don't read the cache if it is invalid
+ if (!BaseEval().ParseCacheTime.Load(BaseConst().ParseCacheFile)) {
+ reason = "Refreshing parse cache because it doesn't exist.";
+ } else if (MocConst().SettingsChanged || UicConst().SettingsChanged) {
+ reason = "Refreshing parse cache because the settings changed.";
+ } else if (BaseEval().ParseCacheTime.Older(
+ BaseConst().CMakeExecutableTime)) {
+ reason =
+ "Refreshing parse cache because it is older than the CMake executable.";
+ }
+
+ if (!reason.empty()) {
+ // Don't read but refresh the complete parse cache
+ if (Log().Verbose()) {
+ Log().Info(GenT::GEN, reason);
+ }
+ BaseEval().ParseCacheChanged = true;
+ } else {
+ // Read parse cache
+ BaseEval().ParseCache.ReadFromFile(BaseConst().ParseCacheFile);
+ }
+}
+
+bool cmQtAutoMocUicT::ParseCacheWrite()
+{
+ if (BaseEval().ParseCacheChanged) {
+ if (Log().Verbose()) {
+ Log().Info(GenT::GEN,
+ cmStrCat("Writing the parse cache file ",
+ MessagePath(BaseConst().ParseCacheFile)));
+ }
+ if (!BaseEval().ParseCache.WriteToFile(BaseConst().ParseCacheFile)) {
+ Log().Error(GenT::GEN,
+ cmStrCat("Writing the parse cache file ",
+ MessagePath(BaseConst().ParseCacheFile),
+ " failed."));
+ return false;
+ }
+ }
+ return true;
+}
+
+bool cmQtAutoMocUicT::CreateDirectories()
+{
+ // Create AUTOGEN include directory
+ if (!cmSystemTools::MakeDirectory(BaseConst().AutogenIncludeDir)) {
+ Log().Error(GenT::GEN,
+ cmStrCat("Creating the AUTOGEN include directory ",
+ MessagePath(BaseConst().AutogenIncludeDir),
+ " failed."));
+ return false;
+ }
+ return true;
+}
+
+void cmQtAutoMocUicT::Abort(bool error)
+{
+ if (error) {
+ JobError_.store(true);
+ }
+ WorkerPool_.Abort();
+}
+
+std::string cmQtAutoMocUicT::AbsoluteBuildPath(
+ cm::string_view relativePath) const
+{
+ return cmStrCat(BaseConst().AutogenBuildDir, '/', relativePath);
+}
+
+std::string cmQtAutoMocUicT::AbsoluteIncludePath(
+ cm::string_view relativePath) const
+{
+ return cmStrCat(BaseConst().AutogenIncludeDir, '/', relativePath);
+}
+
+} // End of unnamed namespace
+
+bool cmQtAutoMocUic(cm::string_view infoFile, cm::string_view config)
+{
+ return cmQtAutoMocUicT().Run(infoFile, config);
+}
diff --git a/Source/cmQtAutoMocUic.h b/Source/cmQtAutoMocUic.h
new file mode 100644
index 000000000..ffcc2db70
--- /dev/null
+++ b/Source/cmQtAutoMocUic.h
@@ -0,0 +1,16 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmQtAutoMocUic_h
+#define cmQtAutoMocUic_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cm/string_view>
+
+/**
+ * Process AUTOMOC and AUTOUIC
+ * @return true on success
+ */
+bool cmQtAutoMocUic(cm::string_view infoFile, cm::string_view config);
+
+#endif
diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx
new file mode 100644
index 000000000..3af81ad38
--- /dev/null
+++ b/Source/cmQtAutoRcc.cxx
@@ -0,0 +1,503 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmQtAutoRcc.h"
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "cmAlgorithms.h"
+#include "cmCryptoHash.h"
+#include "cmDuration.h"
+#include "cmFileLock.h"
+#include "cmFileLockResult.h"
+#include "cmFileTime.h"
+#include "cmProcessOutput.h"
+#include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+namespace {
+
+/** \class cmQtAutoRccT
+ * \brief AUTORCC generator
+ */
+class cmQtAutoRccT : public cmQtAutoGenerator
+{
+public:
+ cmQtAutoRccT();
+ ~cmQtAutoRccT() override;
+
+ cmQtAutoRccT(cmQtAutoRccT const&) = delete;
+ cmQtAutoRccT& operator=(cmQtAutoRccT const&) = delete;
+
+private:
+ // -- Utility
+ bool IsMultiConfig() const { return MultiConfig_; }
+ std::string MultiConfigOutput() const;
+
+ // -- Abstract processing interface
+ bool InitFromInfo(InfoT const& info) override;
+ bool Process() override;
+ // -- Settings file
+ bool SettingsFileRead();
+ bool SettingsFileWrite();
+ // -- Tests
+ bool TestQrcRccFiles(bool& generate);
+ bool TestResources(bool& generate);
+ bool TestInfoFile();
+ // -- Generation
+ bool GenerateRcc();
+ bool GenerateWrapper();
+
+private:
+ // -- Config settings
+ bool MultiConfig_ = false;
+ // -- Directories
+ std::string AutogenBuildDir_;
+ std::string IncludeDir_;
+ // -- Qt environment
+ std::string RccExecutable_;
+ cmFileTime RccExecutableTime_;
+ std::vector<std::string> RccListOptions_;
+ // -- Job
+ std::string LockFile_;
+ cmFileLock LockFileLock_;
+ std::string QrcFile_;
+ std::string QrcFileName_;
+ std::string QrcFileDir_;
+ cmFileTime QrcFileTime_;
+ std::string RccPathChecksum_;
+ std::string RccFileName_;
+ std::string RccFileOutput_;
+ std::string RccFilePublic_;
+ cmFileTime RccFileTime_;
+ std::string Reason;
+ std::vector<std::string> Options_;
+ std::vector<std::string> Inputs_;
+ // -- Settings file
+ std::string SettingsFile_;
+ std::string SettingsString_;
+ bool SettingsChanged_ = false;
+ bool BuildFileChanged_ = false;
+};
+
+cmQtAutoRccT::cmQtAutoRccT()
+ : cmQtAutoGenerator(GenT::RCC)
+{
+}
+cmQtAutoRccT::~cmQtAutoRccT() = default;
+
+bool cmQtAutoRccT::InitFromInfo(InfoT const& info)
+{
+ // -- Required settings
+ if (!info.GetBool("MULTI_CONFIG", MultiConfig_, true) ||
+ !info.GetString("BUILD_DIR", AutogenBuildDir_, true) ||
+ !info.GetStringConfig("INCLUDE_DIR", IncludeDir_, true) ||
+ !info.GetString("RCC_EXECUTABLE", RccExecutable_, true) ||
+ !info.GetArray("RCC_LIST_OPTIONS", RccListOptions_, false) ||
+ !info.GetString("LOCK_FILE", LockFile_, true) ||
+ !info.GetStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
+ !info.GetString("SOURCE", QrcFile_, true) ||
+ !info.GetString("OUTPUT_CHECKSUM", RccPathChecksum_, true) ||
+ !info.GetString("OUTPUT_NAME", RccFileName_, true) ||
+ !info.GetArray("OPTIONS", Options_, false) ||
+ !info.GetArray("INPUTS", Inputs_, false)) {
+ return false;
+ }
+
+ // -- Derive information
+ QrcFileName_ = cmSystemTools::GetFilenameName(QrcFile_);
+ QrcFileDir_ = cmSystemTools::GetFilenamePath(QrcFile_);
+ RccFilePublic_ =
+ cmStrCat(AutogenBuildDir_, '/', RccPathChecksum_, '/', RccFileName_);
+
+ // rcc output file name
+ if (IsMultiConfig()) {
+ RccFileOutput_ = cmStrCat(IncludeDir_, '/', MultiConfigOutput());
+ } else {
+ RccFileOutput_ = RccFilePublic_;
+ }
+
+ // -- Checks
+ if (!RccExecutableTime_.Load(RccExecutable_)) {
+ return info.LogError(cmStrCat(
+ "The rcc executable ", MessagePath(RccExecutable_), " does not exist."));
+ }
+
+ return true;
+}
+
+bool cmQtAutoRccT::Process()
+{
+ if (!SettingsFileRead()) {
+ return false;
+ }
+
+ // Test if the rcc output needs to be regenerated
+ bool generate = false;
+ if (!TestQrcRccFiles(generate)) {
+ return false;
+ }
+ if (!generate && !TestResources(generate)) {
+ return false;
+ }
+ // Generate on demand
+ if (generate) {
+ if (!GenerateRcc()) {
+ return false;
+ }
+ } else {
+ // Test if the info file is newer than the output file
+ if (!TestInfoFile()) {
+ return false;
+ }
+ }
+
+ if (!GenerateWrapper()) {
+ return false;
+ }
+
+ return SettingsFileWrite();
+}
+
+std::string cmQtAutoRccT::MultiConfigOutput() const
+{
+ return cmStrCat(RccPathChecksum_, '/',
+ AppendFilenameSuffix(RccFileName_, "_CMAKE_"));
+}
+
+bool cmQtAutoRccT::SettingsFileRead()
+{
+ // Compose current settings strings
+ {
+ cmCryptoHash cryptoHash(cmCryptoHash::AlgoSHA256);
+ auto cha = [&cryptoHash](cm::string_view value) {
+ cryptoHash.Append(value);
+ cryptoHash.Append(";");
+ };
+ cha(RccExecutable_);
+ std::for_each(RccListOptions_.begin(), RccListOptions_.end(), cha);
+ cha(QrcFile_);
+ cha(RccPathChecksum_);
+ cha(RccFileName_);
+ std::for_each(Options_.begin(), Options_.end(), cha);
+ std::for_each(Inputs_.begin(), Inputs_.end(), cha);
+ SettingsString_ = cryptoHash.FinalizeHex();
+ }
+
+ // Make sure the settings file exists
+ if (!cmSystemTools::FileExists(SettingsFile_, true)) {
+ // Touch the settings file to make sure it exists
+ if (!cmSystemTools::Touch(SettingsFile_, true)) {
+ Log().Error(GenT::RCC,
+ cmStrCat("Touching the settings file ",
+ MessagePath(SettingsFile_), " failed."));
+ return false;
+ }
+ }
+
+ // Lock the lock file
+ {
+ // Make sure the lock file exists
+ if (!cmSystemTools::FileExists(LockFile_, true)) {
+ if (!cmSystemTools::Touch(LockFile_, true)) {
+ Log().Error(GenT::RCC,
+ cmStrCat("Touching the lock file ", MessagePath(LockFile_),
+ " failed."));
+ return false;
+ }
+ }
+ // Lock the lock file
+ cmFileLockResult lockResult =
+ LockFileLock_.Lock(LockFile_, static_cast<unsigned long>(-1));
+ if (!lockResult.IsOk()) {
+ Log().Error(GenT::RCC,
+ cmStrCat("Locking of the lock file ", MessagePath(LockFile_),
+ " failed.\n", lockResult.GetOutputMessage()));
+ return false;
+ }
+ }
+
+ // Read old settings
+ {
+ std::string content;
+ if (FileRead(content, SettingsFile_)) {
+ SettingsChanged_ = (SettingsString_ != SettingsFind(content, "rcc"));
+ // In case any setting changed clear 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_) {
+ std::string error;
+ if (!FileWrite(SettingsFile_, "", &error)) {
+ Log().Error(GenT::RCC,
+ cmStrCat("Clearing of the settings file ",
+ MessagePath(SettingsFile_), " failed.\n",
+ error));
+ return false;
+ }
+ }
+ } else {
+ SettingsChanged_ = true;
+ }
+ }
+
+ return true;
+}
+
+bool cmQtAutoRccT::SettingsFileWrite()
+{
+ // Only write if any setting changed
+ if (SettingsChanged_) {
+ if (Log().Verbose()) {
+ Log().Info(GenT::RCC,
+ "Writing settings file " + MessagePath(SettingsFile_));
+ }
+ // Write settings file
+ std::string content = cmStrCat("rcc:", SettingsString_, '\n');
+ std::string error;
+ if (!FileWrite(SettingsFile_, content, &error)) {
+ Log().Error(GenT::RCC,
+ cmStrCat("Writing of the settings file ",
+ MessagePath(SettingsFile_), " failed.\n", error));
+ // Remove old settings file to trigger a full rebuild on the next run
+ cmSystemTools::RemoveFile(SettingsFile_);
+ return false;
+ }
+ }
+
+ // Unlock the lock file
+ LockFileLock_.Release();
+ return true;
+}
+
+/// Do basic checks if rcc generation is required
+bool cmQtAutoRccT::TestQrcRccFiles(bool& generate)
+{
+ // Test if the rcc input file exists
+ if (!QrcFileTime_.Load(QrcFile_)) {
+ Log().Error(GenT::RCC,
+ cmStrCat("The resources file ", MessagePath(QrcFile_),
+ " does not exist"));
+ return false;
+ }
+
+ // Test if the rcc output file exists
+ if (!RccFileTime_.Load(RccFileOutput_)) {
+ if (Log().Verbose()) {
+ Reason =
+ cmStrCat("Generating ", MessagePath(RccFileOutput_),
+ ", because it doesn't exist, from ", MessagePath(QrcFile_));
+ }
+ generate = true;
+ return true;
+ }
+
+ // Test if the settings changed
+ if (SettingsChanged_) {
+ if (Log().Verbose()) {
+ Reason = cmStrCat("Generating ", MessagePath(RccFileOutput_),
+ ", because the rcc settings changed, from ",
+ MessagePath(QrcFile_));
+ }
+ generate = true;
+ return true;
+ }
+
+ // Test if the rcc output file is older than the .qrc file
+ if (RccFileTime_.Older(QrcFileTime_)) {
+ if (Log().Verbose()) {
+ Reason = cmStrCat("Generating ", MessagePath(RccFileOutput_),
+ ", because it is older than ", MessagePath(QrcFile_),
+ ", from ", MessagePath(QrcFile_));
+ }
+ generate = true;
+ return true;
+ }
+
+ // Test if the rcc output file is older than the rcc executable
+ if (RccFileTime_.Older(RccExecutableTime_)) {
+ if (Log().Verbose()) {
+ Reason = cmStrCat("Generating ", MessagePath(RccFileOutput_),
+ ", because it is older than the rcc executable, from ",
+ MessagePath(QrcFile_));
+ }
+ generate = true;
+ return true;
+ }
+
+ return true;
+}
+
+bool cmQtAutoRccT::TestResources(bool& generate)
+{
+ // Read resource files list
+ if (Inputs_.empty()) {
+ std::string error;
+ RccLister const lister(RccExecutable_, RccListOptions_);
+ if (!lister.list(QrcFile_, Inputs_, error, Log().Verbose())) {
+ Log().Error(
+ GenT::RCC,
+ cmStrCat("Listing of ", MessagePath(QrcFile_), " failed.\n", error));
+ return false;
+ }
+ }
+
+ // Check if any resource file is newer than the rcc output file
+ for (std::string const& resFile : Inputs_) {
+ // Check if the resource file exists
+ cmFileTime fileTime;
+ if (!fileTime.Load(resFile)) {
+ Log().Error(GenT::RCC,
+ cmStrCat("The resource file ", MessagePath(resFile),
+ " listed in ", MessagePath(QrcFile_),
+ " does not exist."));
+ return false;
+ }
+ // Check if the resource file is newer than the rcc output file
+ if (RccFileTime_.Older(fileTime)) {
+ if (Log().Verbose()) {
+ Reason = cmStrCat("Generating ", MessagePath(RccFileOutput_),
+ ", because it is older than ", MessagePath(resFile),
+ ", from ", MessagePath(QrcFile_));
+ }
+ generate = true;
+ break;
+ }
+ }
+ return true;
+}
+
+bool cmQtAutoRccT::TestInfoFile()
+{
+ // Test if the rcc output file is older than the info file
+ if (RccFileTime_.Older(InfoFileTime())) {
+ if (Log().Verbose()) {
+ Log().Info(GenT::RCC,
+ cmStrCat("Touching ", MessagePath(RccFileOutput_),
+ " because it is older than ",
+ MessagePath(InfoFile())));
+ }
+ // Touch build file
+ if (!cmSystemTools::Touch(RccFileOutput_, false)) {
+ Log().Error(
+ GenT::RCC,
+ cmStrCat("Touching ", MessagePath(RccFileOutput_), " failed."));
+ return false;
+ }
+ BuildFileChanged_ = true;
+ }
+
+ return true;
+}
+
+bool cmQtAutoRccT::GenerateRcc()
+{
+ // Make parent directory
+ if (!MakeParentDirectory(RccFileOutput_)) {
+ Log().Error(GenT::RCC,
+ cmStrCat("Could not create parent directory of ",
+ MessagePath(RccFileOutput_)));
+ return false;
+ }
+
+ // Compose rcc command
+ std::vector<std::string> cmd;
+ cmd.push_back(RccExecutable_);
+ cmAppend(cmd, Options_);
+ cmd.emplace_back("-o");
+ cmd.push_back(RccFileOutput_);
+ cmd.push_back(QrcFile_);
+
+ // Log reason and command
+ if (Log().Verbose()) {
+ Log().Info(GenT::RCC,
+ cmStrCat(Reason, cmHasSuffix(Reason, '\n') ? "" : "\n",
+ QuotedCommand(cmd), '\n'));
+ }
+
+ std::string rccStdOut;
+ std::string rccStdErr;
+ int retVal = 0;
+ bool result = cmSystemTools::RunSingleCommand(
+ cmd, &rccStdOut, &rccStdErr, &retVal, AutogenBuildDir_.c_str(),
+ cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
+ if (!result || (retVal != 0)) {
+ // rcc process failed
+ Log().ErrorCommand(GenT::RCC,
+ cmStrCat("The rcc process failed to compile\n ",
+ MessagePath(QrcFile_), "\ninto\n ",
+ MessagePath(RccFileOutput_)),
+ cmd, rccStdOut + rccStdErr);
+ cmSystemTools::RemoveFile(RccFileOutput_);
+ return false;
+ }
+
+ // rcc process success
+ // Print rcc output
+ if (!rccStdOut.empty()) {
+ Log().Info(GenT::RCC, rccStdOut);
+ }
+ BuildFileChanged_ = true;
+
+ return true;
+}
+
+bool cmQtAutoRccT::GenerateWrapper()
+{
+ // Generate a wrapper source file on demand
+ if (IsMultiConfig()) {
+ // Wrapper file content
+ std::string content =
+ cmStrCat("// This is an autogenerated configuration wrapper file.\n",
+ "// Changes will be overwritten.\n", "#include <",
+ MultiConfigOutput(), ">\n");
+
+ // Compare with existing file content
+ bool fileDiffers = true;
+ {
+ std::string oldContents;
+ if (FileRead(oldContents, RccFilePublic_)) {
+ fileDiffers = (oldContents != content);
+ }
+ }
+ if (fileDiffers) {
+ // Write new wrapper file
+ if (Log().Verbose()) {
+ Log().Info(GenT::RCC,
+ cmStrCat("Generating RCC wrapper file ",
+ MessagePath(RccFilePublic_)));
+ }
+ std::string error;
+ if (!FileWrite(RccFilePublic_, content, &error)) {
+ Log().Error(GenT::RCC,
+ cmStrCat("Generating RCC wrapper file ",
+ MessagePath(RccFilePublic_), " failed.\n",
+ error));
+ return false;
+ }
+ } else if (BuildFileChanged_) {
+ // Just touch the wrapper file
+ if (Log().Verbose()) {
+ Log().Info(
+ GenT::RCC,
+ cmStrCat("Touching RCC wrapper file ", MessagePath(RccFilePublic_)));
+ }
+ if (!cmSystemTools::Touch(RccFilePublic_, false)) {
+ Log().Error(GenT::RCC,
+ cmStrCat("Touching RCC wrapper file ",
+ MessagePath(RccFilePublic_), " failed."));
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+} // End of unnamed namespace
+
+bool cmQtAutoRcc(cm::string_view infoFile, cm::string_view config)
+{
+ return cmQtAutoRccT().Run(infoFile, config);
+}
diff --git a/Source/cmQtAutoRcc.h b/Source/cmQtAutoRcc.h
new file mode 100644
index 000000000..a74b33ae4
--- /dev/null
+++ b/Source/cmQtAutoRcc.h
@@ -0,0 +1,16 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmQtAutoRcc_h
+#define cmQtAutoRcc_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cm/string_view>
+
+/**
+ * Process AUTORCC
+ * @return true on success
+ */
+bool cmQtAutoRcc(cm::string_view infoFile, cm::string_view config);
+
+#endif
diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx
index 5364f76f4..7f4abf904 100644
--- a/Source/cmRST.cxx
+++ b/Source/cmRST.cxx
@@ -2,20 +2,23 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmRST.h"
-#include "cmAlgorithms.h"
-#include "cmSystemTools.h"
-#include "cmVersion.h"
-
-#include "cmsys/FStream.hxx"
#include <algorithm>
-#include <ctype.h>
+#include <cctype>
+#include <cstddef>
#include <iterator>
-#include <stddef.h>
#include <utility>
-cmRST::cmRST(std::ostream& os, std::string const& docroot)
+#include "cmsys/FStream.hxx"
+
+#include "cmAlgorithms.h"
+#include "cmRange.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmVersion.h"
+
+cmRST::cmRST(std::ostream& os, std::string docroot)
: OS(os)
- , DocRoot(docroot)
+ , DocRoot(std::move(docroot))
, IncludeDepth(0)
, OutputLinePending(false)
, LastLineEndedInColonColon(false)
@@ -32,13 +35,15 @@ cmRST::cmRST(std::ostream& os, std::string const& docroot)
, TocTreeDirective("^.. toctree::[ \t]*(.*)$")
, ProductionListDirective("^.. productionlist::[ \t]*(.*)$")
, NoteDirective("^.. note::[ \t]*(.*)$")
- , ModuleRST("^#\\[(=*)\\[\\.rst:$")
+ , ModuleRST(R"(^#\[(=*)\[\.rst:$)")
, CMakeRole("(:cmake)?:("
- "command|generator|variable|module|policy|"
+ "command|cpack_gen|generator|variable|envvar|module|policy|"
"prop_cache|prop_dir|prop_gbl|prop_inst|prop_sf|"
"prop_test|prop_tgt|"
"manual"
"):`(<*([^`<]|[^` \t]<)*)([ \t]+<[^`]*>)?`")
+ , InlineLink("`(<*([^`<]|[^` \t]<)*)([ \t]+<[^`]*>)?`_")
+ , InlineLiteral("``([^`]*)``")
, Substitution("(^|[^A-Za-z0-9_])"
"((\\|[^| \t\r\n]([^|\r\n]*[^| \t\r\n])?\\|)(__|_|))"
"([^A-Za-z0-9_]|$)")
@@ -86,7 +91,7 @@ void cmRST::ProcessModule(std::istream& is)
if (line[0] != '#') {
this->ProcessLine(line.substr(0, pos));
}
- rst = "";
+ rst.clear();
this->Reset();
this->OutputLinePending = true;
}
@@ -101,7 +106,7 @@ void cmRST::ProcessModule(std::istream& is)
this->ProcessLine(line.substr(2));
continue;
}
- rst = "";
+ rst.clear();
this->Reset();
this->OutputLinePending = true;
}
@@ -120,7 +125,7 @@ void cmRST::ProcessModule(std::istream& is)
void cmRST::Reset()
{
if (!this->MarkupLines.empty()) {
- this->UnindentLines(this->MarkupLines);
+ cmRST::UnindentLines(this->MarkupLines);
}
switch (this->Directive) {
case DirectiveNone:
@@ -152,8 +157,9 @@ void cmRST::ProcessLine(std::string const& line)
this->LastLineEndedInColonColon = false;
// A line starting in .. is an explicit markup start.
- if (line == ".." || (line.size() >= 3 && line[0] == '.' && line[1] == '.' &&
- isspace(line[2]))) {
+ if (line == ".." ||
+ (line.size() >= 3 && line[0] == '.' && line[1] == '.' &&
+ isspace(line[2]))) {
this->Reset();
this->Markup =
(line.find_first_not_of(" \t", 2) == std::string::npos ? MarkupEmpty
@@ -175,7 +181,7 @@ void cmRST::ProcessLine(std::string const& line)
// Record the literal lines to output after whole block.
// Ignore the language spec and record the opening line as blank.
this->Directive = DirectiveCodeBlock;
- this->MarkupLines.push_back("");
+ this->MarkupLines.emplace_back();
} else if (this->ReplaceDirective.find(line)) {
// Record the replace directive content.
this->Directive = DirectiveReplace;
@@ -218,15 +224,14 @@ void cmRST::ProcessLine(std::string const& line)
// Record the literal lines to output after whole block.
this->Markup = MarkupNormal;
this->Directive = DirectiveLiteralBlock;
- this->MarkupLines.push_back("");
+ this->MarkupLines.emplace_back();
this->OutputLine("", false);
}
// Print non-markup lines.
else {
this->NormalLine(line);
this->LastLineEndedInColonColon =
- (line.size() >= 2 && line[line.size() - 2] == ':' &&
- line[line.size() - 1] == ':');
+ (line.size() >= 2 && line[line.size() - 2] == ':' && line.back() == ':');
}
}
@@ -245,18 +250,62 @@ void cmRST::OutputLine(std::string const& line_in, bool inlineMarkup)
if (inlineMarkup) {
std::string line = this->ReplaceSubstitutions(line_in);
std::string::size_type pos = 0;
- while (this->CMakeRole.find(line.c_str() + pos)) {
- this->OS << line.substr(pos, this->CMakeRole.start());
- std::string text = this->CMakeRole.match(3);
- // If a command reference has no explicit target and
- // no explicit "(...)" then add "()" to the text.
- if (this->CMakeRole.match(2) == "command" &&
- this->CMakeRole.match(5).empty() &&
- text.find_first_of("()") == std::string::npos) {
- text += "()";
+ for (;;) {
+ std::string::size_type* first = nullptr;
+ std::string::size_type role_start = std::string::npos;
+ std::string::size_type link_start = std::string::npos;
+ std::string::size_type lit_start = std::string::npos;
+ if (this->CMakeRole.find(line.c_str() + pos)) {
+ role_start = this->CMakeRole.start();
+ first = &role_start;
+ }
+ if (this->InlineLiteral.find(line.c_str() + pos)) {
+ lit_start = this->InlineLiteral.start();
+ if (!first || lit_start < *first) {
+ first = &lit_start;
+ }
+ }
+ if (this->InlineLink.find(line.c_str() + pos)) {
+ link_start = this->InlineLink.start();
+ if (!first || link_start < *first) {
+ first = &link_start;
+ }
+ }
+ if (first == &role_start) {
+ this->OS << line.substr(pos, role_start);
+ std::string text = this->CMakeRole.match(3);
+ // If a command reference has no explicit target and
+ // no explicit "(...)" then add "()" to the text.
+ if (this->CMakeRole.match(2) == "command" &&
+ this->CMakeRole.match(5).empty() &&
+ text.find_first_of("()") == std::string::npos) {
+ text += "()";
+ }
+ this->OS << "``" << text << "``";
+ pos += this->CMakeRole.end();
+ } else if (first == &lit_start) {
+ this->OS << line.substr(pos, lit_start);
+ std::string text = this->InlineLiteral.match(1);
+ pos += this->InlineLiteral.end();
+ this->OS << "``" << text << "``";
+ } else if (first == &link_start) {
+ this->OS << line.substr(pos, link_start);
+ std::string text = this->InlineLink.match(1);
+ bool escaped = false;
+ for (char c : text) {
+ if (escaped) {
+ escaped = false;
+ this->OS << c;
+ } else if (c == '\\') {
+ escaped = true;
+ } else {
+ this->OS << c;
+ }
+ }
+ pos += this->InlineLink.end();
+ } else {
+ break;
}
- this->OS << "``" << text << "``";
- pos += this->CMakeRole.end();
}
this->OS << line.substr(pos) << "\n";
} else {
@@ -272,8 +321,7 @@ std::string cmRST::ReplaceSubstitutions(std::string const& line)
std::string::size_type start = this->Substitution.start(2);
std::string::size_type end = this->Substitution.end(2);
std::string substitute = this->Substitution.match(3);
- std::map<std::string, std::string>::iterator replace =
- this->Replace.find(substitute);
+ auto replace = this->Replace.find(substitute);
if (replace != this->Replace.end()) {
std::pair<std::set<std::string>::iterator, bool> replaced =
this->Replaced.insert(substitute);
@@ -292,11 +340,9 @@ std::string cmRST::ReplaceSubstitutions(std::string const& line)
void cmRST::OutputMarkupLines(bool inlineMarkup)
{
- for (std::vector<std::string>::iterator i = this->MarkupLines.begin();
- i != this->MarkupLines.end(); ++i) {
- std::string line = *i;
+ for (auto line : this->MarkupLines) {
if (!line.empty()) {
- line = " " + line;
+ line = cmStrCat(" ", line);
}
this->OutputLine(line, inlineMarkup);
}
@@ -347,15 +393,13 @@ void cmRST::ProcessDirectiveReplace()
// Record markup lines as replacement text.
std::string& replacement = this->Replace[this->ReplaceName];
replacement += cmJoin(this->MarkupLines, " ");
- this->ReplaceName = "";
+ this->ReplaceName.clear();
}
void cmRST::ProcessDirectiveTocTree()
{
// Process documents referenced by toctree directive.
- for (std::vector<std::string>::iterator i = this->MarkupLines.begin();
- i != this->MarkupLines.end(); ++i) {
- std::string const& line = *i;
+ for (std::string const& line : this->MarkupLines) {
if (!line.empty() && line[0] != ':') {
if (this->TocTreeLink.find(line)) {
std::string const& link = this->TocTreeLink.match(1);
@@ -407,14 +451,20 @@ void cmRST::UnindentLines(std::vector<std::string>& lines)
}
}
- std::vector<std::string>::const_iterator it = lines.begin();
+ auto it = lines.cbegin();
size_t leadingEmpty = std::distance(it, cmFindNot(lines, std::string()));
- std::vector<std::string>::const_reverse_iterator rit = lines.rbegin();
+ auto rit = lines.crbegin();
size_t trailingEmpty =
std::distance(rit, cmFindNot(cmReverseRange(lines), std::string()));
- std::vector<std::string>::iterator contentEnd = cmRotate(
- lines.begin(), lines.begin() + leadingEmpty, lines.end() - trailingEmpty);
+ if ((leadingEmpty + trailingEmpty) >= lines.size()) {
+ // All lines are empty. The markup block is empty. Leave only one.
+ lines.resize(1);
+ return;
+ }
+
+ auto contentEnd = cmRotate(lines.begin(), lines.begin() + leadingEmpty,
+ lines.end() - trailingEmpty);
lines.erase(contentEnd, lines.end());
}
diff --git a/Source/cmRST.h b/Source/cmRST.h
index d1a8e2711..6b5d416d8 100644
--- a/Source/cmRST.h
+++ b/Source/cmRST.h
@@ -5,13 +5,14 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmsys/RegularExpression.hxx"
#include <iosfwd>
#include <map>
#include <set>
#include <string>
#include <vector>
+#include "cmsys/RegularExpression.hxx"
+
/** \class cmRST
* \brief Perform basic .rst processing for command-line help
*
@@ -25,7 +26,7 @@
class cmRST
{
public:
- cmRST(std::ostream& os, std::string const& docroot);
+ cmRST(std::ostream& os, std::string docroot);
bool ProcessFile(std::string const& fname, bool isModule = false);
private:
@@ -85,6 +86,8 @@ private:
cmsys::RegularExpression NoteDirective;
cmsys::RegularExpression ModuleRST;
cmsys::RegularExpression CMakeRole;
+ cmsys::RegularExpression InlineLink;
+ cmsys::RegularExpression InlineLiteral;
cmsys::RegularExpression Substitution;
cmsys::RegularExpression TocTreeLink;
diff --git a/Source/cmRange.h b/Source/cmRange.h
new file mode 100644
index 000000000..3be5193e7
--- /dev/null
+++ b/Source/cmRange.h
@@ -0,0 +1,239 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmRange_h
+#define cmRange_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <algorithm>
+#include <functional>
+#include <iterator>
+
+namespace RangeIterators {
+
+template <typename Iter, typename UnaryPredicate>
+class FilterIterator
+{
+public:
+ using iterator_category = std::bidirectional_iterator_tag;
+ using value_type = typename std::iterator_traits<Iter>::value_type;
+ using difference_type = typename std::iterator_traits<Iter>::difference_type;
+ using pointer = typename std::iterator_traits<Iter>::pointer;
+ using reference = typename std::iterator_traits<Iter>::reference;
+
+ FilterIterator(Iter b, Iter e, UnaryPredicate p)
+ : Cur(std::move(b))
+ , End(std::move(e))
+ , Pred(std::move(p))
+ {
+ this->SatisfyPredicate();
+ }
+
+ FilterIterator& operator++()
+ {
+ ++this->Cur;
+ this->SatisfyPredicate();
+ return *this;
+ }
+
+ FilterIterator& operator--()
+ {
+ do {
+ --this->Cur;
+ } while (!this->Pred(*this->Cur));
+ return *this;
+ }
+
+ bool operator==(FilterIterator const& other) const
+ {
+ return this->Cur == other.Cur;
+ }
+
+ bool operator!=(FilterIterator const& other) const
+ {
+ return !this->operator==(other);
+ }
+
+ auto operator*() const -> decltype(*std::declval<Iter>())
+ {
+ return *this->Cur;
+ }
+
+private:
+ void SatisfyPredicate()
+ {
+ while (this->Cur != this->End && !this->Pred(*this->Cur)) {
+ ++this->Cur;
+ }
+ }
+
+ Iter Cur;
+ Iter End;
+ UnaryPredicate Pred;
+};
+
+template <typename Iter, typename UnaryFunction>
+class TransformIterator
+{
+public:
+ using iterator_category = std::bidirectional_iterator_tag;
+ using value_type =
+ typename std::remove_cv<typename std::remove_reference<decltype(
+ std::declval<UnaryFunction>()(*std::declval<Iter>()))>::type>::type;
+ using difference_type = typename std::iterator_traits<Iter>::difference_type;
+ using pointer = value_type const*;
+ using reference = value_type const&;
+
+ TransformIterator(Iter i, UnaryFunction f)
+ : Base(std::move(i))
+ , Func(std::move(f))
+ {
+ }
+
+ TransformIterator& operator++()
+ {
+ ++this->Base;
+ return *this;
+ }
+
+ TransformIterator& operator--()
+ {
+ --this->Base;
+ return *this;
+ }
+
+ bool operator==(TransformIterator const& other) const
+ {
+ return this->Base == other.Base;
+ }
+
+ bool operator!=(TransformIterator const& other) const
+ {
+ return !this->operator==(other);
+ }
+
+ auto operator*() const
+ -> decltype(std::declval<UnaryFunction>()(*std::declval<Iter>()))
+ {
+ return this->Func(*this->Base);
+ }
+
+private:
+ Iter Base;
+ UnaryFunction Func;
+};
+
+} // namespace RangeIterators
+
+template <typename Iter>
+class cmRange
+{
+public:
+ using const_iterator = Iter;
+ using value_type = typename std::iterator_traits<Iter>::value_type;
+ using difference_type = typename std::iterator_traits<Iter>::difference_type;
+
+ cmRange(Iter b, Iter e)
+ : Begin(std::move(b))
+ , End(std::move(e))
+ {
+ }
+
+ Iter begin() const { return this->Begin; }
+ Iter end() const { return this->End; }
+ bool empty() const { return this->Begin == this->End; }
+
+ difference_type size() const
+ {
+ return std::distance(this->Begin, this->End);
+ }
+
+ cmRange& advance(difference_type amount) &
+ {
+ std::advance(this->Begin, amount);
+ return *this;
+ }
+
+ cmRange advance(difference_type amount) &&
+ {
+ std::advance(this->Begin, amount);
+ return std::move(*this);
+ }
+
+ cmRange& retreat(difference_type amount) &
+ {
+ std::advance(this->End, -amount);
+ return *this;
+ }
+
+ cmRange retreat(difference_type amount) &&
+ {
+ std::advance(this->End, -amount);
+ return std::move(*this);
+ }
+
+ template <typename UnaryPredicate>
+ bool all_of(UnaryPredicate p) const
+ {
+ return std::all_of(this->Begin, this->End, std::ref(p));
+ }
+
+ template <typename UnaryPredicate>
+ bool any_of(UnaryPredicate p) const
+ {
+ return std::any_of(this->Begin, this->End, std::ref(p));
+ }
+
+ template <typename UnaryPredicate>
+ bool none_of(UnaryPredicate p) const
+ {
+ return std::none_of(this->Begin, this->End, std::ref(p));
+ }
+
+ template <typename UnaryPredicate>
+ auto filter(UnaryPredicate p) const
+ -> cmRange<RangeIterators::FilterIterator<Iter, UnaryPredicate>>
+ {
+ using It = RangeIterators::FilterIterator<Iter, UnaryPredicate>;
+ return { It(this->Begin, this->End, p), It(this->End, this->End, p) };
+ }
+
+ template <typename UnaryFunction>
+ auto transform(UnaryFunction f) const
+ -> cmRange<RangeIterators::TransformIterator<Iter, UnaryFunction>>
+ {
+ using It = RangeIterators::TransformIterator<Iter, UnaryFunction>;
+ return { It(this->Begin, f), It(this->End, f) };
+ }
+
+private:
+ Iter Begin;
+ Iter End;
+};
+
+template <typename Iter1, typename Iter2>
+bool operator==(cmRange<Iter1> const& left, cmRange<Iter2> const& right)
+{
+ return left.size() == right.size() &&
+ std::equal(left.begin(), left.end(), right.begin());
+}
+
+template <typename Iter1, typename Iter2>
+auto cmMakeRange(Iter1 begin, Iter2 end) -> cmRange<Iter1>
+{
+ return { begin, end };
+}
+
+template <typename Range>
+auto cmMakeRange(Range const& range) -> cmRange<decltype(range.begin())>
+{
+ return { range.begin(), range.end() };
+}
+
+template <typename Range>
+auto cmReverseRange(Range const& range) -> cmRange<decltype(range.rbegin())>
+{
+ return { range.rbegin(), range.rend() };
+}
+
+#endif
diff --git a/Source/cmRemoveCommand.cxx b/Source/cmRemoveCommand.cxx
index 1db84414a..457b70848 100644
--- a/Source/cmRemoveCommand.cxx
+++ b/Source/cmRemoveCommand.cxx
@@ -2,14 +2,13 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmRemoveCommand.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-#include "cmSystemTools.h"
-
-class cmExecutionStatus;
+#include "cmStringAlgorithms.h"
// cmRemoveCommand
-bool cmRemoveCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmRemoveCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
return true;
@@ -17,7 +16,7 @@ bool cmRemoveCommand::InitialPass(std::vector<std::string> const& args,
std::string const& variable = args[0]; // VAR is always first
// get the old value
- const char* cacheValue = this->Makefile->GetDefinition(variable);
+ const char* cacheValue = status.GetMakefile().GetDefinition(variable);
// if there is no old value then return
if (!cacheValue) {
@@ -25,22 +24,19 @@ bool cmRemoveCommand::InitialPass(std::vector<std::string> const& args,
}
// expand the variable
- std::vector<std::string> varArgsExpanded;
- cmSystemTools::ExpandListArgument(cacheValue, varArgsExpanded);
+ std::vector<std::string> const varArgsExpanded = cmExpandedList(cacheValue);
// expand the args
// check for REMOVE(VAR v1 v2 ... vn)
- std::vector<std::string> argsExpanded;
- std::vector<std::string> temp;
- temp.insert(temp.end(), args.begin() + 1, args.end());
- cmSystemTools::ExpandList(temp, argsExpanded);
+ std::vector<std::string> const argsExpanded =
+ cmExpandedLists(args.begin() + 1, args.end());
// now create the new value
std::string value;
- for (unsigned int j = 0; j < varArgsExpanded.size(); ++j) {
+ for (std::string const& varArgExpanded : varArgsExpanded) {
int found = 0;
- for (unsigned int k = 0; k < argsExpanded.size(); ++k) {
- if (varArgsExpanded[j] == argsExpanded[k]) {
+ for (std::string const& argExpanded : argsExpanded) {
+ if (varArgExpanded == argExpanded) {
found = 1;
break;
}
@@ -49,12 +45,12 @@ bool cmRemoveCommand::InitialPass(std::vector<std::string> const& args,
if (!value.empty()) {
value += ";";
}
- value += varArgsExpanded[j];
+ value += varArgExpanded;
}
}
// add the definition
- this->Makefile->AddDefinition(variable, value.c_str());
+ status.GetMakefile().AddDefinition(variable, value);
return true;
}
diff --git a/Source/cmRemoveCommand.h b/Source/cmRemoveCommand.h
index f2e89f6e1..fb72ab5f7 100644
--- a/Source/cmRemoveCommand.h
+++ b/Source/cmRemoveCommand.h
@@ -3,34 +3,19 @@
#ifndef cmRemoveCommand_h
#define cmRemoveCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmRemoveCommand
+/**
* \brief remove command
*
* cmRemoveCommand implements the remove CMake command
*/
-class cmRemoveCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmRemoveCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmRemoveCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmRemoveDefinitionsCommand.cxx b/Source/cmRemoveDefinitionsCommand.cxx
index f5fe2dfb7..339ff9d35 100644
--- a/Source/cmRemoveDefinitionsCommand.cxx
+++ b/Source/cmRemoveDefinitionsCommand.cxx
@@ -2,22 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmRemoveDefinitionsCommand.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-class cmExecutionStatus;
-
-// cmRemoveDefinitionsCommand
-bool cmRemoveDefinitionsCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmRemoveDefinitionsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- // it is OK to have no arguments
- if (args.empty()) {
- return true;
- }
-
- for (std::vector<std::string>::const_iterator i = args.begin();
- i != args.end(); ++i) {
- this->Makefile->RemoveDefineFlag(i->c_str());
+ cmMakefile& mf = status.GetMakefile();
+ for (std::string const& i : args) {
+ mf.RemoveDefineFlag(i);
}
return true;
}
diff --git a/Source/cmRemoveDefinitionsCommand.h b/Source/cmRemoveDefinitionsCommand.h
index 9a9a5d535..868416bc1 100644
--- a/Source/cmRemoveDefinitionsCommand.h
+++ b/Source/cmRemoveDefinitionsCommand.h
@@ -3,36 +3,14 @@
#ifndef cmRemoveDefinitionsCommand_h
#define cmRemoveDefinitionsCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmRemoveDefinitionsCommand
- * \brief Specify a list of compiler defines
- *
- * cmRemoveDefinitionsCommand specifies a list of compiler defines.
- * These defines will
- * be removed from the compile command.
- */
-class cmRemoveDefinitionsCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmRemoveDefinitionsCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmRemoveDefinitionsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmReturnCommand.cxx b/Source/cmReturnCommand.cxx
index ceea8b4d9..59056690c 100644
--- a/Source/cmReturnCommand.cxx
+++ b/Source/cmReturnCommand.cxx
@@ -5,8 +5,8 @@
#include "cmExecutionStatus.h"
// cmReturnCommand
-bool cmReturnCommand::InitialPass(std::vector<std::string> const&,
- cmExecutionStatus& status)
+bool cmReturnCommand(std::vector<std::string> const&,
+ cmExecutionStatus& status)
{
status.SetReturnInvoked();
return true;
diff --git a/Source/cmReturnCommand.h b/Source/cmReturnCommand.h
index 87900e7e9..2404a363d 100644
--- a/Source/cmReturnCommand.h
+++ b/Source/cmReturnCommand.h
@@ -3,34 +3,15 @@
#ifndef cmReturnCommand_h
#define cmReturnCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmReturnCommand
- * \brief Return from a directory or function
- *
- * cmReturnCommand returns from a directory or function
- */
-class cmReturnCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmReturnCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+/// Return from a directory or function
+bool cmReturnCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx
index a71861af7..0a1d109d5 100644
--- a/Source/cmRulePlaceholderExpander.cxx
+++ b/Source/cmRulePlaceholderExpander.cxx
@@ -2,21 +2,21 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmRulePlaceholderExpander.h"
-#include <ctype.h>
-#include <string.h>
+#include <cctype>
+#include <cstring>
#include <utility>
#include "cmOutputConverter.h"
#include "cmSystemTools.h"
cmRulePlaceholderExpander::cmRulePlaceholderExpander(
- std::map<std::string, std::string> const& compilers,
- std::map<std::string, std::string> const& variableMappings,
- std::string const& compilerSysroot, std::string const& linkerSysroot)
- : Compilers(compilers)
- , VariableMappings(variableMappings)
- , CompilerSysroot(compilerSysroot)
- , LinkerSysroot(linkerSysroot)
+ std::map<std::string, std::string> compilers,
+ std::map<std::string, std::string> variableMappings,
+ std::string compilerSysroot, std::string linkerSysroot)
+ : Compilers(std::move(compilers))
+ , VariableMappings(std::move(variableMappings))
+ , CompilerSysroot(std::move(compilerSysroot))
+ , LinkerSysroot(std::move(linkerSysroot))
{
}
@@ -91,6 +91,31 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
if (replaceValues.Includes && variable == "INCLUDES") {
return replaceValues.Includes;
}
+ if (replaceValues.SwiftLibraryName) {
+ if (variable == "SWIFT_LIBRARY_NAME") {
+ return replaceValues.SwiftLibraryName;
+ }
+ }
+ if (replaceValues.SwiftModule) {
+ if (variable == "SWIFT_MODULE") {
+ return replaceValues.SwiftModule;
+ }
+ }
+ if (replaceValues.SwiftModuleName) {
+ if (variable == "SWIFT_MODULE_NAME") {
+ return replaceValues.SwiftModuleName;
+ }
+ }
+ if (replaceValues.SwiftOutputFileMap) {
+ if (variable == "SWIFT_OUTPUT_FILE_MAP") {
+ return replaceValues.SwiftOutputFileMap;
+ }
+ }
+ if (replaceValues.SwiftSources) {
+ if (variable == "SWIFT_SOURCES") {
+ return replaceValues.SwiftSources;
+ }
+ }
if (replaceValues.TargetPDB) {
if (variable == "TARGET_PDB") {
return replaceValues.TargetPDB;
@@ -110,7 +135,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
if (replaceValues.Target) {
if (variable == "TARGET_QUOTED") {
std::string targetQuoted = replaceValues.Target;
- if (!targetQuoted.empty() && targetQuoted[0] != '\"') {
+ if (!targetQuoted.empty() && targetQuoted.front() != '\"') {
targetQuoted = '\"';
targetQuoted += replaceValues.Target;
targetQuoted += '\"';
@@ -120,7 +145,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
if (variable == "TARGET_UNQUOTED") {
std::string unquoted = replaceValues.Target;
std::string::size_type sz = unquoted.size();
- if (sz > 2 && unquoted[0] == '\"' && unquoted[sz - 1] == '\"') {
+ if (sz > 2 && unquoted.front() == '\"' && unquoted.back() == '\"') {
unquoted = unquoted.substr(1, sz - 2);
}
return unquoted;
@@ -210,8 +235,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
cmOutputConverter::SHELL);
}
- std::map<std::string, std::string>::iterator compIt =
- this->Compilers.find(variable);
+ auto compIt = this->Compilers.find(variable);
if (compIt != this->Compilers.end()) {
std::string ret = outputConverter->ConvertToOutputForExisting(
@@ -267,8 +291,7 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
return ret;
}
- std::map<std::string, std::string>::iterator mapIt =
- this->VariableMappings.find(variable);
+ auto mapIt = this->VariableMappings.find(variable);
if (mapIt != this->VariableMappings.end()) {
if (variable.find("_FLAG") == std::string::npos) {
return outputConverter->ConvertToOutputForExisting(mapIt->second);
diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h
index 7b19210d3..8f361967b 100644
--- a/Source/cmRulePlaceholderExpander.h
+++ b/Source/cmRulePlaceholderExpander.h
@@ -15,16 +15,16 @@ class cmRulePlaceholderExpander
{
public:
cmRulePlaceholderExpander(
- std::map<std::string, std::string> const& compilers,
- std::map<std::string, std::string> const& variableMappings,
- std::string const& compilerSysroot, std::string const& linkerSysroot);
+ std::map<std::string, std::string> compilers,
+ std::map<std::string, std::string> variableMappings,
+ std::string compilerSysroot, std::string linkerSysroot);
void SetTargetImpLib(std::string const& targetImpLib)
{
this->TargetImpLib = targetImpLib;
}
- // Create a struct to hold the varibles passed into
+ // Create a struct to hold the variables passed into
// ExpandRuleVariables
struct RuleVariables
{
@@ -58,6 +58,11 @@ public:
const char* Includes;
const char* DependencyFile;
const char* FilterPrefix;
+ const char* SwiftLibraryName;
+ const char* SwiftModule;
+ const char* SwiftModuleName;
+ const char* SwiftOutputFileMap;
+ const char* SwiftSources;
};
// Expand rule variables in CMake of the type found in language rules
diff --git a/Source/cmRuntimeDependencyArchive.cxx b/Source/cmRuntimeDependencyArchive.cxx
new file mode 100644
index 000000000..7a987c27e
--- /dev/null
+++ b/Source/cmRuntimeDependencyArchive.cxx
@@ -0,0 +1,378 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmRuntimeDependencyArchive.h"
+
+#include "cmBinUtilsLinuxELFLinker.h"
+#include "cmBinUtilsMacOSMachOLinker.h"
+#include "cmBinUtilsWindowsPELinker.h"
+#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+#if defined(_WIN32)
+# include "cmGlobalGenerator.h"
+# ifndef CMAKE_BOOTSTRAP
+# include "cmGlobalVisualStudioVersionedGenerator.h"
+# endif
+# include "cmsys/Glob.hxx"
+
+# include "cmVSSetupHelper.h"
+#endif
+
+#include <algorithm>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm/memory>
+
+#if defined(_WIN32)
+static void AddVisualStudioPath(std::vector<std::string>& paths,
+ const std::string& prefix,
+ unsigned int version, cmGlobalGenerator* gg)
+{
+ // If generating for the VS IDE, use the same instance.
+ std::string vsloc;
+ bool found = false;
+# ifndef CMAKE_BOOTSTRAP
+ if (gg->GetName().find(prefix) == 0) {
+ cmGlobalVisualStudioVersionedGenerator* vsgen =
+ static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg);
+ if (vsgen->GetVSInstance(vsloc)) {
+ found = true;
+ }
+ }
+# endif
+
+ // Otherwise, find a VS instance ourselves.
+ if (!found) {
+ cmVSSetupAPIHelper vsSetupAPIHelper(version);
+ if (vsSetupAPIHelper.GetVSInstanceInfo(vsloc)) {
+ cmSystemTools::ConvertToUnixSlashes(vsloc);
+ found = true;
+ }
+ }
+
+ if (found) {
+ cmsys::Glob glob;
+ glob.SetListDirs(true);
+ glob.FindFiles(vsloc + "/VC/Tools/MSVC/*");
+ for (auto const& vcdir : glob.GetFiles()) {
+ paths.push_back(vcdir + "/bin/Hostx64/x64");
+ paths.push_back(vcdir + "/bin/Hostx86/x64");
+ paths.push_back(vcdir + "/bin/Hostx64/x86");
+ paths.push_back(vcdir + "/bin/Hostx86/x86");
+ }
+ }
+}
+
+static void AddRegistryPath(std::vector<std::string>& paths,
+ const std::string& path, cmMakefile* mf)
+{
+ // We should view the registry as the target application would view
+ // it.
+ cmSystemTools::KeyWOW64 view = cmSystemTools::KeyWOW64_32;
+ cmSystemTools::KeyWOW64 other_view = cmSystemTools::KeyWOW64_64;
+ if (mf->PlatformIs64Bit()) {
+ view = cmSystemTools::KeyWOW64_64;
+ other_view = cmSystemTools::KeyWOW64_32;
+ }
+
+ // Expand using the view of the target application.
+ std::string expanded = path;
+ cmSystemTools::ExpandRegistryValues(expanded, view);
+ cmSystemTools::GlobDirs(expanded, paths);
+
+ // Executables can be either 32-bit or 64-bit, so expand using the
+ // alternative view.
+ expanded = path;
+ cmSystemTools::ExpandRegistryValues(expanded, other_view);
+ cmSystemTools::GlobDirs(expanded, paths);
+}
+
+static void AddEnvPath(std::vector<std::string>& paths, const std::string& var,
+ const std::string& suffix)
+{
+ std::string value;
+ if (cmSystemTools::GetEnv(var, value)) {
+ paths.push_back(value + suffix);
+ }
+}
+#endif
+
+static cmsys::RegularExpression TransformCompile(const std::string& str)
+{
+ return cmsys::RegularExpression(str);
+}
+
+cmRuntimeDependencyArchive::cmRuntimeDependencyArchive(
+ cmExecutionStatus& status, std::vector<std::string> searchDirectories,
+ std::string bundleExecutable,
+ const std::vector<std::string>& preIncludeRegexes,
+ const std::vector<std::string>& preExcludeRegexes,
+ const std::vector<std::string>& postIncludeRegexes,
+ const std::vector<std::string>& postExcludeRegexes)
+ : Status(status)
+ , SearchDirectories(std::move(searchDirectories))
+ , BundleExecutable(std::move(bundleExecutable))
+ , PreIncludeRegexes(preIncludeRegexes.size())
+ , PreExcludeRegexes(preExcludeRegexes.size())
+ , PostIncludeRegexes(postIncludeRegexes.size())
+ , PostExcludeRegexes(postExcludeRegexes.size())
+{
+ std::transform(preIncludeRegexes.begin(), preIncludeRegexes.end(),
+ this->PreIncludeRegexes.begin(), TransformCompile);
+ std::transform(preExcludeRegexes.begin(), preExcludeRegexes.end(),
+ this->PreExcludeRegexes.begin(), TransformCompile);
+ std::transform(postIncludeRegexes.begin(), postIncludeRegexes.end(),
+ this->PostIncludeRegexes.begin(), TransformCompile);
+ std::transform(postExcludeRegexes.begin(), postExcludeRegexes.end(),
+ this->PostExcludeRegexes.begin(), TransformCompile);
+}
+
+bool cmRuntimeDependencyArchive::Prepare()
+{
+ std::string platform = this->GetMakefile()->GetSafeDefinition(
+ "CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM");
+ if (platform.empty()) {
+ std::string systemName =
+ this->GetMakefile()->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
+ if (systemName == "Windows") {
+ platform = "windows+pe";
+ } else if (systemName == "Darwin") {
+ platform = "macos+macho";
+ } else if (systemName == "Linux") {
+ platform = "linux+elf";
+ }
+ }
+ if (platform == "linux+elf") {
+ this->Linker = cm::make_unique<cmBinUtilsLinuxELFLinker>(this);
+ } else if (platform == "windows+pe") {
+ this->Linker = cm::make_unique<cmBinUtilsWindowsPELinker>(this);
+ } else if (platform == "macos+macho") {
+ this->Linker = cm::make_unique<cmBinUtilsMacOSMachOLinker>(this);
+ } else {
+ std::ostringstream e;
+ e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM: "
+ << platform;
+ this->SetError(e.str());
+ return false;
+ }
+
+ return this->Linker->Prepare();
+}
+
+bool cmRuntimeDependencyArchive::GetRuntimeDependencies(
+ const std::vector<std::string>& executables,
+ const std::vector<std::string>& libraries,
+ const std::vector<std::string>& modules)
+{
+ for (auto const& exe : executables) {
+ if (!this->Linker->ScanDependencies(exe, cmStateEnums::EXECUTABLE)) {
+ return false;
+ }
+ }
+ for (auto const& lib : libraries) {
+ if (!this->Linker->ScanDependencies(lib, cmStateEnums::SHARED_LIBRARY)) {
+ return false;
+ }
+ }
+ for (auto const& mod : modules) {
+ if (!this->Linker->ScanDependencies(mod, cmStateEnums::MODULE_LIBRARY)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void cmRuntimeDependencyArchive::SetError(const std::string& e)
+{
+ this->Status.SetError(e);
+}
+
+std::string cmRuntimeDependencyArchive::GetBundleExecutable()
+{
+ return this->BundleExecutable;
+}
+
+const std::vector<std::string>&
+cmRuntimeDependencyArchive::GetSearchDirectories()
+{
+ return this->SearchDirectories;
+}
+
+std::string cmRuntimeDependencyArchive::GetGetRuntimeDependenciesTool()
+{
+ return this->GetMakefile()->GetSafeDefinition(
+ "CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL");
+}
+
+bool cmRuntimeDependencyArchive::GetGetRuntimeDependenciesCommand(
+ const std::string& search, std::vector<std::string>& command)
+{
+ // First see if it was supplied by the user
+ std::string toolCommand = this->GetMakefile()->GetSafeDefinition(
+ "CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND");
+ if (!toolCommand.empty()) {
+ cmExpandList(toolCommand, command);
+ return true;
+ }
+
+ // Now go searching for it
+ std::vector<std::string> paths;
+#ifdef _WIN32
+ cmGlobalGenerator* gg = this->GetMakefile()->GetGlobalGenerator();
+
+ // Add newer Visual Studio paths
+ AddVisualStudioPath(paths, "Visual Studio 16 ", 16, gg);
+ AddVisualStudioPath(paths, "Visual Studio 15 ", 15, gg);
+
+ // Add older Visual Studio paths
+ AddRegistryPath(
+ paths,
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\14.0;InstallDir]/"
+ "../../VC/bin",
+ this->GetMakefile());
+ AddEnvPath(paths, "VS140COMNTOOLS", "/../../VC/bin");
+ paths.push_back(
+ "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin");
+ AddRegistryPath(
+ paths,
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\12.0;InstallDir]/"
+ "../../VC/bin",
+ this->GetMakefile());
+ AddEnvPath(paths, "VS120COMNTOOLS", "/../../VC/bin");
+ paths.push_back(
+ "C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/bin");
+ AddRegistryPath(
+ paths,
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\11.0;InstallDir]/"
+ "../../VC/bin",
+ this->GetMakefile());
+ AddEnvPath(paths, "VS110COMNTOOLS", "/../../VC/bin");
+ paths.push_back(
+ "C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/bin");
+ AddRegistryPath(
+ paths,
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\10.0;InstallDir]/"
+ "../../VC/bin",
+ this->GetMakefile());
+ AddEnvPath(paths, "VS100COMNTOOLS", "/../../VC/bin");
+ paths.push_back(
+ "C:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/bin");
+ AddRegistryPath(
+ paths,
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\9.0;InstallDir]/"
+ "../../VC/bin",
+ this->GetMakefile());
+ AddEnvPath(paths, "VS90COMNTOOLS", "/../../VC/bin");
+ paths.push_back("C:/Program Files/Microsoft Visual Studio 9.0/VC/bin");
+ paths.push_back("C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin");
+ AddRegistryPath(
+ paths,
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0;InstallDir]/"
+ "../../VC/bin",
+ this->GetMakefile());
+ AddEnvPath(paths, "VS80COMNTOOLS", "/../../VC/bin");
+ paths.push_back("C:/Program Files/Microsoft Visual Studio 8/VC/BIN");
+ paths.push_back("C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN");
+ AddRegistryPath(
+ paths,
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\7.1;InstallDir]/"
+ "../../VC7/bin",
+ this->GetMakefile());
+ AddEnvPath(paths, "VS71COMNTOOLS", "/../../VC7/bin");
+ paths.push_back(
+ "C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN");
+ paths.push_back(
+ "C:/Program Files (x86)/Microsoft Visual Studio .NET 2003/VC7/BIN");
+#endif
+
+ std::string program = cmSystemTools::FindProgram(search, paths);
+ if (!program.empty()) {
+ command = { program };
+ return true;
+ }
+
+ // Couldn't find it
+ return false;
+}
+
+bool cmRuntimeDependencyArchive::IsPreExcluded(const std::string& name)
+{
+ cmsys::RegularExpressionMatch match;
+
+ for (auto const& regex : this->PreIncludeRegexes) {
+ if (regex.find(name.c_str(), match)) {
+ return false;
+ }
+ }
+
+ for (auto const& regex : this->PreExcludeRegexes) {
+ if (regex.find(name.c_str(), match)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool cmRuntimeDependencyArchive::IsPostExcluded(const std::string& name)
+{
+ cmsys::RegularExpressionMatch match;
+
+ for (auto const& regex : this->PostIncludeRegexes) {
+ if (regex.find(name.c_str(), match)) {
+ return false;
+ }
+ }
+
+ for (auto const& regex : this->PostExcludeRegexes) {
+ if (regex.find(name.c_str(), match)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void cmRuntimeDependencyArchive::AddResolvedPath(const std::string& name,
+ const std::string& path,
+ bool& unique)
+{
+ auto it = this->ResolvedPaths.emplace(name, std::set<std::string>{}).first;
+ unique = true;
+ for (auto const& other : it->second) {
+ if (cmSystemTools::SameFile(path, other)) {
+ unique = false;
+ break;
+ }
+ }
+ it->second.insert(path);
+}
+
+void cmRuntimeDependencyArchive::AddUnresolvedPath(const std::string& name)
+{
+ this->UnresolvedPaths.insert(name);
+}
+
+cmMakefile* cmRuntimeDependencyArchive::GetMakefile()
+{
+ return &this->Status.GetMakefile();
+}
+
+const std::map<std::string, std::set<std::string>>&
+cmRuntimeDependencyArchive::GetResolvedPaths()
+{
+ return this->ResolvedPaths;
+}
+
+const std::set<std::string>& cmRuntimeDependencyArchive::GetUnresolvedPaths()
+{
+ return this->UnresolvedPaths;
+}
diff --git a/Source/cmRuntimeDependencyArchive.h b/Source/cmRuntimeDependencyArchive.h
new file mode 100644
index 000000000..9e2dfb6c2
--- /dev/null
+++ b/Source/cmRuntimeDependencyArchive.h
@@ -0,0 +1,70 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cmRuntimeDependencyArchive_h
+#define cmRuntimeDependencyArchive_h
+
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmBinUtilsLinker.h"
+
+class cmExecutionStatus;
+class cmMakefile;
+
+class cmRuntimeDependencyArchive
+{
+public:
+ explicit cmRuntimeDependencyArchive(
+ cmExecutionStatus& status, std::vector<std::string> searchDirectories,
+ std::string bundleExecutable,
+ const std::vector<std::string>& preIncludeRegexes,
+ const std::vector<std::string>& preExcludeRegexes,
+ const std::vector<std::string>& postIncludeRegexes,
+ const std::vector<std::string>& postExcludeRegexes);
+ bool Prepare();
+ bool GetRuntimeDependencies(const std::vector<std::string>& executables,
+ const std::vector<std::string>& libraries,
+ const std::vector<std::string>& modules);
+
+ void SetError(const std::string& e);
+
+ std::string GetBundleExecutable();
+ const std::vector<std::string>& GetSearchDirectories();
+ std::string GetGetRuntimeDependenciesTool();
+ bool GetGetRuntimeDependenciesCommand(const std::string& search,
+ std::vector<std::string>& command);
+ bool IsPreExcluded(const std::string& name);
+ bool IsPostExcluded(const std::string& name);
+
+ void AddResolvedPath(const std::string& name, const std::string& path,
+ bool& unique);
+ void AddUnresolvedPath(const std::string& name);
+
+ cmMakefile* GetMakefile();
+ const std::map<std::string, std::set<std::string>>& GetResolvedPaths();
+ const std::set<std::string>& GetUnresolvedPaths();
+
+private:
+ cmExecutionStatus& Status;
+ std::unique_ptr<cmBinUtilsLinker> Linker;
+
+ std::string GetRuntimeDependenciesTool;
+ std::vector<std::string> GetRuntimeDependenciesCommand;
+
+ std::vector<std::string> SearchDirectories;
+ std::string BundleExecutable;
+ std::vector<cmsys::RegularExpression> PreIncludeRegexes;
+ std::vector<cmsys::RegularExpression> PreExcludeRegexes;
+ std::vector<cmsys::RegularExpression> PostIncludeRegexes;
+ std::vector<cmsys::RegularExpression> PostExcludeRegexes;
+ std::map<std::string, std::set<std::string>> ResolvedPaths;
+ std::set<std::string> UnresolvedPaths;
+};
+
+#endif // cmRuntimeDependencyArchive_h
diff --git a/Source/cmScriptGenerator.cxx b/Source/cmScriptGenerator.cxx
index 753a1ba6f..adc06792d 100644
--- a/Source/cmScriptGenerator.cxx
+++ b/Source/cmScriptGenerator.cxx
@@ -2,22 +2,22 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmScriptGenerator.h"
+#include <utility>
+
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-cmScriptGenerator::cmScriptGenerator(
- const std::string& config_var,
- std::vector<std::string> const& configurations)
- : RuntimeConfigVariable(config_var)
- , Configurations(configurations)
+cmScriptGenerator::cmScriptGenerator(std::string config_var,
+ std::vector<std::string> configurations)
+ : RuntimeConfigVariable(std::move(config_var))
+ , Configurations(std::move(configurations))
, ConfigurationName("")
- , ConfigurationTypes(CM_NULLPTR)
+ , ConfigurationTypes(nullptr)
, ActionsPerConfig(false)
{
}
-cmScriptGenerator::~cmScriptGenerator()
-{
-}
+cmScriptGenerator::~cmScriptGenerator() = default;
void cmScriptGenerator::Generate(
std::ostream& os, const std::string& config,
@@ -26,8 +26,8 @@ void cmScriptGenerator::Generate(
this->ConfigurationName = config;
this->ConfigurationTypes = &configurationTypes;
this->GenerateScript(os);
- this->ConfigurationName = "";
- this->ConfigurationTypes = CM_NULLPTR;
+ this->ConfigurationName.clear();
+ this->ConfigurationTypes = nullptr;
}
static void cmScriptGeneratorEncodeConfig(const std::string& config,
@@ -52,9 +52,8 @@ static void cmScriptGeneratorEncodeConfig(const std::string& config,
std::string cmScriptGenerator::CreateConfigTest(const std::string& config)
{
- std::string result = "\"${";
- result += this->RuntimeConfigVariable;
- result += "}\" MATCHES \"^(";
+ std::string result =
+ cmStrCat("\"${", this->RuntimeConfigVariable, "}\" MATCHES \"^(");
if (!config.empty()) {
cmScriptGeneratorEncodeConfig(config, result);
}
@@ -65,15 +64,13 @@ std::string cmScriptGenerator::CreateConfigTest(const std::string& config)
std::string cmScriptGenerator::CreateConfigTest(
std::vector<std::string> const& configs)
{
- std::string result = "\"${";
- result += this->RuntimeConfigVariable;
- result += "}\" MATCHES \"^(";
+ std::string result =
+ cmStrCat("\"${", this->RuntimeConfigVariable, "}\" MATCHES \"^(");
const char* sep = "";
- for (std::vector<std::string>::const_iterator ci = configs.begin();
- ci != configs.end(); ++ci) {
+ for (std::string const& config : configs) {
result += sep;
sep = "|";
- cmScriptGeneratorEncodeConfig(*ci, result);
+ cmScriptGeneratorEncodeConfig(config, result);
}
result += ")$\"";
return result;
@@ -123,10 +120,8 @@ bool cmScriptGenerator::GeneratesForConfig(const std::string& config)
// This is a configuration-specific rule. Check if the config
// matches this rule.
std::string config_upper = cmSystemTools::UpperCase(config);
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- if (cmSystemTools::UpperCase(*i) == config_upper) {
+ for (std::string const& cfg : this->Configurations) {
+ if (cmSystemTools::UpperCase(cfg) == config_upper) {
return true;
}
}
@@ -163,15 +158,12 @@ void cmScriptGenerator::GenerateScriptActionsPerConfig(std::ostream& os,
// in a block for each configuration that is built. We restrict
// the list of configurations to those to which this rule applies.
bool first = true;
- for (std::vector<std::string>::const_iterator i =
- this->ConfigurationTypes->begin();
- i != this->ConfigurationTypes->end(); ++i) {
- const char* config = i->c_str();
- if (this->GeneratesForConfig(config)) {
+ for (std::string const& cfgType : *this->ConfigurationTypes) {
+ if (this->GeneratesForConfig(cfgType)) {
// Generate a per-configuration block.
- std::string config_test = this->CreateConfigTest(config);
+ std::string config_test = this->CreateConfigTest(cfgType);
os << indent << (first ? "if(" : "elseif(") << config_test << ")\n";
- this->GenerateScriptForConfig(os, config, indent.Next());
+ this->GenerateScriptForConfig(os, cfgType, indent.Next());
first = false;
}
}
diff --git a/Source/cmScriptGenerator.h b/Source/cmScriptGenerator.h
index d0879c687..c8bb1ab15 100644
--- a/Source/cmScriptGenerator.h
+++ b/Source/cmScriptGenerator.h
@@ -3,7 +3,7 @@
#ifndef cmScriptGenerator_h
#define cmScriptGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <ostream>
#include <string>
@@ -12,10 +12,7 @@
class cmScriptGeneratorIndent
{
public:
- cmScriptGeneratorIndent()
- : Level(0)
- {
- }
+ cmScriptGeneratorIndent() = default;
cmScriptGeneratorIndent(int level)
: Level(level)
{
@@ -28,11 +25,11 @@ public:
}
cmScriptGeneratorIndent Next(int step = 2) const
{
- return cmScriptGeneratorIndent(this->Level + step);
+ return { this->Level + step };
}
private:
- int Level;
+ int Level = 0;
};
inline std::ostream& operator<<(std::ostream& os,
cmScriptGeneratorIndent indent)
@@ -47,18 +44,19 @@ inline std::ostream& operator<<(std::ostream& os,
*/
class cmScriptGenerator
{
- CM_DISABLE_COPY(cmScriptGenerator)
-
public:
- cmScriptGenerator(const std::string& config_var,
- std::vector<std::string> const& configurations);
+ cmScriptGenerator(std::string config_var,
+ std::vector<std::string> configurations);
virtual ~cmScriptGenerator();
+ cmScriptGenerator(cmScriptGenerator const&) = delete;
+ cmScriptGenerator& operator=(cmScriptGenerator const&) = delete;
+
void Generate(std::ostream& os, const std::string& config,
std::vector<std::string> const& configurationTypes);
protected:
- typedef cmScriptGeneratorIndent Indent;
+ using Indent = cmScriptGeneratorIndent;
virtual void GenerateScript(std::ostream& os);
virtual void GenerateScriptConfigs(std::ostream& os, Indent indent);
virtual void GenerateScriptActions(std::ostream& os, Indent indent);
diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx
index 0df6e0c06..d15ce5749 100644
--- a/Source/cmSearchPath.cxx
+++ b/Source/cmSearchPath.cxx
@@ -6,9 +6,9 @@
#include <cassert>
#include <utility>
-#include "cmAlgorithms.h"
#include "cmFindCommon.h"
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
cmSearchPath::cmSearchPath(cmFindCommon* findCmd)
@@ -16,9 +16,7 @@ cmSearchPath::cmSearchPath(cmFindCommon* findCmd)
{
}
-cmSearchPath::~cmSearchPath()
-{
-}
+cmSearchPath::~cmSearchPath() = default;
void cmSearchPath::ExtractWithout(const std::set<std::string>& ignore,
std::vector<std::string>& outPaths,
@@ -27,10 +25,9 @@ void cmSearchPath::ExtractWithout(const std::set<std::string>& ignore,
if (clear) {
outPaths.clear();
}
- for (std::vector<std::string>::const_iterator p = this->Paths.begin();
- p != this->Paths.end(); ++p) {
- if (ignore.count(*p) == 0) {
- outPaths.push_back(*p);
+ for (std::string const& path : this->Paths) {
+ if (ignore.count(path) == 0) {
+ outPaths.push_back(path);
}
}
}
@@ -42,7 +39,7 @@ void cmSearchPath::AddPath(const std::string& path)
void cmSearchPath::AddUserPath(const std::string& path)
{
- assert(this->FC != CM_NULLPTR);
+ assert(this->FC != nullptr);
std::vector<std::string> outPaths;
@@ -69,25 +66,23 @@ void cmSearchPath::AddUserPath(const std::string& path)
}
// Process them all from the current directory
- for (std::vector<std::string>::const_iterator p = outPaths.begin();
- p != outPaths.end(); ++p) {
- this->AddPathInternal(*p, this->FC->Makefile->GetCurrentSourceDirectory());
+ for (std::string const& p : outPaths) {
+ this->AddPathInternal(
+ p, this->FC->Makefile->GetCurrentSourceDirectory().c_str());
}
}
void cmSearchPath::AddCMakePath(const std::string& variable)
{
- assert(this->FC != CM_NULLPTR);
+ assert(this->FC != nullptr);
// Get a path from a CMake variable.
if (const char* value = this->FC->Makefile->GetDefinition(variable)) {
- std::vector<std::string> expanded;
- cmSystemTools::ExpandListArgument(value, expanded);
+ std::vector<std::string> expanded = cmExpandedList(value);
- for (std::vector<std::string>::const_iterator p = expanded.begin();
- p != expanded.end(); ++p) {
- this->AddPathInternal(*p,
- this->FC->Makefile->GetCurrentSourceDirectory());
+ for (std::string const& p : expanded) {
+ this->AddPathInternal(
+ p, this->FC->Makefile->GetCurrentSourceDirectory().c_str());
}
}
}
@@ -96,23 +91,21 @@ void cmSearchPath::AddEnvPath(const std::string& variable)
{
std::vector<std::string> expanded;
cmSystemTools::GetPath(expanded, variable.c_str());
- for (std::vector<std::string>::const_iterator p = expanded.begin();
- p != expanded.end(); ++p) {
- this->AddPathInternal(*p);
+ for (std::string const& p : expanded) {
+ this->AddPathInternal(p);
}
}
void cmSearchPath::AddCMakePrefixPath(const std::string& variable)
{
- assert(this->FC != CM_NULLPTR);
+ assert(this->FC != nullptr);
// Get a path from a CMake variable.
if (const char* value = this->FC->Makefile->GetDefinition(variable)) {
- std::vector<std::string> expanded;
- cmSystemTools::ExpandListArgument(value, expanded);
+ std::vector<std::string> expanded = cmExpandedList(value);
- this->AddPrefixPaths(expanded,
- this->FC->Makefile->GetCurrentSourceDirectory());
+ this->AddPrefixPaths(
+ expanded, this->FC->Makefile->GetCurrentSourceDirectory().c_str());
}
}
@@ -142,33 +135,31 @@ void cmSearchPath::AddSuffixes(const std::vector<std::string>& suffixes)
inPaths.swap(this->Paths);
this->Paths.reserve(inPaths.size() * (suffixes.size() + 1));
- for (std::vector<std::string>::iterator ip = inPaths.begin();
- ip != inPaths.end(); ++ip) {
- cmSystemTools::ConvertToUnixSlashes(*ip);
+ for (std::string& inPath : inPaths) {
+ cmSystemTools::ConvertToUnixSlashes(inPath);
// if *i is only / then do not add a //
// this will get incorrectly considered a network
// path on windows and cause huge delays.
- std::string p = *ip;
- if (!p.empty() && *p.rbegin() != '/') {
+ std::string p = inPath;
+ if (!p.empty() && p.back() != '/') {
p += "/";
}
// Combine with all the suffixes
- for (std::vector<std::string>::const_iterator s = suffixes.begin();
- s != suffixes.end(); ++s) {
- this->Paths.push_back(p + *s);
+ for (std::string const& suffix : suffixes) {
+ this->Paths.push_back(p + suffix);
}
// And now the original w/o any suffix
- this->Paths.push_back(*ip);
+ this->Paths.push_back(std::move(inPath));
}
}
void cmSearchPath::AddPrefixPaths(const std::vector<std::string>& paths,
const char* base)
{
- assert(this->FC != CM_NULLPTR);
+ assert(this->FC != nullptr);
// default for programs
std::string subdir = "bin";
@@ -178,13 +169,12 @@ void cmSearchPath::AddPrefixPaths(const std::vector<std::string>& paths,
} else if (this->FC->CMakePathName == "LIBRARY") {
subdir = "lib";
} else if (this->FC->CMakePathName == "FRAMEWORK") {
- subdir = ""; // ? what to do for frameworks ?
+ subdir.clear(); // ? what to do for frameworks ?
}
- for (std::vector<std::string>::const_iterator p = paths.begin();
- p != paths.end(); ++p) {
- std::string dir = *p;
- if (!subdir.empty() && !dir.empty() && *dir.rbegin() != '/') {
+ for (std::string const& path : paths) {
+ std::string dir = path;
+ if (!subdir.empty() && !dir.empty() && dir.back() != '/') {
dir += "/";
}
if (subdir == "include" || subdir == "lib") {
@@ -201,15 +191,15 @@ void cmSearchPath::AddPrefixPaths(const std::vector<std::string>& paths,
if (subdir == "bin") {
this->AddPathInternal(dir + "sbin", base);
}
- if (!subdir.empty() && *p != "/") {
- this->AddPathInternal(*p, base);
+ if (!subdir.empty() && path != "/") {
+ this->AddPathInternal(path, base);
}
}
}
void cmSearchPath::AddPathInternal(const std::string& path, const char* base)
{
- assert(this->FC != CM_NULLPTR);
+ assert(this->FC != nullptr);
std::string collapsed = cmSystemTools::CollapseFullPath(path, base);
@@ -219,6 +209,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/cmSearchPath.h b/Source/cmSearchPath.h
index 932022aa1..2a576ed59 100644
--- a/Source/cmSearchPath.h
+++ b/Source/cmSearchPath.h
@@ -3,7 +3,7 @@
#ifndef cmSearchPath_h
#define cmSearchPath_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <set>
#include <string>
@@ -23,7 +23,7 @@ public:
// cmSearchPath must be initialized from a valid pointer. The only reason
// for the default is to allow it to be easily used in stl containers.
// Attempting to initialize with a NULL value will fail an assertion
- cmSearchPath(cmFindCommon* findCmd = CM_NULLPTR);
+ cmSearchPath(cmFindCommon* findCmd = nullptr);
~cmSearchPath();
const std::vector<std::string>& GetPaths() const { return this->Paths; }
@@ -39,11 +39,11 @@ public:
void AddCMakePrefixPath(const std::string& variable);
void AddEnvPrefixPath(const std::string& variable, bool stripBin = false);
void AddSuffixes(const std::vector<std::string>& suffixes);
+ void AddPrefixPaths(const std::vector<std::string>& paths,
+ const char* base = nullptr);
protected:
- void AddPrefixPaths(const std::vector<std::string>& paths,
- const char* base = CM_NULLPTR);
- void AddPathInternal(const std::string& path, const char* base = CM_NULLPTR);
+ void AddPathInternal(const std::string& path, const char* base = nullptr);
cmFindCommon* FC;
std::vector<std::string> Paths;
diff --git a/Source/cmSeparateArgumentsCommand.cxx b/Source/cmSeparateArgumentsCommand.cxx
index 7b222a041..52bde7c5c 100644
--- a/Source/cmSeparateArgumentsCommand.cxx
+++ b/Source/cmSeparateArgumentsCommand.cxx
@@ -3,19 +3,18 @@
#include "cmSeparateArgumentsCommand.h"
#include <algorithm>
-#include <sstream>
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
-
// cmSeparateArgumentsCommand
-bool cmSeparateArgumentsCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmSeparateArgumentsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("must be given at least one argument.");
+ status.SetError("must be given at least one argument.");
return false;
}
@@ -36,40 +35,38 @@ bool cmSeparateArgumentsCommand::InitialPass(
DoingCommand
};
Doing doing = DoingVariable;
- for (unsigned int i = 0; i < args.size(); ++i) {
+ for (std::string const& arg : args) {
if (doing == DoingVariable) {
- var = args[i];
+ var = arg;
doing = DoingMode;
- } else if (doing == DoingMode && args[i] == "NATIVE_COMMAND") {
+ } else if (doing == DoingMode && arg == "NATIVE_COMMAND") {
#ifdef _WIN32
mode = ModeWindows;
#else
mode = ModeUnix;
#endif
doing = DoingCommand;
- } else if (doing == DoingMode && args[i] == "UNIX_COMMAND") {
+ } else if (doing == DoingMode && arg == "UNIX_COMMAND") {
mode = ModeUnix;
doing = DoingCommand;
- } else if (doing == DoingMode && args[i] == "WINDOWS_COMMAND") {
+ } else if (doing == DoingMode && arg == "WINDOWS_COMMAND") {
mode = ModeWindows;
doing = DoingCommand;
} else if (doing == DoingCommand) {
- command = args[i];
+ command = arg;
doing = DoingNone;
} else {
- std::ostringstream e;
- e << "given unknown argument " << args[i];
- this->SetError(e.str());
+ status.SetError(cmStrCat("given unknown argument ", arg));
return false;
}
}
if (mode == ModeOld) {
// Original space-replacement version of command.
- if (const char* def = this->Makefile->GetDefinition(var)) {
+ if (const char* def = status.GetMakefile().GetDefinition(var)) {
std::string value = def;
std::replace(value.begin(), value.end(), ' ', ';');
- this->Makefile->AddDefinition(var, value.c_str());
+ status.GetMakefile().AddDefinition(var, value);
}
} else {
// Parse the command line.
@@ -84,22 +81,20 @@ bool cmSeparateArgumentsCommand::InitialPass(
// Construct the result list value.
std::string value;
const char* sep = "";
- for (std::vector<std::string>::const_iterator vi = vec.begin();
- vi != vec.end(); ++vi) {
+ for (std::string const& vi : vec) {
// Separate from the previous argument.
value += sep;
sep = ";";
// Preserve semicolons.
- for (std::string::const_iterator si = vi->begin(); si != vi->end();
- ++si) {
- if (*si == ';') {
+ for (char si : vi) {
+ if (si == ';') {
value += '\\';
}
- value += *si;
+ value += si;
}
}
- this->Makefile->AddDefinition(var, value.c_str());
+ status.GetMakefile().AddDefinition(var, value);
}
return true;
diff --git a/Source/cmSeparateArgumentsCommand.h b/Source/cmSeparateArgumentsCommand.h
index 6bf8549cf..e000c511d 100644
--- a/Source/cmSeparateArgumentsCommand.h
+++ b/Source/cmSeparateArgumentsCommand.h
@@ -3,34 +3,19 @@
#ifndef cmSeparateArgumentsCommand_h
#define cmSeparateArgumentsCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmSeparateArgumentsCommand
+/**
* \brief separate_arguments command
*
* cmSeparateArgumentsCommand implements the separate_arguments CMake command
*/
-class cmSeparateArgumentsCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmSeparateArgumentsCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmSeparateArgumentsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx
index 7fc6ed755..3b2e5f322 100644
--- a/Source/cmServer.cxx
+++ b/Source/cmServer.cxx
@@ -2,19 +2,43 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmServer.h"
-#include "cmServerConnection.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <iostream>
+#include <mutex>
+#include <utility>
+
+#include <cm/memory>
+#include <cm/shared_mutex>
+
+#include "cmsys/FStream.hxx"
+
+#include "cm_jsoncpp_reader.h"
+#include "cm_jsoncpp_writer.h"
+
+#include "cmConnection.h"
+#include "cmFileMonitor.h"
+#include "cmJsonObjectDictionary.h"
#include "cmServerDictionary.h"
#include "cmServerProtocol.h"
#include "cmSystemTools.h"
-#include "cm_jsoncpp_reader.h"
-#include "cm_jsoncpp_writer.h"
#include "cmake.h"
-#include "cmsys/FStream.hxx"
-#include <algorithm>
-#include <cassert>
-#include <cstdint>
-#include <utility>
+void on_signal(uv_signal_t* signal, int signum)
+{
+ 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);
+ }
+}
class cmServer::DebugInfo
{
@@ -30,76 +54,73 @@ public:
uint64_t StartTime;
};
-cmServer::cmServer(cmServerConnection* conn, bool supportExperimental)
- : Connection(conn)
+cmServer::cmServer(cmConnection* conn, bool supportExperimental)
+ : cmServerBase(conn)
, SupportExperimental(supportExperimental)
{
- this->Connection->SetServer(this);
// Register supported protocols:
- this->RegisterProtocol(new cmServerProtocol1_0);
+ this->RegisterProtocol(new cmServerProtocol1);
}
cmServer::~cmServer()
{
- if (!this->Protocol) { // Server was never fully started!
- return;
- }
+ Close();
for (cmServerProtocol* p : this->SupportedProtocols) {
delete p;
}
-
- delete this->Connection;
}
-void cmServer::PopOne()
+void cmServer::ProcessRequest(cmConnection* connection,
+ const std::string& input)
{
- if (this->Queue.empty()) {
- return;
- }
-
Json::Reader reader;
Json::Value value;
- const std::string input = this->Queue.front();
- this->Queue.erase(this->Queue.begin());
-
if (!reader.parse(input, value)) {
- this->WriteParseError("Failed to parse JSON input.");
+ this->WriteParseError(connection, "Failed to parse JSON input.");
return;
}
std::unique_ptr<DebugInfo> debug;
Json::Value debugValue = value["debug"];
if (!debugValue.isNull()) {
- debug = std::make_unique<DebugInfo>();
+ debug = cm::make_unique<DebugInfo>();
debug->OutputFile = debugValue["dumpToFile"].asString();
debug->PrintStatistics = debugValue["showStats"].asBool();
}
- const cmServerRequest request(this, value[kTYPE_KEY].asString(),
+ const cmServerRequest request(this, connection, value[kTYPE_KEY].asString(),
value[kCOOKIE_KEY].asString(), value);
- if (request.Type == "") {
+ if (request.Type.empty()) {
cmServerResponse response(request);
response.SetError("No type given in request.");
- this->WriteResponse(response, nullptr);
+ this->WriteResponse(connection, response, nullptr);
return;
}
- cmSystemTools::SetMessageCallback(reportMessage,
- const_cast<cmServerRequest*>(&request));
+ cmSystemTools::SetMessageCallback(
+ [&request](const std::string& msg, const char* title) {
+ reportMessage(msg, title, request);
+ });
+
if (this->Protocol) {
this->Protocol->CMakeInstance()->SetProgressCallback(
- reportProgress, const_cast<cmServerRequest*>(&request));
- this->WriteResponse(this->Protocol->Process(request), debug.get());
+ [&request](const std::string& msg, float prog) {
+ reportProgress(msg, prog, request);
+ });
+ this->WriteResponse(connection, this->Protocol->Process(request),
+ debug.get());
} else {
- this->WriteResponse(this->SetProtocolVersion(request), debug.get());
+ this->WriteResponse(connection, this->SetProtocolVersion(request),
+ debug.get());
}
}
void cmServer::RegisterProtocol(cmServerProtocol* protocol)
{
if (protocol->IsExperimental() && !this->SupportExperimental) {
+ delete protocol;
return;
}
auto version = protocol->ProtocolVersion();
@@ -115,7 +136,7 @@ void cmServer::RegisterProtocol(cmServerProtocol* protocol)
}
}
-void cmServer::PrintHello() const
+void cmServer::PrintHello(cmConnection* connection) const
{
Json::Value hello = Json::objectValue;
hello[kTYPE_KEY] = "hello";
@@ -134,37 +155,27 @@ void cmServer::PrintHello() const
protocolVersions.append(tmp);
}
- this->WriteJsonObject(hello, nullptr);
-}
-
-void cmServer::QueueRequest(const std::string& request)
-{
- this->Queue.push_back(request);
- this->PopOne();
+ this->WriteJsonObject(connection, hello, nullptr);
}
-void cmServer::reportProgress(const char* msg, float progress, void* data)
+void cmServer::reportProgress(const std::string& msg, float progress,
+ const cmServerRequest& request)
{
- const cmServerRequest* request = static_cast<const cmServerRequest*>(data);
- assert(request);
if (progress < 0.0f || progress > 1.0f) {
- request->ReportMessage(msg, "");
+ request.ReportMessage(msg, "");
} else {
- request->ReportProgress(0, static_cast<int>(progress * 1000), 1000, msg);
+ request.ReportProgress(0, static_cast<int>(progress * 1000), 1000, msg);
}
}
-void cmServer::reportMessage(const char* msg, const char* title,
- bool& /* cancel */, void* data)
+void cmServer::reportMessage(const std::string& msg, const char* title,
+ const cmServerRequest& request)
{
- const cmServerRequest* request = static_cast<const cmServerRequest*>(data);
- assert(request);
- assert(msg);
std::string titleString;
if (title) {
titleString = title;
}
- request->ReportMessage(std::string(msg), titleString);
+ request.ReportMessage(msg, titleString);
}
cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request)
@@ -209,14 +220,14 @@ cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request)
}
this->Protocol =
- this->FindMatchingProtocol(this->SupportedProtocols, major, minor);
+ cmServer::FindMatchingProtocol(this->SupportedProtocols, major, minor);
if (!this->Protocol) {
return request.ReportError("Protocol version not supported.");
}
std::string errorMessage;
if (!this->Protocol->Activate(this, request, &errorMessage)) {
- this->Protocol = CM_NULLPTR;
+ this->Protocol = nullptr;
return request.ReportError("Failed to activate protocol version: " +
errorMessage);
}
@@ -232,17 +243,27 @@ bool cmServer::Serve(std::string* errorMessage)
}
assert(!this->Protocol);
- return Connection->ProcessEvents(errorMessage);
+ return cmServerBase::Serve(errorMessage);
}
cmFileMonitor* cmServer::FileMonitor() const
{
- return Connection->FileMonitor();
+ return fileMonitor.get();
}
void cmServer::WriteJsonObject(const Json::Value& jsonValue,
const DebugInfo* debug) const
{
+ cm::shared_lock<cm::shared_mutex> lock(ConnectionsMutex);
+ for (auto& connection : this->Connections) {
+ WriteJsonObject(connection.get(), jsonValue, debug);
+ }
+}
+
+void cmServer::WriteJsonObject(cmConnection* connection,
+ const Json::Value& jsonValue,
+ const DebugInfo* debug) const
+{
Json::FastWriter writer;
auto beforeJson = uv_hrtime();
@@ -272,8 +293,7 @@ void cmServer::WriteJsonObject(const Json::Value& jsonValue,
}
}
- Connection->WriteData(std::string("\n") + kSTART_MAGIC + std::string("\n") +
- result + kEND_MAGIC + std::string("\n"));
+ connection->WriteData(result);
}
cmServerProtocol* cmServer::FindMatchingProtocol(
@@ -311,7 +331,7 @@ void cmServer::WriteProgress(const cmServerRequest& request, int min,
obj[kPROGRESS_MAXIMUM_KEY] = max;
obj[kPROGRESS_CURRENT_KEY] = current;
- this->WriteJsonObject(obj, nullptr);
+ this->WriteJsonObject(request.Connection, obj, nullptr);
}
void cmServer::WriteMessage(const cmServerRequest& request,
@@ -331,10 +351,11 @@ void cmServer::WriteMessage(const cmServerRequest& request,
obj[kTITLE_KEY] = title;
}
- WriteJsonObject(obj, nullptr);
+ WriteJsonObject(request.Connection, obj, nullptr);
}
-void cmServer::WriteParseError(const std::string& message) const
+void cmServer::WriteParseError(cmConnection* connection,
+ const std::string& message) const
{
Json::Value obj = Json::objectValue;
obj[kTYPE_KEY] = kERROR_TYPE;
@@ -342,7 +363,7 @@ void cmServer::WriteParseError(const std::string& message) const
obj[kREPLY_TO_KEY] = "";
obj[kCOOKIE_KEY] = "";
- this->WriteJsonObject(obj, nullptr);
+ this->WriteJsonObject(connection, obj, nullptr);
}
void cmServer::WriteSignal(const std::string& name,
@@ -358,7 +379,8 @@ void cmServer::WriteSignal(const std::string& name,
WriteJsonObject(obj, nullptr);
}
-void cmServer::WriteResponse(const cmServerResponse& response,
+void cmServer::WriteResponse(cmConnection* connection,
+ const cmServerResponse& response,
const DebugInfo* debug) const
{
assert(response.IsComplete());
@@ -371,5 +393,180 @@ void cmServer::WriteResponse(const cmServerResponse& response,
obj[kERROR_MESSAGE_KEY] = response.ErrorMessage();
}
- this->WriteJsonObject(obj, debug);
+ this->WriteJsonObject(connection, obj, debug);
+}
+
+void cmServer::OnConnected(cmConnection* connection)
+{
+ PrintHello(connection);
+}
+
+void cmServer::OnServeStart()
+{
+ cmServerBase::OnServeStart();
+ fileMonitor = std::make_shared<cmFileMonitor>(GetLoop());
+}
+
+void cmServer::StartShutDown()
+{
+ if (fileMonitor) {
+ fileMonitor->StopMonitoring();
+ fileMonitor.reset();
+ }
+ cmServerBase::StartShutDown();
+}
+
+static void __start_thread(void* arg)
+{
+ auto server = static_cast<cmServerBase*>(arg);
+ std::string error;
+ bool success = server->Serve(&error);
+ if (!success || !error.empty()) {
+ std::cerr << "Error during serve: " << error << std::endl;
+ }
+}
+
+bool cmServerBase::StartServeThread()
+{
+ ServeThreadRunning = true;
+ 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
+ uv_thread_t blank_thread_t = {};
+ assert(uv_thread_equal(&blank_thread_t, &ServeThreadId));
+ ServeThreadId = uv_thread_self();
+#endif
+
+ errorMessage->clear();
+
+ ShutdownSignal.init(Loop, __shutdownThread, this);
+
+ SIGINTHandler.init(Loop, this);
+ SIGHUPHandler.init(Loop, this);
+
+ SIGINTHandler.start(&on_signal, SIGINT);
+ SIGHUPHandler.start(&on_signal, SIGHUP);
+
+ OnServeStart();
+
+ {
+ cm::shared_lock<cm::shared_mutex> lock(ConnectionsMutex);
+ for (auto& connection : Connections) {
+ if (!connection->OnServeStart(errorMessage)) {
+ return false;
+ }
+ }
+ }
+
+ if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) {
+ // It is important we don't ever let the event loop exit with open handles
+ // at best this is a memory leak, but it can also introduce race conditions
+ // which can hang the program.
+ assert(false && "Event loop stopped in unclean state.");
+
+ *errorMessage = "Internal Error: Event loop stopped in unclean state.";
+ return false;
+ }
+
+ return true;
+}
+
+void cmServerBase::OnConnected(cmConnection*)
+{
+}
+
+void cmServerBase::OnServeStart()
+{
+}
+
+void cmServerBase::StartShutDown()
+{
+ ShutdownSignal.reset();
+ SIGINTHandler.reset();
+ SIGHUPHandler.reset();
+
+ {
+ std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
+ for (auto& connection : Connections) {
+ connection->OnConnectionShuttingDown();
+ }
+ Connections.clear();
+ }
+
+ uv_walk(&Loop, on_walk_to_shutdown, nullptr);
+}
+
+bool cmServerBase::OnSignal(int signum)
+{
+ (void)signum;
+ StartShutDown();
+ return true;
+}
+
+cmServerBase::cmServerBase(cmConnection* connection)
+{
+ auto err = uv_loop_init(&Loop);
+ (void)err;
+ Loop.data = this;
+ assert(err == 0);
+
+ AddNewConnection(connection);
+}
+
+void cmServerBase::Close()
+{
+ if (Loop.data) {
+ if (ServeThreadRunning) {
+ this->ShutdownSignal.send();
+ uv_thread_join(&ServeThread);
+ }
+
+ uv_loop_close(&Loop);
+ Loop.data = nullptr;
+ }
+}
+cmServerBase::~cmServerBase()
+{
+ Close();
+}
+
+void cmServerBase::AddNewConnection(cmConnection* ownedConnection)
+{
+ {
+ std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
+ Connections.emplace_back(ownedConnection);
+ }
+ ownedConnection->SetServer(this);
+}
+
+uv_loop_t* cmServerBase::GetLoop()
+{
+ return &Loop;
+}
+
+void cmServerBase::OnDisconnect(cmConnection* pConnection)
+{
+ auto pred = [pConnection](const std::unique_ptr<cmConnection>& m) {
+ return m.get() == pConnection;
+ };
+ {
+ std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
+ Connections.erase(
+ std::remove_if(Connections.begin(), Connections.end(), pred),
+ Connections.end());
+ }
+
+ if (Connections.empty()) {
+ this->ShutdownSignal.send();
+ }
}
diff --git a/Source/cmServer.h b/Source/cmServer.h
index b8140504c..3d7027b39 100644
--- a/Source/cmServer.h
+++ b/Source/cmServer.h
@@ -2,31 +2,103 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <cm/shared_mutex>
#include "cm_jsoncpp_value.h"
#include "cm_uv.h"
-#include <string>
-#include <vector>
+#include "cmUVHandlePtr.h"
+class cmConnection;
class cmFileMonitor;
-class cmServerConnection;
class cmServerProtocol;
class cmServerRequest;
class cmServerResponse;
-class cmServer
+/***
+ * This essentially hold and manages a libuv event queue and responds to
+ * messages
+ * on any of its connections.
+ */
+class cmServerBase
{
- CM_DISABLE_COPY(cmServer)
+public:
+ cmServerBase(cmConnection* connection);
+ virtual ~cmServerBase();
+
+ virtual void AddNewConnection(cmConnection* ownedConnection);
+
+ /***
+ * The main override responsible for tailoring behavior towards
+ * whatever the given server is supposed to do
+ *
+ * This should almost always be called by the given connections
+ * directly.
+ *
+ * @param connection The connection the request was received on
+ * @param request The actual request
+ */
+ virtual void ProcessRequest(cmConnection* connection,
+ const std::string& request) = 0;
+ virtual void OnConnected(cmConnection* connection);
+
+ /***
+ * Start a dedicated thread. If this is used to start the server, it will
+ * join on the
+ * servers dtor.
+ */
+ virtual bool StartServeThread();
+ virtual bool Serve(std::string* errorMessage);
+
+ virtual void OnServeStart();
+ virtual void StartShutDown();
+
+ virtual bool OnSignal(int signum);
+ uv_loop_t* GetLoop();
+ void Close();
+ void OnDisconnect(cmConnection* pConnection);
+
+protected:
+ mutable cm::shared_mutex ConnectionsMutex;
+ std::vector<std::unique_ptr<cmConnection>> Connections;
+
+ bool ServeThreadRunning = false;
+ uv_thread_t ServeThread;
+ cm::uv_async_ptr ShutdownSignal;
+#ifndef NDEBUG
+public:
+ // When the server starts it will mark down it's current thread ID,
+ // which is useful in other contexts to just assert that operations
+ // are performed on that same thread.
+ uv_thread_t ServeThreadId = {};
+
+protected:
+#endif
+ uv_loop_t Loop;
+
+ cm::uv_signal_ptr SIGINTHandler;
+ cm::uv_signal_ptr SIGHUPHandler;
+};
+
+class cmServer : public cmServerBase
+{
public:
class DebugInfo;
- cmServer(cmServerConnection* conn, bool supportExperimental);
- ~cmServer();
+ cmServer(cmConnection* conn, bool supportExperimental);
+ ~cmServer() override;
+
+ cmServer(cmServer const&) = delete;
+ cmServer& operator=(cmServer const&) = delete;
- bool Serve(std::string* errorMessage);
+ bool Serve(std::string* errorMessage) override;
cmFileMonitor* FileMonitor() const;
@@ -34,60 +106,56 @@ private:
void RegisterProtocol(cmServerProtocol* protocol);
// Callbacks from cmServerConnection:
- void PopOne();
- void QueueRequest(const std::string& request);
- static void reportProgress(const char* msg, float progress, void* data);
- static void reportMessage(const char* msg, const char* title, bool& cancel,
- void* data);
+ void ProcessRequest(cmConnection* connection,
+ const std::string& request) override;
+ std::shared_ptr<cmFileMonitor> fileMonitor;
+
+public:
+ void OnServeStart() override;
+
+ void StartShutDown() override;
+
+public:
+ void OnConnected(cmConnection* connection) override;
+
+private:
+ static void reportProgress(const std::string& msg, float progress,
+ const cmServerRequest& request);
+ static void reportMessage(const std::string& msg, const char* title,
+ const cmServerRequest& request);
// Handle requests:
cmServerResponse SetProtocolVersion(const cmServerRequest& request);
- void PrintHello() const;
+ void PrintHello(cmConnection* connection) const;
// Write responses:
void WriteProgress(const cmServerRequest& request, int min, int current,
int max, const std::string& message) const;
void WriteMessage(const cmServerRequest& request, const std::string& message,
const std::string& title) const;
- void WriteResponse(const cmServerResponse& response,
+ void WriteResponse(cmConnection* connection,
+ const cmServerResponse& response,
const DebugInfo* debug) const;
- void WriteParseError(const std::string& message) const;
+ void WriteParseError(cmConnection* connection,
+ const std::string& message) const;
void WriteSignal(const std::string& name, const Json::Value& obj) const;
void WriteJsonObject(Json::Value const& jsonValue,
const DebugInfo* debug) const;
+ void WriteJsonObject(cmConnection* connection, Json::Value const& jsonValue,
+ const DebugInfo* debug) const;
+
static cmServerProtocol* FindMatchingProtocol(
const std::vector<cmServerProtocol*>& protocols, int major, int minor);
- cmServerConnection* Connection = nullptr;
const bool SupportExperimental;
cmServerProtocol* Protocol = nullptr;
std::vector<cmServerProtocol*> SupportedProtocols;
- std::vector<std::string> Queue;
-
- std::string DataBuffer;
- std::string JsonData;
-
- uv_loop_t* Loop = nullptr;
-
- typedef union
- {
- uv_tty_t tty;
- uv_pipe_t pipe;
- } InOutUnion;
-
- InOutUnion Input;
- InOutUnion Output;
- uv_stream_t* InputStream = nullptr;
- uv_stream_t* OutputStream = nullptr;
-
- mutable bool Writing = false;
- friend class cmServerConnection;
friend class cmServerProtocol;
friend class cmServerRequest;
};
diff --git a/Source/cmServerConnection.cxx b/Source/cmServerConnection.cxx
index 36312edf4..279197214 100644
--- a/Source/cmServerConnection.cxx
+++ b/Source/cmServerConnection.cxx
@@ -1,377 +1,165 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmConfigure.h"
+
#include "cmServerConnection.h"
-#include "cmFileMonitor.h"
+#include "cm_uv.h"
+
#include "cmServer.h"
#include "cmServerDictionary.h"
-#include <assert.h>
-#include <string.h>
+#ifdef _WIN32
+# include "io.h"
+#else
+# include <unistd.h>
+#endif
+#include <cassert>
+#include <utility>
-namespace {
-
-struct write_req_t
+cmStdIoConnection::cmStdIoConnection(
+ cmConnectionBufferStrategy* bufferStrategy)
+ : cmEventBasedConnection(bufferStrategy)
{
- uv_write_t req;
- uv_buf_t buf;
-};
-
-void on_alloc_buffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
-{
- (void)(handle);
- char* rawBuffer = new char[suggested_size];
- *buf = uv_buf_init(rawBuffer, static_cast<unsigned int>(suggested_size));
}
-void on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
+cm::uv_stream_ptr cmStdIoConnection::SetupStream(int file_id)
{
- auto conn = reinterpret_cast<cmServerConnection*>(stream->data);
- if (nread >= 0) {
- conn->ReadData(std::string(buf->base, buf->base + nread));
- } else {
- conn->TriggerShutdown();
+ switch (uv_guess_handle(file_id)) {
+ case UV_TTY: {
+ 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);
+ return { std::move(tty) };
+ }
+ case UV_FILE:
+ if (file_id == 0) {
+ return nullptr;
+ }
+ // Intentional fallthrough; stdin can _not_ be treated as a named
+ // pipe, however stdout can be.
+ CM_FALLTHROUGH;
+ case UV_NAMED_PIPE: {
+ cm::uv_pipe_ptr pipe;
+ pipe.init(*this->Server->GetLoop(), 0,
+ static_cast<cmEventBasedConnection*>(this));
+ uv_pipe_open(pipe, file_id);
+ return { std::move(pipe) };
+ }
+ default:
+ assert(false && "Unable to determine stream type");
+ return nullptr;
}
-
- delete[](buf->base);
}
-void on_write(uv_write_t* req, int status)
+void cmStdIoConnection::SetServer(cmServerBase* s)
{
- (void)(status);
- auto conn = reinterpret_cast<cmServerConnection*>(req->data);
-
- // Free req and buffer
- write_req_t* wr = reinterpret_cast<write_req_t*>(req);
- delete[](wr->buf.base);
- delete wr;
-
- conn->ProcessNextRequest();
-}
+ cmConnection::SetServer(s);
+ if (!s) {
+ return;
+ }
-void on_new_connection(uv_stream_t* stream, int status)
-{
- (void)(status);
- auto conn = reinterpret_cast<cmServerConnection*>(stream->data);
- conn->Connect(stream);
+ this->ReadStream = SetupStream(0);
+ this->WriteStream = SetupStream(1);
}
-void on_signal(uv_signal_t* signal, int signum)
+void shutdown_connection(uv_prepare_t* prepare)
{
- auto conn = reinterpret_cast<cmServerConnection*>(signal->data);
- (void)(signum);
- conn->TriggerShutdown();
-}
+ cmStdIoConnection* connection =
+ static_cast<cmStdIoConnection*>(prepare->data);
-void on_signal_close(uv_handle_t* handle)
-{
- delete reinterpret_cast<uv_signal_t*>(handle);
+ if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(prepare))) {
+ uv_close(reinterpret_cast<uv_handle_t*>(prepare),
+ &cmEventBasedConnection::on_close_delete<uv_prepare_t>);
+ }
+ connection->OnDisconnect(0);
}
-void on_pipe_close(uv_handle_t* handle)
+bool cmStdIoConnection::OnServeStart(std::string* pString)
{
- delete reinterpret_cast<uv_pipe_t*>(handle);
-}
+ Server->OnConnected(this);
+ 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];
+ while (auto len = read(0, buffer, sizeof(buffer))) {
+ ReadData(std::string(buffer, buffer + len));
+ }
-void on_tty_close(uv_handle_t* handle)
-{
- delete reinterpret_cast<uv_tty_t*>(handle);
+ // We can't start the disconnect from here, add a prepare hook to do that
+ // for us
+ auto prepare = new uv_prepare_t();
+ prepare->data = this;
+ uv_prepare_init(Server->GetLoop(), prepare);
+ uv_prepare_start(prepare, shutdown_connection);
+ }
+ return cmConnection::OnServeStart(pString);
}
-} // namespace
-
-class LoopGuard
+bool cmStdIoConnection::OnConnectionShuttingDown()
{
-public:
- LoopGuard(cmServerConnection* connection)
- : Connection(connection)
- {
- this->Connection->mLoop = uv_default_loop();
- if (!this->Connection->mLoop) {
- return;
- }
- this->Connection->mFileMonitor =
- new cmFileMonitor(this->Connection->mLoop);
+ if (ReadStream.get()) {
+ uv_read_stop(ReadStream);
+ ReadStream->data = nullptr;
}
- ~LoopGuard()
- {
- if (!this->Connection->mLoop) {
- return;
- }
+ this->ReadStream.reset();
- if (this->Connection->mFileMonitor) {
- delete this->Connection->mFileMonitor;
- }
- uv_loop_close(this->Connection->mLoop);
- this->Connection->mLoop = nullptr;
- }
+ cmEventBasedConnection::OnConnectionShuttingDown();
-private:
- cmServerConnection* Connection;
-};
+ return true;
+}
-cmServerConnection::cmServerConnection()
+cmServerPipeConnection::cmServerPipeConnection(const std::string& name)
+ : cmPipeConnection(name, new cmServerBufferStrategy)
{
}
-cmServerConnection::~cmServerConnection()
+cmServerStdIoConnection::cmServerStdIoConnection()
+ : cmStdIoConnection(new cmServerBufferStrategy)
{
}
-void cmServerConnection::SetServer(cmServer* s)
+cmConnectionBufferStrategy::~cmConnectionBufferStrategy() = default;
+
+void cmConnectionBufferStrategy::clear()
{
- this->Server = s;
}
-bool cmServerConnection::ProcessEvents(std::string* errorMessage)
+std::string cmServerBufferStrategy::BufferOutMessage(
+ const std::string& rawBuffer) const
{
- assert(this->Server);
- errorMessage->clear();
-
- this->RawReadBuffer.clear();
- this->RequestBuffer.clear();
-
- LoopGuard guard(this);
- (void)(guard);
- if (!this->mLoop) {
- *errorMessage = "Internal Error: Failed to create event loop.";
- return false;
- }
-
- this->SIGINTHandler = new uv_signal_t;
- uv_signal_init(this->mLoop, this->SIGINTHandler);
- this->SIGINTHandler->data = static_cast<void*>(this);
- uv_signal_start(this->SIGINTHandler, &on_signal, SIGINT);
-
- this->SIGHUPHandler = new uv_signal_t;
- uv_signal_init(this->mLoop, this->SIGHUPHandler);
- this->SIGHUPHandler->data = static_cast<void*>(this);
- uv_signal_start(this->SIGHUPHandler, &on_signal, SIGHUP);
-
- if (!DoSetup(errorMessage)) {
- return false;
- }
-
- if (uv_run(this->mLoop, UV_RUN_DEFAULT) != 0) {
- *errorMessage = "Internal Error: Event loop stopped in unclean state.";
- return false;
- }
-
- // These need to be cleaned up by now:
- assert(!this->ReadStream);
- assert(!this->WriteStream);
-
- this->RawReadBuffer.clear();
- this->RequestBuffer.clear();
-
- return true;
+ return std::string("\n") + kSTART_MAGIC + std::string("\n") + rawBuffer +
+ kEND_MAGIC + std::string("\n");
}
-void cmServerConnection::ReadData(const std::string& data)
+std::string cmServerBufferStrategy::BufferMessage(std::string& RawReadBuffer)
{
- this->RawReadBuffer += data;
-
for (;;) {
- auto needle = this->RawReadBuffer.find('\n');
+ auto needle = RawReadBuffer.find('\n');
if (needle == std::string::npos) {
- return;
+ return "";
}
- std::string line = this->RawReadBuffer.substr(0, needle);
+ std::string line = RawReadBuffer.substr(0, needle);
const auto ls = line.size();
if (ls > 1 && line.at(ls - 1) == '\r') {
line.erase(ls - 1, 1);
}
- this->RawReadBuffer.erase(this->RawReadBuffer.begin(),
- this->RawReadBuffer.begin() +
- static_cast<long>(needle) + 1);
+ RawReadBuffer.erase(RawReadBuffer.begin(),
+ RawReadBuffer.begin() + static_cast<long>(needle) + 1);
if (line == kSTART_MAGIC) {
- this->RequestBuffer.clear();
+ RequestBuffer.clear();
continue;
}
if (line == kEND_MAGIC) {
- this->Server->QueueRequest(this->RequestBuffer);
- this->RequestBuffer.clear();
- } else {
- this->RequestBuffer += line;
- this->RequestBuffer += "\n";
+ std::string rtn;
+ rtn.swap(this->RequestBuffer);
+ return rtn;
}
- }
-}
-
-void cmServerConnection::TriggerShutdown()
-{
- this->FileMonitor()->StopMonitoring();
- uv_signal_stop(this->SIGINTHandler);
- uv_signal_stop(this->SIGHUPHandler);
-
- uv_close(reinterpret_cast<uv_handle_t*>(this->SIGINTHandler),
- &on_signal_close); // delete handle
- uv_close(reinterpret_cast<uv_handle_t*>(this->SIGHUPHandler),
- &on_signal_close); // delete handle
-
- this->SIGINTHandler = nullptr;
- this->SIGHUPHandler = nullptr;
-
- this->TearDown();
-}
-
-void cmServerConnection::WriteData(const std::string& data)
-{
- assert(this->WriteStream);
-
- auto ds = data.size();
-
- write_req_t* req = new write_req_t;
- 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,
- on_write);
-}
-
-void cmServerConnection::ProcessNextRequest()
-{
- Server->PopOne();
-}
-
-void cmServerConnection::SendGreetings()
-{
- Server->PrintHello();
-}
-
-cmServerStdIoConnection::cmServerStdIoConnection()
-{
- this->Input.tty = nullptr;
- this->Output.tty = nullptr;
-}
-
-bool cmServerStdIoConnection::DoSetup(std::string* errorMessage)
-{
- (void)(errorMessage);
-
- if (uv_guess_handle(1) == UV_TTY) {
- usesTty = true;
- this->Input.tty = new uv_tty_t;
- uv_tty_init(this->Loop(), this->Input.tty, 0, 1);
- uv_tty_set_mode(this->Input.tty, UV_TTY_MODE_NORMAL);
- Input.tty->data = this;
- this->ReadStream = reinterpret_cast<uv_stream_t*>(this->Input.tty);
-
- this->Output.tty = new uv_tty_t;
- uv_tty_init(this->Loop(), this->Output.tty, 1, 0);
- uv_tty_set_mode(this->Output.tty, UV_TTY_MODE_NORMAL);
- Output.tty->data = this;
- this->WriteStream = reinterpret_cast<uv_stream_t*>(this->Output.tty);
- } else {
- usesTty = false;
- this->Input.pipe = new uv_pipe_t;
- uv_pipe_init(this->Loop(), this->Input.pipe, 0);
- uv_pipe_open(this->Input.pipe, 0);
- Input.pipe->data = this;
- this->ReadStream = reinterpret_cast<uv_stream_t*>(this->Input.pipe);
-
- this->Output.pipe = new uv_pipe_t;
- uv_pipe_init(this->Loop(), this->Output.pipe, 0);
- uv_pipe_open(this->Output.pipe, 1);
- Output.pipe->data = this;
- this->WriteStream = reinterpret_cast<uv_stream_t*>(this->Output.pipe);
- }
-
- SendGreetings();
- uv_read_start(this->ReadStream, on_alloc_buffer, on_read);
-
- return true;
-}
-
-void cmServerStdIoConnection::TearDown()
-{
- if (usesTty) {
- uv_close(reinterpret_cast<uv_handle_t*>(this->Input.tty), &on_tty_close);
- uv_close(reinterpret_cast<uv_handle_t*>(this->Output.tty), &on_tty_close);
- this->Input.tty = nullptr;
- this->Output.tty = nullptr;
- } else {
- uv_close(reinterpret_cast<uv_handle_t*>(this->Input.pipe), &on_pipe_close);
- uv_close(reinterpret_cast<uv_handle_t*>(this->Output.pipe),
- &on_pipe_close);
- this->Input.pipe = nullptr;
- this->Input.pipe = nullptr;
- }
- this->ReadStream = nullptr;
- this->WriteStream = nullptr;
-}
-
-cmServerPipeConnection::cmServerPipeConnection(const std::string& name)
- : PipeName(name)
-{
-}
-
-bool cmServerPipeConnection::DoSetup(std::string* errorMessage)
-{
- this->ServerPipe = new uv_pipe_t;
- uv_pipe_init(this->Loop(), this->ServerPipe, 0);
- this->ServerPipe->data = this;
-
- int r;
- if ((r = uv_pipe_bind(this->ServerPipe, this->PipeName.c_str())) != 0) {
- *errorMessage = std::string("Internal Error with ") + this->PipeName +
- ": " + 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) {
- *errorMessage = std::string("Internal Error listening on ") +
- this->PipeName + ": " + uv_err_name(r);
- return false;
+ this->RequestBuffer += line;
+ this->RequestBuffer += "\n";
}
-
- return true;
-}
-
-void cmServerPipeConnection::TearDown()
-{
- if (this->ClientPipe) {
- uv_close(reinterpret_cast<uv_handle_t*>(this->ClientPipe), &on_pipe_close);
- this->WriteStream->data = nullptr;
- }
- uv_close(reinterpret_cast<uv_handle_t*>(this->ServerPipe), &on_pipe_close);
-
- this->ClientPipe = nullptr;
- this->ServerPipe = nullptr;
- this->WriteStream = nullptr;
- this->ReadStream = nullptr;
-}
-
-void cmServerPipeConnection::Connect(uv_stream_t* server)
-{
- if (this->ClientPipe) {
- // Accept and close all pipes but the first:
- uv_pipe_t* rejectPipe = new uv_pipe_t;
-
- uv_pipe_init(this->Loop(), rejectPipe, 0);
- auto rejecter = reinterpret_cast<uv_stream_t*>(rejectPipe);
- uv_accept(server, rejecter);
- uv_close(reinterpret_cast<uv_handle_t*>(rejecter), &on_pipe_close);
- return;
- }
-
- this->ClientPipe = new uv_pipe_t;
- uv_pipe_init(this->Loop(), this->ClientPipe, 0);
- this->ClientPipe->data = this;
- auto client = reinterpret_cast<uv_stream_t*>(this->ClientPipe);
- if (uv_accept(server, client) != 0) {
- uv_close(reinterpret_cast<uv_handle_t*>(client), nullptr);
- return;
- }
- this->ReadStream = client;
- this->WriteStream = client;
-
- uv_read_start(this->ReadStream, on_alloc_buffer, on_read);
-
- this->SendGreetings();
}
diff --git a/Source/cmServerConnection.h b/Source/cmServerConnection.h
index b96bf3c54..a70edb4b5 100644
--- a/Source/cmServerConnection.h
+++ b/Source/cmServerConnection.h
@@ -2,94 +2,66 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
-#include "cmConfigure.h"
-
-#include "cm_uv.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
-class cmFileMonitor;
-class cmServer;
+#include "cmConnection.h"
+#include "cmPipeConnection.h"
+#include "cmUVHandlePtr.h"
-class cmServerConnection
-{
- CM_DISABLE_COPY(cmServerConnection)
+class cmServerBase;
+/***
+ * This connection buffer strategy accepts messages in the form of
+ * [== "CMake Server" ==[
+{
+ ... some JSON message ...
+}
+]== "CMake Server" ==]
+ * and only passes on the core json; it discards the envelope.
+ */
+class cmServerBufferStrategy : public cmConnectionBufferStrategy
+{
public:
- cmServerConnection();
- virtual ~cmServerConnection();
-
- void SetServer(cmServer* s);
-
- bool ProcessEvents(std::string* errorMessage);
-
- void ReadData(const std::string& data);
- void TriggerShutdown();
- void WriteData(const std::string& data);
- void ProcessNextRequest();
+ std::string BufferMessage(std::string& rawBuffer) override;
+ std::string BufferOutMessage(const std::string& rawBuffer) const override;
- virtual void Connect(uv_stream_t* server) { (void)(server); }
-
- cmFileMonitor* FileMonitor() const { return this->mFileMonitor; }
-
-protected:
- virtual bool DoSetup(std::string* errorMessage) = 0;
- virtual void TearDown() = 0;
+private:
+ std::string RequestBuffer;
+};
- void SendGreetings();
+/***
+ * Generic connection over std io interfaces -- tty
+ */
+class cmStdIoConnection : public cmEventBasedConnection
+{
+public:
+ cmStdIoConnection(cmConnectionBufferStrategy* bufferStrategy);
- uv_loop_t* Loop() const { return mLoop; }
+ void SetServer(cmServerBase* s) override;
-protected:
- std::string RawReadBuffer;
- std::string RequestBuffer;
+ bool OnConnectionShuttingDown() override;
- uv_stream_t* ReadStream = nullptr;
- uv_stream_t* WriteStream = nullptr;
+ bool OnServeStart(std::string* pString) override;
private:
- uv_loop_t* mLoop = nullptr;
- cmFileMonitor* mFileMonitor = nullptr;
- cmServer* Server = nullptr;
- uv_signal_t* SIGINTHandler = nullptr;
- uv_signal_t* SIGHUPHandler = nullptr;
-
- friend class LoopGuard;
+ cm::uv_stream_ptr SetupStream(int file_id);
+ cm::uv_stream_ptr ReadStream;
};
-class cmServerStdIoConnection : public cmServerConnection
+/***
+ * These specific connections use the cmake server
+ * buffering strategy.
+ */
+class cmServerStdIoConnection : public cmStdIoConnection
{
public:
cmServerStdIoConnection();
- bool DoSetup(std::string* errorMessage) override;
-
- void TearDown() override;
-
-private:
- typedef union
- {
- uv_tty_t* tty;
- uv_pipe_t* pipe;
- } InOutUnion;
-
- bool usesTty = false;
-
- InOutUnion Input;
- InOutUnion Output;
};
-class cmServerPipeConnection : public cmServerConnection
+class cmServerPipeConnection : public cmPipeConnection
{
public:
cmServerPipeConnection(const std::string& name);
- bool DoSetup(std::string* errorMessage) override;
-
- void TearDown() override;
-
- void Connect(uv_stream_t* server) override;
-
-private:
- const std::string PipeName;
- uv_pipe_t* ServerPipe = nullptr;
- uv_pipe_t* ClientPipe = nullptr;
};
diff --git a/Source/cmServerDictionary.h b/Source/cmServerDictionary.h
index e6a7ae6ca..961e4b7ea 100644
--- a/Source/cmServerDictionary.h
+++ b/Source/cmServerDictionary.h
@@ -23,66 +23,37 @@ 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";
static const std::string kBUILD_FILES_KEY = "buildFiles";
static const std::string kCACHE_ARGUMENTS_KEY = "cacheArguments";
static const std::string kCACHE_KEY = "cache";
static const std::string kCAPABILITIES_KEY = "capabilities";
static const std::string kCHECK_SYSTEM_VARS_KEY = "checkSystemVars";
static const std::string kCMAKE_ROOT_DIRECTORY_KEY = "cmakeRootDirectory";
-static const std::string kCOMPILE_FLAGS_KEY = "compileFlags";
-static const std::string kCONFIGURATIONS_KEY = "configurations";
static const std::string kCOOKIE_KEY = "cookie";
static const std::string kDEBUG_OUTPUT_KEY = "debugOutput";
-static const std::string kDEFINES_KEY = "defines";
static const std::string kERROR_MESSAGE_KEY = "errorMessage";
static const std::string kEXTRA_GENERATOR_KEY = "extraGenerator";
-static const std::string kFILE_GROUPS_KEY = "fileGroups";
-static const std::string kFRAMEWORK_PATH_KEY = "frameworkPath";
-static const std::string kFULL_NAME_KEY = "fullName";
static const std::string kGENERATOR_KEY = "generator";
-static const std::string kINCLUDE_PATH_KEY = "includePath";
-static const std::string kIS_CMAKE_KEY = "isCMake";
static const std::string kIS_EXPERIMENTAL_KEY = "isExperimental";
-static const std::string kIS_GENERATED_KEY = "isGenerated";
-static const std::string kIS_SYSTEM_KEY = "isSystem";
-static const std::string kIS_TEMPORARY_KEY = "isTemporary";
-static const std::string kKEY_KEY = "key";
static const std::string kKEYS_KEY = "keys";
-static const std::string kLANGUAGE_KEY = "language";
-static const std::string kLINKER_LANGUAGE_KEY = "linkerLanguage";
-static const std::string kLINK_FLAGS_KEY = "linkFlags";
-static const std::string kLINK_LANGUAGE_FLAGS_KEY = "linkLanguageFlags";
-static const std::string kLINK_LIBRARIES_KEY = "linkLibraries";
-static const std::string kLINK_PATH_KEY = "linkPath";
static const std::string kMAJOR_KEY = "major";
static const std::string kMESSAGE_KEY = "message";
static const std::string kMINOR_KEY = "minor";
-static const std::string kNAME_KEY = "name";
-static const std::string kPATH_KEY = "path";
static const std::string kPLATFORM_KEY = "platform";
static const std::string kPROGRESS_CURRENT_KEY = "progressCurrent";
static const std::string kPROGRESS_MAXIMUM_KEY = "progressMaximum";
static const std::string kPROGRESS_MESSAGE_KEY = "progressMessage";
static const std::string kPROGRESS_MINIMUM_KEY = "progressMinimum";
-static const std::string kPROJECTS_KEY = "projects";
-static const std::string kPROPERTIES_KEY = "properties";
static const std::string kPROTOCOL_VERSION_KEY = "protocolVersion";
static const std::string kREPLY_TO_KEY = "inReplyTo";
-static const std::string kSOURCE_DIRECTORY_KEY = "sourceDirectory";
-static const std::string kSOURCES_KEY = "sources";
static const std::string kSUPPORTED_PROTOCOL_VERSIONS =
"supportedProtocolVersions";
-static const std::string kSYSROOT_KEY = "sysroot";
-static const std::string kTARGETS_KEY = "targets";
static const std::string kTITLE_KEY = "title";
static const std::string kTOOLSET_KEY = "toolset";
static const std::string kTRACE_EXPAND_KEY = "traceExpand";
static const std::string kTRACE_KEY = "trace";
-static const std::string kTYPE_KEY = "type";
-static const std::string kVALUE_KEY = "value";
static const std::string kWARN_UNINITIALIZED_KEY = "warnUninitialized";
static const std::string kWARN_UNUSED_CLI_KEY = "warnUnusedCli";
static const std::string kWARN_UNUSED_KEY = "warnUnused";
diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx
index c5b7f6064..56003df75 100644
--- a/Source/cmServerProtocol.cxx
+++ b/Source/cmServerProtocol.cxx
@@ -2,134 +2,52 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmServerProtocol.h"
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm/memory>
+
+#include "cm_uv.h"
+
+#include "cmAlgorithms.h"
#include "cmExternalMakefileProjectGenerator.h"
#include "cmFileMonitor.h"
-#include "cmGeneratorExpression.h"
-#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
-#include "cmLinkLineComputer.h"
-#include "cmLocalGenerator.h"
-#include "cmMakefile.h"
+#include "cmJsonObjectDictionary.h"
+#include "cmJsonObjects.h"
+#include "cmMessageType.h"
#include "cmServer.h"
#include "cmServerDictionary.h"
-#include "cmSourceFile.h"
#include "cmState.h"
-#include "cmStateDirectory.h"
-#include "cmStateSnapshot.h"
-#include "cmStateTypes.h"
#include "cmSystemTools.h"
-#include "cm_uv.h"
#include "cmake.h"
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <functional>
-#include <limits>
-#include <map>
-#include <set>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
// Get rid of some windows macros:
#undef max
namespace {
-std::vector<std::string> getConfigurations(const cmake* cm)
-{
- std::vector<std::string> configurations;
- auto makefiles = cm->GetGlobalGenerator()->GetMakefiles();
- if (makefiles.empty()) {
- return configurations;
- }
-
- makefiles[0]->GetConfigurations(configurations);
- if (configurations.empty()) {
- configurations.push_back("");
- }
- return configurations;
-}
-
-bool hasString(const Json::Value& v, const std::string& s)
-{
- return !v.isNull() &&
- std::any_of(v.begin(), v.end(),
- [s](const Json::Value& i) { return i.asString() == s; });
-}
-
-template <class T>
-Json::Value fromStringList(const T& in)
-{
- Json::Value result = Json::arrayValue;
- for (const std::string& i : in) {
- result.append(i);
- }
- return result;
-}
-
std::vector<std::string> toStringList(const Json::Value& in)
{
std::vector<std::string> result;
- for (const auto& it : in) {
+ for (auto const& it : in) {
result.push_back(it.asString());
}
return result;
}
-void getCMakeInputs(const cmGlobalGenerator* gg, const std::string& sourceDir,
- const std::string& buildDir,
- std::vector<std::string>* internalFiles,
- std::vector<std::string>* explicitFiles,
- std::vector<std::string>* tmpFiles)
-{
- const std::string cmakeRootDir = cmSystemTools::GetCMakeRoot() + '/';
- std::vector<cmMakefile*> const& makefiles = gg->GetMakefiles();
- for (auto it = makefiles.begin(); it != makefiles.end(); ++it) {
- const std::vector<std::string> listFiles = (*it)->GetListFiles();
-
- for (auto jt = listFiles.begin(); jt != listFiles.end(); ++jt) {
-
- const std::string startOfFile = jt->substr(0, cmakeRootDir.size());
- const bool isInternal = (startOfFile == cmakeRootDir);
- const bool isTemporary = !isInternal && (jt->find(buildDir + '/') == 0);
-
- std::string toAdd = *jt;
- if (!sourceDir.empty()) {
- const std::string& relative =
- cmSystemTools::RelativePath(sourceDir.c_str(), jt->c_str());
- if (toAdd.size() > relative.size()) {
- toAdd = relative;
- }
- }
-
- if (isInternal) {
- if (internalFiles) {
- internalFiles->push_back(toAdd);
- }
- } else {
- if (isTemporary) {
- if (tmpFiles) {
- tmpFiles->push_back(toAdd);
- }
- } else {
- if (explicitFiles) {
- explicitFiles->push_back(toAdd);
- }
- }
- }
- }
- }
-}
-
} // namespace
-cmServerRequest::cmServerRequest(cmServer* server, const std::string& t,
- const std::string& c, const Json::Value& d)
- : Type(t)
- , Cookie(c)
- , Data(d)
+cmServerRequest::cmServerRequest(cmServer* server, cmConnection* connection,
+ std::string t, std::string c, Json::Value d)
+ : Type(std::move(t))
+ , Cookie(std::move(c))
+ , Data(std::move(d))
+ , Connection(connection)
, m_Server(server)
{
}
@@ -215,10 +133,11 @@ bool cmServerProtocol::Activate(cmServer* server,
{
assert(server);
this->m_Server = server;
- this->m_CMakeInstance = std::make_unique<cmake>(cmake::RoleProject);
+ this->m_CMakeInstance =
+ cm::make_unique<cmake>(cmake::RoleProject, cmState::Project);
const bool result = this->DoActivate(request, errorMessage);
if (!result) {
- this->m_CMakeInstance = CM_NULLPTR;
+ this->m_CMakeInstance = nullptr;
}
return result;
}
@@ -247,9 +166,9 @@ bool cmServerProtocol::DoActivate(const cmServerRequest& /*request*/,
return true;
}
-std::pair<int, int> cmServerProtocol1_0::ProtocolVersion() const
+std::pair<int, int> cmServerProtocol1::ProtocolVersion() const
{
- return std::make_pair(1, 0);
+ return { 1, 2 };
}
static void setErrorMessage(std::string* errorMessage, const std::string& text)
@@ -259,11 +178,15 @@ 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"));
+ if (value.empty()) {
+ value = cachedValue;
+ return true;
+ }
const std::string suffix = "/CMakeLists.txt";
const std::string cachedValueCML = cachedValue + suffix;
const std::string valueCML = value + suffix;
@@ -274,44 +197,53 @@ static bool testHomeDirectory(cmState* state, std::string& value,
"source directory value."));
return false;
}
- if (value.empty()) {
- value = cachedValue;
- }
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 =
entry == nullptr ? std::string() : std::string(entry);
- if (!cachedValue.empty() && !value.empty() && cachedValue != value) {
- setErrorMessage(errorMessage, std::string("\"") + key +
+ if (value.empty()) {
+ value = cachedValue;
+ }
+ if (!cachedValue.empty() && cachedValue != value) {
+ setErrorMessage(errorMessage,
+ std::string("\"") + key +
"\" is set but incompatible with configured " +
keyDescription + " value.");
return false;
}
- if (value.empty()) {
- value = cachedValue;
- }
return true;
}
-bool cmServerProtocol1_0::DoActivate(const cmServerRequest& request,
- std::string* errorMessage)
+bool cmServerProtocol1::DoActivate(const cmServerRequest& request,
+ std::string* errorMessage)
{
std::string sourceDirectory = request.Data[kSOURCE_DIRECTORY_KEY].asString();
- const std::string buildDirectory =
- request.Data[kBUILD_DIRECTORY_KEY].asString();
+ std::string buildDirectory = request.Data[kBUILD_DIRECTORY_KEY].asString();
std::string generator = request.Data[kGENERATOR_KEY].asString();
std::string extraGenerator = request.Data[kEXTRA_GENERATOR_KEY].asString();
std::string toolset = request.Data[kTOOLSET_KEY].asString();
std::string platform = request.Data[kPLATFORM_KEY].asString();
+ // normalize source and build directory
+ if (!sourceDirectory.empty()) {
+ sourceDirectory = cmSystemTools::CollapseFullPath(sourceDirectory);
+ cmSystemTools::ConvertToUnixSlashes(sourceDirectory);
+ }
+ if (!buildDirectory.empty()) {
+ buildDirectory = cmSystemTools::CollapseFullPath(buildDirectory);
+ cmSystemTools::ConvertToUnixSlashes(buildDirectory);
+ }
+
if (buildDirectory.empty()) {
- setErrorMessage(errorMessage, std::string("\"") + kBUILD_DIRECTORY_KEY +
+ setErrorMessage(errorMessage,
+ std::string("\"") + kBUILD_DIRECTORY_KEY +
"\" is missing.");
return false;
}
@@ -319,58 +251,62 @@ bool cmServerProtocol1_0::DoActivate(const cmServerRequest& request,
cmake* cm = CMakeInstance();
if (cmSystemTools::PathExists(buildDirectory)) {
if (!cmSystemTools::FileIsDirectory(buildDirectory)) {
- setErrorMessage(errorMessage, std::string("\"") + kBUILD_DIRECTORY_KEY +
+ setErrorMessage(errorMessage,
+ std::string("\"") + kBUILD_DIRECTORY_KEY +
"\" exists but is not a directory.");
return false;
}
- const std::string cachePath = cm->FindCacheFile(buildDirectory);
+ const std::string cachePath = cmake::FindCacheFile(buildDirectory);
if (cm->LoadCache(cachePath)) {
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;
}
}
}
if (sourceDirectory.empty()) {
- setErrorMessage(errorMessage, std::string("\"") + kSOURCE_DIRECTORY_KEY +
+ setErrorMessage(errorMessage,
+ std::string("\"") + kSOURCE_DIRECTORY_KEY +
"\" is unset but required.");
return false;
}
if (!cmSystemTools::FileIsDirectory(sourceDirectory)) {
- setErrorMessage(errorMessage, std::string("\"") + kSOURCE_DIRECTORY_KEY +
+ setErrorMessage(errorMessage,
+ std::string("\"") + kSOURCE_DIRECTORY_KEY +
"\" is not a directory.");
return false;
}
if (generator.empty()) {
- setErrorMessage(errorMessage, std::string("\"") + kGENERATOR_KEY +
+ setErrorMessage(errorMessage,
+ std::string("\"") + kGENERATOR_KEY +
"\" is unset but required.");
return false;
}
@@ -382,7 +318,8 @@ bool cmServerProtocol1_0::DoActivate(const cmServerRequest& request,
return info.name == generator;
});
if (baseIt == generators.end()) {
- setErrorMessage(errorMessage, std::string("Generator \"") + generator +
+ setErrorMessage(errorMessage,
+ std::string("Generator \"") + generator +
"\" not supported.");
return false;
}
@@ -419,8 +356,8 @@ bool cmServerProtocol1_0::DoActivate(const cmServerRequest& request,
return true;
}
-void cmServerProtocol1_0::HandleCMakeFileChanges(const std::string& path,
- int event, int status)
+void cmServerProtocol1::HandleCMakeFileChanges(const std::string& path,
+ int event, int status)
{
assert(status == 0);
static_cast<void>(status);
@@ -443,8 +380,7 @@ void cmServerProtocol1_0::HandleCMakeFileChanges(const std::string& path,
SendSignal(kFILE_CHANGE_SIGNAL, obj);
}
-const cmServerResponse cmServerProtocol1_0::Process(
- const cmServerRequest& request)
+cmServerResponse cmServerProtocol1::Process(const cmServerRequest& request)
{
assert(this->m_State >= STATE_ACTIVE);
@@ -472,22 +408,21 @@ const cmServerResponse cmServerProtocol1_0::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!");
}
-bool cmServerProtocol1_0::IsExperimental() const
+bool cmServerProtocol1::IsExperimental() const
{
return true;
}
-cmServerResponse cmServerProtocol1_0::ProcessCache(
+cmServerResponse cmServerProtocol1::ProcessCache(
const cmServerRequest& request)
{
- if (this->m_State < STATE_CONFIGURED) {
- return request.ReportError("This project was not configured yet.");
- }
-
cmState* state = this->CMakeInstance()->GetState();
Json::Value result = Json::objectValue;
@@ -499,14 +434,14 @@ cmServerResponse cmServerProtocol1_0::ProcessCache(
if (keys.empty()) {
keys = allKeys;
} else {
- for (const auto& i : keys) {
- if (std::find(allKeys.begin(), allKeys.end(), i) == allKeys.end()) {
+ for (auto const& i : keys) {
+ if (!cmContains(allKeys, i)) {
return request.ReportError("Key \"" + i + "\" not found in cache.");
}
}
}
std::sort(keys.begin(), keys.end());
- for (const auto& key : keys) {
+ for (auto const& key : keys) {
Json::Value entry = Json::objectValue;
entry[kKEY_KEY] = key;
entry[kTYPE_KEY] =
@@ -515,7 +450,7 @@ cmServerResponse cmServerProtocol1_0::ProcessCache(
Json::Value props = Json::objectValue;
bool haveProperties = false;
- for (const auto& prop : state->GetCacheEntryPropertyList(key)) {
+ for (auto const& prop : state->GetCacheEntryPropertyList(key)) {
haveProperties = true;
props[prop] = state->GetCacheEntryProperty(key, prop);
}
@@ -530,7 +465,7 @@ cmServerResponse cmServerProtocol1_0::ProcessCache(
return request.Reply(result);
}
-cmServerResponse cmServerProtocol1_0::ProcessCMakeInputs(
+cmServerResponse cmServerProtocol1::ProcessCMakeInputs(
const cmServerRequest& request)
{
if (this->m_State < STATE_CONFIGURED) {
@@ -538,398 +473,27 @@ cmServerResponse cmServerProtocol1_0::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& sourceDir = cm->GetHomeDirectory();
Json::Value result = Json::objectValue;
result[kSOURCE_DIRECTORY_KEY] = sourceDir;
result[kCMAKE_ROOT_DIRECTORY_KEY] = cmakeRootDir;
-
- std::vector<std::string> internalFiles;
- std::vector<std::string> explicitFiles;
- std::vector<std::string> tmpFiles;
- getCMakeInputs(gg, sourceDir, buildDir, &internalFiles, &explicitFiles,
- &tmpFiles);
-
- Json::Value array = Json::arrayValue;
-
- Json::Value tmp = Json::objectValue;
- tmp[kIS_CMAKE_KEY] = true;
- tmp[kIS_TEMPORARY_KEY] = false;
- tmp[kSOURCES_KEY] = fromStringList(internalFiles);
- array.append(tmp);
-
- tmp = Json::objectValue;
- tmp[kIS_CMAKE_KEY] = false;
- tmp[kIS_TEMPORARY_KEY] = false;
- tmp[kSOURCES_KEY] = fromStringList(explicitFiles);
- array.append(tmp);
-
- tmp = Json::objectValue;
- tmp[kIS_CMAKE_KEY] = false;
- tmp[kIS_TEMPORARY_KEY] = true;
- tmp[kSOURCES_KEY] = fromStringList(tmpFiles);
- array.append(tmp);
-
- result[kBUILD_FILES_KEY] = array;
-
+ result[kBUILD_FILES_KEY] = cmDumpCMakeInputs(cm);
return request.Reply(result);
}
-class LanguageData
-{
-public:
- bool operator==(const LanguageData& other) const;
-
- void SetDefines(const std::set<std::string>& defines);
-
- bool IsGenerated = false;
- std::string Language;
- std::string Flags;
- std::vector<std::string> Defines;
- std::vector<std::pair<std::string, bool> > IncludePathList;
-};
-
-bool LanguageData::operator==(const LanguageData& other) const
-{
- return Language == other.Language && Defines == other.Defines &&
- Flags == other.Flags && IncludePathList == other.IncludePathList &&
- IsGenerated == other.IsGenerated;
-}
-
-void LanguageData::SetDefines(const std::set<std::string>& defines)
-{
- std::vector<std::string> result;
- for (const auto& i : defines) {
- result.push_back(i);
- }
- std::sort(result.begin(), result.end());
- Defines = result;
-}
-
-namespace std {
-
-template <>
-struct hash<LanguageData>
-{
- std::size_t operator()(const LanguageData& in) const
- {
- using std::hash;
- size_t result =
- hash<std::string>()(in.Language) ^ hash<std::string>()(in.Flags);
- for (const auto& i : in.IncludePathList) {
- result = result ^ (hash<std::string>()(i.first) ^
- (i.second ? std::numeric_limits<size_t>::max() : 0));
- }
- for (const auto& i : in.Defines) {
- result = result ^ hash<std::string>()(i);
- }
- result =
- result ^ (in.IsGenerated ? std::numeric_limits<size_t>::max() : 0);
- return result;
- }
-};
-
-} // namespace std
-
-static Json::Value DumpSourceFileGroup(const LanguageData& data,
- const std::vector<std::string>& files,
- const std::string& baseDir)
-{
- Json::Value result = Json::objectValue;
-
- if (!data.Language.empty()) {
- result[kLANGUAGE_KEY] = data.Language;
- if (!data.Flags.empty()) {
- result[kCOMPILE_FLAGS_KEY] = data.Flags;
- }
- if (!data.IncludePathList.empty()) {
- Json::Value includes = Json::arrayValue;
- for (const auto& i : data.IncludePathList) {
- Json::Value tmp = Json::objectValue;
- tmp[kPATH_KEY] = i.first;
- if (i.second) {
- tmp[kIS_SYSTEM_KEY] = i.second;
- }
- includes.append(tmp);
- }
- result[kINCLUDE_PATH_KEY] = includes;
- }
- if (!data.Defines.empty()) {
- result[kDEFINES_KEY] = fromStringList(data.Defines);
- }
- }
-
- result[kIS_GENERATED_KEY] = data.IsGenerated;
-
- Json::Value sourcesValue = Json::arrayValue;
- for (const auto& i : files) {
- const std::string relPath =
- cmSystemTools::RelativePath(baseDir.c_str(), i.c_str());
- sourcesValue.append(relPath.size() < i.size() ? relPath : i);
- }
-
- result[kSOURCES_KEY] = sourcesValue;
- return result;
-}
-
-static Json::Value DumpSourceFilesList(
- cmGeneratorTarget* target, const std::string& config,
- const std::map<std::string, LanguageData>& languageDataMap)
-{
- // Collect sourcefile groups:
-
- std::vector<cmSourceFile*> files;
- target->GetSourceFiles(files, config);
-
- std::unordered_map<LanguageData, std::vector<std::string> > fileGroups;
- for (cmSourceFile* file : files) {
- LanguageData fileData;
- fileData.Language = file->GetLanguage();
- if (!fileData.Language.empty()) {
- const LanguageData& ld = languageDataMap.at(fileData.Language);
- cmLocalGenerator* lg = target->GetLocalGenerator();
-
- 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);
- }
- fileData.Flags = compileFlags;
-
- fileData.IncludePathList = ld.IncludePathList;
-
- std::set<std::string> defines;
- lg->AppendDefines(defines, file->GetProperty("COMPILE_DEFINITIONS"));
- const std::string defPropName =
- "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config);
- lg->AppendDefines(defines, file->GetProperty(defPropName));
- defines.insert(ld.Defines.begin(), ld.Defines.end());
-
- fileData.SetDefines(defines);
- }
-
- fileData.IsGenerated = file->GetPropertyAsBool("GENERATED");
- std::vector<std::string>& groupFileList = fileGroups[fileData];
- groupFileList.push_back(file->GetFullPath());
- }
-
- const std::string baseDir = target->Makefile->GetCurrentSourceDirectory();
- Json::Value result = Json::arrayValue;
- for (auto it = fileGroups.begin(); it != fileGroups.end(); ++it) {
- Json::Value group = DumpSourceFileGroup(it->first, it->second, baseDir);
- if (!group.isNull()) {
- result.append(group);
- }
- }
-
- return result;
-}
-
-static Json::Value DumpTarget(cmGeneratorTarget* target,
- const std::string& config)
-{
- cmLocalGenerator* lg = target->GetLocalGenerator();
- const cmState* state = lg->GetState();
-
- const cmStateEnums::TargetType type = target->GetType();
- const std::string typeName = state->GetTargetTypeName(type);
-
- Json::Value ttl = Json::arrayValue;
- ttl.append("EXECUTABLE");
- ttl.append("STATIC_LIBRARY");
- ttl.append("SHARED_LIBRARY");
- ttl.append("MODULE_LIBRARY");
- ttl.append("OBJECT_LIBRARY");
- ttl.append("UTILITY");
- ttl.append("INTERFACE_LIBRARY");
-
- if (!hasString(ttl, typeName) || target->IsImported()) {
- return Json::Value();
- }
-
- Json::Value result = Json::objectValue;
- result[kNAME_KEY] = target->GetName();
- result[kTYPE_KEY] = typeName;
- result[kSOURCE_DIRECTORY_KEY] = lg->GetCurrentSourceDirectory();
- result[kBUILD_DIRECTORY_KEY] = lg->GetCurrentBinaryDirectory();
-
- if (type == cmStateEnums::INTERFACE_LIBRARY) {
- return result;
- }
-
- result[kFULL_NAME_KEY] = target->GetFullName(config);
-
- if (target->HaveWellDefinedOutputFiles()) {
- Json::Value artifacts = Json::arrayValue;
- artifacts.append(
- target->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact));
- if (target->IsDLLPlatform()) {
- artifacts.append(
- target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact));
- const cmGeneratorTarget::OutputInfo* output =
- target->GetOutputInfo(config);
- if (output && !output->PdbDir.empty()) {
- artifacts.append(output->PdbDir + '/' + target->GetPDBName(config));
- }
- }
- result[kARTIFACTS_KEY] = artifacts;
-
- result[kLINKER_LANGUAGE_KEY] = target->GetLinkerLanguage(config);
-
- std::string linkLibs;
- std::string linkFlags;
- std::string linkLanguageFlags;
- std::string frameworkPath;
- std::string linkPath;
- cmLinkLineComputer linkLineComputer(lg,
- lg->GetStateSnapshot().GetDirectory());
- lg->GetTargetFlags(&linkLineComputer, config, linkLibs, linkLanguageFlags,
- linkFlags, frameworkPath, linkPath, target);
-
- linkLibs = cmSystemTools::TrimWhitespace(linkLibs);
- linkFlags = cmSystemTools::TrimWhitespace(linkFlags);
- linkLanguageFlags = cmSystemTools::TrimWhitespace(linkLanguageFlags);
- frameworkPath = cmSystemTools::TrimWhitespace(frameworkPath);
- linkPath = cmSystemTools::TrimWhitespace(linkPath);
-
- if (!cmSystemTools::TrimWhitespace(linkLibs).empty()) {
- result[kLINK_LIBRARIES_KEY] = linkLibs;
- }
- if (!cmSystemTools::TrimWhitespace(linkFlags).empty()) {
- result[kLINK_FLAGS_KEY] = linkFlags;
- }
- if (!cmSystemTools::TrimWhitespace(linkLanguageFlags).empty()) {
- result[kLINK_LANGUAGE_FLAGS_KEY] = linkLanguageFlags;
- }
- if (!frameworkPath.empty()) {
- result[kFRAMEWORK_PATH_KEY] = frameworkPath;
- }
- if (!linkPath.empty()) {
- result[kLINK_PATH_KEY] = linkPath;
- }
- const std::string sysroot =
- lg->GetMakefile()->GetSafeDefinition("CMAKE_SYSROOT");
- if (!sysroot.empty()) {
- result[kSYSROOT_KEY] = sysroot;
- }
- }
-
- std::set<std::string> languages;
- target->GetLanguages(languages, config);
- std::map<std::string, LanguageData> languageDataMap;
- for (const auto& lang : languages) {
- LanguageData& ld = languageDataMap[lang];
- ld.Language = lang;
- lg->GetTargetCompileFlags(target, config, lang, ld.Flags);
- std::set<std::string> defines;
- lg->GetTargetDefines(target, config, lang, defines);
- ld.SetDefines(defines);
- std::vector<std::string> includePathList;
- lg->GetIncludeDirectories(includePathList, target, lang, config, true);
- for (auto i : includePathList) {
- ld.IncludePathList.push_back(
- std::make_pair(i, target->IsSystemIncludeDirectory(i, config)));
- }
- }
-
- Json::Value sourceGroupsValue =
- DumpSourceFilesList(target, config, languageDataMap);
- if (!sourceGroupsValue.empty()) {
- result[kFILE_GROUPS_KEY] = sourceGroupsValue;
- }
-
- return result;
-}
-
-static Json::Value DumpTargetsList(
- const std::vector<cmLocalGenerator*>& generators, const std::string& config)
-{
- Json::Value result = Json::arrayValue;
-
- std::vector<cmGeneratorTarget*> targetList;
- for (const auto& lgIt : generators) {
- auto list = lgIt->GetGeneratorTargets();
- targetList.insert(targetList.end(), list.begin(), list.end());
- }
- std::sort(targetList.begin(), targetList.end());
-
- for (cmGeneratorTarget* target : targetList) {
- Json::Value tmp = DumpTarget(target, config);
- if (!tmp.isNull()) {
- result.append(tmp);
- }
- }
-
- return result;
-}
-
-static Json::Value DumpProjectList(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;
-
- // All Projects must have at least one local generator
- assert(!projectIt.second.empty());
- const cmLocalGenerator* lg = projectIt.second.at(0);
-
- // Project structure information:
- const cmMakefile* mf = lg->GetMakefile();
- pObj[kSOURCE_DIRECTORY_KEY] = mf->GetCurrentSourceDirectory();
- pObj[kBUILD_DIRECTORY_KEY] = mf->GetCurrentBinaryDirectory();
- pObj[kTARGETS_KEY] = DumpTargetsList(projectIt.second, config);
-
- result.append(pObj);
- }
-
- return result;
-}
-
-static Json::Value DumpConfiguration(const cmake* cm,
- const std::string& config)
-{
- Json::Value result = Json::objectValue;
- result[kNAME_KEY] = config;
-
- result[kPROJECTS_KEY] = DumpProjectList(cm, config);
-
- return result;
-}
-
-static Json::Value DumpConfigurationsList(const cmake* cm)
-{
- Json::Value result = Json::arrayValue;
-
- for (const std::string& c : getConfigurations(cm)) {
- result.append(DumpConfiguration(cm, c));
- }
-
- return result;
-}
-
-cmServerResponse cmServerProtocol1_0::ProcessCodeModel(
+cmServerResponse cmServerProtocol1::ProcessCodeModel(
const cmServerRequest& request)
{
if (this->m_State != STATE_COMPUTED) {
return request.ReportError("No build system was generated yet.");
}
- Json::Value result = Json::objectValue;
- result[kCONFIGURATIONS_KEY] = DumpConfigurationsList(this->CMakeInstance());
- return request.Reply(result);
+ return request.Reply(cmDumpCodeModel(this->CMakeInstance()));
}
-cmServerResponse cmServerProtocol1_0::ProcessCompute(
+cmServerResponse cmServerProtocol1::ProcessCompute(
const cmServerRequest& request)
{
if (this->m_State > STATE_CONFIGURED) {
@@ -949,7 +513,7 @@ cmServerResponse cmServerProtocol1_0::ProcessCompute(
return request.Reply(Json::Value());
}
-cmServerResponse cmServerProtocol1_0::ProcessConfigure(
+cmServerResponse cmServerProtocol1::ProcessConfigure(
const cmServerRequest& request)
{
if (this->m_State == STATE_INACTIVE) {
@@ -973,12 +537,12 @@ cmServerResponse cmServerProtocol1_0::ProcessConfigure(
if (passedArgs.isString()) {
cacheArgs.push_back(passedArgs.asString());
} else if (passedArgs.isArray()) {
- for (auto i = passedArgs.begin(); i != passedArgs.end(); ++i) {
- if (!i->isString()) {
+ for (auto const& arg : passedArgs) {
+ if (!arg.isString()) {
cacheArgumentsError = true;
break;
}
- cacheArgs.push_back(i->asString());
+ cacheArgs.push_back(arg.asString());
}
} else {
cacheArgumentsError = true;
@@ -1000,20 +564,20 @@ cmServerResponse cmServerProtocol1_0::ProcessConfigure(
if (cm->LoadCache(buildDir)) {
// build directory has been set up before
- const char* cachedSourceDir =
+ const std::string* cachedSourceDir =
cm->GetState()->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY");
if (!cachedSourceDir) {
return request.ReportError("No CMAKE_HOME_DIRECTORY found in cache.");
}
if (sourceDir.empty()) {
- sourceDir = std::string(cachedSourceDir);
+ sourceDir = *cachedSourceDir;
cm->SetHomeDirectory(sourceDir);
}
- const char* cachedGenerator =
+ const std::string* cachedGenerator =
cm->GetState()->GetInitializedCacheValue("CMAKE_GENERATOR");
if (cachedGenerator) {
- if (gg && gg->GetName() != cachedGenerator) {
+ if (gg && gg->GetName() != *cachedGenerator) {
return request.ReportError("Configured generator does not match with "
"CMAKE_GENERATOR found in cache.");
}
@@ -1038,12 +602,17 @@ cmServerResponse cmServerProtocol1_0::ProcessConfigure(
}
int ret = cm->Configure();
+ cm->IssueMessage(
+ MessageType::DEPRECATION_WARNING,
+ "The 'cmake-server(7)' is deprecated. "
+ "Please port clients to use the 'cmake-file-api(7)' instead.");
if (ret < 0) {
return request.ReportError("Configuration failed.");
}
std::vector<std::string> toWatchList;
- getCMakeInputs(gg, std::string(), buildDir, nullptr, &toWatchList, nullptr);
+ cmGetCMakeInputs(gg, std::string(), buildDir, nullptr, &toWatchList,
+ nullptr);
FileMonitor()->MonitorPaths(toWatchList,
[this](const std::string& p, int e, int s) {
@@ -1055,14 +624,14 @@ cmServerResponse cmServerProtocol1_0::ProcessConfigure(
return request.Reply(Json::Value());
}
-cmServerResponse cmServerProtocol1_0::ProcessGlobalSettings(
+cmServerResponse cmServerProtocol1::ProcessGlobalSettings(
const cmServerRequest& request)
{
cmake* cm = this->CMakeInstance();
Json::Value obj = Json::objectValue;
// Capabilities information:
- obj[kCAPABILITIES_KEY] = cm->ReportCapabilitiesJson(true);
+ obj[kCAPABILITIES_KEY] = cm->ReportCapabilitiesJson();
obj[kDEBUG_OUTPUT_KEY] = cm->GetDebugOutput();
obj[kTRACE_KEY] = cm->GetTrace();
@@ -1091,7 +660,7 @@ static void setBool(const cmServerRequest& request, const std::string& key,
setter(request.Data[key].asBool());
}
-cmServerResponse cmServerProtocol1_0::ProcessSetGlobalSettings(
+cmServerResponse cmServerProtocol1::ProcessSetGlobalSettings(
const cmServerRequest& request)
{
const std::vector<std::string> boolValues = {
@@ -1099,7 +668,7 @@ cmServerResponse cmServerProtocol1_0::ProcessSetGlobalSettings(
kWARN_UNINITIALIZED_KEY, kWARN_UNUSED_KEY, kWARN_UNUSED_CLI_KEY,
kCHECK_SYSTEM_VARS_KEY
};
- for (const auto& i : boolValues) {
+ for (std::string const& i : boolValues) {
if (!request.Data[i].isNull() && !request.Data[i].isBool()) {
return request.ReportError("\"" + i +
"\" must be unset or a bool value.");
@@ -1123,17 +692,17 @@ cmServerResponse cmServerProtocol1_0::ProcessSetGlobalSettings(
return request.Reply(Json::Value());
}
-cmServerResponse cmServerProtocol1_0::ProcessFileSystemWatchers(
+cmServerResponse cmServerProtocol1::ProcessFileSystemWatchers(
const cmServerRequest& request)
{
const cmFileMonitor* const fm = FileMonitor();
Json::Value result = Json::objectValue;
Json::Value files = Json::arrayValue;
- for (const auto& f : fm->WatchedFiles()) {
+ for (auto const& f : fm->WatchedFiles()) {
files.append(f);
}
Json::Value directories = Json::arrayValue;
- for (const auto& d : fm->WatchedDirectories()) {
+ for (auto const& d : fm->WatchedDirectories()) {
directories.append(d);
}
result[kWATCHED_FILES_KEY] = files;
@@ -1142,20 +711,30 @@ cmServerResponse cmServerProtocol1_0::ProcessFileSystemWatchers(
return request.Reply(result);
}
-cmServerProtocol1_0::GeneratorInformation::GeneratorInformation(
- const std::string& generatorName, const std::string& extraGeneratorName,
- const std::string& toolset, const std::string& platform,
- const std::string& sourceDirectory, const std::string& buildDirectory)
- : GeneratorName(generatorName)
- , ExtraGeneratorName(extraGeneratorName)
- , Toolset(toolset)
- , Platform(platform)
- , SourceDirectory(sourceDirectory)
- , BuildDirectory(buildDirectory)
+cmServerResponse cmServerProtocol1::ProcessCTests(
+ const cmServerRequest& request)
+{
+ if (this->m_State < STATE_COMPUTED) {
+ return request.ReportError("This instance was not yet computed.");
+ }
+
+ return request.Reply(cmDumpCTestInfo(this->CMakeInstance()));
+}
+
+cmServerProtocol1::GeneratorInformation::GeneratorInformation(
+ std::string generatorName, std::string extraGeneratorName,
+ std::string toolset, std::string platform, std::string sourceDirectory,
+ std::string buildDirectory)
+ : GeneratorName(std::move(generatorName))
+ , ExtraGeneratorName(std::move(extraGeneratorName))
+ , Toolset(std::move(toolset))
+ , Platform(std::move(platform))
+ , SourceDirectory(std::move(sourceDirectory))
+ , BuildDirectory(std::move(buildDirectory))
{
}
-void cmServerProtocol1_0::GeneratorInformation::SetupGenerator(
+void cmServerProtocol1::GeneratorInformation::SetupGenerator(
cmake* cm, std::string* errorMessage)
{
const std::string fullGeneratorName =
diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h
index 83b3d58de..8446c3e76 100644
--- a/Source/cmServerProtocol.h
+++ b/Source/cmServerProtocol.h
@@ -2,15 +2,17 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
-#include "cmConfigure.h"
-
-#include "cm_jsoncpp_value.h"
-#include "cmake.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <memory>
#include <string>
#include <utility>
+#include "cm_jsoncpp_value.h"
+
+#include "cmake.h"
+
+class cmConnection;
class cmFileMonitor;
class cmServer;
class cmServerRequest;
@@ -52,10 +54,11 @@ public:
const std::string Type;
const std::string Cookie;
const Json::Value Data;
+ cmConnection* Connection;
private:
- cmServerRequest(cmServer* server, const std::string& t, const std::string& c,
- const Json::Value& d);
+ cmServerRequest(cmServer* server, cmConnection* connection, std::string t,
+ std::string c, Json::Value d);
void ReportProgress(int min, int current, int max,
const std::string& message) const;
@@ -69,15 +72,16 @@ private:
class cmServerProtocol
{
- CM_DISABLE_COPY(cmServerProtocol)
-
public:
cmServerProtocol() = default;
virtual ~cmServerProtocol() = default;
+ cmServerProtocol(cmServerProtocol const&) = delete;
+ cmServerProtocol& operator=(cmServerProtocol const&) = delete;
+
virtual std::pair<int, int> ProtocolVersion() const = 0;
virtual bool IsExperimental() const = 0;
- virtual const cmServerResponse Process(const cmServerRequest& request) = 0;
+ virtual cmServerResponse Process(const cmServerRequest& request) = 0;
bool Activate(cmServer* server, const cmServerRequest& request,
std::string* errorMessage);
@@ -98,12 +102,12 @@ private:
friend class cmServer;
};
-class cmServerProtocol1_0 : public cmServerProtocol
+class cmServerProtocol1 : public cmServerProtocol
{
public:
std::pair<int, int> ProtocolVersion() const override;
bool IsExperimental() const override;
- const cmServerResponse Process(const cmServerRequest& request) override;
+ cmServerResponse Process(const cmServerRequest& request) override;
private:
bool DoActivate(const cmServerRequest& request,
@@ -120,6 +124,7 @@ private:
cmServerResponse ProcessGlobalSettings(const cmServerRequest& request);
cmServerResponse ProcessSetGlobalSettings(const cmServerRequest& request);
cmServerResponse ProcessFileSystemWatchers(const cmServerRequest& request);
+ cmServerResponse ProcessCTests(const cmServerRequest& request);
enum State
{
@@ -136,12 +141,10 @@ private:
{
public:
GeneratorInformation() = default;
- GeneratorInformation(const std::string& generatorName,
- const std::string& extraGeneratorName,
- const std::string& toolset,
- const std::string& platform,
- const std::string& sourceDirectory,
- const std::string& buildDirectory);
+ GeneratorInformation(std::string generatorName,
+ std::string extraGeneratorName, std::string toolset,
+ std::string platform, std::string sourceDirectory,
+ std::string buildDirectory);
void SetupGenerator(cmake* cm, std::string* errorMessage);
diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx
index 820e7f695..8c3a4cb48 100644
--- a/Source/cmSetCommand.cxx
+++ b/Source/cmSetCommand.cxx
@@ -2,39 +2,34 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSetCommand.h"
-#include <string.h>
-
-#include "cmAlgorithms.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmRange.h"
#include "cmState.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
-
// cmSetCommand
-bool cmSetCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmSetCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
// 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()) {
@@ -43,6 +38,14 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args,
putEnvArg += args[1];
cmSystemTools::PutEnv(putEnvArg);
}
+ // if there's extra arguments, warn user
+ // that they are ignored by this command.
+ if (args.size() > 2) {
+ std::string m = "Only the first value argument is used when setting "
+ "an environment variable. Argument '" +
+ args[2] + "' and later are unused.";
+ status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, m);
+ }
return true;
}
@@ -55,13 +58,13 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args,
// SET (VAR) // Removes the definition of VAR.
if (args.size() == 1) {
- this->Makefile->RemoveDefinition(variable);
+ status.GetMakefile().RemoveDefinition(variable);
return true;
}
// SET (VAR PARENT_SCOPE) // Removes the definition of VAR
// in the parent scope.
- if (args.size() == 2 && args[args.size() - 1] == "PARENT_SCOPE") {
- this->Makefile->RaiseScope(variable, CM_NULLPTR);
+ if (args.size() == 2 && args.back() == "PARENT_SCOPE") {
+ status.GetMakefile().RaiseScope(variable, nullptr);
return true;
}
@@ -75,17 +78,17 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args,
bool force = false; // optional
bool parentScope = false;
cmStateEnums::CacheEntryType type =
- cmStateEnums::STRING; // required if cache
- const char* docstring = CM_NULLPTR; // required if cache
+ cmStateEnums::STRING; // required if cache
+ const char* docstring = nullptr; // required if cache
unsigned int ignoreLastArgs = 0;
// look for PARENT_SCOPE argument
- if (args.size() > 1 && args[args.size() - 1] == "PARENT_SCOPE") {
+ if (args.size() > 1 && args.back() == "PARENT_SCOPE") {
parentScope = true;
ignoreLastArgs++;
} else {
// look for FORCE argument
- if (args.size() > 4 && args[args.size() - 1] == "FORCE") {
+ if (args.size() > 4 && args.back() == "FORCE") {
force = true;
ignoreLastArgs++;
}
@@ -102,28 +105,36 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args,
value = cmJoin(cmMakeRange(args).advance(1).retreat(ignoreLastArgs), ";");
if (parentScope) {
- this->Makefile->RaiseScope(variable, value.c_str());
+ status.GetMakefile().RaiseScope(variable, value.c_str());
return true;
}
// we should be nice and try to catch some simple screwups if the last or
// next to last args are CACHE then they screwed up. If they used FORCE
// without CACHE they screwed up
- if ((args[args.size() - 1] == "CACHE") ||
+ if ((args.back() == "CACHE") ||
(args.size() > 1 && args[args.size() - 2] == "CACHE") ||
(force && !cache)) {
- this->SetError("given invalid arguments for CACHE mode.");
+ status.SetError("given invalid arguments for CACHE mode.");
return false;
}
if (cache) {
std::string::size_type cacheStart = args.size() - 3 - (force ? 1 : 0);
- type = cmState::StringToCacheEntryType(args[cacheStart + 1].c_str());
+ if (!cmState::StringToCacheEntryType(args[cacheStart + 1].c_str(), type)) {
+ std::string m = "implicitly converting '" + args[cacheStart + 1] +
+ "' to 'STRING' type.";
+ status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, m);
+ // Setting this may not be required, since it's
+ // initialized as a string. Keeping this here to
+ // ensure that the type is actually converting to a string.
+ type = cmStateEnums::STRING;
+ }
docstring = args[cacheStart + 2].c_str();
}
// see if this is already in the cache
- cmState* state = this->Makefile->GetState();
+ cmState* state = status.GetMakefile().GetState();
const char* existingValue = state->GetCacheEntryValue(variable);
if (existingValue &&
(state->GetCacheEntryType(variable) != cmStateEnums::UNINITIALIZED)) {
@@ -138,11 +149,11 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args,
// if it is meant to be in the cache then define it in the cache
if (cache) {
- this->Makefile->AddCacheDefinition(variable, value.c_str(), docstring,
- type, force);
+ status.GetMakefile().AddCacheDefinition(variable, value.c_str(), docstring,
+ type, force);
} else {
// add the definition
- this->Makefile->AddDefinition(variable, value.c_str());
+ status.GetMakefile().AddDefinition(variable, value);
}
return true;
}
diff --git a/Source/cmSetCommand.h b/Source/cmSetCommand.h
index c0858b15b..0973d33aa 100644
--- a/Source/cmSetCommand.h
+++ b/Source/cmSetCommand.h
@@ -3,34 +3,19 @@
#ifndef cmSetCommand_h
#define cmSetCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmSetCommand
+/**
* \brief Set a CMAKE variable
*
* cmSetCommand sets a variable to a value with expansion.
*/
-class cmSetCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmSetCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmSetCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmSetDirectoryPropertiesCommand.cxx b/Source/cmSetDirectoryPropertiesCommand.cxx
index 8d3961a79..35daca6ff 100644
--- a/Source/cmSetDirectoryPropertiesCommand.cxx
+++ b/Source/cmSetDirectoryPropertiesCommand.cxx
@@ -2,31 +2,37 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSetDirectoryPropertiesCommand.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-class cmExecutionStatus;
+namespace {
+bool RunCommand(cmMakefile& mf, std::vector<std::string>::const_iterator ait,
+ std::vector<std::string>::const_iterator aitend,
+ std::string& errors);
+}
// cmSetDirectoryPropertiesCommand
-bool cmSetDirectoryPropertiesCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmSetDirectoryPropertiesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
std::string errors;
- bool ret = cmSetDirectoryPropertiesCommand::RunCommand(
- this->Makefile, args.begin() + 1, args.end(), errors);
+ bool ret =
+ RunCommand(status.GetMakefile(), args.begin() + 1, args.end(), errors);
if (!ret) {
- this->SetError(errors);
+ status.SetError(errors);
}
return ret;
}
-bool cmSetDirectoryPropertiesCommand::RunCommand(
- cmMakefile* mf, std::vector<std::string>::const_iterator ait,
- std::vector<std::string>::const_iterator aitend, std::string& errors)
+namespace {
+bool RunCommand(cmMakefile& mf, std::vector<std::string>::const_iterator ait,
+ std::vector<std::string>::const_iterator aitend,
+ std::string& errors)
{
for (; ait != aitend; ait += 2) {
if (ait + 1 == aitend) {
@@ -43,8 +49,9 @@ bool cmSetDirectoryPropertiesCommand::RunCommand(
errors = "Commands and macros cannot be set using SET_CMAKE_PROPERTIES";
return false;
}
- mf->SetProperty(prop, value.c_str());
+ mf.SetProperty(prop, value.c_str());
}
return true;
}
+}
diff --git a/Source/cmSetDirectoryPropertiesCommand.h b/Source/cmSetDirectoryPropertiesCommand.h
index 8832b3389..c243dd70f 100644
--- a/Source/cmSetDirectoryPropertiesCommand.h
+++ b/Source/cmSetDirectoryPropertiesCommand.h
@@ -3,38 +3,14 @@
#ifndef cmSetDirectoryPropertiesCommand_h
#define cmSetDirectoryPropertiesCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmMakefile;
-
-class cmSetDirectoryPropertiesCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE
- {
- return new cmSetDirectoryPropertiesCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the input file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
- /**
- * Static entry point for use by other commands
- */
- static bool RunCommand(cmMakefile* mf,
- std::vector<std::string>::const_iterator ait,
- std::vector<std::string>::const_iterator aitend,
- std::string& errors);
-};
+bool cmSetDirectoryPropertiesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx
index b57f62a50..112d832e6 100644
--- a/Source/cmSetPropertyCommand.cxx
+++ b/Source/cmSetPropertyCommand.cxx
@@ -2,62 +2,118 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSetPropertyCommand.h"
+#include <set>
#include <sstream>
+#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmInstalledFile.h"
#include "cmMakefile.h"
#include "cmProperty.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmState.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTest.h"
#include "cmake.h"
-class cmExecutionStatus;
-
-cmSetPropertyCommand::cmSetPropertyCommand()
-{
- this->AppendMode = false;
- this->AppendAsString = false;
- this->Remove = true;
+namespace {
+bool HandleGlobalMode(cmExecutionStatus& status,
+ const std::set<std::string>& names,
+ const std::string& propertyName,
+ const std::string& propertyValue, bool appendAsString,
+ bool appendMode, bool remove);
+bool HandleDirectoryMode(cmExecutionStatus& status,
+ const std::set<std::string>& names,
+ const std::string& propertyName,
+ const std::string& propertyValue, bool appendAsString,
+ bool appendMode, bool remove);
+bool HandleTargetMode(cmExecutionStatus& status,
+ const std::set<std::string>& names,
+ const std::string& propertyName,
+ const std::string& propertyValue, bool appendAsString,
+ bool appendMode, bool remove);
+bool HandleTarget(cmTarget* target, cmMakefile& makefile,
+ const std::string& propertyName,
+ const std::string& propertyValue, bool appendAsString,
+ bool appendMode, bool remove);
+bool HandleSourceMode(cmExecutionStatus& status,
+ const std::set<std::string>& names,
+ const std::string& propertyName,
+ const std::string& propertyValue, bool appendAsString,
+ bool appendMode, bool remove);
+bool HandleSource(cmSourceFile* sf, const std::string& propertyName,
+ const std::string& propertyValue, bool appendAsString,
+ bool appendMode, bool remove);
+bool HandleTestMode(cmExecutionStatus& status, std::set<std::string>& names,
+ const std::string& propertyName,
+ const std::string& propertyValue, bool appendAsString,
+ bool appendMode, bool remove);
+bool HandleTest(cmTest* test, const std::string& propertyName,
+ const std::string& propertyValue, bool appendAsString,
+ bool appendMode, bool remove);
+bool HandleCacheMode(cmExecutionStatus& status,
+ const std::set<std::string>& names,
+ const std::string& propertyName,
+ const std::string& propertyValue, bool appendAsString,
+ bool appendMode, bool remove);
+bool HandleCacheEntry(std::string const& cacheKey, const cmMakefile& makefile,
+ const std::string& propertyName,
+ const std::string& propertyValue, bool appendAsString,
+ bool appendMode, bool remove);
+bool HandleInstallMode(cmExecutionStatus& status,
+ const std::set<std::string>& names,
+ const std::string& propertyName,
+ const std::string& propertyValue, bool appendAsString,
+ bool appendMode, bool remove);
+bool HandleInstall(cmInstalledFile* file, cmMakefile& makefile,
+ const std::string& propertyName,
+ const std::string& propertyValue, bool appendAsString,
+ bool appendMode, bool remove);
}
-bool cmSetPropertyCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmSetPropertyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
// Get the scope on which to set the property.
- std::vector<std::string>::const_iterator arg = args.begin();
+ std::string const& scopeName = args.front();
cmProperty::ScopeType scope;
- if (*arg == "GLOBAL") {
+ if (scopeName == "GLOBAL") {
scope = cmProperty::GLOBAL;
- } else if (*arg == "DIRECTORY") {
+ } else if (scopeName == "DIRECTORY") {
scope = cmProperty::DIRECTORY;
- } else if (*arg == "TARGET") {
+ } else if (scopeName == "TARGET") {
scope = cmProperty::TARGET;
- } else if (*arg == "SOURCE") {
+ } else if (scopeName == "SOURCE") {
scope = cmProperty::SOURCE_FILE;
- } else if (*arg == "TEST") {
+ } else if (scopeName == "TEST") {
scope = cmProperty::TEST;
- } else if (*arg == "CACHE") {
+ } else if (scopeName == "CACHE") {
scope = cmProperty::CACHE;
- } else if (*arg == "INSTALL") {
+ } else if (scopeName == "INSTALL") {
scope = cmProperty::INSTALL;
} else {
- std::ostringstream e;
- e << "given invalid scope " << *arg << ". "
- << "Valid scopes are GLOBAL, DIRECTORY, "
- "TARGET, SOURCE, TEST, CACHE, INSTALL.";
- this->SetError(e.str());
+ status.SetError(cmStrCat("given invalid scope ", scopeName,
+ ". "
+ "Valid scopes are GLOBAL, DIRECTORY, "
+ "TARGET, SOURCE, TEST, CACHE, INSTALL."));
return false;
}
+ bool appendAsString = false;
+ bool appendMode = false;
+ bool remove = true;
+ std::set<std::string> names;
+ std::string propertyName;
+ std::string propertyValue;
+
// Parse the rest of the arguments up to the values.
enum Doing
{
@@ -68,59 +124,64 @@ bool cmSetPropertyCommand::InitialPass(std::vector<std::string> const& args,
};
Doing doing = DoingNames;
const char* sep = "";
- for (++arg; arg != args.end(); ++arg) {
- if (*arg == "PROPERTY") {
+ for (std::string const& arg : cmMakeRange(args).advance(1)) {
+ if (arg == "PROPERTY") {
doing = DoingProperty;
- } else if (*arg == "APPEND") {
+ } else if (arg == "APPEND") {
doing = DoingNone;
- this->AppendMode = true;
- this->Remove = false;
- this->AppendAsString = false;
- } else if (*arg == "APPEND_STRING") {
+ appendMode = true;
+ remove = false;
+ appendAsString = false;
+ } else if (arg == "APPEND_STRING") {
doing = DoingNone;
- this->AppendMode = true;
- this->Remove = false;
- this->AppendAsString = true;
+ appendMode = true;
+ remove = false;
+ appendAsString = true;
} else if (doing == DoingNames) {
- this->Names.insert(*arg);
+ names.insert(arg);
} else if (doing == DoingProperty) {
- this->PropertyName = *arg;
+ propertyName = arg;
doing = DoingValues;
} else if (doing == DoingValues) {
- this->PropertyValue += sep;
+ propertyValue += sep;
sep = ";";
- this->PropertyValue += *arg;
- this->Remove = false;
+ propertyValue += arg;
+ remove = false;
} else {
- std::ostringstream e;
- e << "given invalid argument \"" << *arg << "\".";
- this->SetError(e.str());
+ status.SetError(cmStrCat("given invalid argument \"", arg, "\"."));
return false;
}
}
// Make sure a property name was found.
- if (this->PropertyName.empty()) {
- this->SetError("not given a PROPERTY <name> argument.");
+ if (propertyName.empty()) {
+ status.SetError("not given a PROPERTY <name> argument.");
return false;
}
// Dispatch property setting.
switch (scope) {
case cmProperty::GLOBAL:
- return this->HandleGlobalMode();
+ return HandleGlobalMode(status, names, propertyName, propertyValue,
+ appendAsString, appendMode, remove);
case cmProperty::DIRECTORY:
- return this->HandleDirectoryMode();
+ return HandleDirectoryMode(status, names, propertyName, propertyValue,
+ appendAsString, appendMode, remove);
case cmProperty::TARGET:
- return this->HandleTargetMode();
+ return HandleTargetMode(status, names, propertyName, propertyValue,
+ appendAsString, appendMode, remove);
case cmProperty::SOURCE_FILE:
- return this->HandleSourceMode();
+ return HandleSourceMode(status, names, propertyName, propertyValue,
+ appendAsString, appendMode, remove);
case cmProperty::TEST:
- return this->HandleTestMode();
+ return HandleTestMode(status, names, propertyName, propertyValue,
+ appendAsString, appendMode, remove);
case cmProperty::CACHE:
- return this->HandleCacheMode();
+ return HandleCacheMode(status, names, propertyName, propertyValue,
+ appendAsString, appendMode, remove);
case cmProperty::INSTALL:
- return this->HandleInstallMode();
+ return HandleInstallMode(status, names, propertyName, propertyValue,
+ appendAsString, appendMode, remove);
case cmProperty::VARIABLE:
case cmProperty::CACHED_VARIABLE:
@@ -129,57 +190,66 @@ bool cmSetPropertyCommand::InitialPass(std::vector<std::string> const& args,
return true;
}
-bool cmSetPropertyCommand::HandleGlobalMode()
+namespace {
+bool HandleGlobalMode(cmExecutionStatus& status,
+ const std::set<std::string>& names,
+ const std::string& propertyName,
+ const std::string& propertyValue,
+ const bool appendAsString, const bool appendMode,
+ const bool remove)
{
- if (!this->Names.empty()) {
- this->SetError("given names for GLOBAL scope.");
+ if (!names.empty()) {
+ status.SetError("given names for GLOBAL scope.");
return false;
}
// Set or append the property.
- cmake* cm = this->Makefile->GetCMakeInstance();
- std::string const& name = this->PropertyName;
- const char* value = this->PropertyValue.c_str();
- if (this->Remove) {
- value = CM_NULLPTR;
+ cmake* cm = status.GetMakefile().GetCMakeInstance();
+ const char* value = propertyValue.c_str();
+ if (remove) {
+ value = nullptr;
}
- if (this->AppendMode) {
- cm->AppendProperty(name, value ? value : "", this->AppendAsString);
+ if (appendMode) {
+ cm->AppendProperty(propertyName, value ? value : "", appendAsString);
} else {
- cm->SetProperty(name, value);
+ cm->SetProperty(propertyName, value);
}
return true;
}
-bool cmSetPropertyCommand::HandleDirectoryMode()
+bool HandleDirectoryMode(cmExecutionStatus& status,
+ const std::set<std::string>& names,
+ const std::string& propertyName,
+ const std::string& propertyValue,
+ const bool appendAsString, const bool appendMode,
+ const bool remove)
{
- if (this->Names.size() > 1) {
- this->SetError("allows at most one name for DIRECTORY scope.");
+ if (names.size() > 1) {
+ status.SetError("allows at most one name for DIRECTORY scope.");
return false;
}
// Default to the current directory.
- cmMakefile* mf = this->Makefile;
+ cmMakefile* mf = &status.GetMakefile();
// Lookup the directory if given.
- if (!this->Names.empty()) {
+ if (!names.empty()) {
// 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())) {
- dir = this->Makefile->GetCurrentSourceDirectory();
- dir += "/";
- dir += *this->Names.begin();
+ std::string dir = *names.begin();
+ if (!cmSystemTools::FileIsFullPath(dir)) {
+ dir = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/',
+ *names.begin());
}
// The local generators are associated with collapsed paths.
dir = cmSystemTools::CollapseFullPath(dir);
- mf = this->Makefile->GetGlobalGenerator()->FindMakefile(dir);
+ mf = status.GetMakefile().GetGlobalGenerator()->FindMakefile(dir);
if (!mf) {
// Could not find the directory.
- this->SetError(
+ status.SetError(
"DIRECTORY scope provided but requested directory was not found. "
"This could be because the directory argument was invalid or, "
"it is valid but has not been processed yet.");
@@ -188,111 +258,124 @@ bool cmSetPropertyCommand::HandleDirectoryMode()
}
// Set or append the property.
- std::string const& name = this->PropertyName;
- const char* value = this->PropertyValue.c_str();
- if (this->Remove) {
- value = CM_NULLPTR;
+ const char* value = propertyValue.c_str();
+ if (remove) {
+ value = nullptr;
}
- if (this->AppendMode) {
- mf->AppendProperty(name, value ? value : "", this->AppendAsString);
+ if (appendMode) {
+ mf->AppendProperty(propertyName, value ? value : "", appendAsString);
} else {
- mf->SetProperty(name, value);
+ mf->SetProperty(propertyName, value);
}
return true;
}
-bool cmSetPropertyCommand::HandleTargetMode()
+bool HandleTargetMode(cmExecutionStatus& status,
+ const std::set<std::string>& names,
+ const std::string& propertyName,
+ const std::string& propertyValue,
+ const bool appendAsString, const bool appendMode,
+ const bool remove)
{
- for (std::set<std::string>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni) {
- if (this->Makefile->IsAlias(*ni)) {
- this->SetError("can not be used on an ALIAS target.");
+ for (std::string const& name : names) {
+ if (status.GetMakefile().IsAlias(name)) {
+ status.SetError("can not be used on an ALIAS target.");
return false;
}
- if (cmTarget* target = this->Makefile->FindTargetToUse(*ni)) {
+ if (cmTarget* target = status.GetMakefile().FindTargetToUse(name)) {
// Handle the current target.
- if (!this->HandleTarget(target)) {
+ if (!HandleTarget(target, status.GetMakefile(), propertyName,
+ propertyValue, appendAsString, appendMode, remove)) {
return false;
}
} else {
- std::ostringstream e;
- e << "could not find TARGET " << *ni
- << ". Perhaps it has not yet been created.";
- this->SetError(e.str());
+ status.SetError(cmStrCat("could not find TARGET ", name,
+ ". Perhaps it has not yet been created."));
return false;
}
}
return true;
}
-bool cmSetPropertyCommand::HandleTarget(cmTarget* target)
+bool HandleTarget(cmTarget* target, cmMakefile& makefile,
+ const std::string& propertyName,
+ const std::string& propertyValue, const bool appendAsString,
+ const bool appendMode, const bool remove)
{
// Set or append the property.
- std::string const& name = this->PropertyName;
- const char* value = this->PropertyValue.c_str();
- if (this->Remove) {
- value = CM_NULLPTR;
+ const char* value = propertyValue.c_str();
+ if (remove) {
+ value = nullptr;
}
- if (this->AppendMode) {
- target->AppendProperty(name, value, this->AppendAsString);
+ if (appendMode) {
+ target->AppendProperty(propertyName, value, appendAsString);
} else {
- target->SetProperty(name, value);
+ target->SetProperty(propertyName, value);
}
// Check the resulting value.
- target->CheckProperty(name, this->Makefile);
+ target->CheckProperty(propertyName, &makefile);
return true;
}
-bool cmSetPropertyCommand::HandleSourceMode()
+bool HandleSourceMode(cmExecutionStatus& status,
+ const std::set<std::string>& names,
+ const std::string& propertyName,
+ const std::string& propertyValue,
+ const bool appendAsString, const bool appendMode,
+ const bool remove)
{
- for (std::set<std::string>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni) {
+ for (std::string const& name : names) {
// Get the source file.
- if (cmSourceFile* sf = this->Makefile->GetOrCreateSource(*ni)) {
- if (!this->HandleSource(sf)) {
+ if (cmSourceFile* sf = status.GetMakefile().GetOrCreateSource(name)) {
+ if (!HandleSource(sf, propertyName, propertyValue, appendAsString,
+ appendMode, remove)) {
return false;
}
} else {
- std::ostringstream e;
- e << "given SOURCE name that could not be found or created: " << *ni;
- this->SetError(e.str());
+ status.SetError(cmStrCat(
+ "given SOURCE name that could not be found or created: ", name));
return false;
}
}
return true;
}
-bool cmSetPropertyCommand::HandleSource(cmSourceFile* sf)
+bool HandleSource(cmSourceFile* sf, const std::string& propertyName,
+ const std::string& propertyValue, const bool appendAsString,
+ const bool appendMode, const bool remove)
{
// Set or append the property.
- std::string const& name = this->PropertyName;
- const char* value = this->PropertyValue.c_str();
- if (this->Remove) {
- value = CM_NULLPTR;
+ const char* value = propertyValue.c_str();
+ if (remove) {
+ value = nullptr;
}
- if (this->AppendMode) {
- sf->AppendProperty(name, value, this->AppendAsString);
+ if (appendMode) {
+ sf->AppendProperty(propertyName, value, appendAsString);
} else {
- sf->SetProperty(name, value);
+ sf->SetProperty(propertyName, value);
}
return true;
}
-bool cmSetPropertyCommand::HandleTestMode()
+bool HandleTestMode(cmExecutionStatus& status, std::set<std::string>& names,
+ const std::string& propertyName,
+ const std::string& propertyValue,
+ const bool appendAsString, const bool appendMode,
+ const bool remove)
{
// Look for tests with all names given.
std::set<std::string>::iterator next;
- for (std::set<std::string>::iterator ni = this->Names.begin();
- ni != this->Names.end(); ni = next) {
+ for (auto ni = names.begin(); ni != names.end(); ni = next) {
next = ni;
++next;
- if (cmTest* test = this->Makefile->GetTest(*ni)) {
- if (this->HandleTest(test)) {
- this->Names.erase(ni);
+ if (cmTest* test = status.GetMakefile().GetTest(*ni)) {
+ if (HandleTest(test, propertyName, propertyValue, appendAsString,
+ appendMode, remove)) {
+ names.erase(ni);
} else {
return false;
}
@@ -300,140 +383,145 @@ bool cmSetPropertyCommand::HandleTestMode()
}
// Names that are still left were not found.
- if (!this->Names.empty()) {
+ if (!names.empty()) {
std::ostringstream e;
e << "given TEST names that do not exist:\n";
- for (std::set<std::string>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni) {
- e << " " << *ni << "\n";
+ for (std::string const& name : names) {
+ e << " " << name << "\n";
}
- this->SetError(e.str());
+ status.SetError(e.str());
return false;
}
return true;
}
-bool cmSetPropertyCommand::HandleTest(cmTest* test)
+bool HandleTest(cmTest* test, const std::string& propertyName,
+ const std::string& propertyValue, const bool appendAsString,
+ const bool appendMode, const bool remove)
{
// Set or append the property.
- std::string const& name = this->PropertyName;
- const char* value = this->PropertyValue.c_str();
- if (this->Remove) {
- value = CM_NULLPTR;
+ const char* value = propertyValue.c_str();
+ if (remove) {
+ value = nullptr;
}
- if (this->AppendMode) {
- test->AppendProperty(name, value, this->AppendAsString);
+ if (appendMode) {
+ test->AppendProperty(propertyName, value, appendAsString);
} else {
- test->SetProperty(name, value);
+ test->SetProperty(propertyName, value);
}
return true;
}
-bool cmSetPropertyCommand::HandleCacheMode()
+bool HandleCacheMode(cmExecutionStatus& status,
+ const std::set<std::string>& names,
+ const std::string& propertyName,
+ const std::string& propertyValue,
+ const bool appendAsString, const bool appendMode,
+ const bool remove)
{
- if (this->PropertyName == "ADVANCED") {
- if (!this->Remove && !cmSystemTools::IsOn(this->PropertyValue.c_str()) &&
- !cmSystemTools::IsOff(this->PropertyValue.c_str())) {
- std::ostringstream e;
- e << "given non-boolean value \"" << this->PropertyValue
- << "\" for CACHE property \"ADVANCED\". ";
- this->SetError(e.str());
+ if (propertyName == "ADVANCED") {
+ if (!remove && !cmIsOn(propertyValue) && !cmIsOff(propertyValue)) {
+ status.SetError(cmStrCat("given non-boolean value \"", propertyValue,
+ R"(" for CACHE property "ADVANCED". )"));
return false;
}
- } else if (this->PropertyName == "TYPE") {
- if (!cmState::IsCacheEntryType(this->PropertyValue)) {
- std::ostringstream e;
- e << "given invalid CACHE entry TYPE \"" << this->PropertyValue << "\"";
- this->SetError(e.str());
+ } else if (propertyName == "TYPE") {
+ if (!cmState::IsCacheEntryType(propertyValue)) {
+ status.SetError(
+ cmStrCat("given invalid CACHE entry TYPE \"", propertyValue, "\""));
return false;
}
- } else if (this->PropertyName != "HELPSTRING" &&
- this->PropertyName != "STRINGS" &&
- this->PropertyName != "VALUE") {
- std::ostringstream e;
- e << "given invalid CACHE property " << this->PropertyName << ". "
- << "Settable CACHE properties are: "
- << "ADVANCED, HELPSTRING, STRINGS, TYPE, and VALUE.";
- this->SetError(e.str());
+ } else if (propertyName != "HELPSTRING" && propertyName != "STRINGS" &&
+ propertyName != "VALUE") {
+ status.SetError(
+ cmStrCat("given invalid CACHE property ", propertyName,
+ ". "
+ "Settable CACHE properties are: "
+ "ADVANCED, HELPSTRING, STRINGS, TYPE, and VALUE."));
return false;
}
- for (std::set<std::string>::const_iterator ni = this->Names.begin();
- ni != this->Names.end(); ++ni) {
+ for (std::string const& name : names) {
// Get the source file.
- cmMakefile* mf = this->GetMakefile();
- cmake* cm = mf->GetCMakeInstance();
- const char* existingValue = cm->GetState()->GetCacheEntryValue(*ni);
+ cmake* cm = status.GetMakefile().GetCMakeInstance();
+ const char* existingValue = cm->GetState()->GetCacheEntryValue(name);
if (existingValue) {
- if (!this->HandleCacheEntry(*ni)) {
+ if (!HandleCacheEntry(name, status.GetMakefile(), propertyName,
+ propertyValue, appendAsString, appendMode,
+ remove)) {
return false;
}
} else {
- std::ostringstream e;
- e << "could not find CACHE variable " << *ni
- << ". Perhaps it has not yet been created.";
- this->SetError(e.str());
+ status.SetError(cmStrCat("could not find CACHE variable ", name,
+ ". Perhaps it has not yet been created."));
return false;
}
}
return true;
}
-bool cmSetPropertyCommand::HandleCacheEntry(std::string const& cacheKey)
+bool HandleCacheEntry(std::string const& cacheKey, const cmMakefile& makefile,
+ const std::string& propertyName,
+ const std::string& propertyValue,
+ const bool appendAsString, const bool appendMode,
+ const bool remove)
{
// Set or append the property.
- std::string const& name = this->PropertyName;
- const char* value = this->PropertyValue.c_str();
- cmState* state = this->Makefile->GetState();
- if (this->Remove) {
- state->RemoveCacheEntryProperty(cacheKey, name);
+ const char* value = propertyValue.c_str();
+ cmState* state = makefile.GetState();
+ if (remove) {
+ state->RemoveCacheEntryProperty(cacheKey, propertyName);
}
- if (this->AppendMode) {
- state->AppendCacheEntryProperty(cacheKey, name, value,
- this->AppendAsString);
+ if (appendMode) {
+ state->AppendCacheEntryProperty(cacheKey, propertyName, value,
+ appendAsString);
} else {
- state->SetCacheEntryProperty(cacheKey, name, value);
+ state->SetCacheEntryProperty(cacheKey, propertyName, value);
}
return true;
}
-bool cmSetPropertyCommand::HandleInstallMode()
+bool HandleInstallMode(cmExecutionStatus& status,
+ const std::set<std::string>& names,
+ const std::string& propertyName,
+ const std::string& propertyValue,
+ const bool appendAsString, const bool appendMode,
+ const bool remove)
{
- cmake* cm = this->Makefile->GetCMakeInstance();
+ cmake* cm = status.GetMakefile().GetCMakeInstance();
- for (std::set<std::string>::const_iterator i = this->Names.begin();
- i != this->Names.end(); ++i) {
+ for (std::string const& name : names) {
if (cmInstalledFile* file =
- cm->GetOrCreateInstalledFile(this->Makefile, *i)) {
- if (!this->HandleInstall(file)) {
+ cm->GetOrCreateInstalledFile(&status.GetMakefile(), name)) {
+ if (!HandleInstall(file, status.GetMakefile(), propertyName,
+ propertyValue, appendAsString, appendMode, remove)) {
return false;
}
} else {
- std::ostringstream e;
- e << "given INSTALL name that could not be found or created: " << *i;
- this->SetError(e.str());
+ status.SetError(cmStrCat(
+ "given INSTALL name that could not be found or created: ", name));
return false;
}
}
return true;
}
-bool cmSetPropertyCommand::HandleInstall(cmInstalledFile* file)
+bool HandleInstall(cmInstalledFile* file, cmMakefile& makefile,
+ const std::string& propertyName,
+ const std::string& propertyValue, const bool appendAsString,
+ const bool appendMode, const bool remove)
{
// Set or append the property.
- std::string const& name = this->PropertyName;
-
- cmMakefile* mf = this->Makefile;
-
- const char* value = this->PropertyValue.c_str();
- if (this->Remove) {
- file->RemoveProperty(name);
- } else if (this->AppendMode) {
- file->AppendProperty(mf, name, value, this->AppendAsString);
+ const char* value = propertyValue.c_str();
+ if (remove) {
+ file->RemoveProperty(propertyName);
+ } else if (appendMode) {
+ file->AppendProperty(&makefile, propertyName, value, appendAsString);
} else {
- file->SetProperty(mf, name, value);
+ file->SetProperty(&makefile, propertyName, value);
}
return true;
}
+}
diff --git a/Source/cmSetPropertyCommand.h b/Source/cmSetPropertyCommand.h
index 08158244a..ec36f849e 100644
--- a/Source/cmSetPropertyCommand.h
+++ b/Source/cmSetPropertyCommand.h
@@ -3,55 +3,14 @@
#ifndef cmSetsPropertiesCommand_h
#define cmSetsPropertiesCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include <set>
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmInstalledFile;
-class cmSourceFile;
-class cmTarget;
-class cmTest;
-
-class cmSetPropertyCommand : public cmCommand
-{
-public:
- cmSetPropertyCommand();
-
- cmCommand* Clone() CM_OVERRIDE { return new cmSetPropertyCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the input file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- std::set<std::string> Names;
- std::string PropertyName;
- std::string PropertyValue;
- bool Remove;
- bool AppendMode;
- bool AppendAsString;
- // Implementation of each property type.
- bool HandleGlobalMode();
- bool HandleDirectoryMode();
- bool HandleTargetMode();
- bool HandleTarget(cmTarget* target);
- bool HandleSourceMode();
- bool HandleSource(cmSourceFile* sf);
- bool HandleTestMode();
- bool HandleTest(cmTest* test);
- bool HandleCacheMode();
- bool HandleCacheEntry(std::string const&);
- bool HandleInstallMode();
- bool HandleInstall(cmInstalledFile* file);
-};
+bool cmSetPropertyCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmSetSourceFilesPropertiesCommand.cxx b/Source/cmSetSourceFilesPropertiesCommand.cxx
index 33e1b2e06..7ff604be0 100644
--- a/Source/cmSetSourceFilesPropertiesCommand.cxx
+++ b/Source/cmSetSourceFilesPropertiesCommand.cxx
@@ -2,18 +2,23 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSetSourceFilesPropertiesCommand.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
-#include "cmSystemTools.h"
+#include "cmStringAlgorithms.h"
-class cmExecutionStatus;
+static bool RunCommand(cmMakefile* mf,
+ std::vector<std::string>::const_iterator filebeg,
+ std::vector<std::string>::const_iterator fileend,
+ std::vector<std::string>::const_iterator propbeg,
+ std::vector<std::string>::const_iterator propend,
+ std::string& errors);
-// cmSetSourceFilesPropertiesCommand
-bool cmSetSourceFilesPropertiesCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmSetSourceFilesPropertiesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
@@ -29,22 +34,24 @@ bool cmSetSourceFilesPropertiesCommand::InitialPass(
++j;
}
+ cmMakefile& mf = status.GetMakefile();
+
// now call the worker function
std::string errors;
- bool ret = cmSetSourceFilesPropertiesCommand::RunCommand(
- this->Makefile, args.begin(), args.begin() + numFiles,
- args.begin() + numFiles, args.end(), errors);
+ bool ret = RunCommand(&mf, args.begin(), args.begin() + numFiles,
+ args.begin() + numFiles, args.end(), errors);
if (!ret) {
- this->SetError(errors);
+ status.SetError(errors);
}
return ret;
}
-bool cmSetSourceFilesPropertiesCommand::RunCommand(
- cmMakefile* mf, std::vector<std::string>::const_iterator filebeg,
- std::vector<std::string>::const_iterator fileend,
- std::vector<std::string>::const_iterator propbeg,
- std::vector<std::string>::const_iterator propend, std::string& errors)
+static bool RunCommand(cmMakefile* mf,
+ std::vector<std::string>::const_iterator filebeg,
+ std::vector<std::string>::const_iterator fileend,
+ std::vector<std::string>::const_iterator propbeg,
+ std::vector<std::string>::const_iterator propend,
+ std::string& errors)
{
std::vector<std::string> propertyPairs;
bool generated = false;
@@ -53,17 +60,17 @@ bool cmSetSourceFilesPropertiesCommand::RunCommand(
for (j = propbeg; j != propend; ++j) {
// old style allows for specifier before PROPERTIES keyword
if (*j == "ABSTRACT") {
- propertyPairs.push_back("ABSTRACT");
- propertyPairs.push_back("1");
+ propertyPairs.emplace_back("ABSTRACT");
+ propertyPairs.emplace_back("1");
} else if (*j == "WRAP_EXCLUDE") {
- propertyPairs.push_back("WRAP_EXCLUDE");
- propertyPairs.push_back("1");
+ propertyPairs.emplace_back("WRAP_EXCLUDE");
+ propertyPairs.emplace_back("1");
} else if (*j == "GENERATED") {
generated = true;
- propertyPairs.push_back("GENERATED");
- propertyPairs.push_back("1");
+ propertyPairs.emplace_back("GENERATED");
+ propertyPairs.emplace_back("1");
} else if (*j == "COMPILE_FLAGS") {
- propertyPairs.push_back("COMPILE_FLAGS");
+ propertyPairs.emplace_back("COMPILE_FLAGS");
++j;
if (j == propend) {
errors = "called with incorrect number of arguments "
@@ -72,7 +79,7 @@ bool cmSetSourceFilesPropertiesCommand::RunCommand(
}
propertyPairs.push_back(*j);
} else if (*j == "OBJECT_DEPENDS") {
- propertyPairs.push_back("OBJECT_DEPENDS");
+ propertyPairs.emplace_back("OBJECT_DEPENDS");
++j;
if (j == propend) {
errors = "called with incorrect number of arguments "
@@ -87,7 +94,7 @@ bool cmSetSourceFilesPropertiesCommand::RunCommand(
propertyPairs.push_back(*j);
if (*j == "GENERATED") {
++j;
- if (j != propend && cmSystemTools::IsOn(j->c_str())) {
+ if (j != propend && cmIsOn(*j)) {
generated = true;
}
} else {
diff --git a/Source/cmSetSourceFilesPropertiesCommand.h b/Source/cmSetSourceFilesPropertiesCommand.h
index 2e22dc9ef..5eef7859a 100644
--- a/Source/cmSetSourceFilesPropertiesCommand.h
+++ b/Source/cmSetSourceFilesPropertiesCommand.h
@@ -3,37 +3,14 @@
#ifndef cmSetSourceFilesPropertiesCommand_h
#define cmSetSourceFilesPropertiesCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmMakefile;
-
-class cmSetSourceFilesPropertiesCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE
- {
- return new cmSetSourceFilesPropertiesCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the input file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
- static bool RunCommand(cmMakefile* mf,
- std::vector<std::string>::const_iterator filebeg,
- std::vector<std::string>::const_iterator fileend,
- std::vector<std::string>::const_iterator propbeg,
- std::vector<std::string>::const_iterator propend,
- std::string& errors);
-};
+bool cmSetSourceFilesPropertiesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmSetTargetPropertiesCommand.cxx b/Source/cmSetTargetPropertiesCommand.cxx
index 642591337..8d917dbe5 100644
--- a/Source/cmSetTargetPropertiesCommand.cxx
+++ b/Source/cmSetTargetPropertiesCommand.cxx
@@ -4,65 +4,67 @@
#include <iterator>
+#include "cmAlgorithms.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
#include "cmTarget.h"
-class cmExecutionStatus;
+static bool SetOneTarget(const std::string& tname,
+ std::vector<std::string>& propertyPairs,
+ cmMakefile* mf);
-// cmSetTargetPropertiesCommand
-bool cmSetTargetPropertiesCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmSetTargetPropertiesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
// first collect up the list of files
std::vector<std::string> propertyPairs;
int numFiles = 0;
- std::vector<std::string>::const_iterator j;
- for (j = args.begin(); j != args.end(); ++j) {
+ for (auto j = args.begin(); j != args.end(); ++j) {
if (*j == "PROPERTIES") {
// now loop through the rest of the arguments, new style
++j;
if (std::distance(j, args.end()) % 2 != 0) {
- this->SetError("called with incorrect number of arguments.");
+ status.SetError("called with incorrect number of arguments.");
return false;
}
- propertyPairs.insert(propertyPairs.end(), j, args.end());
+ cmAppend(propertyPairs, j, args.end());
break;
}
numFiles++;
}
if (propertyPairs.empty()) {
- this->SetError("called with illegal arguments, maybe missing "
- "a PROPERTIES specifier?");
+ status.SetError("called with illegal arguments, maybe missing "
+ "a PROPERTIES specifier?");
return false;
}
+ cmMakefile& mf = status.GetMakefile();
+
// now loop over all the targets
- int i;
- for (i = 0; i < numFiles; ++i) {
- if (this->Makefile->IsAlias(args[i])) {
- this->SetError("can not be used on an ALIAS target.");
+ for (int i = 0; i < numFiles; ++i) {
+ if (mf.IsAlias(args[i])) {
+ status.SetError("can not be used on an ALIAS target.");
return false;
}
- bool ret = cmSetTargetPropertiesCommand::SetOneTarget(
- args[i], propertyPairs, this->Makefile);
+ bool ret = SetOneTarget(args[i], propertyPairs, &mf);
if (!ret) {
- std::string message = "Can not find target to add properties to: ";
- message += args[i];
- this->SetError(message);
+ status.SetError(
+ cmStrCat("Can not find target to add properties to: ", args[i]));
return false;
}
}
return true;
}
-bool cmSetTargetPropertiesCommand::SetOneTarget(
- const std::string& tname, std::vector<std::string>& propertyPairs,
- cmMakefile* mf)
+static bool SetOneTarget(const std::string& tname,
+ std::vector<std::string>& propertyPairs,
+ cmMakefile* mf)
{
if (cmTarget* target = mf->FindTargetToUse(tname)) {
// now loop through all the props and set them
diff --git a/Source/cmSetTargetPropertiesCommand.h b/Source/cmSetTargetPropertiesCommand.h
index 425618157..9d40c7498 100644
--- a/Source/cmSetTargetPropertiesCommand.h
+++ b/Source/cmSetTargetPropertiesCommand.h
@@ -3,34 +3,14 @@
#ifndef cmSetTargetsPropertiesCommand_h
#define cmSetTargetsPropertiesCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmMakefile;
-
-class cmSetTargetPropertiesCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE { return new cmSetTargetPropertiesCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the input file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
- /**
- * Used by this command and cmSetPropertiesCommand
- */
- static bool SetOneTarget(const std::string& tname,
- std::vector<std::string>& propertyPairs,
- cmMakefile* mf);
-};
+bool cmSetTargetPropertiesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmSetTestsPropertiesCommand.cxx b/Source/cmSetTestsPropertiesCommand.cxx
index e27c675c6..de61edaf0 100644
--- a/Source/cmSetTestsPropertiesCommand.cxx
+++ b/Source/cmSetTestsPropertiesCommand.cxx
@@ -4,20 +4,26 @@
#include <iterator>
+#include "cmAlgorithms.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
#include "cmTest.h"
-class cmExecutionStatus;
+static bool SetOneTest(const std::string& tname,
+ std::vector<std::string>& propertyPairs, cmMakefile* mf,
+ std::string& errors);
-// cmSetTestsPropertiesCommand
-bool cmSetTestsPropertiesCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmSetTestsPropertiesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
+ cmMakefile& mf = status.GetMakefile();
+
// first collect up the list of files
std::vector<std::string> propertyPairs;
int numFiles = 0;
@@ -27,17 +33,17 @@ bool cmSetTestsPropertiesCommand::InitialPass(
// now loop through the rest of the arguments, new style
++j;
if (std::distance(j, args.end()) % 2 != 0) {
- this->SetError("called with incorrect number of arguments.");
+ status.SetError("called with incorrect number of arguments.");
return false;
}
- propertyPairs.insert(propertyPairs.end(), j, args.end());
+ cmAppend(propertyPairs, j, args.end());
break;
}
numFiles++;
}
if (propertyPairs.empty()) {
- this->SetError("called with illegal arguments, maybe "
- "missing a PROPERTIES specifier?");
+ status.SetError("called with illegal arguments, maybe "
+ "missing a PROPERTIES specifier?");
return false;
}
@@ -45,10 +51,9 @@ bool cmSetTestsPropertiesCommand::InitialPass(
int i;
for (i = 0; i < numFiles; ++i) {
std::string errors;
- bool ret = cmSetTestsPropertiesCommand::SetOneTest(args[i], propertyPairs,
- this->Makefile, errors);
+ bool ret = SetOneTest(args[i], propertyPairs, &mf, errors);
if (!ret) {
- this->SetError(errors);
+ status.SetError(errors);
return ret;
}
}
@@ -56,9 +61,9 @@ bool cmSetTestsPropertiesCommand::InitialPass(
return true;
}
-bool cmSetTestsPropertiesCommand::SetOneTest(
- const std::string& tname, std::vector<std::string>& propertyPairs,
- cmMakefile* mf, std::string& errors)
+static bool SetOneTest(const std::string& tname,
+ std::vector<std::string>& propertyPairs, cmMakefile* mf,
+ std::string& errors)
{
if (cmTest* test = mf->GetTest(tname)) {
// now loop through all the props and set them
@@ -69,8 +74,7 @@ bool cmSetTestsPropertiesCommand::SetOneTest(
}
}
} else {
- errors = "Can not find test to add properties to: ";
- errors += tname;
+ errors = cmStrCat("Can not find test to add properties to: ", tname);
return false;
}
diff --git a/Source/cmSetTestsPropertiesCommand.h b/Source/cmSetTestsPropertiesCommand.h
index 90f004c34..4b754641b 100644
--- a/Source/cmSetTestsPropertiesCommand.h
+++ b/Source/cmSetTestsPropertiesCommand.h
@@ -3,31 +3,14 @@
#ifndef cmSetTestsPropertiesCommand_h
#define cmSetTestsPropertiesCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmMakefile;
-
-class cmSetTestsPropertiesCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE { return new cmSetTestsPropertiesCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the input file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
- static bool SetOneTest(const std::string& tname,
- std::vector<std::string>& propertyPairs,
- cmMakefile* mf, std::string& errors);
-};
+bool cmSetTestsPropertiesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmSiteNameCommand.cxx b/Source/cmSiteNameCommand.cxx
index 7eace268f..d47f121e0 100644
--- a/Source/cmSiteNameCommand.cxx
+++ b/Source/cmSiteNameCommand.cxx
@@ -4,34 +4,34 @@
#include "cmsys/RegularExpression.hxx"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
-
// cmSiteNameCommand
-bool cmSiteNameCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmSiteNameCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() != 1) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
std::vector<std::string> paths;
- paths.push_back("/usr/bsd");
- paths.push_back("/usr/sbin");
- paths.push_back("/usr/bin");
- paths.push_back("/bin");
- paths.push_back("/sbin");
- paths.push_back("/usr/local/bin");
+ paths.emplace_back("/usr/bsd");
+ paths.emplace_back("/usr/sbin");
+ paths.emplace_back("/usr/bin");
+ paths.emplace_back("/bin");
+ paths.emplace_back("/sbin");
+ paths.emplace_back("/usr/local/bin");
- const char* cacheValue = this->Makefile->GetDefinition(args[0]);
+ const char* cacheValue = status.GetMakefile().GetDefinition(args[0]);
if (cacheValue) {
return true;
}
- const char* temp = this->Makefile->GetDefinition("HOSTNAME");
+ const char* temp = status.GetMakefile().GetDefinition("HOSTNAME");
std::string hostname_cmd;
if (temp) {
hostname_cmd = temp;
@@ -50,11 +50,10 @@ bool cmSiteNameCommand::InitialPass(std::vector<std::string> const& args,
}
#else
// try to find the hostname for this computer
- if (!cmSystemTools::IsOff(hostname_cmd.c_str())) {
+ if (!cmIsOff(hostname_cmd)) {
std::string host;
- cmSystemTools::RunSingleCommand(hostname_cmd.c_str(), &host, CM_NULLPTR,
- CM_NULLPTR, CM_NULLPTR,
- cmSystemTools::OUTPUT_NONE);
+ cmSystemTools::RunSingleCommand(hostname_cmd, &host, nullptr, nullptr,
+ nullptr, cmSystemTools::OUTPUT_NONE);
// got the hostname
if (!host.empty()) {
@@ -72,7 +71,7 @@ bool cmSiteNameCommand::InitialPass(std::vector<std::string> const& args,
}
}
#endif
- this->Makefile->AddCacheDefinition(
+ status.GetMakefile().AddCacheDefinition(
args[0], siteName.c_str(),
"Name of the computer/site where compile is being run",
cmStateEnums::STRING);
diff --git a/Source/cmSiteNameCommand.h b/Source/cmSiteNameCommand.h
index 6c65480ed..e8fc60807 100644
--- a/Source/cmSiteNameCommand.h
+++ b/Source/cmSiteNameCommand.h
@@ -3,34 +3,19 @@
#ifndef cmSiteNameCommand_h
#define cmSiteNameCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmSiteNameCommand
+/**
* \brief site_name command
*
* cmSiteNameCommand implements the site_name CMake command
*/
-class cmSiteNameCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmSiteNameCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmSiteNameCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx
index 5c4f18b40..2a345eb85 100644
--- a/Source/cmSourceFile.cxx
+++ b/Source/cmSourceFile.cxx
@@ -2,28 +2,23 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSourceFile.h"
-#include <sstream>
+#include <array>
+#include <utility>
-#include "cmCustomCommand.h"
#include "cmGlobalGenerator.h"
+#include "cmListFileCache.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmProperty.h"
#include "cmState.h"
+#include "cmStringAlgorithms.h"
#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 = CM_NULLPTR;
- this->FindFullPathFailed = false;
- this->IsUiFile = (".ui" == cmSystemTools::GetFilenameLastExtension(
- this->Location.GetName()));
-}
-
-cmSourceFile::~cmSourceFile()
-{
- this->SetCustomCommand(CM_NULLPTR);
}
std::string const& cmSourceFile::GetExtension() const
@@ -32,6 +27,13 @@ std::string const& cmSourceFile::GetExtension() const
}
const std::string cmSourceFile::propLANGUAGE = "LANGUAGE";
+const std::string cmSourceFile::propLOCATION = "LOCATION";
+const std::string cmSourceFile::propGENERATED = "GENERATED";
+const std::string cmSourceFile::propCOMPILE_DEFINITIONS =
+ "COMPILE_DEFINITIONS";
+const std::string cmSourceFile::propCOMPILE_OPTIONS = "COMPILE_OPTIONS";
+const std::string cmSourceFile::propINCLUDE_DIRECTORIES =
+ "INCLUDE_DIRECTORIES";
void cmSourceFile::SetObjectLibrary(std::string const& objlib)
{
@@ -43,11 +45,13 @@ std::string cmSourceFile::GetObjectLibrary() const
return this->ObjectLibrary;
}
-std::string cmSourceFile::GetLanguage()
+std::string const& cmSourceFile::GetOrDetermineLanguage()
{
// If the language was set explicitly by the user then use it.
if (const char* lang = this->GetProperty(propLANGUAGE)) {
- return lang;
+ // Assign to member in order to return a reference.
+ this->Language = lang;
+ return this->Language;
}
// Perform computation needed to get the language if necessary.
@@ -61,7 +65,7 @@ std::string cmSourceFile::GetLanguage()
this->Location.DirectoryIsAmbiguous()) {
// Finalize the file location to get the extension and set the
// language.
- this->GetFullPath();
+ this->ResolveFullPath();
} else {
// Use the known extension to get the language if possible.
std::string ext =
@@ -70,8 +74,8 @@ std::string cmSourceFile::GetLanguage()
}
}
- // Now try to determine the language.
- return static_cast<cmSourceFile const*>(this)->GetLanguage();
+ // Use the language determined from the file extension.
+ return this->Language;
}
std::string cmSourceFile::GetLanguage() const
@@ -81,13 +85,8 @@ std::string cmSourceFile::GetLanguage() const
return lang;
}
- // If the language was determined from the source file extension use it.
- if (!this->Language.empty()) {
- return this->Language;
- }
-
- // The language is not known.
- return "";
+ // Use the language determined from the file extension.
+ return this->Language;
}
cmSourceFileLocation const& cmSourceFile::GetLocation() const
@@ -95,7 +94,7 @@ cmSourceFileLocation const& cmSourceFile::GetLocation() const
return this->Location;
}
-std::string const& cmSourceFile::GetFullPath(std::string* error)
+std::string const& cmSourceFile::ResolveFullPath(std::string* error)
{
if (this->FullPath.empty()) {
if (this->FindFullPath(error)) {
@@ -112,95 +111,84 @@ 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->FindFullPathFailed) {
- return false;
- }
-
- // If the file is generated compute the location without checking on
- // disk.
- if (this->GetPropertyAsBool("GENERATED")) {
+ // If the file is generated compute the location without checking on disk.
+ if (this->GetIsGenerated()) {
// The file is either already a full path or is relative to the
// build directory for the target.
this->Location.DirectoryUseBinary();
- this->FullPath = this->Location.GetDirectory();
- this->FullPath += "/";
- this->FullPath += this->Location.GetName();
+ this->FullPath = this->Location.GetFullPath();
return true;
}
- // The file is not generated. It must exist on disk.
- cmMakefile const* mf = this->Location.GetMakefile();
- const char* tryDirs[3] = { CM_NULLPTR, CM_NULLPTR, CM_NULLPTR };
- if (this->Location.DirectoryIsAmbiguous()) {
- tryDirs[0] = mf->GetCurrentSourceDirectory();
- tryDirs[1] = mf->GetCurrentBinaryDirectory();
- } else {
- tryDirs[0] = "";
+ // If this method has already failed once do not try again.
+ if (this->FindFullPathFailed) {
+ return false;
}
- const std::vector<std::string>& srcExts =
- mf->GetCMakeInstance()->GetSourceExtensions();
- std::vector<std::string> hdrExts =
- mf->GetCMakeInstance()->GetHeaderExtensions();
- for (const char* const* di = tryDirs; *di; ++di) {
- std::string tryPath = this->Location.GetDirectory();
- if (!tryPath.empty()) {
- tryPath += "/";
- }
- tryPath += this->Location.GetName();
- tryPath = cmSystemTools::CollapseFullPath(tryPath, *di);
- if (this->TryFullPath(tryPath, "")) {
+
+ // The file is not generated. It must exist on disk.
+ cmMakefile const* makefile = this->Location.GetMakefile();
+ // Location path
+ std::string const lPath = this->Location.GetFullPath();
+ // List of extension lists
+ std::array<std::vector<std::string> const*, 2> const extsLists = {
+ { &makefile->GetCMakeInstance()->GetSourceExtensions(),
+ &makefile->GetCMakeInstance()->GetHeaderExtensions() }
+ };
+
+ // Tries to find the file in a given directory
+ auto findInDir = [this, &extsLists, &lPath](std::string const& dir) -> bool {
+ // Compute full path
+ std::string const fullPath = cmSystemTools::CollapseFullPath(lPath, dir);
+ // Try full path
+ if (cmSystemTools::FileExists(fullPath)) {
+ this->FullPath = fullPath;
return true;
}
- for (std::vector<std::string>::const_iterator ei = srcExts.begin();
- ei != srcExts.end(); ++ei) {
- if (this->TryFullPath(tryPath, *ei)) {
- return true;
+ // Try full path with extension
+ for (auto exts : extsLists) {
+ for (std::string const& ext : *exts) {
+ if (!ext.empty()) {
+ std::string extPath = cmStrCat(fullPath, '.', ext);
+ if (cmSystemTools::FileExists(extPath)) {
+ this->FullPath = extPath;
+ return true;
+ }
+ }
}
}
- for (std::vector<std::string>::const_iterator ei = hdrExts.begin();
- ei != hdrExts.end(); ++ei) {
- if (this->TryFullPath(tryPath, *ei)) {
- return true;
- }
+ // File not found
+ return false;
+ };
+
+ // Try to find the file in various directories
+ if (this->Location.DirectoryIsAmbiguous()) {
+ if (findInDir(makefile->GetCurrentSourceDirectory()) ||
+ findInDir(makefile->GetCurrentBinaryDirectory())) {
+ return true;
+ }
+ } else {
+ if (findInDir({})) {
+ return true;
}
}
- std::ostringstream e;
- std::string missing = this->Location.GetDirectory();
- if (!missing.empty()) {
- missing += "/";
- }
- missing += this->Location.GetName();
- e << "Cannot find source file:\n " << missing << "\nTried extensions";
- for (std::vector<std::string>::const_iterator ext = srcExts.begin();
- ext != srcExts.end(); ++ext) {
- e << " ." << *ext;
- }
- for (std::vector<std::string>::const_iterator ext = hdrExts.begin();
- ext != hdrExts.end(); ++ext) {
- e << " ." << *ext;
+ // Compose error
+ std::string err =
+ cmStrCat("Cannot find source file:\n ", lPath, "\nTried extensions");
+ for (auto exts : extsLists) {
+ for (std::string const& ext : *exts) {
+ err += " .";
+ err += ext;
+ }
}
- if (error) {
- *error = e.str();
+ if (error != nullptr) {
+ *error = std::move(err);
} else {
- this->Location.GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str());
+ makefile->IssueMessage(MessageType::FATAL_ERROR, err);
}
this->FindFullPathFailed = true;
- return false;
-}
-bool cmSourceFile::TryFullPath(const std::string& path, const std::string& ext)
-{
- std::string tryPath = path;
- if (!ext.empty()) {
- tryPath += ".";
- tryPath += ext;
- }
- if (cmSystemTools::FileExists(tryPath.c_str())) {
- this->FullPath = tryPath;
- return true;
- }
+ // File not found
return false;
}
@@ -244,20 +232,60 @@ bool cmSourceFile::Matches(cmSourceFileLocation const& loc)
void cmSourceFile::SetProperty(const std::string& prop, const char* value)
{
- this->Properties.SetProperty(prop, value);
-
- if (this->IsUiFile) {
- cmMakefile const* mf = this->Location.GetMakefile();
- if (prop == "AUTOUIC_OPTIONS") {
- const_cast<cmMakefile*>(mf)->AddQtUiFileWithOptions(this);
+ if (prop == propINCLUDE_DIRECTORIES) {
+ this->IncludeDirectories.clear();
+ if (value) {
+ cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace();
+ this->IncludeDirectories.emplace_back(value, lfbt);
+ }
+ } else if (prop == propCOMPILE_OPTIONS) {
+ this->CompileOptions.clear();
+ if (value) {
+ cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace();
+ this->CompileOptions.emplace_back(value, lfbt);
}
+ } else if (prop == propCOMPILE_DEFINITIONS) {
+ this->CompileDefinitions.clear();
+ if (value) {
+ cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace();
+ this->CompileDefinitions.emplace_back(value, lfbt);
+ }
+ } else {
+ this->Properties.SetProperty(prop, value);
+ }
+
+ // Update IsGenerated flag
+ if (prop == propGENERATED) {
+ this->IsGenerated = cmIsOn(value);
}
}
void cmSourceFile::AppendProperty(const std::string& prop, const char* value,
bool asString)
{
- this->Properties.AppendProperty(prop, value, asString);
+ if (prop == propINCLUDE_DIRECTORIES) {
+ if (value && *value) {
+ cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace();
+ this->IncludeDirectories.emplace_back(value, lfbt);
+ }
+ } else if (prop == propCOMPILE_OPTIONS) {
+ if (value && *value) {
+ cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace();
+ this->CompileOptions.emplace_back(value, lfbt);
+ }
+ } else if (prop == propCOMPILE_DEFINITIONS) {
+ if (value && *value) {
+ cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace();
+ this->CompileDefinitions.emplace_back(value, lfbt);
+ }
+ } else {
+ this->Properties.AppendProperty(prop, value, asString);
+ }
+
+ // Update IsGenerated flag
+ if (prop == propGENERATED) {
+ this->IsGenerated = this->GetPropertyAsBool(propGENERATED);
+ }
}
const char* cmSourceFile::GetPropertyForUser(const std::string& prop)
@@ -276,9 +304,16 @@ const char* cmSourceFile::GetPropertyForUser(const std::string& prop)
// cmSourceFileLocation class to commit to a particular full path to
// the source file as late as possible. If the users requests the
// LOCATION property we must commit now.
- if (prop == "LOCATION") {
+ if (prop == propLOCATION) {
// Commit to a location.
- this->GetFullPath();
+ this->ResolveFullPath();
+ }
+
+ // Similarly, LANGUAGE can be determined by the file extension
+ // if it is requested by the user.
+ if (prop == propLANGUAGE) {
+ // The c_str pointer is valid until `this->Language` is modified.
+ return this->GetOrDetermineLanguage().c_str();
}
// Perform the normal property lookup.
@@ -288,13 +323,44 @@ const char* cmSourceFile::GetPropertyForUser(const std::string& prop)
const char* cmSourceFile::GetProperty(const std::string& prop) const
{
// Check for computed properties.
- if (prop == "LOCATION") {
+ if (prop == propLOCATION) {
if (this->FullPath.empty()) {
- return CM_NULLPTR;
+ return nullptr;
}
return this->FullPath.c_str();
}
+ // Check for the properties with backtraces.
+ if (prop == propINCLUDE_DIRECTORIES) {
+ if (this->IncludeDirectories.empty()) {
+ return nullptr;
+ }
+
+ static std::string output;
+ output = cmJoin(this->IncludeDirectories, ";");
+ return output.c_str();
+ }
+
+ if (prop == propCOMPILE_OPTIONS) {
+ if (this->CompileOptions.empty()) {
+ return nullptr;
+ }
+
+ static std::string output;
+ output = cmJoin(this->CompileOptions, ";");
+ return output.c_str();
+ }
+
+ if (prop == propCOMPILE_DEFINITIONS) {
+ if (this->CompileDefinitions.empty()) {
+ return nullptr;
+ }
+
+ static std::string output;
+ output = cmJoin(this->CompileDefinitions, ";");
+ return output.c_str();
+ }
+
const char* retVal = this->Properties.GetPropertyValue(prop);
if (!retVal) {
cmMakefile const* mf = this->Location.GetMakefile();
@@ -308,24 +374,33 @@ const char* cmSourceFile::GetProperty(const std::string& prop) const
return retVal;
}
+const char* cmSourceFile::GetSafeProperty(const std::string& prop) const
+{
+ const char* ret = this->GetProperty(prop);
+ if (!ret) {
+ return "";
+ }
+ return ret;
+}
+
bool cmSourceFile::GetPropertyAsBool(const std::string& prop) const
{
- return cmSystemTools::IsOn(this->GetProperty(prop));
+ return cmIsOn(this->GetProperty(prop));
}
-cmCustomCommand* cmSourceFile::GetCustomCommand()
+void cmSourceFile::SetProperties(cmPropertyMap properties)
{
- return this->CustomCommand;
+ this->Properties = std::move(properties);
+
+ this->IsGenerated = this->GetPropertyAsBool(propGENERATED);
}
-cmCustomCommand const* cmSourceFile::GetCustomCommand() const
+cmCustomCommand* cmSourceFile::GetCustomCommand() const
{
- return this->CustomCommand;
+ return this->CustomCommand.get();
}
-void cmSourceFile::SetCustomCommand(cmCustomCommand* cc)
+void cmSourceFile::SetCustomCommand(std::unique_ptr<cmCustomCommand> cc)
{
- cmCustomCommand* old = this->CustomCommand;
- this->CustomCommand = cc;
- delete old;
+ this->CustomCommand = std::move(cc);
}
diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h
index 0be659c5f..82a3625b8 100644
--- a/Source/cmSourceFile.h
+++ b/Source/cmSourceFile.h
@@ -3,15 +3,18 @@
#ifndef cmSourceFile_h
#define cmSourceFile_h
-#include "cmConfigure.h"
-
-#include "cmPropertyMap.h"
-#include "cmSourceFileLocation.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+#include <memory>
#include <string>
#include <vector>
-class cmCustomCommand;
+#include "cmCustomCommand.h"
+#include "cmListFileCache.h"
+#include "cmPropertyMap.h"
+#include "cmSourceFileLocation.h"
+#include "cmSourceFileLocationKind.h"
+
class cmMakefile;
/** \class cmSourceFile
@@ -27,37 +30,59 @@ public:
* Construct with the makefile storing the source and the initial
* name referencing it.
*/
- cmSourceFile(cmMakefile* mf, const std::string& name);
-
- ~cmSourceFile();
+ cmSourceFile(
+ cmMakefile* mf, const std::string& name,
+ cmSourceFileLocationKind kind = cmSourceFileLocationKind::Ambiguous);
/**
- * Get the list of the custom commands for this source file
+ * Get the custom command for this source file
*/
- cmCustomCommand* GetCustomCommand();
- cmCustomCommand const* GetCustomCommand() const;
- void SetCustomCommand(cmCustomCommand* cc);
+ cmCustomCommand* GetCustomCommand() const;
+ void SetCustomCommand(std::unique_ptr<cmCustomCommand> cc);
- ///! Set/Get a property of this source file
+ //! Set/Get a property of this source file
void SetProperty(const std::string& prop, const char* value);
void AppendProperty(const std::string& prop, const char* value,
bool asString = false);
+ //! Might return a nullptr if the property is not set or invalid
const char* GetProperty(const std::string& prop) const;
+ //! Always returns a valid pointer
+ const char* GetSafeProperty(const std::string& prop) const;
bool GetPropertyAsBool(const std::string& prop) const;
/** Implement getting a property when called from a CMake language
command like get_property or get_source_file_property. */
const char* GetPropertyForUser(const std::string& prop);
+ //! Checks is the GENERATED property is set and true
+ /// @return Equivalent to GetPropertyAsBool("GENERATED")
+ bool GetIsGenerated() const { return this->IsGenerated; }
+
+ const std::vector<BT<std::string>>& GetCompileOptions() const
+ {
+ return this->CompileOptions;
+ }
+
+ const std::vector<BT<std::string>>& GetCompileDefinitions() const
+ {
+ return this->CompileDefinitions;
+ }
+
+ const std::vector<BT<std::string>>& GetIncludeDirectories() const
+ {
+ return this->IncludeDirectories;
+ }
+
+ /**
+ * Resolves the full path to the file. Attempts to locate the file on disk
+ * and finalizes its location.
+ */
+ std::string const& ResolveFullPath(std::string* error = nullptr);
+
/**
- * The full path to the file. The non-const version of this method
- * may attempt to locate the file on disk and finalize its location.
- * The const version of this method may return an empty string if
- * the non-const version has not yet been called (yes this is a
- * horrible interface, but is necessary for backwards
- * compatibility).
+ * The resolved full path to the file. The returned file name might be empty
+ * if the path has not yet been resolved.
*/
- std::string const& GetFullPath(std::string* error = CM_NULLPTR);
std::string const& GetFullPath() const;
/**
@@ -75,7 +100,7 @@ public:
/**
* Get the language of the compiler to use for this source file.
*/
- std::string GetLanguage();
+ std::string const& GetOrDetermineLanguage();
std::string GetLanguage() const;
/**
@@ -85,8 +110,9 @@ public:
void AddDepend(const std::string& d) { this->Depends.push_back(d); }
// Get the properties
- cmPropertyMap& GetProperties() { return this->Properties; }
const cmPropertyMap& GetProperties() const { return this->Properties; }
+ // Set the properties
+ void SetProperties(cmPropertyMap properties);
/**
* Check whether the given source file location could refer to this
@@ -100,24 +126,40 @@ public:
private:
cmSourceFileLocation Location;
cmPropertyMap Properties;
- cmCustomCommand* CustomCommand;
+ std::unique_ptr<cmCustomCommand> CustomCommand;
std::string Extension;
std::string Language;
std::string FullPath;
std::string ObjectLibrary;
std::vector<std::string> Depends;
- bool FindFullPathFailed;
- bool IsUiFile;
+ std::vector<BT<std::string>> CompileOptions;
+ std::vector<BT<std::string>> CompileDefinitions;
+ std::vector<BT<std::string>> IncludeDirectories;
+ bool FindFullPathFailed = false;
+ bool IsGenerated = false;
bool FindFullPath(std::string* error);
- bool TryFullPath(const std::string& path, const std::string& ext);
void CheckExtension();
void CheckLanguage(std::string const& ext);
static const std::string propLANGUAGE;
+ static const std::string propLOCATION;
+ static const std::string propGENERATED;
+ static const std::string propCOMPILE_DEFINITIONS;
+ static const std::string propCOMPILE_OPTIONS;
+ static const std::string propINCLUDE_DIRECTORIES;
};
// TODO: Factor out into platform information modules.
#define CM_HEADER_REGEX "\\.(h|hh|h\\+\\+|hm|hpp|hxx|in|txx|inl)$"
+#define CM_SOURCE_REGEX \
+ "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|cu|f|f90|for|fpp|ftn|m|mm|rc|def|r|odl|idl|" \
+ "hpj" \
+ "|bat)$"
+
+#define CM_PCH_REGEX "cmake_pch\\.(h|hxx)$"
+
+#define CM_RESOURCE_REGEX "\\.(pdf|plist|png|jpeg|jpg|storyboard|xcassets)$"
+
#endif
diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx
index 86711d784..df702b050 100644
--- a/Source/cmSourceFileLocation.cxx
+++ b/Source/cmSourceFileLocation.cxx
@@ -2,24 +2,16 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSourceFileLocation.h"
-#include "cmConfigure.h"
+#include <cassert>
-#include "cmAlgorithms.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
-#include <algorithm>
-#include <assert.h>
-#include <vector>
-
-cmSourceFileLocation::cmSourceFileLocation()
- : Makefile(CM_NULLPTR)
- , AmbiguousDirectory(true)
- , AmbiguousExtension(true)
-{
-}
+cmSourceFileLocation::cmSourceFileLocation() = default;
cmSourceFileLocation::cmSourceFileLocation(const cmSourceFileLocation& loc)
: Makefile(loc.Makefile)
@@ -30,33 +22,34 @@ cmSourceFileLocation::cmSourceFileLocation(const cmSourceFileLocation& loc)
this->Name = loc.Name;
}
-cmSourceFileLocation& cmSourceFileLocation::operator=(
- const cmSourceFileLocation& loc)
-{
- if (this == &loc) {
- return *this;
- }
- this->Makefile = loc.Makefile;
- this->AmbiguousDirectory = loc.AmbiguousDirectory;
- this->AmbiguousExtension = loc.AmbiguousExtension;
- this->Directory = loc.Directory;
- this->Name = loc.Name;
- this->UpdateExtension(this->Name);
- return *this;
-}
-
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);
+ }
+}
+
+std::string cmSourceFileLocation::GetFullPath() const
+{
+ std::string path = this->GetDirectory();
+ if (!path.empty()) {
+ path += '/';
+ }
+ path += this->GetName();
+ return path;
}
void cmSourceFileLocation::Update(cmSourceFileLocation const& loc)
@@ -103,13 +96,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;
@@ -121,15 +110,14 @@ void cmSourceFileLocation::UpdateExtension(const std::string& name)
// Check the source tree only because a file in the build tree should
// be specified by full path at least once. We do not want this
// detection to depend on whether the project has already been built.
- tryPath = this->Makefile->GetCurrentSourceDirectory();
- tryPath += "/";
+ tryPath = cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/');
}
if (!this->Directory.empty()) {
tryPath += this->Directory;
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);
@@ -157,8 +145,7 @@ bool cmSourceFileLocation::MatchesAmbiguousExtension(
// adding an extension.
if (!(this->Name.size() > loc.Name.size() &&
this->Name[loc.Name.size()] == '.' &&
- cmHasLiteralPrefixImpl(this->Name.c_str(), loc.Name.c_str(),
- loc.Name.size()))) {
+ cmHasPrefix(this->Name, loc.Name))) {
return false;
}
@@ -166,14 +153,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)
@@ -220,7 +201,7 @@ bool cmSourceFileLocation::Matches(cmSourceFileLocation const& loc)
// This can occur when referencing a source file from a different
// directory. This is not yet allowed.
this->Makefile->IssueMessage(
- cmake::INTERNAL_ERROR,
+ MessageType::INTERNAL_ERROR,
"Matches error: Each side has a directory relative to a different "
"location. This can occur when referencing a source file from a "
"different directory. This is not yet allowed.");
@@ -228,18 +209,18 @@ bool cmSourceFileLocation::Matches(cmSourceFileLocation const& loc)
}
} else if (this->AmbiguousDirectory) {
// Compare possible directory combinations.
- std::string const& srcDir = cmSystemTools::CollapseFullPath(
+ std::string const srcDir = cmSystemTools::CollapseFullPath(
this->Directory, this->Makefile->GetCurrentSourceDirectory());
- std::string const& binDir = cmSystemTools::CollapseFullPath(
+ std::string const binDir = cmSystemTools::CollapseFullPath(
this->Directory, this->Makefile->GetCurrentBinaryDirectory());
if (srcDir != loc.Directory && binDir != loc.Directory) {
return false;
}
} else if (loc.AmbiguousDirectory) {
// Compare possible directory combinations.
- std::string const& srcDir = cmSystemTools::CollapseFullPath(
+ std::string const srcDir = cmSystemTools::CollapseFullPath(
loc.Directory, loc.Makefile->GetCurrentSourceDirectory());
- std::string const& binDir = cmSystemTools::CollapseFullPath(
+ std::string const binDir = cmSystemTools::CollapseFullPath(
loc.Directory, loc.Makefile->GetCurrentBinaryDirectory());
if (srcDir != this->Directory && binDir != this->Directory) {
return false;
diff --git a/Source/cmSourceFileLocation.h b/Source/cmSourceFileLocation.h
index 6dbc2daed..87040b882 100644
--- a/Source/cmSourceFileLocation.h
+++ b/Source/cmSourceFileLocation.h
@@ -7,6 +7,8 @@
#include <string>
+#include "cmSourceFileLocationKind.h"
+
class cmMakefile;
/** \class cmSourceFileLocation
@@ -26,10 +28,13 @@ 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);
- cmSourceFileLocation& operator=(const cmSourceFileLocation& loc);
+
+ cmSourceFileLocation& operator=(cmSourceFileLocation const&) = delete;
/**
* Return whether the given source file location could refers to the
@@ -39,12 +44,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();
@@ -75,13 +80,19 @@ public:
const std::string& GetName() const { return this->Name; }
/**
+ * Get the full file path composed of GetDirectory() and GetName().
+ */
+ std::string GetFullPath() const;
+
+ /**
* Get the cmMakefile instance for which the source file was created.
*/
cmMakefile const* GetMakefile() const { return this->Makefile; }
+
private:
- cmMakefile const* Makefile;
- bool AmbiguousDirectory;
- bool AmbiguousExtension;
+ cmMakefile const* const Makefile = nullptr;
+ bool AmbiguousDirectory = true;
+ bool AmbiguousExtension = true;
std::string Directory;
std::string Name;
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 104e959a9..8c3ec9fec 100644
--- a/Source/cmSourceGroup.cxx
+++ b/Source/cmSourceGroup.cxx
@@ -2,21 +2,24 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSourceGroup.h"
+#include <utility>
+
+#include "cmStringAlgorithms.h"
+
class cmSourceGroupInternals
{
public:
std::vector<cmSourceGroup> GroupChildren;
};
-cmSourceGroup::cmSourceGroup(const char* name, const char* regex,
+cmSourceGroup::cmSourceGroup(std::string name, const char* regex,
const char* parentName)
- : Name(name)
+ : Name(std::move(name))
{
this->Internal = new cmSourceGroupInternals;
this->SetGroupRegex(regex);
if (parentName) {
- this->FullName = parentName;
- this->FullName += "\\";
+ this->FullName = cmStrCat(parentName, '\\');
}
this->FullName += this->Name;
}
@@ -60,24 +63,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,58 +98,37 @@ 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
}
}
// if no child with this name was found return NULL
- return CM_NULLPTR;
+ 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;
}
}
- return CM_NULLPTR;
+ 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;
}
@@ -155,7 +137,7 @@ cmSourceGroup* cmSourceGroup::MatchChildrenRegex(const char* name)
return this;
}
- return CM_NULLPTR;
+ return nullptr;
}
std::vector<cmSourceGroup> const& cmSourceGroup::GetGroupChildren() const
diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h
index 97affed6e..581dc5dee 100644
--- a/Source/cmSourceGroup.h
+++ b/Source/cmSourceGroup.h
@@ -3,13 +3,14 @@
#ifndef cmSourceGroup_h
#define cmSourceGroup_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmsys/RegularExpression.hxx"
#include <set>
#include <string>
#include <vector>
+#include "cmsys/RegularExpression.hxx"
+
class cmSourceFile;
class cmSourceGroupInternals;
@@ -26,8 +27,8 @@ class cmSourceGroupInternals;
class cmSourceGroup
{
public:
- cmSourceGroup(const char* name, const char* regex,
- const char* parentName = CM_NULLPTR);
+ cmSourceGroup(std::string name, const char* regex,
+ const char* parentName = nullptr);
cmSourceGroup(cmSourceGroup const& r);
~cmSourceGroup();
cmSourceGroup& operator=(cmSourceGroup const&);
@@ -50,38 +51,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 a966300c0..cc62952d8 100644
--- a/Source/cmSourceGroupCommand.cxx
+++ b/Source/cmSourceGroupCommand.cxx
@@ -2,23 +2,32 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSourceGroupCommand.h"
+#include <cstddef>
+#include <map>
#include <set>
-#include <sstream>
-#include <stddef.h>
+#include <utility>
+#include "cmAlgorithms.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmSourceGroup.h"
+#include "cmStringAlgorithms.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;
+
+using ParsedArguments = std::map<std::string, std::vector<std::string>>;
+using ExpectedOptions = std::vector<std::string>;
+
+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)
{
- return cmSystemTools::tokenize(path, "\\/");
+ return cmTokenize(path, "\\/");
}
std::string getFullFilePath(const std::string& currentPath,
@@ -26,10 +35,8 @@ std::string getFullFilePath(const std::string& currentPath,
{
std::string fullPath = path;
- if (!cmSystemTools::FileIsFullPath(path.c_str())) {
- fullPath = currentPath;
- fullPath += "/";
- fullPath += path;
+ if (!cmSystemTools::FileIsFullPath(path)) {
+ fullPath = cmStrCat(currentPath, '/', path);
}
return cmSystemTools::CollapseFullPath(fullPath);
@@ -41,8 +48,8 @@ std::set<std::string> getSourceGroupFilesPaths(
std::set<std::string> ret;
const std::string::size_type rootLength = root.length();
- for (size_t i = 0; i < files.size(); ++i) {
- ret.insert(files[i].substr(rootLength + 1)); // +1 to also omnit last '/'
+ for (std::string const& file : files) {
+ ret.insert(file.substr(rootLength + 1)); // +1 to also omnit last '/'
}
return ret;
@@ -51,9 +58,9 @@ std::set<std::string> getSourceGroupFilesPaths(
bool rootIsPrefix(const std::string& root,
const std::vector<std::string>& files, std::string& error)
{
- for (size_t i = 0; i < files.size(); ++i) {
- if (!cmSystemTools::StringStartsWith(files[i], root.c_str())) {
- error = "ROOT: " + root + " is not a prefix of file: " + files[i];
+ for (std::string const& file : files) {
+ if (!cmHasPrefix(file, root)) {
+ error = cmStrCat("ROOT: ", root, " is not a prefix of file: ", file);
return false;
}
}
@@ -61,41 +68,28 @@ bool rootIsPrefix(const std::string& root,
return true;
}
-cmSourceGroup* addSourceGroup(const std::vector<std::string>& tokenizedPath,
- cmMakefile& makefile)
-{
- cmSourceGroup* sg;
-
- sg = makefile.GetSourceGroup(tokenizedPath);
- if (!sg) {
- makefile.AddSourceGroup(tokenizedPath);
- sg = makefile.GetSourceGroup(tokenizedPath);
- if (!sg) {
- return CM_NULLPTR;
- }
- }
-
- return sg;
-}
-
-std::string prepareFilePathForTree(const std::string& path,
- const std::string& currentSourceDir)
-{
- if (!cmSystemTools::FileIsFullPath(path)) {
- return cmSystemTools::CollapseFullPath(currentSourceDir + "/" + path);
- }
- return cmSystemTools::CollapseFullPath(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;
+ prepared.reserve(filesPaths.size());
+
+ for (auto const& filePath : filesPaths) {
+ std::string fullPath =
+ cmSystemTools::CollapseFullPath(filePath, currentSourceDir);
+ // If provided file path is actually not a directory, silently ignore it.
+ if (cmSystemTools::FileIsDirectory(fullPath)) {
+ continue;
+ }
- for (; begin != end; ++begin) {
- prepared.push_back(prepareFilePathForTree(*begin, currentSourceDir));
+ // Handle directory that doesn't exist yet.
+ if (!fullPath.empty() &&
+ (fullPath.back() == '/' || fullPath.back() == '\\')) {
+ continue;
+ }
+
+ prepared.emplace_back(std::move(fullPath));
}
return prepared;
@@ -108,167 +102,192 @@ bool addFilesToItsSourceGroups(const std::string& root,
{
cmSourceGroup* sg;
- for (std::set<std::string>::const_iterator it = sgFilesPaths.begin();
- it != sgFilesPaths.end(); ++it) {
+ for (std::string const& sgFilesPath : sgFilesPaths) {
std::vector<std::string> tokenizedPath;
if (!prefix.empty()) {
- tokenizedPath = tokenizePath(prefix + '/' + *it);
+ tokenizedPath = tokenizePath(cmStrCat(prefix, '/', sgFilesPath));
} else {
- tokenizedPath = tokenizePath(*it);
+ tokenizedPath = tokenizePath(sgFilesPath);
}
- if (tokenizedPath.size() > 1) {
+ if (!tokenizedPath.empty()) {
tokenizedPath.pop_back();
- sg = addSourceGroup(tokenizedPath, makefile);
+ if (tokenizedPath.empty()) {
+ tokenizedPath.emplace_back();
+ }
+
+ sg = makefile.GetOrCreateSourceGroup(tokenizedPath);
if (!sg) {
- errorMsg = "Could not create source group for file: " + *it;
+ errorMsg = "Could not create source group for file: " + sgFilesPath;
return false;
}
- const std::string fullPath = getFullFilePath(root, *it);
+ const std::string fullPath = getFullFilePath(root, sgFilesPath);
sg->AddGroupFile(fullPath);
}
}
return true;
}
+
+ExpectedOptions getExpectedOptions()
+{
+ ExpectedOptions options;
+
+ options.push_back(kTreeOptionName);
+ options.push_back(kPrefixOptionName);
+ options.push_back(kFilesOptionName);
+ options.push_back(kRegexOptionName);
+
+ return options;
}
-class cmExecutionStatus;
+bool isExpectedOption(const std::string& argument,
+ const ExpectedOptions& expectedOptions)
+{
+ return cmContains(expectedOptions, argument);
+}
-// cmSourceGroupCommand
-bool cmSourceGroupCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+void parseArguments(const std::vector<std::string>& args,
+ ParsedArguments& parsedArguments)
{
- if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
- return false;
+ 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;
}
- if (args[0] == "TREE") {
- std::string error;
+ for (; i < args.size();) {
+ // get current option and increment index to go to next argument
+ const std::string& currentOption = args[i++];
- if (!processTree(args, error)) {
- this->SetError(error);
- return false;
- }
+ // create current option entry in parsed arguments
+ std::vector<std::string>& currentOptionArguments =
+ parsedArguments[currentOption];
- return true;
+ // collect option arguments while we won't find another expected option
+ while (i < args.size() && !isExpectedOption(args[i], expectedOptions)) {
+ currentOptionArguments.push_back(args[i++]);
+ }
}
+}
- std::string delimiter = "\\";
- if (this->Makefile->GetDefinition("SOURCE_GROUP_DELIMITER")) {
- delimiter = this->Makefile->GetDefinition("SOURCE_GROUP_DELIMITER");
- }
+} // namespace
- std::vector<std::string> folders =
- cmSystemTools::tokenize(args[0], delimiter);
+static bool checkArgumentsPreconditions(const ParsedArguments& parsedArguments,
+ std::string& errorMsg);
- cmSourceGroup* sg = CM_NULLPTR;
- sg = this->Makefile->GetSourceGroup(folders);
- if (!sg) {
- this->Makefile->AddSourceGroup(folders);
- sg = this->Makefile->GetSourceGroup(folders);
- }
+static bool processTree(cmMakefile& mf, ParsedArguments& parsedArguments,
+ std::string& errorMsg);
- if (!sg) {
- this->SetError("Could not create or find source group");
+static bool checkSingleParameterArgumentPreconditions(
+ const std::string& argument, const ParsedArguments& parsedArguments,
+ std::string& errorMsg);
+
+bool cmSourceGroupCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.empty()) {
+ status.SetError("called with incorrect number of arguments");
return false;
}
+
+ cmMakefile& mf = status.GetMakefile();
+
// 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;
- }
+ cmSourceGroup* sg = mf.GetOrCreateSourceGroup(args[0]);
- // 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())) {
- src = this->Makefile->GetCurrentSourceDirectory();
- src += "/";
- src += args[i];
- }
- 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());
+ if (!sg) {
+ status.SetError("Could not create or find source group");
return false;
}
+
+ sg->SetGroupRegex(args[1].c_str());
+ return true;
}
- return true;
-}
+ ParsedArguments parsedArguments;
+ std::string errorMsg;
-bool cmSourceGroupCommand::checkTreeArgumentsPreconditions(
- const std::vector<std::string>& args, std::string& errorMsg) const
-{
- if (args.size() == 1) {
- errorMsg = "TREE argument given without a root.";
- return false;
- }
+ parseArguments(args, parsedArguments);
- if (args.size() < 3) {
- errorMsg = "Missing FILES arguments.";
+ if (!checkArgumentsPreconditions(parsedArguments, errorMsg)) {
return false;
}
- if (args[FilesWithoutPrefixKeywordIndex] != "FILES" &&
- args[PrefixKeywordIndex] != "PREFIX") {
- errorMsg = "Unknown argument \"" + args[2] +
- "\". Perhaps the FILES keyword is missing.\n";
- return false;
- }
+ if (parsedArguments.find(kTreeOptionName) != parsedArguments.end()) {
+ if (!processTree(mf, parsedArguments, errorMsg)) {
+ status.SetError(errorMsg);
+ return false;
+ }
+ } else {
+ if (parsedArguments.find(kSourceGroupOptionName) ==
+ parsedArguments.end()) {
+ status.SetError("Missing source group name.");
+ return false;
+ }
- if (args[PrefixKeywordIndex] == "PREFIX" &&
- (args.size() < 5 || args[FilesWithPrefixKeywordIndex] != "FILES")) {
- errorMsg = "Missing FILES arguments.";
- return false;
+ cmSourceGroup* sg = mf.GetOrCreateSourceGroup(args[0]);
+
+ if (!sg) {
+ status.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 = cmStrCat(mf.GetCurrentSourceDirectory(), '/', filesArg);
+ }
+ src = cmSystemTools::CollapseFullPath(src);
+ sg->AddGroupFile(src);
+ }
}
return true;
}
-bool cmSourceGroupCommand::processTree(const std::vector<std::string>& args,
- std::string& errorMsg)
+static bool checkArgumentsPreconditions(const ParsedArguments& parsedArguments,
+ std::string& errorMsg)
{
- if (!checkTreeArgumentsPreconditions(args, errorMsg)) {
- return false;
- }
+ return checkSingleParameterArgumentPreconditions(
+ kPrefixOptionName, parsedArguments, errorMsg) &&
+ checkSingleParameterArgumentPreconditions(kTreeOptionName, parsedArguments,
+ errorMsg) &&
+ checkSingleParameterArgumentPreconditions(kRegexOptionName,
+ parsedArguments, errorMsg);
+}
- 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;
- }
+static bool processTree(cmMakefile& mf, ParsedArguments& parsedArguments,
+ std::string& errorMsg)
+{
+ 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(),
- this->Makefile->GetCurrentSourceDirectory());
+ const std::vector<std::string> filesVector = prepareFilesPathsForTree(
+ parsedArguments[kFilesOptionName], mf.GetCurrentSourceDirectory());
if (!rootIsPrefix(root, filesVector, errorMsg)) {
return false;
@@ -277,9 +296,26 @@ bool cmSourceGroupCommand::processTree(const std::vector<std::string>& args,
std::set<std::string> sourceGroupPaths =
getSourceGroupFilesPaths(root, filesVector);
- if (!addFilesToItsSourceGroups(root, sourceGroupPaths, prefix,
- *(this->Makefile), errorMsg)) {
- return false;
+ return addFilesToItsSourceGroups(root, sourceGroupPaths, prefix, mf,
+ errorMsg);
+}
+
+static bool checkSingleParameterArgumentPreconditions(
+ const std::string& argument, const ParsedArguments& parsedArguments,
+ std::string& errorMsg)
+{
+ auto 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 7d56b0d65..ad3970157 100644
--- a/Source/cmSourceGroupCommand.h
+++ b/Source/cmSourceGroupCommand.h
@@ -3,41 +3,14 @@
#ifndef cmSourceGroupCommand_h
#define cmSourceGroupCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmSourceGroupCommand
- * \brief Adds a cmSourceGroup to the cmMakefile.
- *
- * cmSourceGroupCommand is used to define cmSourceGroups which split up
- * source files in to named, organized groups in the generated makefiles.
- */
-class cmSourceGroupCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmSourceGroupCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_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;
-};
+bool cmSourceGroupCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmStandardLexer.h b/Source/cmStandardLexer.h
index c9f42e4ce..13f7622a7 100644
--- a/Source/cmStandardLexer.h
+++ b/Source/cmStandardLexer.h
@@ -3,45 +3,45 @@
#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)
-#pragma warning(disable : 4018)
-#pragma warning(disable : 4127)
-#pragma warning(disable : 4131)
-#pragma warning(disable : 4244)
-#pragma warning(disable : 4251)
-#pragma warning(disable : 4267)
-#pragma warning(disable : 4305)
-#pragma warning(disable : 4309)
-#pragma warning(disable : 4706)
-#pragma warning(disable : 4786)
+# pragma warning(disable : 4018)
+# pragma warning(disable : 4127)
+# pragma warning(disable : 4131)
+# pragma warning(disable : 4244)
+# pragma warning(disable : 4251)
+# pragma warning(disable : 4267)
+# pragma warning(disable : 4305)
+# pragma warning(disable : 4309)
+# pragma warning(disable : 4706)
+# pragma warning(disable : 4786)
#endif
#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
-#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402
-#pragma GCC diagnostic ignored "-Wconversion"
-#pragma GCC diagnostic ignored "-Wsign-compare"
-#endif
-#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 403
-#pragma GCC diagnostic ignored "-Wsign-conversion"
-#endif
+# if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402
+# pragma GCC diagnostic ignored "-Wconversion"
+# pragma GCC diagnostic ignored "-Wsign-compare"
+# endif
+# if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 403
+# pragma GCC diagnostic ignored "-Wsign-conversion"
+# endif
#endif
/* Make sure isatty is available. */
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <io.h>
-#if defined(_MSC_VER)
-#define isatty _isatty
-#endif
+# include <io.h>
+# if defined(_MSC_VER)
+# define isatty _isatty
+# endif
#else
-#include <unistd.h> // IWYU pragma: export
+# include <unistd.h> // IWYU pragma: export
#endif
/* Make sure malloc and free are available on QNX. */
#ifdef __QNX__
-#include <malloc.h>
+# include <malloc.h>
#endif
/* Disable features we do not need. */
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index 92e47f748..f9b5ed1c0 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -2,43 +2,37 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmState.h"
-#include "cmsys/RegularExpression.hxx"
#include <algorithm>
-#include <assert.h>
-#include <string.h>
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
#include <utility>
-#include "cmAlgorithms.h"
+#include <cm/memory>
+
+#include "cmsys/RegularExpression.hxx"
+
#include "cmCacheManager.h"
#include "cmCommand.h"
#include "cmDefinitions.h"
-#include "cmDisallowedCommand.h"
+#include "cmExecutionStatus.h"
+#include "cmGlobVerificationManager.h"
#include "cmListFileCache.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmStatePrivate.h"
#include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#include "cmUnexpectedCommand.h"
#include "cmake.h"
cmState::cmState()
- : IsInTryCompile(false)
- , IsGeneratorMultiConfig(false)
- , WindowsShell(false)
- , WindowsVSIDE(false)
- , WatcomWMake(false)
- , MinGWMake(false)
- , NMake(false)
- , MSYSShell(false)
{
- this->CacheManager = new cmCacheManager;
+ this->CacheManager = cm::make_unique<cmCacheManager>();
+ this->GlobVerificationManager = cm::make_unique<cmGlobVerificationManager>();
}
-cmState::~cmState()
-{
- delete this->CacheManager;
- cmDeleteAll(this->BuiltinCommands);
- cmDeleteAll(this->ScriptedCommands);
-}
+cmState::~cmState() = default;
const char* cmState::GetTargetTypeName(cmStateEnums::TargetType targetType)
{
@@ -63,12 +57,12 @@ const char* cmState::GetTargetTypeName(cmStateEnums::TargetType targetType)
return "UNKNOWN_LIBRARY";
}
assert(false && "Unexpected target type");
- return CM_NULLPTR;
+ return nullptr;
}
const char* cmCacheEntryTypes[] = { "BOOL", "PATH", "FILEPATH",
"STRING", "INTERNAL", "STATIC",
- "UNINITIALIZED", CM_NULLPTR };
+ "UNINITIALIZED", nullptr };
const char* cmState::CacheEntryTypeToString(cmStateEnums::CacheEntryType type)
{
@@ -80,20 +74,29 @@ const char* cmState::CacheEntryTypeToString(cmStateEnums::CacheEntryType type)
cmStateEnums::CacheEntryType cmState::StringToCacheEntryType(const char* s)
{
+ cmStateEnums::CacheEntryType type = cmStateEnums::STRING;
+ StringToCacheEntryType(s, type);
+ return type;
+}
+
+bool cmState::StringToCacheEntryType(const char* s,
+ cmStateEnums::CacheEntryType& type)
+{
int i = 0;
while (cmCacheEntryTypes[i]) {
if (strcmp(s, cmCacheEntryTypes[i]) == 0) {
- return static_cast<cmStateEnums::CacheEntryType>(i);
+ type = static_cast<cmStateEnums::CacheEntryType>(i);
+ return true;
}
++i;
}
- return cmStateEnums::STRING;
+ return false;
}
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 +110,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)
@@ -132,12 +135,13 @@ const char* cmState::GetCacheEntryValue(std::string const& key) const
{
cmCacheManager::CacheEntry* e = this->CacheManager->GetCacheEntry(key);
if (!e) {
- return CM_NULLPTR;
+ return nullptr;
}
return e->Value.c_str();
}
-const char* cmState::GetInitializedCacheValue(std::string const& key) const
+const std::string* cmState::GetInitializedCacheValue(
+ std::string const& key) const
{
return this->CacheManager->GetInitializedCacheValue(key);
}
@@ -188,7 +192,7 @@ const char* cmState::GetCacheEntryProperty(std::string const& key,
cmCacheManager::CacheIterator it =
this->CacheManager->GetCacheIterator(key.c_str());
if (!it.PropertyExists(propertyName)) {
- return CM_NULLPTR;
+ return nullptr;
}
return it.GetProperty(propertyName);
}
@@ -207,6 +211,39 @@ void cmState::AddCacheEntry(const std::string& key, const char* value,
this->CacheManager->AddCacheEntry(key, value, helpString, type);
}
+bool cmState::DoWriteGlobVerifyTarget() const
+{
+ return this->GlobVerificationManager->DoWriteVerifyTarget();
+}
+
+std::string const& cmState::GetGlobVerifyScript() const
+{
+ return this->GlobVerificationManager->GetVerifyScript();
+}
+
+std::string const& cmState::GetGlobVerifyStamp() const
+{
+ return this->GlobVerificationManager->GetVerifyStamp();
+}
+
+bool cmState::SaveVerificationScript(const std::string& path)
+{
+ return this->GlobVerificationManager->SaveVerificationScript(path);
+}
+
+void cmState::AddGlobCacheEntry(bool recurse, bool listDirectories,
+ bool followSymlinks,
+ const std::string& relative,
+ const std::string& expression,
+ const std::vector<std::string>& files,
+ const std::string& variable,
+ cmListFileBacktrace const& backtrace)
+{
+ this->GlobVerificationManager->AddCacheEntry(
+ recurse, listDirectories, followSymlinks, relative, expression, files,
+ variable, backtrace);
+}
+
void cmState::RemoveCacheEntry(std::string const& key)
{
this->CacheManager->RemoveCacheEntry(key);
@@ -224,13 +261,14 @@ void cmState::RemoveCacheEntryProperty(std::string const& key,
std::string const& propertyName)
{
this->CacheManager->GetCacheIterator(key.c_str())
- .SetProperty(propertyName, (void*)CM_NULLPTR);
+ .SetProperty(propertyName, nullptr);
}
cmStateSnapshot cmState::Reset()
{
- this->GlobalProperties.clear();
+ this->GlobalProperties.Clear();
this->PropertyDefinitions.clear();
+ this->GlobVerificationManager->Reset();
cmStateDetail::PositionType pos = this->SnapshotData.Truncate();
this->ExecutionListFiles.Truncate();
@@ -244,9 +282,13 @@ cmStateSnapshot cmState::Reset()
it->CompileDefinitionsBacktraces.clear();
it->CompileOptions.clear();
it->CompileOptionsBacktraces.clear();
+ it->LinkOptions.clear();
+ it->LinkOptionsBacktraces.clear();
+ it->LinkDirectories.clear();
+ it->LinkDirectoriesBacktraces.clear();
it->DirectoryEnd = pos;
it->NormalTargetNames.clear();
- it->Properties.clear();
+ it->Properties.Clear();
it->Children.clear();
}
@@ -259,16 +301,16 @@ cmStateSnapshot cmState::Reset()
{
std::string srcDir =
- cmDefinitions::Get("CMAKE_SOURCE_DIR", pos->Vars, pos->Root);
+ *cmDefinitions::Get("CMAKE_SOURCE_DIR", pos->Vars, pos->Root);
std::string binDir =
- cmDefinitions::Get("CMAKE_BINARY_DIR", pos->Vars, pos->Root);
+ *cmDefinitions::Get("CMAKE_BINARY_DIR", pos->Vars, pos->Root);
this->VarTree.Clear();
pos->Vars = this->VarTree.Push(this->VarTree.Root());
pos->Parent = this->VarTree.Root();
pos->Root = this->VarTree.Root();
- pos->Vars->Set("CMAKE_SOURCE_DIR", srcDir.c_str());
- pos->Vars->Set("CMAKE_BINARY_DIR", binDir.c_str());
+ pos->Vars->Set("CMAKE_SOURCE_DIR", srcDir);
+ pos->Vars->Set("CMAKE_BINARY_DIR", binDir);
}
this->DefineProperty("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY, "", "",
@@ -283,7 +325,7 @@ cmStateSnapshot cmState::Reset()
this->DefineProperty("RULE_LAUNCH_LINK", cmProperty::TARGET, "", "", true);
this->DefineProperty("RULE_LAUNCH_CUSTOM", cmProperty::TARGET, "", "", true);
- return cmStateSnapshot(this, pos);
+ return { this, pos };
}
void cmState::DefineProperty(const std::string& name,
@@ -303,14 +345,13 @@ cmPropertyDefinition const* cmState::GetPropertyDefinition(
this->PropertyDefinitions.find(scope)->second;
return &defs.find(name)->second;
}
- return CM_NULLPTR;
+ return nullptr;
}
bool cmState::IsPropertyDefined(const std::string& name,
cmProperty::ScopeType scope) const
{
- std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::const_iterator it =
- this->PropertyDefinitions.find(scope);
+ auto it = this->PropertyDefinitions.find(scope);
if (it == this->PropertyDefinitions.end()) {
return false;
}
@@ -320,8 +361,7 @@ bool cmState::IsPropertyDefined(const std::string& name,
bool cmState::IsPropertyChained(const std::string& name,
cmProperty::ScopeType scope) const
{
- std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::const_iterator it =
- this->PropertyDefinitions.find(scope);
+ auto it = this->PropertyDefinitions.find(scope);
if (it == this->PropertyDefinitions.end()) {
return false;
}
@@ -330,8 +370,8 @@ bool cmState::IsPropertyChained(const std::string& name,
void cmState::SetLanguageEnabled(std::string const& l)
{
- std::vector<std::string>::iterator it = std::lower_bound(
- this->EnabledLanguages.begin(), this->EnabledLanguages.end(), l);
+ auto it = std::lower_bound(this->EnabledLanguages.begin(),
+ this->EnabledLanguages.end(), l);
if (it == this->EnabledLanguages.end() || *it != l) {
this->EnabledLanguages.insert(it, l);
}
@@ -378,65 +418,115 @@ void cmState::SetIsGeneratorMultiConfig(bool b)
this->IsGeneratorMultiConfig = b;
}
-void cmState::AddBuiltinCommand(std::string const& name, cmCommand* command)
+void cmState::AddBuiltinCommand(std::string const& name,
+ std::unique_ptr<cmCommand> command)
+{
+ this->AddBuiltinCommand(name, cmLegacyCommandWrapper(std::move(command)));
+}
+
+void cmState::AddBuiltinCommand(std::string const& name, Command command)
{
assert(name == cmSystemTools::LowerCase(name));
assert(this->BuiltinCommands.find(name) == this->BuiltinCommands.end());
- this->BuiltinCommands.insert(std::make_pair(name, command));
+ this->BuiltinCommands.emplace(name, std::move(command));
+}
+
+static bool InvokeBuiltinCommand(cmState::BuiltinCommand command,
+ std::vector<cmListFileArgument> const& args,
+ cmExecutionStatus& status)
+{
+ cmMakefile& mf = status.GetMakefile();
+ std::vector<std::string> expandedArguments;
+ if (!mf.ExpandArguments(args, expandedArguments)) {
+ // There was an error expanding arguments. It was already
+ // reported, so we can skip this command without error.
+ return true;
+ }
+ return command(expandedArguments, status);
+}
+
+void cmState::AddBuiltinCommand(std::string const& name,
+ BuiltinCommand command)
+{
+ this->AddBuiltinCommand(
+ name,
+ [command](const std::vector<cmListFileArgument>& args,
+ cmExecutionStatus& status) -> bool {
+ return InvokeBuiltinCommand(command, args, status);
+ });
}
-void cmState::AddDisallowedCommand(std::string const& name, cmCommand* command,
+void cmState::AddDisallowedCommand(std::string const& name,
+ BuiltinCommand command,
cmPolicies::PolicyID policy,
const char* message)
{
- this->AddBuiltinCommand(name,
- new cmDisallowedCommand(command, policy, message));
+ this->AddBuiltinCommand(
+ name,
+ [command, policy, message](const std::vector<cmListFileArgument>& args,
+ cmExecutionStatus& status) -> bool {
+ cmMakefile& mf = status.GetMakefile();
+ switch (mf.GetPolicyStatus(policy)) {
+ case cmPolicies::WARN:
+ mf.IssueMessage(MessageType::AUTHOR_WARNING,
+ cmPolicies::GetPolicyWarning(policy));
+ break;
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ mf.IssueMessage(MessageType::FATAL_ERROR, message);
+ return true;
+ }
+ return InvokeBuiltinCommand(command, args, status);
+ });
}
void cmState::AddUnexpectedCommand(std::string const& name, const char* error)
{
- this->AddBuiltinCommand(name, new cmUnexpectedCommand(name, error));
+ this->AddBuiltinCommand(
+ name,
+ [name, error](std::vector<cmListFileArgument> const&,
+ cmExecutionStatus& status) -> bool {
+ const char* versionValue =
+ status.GetMakefile().GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
+ if (name == "endif" && (!versionValue || atof(versionValue) <= 1.4)) {
+ return true;
+ }
+ status.SetError(error);
+ return false;
+ });
}
-void cmState::AddScriptedCommand(std::string const& name, cmCommand* command)
+void cmState::AddScriptedCommand(std::string const& name, Command command)
{
std::string sName = cmSystemTools::LowerCase(name);
// if the command already exists, give a new name to the old command.
- if (cmCommand* oldCmd = this->GetCommand(sName)) {
- std::string const newName = "_" + sName;
- std::map<std::string, cmCommand*>::iterator pos =
- this->ScriptedCommands.find(newName);
- if (pos != this->ScriptedCommands.end()) {
- delete pos->second;
- this->ScriptedCommands.erase(pos);
- }
- this->ScriptedCommands.insert(std::make_pair(newName, oldCmd->Clone()));
+ if (Command oldCmd = this->GetCommandByExactName(sName)) {
+ this->ScriptedCommands["_" + sName] = oldCmd;
}
- // if the command already exists, free the old one
- std::map<std::string, cmCommand*>::iterator pos =
- this->ScriptedCommands.find(sName);
- if (pos != this->ScriptedCommands.end()) {
- delete pos->second;
- this->ScriptedCommands.erase(pos);
- }
- this->ScriptedCommands.insert(std::make_pair(sName, command));
+ this->ScriptedCommands[sName] = std::move(command);
}
-cmCommand* cmState::GetCommand(std::string const& name) const
+cmState::Command cmState::GetCommand(std::string const& name) const
{
- std::string sName = cmSystemTools::LowerCase(name);
- std::map<std::string, cmCommand*>::const_iterator pos;
- pos = this->ScriptedCommands.find(sName);
+ return GetCommandByExactName(cmSystemTools::LowerCase(name));
+}
+
+cmState::Command cmState::GetCommandByExactName(std::string const& name) const
+{
+ auto pos = this->ScriptedCommands.find(name);
if (pos != this->ScriptedCommands.end()) {
return pos->second;
}
- pos = this->BuiltinCommands.find(sName);
+ pos = this->BuiltinCommands.find(name);
if (pos != this->BuiltinCommands.end()) {
return pos->second;
}
- return CM_NULLPTR;
+ return nullptr;
}
std::vector<std::string> cmState::GetCommandNames() const
@@ -444,15 +534,11 @@ std::vector<std::string> cmState::GetCommandNames() const
std::vector<std::string> commandNames;
commandNames.reserve(this->BuiltinCommands.size() +
this->ScriptedCommands.size());
- for (std::map<std::string, cmCommand*>::const_iterator cmds =
- this->BuiltinCommands.begin();
- cmds != this->BuiltinCommands.end(); ++cmds) {
- commandNames.push_back(cmds->first);
+ for (auto const& bc : this->BuiltinCommands) {
+ commandNames.push_back(bc.first);
}
- for (std::map<std::string, cmCommand*>::const_iterator cmds =
- this->ScriptedCommands.begin();
- cmds != this->ScriptedCommands.end(); ++cmds) {
- commandNames.push_back(cmds->first);
+ for (auto const& sc : this->ScriptedCommands) {
+ commandNames.push_back(sc.first);
}
std::sort(commandNames.begin(), commandNames.end());
commandNames.erase(std::unique(commandNames.begin(), commandNames.end()),
@@ -460,9 +546,14 @@ std::vector<std::string> cmState::GetCommandNames() const
return commandNames;
}
+void cmState::RemoveBuiltinCommand(std::string const& name)
+{
+ assert(name == cmSystemTools::LowerCase(name));
+ this->BuiltinCommands.erase(name);
+}
+
void cmState::RemoveUserDefinedCommands()
{
- cmDeleteAll(this->ScriptedCommands);
this->ScriptedCommands.clear();
}
@@ -495,21 +586,43 @@ const char* cmState::GetGlobalProperty(const std::string& prop)
std::string langs;
langs = cmJoin(this->EnabledLanguages, ";");
this->SetGlobalProperty("ENABLED_LANGUAGES", langs.c_str());
+ } else if (prop == "CMAKE_ROLE") {
+ std::string mode = this->GetModeString();
+ this->SetGlobalProperty("CMAKE_ROLE", mode.c_str());
}
#define STRING_LIST_ELEMENT(F) ";" #F
if (prop == "CMAKE_C_KNOWN_FEATURES") {
- return FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT) + 1;
+ return &FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT)[1];
+ }
+ if (prop == "CMAKE_C90_KNOWN_FEATURES") {
+ return &FOR_EACH_C90_FEATURE(STRING_LIST_ELEMENT)[1];
+ }
+ if (prop == "CMAKE_C99_KNOWN_FEATURES") {
+ return &FOR_EACH_C99_FEATURE(STRING_LIST_ELEMENT)[1];
+ }
+ if (prop == "CMAKE_C11_KNOWN_FEATURES") {
+ return &FOR_EACH_C11_FEATURE(STRING_LIST_ELEMENT)[1];
}
if (prop == "CMAKE_CXX_KNOWN_FEATURES") {
- return FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT) + 1;
+ return &FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT)[1];
+ }
+ if (prop == "CMAKE_CXX98_KNOWN_FEATURES") {
+ return &FOR_EACH_CXX98_FEATURE(STRING_LIST_ELEMENT)[1];
}
+ if (prop == "CMAKE_CXX11_KNOWN_FEATURES") {
+ return &FOR_EACH_CXX11_FEATURE(STRING_LIST_ELEMENT)[1];
+ }
+ if (prop == "CMAKE_CXX14_KNOWN_FEATURES") {
+ return &FOR_EACH_CXX14_FEATURE(STRING_LIST_ELEMENT)[1];
+ }
+
#undef STRING_LIST_ELEMENT
return this->GlobalProperties.GetPropertyValue(prop);
}
bool cmState::GetGlobalPropertyAsBool(const std::string& prop)
{
- return cmSystemTools::IsOn(this->GetGlobalProperty(prop));
+ return cmIsOn(this->GetGlobalProperty(prop));
}
void cmState::SetSourceDirectory(std::string const& sourceDirectory)
@@ -518,9 +631,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)
@@ -549,6 +662,16 @@ bool cmState::UseWindowsVSIDE() const
return this->WindowsVSIDE;
}
+void cmState::SetGhsMultiIDE(bool ghsMultiIDE)
+{
+ this->GhsMultiIDE = ghsMultiIDE;
+}
+
+bool cmState::UseGhsMultiIDE() const
+{
+ return this->GhsMultiIDE;
+}
+
void cmState::SetWatcomWMake(bool watcomWMake)
{
this->WatcomWMake = watcomWMake;
@@ -599,9 +722,43 @@ unsigned int cmState::GetCacheMinorVersion() const
return this->CacheManager->GetCacheMinorVersion();
}
-const char* cmState::GetBinaryDirectory() const
+cmState::Mode cmState::GetMode() const
+{
+ return this->CurrentMode;
+}
+
+std::string cmState::GetModeString() const
+{
+ return ModeToString(this->CurrentMode);
+}
+
+void cmState::SetMode(cmState::Mode mode)
+{
+ this->CurrentMode = mode;
+}
+
+std::string cmState::ModeToString(cmState::Mode mode)
+{
+ switch (mode) {
+ case Project:
+ return "PROJECT";
+ case Script:
+ return "SCRIPT";
+ case FindPackage:
+ return "FIND_PACKAGE";
+ case CTest:
+ return "CTEST";
+ case CPack:
+ return "CPACK";
+ case Unknown:
+ return "UNKNOWN";
+ }
+ return "UNKNOWN";
+}
+
+std::string const& cmState::GetBinaryDirectory() const
{
- return this->BinaryDirectory.c_str();
+ return this->BinaryDirectory;
}
cmStateSnapshot cmState::CreateBaseSnapshot()
@@ -619,6 +776,8 @@ cmStateSnapshot cmState::CreateBaseSnapshot()
pos->IncludeDirectoryPosition = 0;
pos->CompileDefinitionsPosition = 0;
pos->CompileOptionsPosition = 0;
+ pos->LinkOptionsPosition = 0;
+ pos->LinkDirectoriesPosition = 0;
pos->BuildSystemDirectory->DirectoryEnd = pos;
pos->Policies = this->PolicyStack.Root();
pos->PolicyRoot = this->PolicyStack.Root();
@@ -629,7 +788,7 @@ cmStateSnapshot cmState::CreateBaseSnapshot()
assert(pos->Vars.IsValid());
pos->Parent = this->VarTree.Root();
pos->Root = this->VarTree.Root();
- return cmStateSnapshot(this, pos);
+ return { this, pos };
}
cmStateSnapshot cmState::CreateBuildsystemDirectorySnapshot(
@@ -682,7 +841,7 @@ cmStateSnapshot cmState::CreateFunctionCallSnapshot(
cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
pos->Parent = origin;
pos->Vars = this->VarTree.Push(origin);
- return cmStateSnapshot(this, pos);
+ return { this, pos };
}
cmStateSnapshot cmState::CreateMacroCallSnapshot(
@@ -697,7 +856,7 @@ cmStateSnapshot cmState::CreateMacroCallSnapshot(
assert(originSnapshot.Position->Vars.IsValid());
pos->BuildSystemDirectory->DirectoryEnd = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
- return cmStateSnapshot(this, pos);
+ return { this, pos };
}
cmStateSnapshot cmState::CreateIncludeFileSnapshot(
@@ -712,7 +871,7 @@ cmStateSnapshot cmState::CreateIncludeFileSnapshot(
assert(originSnapshot.Position->Vars.IsValid());
pos->BuildSystemDirectory->DirectoryEnd = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
- return cmStateSnapshot(this, pos);
+ return { this, pos };
}
cmStateSnapshot cmState::CreateVariableScopeSnapshot(
@@ -730,7 +889,7 @@ cmStateSnapshot cmState::CreateVariableScopeSnapshot(
pos->Parent = origin;
pos->Vars = this->VarTree.Push(origin);
assert(pos->Vars.IsValid());
- return cmStateSnapshot(this, pos);
+ return { this, pos };
}
cmStateSnapshot cmState::CreateInlineListFileSnapshot(
@@ -744,7 +903,7 @@ cmStateSnapshot cmState::CreateInlineListFileSnapshot(
originSnapshot.Position->ExecutionListFile, fileName);
pos->BuildSystemDirectory->DirectoryEnd = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
- return cmStateSnapshot(this, pos);
+ return { this, pos };
}
cmStateSnapshot cmState::CreatePolicyScopeSnapshot(
@@ -756,7 +915,7 @@ cmStateSnapshot cmState::CreatePolicyScopeSnapshot(
pos->Keep = false;
pos->BuildSystemDirectory->DirectoryEnd = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
- return cmStateSnapshot(this, pos);
+ return { this, pos };
}
cmStateSnapshot cmState::Pop(cmStateSnapshot const& originSnapshot)
@@ -770,6 +929,10 @@ cmStateSnapshot cmState::Pop(cmStateSnapshot const& originSnapshot)
prevPos->BuildSystemDirectory->CompileDefinitions.size();
prevPos->CompileOptionsPosition =
prevPos->BuildSystemDirectory->CompileOptions.size();
+ prevPos->LinkOptionsPosition =
+ prevPos->BuildSystemDirectory->LinkOptions.size();
+ prevPos->LinkDirectoriesPosition =
+ prevPos->BuildSystemDirectory->LinkDirectories.size();
prevPos->BuildSystemDirectory->DirectoryEnd = prevPos;
if (!pos->Keep && this->SnapshotData.IsLast(pos)) {
@@ -784,7 +947,7 @@ cmStateSnapshot cmState::Pop(cmStateSnapshot const& originSnapshot)
this->SnapshotData.Pop(pos);
}
- return cmStateSnapshot(this, prevPos);
+ return { this, prevPos };
}
static bool ParseEntryWithoutType(const std::string& entry, std::string& var,
@@ -809,8 +972,8 @@ static bool ParseEntryWithoutType(const std::string& entry, std::string& var,
// if value is enclosed in single quotes ('foo') then remove them
// it is used to enclose trailing space or tab
- if (flag && value.size() >= 2 && value[0] == '\'' &&
- value[value.size() - 1] == '\'') {
+ if (flag && value.size() >= 2 && value.front() == '\'' &&
+ value.back() == '\'') {
value = value.substr(1, value.size() - 2);
}
@@ -842,8 +1005,8 @@ bool cmState::ParseCacheEntry(const std::string& entry, std::string& var,
// if value is enclosed in single quotes ('foo') then remove them
// it is used to enclose trailing space or tab
- if (flag && value.size() >= 2 && value[0] == '\'' &&
- value[value.size() - 1] == '\'') {
+ if (flag && value.size() >= 2 && value.front() == '\'' &&
+ value.back() == '\'') {
value = value.substr(1, value.size() - 2);
}
diff --git a/Source/cmState.h b/Source/cmState.h
index e03ad8981..a7ca015c1 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -5,13 +5,16 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <functional>
#include <map>
+#include <memory>
#include <set>
#include <string>
#include <vector>
#include "cmDefinitions.h"
#include "cmLinkedTree.h"
+#include "cmListFileCache.h"
#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmPropertyDefinitionMap.h"
@@ -21,8 +24,11 @@
class cmCacheManager;
class cmCommand;
+class cmGlobVerificationManager;
class cmPropertyDefinition;
class cmStateSnapshot;
+class cmMessenger;
+class cmExecutionStatus;
class cmState
{
@@ -32,6 +38,19 @@ public:
cmState();
~cmState();
+ cmState(const cmState&) = delete;
+ cmState& operator=(const cmState&) = delete;
+
+ enum Mode
+ {
+ Unknown,
+ Project,
+ Script,
+ FindPackage,
+ CTest,
+ CPack,
+ };
+
static const char* GetTargetTypeName(cmStateEnums::TargetType targetType);
cmStateSnapshot CreateBaseSnapshot();
@@ -52,6 +71,8 @@ public:
cmStateSnapshot Pop(cmStateSnapshot const& originSnapshot);
static cmStateEnums::CacheEntryType StringToCacheEntryType(const char*);
+ static bool StringToCacheEntryType(const char*,
+ cmStateEnums::CacheEntryType& type);
static const char* CacheEntryTypeToString(cmStateEnums::CacheEntryType);
static bool IsCacheEntryType(std::string const& key);
@@ -59,13 +80,13 @@ 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);
std::vector<std::string> GetCacheEntryKeys() const;
const char* GetCacheEntryValue(std::string const& key) const;
- const char* GetInitializedCacheValue(std::string const& key) const;
+ const std::string* GetInitializedCacheValue(std::string const& key) const;
cmStateEnums::CacheEntryType GetCacheEntryType(std::string const& key) const;
void SetCacheEntryValue(std::string const& key, std::string const& value);
void SetCacheValue(std::string const& key, std::string const& value);
@@ -89,7 +110,7 @@ public:
void RemoveCacheEntryProperty(std::string const& key,
std::string const& propertyName);
- ///! Break up a line like VAR:type="value" into var, type and value
+ //! Break up a line like VAR:type="value" into var, type and value
static bool ParseCacheEntry(const std::string& entry, std::string& var,
std::string& value,
cmStateEnums::CacheEntryType& type);
@@ -122,12 +143,25 @@ public:
bool GetIsGeneratorMultiConfig() const;
void SetIsGeneratorMultiConfig(bool b);
- cmCommand* GetCommand(std::string const& name) const;
- void AddBuiltinCommand(std::string const& name, cmCommand* command);
- void AddDisallowedCommand(std::string const& name, cmCommand* command,
+ using Command = std::function<bool(std::vector<cmListFileArgument> const&,
+ cmExecutionStatus&)>;
+ using BuiltinCommand = bool (*)(std::vector<std::string> const&,
+ cmExecutionStatus&);
+
+ // Returns a command from its name, case insensitive, or nullptr
+ Command GetCommand(std::string const& name) const;
+ // Returns a command from its name, or nullptr
+ Command GetCommandByExactName(std::string const& name) const;
+
+ void AddBuiltinCommand(std::string const& name,
+ std::unique_ptr<cmCommand> command);
+ void AddBuiltinCommand(std::string const& name, Command command);
+ void AddBuiltinCommand(std::string const& name, BuiltinCommand command);
+ void AddDisallowedCommand(std::string const& name, BuiltinCommand command,
cmPolicies::PolicyID policy, const char* message);
void AddUnexpectedCommand(std::string const& name, const char* error);
- void AddScriptedCommand(std::string const& name, cmCommand* command);
+ void AddScriptedCommand(std::string const& name, Command command);
+ void RemoveBuiltinCommand(std::string const& name);
void RemoveUserDefinedCommands();
std::vector<std::string> GetCommandNames() const;
@@ -137,15 +171,17 @@ 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);
bool UseWindowsShell() const;
void SetWindowsVSIDE(bool windowsVSIDE);
bool UseWindowsVSIDE() const;
+ void SetGhsMultiIDE(bool ghsMultiIDE);
+ bool UseGhsMultiIDE() const;
void SetWatcomWMake(bool watcomWMake);
bool UseWatcomWMake() const;
void SetMinGWMake(bool minGWMake);
@@ -158,18 +194,36 @@ public:
unsigned int GetCacheMajorVersion() const;
unsigned int GetCacheMinorVersion() const;
+ Mode GetMode() const;
+ std::string GetModeString() const;
+ void SetMode(Mode mode);
+
+ static std::string ModeToString(Mode mode);
+
private:
friend class cmake;
void AddCacheEntry(const std::string& key, const char* value,
const char* helpString,
cmStateEnums::CacheEntryType type);
+ bool DoWriteGlobVerifyTarget() const;
+ std::string const& GetGlobVerifyScript() const;
+ std::string const& GetGlobVerifyStamp() const;
+ bool SaveVerificationScript(const std::string& path);
+ void AddGlobCacheEntry(bool recurse, bool listDirectories,
+ bool followSymlinks, const std::string& relative,
+ const std::string& expression,
+ const std::vector<std::string>& files,
+ const std::string& variable,
+ cmListFileBacktrace const& bt);
+
std::map<cmProperty::ScopeType, cmPropertyDefinitionMap> PropertyDefinitions;
std::vector<std::string> EnabledLanguages;
- std::map<std::string, cmCommand*> BuiltinCommands;
- std::map<std::string, cmCommand*> ScriptedCommands;
+ std::map<std::string, Command> BuiltinCommands;
+ std::map<std::string, Command> ScriptedCommands;
cmPropertyMap GlobalProperties;
- cmCacheManager* CacheManager;
+ std::unique_ptr<cmCacheManager> CacheManager;
+ std::unique_ptr<cmGlobVerificationManager> GlobVerificationManager;
cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>
BuildsystemDirectory;
@@ -182,14 +236,16 @@ private:
std::string SourceDirectory;
std::string BinaryDirectory;
- bool IsInTryCompile;
- bool IsGeneratorMultiConfig;
- bool WindowsShell;
- bool WindowsVSIDE;
- bool WatcomWMake;
- bool MinGWMake;
- bool NMake;
- bool MSYSShell;
+ bool IsInTryCompile = false;
+ bool IsGeneratorMultiConfig = false;
+ bool WindowsShell = false;
+ bool WindowsVSIDE = false;
+ bool GhsMultiIDE = false;
+ bool WatcomWMake = false;
+ bool MinGWMake = false;
+ bool NMake = false;
+ bool MSYSShell = false;
+ Mode CurrentMode = Unknown;
};
#endif
diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx
index 46a185848..1262f53d9 100644
--- a/Source/cmStateDirectory.cxx
+++ b/Source/cmStateDirectory.cxx
@@ -4,13 +4,15 @@
#include "cmStateDirectory.h"
#include <algorithm>
-#include <assert.h>
-#include <iterator>
-#include <map>
-#include <utility>
+#include <cassert>
+#include <vector>
+#include <cm/iterator>
+
+#include "cmAlgorithms.h"
#include "cmProperty.h"
#include "cmPropertyMap.h"
+#include "cmRange.h"
#include "cmState.h"
#include "cmStatePrivate.h"
#include "cmStateTypes.h"
@@ -41,9 +43,8 @@ void cmStateDirectory::ComputeRelativePathTopSource()
std::string result = snapshots.front().GetDirectory().GetCurrentSource();
- for (std::vector<cmStateSnapshot>::const_iterator it = snapshots.begin() + 1;
- it != snapshots.end(); ++it) {
- std::string currentSource = it->GetDirectory().GetCurrentSource();
+ for (cmStateSnapshot const& snp : cmMakeRange(snapshots).advance(1)) {
+ std::string currentSource = snp.GetDirectory().GetCurrentSource();
if (cmSystemTools::IsSubDirectory(result, currentSource)) {
result = currentSource;
}
@@ -67,9 +68,8 @@ void cmStateDirectory::ComputeRelativePathTopBinary()
std::string result = snapshots.front().GetDirectory().GetCurrentBinary();
- for (std::vector<cmStateSnapshot>::const_iterator it = snapshots.begin() + 1;
- it != snapshots.end(); ++it) {
- std::string currentBinary = it->GetDirectory().GetCurrentBinary();
+ for (cmStateSnapshot const& snp : cmMakeRange(snapshots).advance(1)) {
+ std::string currentBinary = snp.GetDirectory().GetCurrentBinary();
if (cmSystemTools::IsSubDirectory(result, currentBinary)) {
result = currentBinary;
}
@@ -81,13 +81,13 @@ void cmStateDirectory::ComputeRelativePathTopBinary()
if (result.size() < 2 || result.substr(0, 2) != "//") {
this->DirectoryState->RelativePathTopBinary = result;
} else {
- this->DirectoryState->RelativePathTopBinary = "";
+ this->DirectoryState->RelativePathTopBinary.clear();
}
}
-const char* cmStateDirectory::GetCurrentSource() const
+std::string const& cmStateDirectory::GetCurrentSource() const
{
- return this->DirectoryState->Location.c_str();
+ return this->DirectoryState->Location;
}
void cmStateDirectory::SetCurrentSource(std::string const& dir)
@@ -102,9 +102,9 @@ void cmStateDirectory::SetCurrentSource(std::string const& dir)
this->Snapshot_.SetDefinition("CMAKE_CURRENT_SOURCE_DIR", loc);
}
-const char* cmStateDirectory::GetCurrentBinary() const
+std::string const& cmStateDirectory::GetCurrentBinary() const
{
- return this->DirectoryState->OutputLocation.c_str();
+ return this->DirectoryState->OutputLocation;
}
void cmStateDirectory::SetCurrentBinary(std::string const& dir)
@@ -119,14 +119,14 @@ void cmStateDirectory::SetCurrentBinary(std::string const& dir)
this->Snapshot_.SetDefinition("CMAKE_CURRENT_BINARY_DIR", loc);
}
-const char* cmStateDirectory::GetRelativePathTopSource() const
+std::string const& cmStateDirectory::GetRelativePathTopSource() const
{
- return this->DirectoryState->RelativePathTopSource.c_str();
+ return this->DirectoryState->RelativePathTopSource;
}
-const char* cmStateDirectory::GetRelativePathTopBinary() const
+std::string const& cmStateDirectory::GetRelativePathTopBinary() const
{
- return this->DirectoryState->RelativePathTopBinary.c_str();
+ return this->DirectoryState->RelativePathTopBinary;
}
void cmStateDirectory::SetRelativePathTopSource(const char* dir)
@@ -139,6 +139,32 @@ void cmStateDirectory::SetRelativePathTopBinary(const char* dir)
this->DirectoryState->RelativePathTopBinary = dir;
}
+bool cmStateDirectory::ContainsBoth(std::string const& local_path,
+ std::string const& remote_path) const
+{
+ auto PathEqOrSubDir = [](std::string const& a, std::string const& b) {
+ return (cmSystemTools::ComparePath(a, b) ||
+ cmSystemTools::IsSubDirectory(a, b));
+ };
+
+ bool bothInBinary = PathEqOrSubDir(local_path, GetRelativePathTopBinary()) &&
+ PathEqOrSubDir(remote_path, GetRelativePathTopBinary());
+
+ bool bothInSource = PathEqOrSubDir(local_path, GetRelativePathTopSource()) &&
+ PathEqOrSubDir(remote_path, GetRelativePathTopSource());
+
+ return bothInBinary || bothInSource;
+}
+
+std::string cmStateDirectory::ConvertToRelPathIfNotContained(
+ std::string const& local_path, std::string const& remote_path) const
+{
+ if (!this->ContainsBoth(local_path, remote_path)) {
+ return remote_path;
+ }
+ return cmSystemTools::ForceToRelativePath(local_path, remote_path);
+}
+
cmStateDirectory::cmStateDirectory(
cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator iter,
const cmStateSnapshot& snapshot)
@@ -150,11 +176,9 @@ cmStateDirectory::cmStateDirectory(
template <typename T, typename U>
cmStringRange GetPropertyContent(T const& content, U contentEndPosition)
{
- std::vector<std::string>::const_iterator end =
- content.begin() + contentEndPosition;
+ auto end = content.begin() + contentEndPosition;
- std::vector<std::string>::const_reverse_iterator rbegin =
- cmMakeReverseIterator(end);
+ auto rbegin = cm::make_reverse_iterator(end);
rbegin = std::find(rbegin, content.rend(), cmPropertySentinal);
return cmMakeRange(rbegin.base(), end);
@@ -164,17 +188,14 @@ template <typename T, typename U, typename V>
cmBacktraceRange GetPropertyBacktraces(T const& content, U const& backtraces,
V contentEndPosition)
{
- std::vector<std::string>::const_iterator entryEnd =
- content.begin() + contentEndPosition;
+ auto entryEnd = content.begin() + contentEndPosition;
- std::vector<std::string>::const_reverse_iterator rbegin =
- cmMakeReverseIterator(entryEnd);
+ auto rbegin = cm::make_reverse_iterator(entryEnd);
rbegin = std::find(rbegin, content.rend(), cmPropertySentinal);
- std::vector<cmListFileBacktrace>::const_iterator it =
- backtraces.begin() + std::distance(content.begin(), rbegin.base());
+ auto it = backtraces.begin() + std::distance(content.begin(), rbegin.base());
- std::vector<cmListFileBacktrace>::const_iterator end = backtraces.end();
+ auto end = backtraces.end();
return cmMakeRange(it, end);
}
@@ -246,22 +267,17 @@ void cmStateDirectory::AppendIncludeDirectoriesEntry(
void cmStateDirectory::PrependIncludeDirectoriesEntry(
const std::string& vec, const cmListFileBacktrace& lfbt)
{
- std::vector<std::string>::iterator entryEnd =
- this->DirectoryState->IncludeDirectories.begin() +
+ auto entryEnd = this->DirectoryState->IncludeDirectories.begin() +
this->Snapshot_.Position->IncludeDirectoryPosition;
- std::vector<std::string>::reverse_iterator rend =
- this->DirectoryState->IncludeDirectories.rend();
- std::vector<std::string>::reverse_iterator rbegin =
- cmMakeReverseIterator(entryEnd);
+ auto rend = this->DirectoryState->IncludeDirectories.rend();
+ auto rbegin = cm::make_reverse_iterator(entryEnd);
rbegin = std::find(rbegin, rend, cmPropertySentinal);
- std::vector<std::string>::iterator entryIt = rbegin.base();
- std::vector<std::string>::iterator entryBegin =
- this->DirectoryState->IncludeDirectories.begin();
+ auto entryIt = rbegin.base();
+ auto entryBegin = this->DirectoryState->IncludeDirectories.begin();
- std::vector<cmListFileBacktrace>::iterator btIt =
- this->DirectoryState->IncludeDirectoryBacktraces.begin() +
+ auto btIt = this->DirectoryState->IncludeDirectoryBacktraces.begin() +
std::distance(entryBegin, entryIt);
this->DirectoryState->IncludeDirectories.insert(entryIt, vec);
@@ -361,6 +377,101 @@ void cmStateDirectory::ClearCompileOptions()
this->Snapshot_.Position->CompileOptionsPosition);
}
+cmStringRange cmStateDirectory::GetLinkOptionsEntries() const
+{
+ return GetPropertyContent(this->DirectoryState->LinkOptions,
+ this->Snapshot_.Position->LinkOptionsPosition);
+}
+
+cmBacktraceRange cmStateDirectory::GetLinkOptionsEntryBacktraces() const
+{
+ return GetPropertyBacktraces(this->DirectoryState->LinkOptions,
+ this->DirectoryState->LinkOptionsBacktraces,
+ this->Snapshot_.Position->LinkOptionsPosition);
+}
+
+void cmStateDirectory::AppendLinkOptionsEntry(const std::string& vec,
+ const cmListFileBacktrace& lfbt)
+{
+ AppendEntry(this->DirectoryState->LinkOptions,
+ this->DirectoryState->LinkOptionsBacktraces,
+ this->Snapshot_.Position->LinkOptionsPosition, vec, lfbt);
+}
+
+void cmStateDirectory::SetLinkOptions(const std::string& vec,
+ const cmListFileBacktrace& lfbt)
+{
+ SetContent(this->DirectoryState->LinkOptions,
+ this->DirectoryState->LinkOptionsBacktraces,
+ this->Snapshot_.Position->LinkOptionsPosition, vec, lfbt);
+}
+
+void cmStateDirectory::ClearLinkOptions()
+{
+ ClearContent(this->DirectoryState->LinkOptions,
+ this->DirectoryState->LinkOptionsBacktraces,
+ this->Snapshot_.Position->LinkOptionsPosition);
+}
+
+cmStringRange cmStateDirectory::GetLinkDirectoriesEntries() const
+{
+ return GetPropertyContent(this->DirectoryState->LinkDirectories,
+ this->Snapshot_.Position->LinkDirectoriesPosition);
+}
+
+cmBacktraceRange cmStateDirectory::GetLinkDirectoriesEntryBacktraces() const
+{
+ return GetPropertyBacktraces(
+ this->DirectoryState->LinkDirectories,
+ this->DirectoryState->LinkDirectoriesBacktraces,
+ this->Snapshot_.Position->LinkDirectoriesPosition);
+}
+
+void cmStateDirectory::AppendLinkDirectoriesEntry(
+ const std::string& vec, const cmListFileBacktrace& lfbt)
+{
+ AppendEntry(this->DirectoryState->LinkDirectories,
+ this->DirectoryState->LinkDirectoriesBacktraces,
+ this->Snapshot_.Position->LinkDirectoriesPosition, vec, lfbt);
+}
+void cmStateDirectory::PrependLinkDirectoriesEntry(
+ const std::string& vec, const cmListFileBacktrace& lfbt)
+{
+ auto entryEnd = this->DirectoryState->LinkDirectories.begin() +
+ this->Snapshot_.Position->LinkDirectoriesPosition;
+
+ auto rend = this->DirectoryState->LinkDirectories.rend();
+ auto rbegin = cm::make_reverse_iterator(entryEnd);
+ rbegin = std::find(rbegin, rend, cmPropertySentinal);
+
+ auto entryIt = rbegin.base();
+ auto entryBegin = this->DirectoryState->LinkDirectories.begin();
+
+ auto btIt = this->DirectoryState->LinkDirectoriesBacktraces.begin() +
+ std::distance(entryBegin, entryIt);
+
+ this->DirectoryState->LinkDirectories.insert(entryIt, vec);
+ this->DirectoryState->LinkDirectoriesBacktraces.insert(btIt, lfbt);
+
+ this->Snapshot_.Position->LinkDirectoriesPosition =
+ this->DirectoryState->LinkDirectories.size();
+}
+
+void cmStateDirectory::SetLinkDirectories(const std::string& vec,
+ const cmListFileBacktrace& lfbt)
+{
+ SetContent(this->DirectoryState->LinkDirectories,
+ this->DirectoryState->LinkDirectoriesBacktraces,
+ this->Snapshot_.Position->LinkDirectoriesPosition, vec, lfbt);
+}
+
+void cmStateDirectory::ClearLinkDirectories()
+{
+ ClearContent(this->DirectoryState->LinkDirectories,
+ this->DirectoryState->LinkDirectoriesBacktraces,
+ this->Snapshot_.Position->LinkDirectoriesPosition);
+}
+
void cmStateDirectory::SetProperty(const std::string& prop, const char* value,
cmListFileBacktrace const& lfbt)
{
@@ -388,6 +499,22 @@ void cmStateDirectory::SetProperty(const std::string& prop, const char* value,
this->SetCompileDefinitions(value, lfbt);
return;
}
+ if (prop == "LINK_OPTIONS") {
+ if (!value) {
+ this->ClearLinkOptions();
+ return;
+ }
+ this->SetLinkOptions(value, lfbt);
+ return;
+ }
+ if (prop == "LINK_DIRECTORIES") {
+ if (!value) {
+ this->ClearLinkDirectories();
+ return;
+ }
+ this->SetLinkDirectories(value, lfbt);
+ return;
+ }
this->DirectoryState->Properties.SetProperty(prop, value);
}
@@ -408,6 +535,14 @@ void cmStateDirectory::AppendProperty(const std::string& prop,
this->AppendCompileDefinitionsEntry(value, lfbt);
return;
}
+ if (prop == "LINK_OPTIONS") {
+ this->AppendLinkOptionsEntry(value, lfbt);
+ return;
+ }
+ if (prop == "LINK_DIRECTORIES") {
+ this->AppendLinkDirectoriesEntry(value, lfbt);
+ return;
+ }
this->DirectoryState->Properties.AppendProperty(prop, value, asString);
}
@@ -423,11 +558,11 @@ const char* cmStateDirectory::GetProperty(const std::string& prop,
bool chain) const
{
static std::string output;
- output = "";
+ output.clear();
if (prop == "PARENT_DIRECTORY") {
cmStateSnapshot parent = this->Snapshot_.GetBuildsystemDirectoryParent();
if (parent.IsValid()) {
- return parent.GetDirectory().GetCurrentSource();
+ return parent.GetDirectory().GetCurrentSource().c_str();
}
return "";
}
@@ -443,9 +578,9 @@ const char* cmStateDirectory::GetProperty(const std::string& prop,
std::vector<std::string> child_dirs;
std::vector<cmStateSnapshot> const& children =
this->DirectoryState->Children;
- for (std::vector<cmStateSnapshot>::const_iterator ci = children.begin();
- ci != children.end(); ++ci) {
- child_dirs.push_back(ci->GetDirectory().GetCurrentSource());
+ child_dirs.reserve(children.size());
+ for (cmStateSnapshot const& ci : children) {
+ child_dirs.push_back(ci.GetDirectory().GetCurrentSource());
}
output = cmJoin(child_dirs, ";");
return output.c_str();
@@ -472,9 +607,7 @@ const char* cmStateDirectory::GetProperty(const std::string& prop,
}
if (prop == "VARIABLES") {
std::vector<std::string> res = this->Snapshot_.ClosureKeys();
- std::vector<std::string> cacheKeys =
- this->Snapshot_.State->GetCacheEntryKeys();
- res.insert(res.end(), cacheKeys.begin(), cacheKeys.end());
+ cmAppend(res, this->Snapshot_.State->GetCacheEntryKeys());
std::sort(res.begin(), res.end());
output = cmJoin(res, ";");
return output.c_str();
@@ -491,6 +624,14 @@ const char* cmStateDirectory::GetProperty(const std::string& prop,
output = cmJoin(this->GetCompileDefinitionsEntries(), ";");
return output.c_str();
}
+ if (prop == "LINK_OPTIONS") {
+ output = cmJoin(this->GetLinkOptionsEntries(), ";");
+ return output.c_str();
+ }
+ if (prop == "LINK_DIRECTORIES") {
+ output = cmJoin(this->GetLinkDirectoriesEntries(), ";");
+ return output.c_str();
+ }
const char* retVal = this->DirectoryState->Properties.GetPropertyValue(prop);
if (!retVal && chain) {
@@ -507,19 +648,12 @@ const char* cmStateDirectory::GetProperty(const std::string& prop,
bool cmStateDirectory::GetPropertyAsBool(const std::string& prop) const
{
- return cmSystemTools::IsOn(this->GetProperty(prop));
+ return cmIsOn(this->GetProperty(prop));
}
std::vector<std::string> cmStateDirectory::GetPropertyKeys() const
{
- std::vector<std::string> keys;
- keys.reserve(this->DirectoryState->Properties.size());
- for (cmPropertyMap::const_iterator it =
- this->DirectoryState->Properties.begin();
- it != this->DirectoryState->Properties.end(); ++it) {
- keys.push_back(it->first);
- }
- return keys;
+ return this->DirectoryState->Properties.GetKeys();
}
void cmStateDirectory::AddNormalTargetName(std::string const& name)
diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h
index 79bb36943..fe15563cb 100644
--- a/Source/cmStateDirectory.h
+++ b/Source/cmStateDirectory.h
@@ -14,6 +14,7 @@
#include "cmListFileCache.h"
#include "cmStatePrivate.h"
#include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
class cmStateDirectory
{
@@ -22,16 +23,22 @@ class cmStateDirectory
cmStateSnapshot const& snapshot);
public:
- const char* GetCurrentSource() const;
+ std::string const& GetCurrentSource() const;
void SetCurrentSource(std::string const& dir);
- const char* GetCurrentBinary() const;
+ std::string const& GetCurrentBinary() const;
void SetCurrentBinary(std::string const& dir);
- const char* GetRelativePathTopSource() const;
- const char* GetRelativePathTopBinary() const;
+ std::string const& GetRelativePathTopSource() const;
+ std::string const& GetRelativePathTopBinary() const;
void SetRelativePathTopSource(const char* dir);
void SetRelativePathTopBinary(const char* dir);
+ bool ContainsBoth(std::string const& local_path,
+ std::string const& remote_path) const;
+
+ std::string ConvertToRelPathIfNotContained(
+ std::string const& local_path, std::string const& remote_path) const;
+
cmStringRange GetIncludeDirectoriesEntries() const;
cmBacktraceRange GetIncludeDirectoriesEntryBacktraces() const;
void AppendIncludeDirectoriesEntry(std::string const& vec,
@@ -58,6 +65,23 @@ public:
cmListFileBacktrace const& lfbt);
void ClearCompileOptions();
+ cmStringRange GetLinkOptionsEntries() const;
+ cmBacktraceRange GetLinkOptionsEntryBacktraces() const;
+ void AppendLinkOptionsEntry(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
+ void PrependLinkDirectoriesEntry(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
+ void SetLinkOptions(std::string const& vec, cmListFileBacktrace const& lfbt);
+ void ClearLinkOptions();
+
+ cmStringRange GetLinkDirectoriesEntries() const;
+ cmBacktraceRange GetLinkDirectoriesEntryBacktraces() const;
+ void AppendLinkDirectoriesEntry(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
+ void SetLinkDirectories(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
+ void ClearLinkDirectories();
+
void SetProperty(const std::string& prop, const char* value,
cmListFileBacktrace const& lfbt);
void AppendProperty(const std::string& prop, const char* value,
diff --git a/Source/cmStatePrivate.h b/Source/cmStatePrivate.h
index f36ee37ea..4efaf97eb 100644
--- a/Source/cmStatePrivate.h
+++ b/Source/cmStatePrivate.h
@@ -42,14 +42,15 @@ struct cmStateDetail::SnapshotDataType
std::vector<std::string>::size_type IncludeDirectoryPosition;
std::vector<std::string>::size_type CompileDefinitionsPosition;
std::vector<std::string>::size_type CompileOptionsPosition;
+ std::vector<std::string>::size_type LinkOptionsPosition;
+ std::vector<std::string>::size_type LinkDirectoriesPosition;
};
struct cmStateDetail::PolicyStackEntry : public cmPolicies::PolicyMap
{
- typedef cmPolicies::PolicyMap derived;
+ using derived = cmPolicies::PolicyMap;
PolicyStackEntry(bool w = false)
- : derived()
- , Weak(w)
+ : Weak(w)
{
}
PolicyStackEntry(derived const& d, bool w)
@@ -84,6 +85,12 @@ struct cmStateDetail::BuildsystemDirectoryStateType
std::vector<std::string> CompileOptions;
std::vector<cmListFileBacktrace> CompileOptionsBacktraces;
+ std::vector<std::string> LinkOptions;
+ std::vector<cmListFileBacktrace> LinkOptionsBacktraces;
+
+ std::vector<std::string> LinkDirectories;
+ std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces;
+
std::vector<std::string> NormalTargetNames;
std::string ProjectName;
diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx
index 77413c7b5..645907c21 100644
--- a/Source/cmStateSnapshot.cxx
+++ b/Source/cmStateSnapshot.cxx
@@ -4,11 +4,11 @@
#include "cmStateSnapshot.h"
#include <algorithm>
-#include <assert.h>
-#include <iterator>
-#include <stdio.h>
+#include <cassert>
+#include <string>
+
+#include <cm/iterator>
-#include "cmAlgorithms.h"
#include "cmDefinitions.h"
#include "cmListFileCache.h"
#include "cmPropertyMap.h"
@@ -16,19 +16,17 @@
#include "cmStateDirectory.h"
#include "cmStatePrivate.h"
#include "cmVersion.h"
-#include "cmake.h"
#if !defined(_WIN32)
-#include <sys/utsname.h>
+# include <sys/utsname.h>
#endif
#if defined(__CYGWIN__)
-#include "cmSystemTools.h"
+# include "cmSystemTools.h"
#endif
cmStateSnapshot::cmStateSnapshot(cmState* state)
: State(state)
- , Position()
{
}
@@ -66,6 +64,11 @@ bool cmStateSnapshot::IsValid() const
: false;
}
+cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectory() const
+{
+ return { this->State, this->Position->BuildSystemDirectory->DirectoryEnd };
+}
+
cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectoryParent() const
{
cmStateSnapshot snapshot;
@@ -122,7 +125,7 @@ cmStateSnapshot cmStateSnapshot::GetCallStackBottom() const
pos != this->State->SnapshotData.Root()) {
++pos;
}
- return cmStateSnapshot(this->State, pos);
+ return { this->State, pos };
}
void cmStateSnapshot::PushPolicy(cmPolicies::PolicyMap const& entry, bool weak)
@@ -160,8 +163,8 @@ void cmStateSnapshot::SetPolicy(cmPolicies::PolicyID id,
}
}
-cmPolicies::PolicyStatus cmStateSnapshot::GetPolicy(
- cmPolicies::PolicyID id) const
+cmPolicies::PolicyStatus cmStateSnapshot::GetPolicy(cmPolicies::PolicyID id,
+ bool parent_scope) const
{
cmPolicies::PolicyStatus status = cmPolicies::GetPolicyStatus(id);
@@ -180,6 +183,10 @@ cmPolicies::PolicyStatus cmStateSnapshot::GetPolicy(
cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator root =
dir->DirectoryEnd->PolicyRoot;
for (; leaf != root; ++leaf) {
+ if (parent_scope) {
+ parent_scope = false;
+ continue;
+ }
if (leaf->IsDefined(id)) {
status = leaf->Get(id);
return status;
@@ -200,7 +207,8 @@ bool cmStateSnapshot::HasDefinedPolicyCMP0011()
return !this->Position->Policies->IsEmpty();
}
-const char* cmStateSnapshot::GetDefinition(std::string const& name) const
+std::string const* cmStateSnapshot::GetDefinition(
+ std::string const& name) const
{
assert(this->Position->Vars.IsValid());
return cmDefinitions::Get(name, this->Position->Vars, this->Position->Root);
@@ -213,14 +221,14 @@ bool cmStateSnapshot::IsInitialized(std::string const& name) const
}
void cmStateSnapshot::SetDefinition(std::string const& name,
- std::string const& value)
+ cm::string_view value)
{
- this->Position->Vars->Set(name, value.c_str());
+ this->Position->Vars->Set(name, value);
}
void cmStateSnapshot::RemoveDefinition(std::string const& name)
{
- this->Position->Vars->Set(name, CM_NULLPTR);
+ this->Position->Vars->Unset(name);
}
std::vector<std::string> cmStateSnapshot::UnusedKeys() const
@@ -255,7 +263,11 @@ bool cmStateSnapshot::RaiseScope(std::string const& var, const char* varDef)
cmDefinitions::Raise(var, this->Position->Vars, this->Position->Root);
// Now update the definition in the parent scope.
- this->Position->Parent->Set(var, varDef);
+ if (varDef) {
+ this->Position->Parent->Set(var, varDef);
+ } else {
+ this->Position->Parent->Unset(var);
+ }
return true;
}
@@ -264,22 +276,18 @@ void InitializeContentFromParent(T& parentContent, T& thisContent,
U& parentBacktraces, U& thisBacktraces,
V& contentEndPosition)
{
- std::vector<std::string>::const_iterator parentBegin = parentContent.begin();
- std::vector<std::string>::const_iterator parentEnd = parentContent.end();
+ auto parentBegin = parentContent.begin();
+ auto parentEnd = parentContent.end();
- std::vector<std::string>::const_reverse_iterator parentRbegin =
- cmMakeReverseIterator(parentEnd);
- std::vector<std::string>::const_reverse_iterator parentRend =
- parentContent.rend();
+ auto parentRbegin = cm::make_reverse_iterator(parentEnd);
+ auto parentRend = parentContent.rend();
parentRbegin = std::find(parentRbegin, parentRend, cmPropertySentinal);
- std::vector<std::string>::const_iterator parentIt = parentRbegin.base();
+ auto parentIt = parentRbegin.base();
thisContent = std::vector<std::string>(parentIt, parentEnd);
- std::vector<cmListFileBacktrace>::const_iterator btIt =
- parentBacktraces.begin() + std::distance(parentBegin, parentIt);
- std::vector<cmListFileBacktrace>::const_iterator btEnd =
- parentBacktraces.end();
+ auto btIt = parentBacktraces.begin() + std::distance(parentBegin, parentIt);
+ auto btEnd = parentBacktraces.end();
thisBacktraces = std::vector<cmListFileBacktrace>(btIt, btEnd);
@@ -315,7 +323,7 @@ void cmStateSnapshot::SetDefaultDefinitions()
#if defined(__CYGWIN__)
std::string legacy;
if (cmSystemTools::GetEnv("CMAKE_LEGACY_CYGWIN_WIN32", legacy) &&
- cmSystemTools::IsOn(legacy.c_str())) {
+ cmIsOn(legacy.c_str())) {
this->SetDefinition("WIN32", "1");
this->SetDefinition("CMAKE_HOST_WIN32", "1");
}
@@ -328,19 +336,17 @@ void cmStateSnapshot::SetDefaultDefinitions()
this->SetDefinition("CMAKE_HOST_SOLARIS", "1");
#endif
- char temp[1024];
- sprintf(temp, "%d", cmVersion::GetMinorVersion());
- this->SetDefinition("CMAKE_MINOR_VERSION", temp);
- sprintf(temp, "%d", cmVersion::GetMajorVersion());
- this->SetDefinition("CMAKE_MAJOR_VERSION", temp);
- sprintf(temp, "%d", cmVersion::GetPatchVersion());
- this->SetDefinition("CMAKE_PATCH_VERSION", temp);
- sprintf(temp, "%d", cmVersion::GetTweakVersion());
- this->SetDefinition("CMAKE_TWEAK_VERSION", temp);
+ this->SetDefinition("CMAKE_MAJOR_VERSION",
+ std::to_string(cmVersion::GetMajorVersion()));
+ this->SetDefinition("CMAKE_MINOR_VERSION",
+ std::to_string(cmVersion::GetMinorVersion()));
+ this->SetDefinition("CMAKE_PATCH_VERSION",
+ std::to_string(cmVersion::GetPatchVersion()));
+ this->SetDefinition("CMAKE_TWEAK_VERSION",
+ std::to_string(cmVersion::GetTweakVersion()));
this->SetDefinition("CMAKE_VERSION", cmVersion::GetCMakeVersion());
- this->SetDefinition("CMAKE_FILES_DIRECTORY",
- cmake::GetCMakeFilesDirectory());
+ this->SetDefinition("CMAKE_FILES_DIRECTORY", "/CMakeFiles");
// Setup the default include file regular expression (match everything).
this->Position->BuildSystemDirectory->Properties.SetProperty(
@@ -386,6 +392,26 @@ void cmStateSnapshot::InitializeFromParent()
parent->BuildSystemDirectory->CompileOptionsBacktraces,
this->Position->BuildSystemDirectory->CompileOptionsBacktraces,
this->Position->CompileOptionsPosition);
+
+ InitializeContentFromParent(
+ parent->BuildSystemDirectory->LinkOptions,
+ this->Position->BuildSystemDirectory->LinkOptions,
+ parent->BuildSystemDirectory->LinkOptionsBacktraces,
+ this->Position->BuildSystemDirectory->LinkOptionsBacktraces,
+ this->Position->LinkOptionsPosition);
+
+ InitializeContentFromParent(
+ parent->BuildSystemDirectory->LinkDirectories,
+ this->Position->BuildSystemDirectory->LinkDirectories,
+ parent->BuildSystemDirectory->LinkDirectoriesBacktraces,
+ this->Position->BuildSystemDirectory->LinkDirectoriesBacktraces,
+ this->Position->LinkDirectoriesPosition);
+
+ 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
@@ -395,7 +421,7 @@ cmState* cmStateSnapshot::GetState() const
cmStateDirectory cmStateSnapshot::GetDirectory() const
{
- return cmStateDirectory(this->Position->BuildSystemDirectory, *this);
+ return { this->Position->BuildSystemDirectory, *this };
}
void cmStateSnapshot::SetProjectName(const std::string& name)
@@ -410,8 +436,8 @@ std::string cmStateSnapshot::GetProjectName() const
void cmStateSnapshot::InitializeFromParent_ForSubdirsCommand()
{
- std::string currentSrcDir = this->GetDefinition("CMAKE_CURRENT_SOURCE_DIR");
- std::string currentBinDir = this->GetDefinition("CMAKE_CURRENT_BINARY_DIR");
+ std::string currentSrcDir = *this->GetDefinition("CMAKE_CURRENT_SOURCE_DIR");
+ std::string currentBinDir = *this->GetDefinition("CMAKE_CURRENT_BINARY_DIR");
this->InitializeFromParent();
this->SetDefinition("CMAKE_SOURCE_DIR", this->State->GetSourceDirectory());
this->SetDefinition("CMAKE_BINARY_DIR", this->State->GetBinaryDirectory());
diff --git a/Source/cmStateSnapshot.h b/Source/cmStateSnapshot.h
index 6293803b9..021fd53c1 100644
--- a/Source/cmStateSnapshot.h
+++ b/Source/cmStateSnapshot.h
@@ -9,6 +9,8 @@
#include <string>
#include <vector>
+#include <cm/string_view>
+
#include "cmLinkedTree.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
@@ -19,12 +21,12 @@ class cmStateDirectory;
class cmStateSnapshot
{
public:
- cmStateSnapshot(cmState* state = CM_NULLPTR);
+ cmStateSnapshot(cmState* state = nullptr);
cmStateSnapshot(cmState* state, cmStateDetail::PositionType position);
- const char* GetDefinition(std::string const& name) const;
+ std::string const* GetDefinition(std::string const& name) const;
bool IsInitialized(std::string const& name) const;
- void SetDefinition(std::string const& name, std::string const& value);
+ void SetDefinition(std::string const& name, cm::string_view value);
void RemoveDefinition(std::string const& name);
std::vector<std::string> UnusedKeys() const;
std::vector<std::string> ClosureKeys() const;
@@ -37,13 +39,15 @@ public:
std::vector<cmStateSnapshot> GetChildren();
bool IsValid() const;
+ cmStateSnapshot GetBuildsystemDirectory() const;
cmStateSnapshot GetBuildsystemDirectoryParent() const;
cmStateSnapshot GetCallStackParent() const;
cmStateSnapshot GetCallStackBottom() const;
cmStateEnums::SnapshotType GetType() const;
void SetPolicy(cmPolicies::PolicyID id, cmPolicies::PolicyStatus status);
- cmPolicies::PolicyStatus GetPolicy(cmPolicies::PolicyID id) const;
+ cmPolicies::PolicyStatus GetPolicy(cmPolicies::PolicyID id,
+ bool parent_scope = false) const;
bool HasDefinedPolicyCMP0011();
void PushPolicy(cmPolicies::PolicyMap const& entry, bool weak);
bool PopPolicy();
diff --git a/Source/cmStateTypes.h b/Source/cmStateTypes.h
index 7d6158e33..d089ea73d 100644
--- a/Source/cmStateTypes.h
+++ b/Source/cmStateTypes.h
@@ -10,7 +10,7 @@
namespace cmStateDetail {
struct SnapshotDataType;
-typedef cmLinkedTree<cmStateDetail::SnapshotDataType>::iterator PositionType;
+using PositionType = cmLinkedTree<cmStateDetail::SnapshotDataType>::iterator;
}
namespace cmStateEnums {
diff --git a/Source/cmString.cxx b/Source/cmString.cxx
new file mode 100644
index 000000000..2a0c125e6
--- /dev/null
+++ b/Source/cmString.cxx
@@ -0,0 +1,152 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#define _SCL_SECURE_NO_WARNINGS
+
+#include "cmString.hxx"
+
+#include <memory>
+#include <ostream>
+#include <stdexcept>
+#include <string>
+#include <type_traits>
+
+namespace cm {
+
+static std::string const empty_string_;
+
+void String::internally_mutate_to_stable_string()
+{
+ // We assume that only one thread mutates this instance at
+ // a time even if we point to a shared string buffer refernced
+ // by other threads.
+ *this = String(data(), size());
+}
+
+bool String::is_stable() const
+{
+ return str_if_stable() != nullptr;
+}
+
+void String::stabilize()
+{
+ if (is_stable()) {
+ return;
+ }
+ this->internally_mutate_to_stable_string();
+}
+
+std::string const* String::str_if_stable() const
+{
+ if (!data()) {
+ // We view no string.
+ // This is stable for the lifetime of our current value.
+ return &empty_string_;
+ }
+
+ if (string_ && data() == string_->data() && size() == string_->size()) {
+ // We view an entire string.
+ // This is stable for the lifetime of our current value.
+ return string_.get();
+ }
+
+ return nullptr;
+}
+
+std::string const& String::str()
+{
+ if (std::string const* s = str_if_stable()) {
+ return *s;
+ }
+ // Mutate to hold a std::string that is stable for the lifetime
+ // of our current value.
+ this->internally_mutate_to_stable_string();
+ return *string_;
+}
+
+const char* String::c_str()
+{
+ const char* c = data();
+ if (c == nullptr) {
+ return c;
+ }
+
+ // We always point into a null-terminated string so it is safe to
+ // access one past the end. If it is a null byte then we can use
+ // the pointer directly.
+ if (c[size()] == '\0') {
+ return c;
+ }
+
+ // Mutate to hold a std::string so we can get a null terminator.
+ this->internally_mutate_to_stable_string();
+ c = string_->c_str();
+ return c;
+}
+
+String& String::insert(size_type index, size_type count, char ch)
+{
+ std::string s;
+ s.reserve(size() + count);
+ s.assign(data(), size());
+ s.insert(index, count, ch);
+ return *this = std::move(s);
+}
+
+String& String::erase(size_type index, size_type count)
+{
+ if (index > size()) {
+ throw std::out_of_range("Index out of range in String::erase");
+ }
+ size_type const rcount = std::min(count, size() - index);
+ size_type const rindex = index + rcount;
+ std::string s;
+ s.reserve(size() - rcount);
+ s.assign(data(), index);
+ s.append(data() + rindex, size() - rindex);
+ return *this = std::move(s);
+}
+
+String String::substr(size_type pos, size_type count) const
+{
+ if (pos > size()) {
+ throw std::out_of_range("Index out of range in String::substr");
+ }
+ return String(*this, pos, count);
+}
+
+String::String(std::string&& s, Private)
+ : string_(std::make_shared<std::string>(std::move(s)))
+ , view_(string_->data(), string_->size())
+{
+}
+
+String::size_type String::copy(char* dest, size_type count,
+ size_type pos) const
+{
+ return view_.copy(dest, count, pos);
+}
+
+std::ostream& operator<<(std::ostream& os, String const& s)
+{
+ return os.write(s.data(), s.size());
+}
+
+std::string& operator+=(std::string& self, String const& s)
+{
+ return self += s.view();
+}
+
+String IntoString<char*>::into_string(const char* s)
+{
+ if (!s) {
+ return String();
+ }
+ return std::string(s);
+}
+
+string_view AsStringView<String>::view(String const& s)
+{
+ return s.view();
+}
+
+} // namespace cm
diff --git a/Source/cmString.hxx b/Source/cmString.hxx
new file mode 100644
index 000000000..073f4c940
--- /dev/null
+++ b/Source/cmString.hxx
@@ -0,0 +1,817 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmString_hxx
+#define cmString_hxx
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <algorithm>
+#include <cstddef>
+#include <functional>
+#include <initializer_list>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include <cm/string_view>
+
+#include "cm_static_string_view.hxx"
+
+namespace cm {
+
+class String;
+
+/**
+ * Trait to convert type T into a String.
+ * Implementations must derive from 'std::true_type'
+ * and define an 'into_string' member that accepts
+ * type T (by value or reference) and returns one of:
+ *
+ * - 'std::string' to construct an owned instance.
+ * - 'cm::string_view' to construct a borrowed or null instances.
+ * The buffer from which the view is borrowed must outlive
+ * all copies of the resulting String, e.g. static storage.
+ * - 'cm::String' for already-constructed instances.
+ */
+template <typename T>
+struct IntoString : std::false_type
+{
+};
+
+template <typename T>
+struct IntoString<T&> : IntoString<T>
+{
+};
+
+template <typename T>
+struct IntoString<T const> : IntoString<T>
+{
+};
+
+template <typename T>
+struct IntoString<T const*> : IntoString<T*>
+{
+};
+
+template <typename T, std::string::size_type N>
+struct IntoString<T const[N]> : IntoString<T[N]>
+{
+};
+
+template <>
+struct IntoString<char*> : std::true_type
+{
+ static String into_string(const char* s);
+};
+
+template <>
+struct IntoString<std::nullptr_t> : std::true_type
+{
+ static string_view into_string(std::nullptr_t) { return string_view(); }
+};
+
+template <std::string::size_type N>
+struct IntoString<char[N]> : std::true_type
+{
+ static std::string into_string(char const (&s)[N])
+ {
+ return std::string(s, N - 1);
+ }
+};
+
+template <>
+struct IntoString<std::string> : std::true_type
+{
+ static std::string into_string(std::string s) { return s; }
+};
+
+template <>
+struct IntoString<string_view> : std::true_type
+{
+ static std::string into_string(string_view s) { return std::string(s); }
+};
+
+template <>
+struct IntoString<static_string_view> : std::true_type
+{
+ static string_view into_string(static_string_view s) { return s; }
+};
+
+template <>
+struct IntoString<char> : std::true_type
+{
+ static std::string into_string(char const& c) { return std::string(1, c); }
+};
+
+/**
+ * Trait to convert type T into a 'cm::string_view'.
+ * Implementations must derive from 'std::true_type' and
+ * define a 'view' member that accepts type T (by reference)
+ * and returns a 'cm::string_view'.
+ */
+template <typename T>
+struct AsStringView : std::false_type
+{
+};
+
+template <typename T>
+struct AsStringView<T&> : AsStringView<T>
+{
+};
+
+template <typename T>
+struct AsStringView<T const> : AsStringView<T>
+{
+};
+
+template <typename T>
+struct AsStringView<T const*> : AsStringView<T*>
+{
+};
+
+template <typename T, std::string::size_type N>
+struct AsStringView<T const[N]> : AsStringView<T[N]>
+{
+};
+
+template <>
+struct AsStringView<char*> : std::true_type
+{
+ static string_view view(const char* s) { return s; }
+};
+
+template <std::string::size_type N>
+struct AsStringView<char[N]> : std::true_type
+{
+ static string_view view(char const (&s)[N]) { return string_view(s, N - 1); }
+};
+
+template <>
+struct AsStringView<std::string> : std::true_type
+{
+ static string_view view(std::string const& s) { return s; }
+};
+
+template <>
+struct AsStringView<char> : std::true_type
+{
+ static string_view view(const char& s) { return string_view(&s, 1); }
+};
+
+template <>
+struct AsStringView<string_view> : std::true_type
+{
+ static string_view view(string_view const& s) { return s; }
+};
+
+template <>
+struct AsStringView<static_string_view> : std::true_type
+{
+ static string_view view(static_string_view const& s) { return s; }
+};
+
+template <>
+struct AsStringView<String> : std::true_type
+{
+ static string_view view(String const& s);
+};
+
+/**
+ * \class String
+ *
+ * A custom string type that holds a view of a string buffer
+ * and optionally shares ownership of the buffer. Instances
+ * may have one of the following states:
+ *
+ * - null: views and owns nothing.
+ * Conversion to 'bool' is 'false'.
+ * 'data()' and 'c_str()' return nullptr.
+ * 'size()' returns 0.
+ * 'str()' returns an empty string.
+ *
+ * - borrowed: views a string but does not own it. This is used
+ * to bind to static storage (e.g. string literals) or for
+ * temporary instances that do not outlive the borrowed buffer.
+ * Copies and substrings still borrow the original buffer.
+ * Mutation allocates a new internal string and converts to
+ * the 'owned' state.
+ * Conversion to 'bool' is 'true'.
+ * 'c_str()' may internally mutate to the 'owned' state.
+ * 'str()' internally mutates to the 'owned' state.
+ *
+ * - owned: views an immutable 'std::string' instance owned internally.
+ * Copies and substrings share ownership of the internal string.
+ * Mutation allocates a new internal string.
+ * Conversion to 'bool' is 'true'.
+ */
+class String
+{
+ enum class Private
+ {
+ };
+
+public:
+ using traits_type = std::string::traits_type;
+ using value_type = string_view::value_type;
+ using pointer = string_view::pointer;
+ using const_pointer = string_view::const_pointer;
+ using reference = string_view::reference;
+ using const_reference = string_view::const_reference;
+ using const_iterator = string_view::const_iterator;
+ using iterator = string_view::const_iterator;
+ using const_reverse_iterator = string_view::const_reverse_iterator;
+ using reverse_iterator = string_view::const_reverse_iterator;
+ using difference_type = string_view::difference_type;
+ using size_type = string_view::size_type;
+
+ static size_type const npos = string_view::npos;
+
+ /** Construct a null string. */
+ String() = default;
+
+ /** Construct from any type implementing the IntoString trait. */
+ template <typename T,
+ typename = typename std::enable_if<IntoString<T>::value>::type>
+ String(T&& s)
+ : String(IntoString<T>::into_string(std::forward<T>(s)), Private())
+ {
+ }
+
+ /** Construct via std::string initializer list constructor. */
+ String(std::initializer_list<char> il)
+ : String(std::string(il))
+ {
+ }
+
+ /** Construct by copying the specified buffer. */
+ String(const char* d, size_type s)
+ : String(std::string(d, s))
+ {
+ }
+
+ /** Construct by copying from input iterator range. */
+ template <typename InputIterator>
+ String(InputIterator first, InputIterator last)
+ : String(std::string(first, last))
+ {
+ }
+
+ /** Construct a string with 'n' copies of character 'c'. */
+ String(size_type n, char c)
+ : String(std::string(n, c))
+ {
+ }
+
+ /** Construct from a substring of another String instance.
+ This shares ownership of the other string's buffer
+ but views only a substring. */
+ String(String const& s, size_type pos, size_type count = npos)
+ : string_(s.string_)
+ , view_(s.data() + pos, std::min(count, s.size() - pos))
+ {
+ }
+
+ /** Construct by moving from another String instance.
+ The other instance is left as a null string. */
+ String(String&& s) noexcept
+ : string_(std::move(s.string_))
+ , view_(s.view_)
+ {
+ s.view_ = string_view();
+ }
+
+ /** Construct by copying from another String instance.
+ This shares ownership of the other string's buffer. */
+ String(String const&) noexcept = default;
+
+ ~String() = default;
+
+ /** Construct by borrowing an externally-owned buffer. The buffer
+ must outlive the returned instance and all copies of it. */
+ static String borrow(string_view v) { return String(v, Private()); }
+
+ /** Assign by moving from another String instance.
+ The other instance is left as a null string. */
+ String& operator=(String&& s) noexcept
+ {
+ string_ = std::move(s.string_);
+ view_ = s.view_;
+ s.view_ = string_view();
+ return *this;
+ }
+
+ /** Assign by copying from another String instance.
+ This shares ownership of the other string's buffer. */
+ String& operator=(String const&) noexcept = default;
+
+ /** Assign from any type implementing the IntoString trait. */
+ template <typename T>
+ typename // NOLINT(*)
+ std::enable_if<IntoString<T>::value, String&>::type
+ operator=(T&& s)
+ {
+ *this = String(std::forward<T>(s));
+ return *this;
+ }
+
+ /** Assign via std::string initializer list constructor. */
+ String& operator=(std::initializer_list<char> il)
+ {
+ *this = String(il);
+ return *this;
+ }
+
+ /** Return true if the instance is not a null string. */
+ explicit operator bool() const noexcept { return data() != nullptr; }
+
+ /** Return a view of the string. */
+ string_view view() const noexcept { return view_; }
+
+ /** Return true if the instance is an empty stringn or null string. */
+ bool empty() const noexcept { return view_.empty(); }
+
+ /** Return a pointer to the start of the string. */
+ const char* data() const noexcept { return view_.data(); }
+
+ /** Return the length of the string in bytes. */
+ size_type size() const noexcept { return view_.size(); }
+ size_type length() const noexcept { return view_.length(); }
+
+ /** Return the character at the given position.
+ No bounds checking is performed. */
+ char operator[](size_type pos) const noexcept { return view_[pos]; }
+
+ /** Return the character at the given position.
+ If the position is out of bounds, throws std::out_of_range. */
+ char at(size_type pos) const { return view_.at(pos); }
+
+ char front() const noexcept { return view_.front(); }
+
+ char back() const noexcept { return view_.back(); }
+
+ /** Return true if this instance is stable and otherwise false.
+ An instance is stable if it is in the 'null' state or if it is
+ an 'owned' state not produced by substring operations, or
+ after a call to 'stabilize()' or 'str()'. */
+ bool is_stable() const;
+
+ /** If 'is_stable()' does not return true, mutate so it does. */
+ void stabilize();
+
+ /** Get a pointer to a normal std::string if 'is_stable()' returns
+ true and otherwise nullptr. The pointer is valid until this
+ instance is mutated or destroyed. */
+ std::string const* str_if_stable() const;
+
+ /** Get a refernce to a normal std::string. The reference
+ is valid until this instance is mutated or destroyed. */
+ std::string const& str();
+
+ /** Get a pointer to a C-style null-terminated string
+ containing the same value as this instance. The pointer
+ is valid until this instance is mutated, destroyed,
+ or str() is called. */
+ const char* c_str();
+
+ const_iterator begin() const noexcept { return view_.begin(); }
+ const_iterator end() const noexcept { return view_.end(); }
+ const_iterator cbegin() const noexcept { return begin(); }
+ const_iterator cend() const noexcept { return end(); }
+
+ const_reverse_iterator rbegin() const noexcept { return view_.rbegin(); }
+ const_reverse_iterator rend() const noexcept { return view_.rend(); }
+ const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+ const_reverse_iterator crend() const noexcept { return rend(); }
+
+ /** Append to the string using any type that implements the
+ AsStringView trait. */
+ template <typename T>
+ typename std::enable_if<AsStringView<T>::value, String&>::type operator+=(
+ T&& s)
+ {
+ string_view v = AsStringView<T>::view(std::forward<T>(s));
+ std::string r;
+ r.reserve(size() + v.size());
+ r.assign(data(), size());
+ r.append(v.data(), v.size());
+ return *this = std::move(r);
+ }
+
+ /** Assign to an empty string. */
+ void clear() { *this = ""_s; }
+
+ /** Insert 'count' copies of 'ch' at position 'index'. */
+ String& insert(size_type index, size_type count, char ch);
+
+ /** Erase 'count' characters starting at position 'index'. */
+ String& erase(size_type index = 0, size_type count = npos);
+
+ void push_back(char ch)
+ {
+ std::string s;
+ s.reserve(size() + 1);
+ s.assign(data(), size());
+ s.push_back(ch);
+ *this = std::move(s);
+ }
+
+ void pop_back() { *this = String(*this, 0, size() - 1); }
+
+ template <typename T>
+ typename std::enable_if<AsStringView<T>::value, String&>::type replace(
+ size_type pos, size_type count, T&& s)
+ {
+ const_iterator first = begin() + pos;
+ const_iterator last = first + count;
+ return replace(first, last, std::forward<T>(s));
+ }
+
+ template <typename InputIterator>
+ String& replace(const_iterator first, const_iterator last,
+ InputIterator first2, InputIterator last2)
+ {
+ std::string out;
+ out.append(view_.begin(), first);
+ out.append(first2, last2);
+ out.append(last, view_.end());
+ return *this = std::move(out);
+ }
+
+ template <typename T>
+ typename std::enable_if<AsStringView<T>::value, String&>::type replace(
+ const_iterator first, const_iterator last, T&& s)
+ {
+ string_view v = AsStringView<T>::view(std::forward<T>(s));
+ std::string out;
+ out.reserve((first - view_.begin()) + v.size() + (view_.end() - last));
+ out.append(view_.begin(), first);
+ out.append(v.data(), v.size());
+ out.append(last, view_.end());
+ return *this = std::move(out);
+ }
+
+ template <typename T>
+ typename std::enable_if<AsStringView<T>::value, String&>::type replace(
+ size_type pos, size_type count, T&& s, size_type pos2,
+ size_type count2 = npos)
+ {
+ string_view v = AsStringView<T>::view(std::forward<T>(s));
+ v = v.substr(pos2, count2);
+ return replace(pos, count, v);
+ }
+
+ String& replace(size_type pos, size_type count, size_type count2, char ch)
+ {
+ const_iterator first = begin() + pos;
+ const_iterator last = first + count;
+ return replace(first, last, count2, ch);
+ }
+
+ String& replace(const_iterator first, const_iterator last, size_type count2,
+ char ch)
+ {
+ std::string out;
+ out.reserve((first - view_.begin()) + count2 + (view_.end() - last));
+ out.append(view_.begin(), first);
+ out.append(count2, ch);
+ out.append(last, view_.end());
+ return *this = std::move(out);
+ }
+
+ size_type copy(char* dest, size_type count, size_type pos = 0) const;
+
+ void resize(size_type count) { resize(count, char()); }
+
+ void resize(size_type count, char ch)
+ {
+ std::string s;
+ s.reserve(count);
+ if (count <= size()) {
+ s.assign(data(), count);
+ } else {
+ s.assign(data(), size());
+ s.resize(count, ch);
+ }
+ *this = std::move(s);
+ }
+
+ void swap(String& other)
+ {
+ std::swap(string_, other.string_);
+ std::swap(view_, other.view_);
+ }
+
+ /** Return a substring starting at position 'pos' and
+ consisting of at most 'count' characters. */
+ String substr(size_type pos = 0, size_type count = npos) const;
+
+ template <typename T>
+ typename std::enable_if<AsStringView<T>::value, int>::type compare(
+ T&& s) const
+ {
+ return view_.compare(AsStringView<T>::view(std::forward<T>(s)));
+ }
+
+ int compare(size_type pos1, size_type count1, string_view v) const
+ {
+ return view_.compare(pos1, count1, v);
+ }
+
+ int compare(size_type pos1, size_type count1, string_view v, size_type pos2,
+ size_type count2) const
+ {
+ return view_.compare(pos1, count1, v, pos2, count2);
+ }
+
+ int compare(size_type pos1, size_type count1, const char* s) const
+ {
+ return view_.compare(pos1, count1, s);
+ }
+
+ int compare(size_type pos1, size_type count1, const char* s,
+ size_type count2) const
+ {
+ return view_.compare(pos1, count1, s, count2);
+ }
+
+ template <typename T>
+ typename std::enable_if<AsStringView<T>::value, size_type>::type find(
+ T&& s, size_type pos = 0) const
+ {
+ string_view v = AsStringView<T>::view(std::forward<T>(s));
+ return view_.find(v, pos);
+ }
+
+ size_type find(const char* s, size_type pos, size_type count) const
+ {
+ return view_.find(s, pos, count);
+ }
+
+ template <typename T>
+ typename std::enable_if<AsStringView<T>::value, size_type>::type rfind(
+ T&& s, size_type pos = npos) const
+ {
+ string_view v = AsStringView<T>::view(std::forward<T>(s));
+ return view_.rfind(v, pos);
+ }
+
+ size_type rfind(const char* s, size_type pos, size_type count) const
+ {
+ return view_.rfind(s, pos, count);
+ }
+
+ template <typename T>
+ typename std::enable_if<AsStringView<T>::value, size_type>::type
+ find_first_of(T&& s, size_type pos = 0) const
+ {
+ string_view v = AsStringView<T>::view(std::forward<T>(s));
+ return view_.find_first_of(v, pos);
+ }
+
+ size_type find_first_of(const char* s, size_type pos, size_type count) const
+ {
+ return view_.find_first_of(s, pos, count);
+ }
+
+ template <typename T>
+ typename std::enable_if<AsStringView<T>::value, size_type>::type
+ find_first_not_of(T&& s, size_type pos = 0) const
+ {
+ string_view v = AsStringView<T>::view(std::forward<T>(s));
+ return view_.find_first_not_of(v, pos);
+ }
+
+ size_type find_first_not_of(const char* s, size_type pos,
+ size_type count) const
+ {
+ return view_.find_first_not_of(s, pos, count);
+ }
+
+ template <typename T>
+ typename std::enable_if<AsStringView<T>::value, size_type>::type
+ find_last_of(T&& s, size_type pos = npos) const
+ {
+ string_view v = AsStringView<T>::view(std::forward<T>(s));
+ return view_.find_last_of(v, pos);
+ }
+
+ size_type find_last_of(const char* s, size_type pos, size_type count) const
+ {
+ return view_.find_last_of(s, pos, count);
+ }
+
+ template <typename T>
+ typename std::enable_if<AsStringView<T>::value, size_type>::type
+ find_last_not_of(T&& s, size_type pos = npos) const
+ {
+ string_view v = AsStringView<T>::view(std::forward<T>(s));
+ return view_.find_last_not_of(v, pos);
+ }
+
+ size_type find_last_not_of(const char* s, size_type pos,
+ size_type count) const
+ {
+ return view_.find_last_not_of(s, pos, count);
+ }
+
+private:
+ // Internal constructor to move from existing String.
+ String(String&& s, Private) noexcept
+ : String(std::move(s))
+ {
+ }
+
+ // Internal constructor for dynamically allocated string.
+ String(std::string&& s, Private);
+
+ // Internal constructor for view of statically allocated string.
+ String(string_view v, Private)
+ : view_(v)
+ {
+ }
+
+ void internally_mutate_to_stable_string();
+
+ std::shared_ptr<std::string const> string_;
+ string_view view_;
+};
+
+template <typename L, typename R>
+typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
+ bool>::type
+operator==(L&& l, R&& r)
+{
+ return (AsStringView<L>::view(std::forward<L>(l)) ==
+ AsStringView<R>::view(std::forward<R>(r)));
+}
+
+template <typename L, typename R>
+typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
+ bool>::type
+operator!=(L&& l, R&& r)
+{
+ return (AsStringView<L>::view(std::forward<L>(l)) !=
+ AsStringView<R>::view(std::forward<R>(r)));
+}
+
+template <typename L, typename R>
+typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
+ bool>::type
+operator<(L&& l, R&& r)
+{
+ return (AsStringView<L>::view(std::forward<L>(l)) <
+ AsStringView<R>::view(std::forward<R>(r)));
+}
+
+template <typename L, typename R>
+typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
+ bool>::type
+operator<=(L&& l, R&& r)
+{
+ return (AsStringView<L>::view(std::forward<L>(l)) <=
+ AsStringView<R>::view(std::forward<R>(r)));
+}
+
+template <typename L, typename R>
+typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
+ bool>::type
+operator>(L&& l, R&& r)
+{
+ return (AsStringView<L>::view(std::forward<L>(l)) >
+ AsStringView<R>::view(std::forward<R>(r)));
+}
+
+template <typename L, typename R>
+typename std::enable_if<AsStringView<L>::value && AsStringView<R>::value,
+ bool>::type
+operator>=(L&& l, R&& r)
+{
+ return (AsStringView<L>::view(std::forward<L>(l)) >=
+ AsStringView<R>::view(std::forward<R>(r)));
+}
+
+std::ostream& operator<<(std::ostream& os, String const& s);
+std::string& operator+=(std::string& self, String const& s);
+
+template <typename L, typename R>
+struct StringOpPlus
+{
+ L l;
+ R r;
+#if defined(__SUNPRO_CC)
+ StringOpPlus(L in_l, R in_r)
+ : l(in_l)
+ , r(in_r)
+ {
+ }
+#endif
+ operator std::string() const;
+ std::string::size_type size() const { return l.size() + r.size(); }
+};
+
+template <typename T>
+struct StringAdd
+{
+ static const bool value = AsStringView<T>::value;
+ using temp_type = string_view;
+ template <typename S>
+ static temp_type temp(S&& s)
+ {
+ return AsStringView<T>::view(std::forward<S>(s));
+ }
+};
+
+template <typename L, typename R>
+struct StringAdd<StringOpPlus<L, R>> : std::true_type
+{
+ using temp_type = StringOpPlus<L, R> const&;
+ static temp_type temp(temp_type s) { return s; }
+};
+
+template <typename L, typename R>
+StringOpPlus<L, R>::operator std::string() const
+{
+ std::string s;
+ s.reserve(size());
+ s += *this;
+ return s;
+}
+
+template <typename L, typename R>
+std::string& operator+=(std::string& s, StringOpPlus<L, R> const& a)
+{
+ s.reserve(s.size() + a.size());
+ s += a.l;
+ s += a.r;
+ return s;
+}
+
+template <typename L, typename R>
+String& operator+=(String& s, StringOpPlus<L, R> const& a)
+{
+ std::string r;
+ r.reserve(s.size() + a.size());
+ r.assign(s.data(), s.size());
+ r += a.l;
+ r += a.r;
+ s = std::move(r);
+ return s;
+}
+
+template <typename L, typename R>
+std::ostream& operator<<(std::ostream& os, StringOpPlus<L, R> const& a)
+{
+ return os << a.l << a.r;
+}
+
+template <typename L, typename R>
+struct IntoString<StringOpPlus<L, R>> : std::true_type
+{
+ static std::string into_string(StringOpPlus<L, R> const& a) { return a; }
+};
+
+template <typename L, typename R>
+typename std::enable_if<StringAdd<L>::value && StringAdd<R>::value,
+ StringOpPlus<typename StringAdd<L>::temp_type,
+ typename StringAdd<R>::temp_type>>::type
+operator+(L&& l, R&& r)
+{
+ return { StringAdd<L>::temp(std::forward<L>(l)),
+ StringAdd<R>::temp(std::forward<R>(r)) };
+}
+
+template <typename LL, typename LR, typename R>
+typename std::enable_if<AsStringView<R>::value, bool>::type operator==(
+ StringOpPlus<LL, LR> const& l, R&& r)
+{
+ return std::string(l) == AsStringView<R>::view(std::forward<R>(r));
+}
+
+template <typename L, typename RL, typename RR>
+typename std::enable_if<AsStringView<L>::value, bool>::type operator==(
+ L&& l, StringOpPlus<RL, RR> const& r)
+{
+ return AsStringView<L>::view(std::forward<L>(l)) == std::string(r);
+}
+
+} // namespace cm
+
+namespace std {
+
+template <>
+struct hash<cm::String>
+{
+ using argument_type = cm::String;
+ using result_type = size_t;
+
+ result_type operator()(argument_type const& s) const noexcept
+ {
+ result_type const h(std::hash<cm::string_view>{}(s.view()));
+ return h;
+ }
+};
+}
+
+#endif
diff --git a/Source/cmStringAlgorithms.cxx b/Source/cmStringAlgorithms.cxx
new file mode 100644
index 000000000..bb6dcd734
--- /dev/null
+++ b/Source/cmStringAlgorithms.cxx
@@ -0,0 +1,325 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmStringAlgorithms.h"
+
+#include <algorithm>
+#include <cerrno>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+
+std::string cmTrimWhitespace(cm::string_view str)
+{
+ auto start = str.begin();
+ while (start != str.end() && cmIsSpace(*start)) {
+ ++start;
+ }
+ if (start == str.end()) {
+ return std::string();
+ }
+ auto stop = str.end() - 1;
+ while (cmIsSpace(*stop)) {
+ --stop;
+ }
+ return std::string(start, stop + 1);
+}
+
+std::string cmRemoveQuotes(cm::string_view str)
+{
+ // We process only strings that have two quotes at least.
+ // Also front() and back() are only defined behavior on non empty strings.
+ if (str.size() >= 2 && //
+ str.front() == '"' && //
+ str.back() == '"') {
+ // Remove a quote from the front and back
+ str.remove_prefix(1);
+ str.remove_suffix(1);
+ }
+ return std::string(str);
+}
+
+std::string cmEscapeQuotes(cm::string_view str)
+{
+ std::string result;
+ result.reserve(str.size());
+ for (const char ch : str) {
+ if (ch == '"') {
+ result += '\\';
+ }
+ result += ch;
+ }
+ return result;
+}
+
+std::vector<std::string> cmTokenize(cm::string_view str, cm::string_view sep)
+{
+ std::vector<std::string> tokens;
+ cm::string_view::size_type tokend = 0;
+
+ do {
+ cm::string_view::size_type tokstart = str.find_first_not_of(sep, tokend);
+ if (tokstart == cm::string_view::npos) {
+ break; // no more tokens
+ }
+ tokend = str.find_first_of(sep, tokstart);
+ if (tokend == cm::string_view::npos) {
+ tokens.emplace_back(str.substr(tokstart));
+ } else {
+ tokens.emplace_back(str.substr(tokstart, tokend - tokstart));
+ }
+ } while (tokend != cm::string_view::npos);
+
+ if (tokens.empty()) {
+ tokens.emplace_back();
+ }
+ return tokens;
+}
+
+void cmExpandList(cm::string_view arg, std::vector<std::string>& argsOut,
+ bool emptyArgs)
+{
+ // If argument is empty, it is an empty list.
+ if (!emptyArgs && arg.empty()) {
+ return;
+ }
+
+ // if there are no ; in the name then just copy the current string
+ if (arg.find(';') == cm::string_view::npos) {
+ argsOut.emplace_back(arg);
+ return;
+ }
+
+ std::string newArg;
+ // Break the string at non-escaped semicolons not nested in [].
+ int squareNesting = 0;
+ cm::string_view::iterator last = arg.begin();
+ cm::string_view::iterator const cend = arg.end();
+ for (cm::string_view::iterator c = last; c != cend; ++c) {
+ switch (*c) {
+ case '\\': {
+ // We only want to allow escaping of semicolons. Other
+ // escapes should not be processed here.
+ cm::string_view::iterator cnext = c + 1;
+ if ((cnext != cend) && *cnext == ';') {
+ newArg.append(last, c);
+ // Skip over the escape character
+ last = cnext;
+ c = cnext;
+ }
+ } break;
+ case '[': {
+ ++squareNesting;
+ } break;
+ case ']': {
+ --squareNesting;
+ } break;
+ case ';': {
+ // Break the string here if we are not nested inside square
+ // brackets.
+ if (squareNesting == 0) {
+ newArg.append(last, c);
+ // Skip over the semicolon
+ last = c + 1;
+ if (!newArg.empty() || emptyArgs) {
+ // Add the last argument if the string is not empty.
+ argsOut.push_back(newArg);
+ newArg.clear();
+ }
+ }
+ } break;
+ default: {
+ // Just append this character.
+ } break;
+ }
+ }
+ newArg.append(last, cend);
+ if (!newArg.empty() || emptyArgs) {
+ // Add the last argument if the string is not empty.
+ argsOut.push_back(std::move(newArg));
+ }
+}
+
+std::vector<std::string> cmExpandedList(cm::string_view arg, bool emptyArgs)
+{
+ std::vector<std::string> argsOut;
+ cmExpandList(arg, argsOut, emptyArgs);
+ return argsOut;
+}
+
+namespace {
+template <std::size_t N, typename T>
+inline void MakeDigits(cm::string_view& view, char (&digits)[N],
+ const char* pattern, T value)
+{
+ int res = std::snprintf(digits, N, pattern, value);
+ if (res > 0 && res < static_cast<int>(N)) {
+ view = cm::string_view(digits, static_cast<std::size_t>(res));
+ }
+}
+} // unnamed namespace
+
+cmAlphaNum::cmAlphaNum(int val)
+{
+ MakeDigits(View_, Digits_, "%i", val);
+}
+
+cmAlphaNum::cmAlphaNum(unsigned int val)
+{
+ MakeDigits(View_, Digits_, "%u", val);
+}
+
+cmAlphaNum::cmAlphaNum(long int val)
+{
+ MakeDigits(View_, Digits_, "%li", val);
+}
+
+cmAlphaNum::cmAlphaNum(unsigned long int val)
+{
+ MakeDigits(View_, Digits_, "%lu", val);
+}
+
+cmAlphaNum::cmAlphaNum(long long int val)
+{
+ MakeDigits(View_, Digits_, "%lli", val);
+}
+
+cmAlphaNum::cmAlphaNum(unsigned long long int val)
+{
+ MakeDigits(View_, Digits_, "%llu", val);
+}
+
+cmAlphaNum::cmAlphaNum(float val)
+{
+ MakeDigits(View_, Digits_, "%g", static_cast<double>(val));
+}
+
+cmAlphaNum::cmAlphaNum(double val)
+{
+ MakeDigits(View_, Digits_, "%g", val);
+}
+
+std::string cmCatViews(std::initializer_list<cm::string_view> views)
+{
+ std::size_t total_size = 0;
+ for (cm::string_view const& view : views) {
+ total_size += view.size();
+ }
+
+ std::string result(total_size, '\0');
+ std::string::iterator sit = result.begin();
+ for (cm::string_view const& view : views) {
+ sit = std::copy_n(view.data(), view.size(), sit);
+ }
+ return result;
+}
+
+bool cmIsInternallyOn(cm::string_view val)
+{
+ return (val.size() == 4) && //
+ (val[0] == 'I' || val[0] == 'i') && //
+ (val[1] == '_') && //
+ (val[2] == 'O' || val[2] == 'o') && //
+ (val[3] == 'N' || val[3] == 'n');
+}
+
+bool cmIsNOTFOUND(cm::string_view val)
+{
+ return (val == "NOTFOUND") || cmHasLiteralSuffix(val, "-NOTFOUND");
+}
+
+bool cmIsOn(cm::string_view val)
+{
+ switch (val.size()) {
+ case 1:
+ return val[0] == '1' || val[0] == 'Y' || val[0] == 'y';
+ case 2:
+ return //
+ (val[0] == 'O' || val[0] == 'o') && //
+ (val[1] == 'N' || val[1] == 'n');
+ case 3:
+ return //
+ (val[0] == 'Y' || val[0] == 'y') && //
+ (val[1] == 'E' || val[1] == 'e') && //
+ (val[2] == 'S' || val[2] == 's');
+ case 4:
+ return //
+ (val[0] == 'T' || val[0] == 't') && //
+ (val[1] == 'R' || val[1] == 'r') && //
+ (val[2] == 'U' || val[2] == 'u') && //
+ (val[3] == 'E' || val[3] == 'e');
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool cmIsOff(cm::string_view val)
+{
+ switch (val.size()) {
+ case 0:
+ return true;
+ case 1:
+ return val[0] == '0' || val[0] == 'N' || val[0] == 'n';
+ case 2:
+ return //
+ (val[0] == 'N' || val[0] == 'n') && //
+ (val[1] == 'O' || val[1] == 'o');
+ case 3:
+ return //
+ (val[0] == 'O' || val[0] == 'o') && //
+ (val[1] == 'F' || val[1] == 'f') && //
+ (val[2] == 'F' || val[2] == 'f');
+ case 5:
+ return //
+ (val[0] == 'F' || val[0] == 'f') && //
+ (val[1] == 'A' || val[1] == 'a') && //
+ (val[2] == 'L' || val[2] == 'l') && //
+ (val[3] == 'S' || val[3] == 's') && //
+ (val[4] == 'E' || val[4] == 'e');
+ case 6:
+ return //
+ (val[0] == 'I' || val[0] == 'i') && //
+ (val[1] == 'G' || val[1] == 'g') && //
+ (val[2] == 'N' || val[2] == 'n') && //
+ (val[3] == 'O' || val[3] == 'o') && //
+ (val[4] == 'R' || val[4] == 'r') && //
+ (val[5] == 'E' || val[5] == 'e');
+ default:
+ break;
+ }
+
+ return cmIsNOTFOUND(val);
+}
+
+bool cmStrToLong(const char* str, long* value)
+{
+ errno = 0;
+ char* endp;
+ *value = strtol(str, &endp, 10);
+ return (*endp == '\0') && (endp != str) && (errno == 0);
+}
+
+bool cmStrToLong(std::string const& str, long* value)
+{
+ return cmStrToLong(str.c_str(), value);
+}
+
+bool cmStrToULong(const char* str, unsigned long* value)
+{
+ errno = 0;
+ char* endp;
+ while (cmIsSpace(*str)) {
+ ++str;
+ }
+ if (*str == '-') {
+ return false;
+ }
+ *value = strtoul(str, &endp, 10);
+ return (*endp == '\0') && (endp != str) && (errno == 0);
+}
+
+bool cmStrToULong(std::string const& str, unsigned long* value)
+{
+ return cmStrToULong(str.c_str(), value);
+}
diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h
new file mode 100644
index 000000000..0e405dea6
--- /dev/null
+++ b/Source/cmStringAlgorithms.h
@@ -0,0 +1,294 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmStringAlgorithms_h
+#define cmStringAlgorithms_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cctype>
+#include <cstring>
+#include <initializer_list>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm/string_view>
+
+#include "cmRange.h"
+
+/** String range type. */
+using cmStringRange = cmRange<std::vector<std::string>::const_iterator>;
+
+/** Callable string comparison struct. */
+struct cmStrCmp
+{
+ cmStrCmp(std::string str)
+ : Test_(std::move(str))
+ {
+ }
+
+ bool operator()(cm::string_view sv) const { return Test_ == sv; }
+
+private:
+ std::string const Test_;
+};
+
+/** Returns true if the character @a ch is a whitespace character. **/
+inline bool cmIsSpace(char ch)
+{
+ return ((ch & 0x80) == 0) && std::isspace(ch);
+}
+
+/** Returns a string that has whitespace removed from the start and the end. */
+std::string cmTrimWhitespace(cm::string_view str);
+
+/** Returns a string that has quotes removed from the start and the end. */
+std::string cmRemoveQuotes(cm::string_view str);
+
+/** Escape quotes in a string. */
+std::string cmEscapeQuotes(cm::string_view str);
+
+/** Joins elements of a range with separator into a single string. */
+template <typename Range>
+std::string cmJoin(Range const& rng, cm::string_view separator)
+{
+ if (rng.empty()) {
+ return std::string();
+ }
+
+ std::ostringstream os;
+ auto it = rng.begin();
+ auto const end = rng.end();
+ os << *it;
+ while (++it != end) {
+ os << separator << *it;
+ }
+ return os.str();
+}
+
+/** Extract tokens that are separated by any of the characters in @a sep. */
+std::vector<std::string> cmTokenize(cm::string_view str, cm::string_view sep);
+
+/**
+ * Expand the ; separated string @a arg into multiple arguments.
+ * All found arguments are appended to @a argsOut.
+ */
+void cmExpandList(cm::string_view arg, std::vector<std::string>& argsOut,
+ bool emptyArgs = false);
+
+/**
+ * Expand out any arguments in the string range [@a first, @a last) that have
+ * ; separated strings into multiple arguments. All found arguments are
+ * appended to @a argsOut.
+ */
+template <class InputIt>
+void cmExpandLists(InputIt first, InputIt last,
+ std::vector<std::string>& argsOut)
+{
+ for (; first != last; ++first) {
+ ExpandList(*first, argsOut);
+ }
+}
+
+/**
+ * Same as cmExpandList but a new vector is created containing
+ * the expanded arguments from the string @a arg.
+ */
+std::vector<std::string> cmExpandedList(cm::string_view arg,
+ bool emptyArgs = false);
+
+/**
+ * Same as cmExpandList but a new vector is created containing the expanded
+ * versions of all arguments in the string range [@a first, @a last).
+ */
+template <class InputIt>
+std::vector<std::string> cmExpandedLists(InputIt first, InputIt last)
+{
+ std::vector<std::string> argsOut;
+ for (; first != last; ++first) {
+ cmExpandList(*first, argsOut);
+ }
+ return argsOut;
+}
+
+/** Concatenate string pieces into a single string. */
+std::string cmCatViews(std::initializer_list<cm::string_view> views);
+
+/** Utility class for cmStrCat. */
+class cmAlphaNum
+{
+public:
+ cmAlphaNum(cm::string_view view)
+ : View_(view)
+ {
+ }
+ cmAlphaNum(std::string const& str)
+ : View_(str)
+ {
+ }
+ cmAlphaNum(const char* str)
+ : View_(str)
+ {
+ }
+ cmAlphaNum(char ch)
+ : View_(Digits_, 1)
+ {
+ Digits_[0] = ch;
+ }
+ cmAlphaNum(int val);
+ cmAlphaNum(unsigned int val);
+ cmAlphaNum(long int val);
+ cmAlphaNum(unsigned long int val);
+ cmAlphaNum(long long int val);
+ cmAlphaNum(unsigned long long int val);
+ cmAlphaNum(float val);
+ cmAlphaNum(double val);
+
+ cm::string_view View() const { return View_; }
+
+private:
+ cm::string_view View_;
+ char Digits_[32];
+};
+
+/** Concatenate string pieces and numbers into a single string. */
+template <typename... AV>
+inline std::string cmStrCat(cmAlphaNum const& a, cmAlphaNum const& b,
+ AV const&... args)
+{
+ return cmCatViews(
+ { a.View(), b.View(), static_cast<cmAlphaNum const&>(args).View()... });
+}
+
+/** Joins wrapped elements of a range with separator into a single string. */
+template <typename Range>
+std::string cmWrap(cm::string_view prefix, Range const& rng,
+ cm::string_view suffix, cm::string_view sep)
+{
+ if (rng.empty()) {
+ return std::string();
+ }
+ return cmCatViews(
+ { prefix, cmJoin(rng, cmCatViews({ suffix, sep, prefix })), suffix });
+}
+
+/** Joins wrapped elements of a range with separator into a single string. */
+template <typename Range>
+std::string cmWrap(char prefix, Range const& rng, char suffix,
+ cm::string_view sep)
+{
+ return cmWrap(cm::string_view(&prefix, 1), rng, cm::string_view(&suffix, 1),
+ sep);
+}
+
+/**
+ * Does a string indicates that CMake/CPack/CTest internally
+ * forced this value. This is not the same as On, but this
+ * may be considered as "internally switched on".
+ */
+bool cmIsInternallyOn(cm::string_view val);
+inline bool cmIsInternallyOn(const char* val)
+{
+ if (!val) {
+ return false;
+ }
+ return cmIsInternallyOn(cm::string_view(val));
+}
+
+/** Return true if value is NOTFOUND or ends in -NOTFOUND. */
+bool cmIsNOTFOUND(cm::string_view val);
+
+/**
+ * Does a string indicate a true or ON value? This is not the same as ifdef.
+ */
+bool cmIsOn(cm::string_view val);
+inline bool cmIsOn(const char* val)
+{
+ if (!val) {
+ return false;
+ }
+ return cmIsOn(cm::string_view(val));
+}
+
+/**
+ * Does a string indicate a false or off value ? Note that this is
+ * not the same as !IsOn(...) because there are a number of
+ * ambiguous values such as "/usr/local/bin" a path will result in
+ * IsON and IsOff both returning false. Note that the special path
+ * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true.
+ */
+bool cmIsOff(cm::string_view val);
+inline bool cmIsOff(const char* val)
+{
+ if (!val) {
+ return true;
+ }
+ return cmIsOff(cm::string_view(val));
+}
+
+/** Returns true if string @a str starts with the character @a prefix. */
+inline bool cmHasPrefix(cm::string_view str, char prefix)
+{
+ return !str.empty() && (str.front() == prefix);
+}
+
+/** Returns true if string @a str starts with string @a prefix. */
+inline bool cmHasPrefix(cm::string_view str, cm::string_view prefix)
+{
+ return str.compare(0, prefix.size(), prefix) == 0;
+}
+
+/** Returns true if string @a str starts with string @a prefix. */
+template <size_t N>
+inline bool cmHasLiteralPrefix(cm::string_view str, const char (&prefix)[N])
+{
+ return cmHasPrefix(str, cm::string_view(prefix, N - 1));
+}
+
+/** Returns true if string @a str ends with the character @a suffix. */
+inline bool cmHasSuffix(cm::string_view str, char suffix)
+{
+ return !str.empty() && (str.back() == suffix);
+}
+
+/** Returns true if string @a str ends with string @a suffix. */
+inline bool cmHasSuffix(cm::string_view str, cm::string_view suffix)
+{
+ return str.size() >= suffix.size() &&
+ str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
+}
+
+/** Returns true if string @a str ends with string @a suffix. */
+template <size_t N>
+inline bool cmHasLiteralSuffix(cm::string_view str, const char (&suffix)[N])
+{
+ return cmHasSuffix(str, cm::string_view(suffix, N - 1));
+}
+
+/** Removes an existing suffix character of from the string @a str. */
+inline void cmStripSuffixIfExists(std::string& str, char suffix)
+{
+ if (cmHasSuffix(str, suffix)) {
+ str.pop_back();
+ }
+}
+
+/** Removes an existing suffix string of from the string @a str. */
+inline void cmStripSuffixIfExists(std::string& str, cm::string_view suffix)
+{
+ if (cmHasSuffix(str, suffix)) {
+ str.resize(str.size() - suffix.size());
+ }
+}
+
+/** Converts a string to long. Expects that the whole string is an integer. */
+bool cmStrToLong(const char* str, long* value);
+bool cmStrToLong(std::string const& str, long* value);
+
+/** Converts a string to unsigned long. Expects that the whole string is an
+ * integer */
+bool cmStrToULong(const char* str, unsigned long* value);
+bool cmStrToULong(std::string const& str, unsigned long* value);
+
+#endif
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index 7a097ba21..9212195f5 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -1,130 +1,74 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+#define _SCL_SECURE_NO_WARNINGS
+
#include "cmStringCommand.h"
+#include <algorithm>
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include <memory>
+
+#include <cm/iterator>
+
#include "cmsys/RegularExpression.hxx"
-#include <ctype.h>
-#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
-#include "cmAlgorithms.h"
+#include "cm_static_string_view.hxx"
+
#include "cmCryptoHash.h"
+#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmRange.h"
+#include "cmStringAlgorithms.h"
+#include "cmStringReplaceHelper.h"
+#include "cmSubcommandTable.h"
#include "cmSystemTools.h"
#include "cmTimestamp.h"
#include "cmUuid.h"
-#include "cm_auto_ptr.hxx"
-class cmExecutionStatus;
+namespace {
-bool cmStringCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
-{
- if (args.empty()) {
- this->SetError("must be called with at least one argument.");
- return false;
- }
+bool RegexMatch(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+bool RegexMatchAll(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+bool RegexReplace(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
- const std::string& subCommand = args[0];
- if (subCommand == "REGEX") {
- return this->HandleRegexCommand(args);
- }
- if (subCommand == "REPLACE") {
- return this->HandleReplaceCommand(args);
- }
- if (subCommand == "MD5" || subCommand == "SHA1" || subCommand == "SHA224" ||
- subCommand == "SHA256" || subCommand == "SHA384" ||
- subCommand == "SHA512" || subCommand == "SHA3_224" ||
- subCommand == "SHA3_256" || subCommand == "SHA3_384" ||
- subCommand == "SHA3_512") {
- return this->HandleHashCommand(args);
- }
- if (subCommand == "TOLOWER") {
- return this->HandleToUpperLowerCommand(args, false);
- }
- if (subCommand == "TOUPPER") {
- return this->HandleToUpperLowerCommand(args, true);
- }
- if (subCommand == "COMPARE") {
- return this->HandleCompareCommand(args);
- }
- if (subCommand == "ASCII") {
- return this->HandleAsciiCommand(args);
- }
- if (subCommand == "CONFIGURE") {
- return this->HandleConfigureCommand(args);
- }
- if (subCommand == "LENGTH") {
- return this->HandleLengthCommand(args);
- }
- if (subCommand == "APPEND") {
- return this->HandleAppendCommand(args);
- }
- if (subCommand == "CONCAT") {
- return this->HandleConcatCommand(args);
- }
- if (subCommand == "SUBSTRING") {
- return this->HandleSubstringCommand(args);
- }
- if (subCommand == "STRIP") {
- return this->HandleStripCommand(args);
- }
- if (subCommand == "RANDOM") {
- return this->HandleRandomCommand(args);
- }
- if (subCommand == "FIND") {
- return this->HandleFindCommand(args);
- }
- if (subCommand == "TIMESTAMP") {
- return this->HandleTimestampCommand(args);
- }
- if (subCommand == "MAKE_C_IDENTIFIER") {
- return this->HandleMakeCIdentifierCommand(args);
- }
- if (subCommand == "GENEX_STRIP") {
- return this->HandleGenexStripCommand(args);
- }
- if (subCommand == "UUID") {
- return this->HandleUuidCommand(args);
- }
+bool joinImpl(std::vector<std::string> const& args, std::string const& glue,
+ size_t varIdx, cmMakefile& makefile);
- std::string e = "does not recognize sub-command " + subCommand;
- this->SetError(e);
- return false;
-}
-
-bool cmStringCommand::HandleHashCommand(std::vector<std::string> const& args)
+bool HandleHashCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
if (args.size() != 3) {
- std::ostringstream e;
- e << args[0] << " requires an output variable and an input string";
- this->SetError(e.str());
+ status.SetError(
+ cmStrCat(args[0], " requires an output variable and an input string"));
return false;
}
- CM_AUTO_PTR<cmCryptoHash> hash(cmCryptoHash::New(args[0].c_str()));
- if (hash.get()) {
+ std::unique_ptr<cmCryptoHash> hash(cmCryptoHash::New(args[0]));
+ if (hash) {
std::string out = hash->HashString(args[2]);
- this->Makefile->AddDefinition(args[1], out.c_str());
+ status.GetMakefile().AddDefinition(args[1], out);
return true;
}
return false;
#else
- std::ostringstream e;
- e << args[0] << " not available during bootstrap";
- this->SetError(e.str().c_str());
+ status.SetError(cmStrCat(args[0], " not available during bootstrap"));
return false;
#endif
}
-bool cmStringCommand::HandleToUpperLowerCommand(
- std::vector<std::string> const& args, bool toUpper)
+bool HandleToUpperLowerCommand(std::vector<std::string> const& args,
+ bool toUpper, cmExecutionStatus& status)
{
if (args.size() < 3) {
- this->SetError("no output variable specified");
+ status.SetError("no output variable specified");
return false;
}
@@ -138,45 +82,57 @@ bool cmStringCommand::HandleToUpperLowerCommand(
}
// Store the output in the provided variable.
- this->Makefile->AddDefinition(outvar, output.c_str());
+ status.GetMakefile().AddDefinition(outvar, output);
return true;
}
-bool cmStringCommand::HandleAsciiCommand(std::vector<std::string> const& args)
+bool HandleToUpperCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return HandleToUpperLowerCommand(args, true, status);
+}
+
+bool HandleToLowerCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return HandleToUpperLowerCommand(args, false, status);
+}
+
+bool HandleAsciiCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 3) {
- this->SetError("No output variable specified");
+ status.SetError("No output variable specified");
return false;
}
std::string::size_type cc;
- std::string const& outvar = args[args.size() - 1];
+ std::string const& outvar = args.back();
std::string output;
for (cc = 1; cc < args.size() - 1; cc++) {
int ch = atoi(args[cc].c_str());
if (ch > 0 && ch < 256) {
output += static_cast<char>(ch);
} else {
- std::string error = "Character with code ";
- error += args[cc];
- error += " does not exist.";
- this->SetError(error);
+ std::string error =
+ cmStrCat("Character with code ", args[cc], " does not exist.");
+ status.SetError(error);
return false;
}
}
// Store the output in the provided variable.
- this->Makefile->AddDefinition(outvar, output.c_str());
+ status.GetMakefile().AddDefinition(outvar, output);
return true;
}
-bool cmStringCommand::HandleConfigureCommand(
- std::vector<std::string> const& args)
+bool HandleConfigureCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("No input string specified.");
+ status.SetError("No input string specified.");
return false;
}
if (args.size() < 3) {
- this->SetError("No output variable specified.");
+ status.SetError("No output variable specified.");
return false;
}
@@ -189,75 +145,75 @@ bool cmStringCommand::HandleConfigureCommand(
} else if (args[i] == "ESCAPE_QUOTES") {
escapeQuotes = true;
} else {
- std::ostringstream err;
- err << "Unrecognized argument \"" << args[i] << "\"";
- this->SetError(err.str());
+ status.SetError(cmStrCat("Unrecognized argument \"", args[i], "\""));
return false;
}
}
// Configure the string.
std::string output;
- this->Makefile->ConfigureString(args[1], output, atOnly, escapeQuotes);
+ status.GetMakefile().ConfigureString(args[1], output, atOnly, escapeQuotes);
// Store the output in the provided variable.
- this->Makefile->AddDefinition(args[2], output.c_str());
+ status.GetMakefile().AddDefinition(args[2], output);
return true;
}
-bool cmStringCommand::HandleRegexCommand(std::vector<std::string> const& args)
+bool HandleRegexCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("sub-command REGEX requires a mode to be specified.");
+ status.SetError("sub-command REGEX requires a mode to be specified.");
return false;
}
std::string const& mode = args[1];
if (mode == "MATCH") {
if (args.size() < 5) {
- this->SetError("sub-command REGEX, mode MATCH needs "
- "at least 5 arguments total to command.");
+ status.SetError("sub-command REGEX, mode MATCH needs "
+ "at least 5 arguments total to command.");
return false;
}
- return this->RegexMatch(args);
+ return RegexMatch(args, status);
}
if (mode == "MATCHALL") {
if (args.size() < 5) {
- this->SetError("sub-command REGEX, mode MATCHALL needs "
- "at least 5 arguments total to command.");
+ status.SetError("sub-command REGEX, mode MATCHALL needs "
+ "at least 5 arguments total to command.");
return false;
}
- return this->RegexMatchAll(args);
+ return RegexMatchAll(args, status);
}
if (mode == "REPLACE") {
if (args.size() < 6) {
- this->SetError("sub-command REGEX, mode REPLACE needs "
- "at least 6 arguments total to command.");
+ status.SetError("sub-command REGEX, mode REPLACE needs "
+ "at least 6 arguments total to command.");
return false;
}
- return this->RegexReplace(args);
+ return RegexReplace(args, status);
}
std::string e = "sub-command REGEX does not recognize mode " + mode;
- this->SetError(e);
+ status.SetError(e);
return false;
}
-bool cmStringCommand::RegexMatch(std::vector<std::string> const& args)
+bool RegexMatch(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
//"STRING(REGEX MATCH <regular_expression> <output variable>
// <input> [<input>...])\n";
std::string const& regex = args[2];
std::string const& outvar = args[3];
- this->Makefile->ClearMatches();
+ status.GetMakefile().ClearMatches();
// Compile the regular expression.
cmsys::RegularExpression re;
if (!re.compile(regex.c_str())) {
std::string e =
"sub-command REGEX, mode MATCH failed to compile regex \"" + regex +
"\".";
- this->SetError(e);
+ status.SetError(e);
return false;
}
@@ -266,39 +222,40 @@ bool cmStringCommand::RegexMatch(std::vector<std::string> const& args)
// Scan through the input for all matches.
std::string output;
- if (re.find(input.c_str())) {
- this->Makefile->StoreMatches(re);
+ if (re.find(input)) {
+ status.GetMakefile().StoreMatches(re);
std::string::size_type l = re.start();
std::string::size_type r = re.end();
if (r - l == 0) {
std::string e = "sub-command REGEX, mode MATCH regex \"" + regex +
"\" matched an empty string.";
- this->SetError(e);
+ status.SetError(e);
return false;
}
output = input.substr(l, r - l);
}
// Store the output in the provided variable.
- this->Makefile->AddDefinition(outvar, output.c_str());
+ status.GetMakefile().AddDefinition(outvar, output);
return true;
}
-bool cmStringCommand::RegexMatchAll(std::vector<std::string> const& args)
+bool RegexMatchAll(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
//"STRING(REGEX MATCHALL <regular_expression> <output variable> <input>
// [<input>...])\n";
std::string const& regex = args[2];
std::string const& outvar = args[3];
- this->Makefile->ClearMatches();
+ status.GetMakefile().ClearMatches();
// Compile the regular expression.
cmsys::RegularExpression re;
if (!re.compile(regex.c_str())) {
std::string e =
"sub-command REGEX, mode MATCHALL failed to compile regex \"" + regex +
"\".";
- this->SetError(e);
+ status.SetError(e);
return false;
}
@@ -309,13 +266,14 @@ bool cmStringCommand::RegexMatchAll(std::vector<std::string> const& args)
std::string output;
const char* p = input.c_str();
while (re.find(p)) {
- this->Makefile->StoreMatches(re);
+ status.GetMakefile().ClearMatches();
+ status.GetMakefile().StoreMatches(re);
std::string::size_type l = re.start();
std::string::size_type r = re.end();
if (r - l == 0) {
std::string e = "sub-command REGEX, mode MATCHALL regex \"" + regex +
"\" matched an empty string.";
- this->SetError(e);
+ status.SetError(e);
return false;
}
if (!output.empty()) {
@@ -326,128 +284,58 @@ bool cmStringCommand::RegexMatchAll(std::vector<std::string> const& args)
}
// Store the output in the provided variable.
- this->Makefile->AddDefinition(outvar, output.c_str());
+ status.GetMakefile().AddDefinition(outvar, output);
return true;
}
-bool cmStringCommand::RegexReplace(std::vector<std::string> const& args)
+bool RegexReplace(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
//"STRING(REGEX REPLACE <regular_expression> <replace_expression>
// <output variable> <input> [<input>...])\n"
std::string const& regex = args[2];
std::string const& replace = args[3];
std::string const& outvar = args[4];
+ cmStringReplaceHelper replaceHelper(regex, replace, &status.GetMakefile());
- // Pull apart the replace expression to find the escaped [0-9] values.
- std::vector<RegexReplacement> replacement;
- std::string::size_type l = 0;
- while (l < replace.length()) {
- std::string::size_type r = replace.find('\\', l);
- if (r == std::string::npos) {
- r = replace.length();
- replacement.push_back(replace.substr(l, r - l));
- } else {
- if (r - l > 0) {
- replacement.push_back(replace.substr(l, r - l));
- }
- if (r == (replace.length() - 1)) {
- this->SetError("sub-command REGEX, mode REPLACE: "
- "replace-expression ends in a backslash.");
- return false;
- }
- if ((replace[r + 1] >= '0') && (replace[r + 1] <= '9')) {
- replacement.push_back(replace[r + 1] - '0');
- } else if (replace[r + 1] == 'n') {
- replacement.push_back("\n");
- } else if (replace[r + 1] == '\\') {
- replacement.push_back("\\");
- } else {
- std::string e = "sub-command REGEX, mode REPLACE: Unknown escape \"";
- e += replace.substr(r, 2);
- e += "\" in replace-expression.";
- this->SetError(e);
- return false;
- }
- r += 2;
- }
- l = r;
+ if (!replaceHelper.IsReplaceExpressionValid()) {
+ status.SetError(
+ "sub-command REGEX, mode REPLACE: " + replaceHelper.GetError() + ".");
+ return false;
}
- this->Makefile->ClearMatches();
- // Compile the regular expression.
- cmsys::RegularExpression re;
- if (!re.compile(regex.c_str())) {
+ status.GetMakefile().ClearMatches();
+
+ if (!replaceHelper.IsRegularExpressionValid()) {
std::string e =
"sub-command REGEX, mode REPLACE failed to compile regex \"" + regex +
"\".";
- this->SetError(e);
+ status.SetError(e);
return false;
}
// Concatenate all the last arguments together.
- std::string input = cmJoin(cmMakeRange(args).advance(5), std::string());
-
- // Scan through the input for all matches.
+ const std::string input =
+ cmJoin(cmMakeRange(args).advance(5), std::string());
std::string output;
- std::string::size_type base = 0;
- while (re.find(input.c_str() + base)) {
- this->Makefile->StoreMatches(re);
- std::string::size_type l2 = re.start();
- std::string::size_type r = re.end();
-
- // Concatenate the part of the input that was not matched.
- output += input.substr(base, l2);
-
- // Make sure the match had some text.
- if (r - l2 == 0) {
- std::string e = "sub-command REGEX, mode REPLACE regex \"" + regex +
- "\" matched an empty string.";
- this->SetError(e);
- return false;
- }
- // Concatenate the replacement for the match.
- for (unsigned int i = 0; i < replacement.size(); ++i) {
- if (replacement[i].number < 0) {
- // This is just a plain-text part of the replacement.
- output += replacement[i].value;
- } else {
- // Replace with part of the match.
- int n = replacement[i].number;
- std::string::size_type start = re.start(n);
- std::string::size_type end = re.end(n);
- std::string::size_type len = input.length() - base;
- if ((start != std::string::npos) && (end != std::string::npos) &&
- (start <= len) && (end <= len)) {
- output += input.substr(base + start, end - start);
- } else {
- std::string e =
- "sub-command REGEX, mode REPLACE: replace expression \"" +
- replace + "\" contains an out-of-range escape for regex \"" +
- regex + "\".";
- this->SetError(e);
- return false;
- }
- }
- }
-
- // Move past the match.
- base += r;
+ if (!replaceHelper.Replace(input, output)) {
+ status.SetError(
+ "sub-command REGEX, mode REPLACE: " + replaceHelper.GetError() + ".");
+ return false;
}
- // Concatenate the text after the last match.
- output += input.substr(base, input.length() - base);
-
// Store the output in the provided variable.
- this->Makefile->AddDefinition(outvar, output.c_str());
+ status.GetMakefile().AddDefinition(outvar, output);
return true;
}
-bool cmStringCommand::HandleFindCommand(std::vector<std::string> const& args)
+bool HandleFindCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
// check if all required parameters were passed
if (args.size() < 4 || args.size() > 5) {
- this->SetError("sub-command FIND requires 3 or 4 parameters.");
+ status.SetError("sub-command FIND requires 3 or 4 parameters.");
return false;
}
@@ -459,7 +347,7 @@ bool cmStringCommand::HandleFindCommand(std::vector<std::string> const& args)
// if we have 5 arguments the last one must be REVERSE
if (args.size() == 5 && args[4] != "REVERSE") {
- this->SetError("sub-command FIND: unknown last parameter");
+ status.SetError("sub-command FIND: unknown last parameter");
return false;
}
@@ -470,9 +358,9 @@ bool cmStringCommand::HandleFindCommand(std::vector<std::string> const& args)
// ensure that the user cannot accidentally specify REVERSE as a variable
if (outvar == "REVERSE") {
- this->SetError("sub-command FIND does not allow one to select REVERSE as "
- "the output variable. "
- "Maybe you missed the actual output variable?");
+ status.SetError("sub-command FIND does not allow one to select REVERSE as "
+ "the output variable. "
+ "Maybe you missed the actual output variable?");
return false;
}
@@ -484,22 +372,20 @@ bool cmStringCommand::HandleFindCommand(std::vector<std::string> const& args)
pos = sstring.rfind(schar);
}
if (std::string::npos != pos) {
- std::ostringstream s;
- s << pos;
- this->Makefile->AddDefinition(outvar, s.str().c_str());
+ status.GetMakefile().AddDefinition(outvar, std::to_string(pos));
return true;
}
// the character was not found, but this is not really an error
- this->Makefile->AddDefinition(outvar, "-1");
+ status.GetMakefile().AddDefinition(outvar, "-1");
return true;
}
-bool cmStringCommand::HandleCompareCommand(
- std::vector<std::string> const& args)
+bool HandleCompareCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("sub-command COMPARE requires a mode to be specified.");
+ status.SetError("sub-command COMPARE requires a mode to be specified.");
return false;
}
std::string const& mode = args[1];
@@ -507,10 +393,10 @@ bool cmStringCommand::HandleCompareCommand(
(mode == "LESS_EQUAL") || (mode == "GREATER") ||
(mode == "GREATER_EQUAL")) {
if (args.size() < 5) {
- std::string e = "sub-command COMPARE, mode ";
- e += mode;
- e += " needs at least 5 arguments total to command.";
- this->SetError(e);
+ std::string e =
+ cmStrCat("sub-command COMPARE, mode ", mode,
+ " needs at least 5 arguments total to command.");
+ status.SetError(e);
return false;
}
@@ -533,22 +419,22 @@ bool cmStringCommand::HandleCompareCommand(
result = !(left == right);
}
if (result) {
- this->Makefile->AddDefinition(outvar, "1");
+ status.GetMakefile().AddDefinition(outvar, "1");
} else {
- this->Makefile->AddDefinition(outvar, "0");
+ status.GetMakefile().AddDefinition(outvar, "0");
}
return true;
}
std::string e = "sub-command COMPARE does not recognize mode " + mode;
- this->SetError(e);
+ status.SetError(e);
return false;
}
-bool cmStringCommand::HandleReplaceCommand(
- std::vector<std::string> const& args)
+bool HandleReplaceCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 5) {
- this->SetError("sub-command REPLACE requires at least four arguments.");
+ status.SetError("sub-command REPLACE requires at least four arguments.");
return false;
}
@@ -561,15 +447,15 @@ bool cmStringCommand::HandleReplaceCommand(
cmsys::SystemTools::ReplaceString(input, matchExpression.c_str(),
replaceExpression.c_str());
- this->Makefile->AddDefinition(variableName, input.c_str());
+ status.GetMakefile().AddDefinition(variableName, input);
return true;
}
-bool cmStringCommand::HandleSubstringCommand(
- std::vector<std::string> const& args)
+bool HandleSubstringCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() != 5) {
- this->SetError("sub-command SUBSTRING requires four arguments.");
+ status.SetError("sub-command SUBSTRING requires four arguments.");
return false;
}
@@ -581,28 +467,25 @@ bool cmStringCommand::HandleSubstringCommand(
size_t stringLength = stringValue.size();
int intStringLength = static_cast<int>(stringLength);
if (begin < 0 || begin > intStringLength) {
- std::ostringstream ostr;
- ostr << "begin index: " << begin << " is out of range 0 - "
- << stringLength;
- this->SetError(ostr.str());
+ status.SetError(
+ cmStrCat("begin index: ", begin, " is out of range 0 - ", stringLength));
return false;
}
if (end < -1) {
- std::ostringstream ostr;
- ostr << "end index: " << end << " should be -1 or greater";
- this->SetError(ostr.str());
+ status.SetError(cmStrCat("end index: ", end, " should be -1 or greater"));
return false;
}
- this->Makefile->AddDefinition(variableName,
- stringValue.substr(begin, end).c_str());
+ status.GetMakefile().AddDefinition(variableName,
+ stringValue.substr(begin, end));
return true;
}
-bool cmStringCommand::HandleLengthCommand(std::vector<std::string> const& args)
+bool HandleLengthCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() != 3) {
- this->SetError("sub-command LENGTH requires two arguments.");
+ status.SetError("sub-command LENGTH requires two arguments.");
return false;
}
@@ -613,14 +496,15 @@ bool cmStringCommand::HandleLengthCommand(std::vector<std::string> const& args)
char buffer[1024];
sprintf(buffer, "%d", static_cast<int>(length));
- this->Makefile->AddDefinition(variableName, buffer);
+ status.GetMakefile().AddDefinition(variableName, buffer);
return true;
}
-bool cmStringCommand::HandleAppendCommand(std::vector<std::string> const& args)
+bool HandleAppendCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("sub-command APPEND requires at least one argument.");
+ status.SetError("sub-command APPEND requires at least one argument.");
return false;
}
@@ -632,50 +516,94 @@ bool cmStringCommand::HandleAppendCommand(std::vector<std::string> const& args)
const std::string& variable = args[1];
std::string value;
- const char* oldValue = this->Makefile->GetDefinition(variable);
+ const char* oldValue = status.GetMakefile().GetDefinition(variable);
if (oldValue) {
value = oldValue;
}
value += cmJoin(cmMakeRange(args).advance(2), std::string());
- this->Makefile->AddDefinition(variable, value.c_str());
+ status.GetMakefile().AddDefinition(variable, value);
return true;
}
-bool cmStringCommand::HandleConcatCommand(std::vector<std::string> const& args)
+bool HandlePrependCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("sub-command CONCAT requires at least one argument.");
+ status.SetError("sub-command PREPEND requires at least one argument.");
return false;
}
- std::string const& variableName = args[1];
+ // Skip if nothing to prepend.
+ if (args.size() < 3) {
+ return true;
+ }
+
+ const std::string& variable = args[1];
+
std::string value = cmJoin(cmMakeRange(args).advance(2), std::string());
+ const char* oldValue = status.GetMakefile().GetDefinition(variable);
+ if (oldValue) {
+ value += oldValue;
+ }
+ status.GetMakefile().AddDefinition(variable, value);
+ return true;
+}
- this->Makefile->AddDefinition(variableName, value.c_str());
+bool HandleConcatCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.size() < 2) {
+ status.SetError("sub-command CONCAT requires at least one argument.");
+ return false;
+ }
+
+ return joinImpl(args, std::string(), 1, status.GetMakefile());
+}
+
+bool HandleJoinCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.size() < 3) {
+ status.SetError("sub-command JOIN requires at least two arguments.");
+ return false;
+ }
+
+ return joinImpl(args, args[1], 2, status.GetMakefile());
+}
+
+bool joinImpl(std::vector<std::string> const& args, std::string const& glue,
+ const size_t varIdx, cmMakefile& makefile)
+{
+ std::string const& variableName = args[varIdx];
+ // NOTE Items to concat/join placed right after the variable for
+ // both `CONCAT` and `JOIN` sub-commands.
+ std::string value = cmJoin(cmMakeRange(args).advance(varIdx + 1), glue);
+
+ makefile.AddDefinition(variableName, value);
return true;
}
-bool cmStringCommand::HandleMakeCIdentifierCommand(
- std::vector<std::string> const& args)
+bool HandleMakeCIdentifierCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() != 3) {
- this->SetError("sub-command MAKE_C_IDENTIFIER requires two arguments.");
+ status.SetError("sub-command MAKE_C_IDENTIFIER requires two arguments.");
return false;
}
const std::string& input = args[1];
const std::string& variableName = args[2];
- this->Makefile->AddDefinition(variableName,
- cmSystemTools::MakeCidentifier(input).c_str());
+ status.GetMakefile().AddDefinition(variableName,
+ cmSystemTools::MakeCidentifier(input));
return true;
}
-bool cmStringCommand::HandleGenexStripCommand(
- std::vector<std::string> const& args)
+bool HandleGenexStripCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() != 3) {
- this->SetError("sub-command GENEX_STRIP requires two arguments.");
+ status.SetError("sub-command GENEX_STRIP requires two arguments.");
return false;
}
@@ -686,14 +614,15 @@ bool cmStringCommand::HandleGenexStripCommand(
const std::string& variableName = args[2];
- this->Makefile->AddDefinition(variableName, result.c_str());
+ status.GetMakefile().AddDefinition(variableName, result);
return true;
}
-bool cmStringCommand::HandleStripCommand(std::vector<std::string> const& args)
+bool HandleStripCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() != 3) {
- this->SetError("sub-command STRIP requires two arguments.");
+ status.SetError("sub-command STRIP requires two arguments.");
return false;
}
@@ -725,15 +654,71 @@ bool cmStringCommand::HandleStripCommand(std::vector<std::string> const& args)
outLength = endPos - startPos + 1;
}
- this->Makefile->AddDefinition(
- variableName, stringValue.substr(startPos, outLength).c_str());
+ status.GetMakefile().AddDefinition(variableName,
+ stringValue.substr(startPos, outLength));
+ return true;
+}
+
+bool HandleRepeatCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ cmMakefile& makefile = status.GetMakefile();
+
+ // `string(REPEAT "<str>" <times> OUTPUT_VARIABLE)`
+ enum ArgPos : std::size_t
+ {
+ SUB_COMMAND,
+ VALUE,
+ TIMES,
+ OUTPUT_VARIABLE,
+ TOTAL_ARGS
+ };
+
+ if (args.size() != ArgPos::TOTAL_ARGS) {
+ makefile.IssueMessage(MessageType::FATAL_ERROR,
+ "sub-command REPEAT requires three arguments.");
+ return true;
+ }
+
+ unsigned long times;
+ if (!cmStrToULong(args[ArgPos::TIMES], &times)) {
+ makefile.IssueMessage(MessageType::FATAL_ERROR,
+ "repeat count is not a positive number.");
+ return true;
+ }
+
+ const auto& stringValue = args[ArgPos::VALUE];
+ const auto& variableName = args[ArgPos::OUTPUT_VARIABLE];
+ const auto inStringLength = stringValue.size();
+
+ std::string result;
+ switch (inStringLength) {
+ case 0u:
+ // Nothing to do for zero length input strings
+ break;
+ case 1u:
+ // NOTE If the string to repeat consists of the only character,
+ // use the appropriate constructor.
+ result = std::string(times, stringValue[0]);
+ break;
+ default:
+ result = std::string(inStringLength * times, char{});
+ for (auto i = 0u; i < times; ++i) {
+ std::copy(cm::cbegin(stringValue), cm::cend(stringValue),
+ &result[i * inStringLength]);
+ }
+ break;
+ }
+
+ makefile.AddDefinition(variableName, result);
return true;
}
-bool cmStringCommand::HandleRandomCommand(std::vector<std::string> const& args)
+bool HandleRandomCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2 || args.size() == 3 || args.size() == 5) {
- this->SetError("sub-command RANDOM requires at least one argument.");
+ status.SetError("sub-command RANDOM requires at least one argument.");
return false;
}
@@ -770,14 +755,14 @@ bool cmStringCommand::HandleRandomCommand(std::vector<std::string> const& args)
double sizeofAlphabet = static_cast<double>(alphabet.size());
if (sizeofAlphabet < 1) {
- this->SetError("sub-command RANDOM invoked with bad alphabet.");
+ status.SetError("sub-command RANDOM invoked with bad alphabet.");
return false;
}
if (length < 1) {
- this->SetError("sub-command RANDOM invoked with bad length.");
+ status.SetError("sub-command RANDOM invoked with bad length.");
return false;
}
- const std::string& variableName = args[args.size() - 1];
+ const std::string& variableName = args.back();
std::vector<char> result;
@@ -787,26 +772,25 @@ bool cmStringCommand::HandleRandomCommand(std::vector<std::string> const& args)
}
const char* alphaPtr = alphabet.c_str();
- int cc;
- for (cc = 0; cc < length; cc++) {
- int idx = (int)(sizeofAlphabet * rand() / (RAND_MAX + 1.0));
+ for (int cc = 0; cc < length; cc++) {
+ int idx = static_cast<int>(sizeofAlphabet * rand() / (RAND_MAX + 1.0));
result.push_back(*(alphaPtr + idx));
}
result.push_back(0);
- this->Makefile->AddDefinition(variableName, &*result.begin());
+ status.GetMakefile().AddDefinition(variableName, result.data());
return true;
}
-bool cmStringCommand::HandleTimestampCommand(
- std::vector<std::string> const& args)
+bool HandleTimestampCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("sub-command TIMESTAMP requires at least one argument.");
+ status.SetError("sub-command TIMESTAMP requires at least one argument.");
return false;
}
if (args.size() > 4) {
- this->SetError("sub-command TIMESTAMP takes at most three arguments.");
+ status.SetError("sub-command TIMESTAMP takes at most three arguments.");
return false;
}
@@ -826,25 +810,26 @@ bool cmStringCommand::HandleTimestampCommand(
} else {
std::string e = " TIMESTAMP sub-command does not recognize option " +
args[argsIndex] + ".";
- this->SetError(e);
+ status.SetError(e);
return false;
}
}
cmTimestamp timestamp;
std::string result = timestamp.CurrentTime(formatString, utcFlag);
- this->Makefile->AddDefinition(outputVariable, result.c_str());
+ status.GetMakefile().AddDefinition(outputVariable, result);
return true;
}
-bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args)
+bool HandleUuidCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
unsigned int argsIndex = 1;
if (args.size() < 2) {
- this->SetError("UUID sub-command requires an output variable.");
+ status.SetError("UUID sub-command requires an output variable.");
return false;
}
@@ -859,21 +844,21 @@ bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args)
if (args[argsIndex] == "NAMESPACE") {
++argsIndex;
if (argsIndex >= args.size()) {
- this->SetError("UUID sub-command, NAMESPACE requires a value.");
+ status.SetError("UUID sub-command, NAMESPACE requires a value.");
return false;
}
uuidNamespaceString = args[argsIndex++];
} else if (args[argsIndex] == "NAME") {
++argsIndex;
if (argsIndex >= args.size()) {
- this->SetError("UUID sub-command, NAME requires a value.");
+ status.SetError("UUID sub-command, NAME requires a value.");
return false;
}
uuidName = args[argsIndex++];
} else if (args[argsIndex] == "TYPE") {
++argsIndex;
if (argsIndex >= args.size()) {
- this->SetError("UUID sub-command, TYPE requires a value.");
+ status.SetError("UUID sub-command, TYPE requires a value.");
return false;
}
uuidType = args[argsIndex++];
@@ -883,7 +868,7 @@ bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args)
} else {
std::string e =
"UUID sub-command does not recognize option " + args[argsIndex] + ".";
- this->SetError(e);
+ status.SetError(e);
return false;
}
}
@@ -893,7 +878,7 @@ bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args)
std::vector<unsigned char> uuidNamespace;
if (!uuidGenerator.StringToBinary(uuidNamespaceString, uuidNamespace)) {
- this->SetError("UUID sub-command, malformed NAMESPACE UUID.");
+ status.SetError("UUID sub-command, malformed NAMESPACE UUID.");
return false;
}
@@ -903,12 +888,12 @@ bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args)
uuid = uuidGenerator.FromSha1(uuidNamespace, uuidName);
} else {
std::string e = "UUID sub-command, unknown TYPE '" + uuidType + "'.";
- this->SetError(e);
+ status.SetError(e);
return false;
}
if (uuid.empty()) {
- this->SetError("UUID sub-command, generation failed.");
+ status.SetError("UUID sub-command, generation failed.");
return false;
}
@@ -916,12 +901,57 @@ bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args)
uuid = cmSystemTools::UpperCase(uuid);
}
- this->Makefile->AddDefinition(outputVariable, uuid.c_str());
+ status.GetMakefile().AddDefinition(outputVariable, uuid);
return true;
#else
- std::ostringstream e;
- e << args[0] << " not available during bootstrap";
- this->SetError(e.str().c_str());
+ status.SetError(cmStrCat(args[0], " not available during bootstrap"));
return false;
#endif
}
+
+} // namespace
+
+bool cmStringCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ if (args.empty()) {
+ status.SetError("must be called with at least one argument.");
+ return false;
+ }
+
+ static cmSubcommandTable const subcommand{
+ { "REGEX"_s, HandleRegexCommand },
+ { "REPLACE"_s, HandleReplaceCommand },
+ { "MD5"_s, HandleHashCommand },
+ { "SHA1"_s, HandleHashCommand },
+ { "SHA224"_s, HandleHashCommand },
+ { "SHA256"_s, HandleHashCommand },
+ { "SHA384"_s, HandleHashCommand },
+ { "SHA512"_s, HandleHashCommand },
+ { "SHA3_224"_s, HandleHashCommand },
+ { "SHA3_256"_s, HandleHashCommand },
+ { "SHA3_384"_s, HandleHashCommand },
+ { "SHA3_512"_s, HandleHashCommand },
+ { "TOLOWER"_s, HandleToLowerCommand },
+ { "TOUPPER"_s, HandleToUpperCommand },
+ { "COMPARE"_s, HandleCompareCommand },
+ { "ASCII"_s, HandleAsciiCommand },
+ { "CONFIGURE"_s, HandleConfigureCommand },
+ { "LENGTH"_s, HandleLengthCommand },
+ { "APPEND"_s, HandleAppendCommand },
+ { "PREPEND"_s, HandlePrependCommand },
+ { "CONCAT"_s, HandleConcatCommand },
+ { "JOIN"_s, HandleJoinCommand },
+ { "SUBSTRING"_s, HandleSubstringCommand },
+ { "STRIP"_s, HandleStripCommand },
+ { "REPEAT"_s, HandleRepeatCommand },
+ { "RANDOM"_s, HandleRandomCommand },
+ { "FIND"_s, HandleFindCommand },
+ { "TIMESTAMP"_s, HandleTimestampCommand },
+ { "MAKE_C_IDENTIFIER"_s, HandleMakeCIdentifierCommand },
+ { "GENEX_STRIP"_s, HandleGenexStripCommand },
+ { "UUID"_s, HandleUuidCommand },
+ };
+
+ return subcommand(args[0], args, status);
+}
diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h
index 88015ad5e..bd71ba293 100644
--- a/Source/cmStringCommand.h
+++ b/Source/cmStringCommand.h
@@ -3,80 +3,18 @@
#ifndef cmStringCommand_h
#define cmStringCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmStringCommand
+/**
* \brief Common string operations
*
*/
-class cmStringCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmStringCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-protected:
- bool HandleConfigureCommand(std::vector<std::string> const& args);
- bool HandleAsciiCommand(std::vector<std::string> const& args);
- bool HandleRegexCommand(std::vector<std::string> const& args);
- bool RegexMatch(std::vector<std::string> const& args);
- bool RegexMatchAll(std::vector<std::string> const& args);
- bool RegexReplace(std::vector<std::string> const& args);
- bool HandleHashCommand(std::vector<std::string> const& args);
- bool HandleToUpperLowerCommand(std::vector<std::string> const& args,
- bool toUpper);
- bool HandleCompareCommand(std::vector<std::string> const& args);
- bool HandleReplaceCommand(std::vector<std::string> const& args);
- bool HandleLengthCommand(std::vector<std::string> const& args);
- bool HandleSubstringCommand(std::vector<std::string> const& args);
- bool HandleAppendCommand(std::vector<std::string> const& args);
- bool HandleConcatCommand(std::vector<std::string> const& args);
- bool HandleStripCommand(std::vector<std::string> const& args);
- bool HandleRandomCommand(std::vector<std::string> const& args);
- bool HandleFindCommand(std::vector<std::string> const& args);
- bool HandleTimestampCommand(std::vector<std::string> const& args);
- bool HandleMakeCIdentifierCommand(std::vector<std::string> const& args);
- bool HandleGenexStripCommand(std::vector<std::string> const& args);
- bool HandleUuidCommand(std::vector<std::string> const& args);
-
- class RegexReplacement
- {
- public:
- RegexReplacement(const char* s)
- : number(-1)
- , value(s)
- {
- }
- RegexReplacement(const std::string& s)
- : number(-1)
- , value(s)
- {
- }
- RegexReplacement(int n)
- : number(n)
- , value()
- {
- }
- RegexReplacement() {}
- int number;
- std::string value;
- };
-};
+bool cmStringCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmStringReplaceHelper.cxx b/Source/cmStringReplaceHelper.cxx
new file mode 100644
index 000000000..998c135e8
--- /dev/null
+++ b/Source/cmStringReplaceHelper.cxx
@@ -0,0 +1,121 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmStringReplaceHelper.h"
+
+#include <sstream>
+#include <utility>
+
+#include "cmMakefile.h"
+
+cmStringReplaceHelper::cmStringReplaceHelper(const std::string& regex,
+ std::string replace_expr,
+ cmMakefile* makefile)
+ : RegExString(regex)
+ , RegularExpression(regex)
+ , ReplaceExpression(std::move(replace_expr))
+ , Makefile(makefile)
+{
+ this->ParseReplaceExpression();
+}
+
+bool cmStringReplaceHelper::Replace(const std::string& input,
+ std::string& output)
+{
+ output.clear();
+
+ // Scan through the input for all matches.
+ std::string::size_type base = 0;
+ while (this->RegularExpression.find(input.c_str() + base)) {
+ if (this->Makefile != nullptr) {
+ this->Makefile->ClearMatches();
+ this->Makefile->StoreMatches(this->RegularExpression);
+ }
+ auto l2 = this->RegularExpression.start();
+ auto r = this->RegularExpression.end();
+
+ // Concatenate the part of the input that was not matched.
+ output += input.substr(base, l2);
+
+ // Make sure the match had some text.
+ if (r - l2 == 0) {
+ std::ostringstream error;
+ error << "regex \"" << this->RegExString << "\" matched an empty string";
+ this->ErrorString = error.str();
+ return false;
+ }
+
+ // Concatenate the replacement for the match.
+ for (const auto& replacement : this->Replacements) {
+ if (replacement.Number < 0) {
+ // This is just a plain-text part of the replacement.
+ output += replacement.Value;
+ } else {
+ // Replace with part of the match.
+ auto n = replacement.Number;
+ auto start = this->RegularExpression.start(n);
+ auto end = this->RegularExpression.end(n);
+ auto len = input.length() - base;
+ if ((start != std::string::npos) && (end != std::string::npos) &&
+ (start <= len) && (end <= len)) {
+ output += input.substr(base + start, end - start);
+ } else {
+ std::ostringstream error;
+ error << "replace expression \"" << this->ReplaceExpression
+ << "\" contains an out-of-range escape for regex \""
+ << this->RegExString << "\"";
+ this->ErrorString = error.str();
+ return false;
+ }
+ }
+ }
+
+ // Move past the match.
+ base += r;
+ }
+
+ // Concatenate the text after the last match.
+ output += input.substr(base, input.length() - base);
+
+ return true;
+}
+
+void cmStringReplaceHelper::ParseReplaceExpression()
+{
+ std::string::size_type l = 0;
+ while (l < this->ReplaceExpression.length()) {
+ auto r = this->ReplaceExpression.find('\\', l);
+ if (r == std::string::npos) {
+ r = this->ReplaceExpression.length();
+ this->Replacements.emplace_back(
+ this->ReplaceExpression.substr(l, r - l));
+ } else {
+ if (r - l > 0) {
+ this->Replacements.emplace_back(
+ this->ReplaceExpression.substr(l, r - l));
+ }
+ if (r == (this->ReplaceExpression.length() - 1)) {
+ this->ValidReplaceExpression = false;
+ this->ErrorString = "replace-expression ends in a backslash";
+ return;
+ }
+ if ((this->ReplaceExpression[r + 1] >= '0') &&
+ (this->ReplaceExpression[r + 1] <= '9')) {
+ this->Replacements.emplace_back(this->ReplaceExpression[r + 1] - '0');
+ } else if (this->ReplaceExpression[r + 1] == 'n') {
+ this->Replacements.emplace_back("\n");
+ } else if (this->ReplaceExpression[r + 1] == '\\') {
+ this->Replacements.emplace_back("\\");
+ } else {
+ this->ValidReplaceExpression = false;
+ std::ostringstream error;
+ error << "Unknown escape \"" << this->ReplaceExpression.substr(r, 2)
+ << "\" in replace-expression";
+ this->ErrorString = error.str();
+ return;
+ }
+ r += 2;
+ }
+ l = r;
+ }
+}
diff --git a/Source/cmStringReplaceHelper.h b/Source/cmStringReplaceHelper.h
new file mode 100644
index 000000000..74d481d70
--- /dev/null
+++ b/Source/cmStringReplaceHelper.h
@@ -0,0 +1,68 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmStringReplaceHelper_h
+#define cmStringReplaceHelper_h
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cmsys/RegularExpression.hxx"
+
+class cmMakefile;
+
+class cmStringReplaceHelper
+{
+public:
+ cmStringReplaceHelper(const std::string& regex, std::string replace_expr,
+ cmMakefile* makefile = nullptr);
+
+ bool IsRegularExpressionValid() const
+ {
+ return this->RegularExpression.is_valid();
+ }
+ bool IsReplaceExpressionValid() const
+ {
+ return this->ValidReplaceExpression;
+ }
+
+ bool Replace(const std::string& input, std::string& output);
+
+ const std::string& GetError() { return this->ErrorString; }
+
+private:
+ class RegexReplacement
+ {
+ public:
+ RegexReplacement(const char* s)
+ : Number(-1)
+ , Value(s)
+ {
+ }
+ RegexReplacement(std::string s)
+ : Number(-1)
+ , Value(std::move(s))
+ {
+ }
+ RegexReplacement(int n)
+ : Number(n)
+ {
+ }
+ RegexReplacement() = default;
+
+ int Number;
+ std::string Value;
+ };
+
+ void ParseReplaceExpression();
+
+ std::string ErrorString;
+ std::string RegExString;
+ cmsys::RegularExpression RegularExpression;
+ bool ValidReplaceExpression = true;
+ std::string ReplaceExpression;
+ std::vector<RegexReplacement> Replacements;
+ cmMakefile* Makefile = nullptr;
+};
+
+#endif
diff --git a/Source/cmSubcommandTable.cxx b/Source/cmSubcommandTable.cxx
new file mode 100644
index 000000000..f6194f816
--- /dev/null
+++ b/Source/cmSubcommandTable.cxx
@@ -0,0 +1,31 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmSubcommandTable.h"
+
+#include <algorithm>
+
+#include "cmExecutionStatus.h"
+#include "cmStringAlgorithms.h"
+
+cmSubcommandTable::cmSubcommandTable(std::initializer_list<InitElem> init)
+ : Impl(init.begin(), init.end())
+{
+ std::sort(this->Impl.begin(), this->Impl.end(),
+ [](Elem const& left, Elem const& right) {
+ return left.first < right.first;
+ });
+}
+
+bool cmSubcommandTable::operator()(cm::string_view key,
+ std::vector<std::string> const& args,
+ cmExecutionStatus& status) const
+{
+ auto const it = std::lower_bound(
+ this->Impl.begin(), this->Impl.end(), key,
+ [](Elem const& elem, cm::string_view k) { return elem.first < k; });
+ if (it != this->Impl.end() && it->first == key) {
+ return it->second(args, status);
+ }
+ status.SetError(cmStrCat("does not recognize sub-command ", key));
+ return false;
+}
diff --git a/Source/cmSubcommandTable.h b/Source/cmSubcommandTable.h
new file mode 100644
index 000000000..65eb8c794
--- /dev/null
+++ b/Source/cmSubcommandTable.h
@@ -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. */
+#ifndef cmSubcommandTable_h
+#define cmSubcommandTable_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <initializer_list>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm/string_view>
+
+#include "cm_static_string_view.hxx"
+
+class cmExecutionStatus;
+
+class cmSubcommandTable
+{
+public:
+ using Command = bool (*)(std::vector<std::string> const&,
+ cmExecutionStatus&);
+
+ using Elem = std::pair<cm::string_view, Command>;
+ using InitElem = std::pair<cm::static_string_view, Command>;
+
+ cmSubcommandTable(std::initializer_list<InitElem> init);
+
+ bool operator()(cm::string_view key, std::vector<std::string> const& args,
+ cmExecutionStatus& status) const;
+
+private:
+ std::vector<Elem> Impl;
+};
+
+#endif
diff --git a/Source/cmSubdirCommand.cxx b/Source/cmSubdirCommand.cxx
index 3727dfa25..2477d7a33 100644
--- a/Source/cmSubdirCommand.cxx
+++ b/Source/cmSubdirCommand.cxx
@@ -2,53 +2,48 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSubdirCommand.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
-
-// cmSubdirCommand
-bool cmSubdirCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmSubdirCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
bool res = true;
bool excludeFromAll = false;
+ cmMakefile& mf = status.GetMakefile();
- for (std::vector<std::string>::const_iterator i = args.begin();
- i != args.end(); ++i) {
- if (*i == "EXCLUDE_FROM_ALL") {
+ for (std::string const& i : args) {
+ if (i == "EXCLUDE_FROM_ALL") {
excludeFromAll = true;
continue;
}
- if (*i == "PREORDER") {
+ if (i == "PREORDER") {
// Ignored
continue;
}
// if they specified a relative path then compute the full
- std::string srcPath =
- std::string(this->Makefile->GetCurrentSourceDirectory()) + "/" + *i;
+ std::string srcPath = mf.GetCurrentSourceDirectory() + "/" + i;
if (cmSystemTools::FileIsDirectory(srcPath)) {
- std::string binPath =
- std::string(this->Makefile->GetCurrentBinaryDirectory()) + "/" + *i;
- this->Makefile->AddSubDirectory(srcPath, binPath, excludeFromAll, false);
+ std::string binPath = mf.GetCurrentBinaryDirectory() + "/" + i;
+ mf.AddSubDirectory(srcPath, binPath, excludeFromAll, false);
}
// otherwise it is a full path
- else if (cmSystemTools::FileIsDirectory(*i)) {
+ else if (cmSystemTools::FileIsDirectory(i)) {
// we must compute the binPath from the srcPath, we just take the last
// element from the source path and use that
- std::string binPath =
- std::string(this->Makefile->GetCurrentBinaryDirectory()) + "/" +
- cmSystemTools::GetFilenameName(*i);
- this->Makefile->AddSubDirectory(*i, binPath, excludeFromAll, false);
+ std::string binPath = mf.GetCurrentBinaryDirectory() + "/" +
+ cmSystemTools::GetFilenameName(i);
+ mf.AddSubDirectory(i, binPath, excludeFromAll, false);
} else {
- std::string error = "Incorrect SUBDIRS command. Directory: ";
- error += *i + " does not exist.";
- this->SetError(error);
+ status.SetError(cmStrCat("Incorrect SUBDIRS command. Directory: ", i,
+ " does not exist."));
res = false;
}
}
diff --git a/Source/cmSubdirCommand.h b/Source/cmSubdirCommand.h
index a2af0fd58..3254e842e 100644
--- a/Source/cmSubdirCommand.h
+++ b/Source/cmSubdirCommand.h
@@ -3,36 +3,14 @@
#ifndef cmSubdirCommand_h
#define cmSubdirCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmSubdirCommand
- * \brief Specify a list of subdirectories to build.
- *
- * cmSubdirCommand specifies a list of subdirectories to process
- * by CMake. For each subdirectory listed, CMake will descend
- * into that subdirectory and process any CMakeLists.txt found.
- */
-class cmSubdirCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmSubdirCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmSubdirCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmSubdirDependsCommand.cxx b/Source/cmSubdirDependsCommand.cxx
index 0bb2c0ac4..496c60da7 100644
--- a/Source/cmSubdirDependsCommand.cxx
+++ b/Source/cmSubdirDependsCommand.cxx
@@ -4,8 +4,8 @@
class cmExecutionStatus;
-bool cmSubdirDependsCommand::InitialPass(std::vector<std::string> const&,
- cmExecutionStatus&)
+bool cmSubdirDependsCommand(std::vector<std::string> const&,
+ cmExecutionStatus&)
{
return true;
}
diff --git a/Source/cmSubdirDependsCommand.h b/Source/cmSubdirDependsCommand.h
index d8ea9284f..bf99bd17d 100644
--- a/Source/cmSubdirDependsCommand.h
+++ b/Source/cmSubdirDependsCommand.h
@@ -3,21 +3,14 @@
#ifndef cmSubdirDependsCommand_h
#define cmSubdirDependsCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmSubdirDependsCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE { return new cmSubdirDependsCommand; }
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmSubdirDependsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index f7192e0b6..c4a4220f8 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -2,164 +2,137 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSystemTools.h"
+#include "cm_uv.h"
+
#include "cmAlgorithms.h"
+#include "cmDuration.h"
#include "cmProcessOutput.h"
-#include "cm_sys_stat.h"
-
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmArchiveWrite.h"
-#include "cmLocale.h"
-#include "cm_libarchive.h"
-#ifndef __LA_INT64_T
-#define __LA_INT64_T la_int64_t
-#endif
+#include "cmRange.h"
+#include "cmStringAlgorithms.h"
+
+#if !defined(CMAKE_BOOTSTRAP)
+# include "cm_libarchive.h"
+
+# include "cmArchiveWrite.h"
+# include "cmLocale.h"
+# ifndef __LA_INT64_T
+# define __LA_INT64_T la_int64_t
+# endif
+# ifndef __LA_SSIZE_T
+# define __LA_SSIZE_T la_ssize_t
+# endif
#endif
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmCryptoHash.h"
+#if !defined(CMAKE_BOOTSTRAP)
+# include "cmCryptoHash.h"
#endif
#if defined(CMAKE_USE_ELF_PARSER)
-#include "cmELF.h"
+# include "cmELF.h"
#endif
#if defined(CMAKE_USE_MACH_PARSER)
-#include "cmMachO.h"
+# include "cmMachO.h"
#endif
+#include <algorithm>
+#include <cassert>
+#include <cctype>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <iostream>
+#include <sstream>
+#include <utility>
+#include <vector>
+
+#include <fcntl.h>
+
#include "cmsys/Directory.hxx"
#include "cmsys/Encoding.hxx"
#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"
#include "cmsys/System.h"
#include "cmsys/Terminal.h"
-#include <algorithm>
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <iostream>
-#include <set>
-#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <utility>
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
// include wincrypt.h after windows.h
-#include <wincrypt.h>
+# include <wincrypt.h>
#else
-#include <sys/time.h>
-#include <unistd.h>
-#include <utime.h>
+# include <unistd.h>
+
+# include <sys/time.h>
#endif
#if defined(_WIN32) && \
(defined(_MSC_VER) || defined(__WATCOMC__) || defined(__MINGW32__))
-#include <io.h>
+# include <io.h>
#endif
#if defined(__APPLE__)
-#include <mach-o/dyld.h>
+# include <mach-o/dyld.h>
#endif
#ifdef __QNX__
-#include <malloc.h> /* for malloc/free on QNX */
+# include <malloc.h> /* for malloc/free on QNX */
#endif
-static bool cm_isspace(char c)
-{
- return ((c & 0x80) == 0) && isspace(c);
-}
+namespace {
-class cmSystemToolsFileTime
-{
-public:
-#if defined(_WIN32) && !defined(__CYGWIN__)
- FILETIME timeCreation;
- FILETIME timeLastAccess;
- FILETIME timeLastWrite;
-#else
- struct utimbuf timeBuf;
-#endif
-};
+cmSystemTools::InterruptCallback s_InterruptCallback;
+cmSystemTools::MessageCallback s_MessageCallback;
+cmSystemTools::OutputCallback s_StderrCallback;
+cmSystemTools::OutputCallback s_StdoutCallback;
+
+} // namespace
#if !defined(HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE)
// For GetEnvironmentVariables
-#if defined(_WIN32)
+# if defined(_WIN32)
extern __declspec(dllimport) char** environ;
-#else
+# else
extern char** environ;
-#endif
+# endif
#endif
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
static std::string cm_archive_entry_pathname(struct archive_entry* entry)
{
-#if cmsys_STL_HAS_WSTRING
+# if cmsys_STL_HAS_WSTRING
return cmsys::Encoding::ToNarrow(archive_entry_pathname_w(entry));
-#else
+# else
return archive_entry_pathname(entry);
-#endif
+# endif
}
static int cm_archive_read_open_file(struct archive* a, const char* file,
int block_size)
{
-#if cmsys_STL_HAS_WSTRING
+# if cmsys_STL_HAS_WSTRING
std::wstring wfile = cmsys::Encoding::ToWide(file);
return archive_read_open_filename_w(a, wfile.c_str(), block_size);
-#else
+# else
return archive_read_open_filename(a, file, block_size);
-#endif
+# endif
}
#endif
#ifdef _WIN32
-class cmSystemToolsWindowsHandle
-{
-public:
- cmSystemToolsWindowsHandle(HANDLE h)
- : handle_(h)
- {
- }
- ~cmSystemToolsWindowsHandle()
- {
- if (this->handle_ != INVALID_HANDLE_VALUE) {
- CloseHandle(this->handle_);
- }
- }
- operator bool() const { return this->handle_ != INVALID_HANDLE_VALUE; }
- bool operator!() const { return this->handle_ == INVALID_HANDLE_VALUE; }
- operator HANDLE() const { return this->handle_; }
-
-private:
- HANDLE handle_;
-};
#elif defined(__APPLE__)
-#include <crt_externs.h>
+# include <crt_externs.h>
-#define environ (*_NSGetEnviron())
+# define environ (*_NSGetEnviron())
#endif
bool cmSystemTools::s_RunCommandHideConsole = false;
bool cmSystemTools::s_DisableRunCommandOutput = false;
bool cmSystemTools::s_ErrorOccured = false;
bool cmSystemTools::s_FatalErrorOccured = false;
-bool cmSystemTools::s_DisableMessages = false;
bool cmSystemTools::s_ForceUnixPaths = false;
-cmSystemTools::MessageCallback cmSystemTools::s_MessageCallback;
-cmSystemTools::OutputCallback cmSystemTools::s_StdoutCallback;
-cmSystemTools::OutputCallback cmSystemTools::s_StderrCallback;
-cmSystemTools::InterruptCallback cmSystemTools::s_InterruptCallback;
-void* cmSystemTools::s_MessageCallbackClientData;
-void* cmSystemTools::s_StdoutCallbackClientData;
-void* cmSystemTools::s_StderrCallbackClientData;
-void* cmSystemTools::s_InterruptCallbackClientData;
-
// replace replace with with as many times as it shows up in source.
// write the result into source.
#if defined(_WIN32) && !defined(__CYGWIN__)
@@ -179,12 +152,10 @@ void cmSystemTools::ExpandRegistryValues(std::string& source, KeyWOW64 view)
std::string key = regEntry.match(1);
std::string val;
if (ReadRegistryValue(key.c_str(), val, view)) {
- std::string reg = "[";
- reg += key + "]";
+ std::string reg = cmStrCat('[', key, ']');
cmSystemTools::ReplaceString(source, reg.c_str(), val.c_str());
} else {
- std::string reg = "[";
- reg += key + "]";
+ std::string reg = cmStrCat('[', key, ']');
cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
}
}
@@ -197,227 +168,87 @@ void cmSystemTools::ExpandRegistryValues(std::string& source,
while (regEntry.find(source)) {
// the arguments are the second match
std::string key = regEntry.match(1);
- std::string reg = "[";
- reg += key + "]";
+ std::string reg = cmStrCat('[', key, ']');
cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
}
}
#endif
-std::string cmSystemTools::EscapeQuotes(const std::string& str)
-{
- std::string result;
- result.reserve(str.size());
- for (const char* ch = str.c_str(); *ch != '\0'; ++ch) {
- if (*ch == '"') {
- result += '\\';
- }
- result += *ch;
- }
- return result;
-}
-
-std::string cmSystemTools::HelpFileName(std::string name)
+std::string cmSystemTools::HelpFileName(cm::string_view str)
{
+ std::string name(str);
cmSystemTools::ReplaceString(name, "<", "");
cmSystemTools::ReplaceString(name, ">", "");
return name;
}
-std::string cmSystemTools::TrimWhitespace(const std::string& s)
-{
- std::string::const_iterator start = s.begin();
- while (start != s.end() && cm_isspace(*start)) {
- ++start;
- }
- if (start == s.end()) {
- return "";
- }
- std::string::const_iterator stop = s.end() - 1;
- while (cm_isspace(*stop)) {
- --stop;
- }
- return std::string(start, stop + 1);
-}
-
-void cmSystemTools::Error(const char* m1, const char* m2, const char* m3,
- const char* m4)
+void cmSystemTools::Error(const std::string& m)
{
- std::string message = "CMake Error: ";
- if (m1) {
- message += m1;
- }
- if (m2) {
- message += m2;
- }
- if (m3) {
- message += m3;
- }
- if (m4) {
- message += m4;
- }
+ std::string message = "CMake Error: " + m;
cmSystemTools::s_ErrorOccured = true;
- cmSystemTools::Message(message.c_str(), "Error");
+ cmSystemTools::Message(message, "Error");
}
-void cmSystemTools::SetInterruptCallback(InterruptCallback f, void* clientData)
+void cmSystemTools::SetInterruptCallback(InterruptCallback f)
{
- s_InterruptCallback = f;
- s_InterruptCallbackClientData = clientData;
+ s_InterruptCallback = std::move(f);
}
bool cmSystemTools::GetInterruptFlag()
{
if (s_InterruptCallback) {
- return (*s_InterruptCallback)(s_InterruptCallbackClientData);
+ return s_InterruptCallback();
}
return false;
}
-void cmSystemTools::SetMessageCallback(MessageCallback f, void* clientData)
-{
- s_MessageCallback = f;
- s_MessageCallbackClientData = clientData;
-}
-
-void cmSystemTools::SetStdoutCallback(OutputCallback f, void* clientData)
-{
- s_StdoutCallback = f;
- s_StdoutCallbackClientData = clientData;
-}
-
-void cmSystemTools::SetStderrCallback(OutputCallback f, void* clientData)
+void cmSystemTools::SetMessageCallback(MessageCallback f)
{
- s_StderrCallback = f;
- s_StderrCallbackClientData = clientData;
+ s_MessageCallback = std::move(f);
}
-void cmSystemTools::Stdout(const char* s)
+void cmSystemTools::SetStdoutCallback(OutputCallback f)
{
- cmSystemTools::Stdout(s, strlen(s));
+ s_StdoutCallback = std::move(f);
}
-void cmSystemTools::Stderr(const char* s)
+void cmSystemTools::SetStderrCallback(OutputCallback f)
{
- cmSystemTools::Stderr(s, strlen(s));
+ s_StderrCallback = std::move(f);
}
-void cmSystemTools::Stderr(const char* s, size_t length)
+void cmSystemTools::Stderr(const std::string& s)
{
if (s_StderrCallback) {
- (*s_StderrCallback)(s, length, s_StderrCallbackClientData);
+ s_StderrCallback(s);
} else {
- std::cerr.write(s, length);
- std::cerr.flush();
+ std::cerr << s << std::flush;
}
}
-void cmSystemTools::Stdout(const char* s, size_t length)
+void cmSystemTools::Stdout(const std::string& s)
{
if (s_StdoutCallback) {
- (*s_StdoutCallback)(s, length, s_StdoutCallbackClientData);
+ s_StdoutCallback(s);
} else {
- std::cout.write(s, length);
- std::cout.flush();
+ std::cout << s << std::flush;
}
}
-void cmSystemTools::Message(const char* m1, const char* title)
+void cmSystemTools::Message(const std::string& m, const char* title)
{
- if (s_DisableMessages) {
- return;
- }
if (s_MessageCallback) {
- (*s_MessageCallback)(m1, title, s_DisableMessages,
- s_MessageCallbackClientData);
- return;
+ s_MessageCallback(m, title);
+ } else {
+ std::cerr << m << std::endl;
}
- std::cerr << m1 << std::endl << std::flush;
}
void cmSystemTools::ReportLastSystemError(const char* msg)
{
- std::string m = msg;
- m += ": System Error: ";
- m += Superclass::GetLastSystemError();
- cmSystemTools::Error(m.c_str());
-}
-
-bool cmSystemTools::IsInternallyOn(const char* val)
-{
- if (!val) {
- return false;
- }
- std::string v = val;
- if (v.size() > 4) {
- return false;
- }
-
- for (std::string::iterator c = v.begin(); c != v.end(); c++) {
- *c = static_cast<char>(toupper(*c));
- }
- return v == "I_ON";
-}
-
-bool cmSystemTools::IsOn(const char* val)
-{
- if (!val) {
- return false;
- }
- size_t len = strlen(val);
- if (len > 4) {
- return false;
- }
- std::string v(val, len);
-
- static std::set<std::string> onValues;
- if (onValues.empty()) {
- onValues.insert("ON");
- onValues.insert("1");
- onValues.insert("YES");
- onValues.insert("TRUE");
- onValues.insert("Y");
- }
- for (std::string::iterator c = v.begin(); c != v.end(); c++) {
- *c = static_cast<char>(toupper(*c));
- }
- return (onValues.count(v) > 0);
-}
-
-bool cmSystemTools::IsNOTFOUND(const char* val)
-{
- if (strcmp(val, "NOTFOUND") == 0) {
- return true;
- }
- return cmHasLiteralSuffix(val, "-NOTFOUND");
-}
-
-bool cmSystemTools::IsOff(const char* val)
-{
- if (!val || !*val) {
- return true;
- }
- size_t len = strlen(val);
- // Try and avoid toupper() for large strings.
- if (len > 6) {
- return cmSystemTools::IsNOTFOUND(val);
- }
-
- static std::set<std::string> offValues;
- if (offValues.empty()) {
- offValues.insert("OFF");
- offValues.insert("0");
- offValues.insert("NO");
- offValues.insert("FALSE");
- offValues.insert("N");
- offValues.insert("IGNORE");
- }
- // Try and avoid toupper().
- std::string v(val, len);
- for (std::string::iterator c = v.begin(); c != v.end(); c++) {
- *c = static_cast<char>(toupper(*c));
- }
- return (offValues.count(v) > 0);
+ std::string m =
+ cmStrCat(msg, ": System Error: ", Superclass::GetLastSystemError());
+ cmSystemTools::Error(m);
}
void cmSystemTools::ParseWindowsCommandLine(const char* command,
@@ -453,12 +284,12 @@ void cmSystemTools::ParseWindowsCommandLine(const char* command,
} else {
arg.append(backslashes, '\\');
backslashes = 0;
- if (cm_isspace(*c)) {
+ if (cmIsSpace(*c)) {
if (in_quotes) {
arg.append(1, *c);
} else if (in_argument) {
args.push_back(arg);
- arg = "";
+ arg.clear();
in_argument = false;
}
} else {
@@ -489,10 +320,12 @@ public:
}
free(this->ArgV);
}
+ cmSystemToolsArgV(const cmSystemToolsArgV&) = delete;
+ cmSystemToolsArgV& operator=(const cmSystemToolsArgV&) = delete;
void Store(std::vector<std::string>& args) const
{
for (char** arg = this->ArgV; arg && *arg; ++arg) {
- args.push_back(*arg);
+ args.emplace_back(*arg);
}
}
};
@@ -501,7 +334,7 @@ void cmSystemTools::ParseUnixCommandLine(const char* command,
std::vector<std::string>& args)
{
// Invoke the underlying parser.
- cmSystemToolsArgV argv = cmsysSystem_Parse_CommandForUnix(command, 0);
+ cmSystemToolsArgV argv(cmsysSystem_Parse_CommandForUnix(command, 0));
argv.Store(args);
}
@@ -510,16 +343,14 @@ std::vector<std::string> cmSystemTools::HandleResponseFile(
std::vector<std::string>::const_iterator argEnd)
{
std::vector<std::string> arg_full;
- for (std::vector<std::string>::const_iterator a = argBeg; a != argEnd; ++a) {
- std::string const& arg = *a;
+ for (std::string const& arg : cmMakeRange(argBeg, argEnd)) {
if (cmHasLiteralPrefix(arg, "@")) {
cmsys::ifstream responseFile(arg.substr(1).c_str(), std::ios::in);
if (!responseFile) {
- std::string error = "failed to open for reading (";
- error += cmSystemTools::GetLastSystemError();
- error += "):\n ";
- error += arg.substr(1);
- cmSystemTools::Error(error.c_str());
+ std::string error = cmStrCat("failed to open for reading (",
+ cmSystemTools::GetLastSystemError(),
+ "):\n ", cm::string_view(arg).substr(1));
+ cmSystemTools::Error(error);
} else {
std::string line;
cmSystemTools::GetLineFromStream(responseFile, line);
@@ -529,7 +360,7 @@ std::vector<std::string> cmSystemTools::HandleResponseFile(
#else
cmSystemTools::ParseUnixCommandLine(line.c_str(), args2);
#endif
- arg_full.insert(arg_full.end(), args2.begin(), args2.end());
+ cmAppend(arg_full, args2);
}
} else {
arg_full.push_back(arg);
@@ -538,19 +369,21 @@ std::vector<std::string> cmSystemTools::HandleResponseFile(
return arg_full;
}
-std::vector<std::string> cmSystemTools::ParseArguments(const char* command)
+std::vector<std::string> cmSystemTools::ParseArguments(const std::string& cmd)
{
std::vector<std::string> args;
std::string arg;
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] == '\\')) {
+ const char* command = cmd.c_str();
+ 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.
@@ -559,7 +392,7 @@ std::vector<std::string> cmSystemTools::ParseArguments(const char* command)
while (*c == ' ' || *c == '\t') {
++c;
}
- arg = "";
+ arg.clear();
if (*c == '"') {
// Parse a quoted argument.
++c;
@@ -603,6 +436,56 @@ std::vector<std::string> cmSystemTools::ParseArguments(const char* command)
return args;
}
+bool cmSystemTools::SplitProgramFromArgs(std::string const& command,
+ std::string& program,
+ std::string& args)
+{
+ const char* c = command.c_str();
+
+ // Skip leading whitespace.
+ while (isspace(static_cast<unsigned char>(*c))) {
+ ++c;
+ }
+
+ // Parse one command-line element up to an unquoted space.
+ bool in_escape = false;
+ bool in_double = false;
+ bool in_single = false;
+ for (; *c; ++c) {
+ if (in_single) {
+ if (*c == '\'') {
+ in_single = false;
+ } else {
+ program += *c;
+ }
+ } else if (in_escape) {
+ in_escape = false;
+ program += *c;
+ } else if (*c == '\\') {
+ in_escape = true;
+ } else if (in_double) {
+ if (*c == '"') {
+ in_double = false;
+ } else {
+ program += *c;
+ }
+ } else if (*c == '"') {
+ in_double = true;
+ } else if (*c == '\'') {
+ in_single = true;
+ } else if (isspace(static_cast<unsigned char>(*c))) {
+ break;
+ } else {
+ program += *c;
+ }
+ }
+
+ // The remainder of the command line holds unparsed arguments.
+ args = c;
+
+ return !in_single && !in_escape && !in_double;
+}
+
size_t cmSystemTools::CalculateCommandLineLengthLimit()
{
size_t sz =
@@ -633,11 +516,11 @@ size_t cmSystemTools::CalculateCommandLineLengthLimit()
// We estimate the size of the environment block to be 1000.
// This isn't accurate at all, but leaves some headroom.
szArgMax = szArgMax < 1000 ? 0 : szArgMax - 1000;
-#if defined(_WIN32) || defined(__linux)
+# if defined(_WIN32) || defined(__linux)
sz = std::min(sz, static_cast<size_t>(szArgMax));
-#else
+# else
sz = static_cast<size_t>(szArgMax);
-#endif
+# endif
}
#endif
return sz;
@@ -647,17 +530,17 @@ 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;
- for (std::vector<std::string>::const_iterator a = command.begin();
- a != command.end(); ++a) {
- argv.push_back(a->c_str());
+ argv.reserve(command.size() + 1);
+ for (std::string const& cmd : command) {
+ argv.push_back(cmd.c_str());
}
- argv.push_back(CM_NULLPTR);
+ argv.push_back(nullptr);
cmsysProcess* cp = cmsysProcess_New();
- cmsysProcess_SetCommand(cp, &*argv.begin());
+ cmsysProcess_SetCommand(cp, argv.data());
cmsysProcess_SetWorkingDirectory(cp, dir);
if (cmSystemTools::GetRunCommandHideConsole()) {
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
@@ -666,16 +549,16 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
if (outputflag == OUTPUT_PASSTHROUGH) {
cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1);
cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1);
- captureStdOut = CM_NULLPTR;
- captureStdErr = CM_NULLPTR;
+ captureStdOut = nullptr;
+ captureStdErr = nullptr;
} else if (outputflag == OUTPUT_MERGE ||
(captureStdErr && captureStdErr == captureStdOut)) {
cmsysProcess_SetOption(cp, cmsysProcess_Option_MergeOutput, 1);
- captureStdErr = CM_NULLPTR;
+ captureStdErr = nullptr;
}
assert(!captureStdErr || captureStdErr != captureStdOut);
- cmsysProcess_SetTimeout(cp, timeout);
+ cmsysProcess_SetTimeout(cp, timeout.count());
cmsysProcess_Execute(cp);
std::vector<char> tempStdOut;
@@ -687,7 +570,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
std::string strdata;
if (outputflag != OUTPUT_PASSTHROUGH &&
(captureStdOut || captureStdErr || outputflag != OUTPUT_NONE)) {
- while ((pipe = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) >
+ while ((pipe = cmsysProcess_WaitForData(cp, &data, &length, nullptr)) >
0) {
// Translate NULL characters in the output into valid text.
for (int i = 0; i < length; ++i) {
@@ -699,18 +582,18 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
if (pipe == cmsysProcess_Pipe_STDOUT) {
if (outputflag != OUTPUT_NONE) {
processOutput.DecodeText(data, length, strdata, 1);
- cmSystemTools::Stdout(strdata.c_str(), strdata.size());
+ cmSystemTools::Stdout(strdata);
}
if (captureStdOut) {
- tempStdOut.insert(tempStdOut.end(), data, data + length);
+ cmAppend(tempStdOut, data, data + length);
}
} else if (pipe == cmsysProcess_Pipe_STDERR) {
if (outputflag != OUTPUT_NONE) {
processOutput.DecodeText(data, length, strdata, 2);
- cmSystemTools::Stderr(strdata.c_str(), strdata.size());
+ cmSystemTools::Stderr(strdata);
}
if (captureStdErr) {
- tempStdErr.insert(tempStdErr.end(), data, data + length);
+ cmAppend(tempStdErr, data, data + length);
}
}
}
@@ -718,16 +601,16 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
if (outputflag != OUTPUT_NONE) {
processOutput.DecodeText(std::string(), strdata, 1);
if (!strdata.empty()) {
- cmSystemTools::Stdout(strdata.c_str(), strdata.size());
+ cmSystemTools::Stdout(strdata);
}
processOutput.DecodeText(std::string(), strdata, 2);
if (!strdata.empty()) {
- cmSystemTools::Stderr(strdata.c_str(), strdata.size());
+ cmSystemTools::Stderr(strdata);
}
}
}
- cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+ cmsysProcess_WaitForExit(cp, nullptr);
if (captureStdOut) {
captureStdOut->assign(tempStdOut.begin(), tempStdOut.end());
@@ -754,6 +637,8 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
}
if (captureStdErr) {
captureStdErr->append(exception_str, strlen(exception_str));
+ } else if (captureStdOut) {
+ captureStdOut->append(exception_str, strlen(exception_str));
}
result = false;
} else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Error) {
@@ -763,6 +648,8 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
}
if (captureStdErr) {
captureStdErr->append(error_str, strlen(error_str));
+ } else if (captureStdOut) {
+ captureStdOut->append(error_str, strlen(error_str));
}
result = false;
} else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Expired) {
@@ -780,11 +667,11 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
return result;
}
-bool cmSystemTools::RunSingleCommand(const char* command,
+bool cmSystemTools::RunSingleCommand(const std::string& command,
std::string* captureStdOut,
std::string* captureStdErr, int* retVal,
const char* dir, OutputOption outputflag,
- double timeout)
+ cmDuration timeout)
{
if (s_DisableRunCommandOutput) {
outputflag = OUTPUT_NONE;
@@ -810,25 +697,22 @@ std::string cmSystemTools::PrintSingleCommand(
}
bool cmSystemTools::DoesFileExistWithExtensions(
- const char* name, const std::vector<std::string>& headerExts)
+ const std::string& name, const std::vector<std::string>& headerExts)
{
std::string hname;
- for (std::vector<std::string>::const_iterator ext = headerExts.begin();
- ext != headerExts.end(); ++ext) {
- hname = name;
- hname += ".";
- hname += *ext;
- if (cmSystemTools::FileExists(hname.c_str())) {
+ for (std::string const& headerExt : headerExts) {
+ hname = cmStrCat(name, '.', headerExt);
+ if (cmSystemTools::FileExists(hname)) {
return true;
}
}
return false;
}
-std::string cmSystemTools::FileExistsInParentDirectories(const char* fname,
- const char* directory,
- const char* toplevel)
+std::string cmSystemTools::FileExistsInParentDirectories(
+ const std::string& fname, const std::string& directory,
+ const std::string& toplevel)
{
std::string file = fname;
cmSystemTools::ConvertToUnixSlashes(file);
@@ -836,11 +720,11 @@ std::string cmSystemTools::FileExistsInParentDirectories(const char* fname,
cmSystemTools::ConvertToUnixSlashes(dir);
std::string prevDir;
while (dir != prevDir) {
- std::string path = dir + "/" + file;
- if (cmSystemTools::FileExists(path.c_str())) {
+ std::string path = cmStrCat(dir, "/", file);
+ if (cmSystemTools::FileExists(path)) {
return path;
}
- if (dir.size() < strlen(toplevel)) {
+ if (dir.size() < toplevel.size()) {
break;
}
prevDir = dir;
@@ -849,17 +733,6 @@ std::string cmSystemTools::FileExistsInParentDirectories(const char* fname,
return "";
}
-bool cmSystemTools::cmCopyFile(const char* source, const char* destination)
-{
- return Superclass::CopyFileAlways(source, destination);
-}
-
-bool cmSystemTools::CopyFileIfDifferent(const char* source,
- const char* destination)
-{
- return Superclass::CopyFileIfDifferent(source, destination);
-}
-
#ifdef _WIN32
cmSystemTools::WindowsFileRetry cmSystemTools::GetWindowsFileRetry()
{
@@ -892,12 +765,65 @@ cmSystemTools::WindowsFileRetry cmSystemTools::GetWindowsFileRetry()
}
#endif
-bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
+std::string cmSystemTools::GetRealPathResolvingWindowsSubst(
+ const std::string& path, std::string* errorMessage)
{
#ifdef _WIN32
-#ifndef INVALID_FILE_ATTRIBUTES
-#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+ // 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;
+#else
+ return cmsys::SystemTools::GetRealPath(path, errorMessage);
#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 std::string& oldname,
+ const std::string& newname)
+{
+#ifdef _WIN32
+# ifndef INVALID_FILE_ATTRIBUTES
+# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+# endif
/* Windows MoveFileEx may not replace read-only or in-use files. If it
fails then remove the read-only attribute from any existing destination.
Try multiple times since we may be racing against another process
@@ -930,29 +856,39 @@ bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
return retry.Count > 0;
#else
/* On UNIX we have an OS-provided call to do this atomically. */
- return rename(oldname, newname) == 0;
+ return rename(oldname.c_str(), newname.c_str()) == 0;
#endif
}
-bool cmSystemTools::ComputeFileMD5(const std::string& source, char* md5out)
+void cmSystemTools::MoveFileIfDifferent(const std::string& source,
+ const std::string& destination)
{
-#if defined(CMAKE_BUILD_WITH_CMAKE)
- cmCryptoHash md5(cmCryptoHash::AlgoMD5);
- std::string const str = md5.HashFile(source);
- strncpy(md5out, str.c_str(), 32);
- return !str.empty();
+ if (FilesDiffer(source, destination)) {
+ if (RenameFile(source, destination)) {
+ return;
+ }
+ CopyFileAlways(source, destination);
+ }
+ RemoveFile(source);
+}
+
+std::string cmSystemTools::ComputeFileHash(const std::string& source,
+ cmCryptoHash::Algo algo)
+{
+#if !defined(CMAKE_BOOTSTRAP)
+ cmCryptoHash hash(algo);
+ return hash.HashFile(source);
#else
(void)source;
- (void)md5out;
- cmSystemTools::Message("md5sum not supported in bootstrapping mode",
+ cmSystemTools::Message("hashsum not supported in bootstrapping mode",
"Error");
- return false;
+ return std::string();
#endif
}
std::string cmSystemTools::ComputeStringMD5(const std::string& input)
{
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
cmCryptoHash md5(cmCryptoHash::AlgoMD5);
return md5.HashString(input);
#else
@@ -968,7 +904,7 @@ std::string cmSystemTools::ComputeCertificateThumbprint(
{
std::string thumbprint;
-#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32)
+#if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32)
BYTE* certData = NULL;
CRYPT_INTEGER_BLOB cryptBlob;
HCERTSTORE certStore = NULL;
@@ -1050,7 +986,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));
}
}
}
@@ -1072,9 +1008,7 @@ void cmSystemTools::GlobDirs(const std::string& path,
for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i) {
if ((std::string(d.GetFile(i)) != ".") &&
(std::string(d.GetFile(i)) != "..")) {
- std::string fname = startPath;
- fname += "/";
- fname += d.GetFile(i);
+ std::string fname = cmStrCat(startPath, '/', d.GetFile(i));
if (cmSystemTools::FileIsDirectory(fname)) {
fname += finishPath;
cmSystemTools::GlobDirs(fname, files);
@@ -1084,82 +1018,12 @@ void cmSystemTools::GlobDirs(const std::string& path,
}
}
-void cmSystemTools::ExpandList(std::vector<std::string> const& arguments,
- std::vector<std::string>& newargs)
-{
- std::vector<std::string>::const_iterator i;
- for (i = arguments.begin(); i != arguments.end(); ++i) {
- cmSystemTools::ExpandListArgument(*i, newargs);
- }
-}
-
-void cmSystemTools::ExpandListArgument(const std::string& arg,
- std::vector<std::string>& newargs,
- bool emptyArgs)
-{
- // If argument is empty, it is an empty list.
- if (!emptyArgs && arg.empty()) {
- return;
- }
- // if there are no ; in the name then just copy the current string
- if (arg.find(';') == std::string::npos) {
- newargs.push_back(arg);
- return;
- }
- std::string newArg;
- const char* last = arg.c_str();
- // Break the string at non-escaped semicolons not nested in [].
- int squareNesting = 0;
- for (const char* c = last; *c; ++c) {
- switch (*c) {
- case '\\': {
- // We only want to allow escaping of semicolons. Other
- // escapes should not be processed here.
- const char* next = c + 1;
- if (*next == ';') {
- newArg.append(last, c - last);
- // Skip over the escape character
- last = c = next;
- }
- } break;
- case '[': {
- ++squareNesting;
- } break;
- case ']': {
- --squareNesting;
- } break;
- case ';': {
- // Break the string here if we are not nested inside square
- // brackets.
- if (squareNesting == 0) {
- newArg.append(last, c - last);
- // Skip over the semicolon
- last = c + 1;
- if (!newArg.empty() || emptyArgs) {
- // Add the last argument if the string is not empty.
- newargs.push_back(newArg);
- newArg = "";
- }
- }
- } break;
- default: {
- // Just append this character.
- } break;
- }
- }
- newArg.append(last);
- if (!newArg.empty() || emptyArgs) {
- // Add the last argument if the string is not empty.
- newargs.push_back(newArg);
- }
-}
-
bool cmSystemTools::SimpleGlob(const std::string& glob,
std::vector<std::string>& files,
int type /* = 0 */)
{
files.clear();
- if (glob[glob.size() - 1] != '*') {
+ if (glob.back() != '*') {
return false;
}
std::string path = cmSystemTools::GetFilenamePath(glob);
@@ -1176,7 +1040,7 @@ bool cmSystemTools::SimpleGlob(const std::string& glob,
if ((std::string(d.GetFile(i)) != ".") &&
(std::string(d.GetFile(i)) != "..")) {
std::string fname = path;
- if (path[path.size() - 1] != '/') {
+ if (path.back() != '/') {
fname += "/";
}
fname += d.GetFile(i);
@@ -1198,73 +1062,7 @@ bool cmSystemTools::SimpleGlob(const std::string& glob,
return res;
}
-cmSystemTools::FileFormat cmSystemTools::GetFileFormat(const char* cext)
-{
- if (!cext || *cext == 0) {
- return cmSystemTools::NO_FILE_FORMAT;
- }
- // std::string ext = cmSystemTools::LowerCase(cext);
- std::string ext = cext;
- if (ext == "c" || ext == ".c" || ext == "m" || ext == ".m") {
- return cmSystemTools::C_FILE_FORMAT;
- }
- if (ext == "C" || ext == ".C" || ext == "M" || ext == ".M" || ext == "c++" ||
- ext == ".c++" || ext == "cc" || ext == ".cc" || ext == "cpp" ||
- ext == ".cpp" || ext == "cxx" || ext == ".cxx" || ext == "mm" ||
- ext == ".mm") {
- return cmSystemTools::CXX_FILE_FORMAT;
- }
- if (ext == "f" || ext == ".f" || ext == "F" || ext == ".F" || ext == "f77" ||
- ext == ".f77" || ext == "f90" || ext == ".f90" || ext == "for" ||
- ext == ".for" || ext == "f95" || ext == ".f95") {
- return cmSystemTools::FORTRAN_FILE_FORMAT;
- }
- if (ext == "java" || ext == ".java") {
- return cmSystemTools::JAVA_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" ||
- ext == ".in" || ext == "txx" || ext == ".txx") {
- return cmSystemTools::HEADER_FILE_FORMAT;
- }
- if (ext == "rc" || ext == ".rc") {
- return cmSystemTools::RESOURCE_FILE_FORMAT;
- }
- if (ext == "def" || ext == ".def") {
- return cmSystemTools::DEFINITION_FILE_FORMAT;
- }
- if (ext == "lib" || ext == ".lib" || ext == "a" || ext == ".a") {
- return cmSystemTools::STATIC_LIBRARY_FILE_FORMAT;
- }
- if (ext == "o" || ext == ".o" || ext == "obj" || ext == ".obj") {
- return cmSystemTools::OBJECT_FILE_FORMAT;
- }
-#ifdef __APPLE__
- if (ext == "dylib" || ext == ".dylib") {
- return cmSystemTools::SHARED_LIBRARY_FILE_FORMAT;
- }
- if (ext == "so" || ext == ".so" || ext == "bundle" || ext == ".bundle") {
- return cmSystemTools::MODULE_FILE_FORMAT;
- }
-#else // __APPLE__
- if (ext == "so" || ext == ".so" || ext == "sl" || ext == ".sl" ||
- ext == "dll" || ext == ".dll") {
- return cmSystemTools::SHARED_LIBRARY_FILE_FORMAT;
- }
-#endif // __APPLE__
- return cmSystemTools::UNKNOWN_FILE_FORMAT;
-}
-
-bool cmSystemTools::Split(const char* s, std::vector<std::string>& l)
-{
- std::vector<std::string> temp;
- bool res = Superclass::Split(s, temp);
- l.insert(l.end(), temp.begin(), temp.end());
- 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) {
@@ -1291,7 +1089,7 @@ void cmSystemTools::ConvertToOutputSlashes(std::string& path)
#endif
}
-std::string cmSystemTools::ConvertToRunCommandPath(const char* path)
+std::string cmSystemTools::ConvertToRunCommandPath(const std::string& path)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
return cmSystemTools::ConvertToWindowsOutputPath(path);
@@ -1301,60 +1099,109 @@ 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: ",
+ cmSystemTools::Error("RelativePath must be passed a full path to local: " +
local);
}
if (!cmSystemTools::FileIsFullPath(remote)) {
- cmSystemTools::Error("RelativePath must be passed a full path to remote: ",
- remote);
+ cmSystemTools::Error(
+ "RelativePath must be passed a full path to remote: " + remote);
}
return cmsys::SystemTools::RelativePath(local, remote);
}
-std::string cmSystemTools::CollapseCombinedPath(std::string const& dir,
- std::string const& file)
+std::string cmSystemTools::ForceToRelativePath(std::string const& local_path,
+ std::string const& remote_path)
{
- if (dir.empty() || dir == ".") {
- return file;
+ // The paths should never be quoted.
+ assert(local_path.front() != '\"');
+ assert(remote_path.front() != '\"');
+
+ // The local path should never have a trailing slash except if it is just the
+ // bare root directory
+ assert(local_path.empty() || local_path.back() != '/' ||
+ local_path.size() == 1 ||
+ (local_path.size() == 3 && local_path[1] == ':' &&
+ ((local_path[0] >= 'A' && local_path[0] <= 'Z') ||
+ (local_path[0] >= 'a' && local_path[0] <= 'z'))));
+
+ // If the path is already relative then just return the path.
+ if (!cmSystemTools::FileIsFullPath(remote_path)) {
+ return remote_path;
+ }
+
+ // Identify the longest shared path component between the remote
+ // path and the local path.
+ std::vector<std::string> local;
+ cmSystemTools::SplitPath(local_path, local);
+ std::vector<std::string> remote;
+ cmSystemTools::SplitPath(remote_path, remote);
+ unsigned int common = 0;
+ while (common < remote.size() && common < local.size() &&
+ cmSystemTools::ComparePath(remote[common], local[common])) {
+ ++common;
+ }
+
+ // If no part of the path is in common then return the full path.
+ if (common == 0) {
+ return remote_path;
}
- std::vector<std::string> dirComponents;
- std::vector<std::string> fileComponents;
- cmSystemTools::SplitPath(dir, dirComponents);
- cmSystemTools::SplitPath(file, fileComponents);
+ // If the entire path is in common then just return a ".".
+ if (common == remote.size() && common == local.size()) {
+ return ".";
+ }
- if (fileComponents.empty()) {
- return dir;
+ // If the entire path is in common except for a trailing slash then
+ // just return a "./".
+ if (common + 1 == remote.size() && remote[common].empty() &&
+ common == local.size()) {
+ return "./";
}
- if (fileComponents[0] != "") {
- // File is not a relative path.
- return file;
+
+ // Construct the relative path.
+ std::string relative;
+
+ // First add enough ../ to get up to the level of the shared portion
+ // of the path. Leave off the trailing slash. Note that the last
+ // component of local will never be empty because local should never
+ // have a trailing slash.
+ for (unsigned int i = common; i < local.size(); ++i) {
+ relative += "..";
+ if (i < local.size() - 1) {
+ relative += "/";
+ }
}
- std::vector<std::string>::iterator i = fileComponents.begin() + 1;
- while (i != fileComponents.end() && *i == ".." && dirComponents.size() > 1) {
- ++i; // Remove ".." file component.
- dirComponents.pop_back(); // Remove last dir component.
+ // Now add the portion of the destination path that is not included
+ // in the shared portion of the path. Add a slash the first time
+ // only if there was already something in the path. If there was a
+ // trailing slash in the input then the last iteration of the loop
+ // will add a slash followed by an empty string which will preserve
+ // the trailing slash in the output.
+
+ if (!relative.empty() && !remote.empty()) {
+ relative += "/";
}
+ relative += cmJoin(cmMakeRange(remote).advance(common), "/");
- dirComponents.insert(dirComponents.end(), i, fileComponents.end());
- return cmSystemTools::JoinPath(dirComponents);
+ // Finally return the path.
+ return relative;
}
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
bool cmSystemTools::UnsetEnv(const char* value)
{
-#if !defined(HAVE_UNSETENV)
- std::string var = value;
- var += "=";
+# if !defined(HAVE_UNSETENV)
+ std::string var = cmStrCat(value, '=');
return cmSystemTools::PutEnv(var.c_str());
-#else
+# else
unsetenv(value);
return true;
-#endif
+# endif
}
std::vector<std::string> cmSystemTools::GetEnvironmentVariables()
@@ -1362,16 +1209,15 @@ std::vector<std::string> cmSystemTools::GetEnvironmentVariables()
std::vector<std::string> env;
int cc;
for (cc = 0; environ[cc]; ++cc) {
- env.push_back(environ[cc]);
+ env.emplace_back(environ[cc]);
}
return env;
}
void cmSystemTools::AppendEnv(std::vector<std::string> const& env)
{
- for (std::vector<std::string>::const_iterator eit = env.begin();
- eit != env.end(); ++eit) {
- cmSystemTools::PutEnv(*eit);
+ for (std::string const& eit : env) {
+ cmSystemTools::PutEnv(eit);
}
}
@@ -1384,10 +1230,7 @@ cmSystemTools::SaveRestoreEnvironment::~SaveRestoreEnvironment()
{
// First clear everything in the current environment:
std::vector<std::string> currentEnv = GetEnvironmentVariables();
- for (std::vector<std::string>::const_iterator eit = currentEnv.begin();
- eit != currentEnv.end(); ++eit) {
- std::string var(*eit);
-
+ for (std::string var : currentEnv) {
std::string::size_type pos = var.find('=');
if (pos != std::string::npos) {
var = var.substr(0, pos);
@@ -1404,7 +1247,7 @@ cmSystemTools::SaveRestoreEnvironment::~SaveRestoreEnvironment()
void cmSystemTools::EnableVSConsoleOutput()
{
#ifdef _WIN32
- // Visual Studio 8 2005 (devenv.exe or VCExpress.exe) will not
+ // Visual Studio tools like devenv may not
// display output to the console unless this environment variable is
// set. We need it to capture the output of these build tools.
// Note for future work that one could pass "/out \\.\pipe\NAME" to
@@ -1413,37 +1256,35 @@ void cmSystemTools::EnableVSConsoleOutput()
// output and allow it to be captured on the fly.
cmSystemTools::PutEnv("vsconsoleoutput=1");
-#ifdef CMAKE_BUILD_WITH_CMAKE
+# ifndef CMAKE_BOOTSTRAP
// VS sets an environment variable to tell MS tools like "cl" to report
// output through a backdoor pipe instead of stdout/stderr. Unset the
// environment variable to close this backdoor for any path of process
// invocations that passes through CMake so we can capture the output.
cmSystemTools::UnsetEnv("VS_UNICODE_OUTPUT");
-#endif
+# endif
#endif
}
-bool cmSystemTools::IsPathToFramework(const char* path)
+bool cmSystemTools::IsPathToFramework(const std::string& path)
{
return (cmSystemTools::FileIsFullPath(path) &&
cmHasLiteralSuffix(path, ".framework"));
}
-bool cmSystemTools::CreateTar(const char* outFileName,
+bool cmSystemTools::CreateTar(const std::string& outFileName,
const std::vector<std::string>& files,
cmTarCompression compressType, bool verbose,
std::string const& mtime,
std::string const& format)
{
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
- cmsys::ofstream fout(outFileName, std::ios::out | std::ios::binary);
+ cmsys::ofstream fout(outFileName.c_str(), std::ios::out | std::ios::binary);
if (!fout) {
- std::string e = "Cannot open output file \"";
- e += outFileName;
- e += "\": ";
- e += cmSystemTools::GetLastSystemError();
- cmSystemTools::Error(e.c_str());
+ std::string e = cmStrCat("Cannot open output file \"", outFileName,
+ "\": ", cmSystemTools::GetLastSystemError());
+ cmSystemTools::Error(e);
return false;
}
cmArchiveWrite::Compress compress = cmArchiveWrite::CompressNone;
@@ -1457,6 +1298,9 @@ bool cmSystemTools::CreateTar(const char* outFileName,
case TarCompressXZ:
compress = cmArchiveWrite::CompressXZ;
break;
+ case TarCompressZstd:
+ compress = cmArchiveWrite::CompressZstd;
+ break;
case TarCompressNone:
compress = cmArchiveWrite::CompressNone;
break;
@@ -1466,22 +1310,18 @@ bool cmSystemTools::CreateTar(const char* outFileName,
a.SetMTime(mtime);
a.SetVerbose(verbose);
- for (std::vector<std::string>::const_iterator i = files.begin();
- i != files.end(); ++i) {
- std::string path = *i;
- if (cmSystemTools::FileIsFullPath(path.c_str())) {
+ bool tarCreatedSuccessfully = true;
+ for (auto path : files) {
+ 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;
+ cmSystemTools::Error(a.GetError());
+ tarCreatedSuccessfully = false;
}
}
- if (!a) {
- cmSystemTools::Error(a.GetError().c_str());
- return false;
- }
- return true;
+ return tarCreatedSuccessfully;
#else
(void)outFileName;
(void)files;
@@ -1490,10 +1330,10 @@ bool cmSystemTools::CreateTar(const char* outFileName,
#endif
}
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
namespace {
-#define BSDTAR_FILESIZE_PRINTF "%lu"
-#define BSDTAR_FILESIZE_TYPE unsigned long
+# define BSDTAR_FILESIZE_PRINTF "%lu"
+# define BSDTAR_FILESIZE_TYPE unsigned long
void list_item_verbose(FILE* out, struct archive_entry* entry)
{
char tmp[100];
@@ -1520,22 +1360,22 @@ void list_item_verbose(FILE* out, struct archive_entry* entry)
/* Use uname if it's present, else uid. */
p = archive_entry_uname(entry);
- if ((p == CM_NULLPTR) || (*p == '\0')) {
- sprintf(tmp, "%lu ", (unsigned long)archive_entry_uid(entry));
+ if ((p == nullptr) || (*p == '\0')) {
+ sprintf(tmp, "%lu ", static_cast<unsigned long>(archive_entry_uid(entry)));
p = tmp;
}
w = strlen(p);
if (w > u_width) {
u_width = w;
}
- fprintf(out, "%-*s ", (int)u_width, p);
+ fprintf(out, "%-*s ", static_cast<int>(u_width), p);
/* Use gname if it's present, else gid. */
p = archive_entry_gname(entry);
- if (p != CM_NULLPTR && p[0] != '\0') {
+ if (p != nullptr && p[0] != '\0') {
fprintf(out, "%s", p);
w = strlen(p);
} else {
- sprintf(tmp, "%lu", (unsigned long)archive_entry_gid(entry));
+ sprintf(tmp, "%lu", static_cast<unsigned long>(archive_entry_gid(entry)));
w = strlen(tmp);
fprintf(out, "%s", tmp);
}
@@ -1547,8 +1387,9 @@ void list_item_verbose(FILE* out, struct archive_entry* entry)
*/
if (archive_entry_filetype(entry) == AE_IFCHR ||
archive_entry_filetype(entry) == AE_IFBLK) {
- sprintf(tmp, "%lu,%lu", (unsigned long)archive_entry_rdevmajor(entry),
- (unsigned long)archive_entry_rdevminor(entry));
+ unsigned long rdevmajor = archive_entry_rdevmajor(entry);
+ unsigned long rdevminor = archive_entry_rdevminor(entry);
+ sprintf(tmp, "%lu,%lu", rdevmajor, rdevminor);
} else {
/*
* Note the use of platform-dependent macros to format
@@ -1556,22 +1397,22 @@ void list_item_verbose(FILE* out, struct archive_entry* entry)
* corresponding type for the cast.
*/
sprintf(tmp, BSDTAR_FILESIZE_PRINTF,
- (BSDTAR_FILESIZE_TYPE)archive_entry_size(entry));
+ static_cast<BSDTAR_FILESIZE_TYPE>(archive_entry_size(entry)));
}
if (w + strlen(tmp) >= gs_width) {
gs_width = w + strlen(tmp) + 1;
}
- fprintf(out, "%*s", (int)(gs_width - w), tmp);
+ fprintf(out, "%*s", static_cast<int>(gs_width - w), tmp);
/* Format the time using 'ls -l' conventions. */
tim = archive_entry_mtime(entry);
-#define HALF_YEAR ((time_t)365 * 86400 / 2)
-#if defined(_WIN32) && !defined(__CYGWIN__)
+# define HALF_YEAR ((time_t)365 * 86400 / 2)
+# if defined(_WIN32) && !defined(__CYGWIN__)
/* Windows' strftime function does not support %e format. */
-#define DAY_FMT "%d"
-#else
-#define DAY_FMT "%e" /* Day number without leading zeros */
-#endif
+# define DAY_FMT "%d"
+# else
+# define DAY_FMT "%e" /* Day number without leading zeros */
+# endif
if (tim < now - HALF_YEAR || tim > now + HALF_YEAR) {
fmt = DAY_FMT " %b %Y";
} else {
@@ -1592,38 +1433,77 @@ void list_item_verbose(FILE* out, struct archive_entry* entry)
fflush(out);
}
-long copy_data(struct archive* ar, struct archive* aw)
+void ArchiveError(const char* m1, struct archive* a)
+{
+ std::string message(m1);
+ const char* m2 = archive_error_string(a);
+ if (m2) {
+ message += m2;
+ }
+ cmSystemTools::Error(message);
+}
+
+bool la_diagnostic(struct archive* ar, __LA_SSIZE_T r)
+{
+ // See archive.h definition of ARCHIVE_OK for return values.
+
+ if (r >= ARCHIVE_OK) {
+ return true;
+ }
+
+ if (r >= ARCHIVE_WARN) {
+ const char* warn = archive_error_string(ar);
+ if (!warn) {
+ warn = "unknown warning";
+ }
+ std::cerr << "cmake -E tar: warning: " << warn << '\n';
+ return true;
+ }
+
+ // Error.
+ const char* err = archive_error_string(ar);
+ if (!err) {
+ err = "unknown error";
+ }
+ std::cerr << "cmake -E tar: error: " << err << '\n';
+ return false;
+}
+
+// Return 'true' on success
+bool copy_data(struct archive* ar, struct archive* aw)
{
long r;
const void* buff;
size_t size;
-#if defined(ARCHIVE_VERSION_NUMBER) && ARCHIVE_VERSION_NUMBER >= 3000000
+# if defined(ARCHIVE_VERSION_NUMBER) && ARCHIVE_VERSION_NUMBER >= 3000000
__LA_INT64_T offset;
-#else
+# else
off_t offset;
-#endif
+# endif
for (;;) {
+ // See archive.h definition of ARCHIVE_OK for return values.
r = archive_read_data_block(ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF) {
- return (ARCHIVE_OK);
+ return true;
}
- if (r != ARCHIVE_OK) {
- return (r);
+ if (!la_diagnostic(ar, r)) {
+ return false;
}
- r = archive_write_data_block(aw, buff, size, offset);
- if (r != ARCHIVE_OK) {
- cmSystemTools::Message("archive_write_data_block()",
- archive_error_string(aw));
- return (r);
+ // See archive.h definition of ARCHIVE_OK for return values.
+ __LA_SSIZE_T const w = archive_write_data_block(aw, buff, size, offset);
+ if (!la_diagnostic(ar, w)) {
+ return false;
}
}
-#if !defined(__clang__) && !defined(__HP_aCC)
- return r; /* this should not happen but it quiets some compilers */
-#endif
+# if !defined(__clang__) && !defined(__HP_aCC)
+ return false; /* this should not happen but it quiets some compilers */
+# endif
}
-bool extract_tar(const char* outFileName, bool verbose, bool extract)
+bool extract_tar(const std::string& outFileName,
+ const std::vector<std::string>& files, bool verbose,
+ bool extract)
{
cmLocaleRAII localeRAII;
static_cast<void>(localeRAII);
@@ -1632,10 +1512,24 @@ bool extract_tar(const char* outFileName, bool verbose, bool extract)
archive_read_support_filter_all(a);
archive_read_support_format_all(a);
struct archive_entry* entry;
- int r = cm_archive_read_open_file(a, outFileName, 10240);
+
+ struct archive* matching = archive_match_new();
+ if (matching == nullptr) {
+ cmSystemTools::Error("Out of memory");
+ return false;
+ }
+
+ for (const auto& filename : files) {
+ if (archive_match_include_pattern(matching, filename.c_str()) !=
+ ARCHIVE_OK) {
+ cmSystemTools::Error("Failed to add to inclusion list: " + filename);
+ return false;
+ }
+ }
+
+ int r = cm_archive_read_open_file(a, outFileName.c_str(), 10240);
if (r) {
- cmSystemTools::Error("Problem with archive_read_open_file(): ",
- archive_error_string(a));
+ ArchiveError("Problem with archive_read_open_file(): ", a);
archive_write_free(ext);
archive_read_close(a);
return false;
@@ -1646,56 +1540,80 @@ bool extract_tar(const char* outFileName, bool verbose, bool extract)
break;
}
if (r != ARCHIVE_OK) {
- cmSystemTools::Error("Problem with archive_read_next_header(): ",
- archive_error_string(a));
+ ArchiveError("Problem with archive_read_next_header(): ", a);
break;
}
+
+ if (archive_match_excluded(matching, entry)) {
+ continue;
+ }
+
if (verbose) {
if (extract) {
cmSystemTools::Stdout("x ");
- cmSystemTools::Stdout(cm_archive_entry_pathname(entry).c_str());
+ cmSystemTools::Stdout(cm_archive_entry_pathname(entry));
} else {
list_item_verbose(stdout, entry);
}
cmSystemTools::Stdout("\n");
} else if (!extract) {
- cmSystemTools::Stdout(cm_archive_entry_pathname(entry).c_str());
+ cmSystemTools::Stdout(cm_archive_entry_pathname(entry));
cmSystemTools::Stdout("\n");
}
if (extract) {
r = archive_write_disk_set_options(ext, ARCHIVE_EXTRACT_TIME);
if (r != ARCHIVE_OK) {
- cmSystemTools::Error("Problem with archive_write_disk_set_options(): ",
- archive_error_string(ext));
+ ArchiveError("Problem with archive_write_disk_set_options(): ", ext);
break;
}
r = archive_write_header(ext, entry);
if (r == ARCHIVE_OK) {
- copy_data(a, ext);
+ if (!copy_data(a, ext)) {
+ break;
+ }
r = archive_write_finish_entry(ext);
if (r != ARCHIVE_OK) {
- cmSystemTools::Error("Problem with archive_write_finish_entry(): ",
- archive_error_string(ext));
+ ArchiveError("Problem with archive_write_finish_entry(): ", ext);
break;
}
}
-#ifdef _WIN32
+# ifdef _WIN32
else if (const char* linktext = archive_entry_symlink(entry)) {
std::cerr << "cmake -E tar: warning: skipping symbolic link \""
<< cm_archive_entry_pathname(entry) << "\" -> \"" << linktext
<< "\"." << std::endl;
}
-#endif
+# endif
else {
- cmSystemTools::Error("Problem with archive_write_header(): ",
- archive_error_string(ext));
- cmSystemTools::Error("Current file: ",
- cm_archive_entry_pathname(entry).c_str());
+ ArchiveError("Problem with archive_write_header(): ", ext);
+ cmSystemTools::Error("Current file: " +
+ cm_archive_entry_pathname(entry));
break;
}
}
}
+
+ bool error_occured = false;
+ if (matching != nullptr) {
+ const char* p;
+ int ar;
+
+ while ((ar = archive_match_path_unmatched_inclusions_next(matching, &p)) ==
+ ARCHIVE_OK) {
+ cmSystemTools::Error("tar: " + std::string(p) +
+ ": Not found in archive");
+ error_occured = true;
+ }
+ if (error_occured) {
+ return false;
+ }
+ if (ar == ARCHIVE_FATAL) {
+ cmSystemTools::Error("tar: Out of memory");
+ return false;
+ }
+ }
+ archive_match_free(matching);
archive_write_free(ext);
archive_read_close(a);
archive_read_free(a);
@@ -1704,35 +1622,41 @@ bool extract_tar(const char* outFileName, bool verbose, bool extract)
}
#endif
-bool cmSystemTools::ExtractTar(const char* outFileName, bool verbose)
+bool cmSystemTools::ExtractTar(const std::string& outFileName,
+ const std::vector<std::string>& files,
+ bool verbose)
{
-#if defined(CMAKE_BUILD_WITH_CMAKE)
- return extract_tar(outFileName, verbose, true);
+#if !defined(CMAKE_BOOTSTRAP)
+ return extract_tar(outFileName, files, verbose, true);
#else
(void)outFileName;
+ (void)files;
(void)verbose;
return false;
#endif
}
-bool cmSystemTools::ListTar(const char* outFileName, bool verbose)
+bool cmSystemTools::ListTar(const std::string& outFileName,
+ const std::vector<std::string>& files,
+ bool verbose)
{
-#if defined(CMAKE_BUILD_WITH_CMAKE)
- return extract_tar(outFileName, verbose, false);
+#if !defined(CMAKE_BOOTSTRAP)
+ return extract_tar(outFileName, files, verbose, false);
#else
(void)outFileName;
+ (void)files;
(void)verbose;
return false;
#endif
}
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 = "";
- std::vector<char>::iterator outiter = out.begin();
- std::vector<char>::iterator erriter = err.begin();
+ line.clear();
+ auto outiter = out.begin();
+ auto erriter = err.begin();
cmProcessOutput processOutput;
std::string strdata;
while (true) {
@@ -1775,7 +1699,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;
@@ -1784,26 +1710,26 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
processOutput.DecodeText(data, length, strdata, 1);
// Append to the stdout buffer.
std::vector<char>::size_type size = out.size();
- out.insert(out.end(), strdata.begin(), strdata.end());
+ cmAppend(out, strdata);
outiter = out.begin() + size;
} else if (pipe == cmsysProcess_Pipe_STDERR) {
processOutput.DecodeText(data, length, strdata, 2);
// Append to the stderr buffer.
std::vector<char>::size_type size = err.size();
- err.insert(err.end(), strdata.begin(), strdata.end());
+ cmAppend(err, strdata);
erriter = err.begin() + size;
} else if (pipe == cmsysProcess_Pipe_None) {
// Both stdout and stderr pipes have broken. Return leftover data.
processOutput.DecodeText(std::string(), strdata, 1);
if (!strdata.empty()) {
std::vector<char>::size_type size = out.size();
- out.insert(out.end(), strdata.begin(), strdata.end());
+ cmAppend(out, strdata);
outiter = out.begin() + size;
}
processOutput.DecodeText(std::string(), strdata, 2);
if (!strdata.empty()) {
std::vector<char>::size_type size = err.size();
- err.insert(err.end(), strdata.begin(), strdata.end());
+ cmAppend(err, strdata);
erriter = err.begin() + size;
}
if (!out.empty()) {
@@ -1821,6 +1747,71 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
}
}
+#ifdef _WIN32
+static void EnsureStdPipe(DWORD fd)
+{
+ if (GetStdHandle(fd) != INVALID_HANDLE_VALUE) {
+ return;
+ }
+ SECURITY_ATTRIBUTES sa;
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = NULL;
+ sa.bInheritHandle = TRUE;
+
+ HANDLE h = CreateFileW(
+ L"NUL",
+ fd == STD_INPUT_HANDLE ? FILE_GENERIC_READ
+ : FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING, 0, NULL);
+
+ if (h == INVALID_HANDLE_VALUE) {
+ LPSTR message = NULL;
+ DWORD size = FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&message, 0, NULL);
+ std::string msg = std::string(message, size);
+ LocalFree(message);
+ std::cerr << "failed to open NUL for missing stdio pipe: " << msg;
+ abort();
+ }
+
+ SetStdHandle(fd, h);
+}
+
+void cmSystemTools::EnsureStdPipes()
+{
+ EnsureStdPipe(STD_INPUT_HANDLE);
+ EnsureStdPipe(STD_OUTPUT_HANDLE);
+ EnsureStdPipe(STD_ERROR_HANDLE);
+}
+#else
+static void EnsureStdPipe(int fd)
+{
+ if (fcntl(fd, F_GETFD) != -1 || errno != EBADF) {
+ return;
+ }
+
+ int f = open("/dev/null", fd == STDIN_FILENO ? O_RDONLY : O_WRONLY);
+ if (f == -1) {
+ perror("failed to open /dev/null for missing stdio pipe");
+ abort();
+ }
+ if (f != fd) {
+ dup2(f, fd);
+ close(f);
+ }
+}
+
+void cmSystemTools::EnsureStdPipes()
+{
+ EnsureStdPipe(STDIN_FILENO);
+ EnsureStdPipe(STDOUT_FILENO);
+ EnsureStdPipe(STDERR_FILENO);
+}
+#endif
+
void cmSystemTools::DoNotInheritStdPipes()
{
#ifdef _WIN32
@@ -1848,92 +1839,10 @@ void cmSystemTools::DoNotInheritStdPipes()
#endif
}
-bool cmSystemTools::CopyFileTime(const char* fromFile, const char* toFile)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- cmSystemToolsWindowsHandle hFrom = CreateFileW(
- SystemTools::ConvertToWindowsExtendedPath(fromFile).c_str(), GENERIC_READ,
- FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
- cmSystemToolsWindowsHandle hTo = CreateFileW(
- SystemTools::ConvertToWindowsExtendedPath(toFile).c_str(),
- FILE_WRITE_ATTRIBUTES, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
- if (!hFrom || !hTo) {
- return false;
- }
- FILETIME timeCreation;
- FILETIME timeLastAccess;
- FILETIME timeLastWrite;
- if (!GetFileTime(hFrom, &timeCreation, &timeLastAccess, &timeLastWrite)) {
- return false;
- }
- return SetFileTime(hTo, &timeCreation, &timeLastAccess, &timeLastWrite) != 0;
-#else
- struct stat fromStat;
- if (stat(fromFile, &fromStat) < 0) {
- return false;
- }
-
- struct utimbuf buf;
- buf.actime = fromStat.st_atime;
- buf.modtime = fromStat.st_mtime;
- return utime(toFile, &buf) >= 0;
-#endif
-}
-
-cmSystemToolsFileTime* cmSystemTools::FileTimeNew()
-{
- return new cmSystemToolsFileTime;
-}
-
-void cmSystemTools::FileTimeDelete(cmSystemToolsFileTime* t)
-{
- delete t;
-}
-
-bool cmSystemTools::FileTimeGet(const char* fname, cmSystemToolsFileTime* t)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- cmSystemToolsWindowsHandle h = CreateFileW(
- SystemTools::ConvertToWindowsExtendedPath(fname).c_str(), GENERIC_READ,
- FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
- if (!h) {
- return false;
- }
- if (!GetFileTime(h, &t->timeCreation, &t->timeLastAccess,
- &t->timeLastWrite)) {
- return false;
- }
-#else
- struct stat st;
- if (stat(fname, &st) < 0) {
- return false;
- }
- t->timeBuf.actime = st.st_atime;
- t->timeBuf.modtime = st.st_mtime;
-#endif
- return true;
-}
-
-bool cmSystemTools::FileTimeSet(const char* fname, cmSystemToolsFileTime* t)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- cmSystemToolsWindowsHandle h = CreateFileW(
- SystemTools::ConvertToWindowsExtendedPath(fname).c_str(),
- FILE_WRITE_ATTRIBUTES, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
- if (!h) {
- return false;
- }
- return SetFileTime(h, &t->timeCreation, &t->timeLastAccess,
- &t->timeLastWrite) != 0;
-#else
- return utime(fname, &t->timeBuf) >= 0;
-#endif
-}
-
#ifdef _WIN32
-#ifndef CRYPT_SILENT
-#define CRYPT_SILENT 0x40 /* Not defined by VS 6 version of header. */
-#endif
+# ifndef CRYPT_SILENT
+# define CRYPT_SILENT 0x40 /* Not defined by VS 6 version of header. */
+# endif
static int WinCryptRandom(void* data, size_t size)
{
int result = 0;
@@ -1973,7 +1882,7 @@ unsigned int cmSystemTools::RandomSeed()
// Try using a real random source.
cmsys::ifstream fin;
- fin.rdbuf()->pubsetbuf(CM_NULLPTR, 0); // Unbuffered read.
+ fin.rdbuf()->pubsetbuf(nullptr, 0); // Unbuffered read.
fin.open("/dev/urandom");
if (fin.good() && fin.read(seed.bytes, sizeof(seed)) &&
fin.gcount() == sizeof(seed)) {
@@ -1982,7 +1891,7 @@ unsigned int cmSystemTools::RandomSeed()
// Fall back to the time and pid.
struct timeval t;
- gettimeofday(&t, CM_NULLPTR);
+ gettimeofday(&t, nullptr);
unsigned int pid = static_cast<unsigned int>(getpid());
unsigned int tv_sec = static_cast<unsigned int>(t.tv_sec);
unsigned int tv_usec = static_cast<unsigned int>(t.tv_usec);
@@ -2006,21 +1915,26 @@ 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::GetRealPathResolvingWindowsSubst(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
+# define CM_EXE_PATH_LOCAL_SIZE 16384
char exe_path_local[CM_EXE_PATH_LOCAL_SIZE];
-#if defined(MAC_OS_X_VERSION_10_3) && !defined(MAC_OS_X_VERSION_10_4)
+# if defined(MAC_OS_X_VERSION_10_3) && !defined(MAC_OS_X_VERSION_10_4)
unsigned long exe_path_size = CM_EXE_PATH_LOCAL_SIZE;
-#else
+# else
uint32_t exe_path_size = CM_EXE_PATH_LOCAL_SIZE;
-#endif
-#undef CM_EXE_PATH_LOCAL_SIZE
+# endif
+# undef CM_EXE_PATH_LOCAL_SIZE
char* exe_path = exe_path_local;
if (_NSGetExecutablePath(exe_path, &exe_path_size) < 0) {
- exe_path = (char*)malloc(exe_path_size);
+ exe_path = static_cast<char*>(malloc(exe_path_size));
_NSGetExecutablePath(exe_path, &exe_path_size);
}
exe_dir =
@@ -2052,40 +1966,34 @@ void cmSystemTools::FindCMakeResources(const char* argv0)
}
#endif
exe_dir = cmSystemTools::GetActualCaseForPath(exe_dir);
- cmSystemToolsCMakeCommand = exe_dir;
- cmSystemToolsCMakeCommand += "/cmake";
- cmSystemToolsCMakeCommand += cmSystemTools::GetExecutableExtension();
-#ifndef CMAKE_BUILD_WITH_CMAKE
+ cmSystemToolsCMakeCommand =
+ cmStrCat(exe_dir, "/cmake", cmSystemTools::GetExecutableExtension());
+#ifdef CMAKE_BOOTSTRAP
// The bootstrap cmake does not provide the other tools,
// so use the directory where they are about to be built.
exe_dir = CMAKE_BOOTSTRAP_BINARY_DIR "/bin";
#endif
- cmSystemToolsCTestCommand = exe_dir;
- cmSystemToolsCTestCommand += "/ctest";
- cmSystemToolsCTestCommand += cmSystemTools::GetExecutableExtension();
- cmSystemToolsCPackCommand = exe_dir;
- cmSystemToolsCPackCommand += "/cpack";
- cmSystemToolsCPackCommand += cmSystemTools::GetExecutableExtension();
- cmSystemToolsCMakeGUICommand = exe_dir;
- cmSystemToolsCMakeGUICommand += "/cmake-gui";
- cmSystemToolsCMakeGUICommand += cmSystemTools::GetExecutableExtension();
- if (!cmSystemTools::FileExists(cmSystemToolsCMakeGUICommand.c_str())) {
- cmSystemToolsCMakeGUICommand = "";
- }
- cmSystemToolsCMakeCursesCommand = exe_dir;
- cmSystemToolsCMakeCursesCommand += "/ccmake";
- cmSystemToolsCMakeCursesCommand += cmSystemTools::GetExecutableExtension();
- if (!cmSystemTools::FileExists(cmSystemToolsCMakeCursesCommand.c_str())) {
- cmSystemToolsCMakeCursesCommand = "";
- }
- cmSystemToolsCMClDepsCommand = exe_dir;
- cmSystemToolsCMClDepsCommand += "/cmcldeps";
- cmSystemToolsCMClDepsCommand += cmSystemTools::GetExecutableExtension();
- if (!cmSystemTools::FileExists(cmSystemToolsCMClDepsCommand.c_str())) {
- cmSystemToolsCMClDepsCommand = "";
- }
-
-#ifdef CMAKE_BUILD_WITH_CMAKE
+ cmSystemToolsCTestCommand =
+ cmStrCat(exe_dir, "/ctest", cmSystemTools::GetExecutableExtension());
+ cmSystemToolsCPackCommand =
+ cmStrCat(exe_dir, "/cpack", cmSystemTools::GetExecutableExtension());
+ cmSystemToolsCMakeGUICommand =
+ cmStrCat(exe_dir, "/cmake-gui", cmSystemTools::GetExecutableExtension());
+ if (!cmSystemTools::FileExists(cmSystemToolsCMakeGUICommand)) {
+ cmSystemToolsCMakeGUICommand.clear();
+ }
+ cmSystemToolsCMakeCursesCommand =
+ cmStrCat(exe_dir, "/ccmake", cmSystemTools::GetExecutableExtension());
+ if (!cmSystemTools::FileExists(cmSystemToolsCMakeCursesCommand)) {
+ cmSystemToolsCMakeCursesCommand.clear();
+ }
+ cmSystemToolsCMClDepsCommand =
+ cmStrCat(exe_dir, "/cmcldeps", cmSystemTools::GetExecutableExtension());
+ if (!cmSystemTools::FileExists(cmSystemToolsCMClDepsCommand)) {
+ cmSystemToolsCMClDepsCommand.clear();
+ }
+
+#ifndef CMAKE_BOOTSTRAP
// Install tree has
// - "<prefix><CMAKE_BIN_DIR>/cmake"
// - "<prefix><CMAKE_DATA_DIR>"
@@ -2096,7 +2004,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);
@@ -2280,12 +2188,13 @@ struct cmSystemToolsRPathInfo
};
#endif
+#if defined(CMAKE_USE_ELF_PARSER)
bool cmSystemTools::ChangeRPath(std::string const& file,
std::string const& oldRPath,
- std::string const& newRPath, std::string* emsg,
+ std::string const& newRPath,
+ bool removeEnvironmentRPath, std::string* emsg,
bool* changed)
{
-#if defined(CMAKE_USE_ELF_PARSER)
if (changed) {
*changed = false;
}
@@ -2298,8 +2207,8 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
// Get the RPATH and RUNPATH entries from it.
int se_count = 0;
- cmELF::StringEntry const* se[2] = { CM_NULLPTR, CM_NULLPTR };
- const char* se_name[2] = { CM_NULLPTR, CM_NULLPTR };
+ cmELF::StringEntry const* se[2] = { nullptr, nullptr };
+ const char* se_name[2] = { nullptr, nullptr };
if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) {
se[se_count] = se_rpath;
se_name[se_count] = "RPATH";
@@ -2317,8 +2226,9 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
return true;
}
if (emsg) {
- *emsg = "No valid ELF RPATH or RUNPATH entry exists in the file; ";
- *emsg += elf.GetErrorMessage();
+ *emsg =
+ cmStrCat("No valid ELF RPATH or RUNPATH entry exists in the file; ",
+ elf.GetErrorMessage());
}
return false;
}
@@ -2370,7 +2280,9 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
// Construct the new value which preserves the part of the path
// not being changed.
- rp[rp_count].Value = se[i]->Value.substr(0, prefix_len);
+ if (!removeEnvironmentRPath) {
+ rp[rp_count].Value = se[i]->Value.substr(0, prefix_len);
+ }
rp[rp_count].Value += newRPath;
rp[rp_count].Value += se[i]->Value.substr(pos + oldRPath.length());
@@ -2382,9 +2294,8 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
// least one null terminator.
if (rp[rp_count].Size < rp[rp_count].Value.length() + 1) {
if (emsg) {
- *emsg = "The replacement path is too long for the ";
- *emsg += se_name[i];
- *emsg += " entry.";
+ *emsg = cmStrCat("The replacement path is too long for the ",
+ se_name[i], " entry.");
}
return false;
}
@@ -2420,9 +2331,7 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
// Seek to the RPATH position.
if (!f.seekp(rp[i].Position)) {
if (emsg) {
- *emsg = "Error seeking to ";
- *emsg += rp[i].Name;
- *emsg += " position.";
+ *emsg = cmStrCat("Error seeking to ", rp[i].Name, " position.");
}
return false;
}
@@ -2437,9 +2346,8 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
// Make sure it wrote correctly.
if (!f) {
if (emsg) {
- *emsg = "Error writing the new ";
- *emsg += rp[i].Name;
- *emsg += " string to the file.";
+ *emsg = cmStrCat("Error writing the new ", rp[i].Name,
+ " string to the file.");
}
return false;
}
@@ -2451,22 +2359,25 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
*changed = true;
}
return true;
+}
#else
- (void)file;
- (void)oldRPath;
- (void)newRPath;
- (void)emsg;
- (void)changed;
+bool cmSystemTools::ChangeRPath(std::string const& /*file*/,
+ std::string const& /*oldRPath*/,
+ std::string const& /*newRPath*/,
+ bool /*removeEnvironmentRPath*/,
+ std::string* /*emsg*/, bool* /*changed*/)
+{
return false;
-#endif
}
+#endif
bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op,
const char* lhss, const char* rhss)
{
const char* endl = lhss;
const char* endr = rhss;
- unsigned long lhs, rhs;
+ unsigned long lhs;
+ unsigned long rhs;
while (((*endl >= '0') && (*endl <= '9')) ||
((*endr >= '0') && (*endr <= '9'))) {
@@ -2593,10 +2504,10 @@ int cmSystemTools::strverscmp(std::string const& lhs, std::string const& rhs)
return cm_strverscmp(lhs.c_str(), rhs.c_str());
}
+#if defined(CMAKE_USE_ELF_PARSER)
bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
bool* removed)
{
-#if defined(CMAKE_USE_ELF_PARSER)
if (removed) {
*removed = false;
}
@@ -2612,7 +2523,7 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
// Get the RPATH and RUNPATH entries from it and sort them by index
// in the dynamic section header.
int se_count = 0;
- cmELF::StringEntry const* se[2] = { CM_NULLPTR, CM_NULLPTR };
+ cmELF::StringEntry const* se[2] = { nullptr, nullptr };
if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) {
se[se_count++] = se_rpath;
}
@@ -2651,8 +2562,7 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
// Adjust the entry list as necessary to remove the run path
unsigned long entriesErased = 0;
- for (cmELF::DynamicEntryList::iterator it = dentries.begin();
- it != dentries.end();) {
+ for (auto it = dentries.begin(); it != dentries.end();) {
if (it->first == cmELF::TagRPath || it->first == cmELF::TagRunPath) {
it = dentries.erase(it);
entriesErased++;
@@ -2666,11 +2576,11 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
// contain the location of the linker map, however on MIPS the
// .dynamic section is always read-only so this is not possible. MIPS
// objects instead contain a DT_MIPS_RLD_MAP tag which contains the
- // address where the dyanmic linker will write to (an indirect
+ // address where the dynamic linker will write to (an indirect
// version of DT_DEBUG). Since this doesn't work when using PIE, a
// relative equivalent was created - DT_MIPS_RLD_MAP_REL. Since this
// version contains a relative offset, moving it changes the
- // calculated address. This may cause the dyanmic linker to write
+ // calculated address. This may cause the dynamic linker to write
// into memory it should not be changing.
//
// To fix this, we adjust the value of DT_MIPS_RLD_MAP_REL here. If
@@ -2734,13 +2644,14 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
*removed = true;
}
return true;
+}
#else
- (void)file;
- (void)emsg;
- (void)removed;
+bool cmSystemTools::RemoveRPath(std::string const& /*file*/,
+ std::string* /*emsg*/, bool* /*removed*/)
+{
return false;
-#endif
}
+#endif
bool cmSystemTools::CheckRPath(std::string const& file,
std::string const& newRPath)
@@ -2774,55 +2685,97 @@ bool cmSystemTools::CheckRPath(std::string const& file,
#endif
}
-bool cmSystemTools::RepeatedRemoveDirectory(const char* dir)
+bool cmSystemTools::RepeatedRemoveDirectory(const std::string& dir)
{
+#ifdef _WIN32
// Windows sometimes locks files temporarily so try a few times.
- for (int i = 0; i < 10; ++i) {
+ WindowsFileRetry retry = cmSystemTools::GetWindowsFileRetry();
+
+ for (unsigned int i = 0; i < retry.Count; ++i) {
if (cmSystemTools::RemoveADirectory(dir)) {
return true;
}
- cmSystemTools::Delay(100);
+ cmSystemTools::Delay(retry.Delay);
}
return false;
+#else
+ return cmSystemTools::RemoveADirectory(dir);
+#endif
}
-std::vector<std::string> cmSystemTools::tokenize(const std::string& str,
- const std::string& sep)
-{
- std::vector<std::string> tokens;
- std::string::size_type tokend = 0;
-
- do {
- std::string::size_type tokstart = str.find_first_not_of(sep, tokend);
- if (tokstart == std::string::npos) {
- break; // no more tokens
- }
- tokend = str.find_first_of(sep, tokstart);
- if (tokend == std::string::npos) {
- tokens.push_back(str.substr(tokstart));
- } else {
- tokens.push_back(str.substr(tokstart, tokend - tokstart));
+std::string cmSystemTools::EncodeURL(std::string const& in, bool escapeSlashes)
+{
+ std::string out;
+ for (char c : in) {
+ char hexCh[4] = { 0, 0, 0, 0 };
+ hexCh[0] = c;
+ switch (c) {
+ case '+':
+ case '?':
+ case '\\':
+ case '&':
+ case ' ':
+ case '=':
+ case '%':
+ sprintf(hexCh, "%%%02X", static_cast<int>(c));
+ break;
+ case '/':
+ if (escapeSlashes) {
+ strcpy(hexCh, "%2F");
+ }
+ break;
+ default:
+ break;
}
- } while (tokend != std::string::npos);
-
- if (tokens.empty()) {
- tokens.push_back("");
+ out.append(hexCh);
}
- return tokens;
+ return out;
}
-bool cmSystemTools::StringToLong(const char* str, long* value)
+bool cmSystemTools::CreateSymlink(const std::string& origName,
+ const std::string& newName,
+ std::string* errorMessage)
{
- errno = 0;
- char* endp;
- *value = strtol(str, &endp, 10);
- return (*endp == '\0') && (endp != str) && (errno == 0);
+ uv_fs_t req;
+ int flags = 0;
+#if defined(_WIN32)
+ if (cmsys::SystemTools::FileIsDirectory(origName)) {
+ flags |= UV_FS_SYMLINK_DIR;
+ }
+#endif
+ int err = uv_fs_symlink(nullptr, &req, origName.c_str(), newName.c_str(),
+ flags, nullptr);
+ if (err) {
+ std::string e =
+ "failed to create symbolic link '" + newName + "': " + uv_strerror(err);
+ if (errorMessage) {
+ *errorMessage = std::move(e);
+ } else {
+ cmSystemTools::Error(e);
+ }
+ return false;
+ }
+
+ return true;
}
-bool cmSystemTools::StringToULong(const char* str, unsigned long* value)
+bool cmSystemTools::CreateLink(const std::string& origName,
+ const std::string& newName,
+ std::string* errorMessage)
{
- errno = 0;
- char* endp;
- *value = strtoul(str, &endp, 10);
- return (*endp == '\0') && (endp != str) && (errno == 0);
+ uv_fs_t req;
+ int err =
+ uv_fs_link(nullptr, &req, origName.c_str(), newName.c_str(), nullptr);
+ if (err) {
+ std::string e =
+ "failed to create link '" + newName + "': " + uv_strerror(err);
+ if (errorMessage) {
+ *errorMessage = std::move(e);
+ } else {
+ cmSystemTools::Error(e);
+ }
+ return false;
+ }
+
+ return true;
}
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 9de796728..ee149a029 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -3,16 +3,21 @@
#ifndef cmSystemTools_h
#define cmSystemTools_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmProcessOutput.h"
-#include "cmsys/Process.h"
-#include "cmsys/SystemTools.hxx" // IWYU pragma: export
-#include <stddef.h>
+#include <cstddef>
+#include <functional>
#include <string>
#include <vector>
-class cmSystemToolsFileTime;
+#include <cm/string_view>
+
+#include "cmsys/Process.h"
+#include "cmsys/SystemTools.hxx" // IWYU pragma: export
+
+#include "cmCryptoHash.h"
+#include "cmDuration.h"
+#include "cmProcessOutput.h"
/** \class cmSystemTools
* \brief A collection of useful functions for CMake.
@@ -23,18 +28,8 @@ class cmSystemToolsFileTime;
class cmSystemTools : public cmsys::SystemTools
{
public:
- typedef cmsys::SystemTools Superclass;
- typedef cmProcessOutput::Encoding Encoding;
-
- /** Expand out any arguments in the vector that have ; separated
- * strings into multiple arguments. A new vector is created
- * containing the expanded versions of all arguments in argsIn.
- */
- static void ExpandList(std::vector<std::string> const& argsIn,
- std::vector<std::string>& argsOut);
- static void ExpandListArgument(const std::string& arg,
- std::vector<std::string>& argsOut,
- bool emptyArgs = false);
+ using Superclass = cmsys::SystemTools;
+ using Encoding = cmProcessOutput::Encoding;
/**
* Look for and replace registry values in a string
@@ -42,117 +37,80 @@ public:
static void ExpandRegistryValues(std::string& source,
KeyWOW64 view = KeyWOW64_Default);
- ///! Escape quotes in a string.
- static std::string EscapeQuotes(const std::string& str);
-
/** Map help document name to file name. */
- static std::string HelpFileName(std::string);
+ static std::string HelpFileName(cm::string_view);
- /**
- * Returns a string that has whitespace removed from the start and the end.
- */
- static std::string TrimWhitespace(const std::string& s);
-
- typedef void (*MessageCallback)(const char*, const char*, bool&, void*);
+ using MessageCallback = std::function<void(const std::string&, const char*)>;
/**
* 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).
+ * title as a const char*.
*/
- static void SetMessageCallback(MessageCallback f,
- void* clientData = CM_NULLPTR);
+ static void SetMessageCallback(MessageCallback f);
/**
* Display an error message.
*/
- static void Error(const char* m, const char* m2 = CM_NULLPTR,
- const char* m3 = CM_NULLPTR, const char* m4 = CM_NULLPTR);
+ static void Error(const std::string& m);
/**
* Display a message.
*/
- static void Message(const char* m, const char* title = CM_NULLPTR);
+ static void Message(const std::string& m, const char* title = nullptr);
- typedef void (*OutputCallback)(const char*, size_t length, void*);
+ using OutputCallback = std::function<void(std::string const&)>;
- ///! Send a string to stdout
- static void Stdout(const char* s);
- static void Stdout(const char* s, size_t length);
- static void SetStdoutCallback(OutputCallback, void* clientData = CM_NULLPTR);
+ //! Send a string to stdout
+ static void Stdout(const std::string& s);
+ static void SetStdoutCallback(OutputCallback f);
- ///! Send a string to stderr
- static void Stderr(const char* s);
- static void Stderr(const char* s, size_t length);
- static void SetStderrCallback(OutputCallback, void* clientData = CM_NULLPTR);
+ //! Send a string to stderr
+ static void Stderr(const std::string& s);
+ static void SetStderrCallback(OutputCallback f);
- typedef bool (*InterruptCallback)(void*);
- static void SetInterruptCallback(InterruptCallback f,
- void* clientData = CM_NULLPTR);
+ using InterruptCallback = std::function<bool()>;
+ static void SetInterruptCallback(InterruptCallback f);
static bool GetInterruptFlag();
- ///! Return true if there was an error at any point.
+ //! Return true if there was an error at any point.
static bool GetErrorOccuredFlag()
{
return cmSystemTools::s_ErrorOccured ||
cmSystemTools::s_FatalErrorOccured || GetInterruptFlag();
}
- ///! If this is set to true, cmake stops processing commands.
+ //! If this is set to true, cmake stops processing commands.
static void SetFatalErrorOccured()
{
cmSystemTools::s_FatalErrorOccured = true;
}
static void SetErrorOccured() { cmSystemTools::s_ErrorOccured = true; }
- ///! Return true if there was an error at any point.
+ //! Return true if there was an error at any point.
static bool GetFatalErrorOccured()
{
return cmSystemTools::s_FatalErrorOccured || GetInterruptFlag();
}
- ///! Set the error occurred flag and fatal error back to false
+ //! Set the error occurred flag and fatal error back to false
static void ResetErrorOccuredFlag()
{
cmSystemTools::s_FatalErrorOccured = false;
cmSystemTools::s_ErrorOccured = false;
}
- /**
- * Does a string indicates that CMake/CPack/CTest internally
- * forced this value. This is not the same as On, but this
- * may be considered as "internally switched on".
- */
- static bool IsInternallyOn(const char* val);
- /**
- * does a string indicate a true or on value ? This is not the same
- * as ifdef.
- */
- static bool IsOn(const char* val);
-
- /**
- * does a string indicate a false or off value ? Note that this is
- * not the same as !IsOn(...) because there are a number of
- * ambiguous values such as "/usr/local/bin" a path will result in
- * IsON and IsOff both returning false. Note that the special path
- * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true.
- */
- static bool IsOff(const char* val);
-
- ///! Return true if value is NOTFOUND or ends in -NOTFOUND.
- static bool IsNOTFOUND(const char* value);
- ///! Return true if the path is a framework
- static bool IsPathToFramework(const char* value);
+ //! Return true if the path is a framework
+ static bool IsPathToFramework(const std::string& value);
static bool DoesFileExistWithExtensions(
- const char* name, const std::vector<std::string>& sourceExts);
+ const std::string& name, const std::vector<std::string>& sourceExts);
/**
* Check if the given file exists in one of the parent directory of the
* given file or directory and if it does, return the name of the file.
* Toplevel specifies the top-most directory to where it will look.
*/
- static std::string FileExistsInParentDirectories(const char* fname,
- const char* directory,
- const char* toplevel);
+ static std::string FileExistsInParentDirectories(
+ const std::string& fname, const std::string& directory,
+ const std::string& toplevel);
static void Glob(const std::string& directory, const std::string& regexp,
std::vector<std::string>& files);
@@ -166,26 +124,28 @@ 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);
- ///! Copy a file.
- static bool cmCopyFile(const char* source, const char* destination);
- static bool CopyFileIfDifferent(const char* source, const char* destination);
-
/** Rename a file or directory within a single disk volume (atomic
if possible). */
- static bool RenameFile(const char* oldname, const char* newname);
+ static bool RenameFile(const std::string& oldname,
+ const std::string& newname);
- ///! Compute the md5sum of a file
- static bool ComputeFileMD5(const std::string& source, char* md5out);
+ //! Rename a file if contents are different, delete the source otherwise
+ static void MoveFileIfDifferent(const std::string& source,
+ const std::string& destination);
+
+ //! Compute the hash of a file
+ static std::string ComputeFileHash(const std::string& source,
+ cmCryptoHash::Algo algo);
/** Compute the md5sum of a string. */
static std::string ComputeStringMD5(const std::string& input);
- ///! Get the SHA thumbprint for a certificate file
+ //! Get the SHA thumbprint for a certificate file
static std::string ComputeCertificateThumbprint(const std::string& source);
/**
@@ -217,25 +177,25 @@ public:
OUTPUT_FORWARD,
OUTPUT_PASSTHROUGH
};
- static bool RunSingleCommand(const char* command,
- std::string* captureStdOut = CM_NULLPTR,
- std::string* captureStdErr = CM_NULLPTR,
- int* retVal = CM_NULLPTR,
- const char* dir = CM_NULLPTR,
+ static bool RunSingleCommand(const std::string& command,
+ std::string* captureStdOut = nullptr,
+ std::string* captureStdErr = nullptr,
+ 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 = CM_NULLPTR,
- std::string* captureStdErr = CM_NULLPTR,
- int* retVal = CM_NULLPTR,
- const char* dir = CM_NULLPTR,
+ std::string* captureStdOut = nullptr,
+ std::string* captureStdErr = nullptr,
+ 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&);
@@ -243,7 +203,7 @@ public:
/**
* Parse arguments out of a single string command
*/
- static std::vector<std::string> ParseArguments(const char* command);
+ static std::vector<std::string> ParseArguments(const std::string& command);
/** Parse arguments out of a windows command line string. */
static void ParseWindowsCommandLine(const char* command,
@@ -253,6 +213,11 @@ public:
static void ParseUnixCommandLine(const char* command,
std::vector<std::string>& args);
+ /** Split a command-line string into the parsed command and the unparsed
+ arguments. Returns false on unfinished quoting or escaping. */
+ static bool SplitProgramFromArgs(std::string const& command,
+ std::string& program, std::string& args);
+
/**
* Handle response file in an argument list and return a new argument list
* **/
@@ -262,32 +227,10 @@ public:
static size_t CalculateCommandLineLengthLimit();
- static void EnableMessages() { s_DisableMessages = false; }
- static void DisableMessages() { s_DisableMessages = true; }
static void DisableRunCommandOutput() { s_DisableRunCommandOutput = true; }
static void EnableRunCommandOutput() { s_DisableRunCommandOutput = false; }
static bool GetRunCommandOutput() { return s_DisableRunCommandOutput; }
- /**
- * Some constants for different file formats.
- */
- enum FileFormat
- {
- NO_FILE_FORMAT = 0,
- C_FILE_FORMAT,
- CXX_FILE_FORMAT,
- FORTRAN_FILE_FORMAT,
- JAVA_FILE_FORMAT,
- HEADER_FILE_FORMAT,
- RESOURCE_FILE_FORMAT,
- DEFINITION_FILE_FORMAT,
- STATIC_LIBRARY_FILE_FORMAT,
- SHARED_LIBRARY_FILE_FORMAT,
- MODULE_FILE_FORMAT,
- OBJECT_FILE_FORMAT,
- UNKNOWN_FILE_FORMAT
- };
-
enum CompareOp
{
OP_EQUAL = 1,
@@ -318,13 +261,8 @@ public:
*/
static int strverscmp(std::string const& lhs, std::string const& rhs);
- /**
- * Determine the file type based on the extension
- */
- static FileFormat GetFileFormat(const char* ext);
-
/** Windows if this is true, the CreateProcess in RunCommand will
- * not show new consol windows when running programs.
+ * not show new console windows when running programs.
*/
static void SetRunCommandHideConsole(bool v) { s_RunCommandHideConsole = v; }
static bool GetRunCommandHideConsole() { return s_RunCommandHideConsole; }
@@ -335,23 +273,20 @@ 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
- false only if the last line stored had no newline. */
- static bool Split(const char* s, std::vector<std::string>& l);
static void SetForceUnixPaths(bool v) { s_ForceUnixPaths = v; }
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
// be used when RunCommand is called from cmake, because the
// running cmake needs paths to be in its format
- static std::string ConvertToRunCommandPath(const char* path);
+ static std::string ConvertToRunCommandPath(const std::string& path);
/** compute the relative path from local to remote. local must
be a directory. remote can be a file or a directory.
@@ -361,15 +296,18 @@ 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"
+ /**
+ * Convert the given remote path to a relative path with respect to
+ * the given local path. Both paths must use forward slashes and not
+ * already be escaped or quoted.
*/
- static std::string CollapseCombinedPath(std::string const& dir,
- std::string const& file);
+ static std::string ForceToRelativePath(std::string const& local_path,
+ std::string const& remote_path);
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
/** Remove an environment variable */
static bool UnsetEnv(const char* value);
@@ -386,11 +324,13 @@ public:
original environment. */
class SaveRestoreEnvironment
{
- CM_DISABLE_COPY(SaveRestoreEnvironment)
public:
SaveRestoreEnvironment();
~SaveRestoreEnvironment();
+ SaveRestoreEnvironment(SaveRestoreEnvironment const&) = delete;
+ SaveRestoreEnvironment& operator=(SaveRestoreEnvironment const&) = delete;
+
private:
std::vector<std::string> Env;
};
@@ -399,21 +339,33 @@ public:
/** Setup the environment to enable VS 8 IDE output. */
static void EnableVSConsoleOutput();
+ enum cmTarAction
+ {
+ TarActionCreate,
+ TarActionList,
+ TarActionExtract,
+ TarActionNone
+ };
+
/** Create tar */
enum cmTarCompression
{
TarCompressGZip,
TarCompressBZip2,
TarCompressXZ,
+ TarCompressZstd,
TarCompressNone
};
- static bool ListTar(const char* outFileName, bool verbose);
- static bool CreateTar(const char* outFileName,
+
+ static bool ListTar(const std::string& outFileName,
+ const std::vector<std::string>& files, bool verbose);
+ static bool CreateTar(const std::string& outFileName,
const std::vector<std::string>& files,
cmTarCompression compressType, bool verbose,
std::string const& mtime = std::string(),
std::string const& format = std::string());
- static bool ExtractTar(const char* inFileName, bool verbose);
+ static bool ExtractTar(const std::string& inFileName,
+ const std::vector<std::string>& files, bool verbose);
// This should be called first thing in main
// it will keep child processes from inheriting the
// stdin and stdout of this process. This is important
@@ -421,15 +373,7 @@ public:
// not get stuck waiting for all the output on the pipes.
static void DoNotInheritStdPipes();
- /** Copy the file create/access/modify times from the file named by
- the first argument to that named by the second. */
- static bool CopyFileTime(const char* fromFile, const char* toFile);
-
- /** Save and restore file times. */
- static cmSystemToolsFileTime* FileTimeNew();
- static void FileTimeDelete(cmSystemToolsFileTime*);
- static bool FileTimeGet(const char* fname, cmSystemToolsFileTime* t);
- static bool FileTimeSet(const char* fname, cmSystemToolsFileTime* t);
+ static void EnsureStdPipes();
/** Random seed generation. */
static unsigned int RandomSeed();
@@ -461,28 +405,24 @@ public:
/** Try to set the RPATH in an ELF binary. */
static bool ChangeRPath(std::string const& file, std::string const& oldRPath,
std::string const& newRPath,
- std::string* emsg = CM_NULLPTR,
- bool* changed = CM_NULLPTR);
+ bool removeEnvironmentRPath,
+ std::string* emsg = nullptr,
+ bool* changed = nullptr);
/** Try to remove the RPATH from an ELF binary. */
- static bool RemoveRPath(std::string const& file,
- std::string* emsg = CM_NULLPTR,
- bool* removed = CM_NULLPTR);
+ static bool RemoveRPath(std::string const& file, std::string* emsg = nullptr,
+ bool* removed = nullptr);
/** Check whether the RPATH in an ELF binary contains the path
given. */
static bool CheckRPath(std::string const& file, std::string const& newRPath);
/** Remove a directory; repeat a few times in case of locked files. */
- static bool RepeatedRemoveDirectory(const char* dir);
-
- /** Tokenize a string */
- static std::vector<std::string> tokenize(const std::string& str,
- const std::string& sep);
+ static bool RepeatedRemoveDirectory(const std::string& dir);
- /** Convert string to long. Expected that the whole string is an integer */
- static bool StringToLong(const char* str, long* value);
- static bool StringToULong(const char* str, unsigned long* value);
+ /** Encode a string as a URL. */
+ static std::string EncodeURL(std::string const& in,
+ bool escapeSlashes = true);
#ifdef _WIN32
struct WindowsFileRetry
@@ -492,21 +432,34 @@ public:
};
static WindowsFileRetry GetWindowsFileRetry();
#endif
+
+ /** Get the real path for a given path, removing all symlinks.
+ This variant of GetRealPath also works on Windows but will
+ resolve subst drives too. */
+ static std::string GetRealPathResolvingWindowsSubst(
+ const std::string& path, std::string* errorMessage = nullptr);
+
+ /** Perform one-time initialization of libuv. */
+ static void InitializeLibUV();
+
+ /** Create a symbolic link if the platform supports it. Returns whether
+ creation succeeded. */
+ static bool CreateSymlink(const std::string& origName,
+ const std::string& newName,
+ std::string* errorMessage = nullptr);
+
+ /** Create a hard link if the platform supports it. Returns whether
+ creation succeeded. */
+ static bool CreateLink(const std::string& origName,
+ const std::string& newName,
+ std::string* errorMessage = nullptr);
+
private:
static bool s_ForceUnixPaths;
static bool s_RunCommandHideConsole;
static bool s_ErrorOccured;
static bool s_FatalErrorOccured;
- static bool s_DisableMessages;
static bool s_DisableRunCommandOutput;
- static MessageCallback s_MessageCallback;
- static OutputCallback s_StdoutCallback;
- static OutputCallback s_StderrCallback;
- static InterruptCallback s_InterruptCallback;
- static void* s_MessageCallbackClientData;
- static void* s_StdoutCallbackClientData;
- static void* s_StderrCallbackClientData;
- static void* s_InterruptCallbackClientData;
};
#endif
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index c95a3ca2c..80986fca4 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -2,31 +2,39 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTarget.h"
-#include "cmsys/RegularExpression.hxx"
#include <algorithm>
-#include <assert.h>
-#include <map>
+#include <cassert>
+#include <cstring>
+#include <initializer_list>
+#include <iterator>
#include <set>
#include <sstream>
-#include <string.h>
+#include <unordered_set>
+
+#include <cm/memory>
+
+#include "cmsys/RegularExpression.hxx"
#include "cmAlgorithms.h"
+#include "cmCustomCommand.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmMessenger.h"
-#include "cmOutputConverter.h"
#include "cmProperty.h"
+#include "cmPropertyMap.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
+#include "cmSourceFileLocationKind.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
#include "cmTargetPropertyComputer.h"
-#include "cm_unordered_set.hxx"
#include "cmake.h"
template <>
@@ -75,34 +83,29 @@ const char* cmTargetPropertyComputer::GetSources<cmTarget>(
{
cmStringRange entries = tgt->GetSourceEntries();
if (entries.empty()) {
- return CM_NULLPTR;
+ return nullptr;
}
std::ostringstream ss;
const char* sep = "";
- for (std::vector<std::string>::const_iterator i = entries.begin();
- i != entries.end(); ++i) {
- std::string const& entry = *i;
-
- std::vector<std::string> files;
- cmSystemTools::ExpandListArgument(entry, files);
- for (std::vector<std::string>::const_iterator li = files.begin();
- li != files.end(); ++li) {
- if (cmHasLiteralPrefix(*li, "$<TARGET_OBJECTS:") &&
- (*li)[li->size() - 1] == '>') {
- std::string objLibName = li->substr(17, li->size() - 18);
+ for (std::string const& entry : entries) {
+ std::vector<std::string> files = cmExpandedList(entry);
+ for (std::string const& file : files) {
+ if (cmHasLiteralPrefix(file, "$<TARGET_OBJECTS:") &&
+ file.back() == '>') {
+ std::string objLibName = file.substr(17, file.size() - 18);
if (cmGeneratorExpression::Find(objLibName) != std::string::npos) {
ss << sep;
sep = ";";
- ss << *li;
+ ss << file;
continue;
}
bool addContent = false;
bool noMessage = true;
std::ostringstream e;
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ MessageType messageType = MessageType::AUTHOR_WARNING;
switch (context.GetBottom().GetPolicy(cmPolicies::CMP0051)) {
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0051) << "\n";
@@ -116,28 +119,25 @@ const char* cmTargetPropertyComputer::GetSources<cmTarget>(
}
if (!noMessage) {
e << "Target \"" << tgt->GetName()
- << "\" contains "
- "$<TARGET_OBJECTS> generator expression in its sources "
- "list. "
- "This content was not previously part of the SOURCES "
- "property "
- "when that property was read at configure time. Code "
- "reading "
- "that property needs to be adapted to ignore the generator "
- "expression using the string(GENEX_STRIP) command.";
+ << "\" contains $<TARGET_OBJECTS> generator expression in its "
+ "sources list. This content was not previously part of the "
+ "SOURCES property when that property was read at configure "
+ "time. Code reading that property needs to be adapted to "
+ "ignore the generator expression using the string(GENEX_STRIP) "
+ "command.";
messenger->IssueMessage(messageType, e.str(), context);
}
if (addContent) {
ss << sep;
sep = ";";
- ss << *li;
+ ss << file;
}
- } else if (cmGeneratorExpression::Find(*li) == std::string::npos) {
+ } else if (cmGeneratorExpression::Find(file) == std::string::npos) {
ss << sep;
sep = ";";
- ss << *li;
+ ss << file;
} else {
- cmSourceFile* sf = tgt->GetMakefile()->GetOrCreateSource(*li);
+ cmSourceFile* sf = tgt->GetMakefile()->GetOrCreateSource(file);
// Construct what is known about this source file location.
cmSourceFileLocation const& location = sf->GetLocation();
std::string sname = location.GetDirectory();
@@ -161,6 +161,28 @@ const char* cmTargetPropertyComputer::GetSources<cmTarget>(
class cmTargetInternals
{
public:
+ cmStateEnums::TargetType TargetType;
+ cmMakefile* Makefile;
+ cmPolicies::PolicyMap PolicyMap;
+ std::string Name;
+ std::string InstallPath;
+ std::string RuntimeInstallPath;
+ cmPropertyMap Properties;
+ bool IsGeneratorProvided;
+ bool HaveInstallRule;
+ bool IsDLLPlatform;
+ bool IsAIX;
+ bool IsAndroid;
+ bool IsImportedTarget;
+ bool ImportedGloballyVisible;
+ bool BuildInterfaceIncludesAppended;
+ std::set<BT<std::string>> Utilities;
+ std::vector<cmCustomCommand> PreBuildCommands;
+ std::vector<cmCustomCommand> PreLinkCommands;
+ std::vector<cmCustomCommand> PostBuildCommands;
+ std::vector<cmInstallTargetGenerator*> InstallGenerators;
+ std::set<std::string> SystemIncludeDirectories;
+ cmTarget::LinkLibraryVectorType OriginalLinkLibraries;
std::vector<std::string> IncludeDirectoriesEntries;
std::vector<cmListFileBacktrace> IncludeDirectoriesBacktraces;
std::vector<std::string> CompileOptionsEntries;
@@ -169,147 +191,230 @@ public:
std::vector<cmListFileBacktrace> CompileFeaturesBacktraces;
std::vector<std::string> CompileDefinitionsEntries;
std::vector<cmListFileBacktrace> CompileDefinitionsBacktraces;
+ std::vector<std::string> PrecompileHeadersEntries;
+ std::vector<cmListFileBacktrace> PrecompileHeadersBacktraces;
std::vector<std::string> SourceEntries;
std::vector<cmListFileBacktrace> SourceBacktraces;
+ std::vector<std::string> LinkOptionsEntries;
+ std::vector<cmListFileBacktrace> LinkOptionsBacktraces;
+ std::vector<std::string> LinkDirectoriesEntries;
+ std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces;
std::vector<std::string> LinkImplementationPropertyEntries;
std::vector<cmListFileBacktrace> LinkImplementationPropertyBacktraces;
+ std::vector<std::pair<cmTarget::TLLSignature, cmListFileContext>>
+ TLLCommands;
+ cmListFileBacktrace Backtrace;
+
+public:
+ bool CheckImportedLibName(std::string const& prop,
+ std::string const& value) const;
+
+ std::string ProcessSourceItemCMP0049(const std::string& s);
};
cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
Visibility vis, cmMakefile* mf)
+ : impl(cm::make_unique<cmTargetInternals>())
{
assert(mf);
- this->Name = name;
- this->TargetTypeValue = type;
- this->Makefile = mf;
- this->HaveInstallRule = false;
- this->DLLPlatform = false;
- this->IsAndroid = false;
- this->IsImportedTarget =
+ impl->TargetType = type;
+ impl->Makefile = mf;
+ impl->Name = name;
+ impl->IsGeneratorProvided = false;
+ impl->HaveInstallRule = false;
+ impl->IsDLLPlatform = false;
+ impl->IsAIX = false;
+ impl->IsAndroid = false;
+ impl->IsImportedTarget =
(vis == VisibilityImported || vis == VisibilityImportedGlobally);
- this->ImportedGloballyVisible = vis == VisibilityImportedGlobally;
- this->BuildInterfaceIncludesAppended = false;
-
- // only add dependency information for library targets
- if (this->TargetTypeValue >= cmStateEnums::STATIC_LIBRARY &&
- this->TargetTypeValue <= cmStateEnums::MODULE_LIBRARY) {
- this->RecordDependencies = true;
- } else {
- this->RecordDependencies = false;
- }
+ impl->ImportedGloballyVisible = vis == VisibilityImportedGlobally;
+ impl->BuildInterfaceIncludesAppended = false;
// Check whether this is a DLL platform.
- this->DLLPlatform =
- (this->Makefile->IsOn("WIN32") || this->Makefile->IsOn("CYGWIN") ||
- this->Makefile->IsOn("MINGW"));
+ impl->IsDLLPlatform =
+ !impl->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
+
+ // Check whether we are targeting AIX.
+ impl->IsAIX =
+ (impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "AIX");
// Check whether we are targeting an Android platform.
- this->IsAndroid =
- strcmp(this->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME"),
- "Android") == 0;
+ impl->IsAndroid =
+ (impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "Android");
+
+ std::string defKey;
+ defKey.reserve(128);
+ defKey += "CMAKE_";
+ auto initProp = [this, mf, &defKey](const std::string& property) {
+ // Replace everything after "CMAKE_"
+ defKey.replace(defKey.begin() + 6, defKey.end(), property);
+ if (const char* value = mf->GetDefinition(defKey)) {
+ this->SetProperty(property, value);
+ }
+ };
+ auto initPropValue = [this, mf, &defKey](const std::string& property,
+ const char* default_value) {
+ // Replace everything after "CMAKE_"
+ defKey.replace(defKey.begin() + 6, defKey.end(), property);
+ if (const char* value = mf->GetDefinition(defKey)) {
+ this->SetProperty(property, value);
+ } else if (default_value) {
+ this->SetProperty(property, default_value);
+ }
+ };
// Setup default property values.
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
this->GetType() != cmStateEnums::UTILITY) {
- this->SetPropertyDefault("ANDROID_API", CM_NULLPTR);
- this->SetPropertyDefault("ANDROID_API_MIN", CM_NULLPTR);
- this->SetPropertyDefault("ANDROID_ARCH", CM_NULLPTR);
- this->SetPropertyDefault("ANDROID_STL_TYPE", CM_NULLPTR);
- this->SetPropertyDefault("ANDROID_SKIP_ANT_STEP", CM_NULLPTR);
- this->SetPropertyDefault("ANDROID_PROCESS_MAX", CM_NULLPTR);
- this->SetPropertyDefault("ANDROID_PROGUARD", CM_NULLPTR);
- this->SetPropertyDefault("ANDROID_PROGUARD_CONFIG_PATH", CM_NULLPTR);
- this->SetPropertyDefault("ANDROID_SECURE_PROPS_PATH", CM_NULLPTR);
- this->SetPropertyDefault("ANDROID_NATIVE_LIB_DIRECTORIES", CM_NULLPTR);
- this->SetPropertyDefault("ANDROID_NATIVE_LIB_DEPENDENCIES", CM_NULLPTR);
- this->SetPropertyDefault("ANDROID_JAVA_SOURCE_DIR", CM_NULLPTR);
- this->SetPropertyDefault("ANDROID_JAR_DIRECTORIES", CM_NULLPTR);
- this->SetPropertyDefault("ANDROID_JAR_DEPENDENCIES", CM_NULLPTR);
- this->SetPropertyDefault("ANDROID_ASSETS_DIRECTORIES", CM_NULLPTR);
- this->SetPropertyDefault("ANDROID_ANT_ADDITIONAL_OPTIONS", CM_NULLPTR);
- this->SetPropertyDefault("BUILD_RPATH", CM_NULLPTR);
- this->SetPropertyDefault("INSTALL_NAME_DIR", CM_NULLPTR);
- this->SetPropertyDefault("INSTALL_RPATH", "");
- this->SetPropertyDefault("INSTALL_RPATH_USE_LINK_PATH", "OFF");
- this->SetPropertyDefault("INTERPROCEDURAL_OPTIMIZATION", CM_NULLPTR);
- this->SetPropertyDefault("SKIP_BUILD_RPATH", "OFF");
- this->SetPropertyDefault("BUILD_WITH_INSTALL_RPATH", "OFF");
- this->SetPropertyDefault("ARCHIVE_OUTPUT_DIRECTORY", CM_NULLPTR);
- this->SetPropertyDefault("LIBRARY_OUTPUT_DIRECTORY", CM_NULLPTR);
- this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", CM_NULLPTR);
- this->SetPropertyDefault("PDB_OUTPUT_DIRECTORY", CM_NULLPTR);
- this->SetPropertyDefault("COMPILE_PDB_OUTPUT_DIRECTORY", CM_NULLPTR);
- this->SetPropertyDefault("Fortran_FORMAT", CM_NULLPTR);
- this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", CM_NULLPTR);
- this->SetPropertyDefault("GNUtoMS", CM_NULLPTR);
- this->SetPropertyDefault("OSX_ARCHITECTURES", CM_NULLPTR);
- this->SetPropertyDefault("IOS_INSTALL_COMBINED", CM_NULLPTR);
- this->SetPropertyDefault("AUTOMOC", CM_NULLPTR);
- this->SetPropertyDefault("AUTOUIC", CM_NULLPTR);
- this->SetPropertyDefault("AUTORCC", CM_NULLPTR);
- this->SetPropertyDefault("AUTOMOC_DEPEND_FILTERS", CM_NULLPTR);
- this->SetPropertyDefault("AUTOMOC_MOC_OPTIONS", CM_NULLPTR);
- this->SetPropertyDefault("AUTOUIC_OPTIONS", CM_NULLPTR);
- this->SetPropertyDefault("AUTOUIC_SEARCH_PATHS", CM_NULLPTR);
- this->SetPropertyDefault("AUTORCC_OPTIONS", CM_NULLPTR);
- this->SetPropertyDefault("LINK_DEPENDS_NO_SHARED", CM_NULLPTR);
- this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", CM_NULLPTR);
- this->SetPropertyDefault("WIN32_EXECUTABLE", CM_NULLPTR);
- this->SetPropertyDefault("MACOSX_BUNDLE", CM_NULLPTR);
- this->SetPropertyDefault("MACOSX_RPATH", CM_NULLPTR);
- this->SetPropertyDefault("BUILD_WITH_INSTALL_NAME_DIR", CM_NULLPTR);
- this->SetPropertyDefault("C_CLANG_TIDY", CM_NULLPTR);
- this->SetPropertyDefault("C_COMPILER_LAUNCHER", CM_NULLPTR);
- this->SetPropertyDefault("C_CPPLINT", CM_NULLPTR);
- this->SetPropertyDefault("C_INCLUDE_WHAT_YOU_USE", CM_NULLPTR);
- this->SetPropertyDefault("LINK_WHAT_YOU_USE", CM_NULLPTR);
- this->SetPropertyDefault("C_STANDARD", CM_NULLPTR);
- this->SetPropertyDefault("C_STANDARD_REQUIRED", CM_NULLPTR);
- this->SetPropertyDefault("C_EXTENSIONS", CM_NULLPTR);
- this->SetPropertyDefault("CXX_CLANG_TIDY", CM_NULLPTR);
- this->SetPropertyDefault("CXX_COMPILER_LAUNCHER", CM_NULLPTR);
- this->SetPropertyDefault("CXX_CPPLINT", CM_NULLPTR);
- this->SetPropertyDefault("CXX_INCLUDE_WHAT_YOU_USE", CM_NULLPTR);
- this->SetPropertyDefault("CXX_STANDARD", CM_NULLPTR);
- this->SetPropertyDefault("CXX_STANDARD_REQUIRED", CM_NULLPTR);
- this->SetPropertyDefault("CXX_EXTENSIONS", CM_NULLPTR);
- this->SetPropertyDefault("CUDA_STANDARD", CM_NULLPTR);
- this->SetPropertyDefault("CUDA_STANDARD_REQUIRED", CM_NULLPTR);
- this->SetPropertyDefault("CUDA_EXTENSIONS", CM_NULLPTR);
- this->SetPropertyDefault("LINK_SEARCH_START_STATIC", CM_NULLPTR);
- this->SetPropertyDefault("LINK_SEARCH_END_STATIC", CM_NULLPTR);
+ initProp("ANDROID_API");
+ initProp("ANDROID_API_MIN");
+ initProp("ANDROID_ARCH");
+ initProp("ANDROID_STL_TYPE");
+ initProp("ANDROID_SKIP_ANT_STEP");
+ initProp("ANDROID_PROCESS_MAX");
+ initProp("ANDROID_PROGUARD");
+ initProp("ANDROID_PROGUARD_CONFIG_PATH");
+ initProp("ANDROID_SECURE_PROPS_PATH");
+ initProp("ANDROID_NATIVE_LIB_DIRECTORIES");
+ initProp("ANDROID_NATIVE_LIB_DEPENDENCIES");
+ initProp("ANDROID_JAVA_SOURCE_DIR");
+ initProp("ANDROID_JAR_DIRECTORIES");
+ initProp("ANDROID_JAR_DEPENDENCIES");
+ initProp("ANDROID_ASSETS_DIRECTORIES");
+ initProp("ANDROID_ANT_ADDITIONAL_OPTIONS");
+ initProp("BUILD_RPATH");
+ initProp("BUILD_RPATH_USE_ORIGIN");
+ initProp("INSTALL_NAME_DIR");
+ initProp("INSTALL_REMOVE_ENVIRONMENT_RPATH");
+ initPropValue("INSTALL_RPATH", "");
+ initPropValue("INSTALL_RPATH_USE_LINK_PATH", "OFF");
+ initProp("INTERPROCEDURAL_OPTIMIZATION");
+ initPropValue("SKIP_BUILD_RPATH", "OFF");
+ initPropValue("BUILD_WITH_INSTALL_RPATH", "OFF");
+ initProp("ARCHIVE_OUTPUT_DIRECTORY");
+ initProp("LIBRARY_OUTPUT_DIRECTORY");
+ initProp("RUNTIME_OUTPUT_DIRECTORY");
+ initProp("PDB_OUTPUT_DIRECTORY");
+ initProp("COMPILE_PDB_OUTPUT_DIRECTORY");
+ initProp("FRAMEWORK");
+ initProp("Fortran_FORMAT");
+ initProp("Fortran_MODULE_DIRECTORY");
+ initProp("Fortran_COMPILER_LAUNCHER");
+ initProp("GNUtoMS");
+ initProp("OSX_ARCHITECTURES");
+ initProp("IOS_INSTALL_COMBINED");
+ initProp("AUTOMOC");
+ initProp("AUTOUIC");
+ initProp("AUTORCC");
+ initProp("AUTOGEN_ORIGIN_DEPENDS");
+ initProp("AUTOGEN_PARALLEL");
+ initProp("AUTOMOC_COMPILER_PREDEFINES");
+ initProp("AUTOMOC_DEPEND_FILTERS");
+ initProp("AUTOMOC_MACRO_NAMES");
+ initProp("AUTOMOC_MOC_OPTIONS");
+ initProp("AUTOUIC_OPTIONS");
+ initProp("AUTOMOC_PATH_PREFIX");
+ initProp("AUTOUIC_SEARCH_PATHS");
+ initProp("AUTORCC_OPTIONS");
+ initProp("LINK_DEPENDS_NO_SHARED");
+ initProp("LINK_INTERFACE_LIBRARIES");
+ initProp("MSVC_RUNTIME_LIBRARY");
+ initProp("WIN32_EXECUTABLE");
+ initProp("MACOSX_BUNDLE");
+ initProp("MACOSX_RPATH");
+ initProp("NO_SYSTEM_FROM_IMPORTED");
+ initProp("BUILD_WITH_INSTALL_NAME_DIR");
+ initProp("C_CLANG_TIDY");
+ initProp("C_COMPILER_LAUNCHER");
+ initProp("C_CPPLINT");
+ initProp("C_CPPCHECK");
+ initProp("C_INCLUDE_WHAT_YOU_USE");
+ initProp("LINK_WHAT_YOU_USE");
+ initProp("C_STANDARD");
+ initProp("C_STANDARD_REQUIRED");
+ initProp("C_EXTENSIONS");
+ initProp("OBJC_COMPILER_LAUNCHER");
+ initProp("OBJC_STANDARD");
+ initProp("OBJC_STANDARD_REQUIRED");
+ initProp("OBJC_EXTENSIONS");
+ initProp("CXX_CLANG_TIDY");
+ initProp("CXX_COMPILER_LAUNCHER");
+ initProp("CXX_CPPLINT");
+ initProp("CXX_CPPCHECK");
+ initProp("CXX_INCLUDE_WHAT_YOU_USE");
+ initProp("CXX_STANDARD");
+ initProp("CXX_STANDARD_REQUIRED");
+ initProp("CXX_EXTENSIONS");
+ initProp("OBJCXX_COMPILER_LAUNCHER");
+ initProp("OBJCXX_STANDARD");
+ initProp("OBJCXX_STANDARD_REQUIRED");
+ initProp("OBJCXX_EXTENSIONS");
+ initProp("CUDA_STANDARD");
+ initProp("CUDA_STANDARD_REQUIRED");
+ initProp("CUDA_EXTENSIONS");
+ initProp("CUDA_COMPILER_LAUNCHER");
+ initProp("CUDA_SEPARABLE_COMPILATION");
+ initProp("CUDA_RESOLVE_DEVICE_SYMBOLS");
+ initProp("LINK_SEARCH_START_STATIC");
+ initProp("LINK_SEARCH_END_STATIC");
+ initProp("FOLDER");
+ initProp("Swift_LANGUAGE_VERSION");
+ initProp("Swift_MODULE_DIRECTORY");
+ initProp("VS_JUST_MY_CODE_DEBUGGING");
+ initProp("DISABLE_PRECOMPILE_HEADERS");
+ initProp("UNITY_BUILD");
+ initPropValue("UNITY_BUILD_BATCH_SIZE", "8");
+#ifdef __APPLE__
+ if (this->GetGlobalGenerator()->IsXcode()) {
+ initProp("XCODE_SCHEME_ADDRESS_SANITIZER");
+ initProp("XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN");
+ initProp("XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING");
+ initProp("XCODE_SCHEME_THREAD_SANITIZER");
+ initProp("XCODE_SCHEME_THREAD_SANITIZER_STOP");
+ initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER");
+ initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP");
+ initProp("XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER");
+ initProp("XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP");
+ initProp("XCODE_SCHEME_MALLOC_SCRIBBLE");
+ initProp("XCODE_SCHEME_MALLOC_GUARD_EDGES");
+ initProp("XCODE_SCHEME_GUARD_MALLOC");
+ initProp("XCODE_SCHEME_ZOMBIE_OBJECTS");
+ initProp("XCODE_SCHEME_MALLOC_STACK");
+ initProp("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE");
+ initProp("XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS");
+ }
+#endif
}
- if (this->GetType() != cmStateEnums::UTILITY) {
- this->SetPropertyDefault("NO_SYSTEM_FROM_IMPORTED", CM_NULLPTR);
+ if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetGlobalGenerator()->IsXcode()) {
+ initProp("XCODE_GENERATE_SCHEME");
+ }
}
- // Collect the set of configuration types.
- std::vector<std::string> configNames;
- mf->GetConfigurations(configNames);
-
// Setup per-configuration property default values.
if (this->GetType() != cmStateEnums::UTILITY) {
- const char* configProps[] = {
+ static const auto configProps = {
/* clang-format needs this comment to break after the opening brace */
"ARCHIVE_OUTPUT_DIRECTORY_", "LIBRARY_OUTPUT_DIRECTORY_",
"RUNTIME_OUTPUT_DIRECTORY_", "PDB_OUTPUT_DIRECTORY_",
"COMPILE_PDB_OUTPUT_DIRECTORY_", "MAP_IMPORTED_CONFIG_",
- "INTERPROCEDURAL_OPTIMIZATION_", CM_NULLPTR
+ "INTERPROCEDURAL_OPTIMIZATION_"
};
- for (std::vector<std::string>::iterator ci = configNames.begin();
- ci != configNames.end(); ++ci) {
- std::string configUpper = cmSystemTools::UpperCase(*ci);
- for (const char** p = configProps; *p; ++p) {
+ // Collect the set of configuration types.
+ std::vector<std::string> configNames;
+ mf->GetConfigurations(configNames);
+ for (std::string const& configName : configNames) {
+ std::string configUpper = cmSystemTools::UpperCase(configName);
+ for (auto const& prop : configProps) {
// Interface libraries have no output locations, so honor only
// the configuration map.
- if (this->TargetTypeValue == cmStateEnums::INTERFACE_LIBRARY &&
- strcmp(*p, "MAP_IMPORTED_CONFIG_") != 0) {
+ if (impl->TargetType == cmStateEnums::INTERFACE_LIBRARY &&
+ strcmp(prop, "MAP_IMPORTED_CONFIG_") != 0) {
continue;
}
- std::string property = *p;
- property += configUpper;
- this->SetPropertyDefault(property, CM_NULLPTR);
+ std::string property = cmStrCat(prop, configUpper);
+ initProp(property);
}
// Initialize per-configuration name postfix property from the
@@ -317,125 +422,172 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
// compatibility with previous CMake versions in which executables
// did not support this variable. Projects may still specify the
// property directly.
- if (this->TargetTypeValue != cmStateEnums::EXECUTABLE &&
- this->TargetTypeValue != cmStateEnums::INTERFACE_LIBRARY) {
- std::string property = cmSystemTools::UpperCase(*ci);
- property += "_POSTFIX";
- this->SetPropertyDefault(property, CM_NULLPTR);
+ if (impl->TargetType != cmStateEnums::EXECUTABLE &&
+ impl->TargetType != cmStateEnums::INTERFACE_LIBRARY) {
+ std::string property =
+ cmStrCat(cmSystemTools::UpperCase(configName), "_POSTFIX");
+ initProp(property);
}
}
}
// Save the backtrace of target construction.
- this->Backtrace = this->Makefile->GetBacktrace();
+ impl->Backtrace = impl->Makefile->GetBacktrace();
if (!this->IsImported()) {
// Initialize the INCLUDE_DIRECTORIES property based on the current value
// of the same directory property:
- const cmStringRange parentIncludes =
- this->Makefile->GetIncludeDirectoriesEntries();
- const cmBacktraceRange parentIncludesBts =
- this->Makefile->GetIncludeDirectoriesBacktraces();
-
- this->Internal->IncludeDirectoriesEntries.insert(
- this->Internal->IncludeDirectoriesEntries.end(), parentIncludes.begin(),
- parentIncludes.end());
- this->Internal->IncludeDirectoriesBacktraces.insert(
- this->Internal->IncludeDirectoriesBacktraces.end(),
- parentIncludesBts.begin(), parentIncludesBts.end());
-
- const std::set<std::string> parentSystemIncludes =
- this->Makefile->GetSystemIncludeDirectories();
+ cmAppend(impl->IncludeDirectoriesEntries,
+ impl->Makefile->GetIncludeDirectoriesEntries());
+ cmAppend(impl->IncludeDirectoriesBacktraces,
+ impl->Makefile->GetIncludeDirectoriesBacktraces());
+
+ {
+ auto const& sysInc = impl->Makefile->GetSystemIncludeDirectories();
+ impl->SystemIncludeDirectories.insert(sysInc.begin(), sysInc.end());
+ }
- this->SystemIncludeDirectories.insert(parentSystemIncludes.begin(),
- parentSystemIncludes.end());
+ cmAppend(impl->CompileOptionsEntries,
+ impl->Makefile->GetCompileOptionsEntries());
+ cmAppend(impl->CompileOptionsBacktraces,
+ impl->Makefile->GetCompileOptionsBacktraces());
- const cmStringRange parentOptions =
- this->Makefile->GetCompileOptionsEntries();
- const cmBacktraceRange parentOptionsBts =
- this->Makefile->GetCompileOptionsBacktraces();
+ cmAppend(impl->LinkOptionsEntries,
+ impl->Makefile->GetLinkOptionsEntries());
+ cmAppend(impl->LinkOptionsBacktraces,
+ impl->Makefile->GetLinkOptionsBacktraces());
- this->Internal->CompileOptionsEntries.insert(
- this->Internal->CompileOptionsEntries.end(), parentOptions.begin(),
- parentOptions.end());
- this->Internal->CompileOptionsBacktraces.insert(
- this->Internal->CompileOptionsBacktraces.end(), parentOptionsBts.begin(),
- parentOptionsBts.end());
+ cmAppend(impl->LinkDirectoriesEntries,
+ impl->Makefile->GetLinkDirectoriesEntries());
+ cmAppend(impl->LinkDirectoriesBacktraces,
+ impl->Makefile->GetLinkDirectoriesBacktraces());
}
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
this->GetType() != cmStateEnums::UTILITY) {
- this->SetPropertyDefault("C_VISIBILITY_PRESET", CM_NULLPTR);
- this->SetPropertyDefault("CXX_VISIBILITY_PRESET", CM_NULLPTR);
- this->SetPropertyDefault("CUDA_VISIBILITY_PRESET", CM_NULLPTR);
- this->SetPropertyDefault("VISIBILITY_INLINES_HIDDEN", CM_NULLPTR);
+ initProp("C_VISIBILITY_PRESET");
+ initProp("CXX_VISIBILITY_PRESET");
+ initProp("OBJC_VISIBILITY_PRESET");
+ initProp("OBJCXX_VISIBILITY_PRESET");
+ initProp("CUDA_VISIBILITY_PRESET");
+ initProp("VISIBILITY_INLINES_HIDDEN");
}
- if (this->TargetTypeValue == cmStateEnums::EXECUTABLE) {
- this->SetPropertyDefault("ANDROID_GUI", CM_NULLPTR);
- this->SetPropertyDefault("CROSSCOMPILING_EMULATOR", CM_NULLPTR);
- this->SetPropertyDefault("ENABLE_EXPORTS", CM_NULLPTR);
+ if (impl->TargetType == cmStateEnums::EXECUTABLE) {
+ initProp("ANDROID_GUI");
+ initProp("CROSSCOMPILING_EMULATOR");
+ initProp("ENABLE_EXPORTS");
}
- if (this->TargetTypeValue == cmStateEnums::SHARED_LIBRARY ||
- this->TargetTypeValue == cmStateEnums::MODULE_LIBRARY) {
+ if (impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
+ impl->TargetType == cmStateEnums::MODULE_LIBRARY) {
this->SetProperty("POSITION_INDEPENDENT_CODE", "True");
}
- if (this->TargetTypeValue == cmStateEnums::SHARED_LIBRARY ||
- this->TargetTypeValue == cmStateEnums::EXECUTABLE) {
- this->SetPropertyDefault("WINDOWS_EXPORT_ALL_SYMBOLS", CM_NULLPTR);
+ if (impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
+ impl->TargetType == cmStateEnums::EXECUTABLE) {
+ initProp("WINDOWS_EXPORT_ALL_SYMBOLS");
}
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
this->GetType() != cmStateEnums::UTILITY) {
- this->SetPropertyDefault("POSITION_INDEPENDENT_CODE", CM_NULLPTR);
+ initProp("POSITION_INDEPENDENT_CODE");
}
// Record current policies for later use.
- this->Makefile->RecordPolicies(this->PolicyMap);
+ impl->Makefile->RecordPolicies(impl->PolicyMap);
- if (this->TargetTypeValue == cmStateEnums::INTERFACE_LIBRARY) {
+ if (impl->TargetType == cmStateEnums::INTERFACE_LIBRARY) {
// This policy is checked in a few conditions. The properties relevant
// to the policy are always ignored for cmStateEnums::INTERFACE_LIBRARY
// targets,
// so ensure that the conditions don't lead to nonsense.
- this->PolicyMap.Set(cmPolicies::CMP0022, cmPolicies::NEW);
+ impl->PolicyMap.Set(cmPolicies::CMP0022, cmPolicies::NEW);
}
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
this->GetType() != cmStateEnums::UTILITY) {
- this->SetPropertyDefault("JOB_POOL_COMPILE", CM_NULLPTR);
- this->SetPropertyDefault("JOB_POOL_LINK", CM_NULLPTR);
+ initProp("JOB_POOL_COMPILE");
+ initProp("JOB_POOL_LINK");
+ }
+
+ if (impl->TargetType <= cmStateEnums::UTILITY) {
+ initProp("DOTNET_TARGET_FRAMEWORK_VERSION");
+ }
+
+ if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
+ this->GetType() != cmStateEnums::UTILITY) {
+
+ // check for "CMAKE_VS_GLOBALS" variable and set up target properties
+ // if any
+ const char* globals = mf->GetDefinition("CMAKE_VS_GLOBALS");
+ if (globals) {
+ const std::string genName = mf->GetGlobalGenerator()->GetName();
+ if (cmHasLiteralPrefix(genName, "Visual Studio")) {
+ std::vector<std::string> props = cmExpandedList(globals);
+ const std::string vsGlobal = "VS_GLOBAL_";
+ for (const std::string& i : props) {
+ // split NAME=VALUE
+ const std::string::size_type assignment = i.find('=');
+ if (assignment != std::string::npos) {
+ const std::string propName = vsGlobal + i.substr(0, assignment);
+ const std::string propValue = i.substr(assignment + 1);
+ initPropValue(propName, propValue.c_str());
+ }
+ }
+ }
+ }
}
}
-cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
+cmTarget::cmTarget(cmTarget&&) noexcept = default;
+cmTarget::~cmTarget() = default;
+
+cmTarget& cmTarget::operator=(cmTarget&&) noexcept = default;
+
+cmStateEnums::TargetType cmTarget::GetType() const
{
- return this->GetMakefile()->GetGlobalGenerator();
+ return impl->TargetType;
}
-void cmTarget::AddUtility(const std::string& u, cmMakefile* makefile)
+cmMakefile* cmTarget::GetMakefile() const
{
- if (this->Utilities.insert(u).second && makefile) {
- this->UtilityBacktraces.insert(
- std::make_pair(u, makefile->GetBacktrace()));
- }
+ return impl->Makefile;
}
-cmListFileBacktrace const* cmTarget::GetUtilityBacktrace(
- const std::string& u) const
+cmPolicies::PolicyMap const& cmTarget::GetPolicyMap() const
{
- std::map<std::string, cmListFileBacktrace>::const_iterator i =
- this->UtilityBacktraces.find(u);
- if (i == this->UtilityBacktraces.end()) {
- return CM_NULLPTR;
- }
+ return impl->PolicyMap;
+}
+
+const std::string& cmTarget::GetName() const
+{
+ return impl->Name;
+}
+
+cmPolicies::PolicyStatus cmTarget::GetPolicyStatus(
+ cmPolicies::PolicyID policy) const
+{
+ return impl->PolicyMap.Get(policy);
+}
+
+cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
+{
+ return impl->Makefile->GetGlobalGenerator();
+}
- return &i->second;
+void cmTarget::AddUtility(std::string const& name, cmMakefile* mf)
+{
+ impl->Utilities.insert(
+ BT<std::string>(name, mf ? mf->GetBacktrace() : cmListFileBacktrace()));
+}
+
+std::set<BT<std::string>> const& cmTarget::GetUtilities() const
+{
+ return impl->Utilities;
}
cmListFileBacktrace const& cmTarget::GetBacktrace() const
{
- return this->Backtrace;
+ return impl->Backtrace;
}
bool cmTarget::IsExecutableWithExports() const
@@ -444,34 +596,72 @@ bool cmTarget::IsExecutableWithExports() const
this->GetPropertyAsBool("ENABLE_EXPORTS"));
}
-bool cmTarget::HasImportLibrary() const
-{
- return (this->DLLPlatform &&
- (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
- this->IsExecutableWithExports()));
-}
-
bool cmTarget::IsFrameworkOnApple() const
{
return ((this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::STATIC_LIBRARY) &&
- this->Makefile->IsOn("APPLE") &&
+ impl->Makefile->IsOn("APPLE") &&
this->GetPropertyAsBool("FRAMEWORK"));
}
bool cmTarget::IsAppBundleOnApple() const
{
return (this->GetType() == cmStateEnums::EXECUTABLE &&
- this->Makefile->IsOn("APPLE") &&
+ impl->Makefile->IsOn("APPLE") &&
this->GetPropertyAsBool("MACOSX_BUNDLE"));
}
+std::vector<cmCustomCommand> const& cmTarget::GetPreBuildCommands() const
+{
+ return impl->PreBuildCommands;
+}
+
+void cmTarget::AddPreBuildCommand(cmCustomCommand const& cmd)
+{
+ impl->PreBuildCommands.push_back(cmd);
+}
+
+void cmTarget::AddPreBuildCommand(cmCustomCommand&& cmd)
+{
+ impl->PreBuildCommands.push_back(std::move(cmd));
+}
+
+std::vector<cmCustomCommand> const& cmTarget::GetPreLinkCommands() const
+{
+ return impl->PreLinkCommands;
+}
+
+void cmTarget::AddPreLinkCommand(cmCustomCommand const& cmd)
+{
+ impl->PreLinkCommands.push_back(cmd);
+}
+
+void cmTarget::AddPreLinkCommand(cmCustomCommand&& cmd)
+{
+ impl->PreLinkCommands.push_back(std::move(cmd));
+}
+
+std::vector<cmCustomCommand> const& cmTarget::GetPostBuildCommands() const
+{
+ return impl->PostBuildCommands;
+}
+
+void cmTarget::AddPostBuildCommand(cmCustomCommand const& cmd)
+{
+ impl->PostBuildCommands.push_back(cmd);
+}
+
+void cmTarget::AddPostBuildCommand(cmCustomCommand&& cmd)
+{
+ impl->PostBuildCommands.push_back(std::move(cmd));
+}
+
void cmTarget::AddTracedSources(std::vector<std::string> const& srcs)
{
if (!srcs.empty()) {
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->SourceEntries.push_back(cmJoin(srcs, ";"));
- this->Internal->SourceBacktraces.push_back(lfbt);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->SourceEntries.push_back(cmJoin(srcs, ";"));
+ impl->SourceBacktraces.push_back(lfbt);
}
}
@@ -479,42 +669,38 @@ void cmTarget::AddSources(std::vector<std::string> const& srcs)
{
std::string srcFiles;
const char* sep = "";
- for (std::vector<std::string>::const_iterator i = srcs.begin();
- i != srcs.end(); ++i) {
- std::string filename = *i;
- const char* src = filename.c_str();
-
- if (!(src[0] == '$' && src[1] == '<')) {
+ for (auto filename : srcs) {
+ if (!cmGeneratorExpression::StartsWithGeneratorExpression(filename)) {
if (!filename.empty()) {
- filename = this->ProcessSourceItemCMP0049(filename);
+ filename = impl->ProcessSourceItemCMP0049(filename);
if (filename.empty()) {
return;
}
}
- this->Makefile->GetOrCreateSource(filename);
+ impl->Makefile->GetOrCreateSource(filename);
}
srcFiles += sep;
srcFiles += filename;
sep = ";";
}
if (!srcFiles.empty()) {
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->SourceEntries.push_back(srcFiles);
- this->Internal->SourceBacktraces.push_back(lfbt);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->SourceEntries.push_back(std::move(srcFiles));
+ impl->SourceBacktraces.push_back(lfbt);
}
}
-std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s)
+std::string cmTargetInternals::ProcessSourceItemCMP0049(const std::string& s)
{
std::string src = s;
- // For backwards compatibility replace varibles in source names.
+ // For backwards compatibility replace variables in source names.
// This should eventually be removed.
this->Makefile->ExpandVariablesInString(src);
if (src != s) {
std::ostringstream e;
bool noMessage = false;
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ MessageType messageType = MessageType::AUTHOR_WARNING;
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0049)) {
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0049) << "\n";
@@ -525,15 +711,15 @@ std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s)
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::NEW:
- messageType = cmake::FATAL_ERROR;
+ messageType = MessageType::FATAL_ERROR;
}
if (!noMessage) {
e << "Legacy variable expansion in source file \"" << s
- << "\" expanded to \"" << src << "\" in target \"" << this->GetName()
+ << "\" expanded to \"" << src << "\" in target \"" << this->Name
<< "\". This behavior will be removed in a "
"future version of CMake.";
this->Makefile->IssueMessage(messageType, e.str());
- if (messageType == cmake::FATAL_ERROR) {
+ if (messageType == MessageType::FATAL_ERROR) {
return "";
}
}
@@ -541,13 +727,9 @@ std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s)
return src;
}
-cmSourceFile* cmTarget::AddSourceCMP0049(const std::string& s)
+std::string cmTarget::GetSourceCMP0049(const std::string& s)
{
- std::string src = this->ProcessSourceItemCMP0049(s);
- if (!s.empty() && src.empty()) {
- return CM_NULLPTR;
- }
- return this->AddSource(src);
+ return impl->ProcessSourceItemCMP0049(s);
}
struct CreateLocation
@@ -593,10 +775,10 @@ public:
bool operator()(std::string const& entry)
{
- std::vector<std::string> files;
- cmSystemTools::ExpandListArgument(entry, files);
- std::vector<cmSourceFileLocation> locations(files.size());
- std::transform(files.begin(), files.end(), locations.begin(),
+ std::vector<std::string> files = cmExpandedList(entry);
+ std::vector<cmSourceFileLocation> locations;
+ locations.reserve(files.size());
+ std::transform(files.begin(), files.end(), std::back_inserter(locations),
CreateLocation(this->Needle.GetMakefile()));
return std::find_if(locations.begin(), locations.end(),
@@ -604,57 +786,31 @@ public:
}
};
-cmSourceFile* cmTarget::AddSource(const std::string& src)
+cmSourceFile* cmTarget::AddSource(const std::string& src, bool before)
{
- cmSourceFileLocation sfl(this->Makefile, src);
- if (std::find_if(this->Internal->SourceEntries.begin(),
- this->Internal->SourceEntries.end(),
+ cmSourceFileLocation sfl(impl->Makefile, src,
+ cmSourceFileLocationKind::Known);
+ if (std::find_if(impl->SourceEntries.begin(), impl->SourceEntries.end(),
TargetPropertyEntryFinder(sfl)) ==
- this->Internal->SourceEntries.end()) {
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->SourceEntries.push_back(src);
- this->Internal->SourceBacktraces.push_back(lfbt);
+ impl->SourceEntries.end()) {
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->SourceEntries.insert(
+ before ? impl->SourceEntries.begin() : impl->SourceEntries.end(), src);
+ impl->SourceBacktraces.insert(before ? impl->SourceBacktraces.begin()
+ : impl->SourceBacktraces.end(),
+ lfbt);
}
if (cmGeneratorExpression::Find(src) != std::string::npos) {
- return CM_NULLPTR;
+ return nullptr;
}
- return this->Makefile->GetOrCreateSource(src);
-}
-
-void cmTarget::AddLinkDirectory(const std::string& d)
-{
- // Make sure we don't add unnecessary search directories.
- if (this->LinkDirectoriesEmmitted.insert(d).second) {
- this->LinkDirectories.push_back(d);
- }
-}
-
-const std::vector<std::string>& cmTarget::GetLinkDirectories() const
-{
- return this->LinkDirectories;
+ return impl->Makefile->GetOrCreateSource(src, false,
+ cmSourceFileLocationKind::Known);
}
-void cmTarget::ClearDependencyInformation(cmMakefile& mf,
- const std::string& target)
+void cmTarget::ClearDependencyInformation(cmMakefile& mf)
{
- // Clear the dependencies. The cache variable must exist iff we are
- // recording dependency information for this target.
- std::string depname = target;
- depname += "_LIB_DEPENDS";
- if (this->RecordDependencies) {
- mf.AddCacheDefinition(depname, "", "Dependencies for target",
- cmStateEnums::STATIC);
- } else {
- if (mf.GetDefinition(depname)) {
- std::string message = "Target ";
- message += target;
- message += " has dependency information when it shouldn't.\n";
- message += "Your cache is probably stale. Please remove the entry\n ";
- message += depname;
- message += "\nfrom the cache.";
- cmSystemTools::Error(message.c_str());
- }
- }
+ std::string depname = cmStrCat(this->GetName(), "_LIB_DEPENDS");
+ mf.RemoveCacheDefinition(depname);
}
std::string cmTarget::GetDebugGeneratorExpressions(
@@ -666,15 +822,13 @@ std::string cmTarget::GetDebugGeneratorExpressions(
// Get the list of configurations considered to be DEBUG.
std::vector<std::string> debugConfigs =
- this->Makefile->GetCMakeInstance()->GetDebugConfigs();
+ impl->Makefile->GetCMakeInstance()->GetDebugConfigs();
std::string configString = "$<CONFIG:" + debugConfigs[0] + ">";
if (debugConfigs.size() > 1) {
- for (std::vector<std::string>::const_iterator li =
- debugConfigs.begin() + 1;
- li != debugConfigs.end(); ++li) {
- configString += ",$<CONFIG:" + *li + ">";
+ for (std::string const& conf : cmMakeRange(debugConfigs).advance(1)) {
+ configString += ",$<CONFIG:" + conf + ">";
}
configString = "$<OR:" + configString + ">";
}
@@ -694,13 +848,13 @@ bool cmTarget::PushTLLCommandTrace(TLLSignature signature,
cmListFileContext const& lfc)
{
bool ret = true;
- if (!this->TLLCommands.empty()) {
- if (this->TLLCommands.back().first != signature) {
+ if (!impl->TLLCommands.empty()) {
+ if (impl->TLLCommands.back().first != signature) {
ret = false;
}
}
- if (this->TLLCommands.empty() || this->TLLCommands.back().second != lfc) {
- this->TLLCommands.push_back(std::make_pair(signature, lfc));
+ if (impl->TLLCommands.empty() || impl->TLLCommands.back().second != lfc) {
+ impl->TLLCommands.emplace_back(signature, lfc);
}
return ret;
}
@@ -710,47 +864,108 @@ void cmTarget::GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const
const char* sigString =
(sig == cmTarget::KeywordTLLSignature ? "keyword" : "plain");
s << "The uses of the " << sigString << " signature are here:\n";
- typedef std::vector<std::pair<TLLSignature, cmListFileContext> > Container;
- cmOutputConverter converter(this->GetMakefile()->GetStateSnapshot());
- for (Container::const_iterator it = this->TLLCommands.begin();
- it != this->TLLCommands.end(); ++it) {
- if (it->first == sig) {
- cmListFileContext lfc = it->second;
- lfc.FilePath = converter.ConvertToRelativePath(
- this->Makefile->GetState()->GetSourceDirectory(), lfc.FilePath);
+ cmStateDirectory cmDir = impl->Makefile->GetStateSnapshot().GetDirectory();
+ for (auto const& cmd : impl->TLLCommands) {
+ if (cmd.first == sig) {
+ cmListFileContext lfc = cmd.second;
+ lfc.FilePath = cmDir.ConvertToRelPathIfNotContained(
+ impl->Makefile->GetState()->GetSourceDirectory(), lfc.FilePath);
s << " * " << lfc << std::endl;
}
}
}
+std::string const& cmTarget::GetInstallPath() const
+{
+ return impl->InstallPath;
+}
+
+void cmTarget::SetInstallPath(std::string const& name)
+{
+ impl->InstallPath = name;
+}
+
+std::string const& cmTarget::GetRuntimeInstallPath() const
+{
+ return impl->RuntimeInstallPath;
+}
+
+void cmTarget::SetRuntimeInstallPath(std::string const& name)
+{
+ impl->RuntimeInstallPath = name;
+}
+
+bool cmTarget::GetHaveInstallRule() const
+{
+ return impl->HaveInstallRule;
+}
+
+void cmTarget::SetHaveInstallRule(bool hir)
+{
+ impl->HaveInstallRule = hir;
+}
+
+void cmTarget::AddInstallGenerator(cmInstallTargetGenerator* g)
+{
+ impl->InstallGenerators.emplace_back(g);
+}
+
+std::vector<cmInstallTargetGenerator*> const& cmTarget::GetInstallGenerators()
+ const
+{
+ return impl->InstallGenerators;
+}
+
+bool cmTarget::GetIsGeneratorProvided() const
+{
+ return impl->IsGeneratorProvided;
+}
+
+void cmTarget::SetIsGeneratorProvided(bool igp)
+{
+ impl->IsGeneratorProvided = igp;
+}
+
+cmTarget::LinkLibraryVectorType const& cmTarget::GetOriginalLinkLibraries()
+ const
+{
+ return impl->OriginalLinkLibraries;
+}
+
void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib,
cmTargetLinkLibraryType llt)
{
- cmTarget* tgt = this->Makefile->FindTargetToUse(lib);
+ this->AddLinkLibrary(mf, lib, lib, llt);
+}
+
+void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib,
+ std::string const& libRef,
+ cmTargetLinkLibraryType llt)
+{
+ cmTarget* tgt = mf.FindTargetToUse(lib);
{
const bool isNonImportedTarget = tgt && !tgt->IsImported();
const std::string libName =
(isNonImportedTarget && llt != GENERAL_LibraryType)
- ? targetNameGenex(lib)
- : lib;
+ ? targetNameGenex(libRef)
+ : libRef;
this->AppendProperty(
"LINK_LIBRARIES",
this->GetDebugGeneratorExpressions(libName, llt).c_str());
}
- if (cmGeneratorExpression::Find(lib) != std::string::npos ||
- (tgt && tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) ||
- (this->Name == lib)) {
+ if (cmGeneratorExpression::Find(lib) != std::string::npos || lib != libRef ||
+ (tgt &&
+ (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ tgt->GetType() == cmStateEnums::OBJECT_LIBRARY)) ||
+ (impl->Name == lib)) {
return;
}
- cmTarget::LibraryID tmp;
- tmp.first = lib;
- tmp.second = llt;
- this->OriginalLinkLibraries.push_back(tmp);
+ impl->OriginalLinkLibraries.emplace_back(lib, llt);
- // Add the explicit dependency information for this target. This is
+ // Add the explicit dependency information for libraries. This is
// simply a set of libraries separated by ";". There should always
// be a trailing ";". These library names are not canonical, in that
// they may be "-framework x", "-ly", "/path/libz.a", etc.
@@ -758,9 +973,11 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib,
// may be purposefully duplicated to handle recursive dependencies,
// and we removing one instance will break the link line. Duplicates
// will be appropriately eliminated at emit time.
- if (this->RecordDependencies) {
- std::string targetEntry = this->Name;
- targetEntry += "_LIB_DEPENDS";
+ if (impl->TargetType >= cmStateEnums::STATIC_LIBRARY &&
+ impl->TargetType <= cmStateEnums::MODULE_LIBRARY &&
+ (this->GetPolicyStatusCMP0073() == cmPolicies::OLD ||
+ this->GetPolicyStatusCMP0073() == cmPolicies::WARN)) {
+ std::string targetEntry = cmStrCat(impl->Name, "_LIB_DEPENDS");
std::string dependencies;
const char* old_val = mf.GetDefinition(targetEntry);
if (old_val) {
@@ -787,170 +1004,297 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib,
void cmTarget::AddSystemIncludeDirectories(const std::set<std::string>& incs)
{
- this->SystemIncludeDirectories.insert(incs.begin(), incs.end());
+ impl->SystemIncludeDirectories.insert(incs.begin(), incs.end());
+}
+
+std::set<std::string> const& cmTarget::GetSystemIncludeDirectories() const
+{
+ return impl->SystemIncludeDirectories;
}
cmStringRange cmTarget::GetIncludeDirectoriesEntries() const
{
- return cmMakeRange(this->Internal->IncludeDirectoriesEntries);
+ return cmMakeRange(impl->IncludeDirectoriesEntries);
}
cmBacktraceRange cmTarget::GetIncludeDirectoriesBacktraces() const
{
- return cmMakeRange(this->Internal->IncludeDirectoriesBacktraces);
+ return cmMakeRange(impl->IncludeDirectoriesBacktraces);
}
cmStringRange cmTarget::GetCompileOptionsEntries() const
{
- return cmMakeRange(this->Internal->CompileOptionsEntries);
+ return cmMakeRange(impl->CompileOptionsEntries);
}
cmBacktraceRange cmTarget::GetCompileOptionsBacktraces() const
{
- return cmMakeRange(this->Internal->CompileOptionsBacktraces);
+ return cmMakeRange(impl->CompileOptionsBacktraces);
}
cmStringRange cmTarget::GetCompileFeaturesEntries() const
{
- return cmMakeRange(this->Internal->CompileFeaturesEntries);
+ return cmMakeRange(impl->CompileFeaturesEntries);
}
cmBacktraceRange cmTarget::GetCompileFeaturesBacktraces() const
{
- return cmMakeRange(this->Internal->CompileFeaturesBacktraces);
+ return cmMakeRange(impl->CompileFeaturesBacktraces);
}
cmStringRange cmTarget::GetCompileDefinitionsEntries() const
{
- return cmMakeRange(this->Internal->CompileDefinitionsEntries);
+ return cmMakeRange(impl->CompileDefinitionsEntries);
}
cmBacktraceRange cmTarget::GetCompileDefinitionsBacktraces() const
{
- return cmMakeRange(this->Internal->CompileDefinitionsBacktraces);
+ return cmMakeRange(impl->CompileDefinitionsBacktraces);
+}
+
+cmStringRange cmTarget::GetPrecompileHeadersEntries() const
+{
+ return cmMakeRange(impl->PrecompileHeadersEntries);
+}
+
+cmBacktraceRange cmTarget::GetPrecompileHeadersBacktraces() const
+{
+ return cmMakeRange(impl->PrecompileHeadersBacktraces);
}
cmStringRange cmTarget::GetSourceEntries() const
{
- return cmMakeRange(this->Internal->SourceEntries);
+ return cmMakeRange(impl->SourceEntries);
}
cmBacktraceRange cmTarget::GetSourceBacktraces() const
{
- return cmMakeRange(this->Internal->SourceBacktraces);
+ return cmMakeRange(impl->SourceBacktraces);
+}
+
+cmStringRange cmTarget::GetLinkOptionsEntries() const
+{
+ return cmMakeRange(impl->LinkOptionsEntries);
+}
+
+cmBacktraceRange cmTarget::GetLinkOptionsBacktraces() const
+{
+ return cmMakeRange(impl->LinkOptionsBacktraces);
+}
+
+cmStringRange cmTarget::GetLinkDirectoriesEntries() const
+{
+ return cmMakeRange(impl->LinkDirectoriesEntries);
+}
+
+cmBacktraceRange cmTarget::GetLinkDirectoriesBacktraces() const
+{
+ return cmMakeRange(impl->LinkDirectoriesBacktraces);
}
cmStringRange cmTarget::GetLinkImplementationEntries() const
{
- return cmMakeRange(this->Internal->LinkImplementationPropertyEntries);
+ return cmMakeRange(impl->LinkImplementationPropertyEntries);
}
cmBacktraceRange cmTarget::GetLinkImplementationBacktraces() const
{
- return cmMakeRange(this->Internal->LinkImplementationPropertyBacktraces);
+ return cmMakeRange(impl->LinkImplementationPropertyBacktraces);
}
void cmTarget::SetProperty(const std::string& prop, const char* value)
{
if (!cmTargetPropertyComputer::PassesWhitelist(
- this->GetType(), prop, this->Makefile->GetMessenger(),
- this->Makefile->GetBacktrace())) {
+ this->GetType(), prop, impl->Makefile->GetMessenger(),
+ impl->Makefile->GetBacktrace())) {
return;
}
- if (prop == "MANUALLY_ADDED_DEPENDENCIES") {
- std::ostringstream e;
- e << "MANUALLY_ADDED_DEPENDENCIES property is read-only\n";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+#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(PRECOMPILE_HEADERS);
+ MAKE_STATIC_PROP(PRECOMPILE_HEADERS_REUSE_FROM);
+ 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_OPTIONS);
+ MAKE_STATIC_PROP(LINK_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) {
+ impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "MANUALLY_ADDED_DEPENDENCIES property is read-only\n");
return;
}
- if (prop == "NAME") {
- std::ostringstream e;
- e << "NAME property is read-only\n";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ if (prop == propNAME) {
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "NAME property is read-only\n");
return;
}
- if (prop == "TYPE") {
- std::ostringstream e;
- e << "TYPE property is read-only\n";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ if (prop == propTYPE) {
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "TYPE property is read-only\n");
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());
+ << impl->Name << "\")\n";
+ impl->Makefile->IssueMessage(MessageType::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
+ e << "SOURCES property can't be set on imported targets (\"" << impl->Name
<< "\")\n";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ impl->Makefile->IssueMessage(MessageType::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 (\""
+ << impl->Name << "\")\n";
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
- if (prop == "INCLUDE_DIRECTORIES") {
- this->Internal->IncludeDirectoriesEntries.clear();
- this->Internal->IncludeDirectoriesBacktraces.clear();
+ if (prop == propINCLUDE_DIRECTORIES) {
+ impl->IncludeDirectoriesEntries.clear();
+ impl->IncludeDirectoriesBacktraces.clear();
if (value) {
- this->Internal->IncludeDirectoriesEntries.push_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->IncludeDirectoriesBacktraces.push_back(lfbt);
+ impl->IncludeDirectoriesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->IncludeDirectoriesBacktraces.push_back(lfbt);
}
- } else if (prop == "COMPILE_OPTIONS") {
- this->Internal->CompileOptionsEntries.clear();
- this->Internal->CompileOptionsBacktraces.clear();
+ } else if (prop == propCOMPILE_OPTIONS) {
+ impl->CompileOptionsEntries.clear();
+ impl->CompileOptionsBacktraces.clear();
if (value) {
- this->Internal->CompileOptionsEntries.push_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->CompileOptionsBacktraces.push_back(lfbt);
+ impl->CompileOptionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->CompileOptionsBacktraces.push_back(lfbt);
}
- } else if (prop == "COMPILE_FEATURES") {
- this->Internal->CompileFeaturesEntries.clear();
- this->Internal->CompileFeaturesBacktraces.clear();
+ } else if (prop == propCOMPILE_FEATURES) {
+ impl->CompileFeaturesEntries.clear();
+ impl->CompileFeaturesBacktraces.clear();
if (value) {
- this->Internal->CompileFeaturesEntries.push_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->CompileFeaturesBacktraces.push_back(lfbt);
+ impl->CompileFeaturesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->CompileFeaturesBacktraces.push_back(lfbt);
}
- } else if (prop == "COMPILE_DEFINITIONS") {
- this->Internal->CompileDefinitionsEntries.clear();
- this->Internal->CompileDefinitionsBacktraces.clear();
+ } else if (prop == propCOMPILE_DEFINITIONS) {
+ impl->CompileDefinitionsEntries.clear();
+ impl->CompileDefinitionsBacktraces.clear();
if (value) {
- this->Internal->CompileDefinitionsEntries.push_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->CompileDefinitionsBacktraces.push_back(lfbt);
+ impl->CompileDefinitionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->CompileDefinitionsBacktraces.push_back(lfbt);
}
- } else if (prop == "LINK_LIBRARIES") {
- this->Internal->LinkImplementationPropertyEntries.clear();
- this->Internal->LinkImplementationPropertyBacktraces.clear();
+ } else if (prop == propLINK_OPTIONS) {
+ impl->LinkOptionsEntries.clear();
+ impl->LinkOptionsBacktraces.clear();
if (value) {
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->LinkImplementationPropertyEntries.push_back(value);
- this->Internal->LinkImplementationPropertyBacktraces.push_back(lfbt);
+ impl->LinkOptionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->LinkOptionsBacktraces.push_back(lfbt);
}
- } else if (prop == "SOURCES") {
- this->Internal->SourceEntries.clear();
- this->Internal->SourceBacktraces.clear();
+ } else if (prop == propLINK_DIRECTORIES) {
+ impl->LinkDirectoriesEntries.clear();
+ impl->LinkDirectoriesBacktraces.clear();
if (value) {
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->SourceEntries.push_back(value);
- this->Internal->SourceBacktraces.push_back(lfbt);
+ impl->LinkDirectoriesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->LinkDirectoriesBacktraces.push_back(lfbt);
+ }
+ } else if (prop == propPRECOMPILE_HEADERS) {
+ impl->PrecompileHeadersEntries.clear();
+ impl->PrecompileHeadersBacktraces.clear();
+ if (value) {
+ impl->PrecompileHeadersEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->PrecompileHeadersBacktraces.push_back(lfbt);
+ }
+ } else if (prop == propLINK_LIBRARIES) {
+ impl->LinkImplementationPropertyEntries.clear();
+ impl->LinkImplementationPropertyBacktraces.clear();
+ if (value) {
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->LinkImplementationPropertyEntries.emplace_back(value);
+ impl->LinkImplementationPropertyBacktraces.push_back(lfbt);
+ }
+ } else if (prop == propSOURCES) {
+ impl->SourceEntries.clear();
+ impl->SourceBacktraces.clear();
+ if (value) {
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->SourceEntries.emplace_back(value);
+ impl->SourceBacktraces.push_back(lfbt);
+ }
+ } else if (prop == propIMPORTED_GLOBAL) {
+ if (!cmIsOn(value)) {
+ std::ostringstream e;
+ e << "IMPORTED_GLOBAL property can't be set to FALSE on targets (\""
+ << impl->Name << "\")\n";
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return;
+ }
+ /* no need to change anything if value does not change */
+ if (!impl->ImportedGloballyVisible) {
+ impl->ImportedGloballyVisible = true;
+ this->GetGlobalGenerator()->IndexTarget(this);
}
} else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") &&
- !this->CheckImportedLibName(prop, value ? value : "")) {
+ !impl->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 "
"targets (\""
- << this->Name << "\")\n";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ << impl->Name << "\")\n";
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
+ } else if (prop == propPRECOMPILE_HEADERS_REUSE_FROM) {
+ if (this->GetProperty("PRECOMPILE_HEADERS")) {
+ std::ostringstream e;
+ e << "PRECOMPILE_HEADERS property is already set on target (\""
+ << impl->Name << "\")\n";
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return;
+ }
+ auto reusedTarget =
+ impl->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(
+ value);
+ if (!reusedTarget) {
+ const std::string e(
+ "PRECOMPILE_HEADERS_REUSE_FROM set with non existing target");
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e);
+ return;
+ }
+
+ std::string reusedFrom = reusedTarget->GetSafeProperty(prop);
+ if (reusedFrom.empty()) {
+ reusedFrom = value;
+ }
+
+ impl->Properties.SetProperty(prop, reusedFrom.c_str());
+
+ reusedTarget->SetProperty("COMPILE_PDB_NAME", reusedFrom.c_str());
+ reusedTarget->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY",
+ cmStrCat(reusedFrom, ".dir/").c_str());
+
+ this->SetProperty("COMPILE_PDB_NAME",
+ reusedTarget->GetProperty("COMPILE_PDB_NAME"));
+ this->AddUtility(reusedFrom, impl->Makefile);
} else {
- this->Properties.SetProperty(prop, value);
+ impl->Properties.SetProperty(prop, value);
}
}
@@ -958,69 +1302,102 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value,
bool asString)
{
if (!cmTargetPropertyComputer::PassesWhitelist(
- this->GetType(), prop, this->Makefile->GetMessenger(),
- this->Makefile->GetBacktrace())) {
+ this->GetType(), prop, impl->Makefile->GetMessenger(),
+ impl->Makefile->GetBacktrace())) {
return;
}
if (prop == "NAME") {
- std::ostringstream e;
- e << "NAME property is read-only\n";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "NAME property is read-only\n");
return;
}
if (prop == "EXPORT_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());
+ << impl->Name << "\")\n";
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == "SOURCES" && this->IsImported()) {
std::ostringstream e;
- e << "SOURCES property can't be set on imported targets (\"" << this->Name
+ e << "SOURCES property can't be set on imported targets (\"" << impl->Name
<< "\")\n";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ impl->Makefile->IssueMessage(MessageType::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 (\""
+ << impl->Name << "\")\n";
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
return;
}
if (prop == "INCLUDE_DIRECTORIES") {
if (value && *value) {
- this->Internal->IncludeDirectoriesEntries.push_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->IncludeDirectoriesBacktraces.push_back(lfbt);
+ impl->IncludeDirectoriesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->IncludeDirectoriesBacktraces.push_back(lfbt);
}
} else if (prop == "COMPILE_OPTIONS") {
if (value && *value) {
- this->Internal->CompileOptionsEntries.push_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->CompileOptionsBacktraces.push_back(lfbt);
+ impl->CompileOptionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->CompileOptionsBacktraces.push_back(lfbt);
}
} else if (prop == "COMPILE_FEATURES") {
if (value && *value) {
- this->Internal->CompileFeaturesEntries.push_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->CompileFeaturesBacktraces.push_back(lfbt);
+ impl->CompileFeaturesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->CompileFeaturesBacktraces.push_back(lfbt);
}
} else if (prop == "COMPILE_DEFINITIONS") {
if (value && *value) {
- this->Internal->CompileDefinitionsEntries.push_back(value);
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->CompileDefinitionsBacktraces.push_back(lfbt);
+ impl->CompileDefinitionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->CompileDefinitionsBacktraces.push_back(lfbt);
+ }
+ } else if (prop == "LINK_OPTIONS") {
+ if (value && *value) {
+ impl->LinkOptionsEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->LinkOptionsBacktraces.push_back(lfbt);
+ }
+ } else if (prop == "LINK_DIRECTORIES") {
+ if (value && *value) {
+ impl->LinkDirectoriesEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->LinkDirectoriesBacktraces.push_back(lfbt);
+ }
+ } else if (prop == "PRECOMPILE_HEADERS") {
+ if (this->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) {
+ std::ostringstream e;
+ e << "PRECOMPILE_HEADERS_REUSE_FROM property is already set on target "
+ "(\""
+ << impl->Name << "\")\n";
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return;
+ }
+ if (value && *value) {
+ impl->PrecompileHeadersEntries.emplace_back(value);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->PrecompileHeadersBacktraces.push_back(lfbt);
}
} else if (prop == "LINK_LIBRARIES") {
if (value && *value) {
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->LinkImplementationPropertyEntries.push_back(value);
- this->Internal->LinkImplementationPropertyBacktraces.push_back(lfbt);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->LinkImplementationPropertyEntries.emplace_back(value);
+ impl->LinkImplementationPropertyBacktraces.push_back(lfbt);
}
} else if (prop == "SOURCES") {
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->SourceEntries.push_back(value);
- this->Internal->SourceBacktraces.push_back(lfbt);
+ cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
+ impl->SourceEntries.emplace_back(value);
+ impl->SourceBacktraces.push_back(lfbt);
} else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME")) {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
prop + " property may not be APPENDed.");
} else {
- this->Properties.AppendProperty(prop, value, asString);
+ impl->Properties.AppendProperty(prop, value, asString);
}
}
@@ -1033,16 +1410,17 @@ void cmTarget::AppendBuildInterfaceIncludes()
!this->IsExecutableWithExports()) {
return;
}
- if (this->BuildInterfaceIncludesAppended) {
+ if (impl->BuildInterfaceIncludesAppended) {
return;
}
- this->BuildInterfaceIncludesAppended = true;
+ impl->BuildInterfaceIncludesAppended = true;
- if (this->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE")) {
- const char* binDir = this->Makefile->GetCurrentBinaryDirectory();
- const char* srcDir = this->Makefile->GetCurrentSourceDirectory();
- const std::string dirs = std::string(binDir ? binDir : "") +
- std::string(binDir ? ";" : "") + std::string(srcDir ? srcDir : "");
+ if (impl->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE")) {
+ std::string dirs = impl->Makefile->GetCurrentBinaryDirectory();
+ if (!dirs.empty()) {
+ dirs += ';';
+ }
+ dirs += impl->Makefile->GetCurrentSourceDirectory();
if (!dirs.empty()) {
this->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
("$<BUILD_INTERFACE:" + dirs + ">").c_str());
@@ -1053,38 +1431,67 @@ void cmTarget::AppendBuildInterfaceIncludes()
void cmTarget::InsertInclude(std::string const& entry,
cmListFileBacktrace const& bt, bool before)
{
- std::vector<std::string>::iterator position = before
- ? this->Internal->IncludeDirectoriesEntries.begin()
- : this->Internal->IncludeDirectoriesEntries.end();
+ auto position = before ? impl->IncludeDirectoriesEntries.begin()
+ : impl->IncludeDirectoriesEntries.end();
- std::vector<cmListFileBacktrace>::iterator btPosition = before
- ? this->Internal->IncludeDirectoriesBacktraces.begin()
- : this->Internal->IncludeDirectoriesBacktraces.end();
+ auto btPosition = before ? impl->IncludeDirectoriesBacktraces.begin()
+ : impl->IncludeDirectoriesBacktraces.end();
- this->Internal->IncludeDirectoriesEntries.insert(position, entry);
- this->Internal->IncludeDirectoriesBacktraces.insert(btPosition, bt);
+ impl->IncludeDirectoriesEntries.insert(position, entry);
+ impl->IncludeDirectoriesBacktraces.insert(btPosition, bt);
}
void cmTarget::InsertCompileOption(std::string const& entry,
cmListFileBacktrace const& bt, bool before)
{
- std::vector<std::string>::iterator position = before
- ? this->Internal->CompileOptionsEntries.begin()
- : this->Internal->CompileOptionsEntries.end();
+ auto position = before ? impl->CompileOptionsEntries.begin()
+ : impl->CompileOptionsEntries.end();
- std::vector<cmListFileBacktrace>::iterator btPosition = before
- ? this->Internal->CompileOptionsBacktraces.begin()
- : this->Internal->CompileOptionsBacktraces.end();
+ auto btPosition = before ? impl->CompileOptionsBacktraces.begin()
+ : impl->CompileOptionsBacktraces.end();
- this->Internal->CompileOptionsEntries.insert(position, entry);
- this->Internal->CompileOptionsBacktraces.insert(btPosition, bt);
+ impl->CompileOptionsEntries.insert(position, entry);
+ impl->CompileOptionsBacktraces.insert(btPosition, bt);
}
void cmTarget::InsertCompileDefinition(std::string const& entry,
cmListFileBacktrace const& bt)
{
- this->Internal->CompileDefinitionsEntries.push_back(entry);
- this->Internal->CompileDefinitionsBacktraces.push_back(bt);
+ impl->CompileDefinitionsEntries.push_back(entry);
+ impl->CompileDefinitionsBacktraces.push_back(bt);
+}
+
+void cmTarget::InsertLinkOption(std::string const& entry,
+ cmListFileBacktrace const& bt, bool before)
+{
+ auto position =
+ before ? impl->LinkOptionsEntries.begin() : impl->LinkOptionsEntries.end();
+
+ auto btPosition = before ? impl->LinkOptionsBacktraces.begin()
+ : impl->LinkOptionsBacktraces.end();
+
+ impl->LinkOptionsEntries.insert(position, entry);
+ impl->LinkOptionsBacktraces.insert(btPosition, bt);
+}
+
+void cmTarget::InsertLinkDirectory(std::string const& entry,
+ cmListFileBacktrace const& bt, bool before)
+{
+ auto position = before ? impl->LinkDirectoriesEntries.begin()
+ : impl->LinkDirectoriesEntries.end();
+
+ auto btPosition = before ? impl->LinkDirectoriesBacktraces.begin()
+ : impl->LinkDirectoriesBacktraces.end();
+
+ impl->LinkDirectoriesEntries.insert(position, entry);
+ impl->LinkDirectoriesBacktraces.insert(btPosition, bt);
+}
+
+void cmTarget::InsertPrecompileHeader(std::string const& entry,
+ cmListFileBacktrace const& bt)
+{
+ impl->PrecompileHeadersEntries.push_back(entry);
+ impl->PrecompileHeadersBacktraces.push_back(bt);
}
static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop,
@@ -1123,7 +1530,7 @@ static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop,
<< "the LINK_INTERFACE_LIBRARIES and LINK_INTERFACE_LIBRARIES_DEBUG "
<< "properties accordingly.";
}
- context->IssueMessage(cmake::FATAL_ERROR, e.str());
+ context->IssueMessage(MessageType::FATAL_ERROR, e.str());
}
static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value,
@@ -1145,7 +1552,21 @@ static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value,
"property may contain configuration-sensitive generator-expressions "
"which may be used to specify per-configuration rules.";
- context->IssueMessage(cmake::FATAL_ERROR, e.str());
+ context->IssueMessage(MessageType::FATAL_ERROR, e.str());
+}
+
+static void cmTargetCheckIMPORTED_GLOBAL(const cmTarget* target,
+ cmMakefile* context)
+{
+ std::vector<cmTarget*> targets = context->GetOwnedImportedTargets();
+ auto 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(MessageType::FATAL_ERROR, e.str());
+ }
}
void cmTarget::CheckProperty(const std::string& prop,
@@ -1162,11 +1583,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(
@@ -1178,7 +1604,6 @@ const char* cmTarget::GetComputedProperty(
const char* cmTarget::GetProperty(const std::string& prop) const
{
- static CM_UNORDERED_SET<std::string> specialProps;
#define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP
MAKE_STATIC_PROP(LINK_LIBRARIES);
MAKE_STATIC_PROP(TYPE);
@@ -1186,35 +1611,43 @@ const char* cmTarget::GetProperty(const std::string& prop) const
MAKE_STATIC_PROP(COMPILE_FEATURES);
MAKE_STATIC_PROP(COMPILE_OPTIONS);
MAKE_STATIC_PROP(COMPILE_DEFINITIONS);
+ MAKE_STATIC_PROP(LINK_OPTIONS);
+ MAKE_STATIC_PROP(LINK_DIRECTORIES);
+ MAKE_STATIC_PROP(PRECOMPILE_HEADERS);
MAKE_STATIC_PROP(IMPORTED);
+ MAKE_STATIC_PROP(IMPORTED_GLOBAL);
MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES);
MAKE_STATIC_PROP(NAME);
MAKE_STATIC_PROP(BINARY_DIR);
MAKE_STATIC_PROP(SOURCE_DIR);
MAKE_STATIC_PROP(SOURCES);
#undef MAKE_STATIC_PROP
- if (specialProps.empty()) {
- specialProps.insert(propLINK_LIBRARIES);
- specialProps.insert(propTYPE);
- specialProps.insert(propINCLUDE_DIRECTORIES);
- specialProps.insert(propCOMPILE_FEATURES);
- specialProps.insert(propCOMPILE_OPTIONS);
- specialProps.insert(propCOMPILE_DEFINITIONS);
- specialProps.insert(propIMPORTED);
- specialProps.insert(propMANUALLY_ADDED_DEPENDENCIES);
- specialProps.insert(propNAME);
- specialProps.insert(propBINARY_DIR);
- specialProps.insert(propSOURCE_DIR);
- specialProps.insert(propSOURCES);
- }
+ static std::unordered_set<std::string> const specialProps{
+ propLINK_LIBRARIES,
+ propTYPE,
+ propINCLUDE_DIRECTORIES,
+ propCOMPILE_FEATURES,
+ propCOMPILE_OPTIONS,
+ propCOMPILE_DEFINITIONS,
+ propPRECOMPILE_HEADERS,
+ propLINK_OPTIONS,
+ propLINK_DIRECTORIES,
+ propIMPORTED,
+ propIMPORTED_GLOBAL,
+ propMANUALLY_ADDED_DEPENDENCIES,
+ propNAME,
+ propBINARY_DIR,
+ propSOURCE_DIR,
+ propSOURCES
+ };
if (specialProps.count(prop)) {
if (prop == propLINK_LIBRARIES) {
- if (this->Internal->LinkImplementationPropertyEntries.empty()) {
- return CM_NULLPTR;
+ if (impl->LinkImplementationPropertyEntries.empty()) {
+ return nullptr;
}
static std::string output;
- output = cmJoin(this->Internal->LinkImplementationPropertyEntries, ";");
+ output = cmJoin(impl->LinkImplementationPropertyEntries, ";");
return output.c_str();
}
// the type property returns what type the target is
@@ -1222,85 +1655,150 @@ const char* cmTarget::GetProperty(const std::string& prop) const
return cmState::GetTargetTypeName(this->GetType());
}
if (prop == propINCLUDE_DIRECTORIES) {
- if (this->Internal->IncludeDirectoriesEntries.empty()) {
- return CM_NULLPTR;
+ if (impl->IncludeDirectoriesEntries.empty()) {
+ return nullptr;
}
static std::string output;
- output = cmJoin(this->Internal->IncludeDirectoriesEntries, ";");
+ output = cmJoin(impl->IncludeDirectoriesEntries, ";");
return output.c_str();
}
if (prop == propCOMPILE_FEATURES) {
- if (this->Internal->CompileFeaturesEntries.empty()) {
- return CM_NULLPTR;
+ if (impl->CompileFeaturesEntries.empty()) {
+ return nullptr;
}
static std::string output;
- output = cmJoin(this->Internal->CompileFeaturesEntries, ";");
+ output = cmJoin(impl->CompileFeaturesEntries, ";");
return output.c_str();
}
if (prop == propCOMPILE_OPTIONS) {
- if (this->Internal->CompileOptionsEntries.empty()) {
- return CM_NULLPTR;
+ if (impl->CompileOptionsEntries.empty()) {
+ return nullptr;
}
static std::string output;
- output = cmJoin(this->Internal->CompileOptionsEntries, ";");
+ output = cmJoin(impl->CompileOptionsEntries, ";");
return output.c_str();
}
if (prop == propCOMPILE_DEFINITIONS) {
- if (this->Internal->CompileDefinitionsEntries.empty()) {
- return CM_NULLPTR;
+ if (impl->CompileDefinitionsEntries.empty()) {
+ return nullptr;
+ }
+
+ static std::string output;
+ output = cmJoin(impl->CompileDefinitionsEntries, ";");
+ return output.c_str();
+ }
+ if (prop == propLINK_OPTIONS) {
+ if (impl->LinkOptionsEntries.empty()) {
+ return nullptr;
}
static std::string output;
- output = cmJoin(this->Internal->CompileDefinitionsEntries, ";");
+ output = cmJoin(impl->LinkOptionsEntries, ";");
+ return output.c_str();
+ }
+ if (prop == propLINK_DIRECTORIES) {
+ if (impl->LinkDirectoriesEntries.empty()) {
+ return nullptr;
+ }
+
+ static std::string output;
+ output = cmJoin(impl->LinkDirectoriesEntries, ";");
+
return output.c_str();
}
if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
- if (this->Utilities.empty()) {
- return CM_NULLPTR;
+ if (impl->Utilities.empty()) {
+ return nullptr;
+ }
+
+ static std::string output;
+ output = cmJoin(impl->Utilities, ";");
+ return output.c_str();
+ }
+ if (prop == propPRECOMPILE_HEADERS) {
+ if (impl->PrecompileHeadersEntries.empty()) {
+ return nullptr;
}
static std::string output;
- output = cmJoin(this->Utilities, ";");
+ output = cmJoin(impl->PrecompileHeadersEntries, ";");
return output.c_str();
}
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();
}
if (prop == propBINARY_DIR) {
- return this->GetMakefile()
- ->GetStateSnapshot()
+ return impl->Makefile->GetStateSnapshot()
.GetDirectory()
- .GetCurrentBinary();
+ .GetCurrentBinary()
+ .c_str();
}
if (prop == propSOURCE_DIR) {
- return this->GetMakefile()
- ->GetStateSnapshot()
+ return impl->Makefile->GetStateSnapshot()
.GetDirectory()
- .GetCurrentSource();
+ .GetCurrentSource()
+ .c_str();
}
}
- const char* retVal = this->Properties.GetPropertyValue(prop);
+ const char* retVal = impl->Properties.GetPropertyValue(prop);
if (!retVal) {
- const bool chain = this->GetMakefile()->GetState()->IsPropertyChained(
- prop, cmProperty::TARGET);
+ const bool chain =
+ impl->Makefile->GetState()->IsPropertyChained(prop, cmProperty::TARGET);
if (chain) {
- return this->Makefile->GetStateSnapshot().GetDirectory().GetProperty(
+ return impl->Makefile->GetStateSnapshot().GetDirectory().GetProperty(
prop, chain);
}
}
return retVal;
}
+const char* cmTarget::GetSafeProperty(const std::string& prop) const
+{
+ const char* ret = this->GetProperty(prop);
+ if (!ret) {
+ return "";
+ }
+ return ret;
+}
+
bool cmTarget::GetPropertyAsBool(const std::string& prop) const
{
- return cmSystemTools::IsOn(this->GetProperty(prop));
+ return cmIsOn(this->GetProperty(prop));
+}
+
+cmPropertyMap const& cmTarget::GetProperties() const
+{
+ return impl->Properties;
+}
+
+bool cmTarget::IsDLLPlatform() const
+{
+ return impl->IsDLLPlatform;
+}
+
+bool cmTarget::IsAIX() const
+{
+ return impl->IsAIX;
+}
+
+bool cmTarget::IsImported() const
+{
+ return impl->IsImportedTarget;
+}
+
+bool cmTarget::IsImportedGloballyVisible() const
+{
+ return impl->ImportedGloballyVisible;
}
const char* cmTarget::GetSuffixVariableInternal(
@@ -1330,11 +1828,12 @@ const char* cmTarget::GetSuffixVariableInternal(
case cmStateEnums::RuntimeBinaryArtifact:
// Android GUI application packages store the native
// binary as a shared library.
- return (this->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")
+ return (impl->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")
? "CMAKE_SHARED_LIBRARY_SUFFIX"
: "CMAKE_EXECUTABLE_SUFFIX");
case cmStateEnums::ImportLibraryArtifact:
- return "CMAKE_IMPORT_LIBRARY_SUFFIX";
+ return (impl->IsAIX ? "CMAKE_AIX_IMPORT_FILE_SUFFIX"
+ : "CMAKE_IMPORT_LIBRARY_SUFFIX");
}
break;
default:
@@ -1370,11 +1869,12 @@ const char* cmTarget::GetPrefixVariableInternal(
case cmStateEnums::RuntimeBinaryArtifact:
// Android GUI application packages store the native
// binary as a shared library.
- return (this->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")
+ return (impl->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI")
? "CMAKE_SHARED_LIBRARY_PREFIX"
: "");
case cmStateEnums::ImportLibraryArtifact:
- return "CMAKE_IMPORT_LIBRARY_PREFIX";
+ return (impl->IsAIX ? "CMAKE_AIX_IMPORT_FILE_PREFIX"
+ : "CMAKE_IMPORT_LIBRARY_PREFIX");
}
break;
default:
@@ -1397,8 +1897,8 @@ std::string cmTarget::ImportedGetFullPath(
std::string result;
- const char* loc = CM_NULLPTR;
- const char* imp = CM_NULLPTR;
+ const char* loc = nullptr;
+ const char* imp = nullptr;
std::string suffix;
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
@@ -1408,8 +1908,7 @@ std::string cmTarget::ImportedGetFullPath(
if (loc) {
result = loc;
} else {
- std::string impProp = "IMPORTED_LOCATION";
- impProp += suffix;
+ std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix);
if (const char* config_location = this->GetProperty(impProp)) {
result = config_location;
} else if (const char* location =
@@ -1424,8 +1923,7 @@ std::string cmTarget::ImportedGetFullPath(
result = imp;
} else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->IsExecutableWithExports()) {
- std::string impProp = "IMPORTED_IMPLIB";
- impProp += suffix;
+ std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
if (const char* config_implib = this->GetProperty(impProp)) {
result = config_implib;
} else if (const char* implib =
@@ -1438,48 +1936,35 @@ std::string cmTarget::ImportedGetFullPath(
}
if (result.empty()) {
- result = this->GetName();
- result += "-NOTFOUND";
+ result = cmStrCat(this->GetName(), "-NOTFOUND");
}
return result;
}
-void cmTarget::SetPropertyDefault(const std::string& property,
- const char* default_value)
+bool cmTargetInternals::CheckImportedLibName(std::string const& prop,
+ std::string const& value) const
{
- // Compute the name of the variable holding the default value.
- std::string var = "CMAKE_";
- var += property;
-
- if (const char* value = this->Makefile->GetDefinition(var)) {
- this->SetProperty(property, value);
- } else if (default_value) {
- this->SetProperty(property, default_value);
- }
-}
-
-bool cmTarget::CheckImportedLibName(std::string const& prop,
- std::string const& value) const
-{
- if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY ||
- !this->IsImported()) {
+ if (this->TargetType != cmStateEnums::INTERFACE_LIBRARY ||
+ !this->IsImportedTarget) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR, prop +
+ MessageType::FATAL_ERROR,
+ prop +
" property may be set only on imported INTERFACE library targets.");
return false;
}
if (!value.empty()) {
if (value[0] == '-') {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, prop +
- " property value\n " + value +
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ prop + " property value\n " + value +
"\nmay not start with '-'.");
return false;
}
std::string::size_type bad = value.find_first_of(":/\\;");
if (bad != std::string::npos) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR, prop + " property value\n " + value +
- "\nmay not contain '" + value.substr(bad, 1) + "'.");
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ prop + " property value\n " + value +
+ "\nmay not contain '" +
+ value.substr(bad, 1) + "'.");
return false;
}
}
@@ -1505,25 +1990,26 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
}
// Track the configuration-specific property suffix.
- suffix = "_";
- suffix += config_upper;
+ suffix = cmStrCat('_', config_upper);
std::vector<std::string> mappedConfigs;
{
- std::string mapProp = "MAP_IMPORTED_CONFIG_";
- mapProp += config_upper;
+ std::string mapProp = cmStrCat("MAP_IMPORTED_CONFIG_", config_upper);
if (const char* mapValue = this->GetProperty(mapProp)) {
- cmSystemTools::ExpandListArgument(mapValue, mappedConfigs, true);
+ cmExpandList(mapValue, mappedConfigs, true);
}
}
// If we needed to find one of the mapped configurations but did not
// On a DLL platform there may be only IMPORTED_IMPLIB for a shared
// library or an executable with exports.
- bool allowImp = this->HasImportLibrary();
+ bool allowImp = (this->IsDLLPlatform() &&
+ (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
+ this->IsExecutableWithExports())) ||
+ (this->IsAIX() && this->IsExecutableWithExports());
// If a mapping was found, check its configurations.
- for (std::vector<std::string>::const_iterator mci = mappedConfigs.begin();
+ for (auto mci = mappedConfigs.begin();
!*loc && !*imp && mci != mappedConfigs.end(); ++mci) {
// Look for this configuration.
if (mci->empty()) {
@@ -1535,23 +2021,20 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
}
// If it was found, set the suffix.
if (*loc || *imp) {
- suffix = "";
+ suffix.clear();
}
} else {
std::string mcUpper = cmSystemTools::UpperCase(*mci);
- std::string locProp = locPropBase + "_";
- locProp += mcUpper;
+ std::string locProp = cmStrCat(locPropBase, '_', mcUpper);
*loc = this->GetProperty(locProp);
if (allowImp) {
- std::string impProp = "IMPORTED_IMPLIB_";
- impProp += mcUpper;
+ std::string impProp = cmStrCat("IMPORTED_IMPLIB_", mcUpper);
*imp = this->GetProperty(impProp);
}
// If it was found, use it for all properties below.
if (*loc || *imp) {
- suffix = "_";
- suffix += mcUpper;
+ suffix = cmStrCat('_', mcUpper);
}
}
}
@@ -1568,12 +2051,10 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
// If we have not yet found it then there are no mapped
// configurations. Look for an exact-match.
if (!*loc && !*imp) {
- std::string locProp = locPropBase;
- locProp += suffix;
+ std::string locProp = cmStrCat(locPropBase, suffix);
*loc = this->GetProperty(locProp);
if (allowImp) {
- std::string impProp = "IMPORTED_IMPLIB";
- impProp += suffix;
+ std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
*imp = this->GetProperty(impProp);
}
}
@@ -1582,7 +2063,7 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
// configurations and no exact match.
if (!*loc && !*imp) {
// The suffix computed above is not useful.
- suffix = "";
+ suffix.clear();
// Look for a configuration-less location. This may be set by
// manually-written code.
@@ -1597,19 +2078,15 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
if (!*loc && !*imp) {
std::vector<std::string> availableConfigs;
if (const char* iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) {
- cmSystemTools::ExpandListArgument(iconfigs, availableConfigs);
+ cmExpandList(iconfigs, availableConfigs);
}
- for (std::vector<std::string>::const_iterator aci =
- availableConfigs.begin();
+ for (auto aci = availableConfigs.begin();
!*loc && !*imp && aci != availableConfigs.end(); ++aci) {
- suffix = "_";
- suffix += cmSystemTools::UpperCase(*aci);
- std::string locProp = locPropBase;
- locProp += suffix;
+ suffix = cmStrCat('_', cmSystemTools::UpperCase(*aci));
+ std::string locProp = cmStrCat(locPropBase, suffix);
*loc = this->GetProperty(locProp);
if (allowImp) {
- std::string impProp = "IMPORTED_IMPLIB";
- impProp += suffix;
+ std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
*imp = this->GetProperty(impProp);
}
}
@@ -1623,37 +2100,3 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
return true;
}
-
-cmTargetInternalPointer::cmTargetInternalPointer()
-{
- this->Pointer = new cmTargetInternals;
-}
-
-cmTargetInternalPointer::cmTargetInternalPointer(
- cmTargetInternalPointer const& r)
-{
- // Ideally cmTarget instances should never be copied. However until
- // we can make a sweep to remove that, this copy constructor avoids
- // allowing the resources (Internals) to be copied.
- this->Pointer = new cmTargetInternals(*r.Pointer);
-}
-
-cmTargetInternalPointer::~cmTargetInternalPointer()
-{
- delete this->Pointer;
-}
-
-cmTargetInternalPointer& cmTargetInternalPointer::operator=(
- cmTargetInternalPointer const& r)
-{
- if (this == &r) {
- return *this;
- } // avoid warning on HP about self check
- // Ideally cmTarget instances should never be copied. However until
- // we can make a sweep to remove that, this copy constructor avoids
- // allowing the resources (Internals) to be copied.
- cmTargetInternals* oldPointer = this->Pointer;
- this->Pointer = new cmTargetInternals(*r.Pointer);
- delete oldPointer;
- return *this;
-}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 1f00c0155..65a1ce36f 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -6,45 +6,32 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
-#include <map>
+#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "cmAlgorithms.h"
-#include "cmCustomCommand.h"
#include "cmListFileCache.h"
#include "cmPolicies.h"
-#include "cmPropertyMap.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmTargetLinkLibraryType.h"
-#include "cm_unordered_map.hxx"
+class cmCustomCommand;
class cmGlobalGenerator;
+class cmInstallTargetGenerator;
class cmMakefile;
class cmMessenger;
+class cmPropertyMap;
class cmSourceFile;
class cmTargetInternals;
-class cmTargetInternalPointer
-{
-public:
- cmTargetInternalPointer();
- cmTargetInternalPointer(cmTargetInternalPointer const& r);
- ~cmTargetInternalPointer();
- cmTargetInternalPointer& operator=(cmTargetInternalPointer const& r);
- cmTargetInternals* operator->() const { return this->Pointer; }
- cmTargetInternals* Get() const { return this->Pointer; }
-private:
- cmTargetInternals* Pointer;
-};
-
/** \class cmTarget
* \brief Represent a library or executable target loaded from a makefile.
*
- * cmTarget represents a target loaded from
- * a makefile.
+ * cmTarget represents a target loaded from a makefile.
*/
class cmTarget
{
@@ -59,88 +46,75 @@ public:
cmTarget(std::string const& name, cmStateEnums::TargetType type,
Visibility vis, cmMakefile* mf);
- enum CustomCommandType
- {
- PRE_BUILD,
- PRE_LINK,
- POST_BUILD
- };
+ cmTarget(cmTarget const&) = delete;
+ cmTarget(cmTarget&&) noexcept;
+ ~cmTarget();
- /**
- * Return the type of target.
- */
- cmStateEnums::TargetType GetType() const { return this->TargetTypeValue; }
+ cmTarget& operator=(cmTarget const&) = delete;
+ cmTarget& operator=(cmTarget&&) noexcept;
+
+ //! Return the type of target.
+ cmStateEnums::TargetType GetType() const;
+ //! Get the cmMakefile that owns this target.
+ cmMakefile* GetMakefile() const;
+
+ //! Return the global generator.
cmGlobalGenerator* GetGlobalGenerator() const;
- ///! Set/Get the name of the target
- const std::string& GetName() const { return this->Name; }
+ //! Set/Get the name of the target
+ const std::string& GetName() const;
+
+ //! Get the policy map
+ cmPolicies::PolicyMap const& GetPolicyMap() const;
- /** Get the cmMakefile that owns this target. */
- cmMakefile* GetMakefile() const { return this->Makefile; }
+ //! Get policy status
+ cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID policy) const;
#define DECLARE_TARGET_POLICY(POLICY) \
cmPolicies::PolicyStatus GetPolicyStatus##POLICY() const \
{ \
- return this->PolicyMap.Get(cmPolicies::POLICY); \
+ return this->GetPolicyStatus(cmPolicies::POLICY); \
}
CM_FOR_EACH_TARGET_POLICY(DECLARE_TARGET_POLICY)
#undef DECLARE_TARGET_POLICY
- /**
- * Get the list of the custom commands for this target
- */
- std::vector<cmCustomCommand> const& GetPreBuildCommands() const
- {
- return this->PreBuildCommands;
- }
- std::vector<cmCustomCommand> const& GetPreLinkCommands() const
- {
- return this->PreLinkCommands;
- }
- std::vector<cmCustomCommand> const& GetPostBuildCommands() const
- {
- return this->PostBuildCommands;
- }
- void AddPreBuildCommand(cmCustomCommand const& cmd)
- {
- this->PreBuildCommands.push_back(cmd);
- }
- void AddPreLinkCommand(cmCustomCommand const& cmd)
- {
- this->PreLinkCommands.push_back(cmd);
- }
- void AddPostBuildCommand(cmCustomCommand const& cmd)
- {
- this->PostBuildCommands.push_back(cmd);
- }
+ //! Get the list of the PRE_BUILD custom commands for this target
+ std::vector<cmCustomCommand> const& GetPreBuildCommands() const;
+ void AddPreBuildCommand(cmCustomCommand const& cmd);
+ void AddPreBuildCommand(cmCustomCommand&& cmd);
- /**
- * Add sources to the target.
- */
+ //! Get the list of the PRE_LINK custom commands for this target
+ std::vector<cmCustomCommand> const& GetPreLinkCommands() const;
+ void AddPreLinkCommand(cmCustomCommand const& cmd);
+ void AddPreLinkCommand(cmCustomCommand&& cmd);
+
+ //! Get the list of the POST_BUILD custom commands for this target
+ std::vector<cmCustomCommand> const& GetPostBuildCommands() const;
+ void AddPostBuildCommand(cmCustomCommand const& cmd);
+ void AddPostBuildCommand(cmCustomCommand&& cmd);
+
+ //! Add sources to the target.
void AddSources(std::vector<std::string> const& srcs);
void AddTracedSources(std::vector<std::string> const& srcs);
- cmSourceFile* AddSourceCMP0049(const std::string& src);
- cmSourceFile* AddSource(const std::string& src);
+ std::string GetSourceCMP0049(const std::string& src);
+ cmSourceFile* AddSource(const std::string& src, bool before = false);
- //* how we identify a library, by name and type
- typedef std::pair<std::string, cmTargetLinkLibraryType> LibraryID;
+ //! how we identify a library, by name and type
+ using LibraryID = std::pair<std::string, cmTargetLinkLibraryType>;
+ using LinkLibraryVectorType = std::vector<LibraryID>;
+ LinkLibraryVectorType const& GetOriginalLinkLibraries() const;
- typedef std::vector<LibraryID> LinkLibraryVectorType;
- const LinkLibraryVectorType& GetOriginalLinkLibraries() const
- {
- return this->OriginalLinkLibraries;
- }
-
- /**
- * Clear the dependency information recorded for this target, if any.
- */
- void ClearDependencyInformation(cmMakefile& mf, const std::string& target);
+ //! Clear the dependency information recorded for this target, if any.
+ void ClearDependencyInformation(cmMakefile& mf);
void AddLinkLibrary(cmMakefile& mf, const std::string& lib,
cmTargetLinkLibraryType llt);
+ void AddLinkLibrary(cmMakefile& mf, std::string const& lib,
+ std::string const& libRef, cmTargetLinkLibraryType llt);
+
enum TLLSignature
{
KeywordTLLSignature,
@@ -150,80 +124,82 @@ public:
cmListFileContext const& lfc);
void GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const;
- const std::vector<std::string>& GetLinkDirectories() const;
-
- void AddLinkDirectory(const std::string& d);
-
/**
* Set the path where this target should be installed. This is relative to
* INSTALL_PREFIX
*/
- std::string GetInstallPath() const { return this->InstallPath; }
- void SetInstallPath(const char* name) { this->InstallPath = name; }
+ std::string const& GetInstallPath() const;
+ void SetInstallPath(std::string const& name);
/**
* Set the path where this target (if it has a runtime part) should be
* installed. This is relative to INSTALL_PREFIX
*/
- std::string GetRuntimeInstallPath() const
- {
- return this->RuntimeInstallPath;
- }
- void SetRuntimeInstallPath(const char* name)
- {
- this->RuntimeInstallPath = name;
- }
+ std::string const& GetRuntimeInstallPath() const;
+ void SetRuntimeInstallPath(std::string const& name);
/**
* Get/Set whether there is an install rule for this target.
*/
- bool GetHaveInstallRule() const { return this->HaveInstallRule; }
- void SetHaveInstallRule(bool h) { this->HaveInstallRule = h; }
+ bool GetHaveInstallRule() const;
+ void SetHaveInstallRule(bool hir);
+
+ void AddInstallGenerator(cmInstallTargetGenerator* g);
+ std::vector<cmInstallTargetGenerator*> const& GetInstallGenerators() const;
+
+ /**
+ * Get/Set whether this target was auto-created by a generator.
+ */
+ bool GetIsGeneratorProvided() const;
+ void SetIsGeneratorProvided(bool igp);
- /** Add a utility on which this project depends. A utility is an executable
+ /**
+ * 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.
*/
- void AddUtility(const std::string& u, cmMakefile* makefile = CM_NULLPTR);
- ///! Get the utilities used by this target
- std::set<std::string> const& GetUtilities() const { return this->Utilities; }
- cmListFileBacktrace const* GetUtilityBacktrace(const std::string& u) const;
+ void AddUtility(std::string const& name, cmMakefile* mf = nullptr);
+ //! Get the utilities used by this target
+ std::set<BT<std::string>> const& GetUtilities() const;
- ///! Set/Get a property of this target file
+ //! Set/Get a property of this target file
void SetProperty(const std::string& prop, const char* value);
void AppendProperty(const std::string& prop, const char* value,
bool asString = false);
+ //! Might return a nullptr if the property is not set or invalid
const char* GetProperty(const std::string& prop) const;
+ //! Always returns a valid pointer
+ const char* GetSafeProperty(const std::string& prop) const;
bool GetPropertyAsBool(const std::string& prop) const;
void CheckProperty(const std::string& prop, cmMakefile* context) const;
const char* GetComputedProperty(const std::string& prop,
cmMessenger* messenger,
cmListFileBacktrace const& context) const;
+ //! Get all properties
+ cmPropertyMap const& GetProperties() const;
- bool IsImported() const { return this->IsImportedTarget; }
- bool IsImportedGloballyVisible() const
- {
- return this->ImportedGloballyVisible;
- }
+ //! Return whether or not the target is for a DLL platform.
+ bool IsDLLPlatform() const;
- // Get the properties
- cmPropertyMap const& GetProperties() const { return this->Properties; }
+ //! Return whether or not we are targeting AIX.
+ bool IsAIX() const;
+
+ bool IsImported() const;
+ bool IsImportedGloballyVisible() const;
bool GetMappedConfig(std::string const& desired_config, const char** loc,
const char** imp, std::string& suffix) const;
- /** Return whether this target is an executable with symbol exports
- enabled. */
+ //! Return whether this target is an executable with symbol exports enabled.
bool IsExecutableWithExports() const;
- /** Return whether this target is a shared library Framework on
- Apple. */
+ //! Return whether this target is a shared library Framework on Apple.
bool IsFrameworkOnApple() const;
- /** Return whether this target is an executable Bundle on Apple. */
+ //! Return whether this target is an executable Bundle on Apple.
bool IsAppBundleOnApple() const;
- /** Get a backtrace from the creation of the target. */
+ //! Get a backtrace from the creation of the target.
cmListFileBacktrace const& GetBacktrace() const;
void InsertInclude(std::string const& entry, cmListFileBacktrace const& bt,
@@ -232,17 +208,20 @@ public:
cmListFileBacktrace const& bt, bool before = false);
void InsertCompileDefinition(std::string const& entry,
cmListFileBacktrace const& bt);
+ void InsertLinkOption(std::string const& entry,
+ cmListFileBacktrace const& bt, bool before = false);
+ void InsertLinkDirectory(std::string const& entry,
+ cmListFileBacktrace const& bt, bool before = false);
+ void InsertPrecompileHeader(std::string const& entry,
+ cmListFileBacktrace const& bt);
void AppendBuildInterfaceIncludes();
std::string GetDebugGeneratorExpressions(const std::string& value,
cmTargetLinkLibraryType llt) const;
- void AddSystemIncludeDirectories(const std::set<std::string>& incs);
- std::set<std::string> const& GetSystemIncludeDirectories() const
- {
- return this->SystemIncludeDirectories;
- }
+ void AddSystemIncludeDirectories(std::set<std::string> const& incs);
+ std::set<std::string> const& GetSystemIncludeDirectories() const;
cmStringRange GetIncludeDirectoriesEntries() const;
cmBacktraceRange GetIncludeDirectoriesBacktraces() const;
@@ -256,80 +235,40 @@ public:
cmStringRange GetCompileDefinitionsEntries() const;
cmBacktraceRange GetCompileDefinitionsBacktraces() const;
+ cmStringRange GetPrecompileHeadersEntries() const;
+ cmBacktraceRange GetPrecompileHeadersBacktraces() const;
+
cmStringRange GetSourceEntries() const;
cmBacktraceRange GetSourceBacktraces() const;
+
+ cmStringRange GetLinkOptionsEntries() const;
+ cmBacktraceRange GetLinkOptionsBacktraces() const;
+
+ cmStringRange GetLinkDirectoriesEntries() const;
+ cmBacktraceRange GetLinkDirectoriesBacktraces() const;
+
cmStringRange GetLinkImplementationEntries() const;
cmBacktraceRange GetLinkImplementationBacktraces() const;
+ std::string ImportedGetFullPath(const std::string& config,
+ cmStateEnums::ArtifactType artifact) const;
+
struct StrictTargetComparison
{
bool operator()(cmTarget const* t1, cmTarget const* t2) const;
};
- std::string ImportedGetFullPath(const std::string& config,
- cmStateEnums::ArtifactType artifact) const;
-
private:
+ // Internal representation details.
+ friend class cmGeneratorTarget;
+
const char* GetSuffixVariableInternal(
cmStateEnums::ArtifactType artifact) const;
const char* GetPrefixVariableInternal(
cmStateEnums::ArtifactType artifact) const;
- // Use a makefile variable to set a default for the given property.
- // If the variable is not defined use the given default instead.
- void SetPropertyDefault(const std::string& property,
- const char* default_value);
-
- bool CheckImportedLibName(std::string const& prop,
- std::string const& value) const;
-
private:
- cmPropertyMap Properties;
- std::set<std::string> SystemIncludeDirectories;
- std::set<std::string> LinkDirectoriesEmmitted;
- std::set<std::string> Utilities;
- std::map<std::string, cmListFileBacktrace> UtilityBacktraces;
- cmPolicies::PolicyMap PolicyMap;
- std::string Name;
- std::string InstallPath;
- std::string RuntimeInstallPath;
- std::vector<std::string> LinkDirectories;
- std::vector<cmCustomCommand> PreBuildCommands;
- std::vector<cmCustomCommand> PreLinkCommands;
- std::vector<cmCustomCommand> PostBuildCommands;
- std::vector<std::pair<TLLSignature, cmListFileContext> > TLLCommands;
- LinkLibraryVectorType OriginalLinkLibraries;
- cmMakefile* Makefile;
- cmTargetInternalPointer Internal;
- cmStateEnums::TargetType TargetTypeValue;
- bool HaveInstallRule;
- bool RecordDependencies;
- bool DLLPlatform;
- bool IsAndroid;
- bool IsImportedTarget;
- bool ImportedGloballyVisible;
- bool BuildInterfaceIncludesAppended;
-
- std::string ProcessSourceItemCMP0049(const std::string& s);
-
- /** Return whether or not the target has a DLL import library. */
- bool HasImportLibrary() const;
-
- // Internal representation details.
- friend class cmTargetInternals;
- friend class cmGeneratorTarget;
- friend class cmTargetTraceDependencies;
-
- cmListFileBacktrace Backtrace;
-};
-
-typedef CM_UNORDERED_MAP<std::string, cmTarget> cmTargets;
-
-class cmTargetSet : public std::set<std::string>
-{
-};
-class cmTargetManifest : public std::map<std::string, cmTargetSet>
-{
+ std::unique_ptr<cmTargetInternals> impl;
};
#endif
diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx
index 008d1a210..edee16700 100644
--- a/Source/cmTargetCompileDefinitionsCommand.cxx
+++ b/Source/cmTargetCompileDefinitionsCommand.cxx
@@ -2,60 +2,57 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTargetCompileDefinitionsCommand.h"
-#include <sstream>
-
-#include "cmAlgorithms.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
#include "cmTarget.h"
-#include "cmake.h"
-
-class cmExecutionStatus;
+#include "cmTargetPropCommandBase.h"
-bool cmTargetCompileDefinitionsCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
-{
- return this->HandleArguments(args, "COMPILE_DEFINITIONS");
-}
+namespace {
-void cmTargetCompileDefinitionsCommand::HandleImportedTarget(
- const std::string& tgt)
+class TargetCompileDefinitionsImpl : public cmTargetPropCommandBase
{
- std::ostringstream e;
- e << "Cannot specify compile definitions for imported target \"" << tgt
- << "\".";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
+public:
+ using cmTargetPropCommandBase::cmTargetPropCommandBase;
+
+private:
+ void HandleMissingTarget(const std::string& name) override
+ {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Cannot specify compile definitions for target \"", name,
+ "\" which is not built by this project."));
+ }
-void cmTargetCompileDefinitionsCommand::HandleMissingTarget(
- const std::string& name)
-{
- std::ostringstream e;
- e << "Cannot specify compile definitions for target \"" << name
- << "\" "
- "which is not built by this project.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
+ bool HandleDirectContent(cmTarget* tgt,
+ const std::vector<std::string>& content,
+ bool /*prepend*/, bool /*system*/) override
+ {
+ tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str());
+ return true; // Successfully handled.
+ }
-std::string cmTargetCompileDefinitionsCommand::Join(
- const std::vector<std::string>& content)
-{
- std::string defs;
- std::string sep;
- for (std::vector<std::string>::const_iterator it = content.begin();
- it != content.end(); ++it) {
- if (cmHasLiteralPrefix(it->c_str(), "-D")) {
- defs += sep + it->substr(2);
- } else {
- defs += sep + *it;
+ std::string Join(const std::vector<std::string>& content) override
+ {
+ std::string defs;
+ std::string sep;
+ for (std::string const& it : content) {
+ if (cmHasLiteralPrefix(it, "-D")) {
+ defs += sep + it.substr(2);
+ } else {
+ defs += sep + it;
+ }
+ sep = ";";
}
- sep = ";";
+ return defs;
}
- return defs;
-}
+};
+
+} // namespace
-bool cmTargetCompileDefinitionsCommand::HandleDirectContent(
- cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
+bool cmTargetCompileDefinitionsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str());
- return true;
+ return TargetCompileDefinitionsImpl(status).HandleArguments(
+ args, "COMPILE_DEFINITIONS");
}
diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h
index 11abf571c..05ff092e8 100644
--- a/Source/cmTargetCompileDefinitionsCommand.h
+++ b/Source/cmTargetCompileDefinitionsCommand.h
@@ -3,43 +3,14 @@
#ifndef cmTargetCompileDefinitionsCommand_h
#define cmTargetCompileDefinitionsCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmTargetPropCommandBase.h"
-
-class cmCommand;
class cmExecutionStatus;
-class cmTarget;
-
-class cmTargetCompileDefinitionsCommand : public cmTargetPropCommandBase
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE
- {
- return new cmTargetCompileDefinitionsCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE;
- void HandleMissingTarget(const std::string& name) CM_OVERRIDE;
- bool HandleDirectContent(cmTarget* tgt,
- const std::vector<std::string>& content,
- bool prepend, bool system) CM_OVERRIDE;
- std::string Join(const std::vector<std::string>& content) CM_OVERRIDE;
-};
+bool cmTargetCompileDefinitionsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmTargetCompileFeaturesCommand.cxx b/Source/cmTargetCompileFeaturesCommand.cxx
index 1b6c00887..06be4f0dd 100644
--- a/Source/cmTargetCompileFeaturesCommand.cxx
+++ b/Source/cmTargetCompileFeaturesCommand.cxx
@@ -2,56 +2,54 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTargetCompileFeaturesCommand.h"
-#include <sstream>
-
-#include "cmAlgorithms.h"
#include "cmMakefile.h"
-#include "cmake.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
+#include "cmTargetPropCommandBase.h"
-class cmExecutionStatus;
class cmTarget;
-bool cmTargetCompileFeaturesCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
-{
- return this->HandleArguments(args, "COMPILE_FEATURES", NO_FLAGS);
-}
+namespace {
-void cmTargetCompileFeaturesCommand::HandleImportedTarget(
- const std::string& tgt)
+class TargetCompileFeaturesImpl : public cmTargetPropCommandBase
{
- std::ostringstream e;
- e << "Cannot specify compile features for imported target \"" << tgt
- << "\".";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
+public:
+ using cmTargetPropCommandBase::cmTargetPropCommandBase;
+
+private:
+ void HandleMissingTarget(const std::string& name) override
+ {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Cannot specify compile features for target \"", name,
+ "\" which is not built by this project."));
+ }
-void cmTargetCompileFeaturesCommand::HandleMissingTarget(
- const std::string& name)
-{
- std::ostringstream e;
- e << "Cannot specify compile features for target \"" << name
- << "\" "
- "which is not built by this project.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
+ bool HandleDirectContent(cmTarget* tgt,
+ const std::vector<std::string>& content,
+ bool /*prepend*/, bool /*system*/) override
+ {
+ for (std::string const& it : content) {
+ std::string error;
+ if (!this->Makefile->AddRequiredTargetFeature(tgt, it, &error)) {
+ this->SetError(error);
+ return false; // Not (successfully) handled.
+ }
+ }
+ return true; // Successfully handled.
+ }
-std::string cmTargetCompileFeaturesCommand::Join(
- const std::vector<std::string>& content)
-{
- return cmJoin(content, ";");
-}
+ std::string Join(const std::vector<std::string>& content) override
+ {
+ return cmJoin(content, ";");
+ }
+};
-bool cmTargetCompileFeaturesCommand::HandleDirectContent(
- cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
+} // namespace
+
+bool cmTargetCompileFeaturesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- for (std::vector<std::string>::const_iterator it = content.begin();
- it != content.end(); ++it) {
- std::string error;
- if (!this->Makefile->AddRequiredTargetFeature(tgt, *it, &error)) {
- this->SetError(error);
- return false;
- }
- }
- return true;
+ return TargetCompileFeaturesImpl(status).HandleArguments(args,
+ "COMPILE_FEATURES");
}
diff --git a/Source/cmTargetCompileFeaturesCommand.h b/Source/cmTargetCompileFeaturesCommand.h
index 990868004..db0c04b7e 100644
--- a/Source/cmTargetCompileFeaturesCommand.h
+++ b/Source/cmTargetCompileFeaturesCommand.h
@@ -3,32 +3,14 @@
#ifndef cmTargetCompileFeaturesCommand_h
#define cmTargetCompileFeaturesCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmTargetPropCommandBase.h"
-
-class cmCommand;
class cmExecutionStatus;
-class cmTarget;
-
-class cmTargetCompileFeaturesCommand : public cmTargetPropCommandBase
-{
- cmCommand* Clone() CM_OVERRIDE { return new cmTargetCompileFeaturesCommand; }
-
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE;
- void HandleMissingTarget(const std::string& name) CM_OVERRIDE;
- bool HandleDirectContent(cmTarget* tgt,
- const std::vector<std::string>& content,
- bool prepend, bool system) CM_OVERRIDE;
- std::string Join(const std::vector<std::string>& content) CM_OVERRIDE;
-};
+bool cmTargetCompileFeaturesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx
index 1b4056d76..e39b72670 100644
--- a/Source/cmTargetCompileOptionsCommand.cxx
+++ b/Source/cmTargetCompileOptionsCommand.cxx
@@ -2,50 +2,49 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTargetCompileOptionsCommand.h"
-#include <sstream>
-
-#include "cmAlgorithms.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
#include "cmTarget.h"
-#include "cmake.h"
-
-class cmExecutionStatus;
-
-bool cmTargetCompileOptionsCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
-{
- 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());
-}
+#include "cmTargetPropCommandBase.h"
-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.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
+namespace {
-std::string cmTargetCompileOptionsCommand::Join(
- const std::vector<std::string>& content)
+class TargetCompileOptionsImpl : public cmTargetPropCommandBase
{
- return cmJoin(content, ";");
-}
-
-bool cmTargetCompileOptionsCommand::HandleDirectContent(
- cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
+public:
+ using cmTargetPropCommandBase::cmTargetPropCommandBase;
+
+private:
+ void HandleMissingTarget(const std::string& name) override
+ {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Cannot specify compile options for target \"", name,
+ "\" which is not built by this project."));
+ }
+
+ bool HandleDirectContent(cmTarget* tgt,
+ const std::vector<std::string>& content,
+ bool /*prepend*/, bool /*system*/) override
+ {
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ tgt->InsertCompileOption(this->Join(content), lfbt);
+ return true; // Successfully handled.
+ }
+
+ std::string Join(const std::vector<std::string>& content) override
+ {
+ return cmJoin(content, ";");
+ }
+};
+
+} // namespace
+
+bool cmTargetCompileOptionsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- tgt->InsertCompileOption(this->Join(content), lfbt);
- return true;
+ return TargetCompileOptionsImpl(status).HandleArguments(
+ args, "COMPILE_OPTIONS", TargetCompileOptionsImpl::PROCESS_BEFORE);
}
diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h
index b5408f7cb..3ab1a89c5 100644
--- a/Source/cmTargetCompileOptionsCommand.h
+++ b/Source/cmTargetCompileOptionsCommand.h
@@ -3,40 +3,14 @@
#ifndef cmTargetCompileOptionsCommand_h
#define cmTargetCompileOptionsCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmTargetPropCommandBase.h"
-
-class cmCommand;
class cmExecutionStatus;
-class cmTarget;
-
-class cmTargetCompileOptionsCommand : public cmTargetPropCommandBase
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmTargetCompileOptionsCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE;
- void HandleMissingTarget(const std::string& name) CM_OVERRIDE;
- bool HandleDirectContent(cmTarget* tgt,
- const std::vector<std::string>& content,
- bool prepend, bool system) CM_OVERRIDE;
- std::string Join(const std::vector<std::string>& content) CM_OVERRIDE;
-};
+bool cmTargetCompileOptionsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmTargetDepend.h b/Source/cmTargetDepend.h
index daa902ecf..4ca78faa9 100644
--- a/Source/cmTargetDepend.h
+++ b/Source/cmTargetDepend.h
@@ -16,9 +16,10 @@ 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;
+ mutable cmListFileBacktrace Backtrace;
public:
cmTargetDepend(cmGeneratorTarget const* t)
@@ -30,7 +31,7 @@ public:
operator cmGeneratorTarget const*() const { return this->Target; }
cmGeneratorTarget const* operator->() const { return this->Target; }
cmGeneratorTarget const& operator*() const { return *this->Target; }
- friend bool operator<(cmTargetDepend l, cmTargetDepend r)
+ friend bool operator<(cmTargetDepend const& l, cmTargetDepend const& r)
{
return l.Target < r.Target;
}
@@ -42,8 +43,13 @@ public:
this->Link = true;
}
}
+ void SetBacktrace(cmListFileBacktrace const& bt) const
+ {
+ this->Backtrace = bt;
+ }
bool IsLink() const { return this->Link; }
bool IsUtil() const { return this->Util; }
+ cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; }
};
/** Unordered set of (direct) dependencies of a target. */
diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx
index 65a31490f..95b69f399 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.cxx
+++ b/Source/cmTargetIncludeDirectoriesCommand.cxx
@@ -3,97 +3,104 @@
#include "cmTargetIncludeDirectoriesCommand.h"
#include <set>
-#include <sstream>
#include "cmGeneratorExpression.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
-#include "cmake.h"
+#include "cmTargetPropCommandBase.h"
-class cmExecutionStatus;
+namespace {
-bool cmTargetIncludeDirectoriesCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+class TargetIncludeDirectoriesImpl : public cmTargetPropCommandBase
{
- return this->HandleArguments(args, "INCLUDE_DIRECTORIES",
- ArgumentFlags(PROCESS_BEFORE | PROCESS_SYSTEM));
-}
+public:
+ using cmTargetPropCommandBase::cmTargetPropCommandBase;
-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());
-}
+private:
+ void HandleMissingTarget(const std::string& name) override
+ {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Cannot specify include directories for target \"", name,
+ "\" which is not built by this project."));
+ }
-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.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
+ bool HandleDirectContent(cmTarget* tgt,
+ const std::vector<std::string>& content,
+ bool prepend, bool system) override;
+
+ void HandleInterfaceContent(cmTarget* tgt,
+ const std::vector<std::string>& content,
+ bool prepend, bool system) override;
-std::string cmTargetIncludeDirectoriesCommand::Join(
+ std::string Join(const std::vector<std::string>& content) override;
+};
+
+std::string TargetIncludeDirectoriesImpl::Join(
const std::vector<std::string>& content)
{
std::string dirs;
std::string sep;
- std::string prefix =
- this->Makefile->GetCurrentSourceDirectory() + std::string("/");
- for (std::vector<std::string>::const_iterator it = content.begin();
- it != content.end(); ++it) {
- if (cmSystemTools::FileIsFullPath(it->c_str()) ||
- cmGeneratorExpression::Find(*it) == 0) {
- dirs += sep + *it;
+ std::string prefix = this->Makefile->GetCurrentSourceDirectory() + "/";
+ for (std::string const& it : content) {
+ if (cmSystemTools::FileIsFullPath(it) ||
+ cmGeneratorExpression::Find(it) == 0) {
+ dirs += cmStrCat(sep, it);
} else {
- dirs += sep + prefix + *it;
+ dirs += cmStrCat(sep, prefix, it);
}
sep = ";";
}
return dirs;
}
-bool cmTargetIncludeDirectoriesCommand::HandleDirectContent(
+bool TargetIncludeDirectoriesImpl::HandleDirectContent(
cmTarget* tgt, const std::vector<std::string>& content, bool prepend,
bool system)
{
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
tgt->InsertInclude(this->Join(content), lfbt, prepend);
if (system) {
- std::string prefix =
- this->Makefile->GetCurrentSourceDirectory() + std::string("/");
+ std::string prefix = this->Makefile->GetCurrentSourceDirectory() + "/";
std::set<std::string> sdirs;
- for (std::vector<std::string>::const_iterator it = content.begin();
- it != content.end(); ++it) {
- if (cmSystemTools::FileIsFullPath(it->c_str()) ||
- cmGeneratorExpression::Find(*it) == 0) {
- sdirs.insert(*it);
+ for (std::string const& it : content) {
+ if (cmSystemTools::FileIsFullPath(it) ||
+ cmGeneratorExpression::Find(it) == 0) {
+ sdirs.insert(it);
} else {
- sdirs.insert(prefix + *it);
+ sdirs.insert(prefix + it);
}
}
tgt->AddSystemIncludeDirectories(sdirs);
}
- return true;
+ return true; // Successfully handled.
}
-void cmTargetIncludeDirectoriesCommand::HandleInterfaceContent(
+void TargetIncludeDirectoriesImpl::HandleInterfaceContent(
cmTarget* tgt, const std::vector<std::string>& content, bool prepend,
bool system)
{
cmTargetPropCommandBase::HandleInterfaceContent(tgt, content, prepend,
system);
-
if (system) {
std::string joined = this->Join(content);
tgt->AppendProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES",
joined.c_str());
}
}
+
+} // namespace
+
+bool cmTargetIncludeDirectoriesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return TargetIncludeDirectoriesImpl(status).HandleArguments(
+ args, "INCLUDE_DIRECTORIES",
+ TargetIncludeDirectoriesImpl::ArgumentFlags(
+ TargetIncludeDirectoriesImpl::PROCESS_BEFORE |
+ TargetIncludeDirectoriesImpl::PROCESS_SYSTEM));
+}
diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h
index 374a867dc..9958f419a 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.h
+++ b/Source/cmTargetIncludeDirectoriesCommand.h
@@ -3,47 +3,14 @@
#ifndef cmTargetIncludeDirectoriesCommand_h
#define cmTargetIncludeDirectoriesCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmTargetPropCommandBase.h"
-
-class cmCommand;
class cmExecutionStatus;
-class cmTarget;
-
-class cmTargetIncludeDirectoriesCommand : public cmTargetPropCommandBase
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE
- {
- return new cmTargetIncludeDirectoriesCommand;
- }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE;
- void HandleMissingTarget(const std::string& name) CM_OVERRIDE;
-
- bool HandleDirectContent(cmTarget* tgt,
- const std::vector<std::string>& content,
- bool prepend, bool system) CM_OVERRIDE;
- void HandleInterfaceContent(cmTarget* tgt,
- const std::vector<std::string>& content,
- bool prepend, bool system) CM_OVERRIDE;
- std::string Join(const std::vector<std::string>& content) CM_OVERRIDE;
-};
+bool cmTargetIncludeDirectoriesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmTargetLinkDirectoriesCommand.cxx b/Source/cmTargetLinkDirectoriesCommand.cxx
new file mode 100644
index 000000000..0c68d604c
--- /dev/null
+++ b/Source/cmTargetLinkDirectoriesCommand.cxx
@@ -0,0 +1,70 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmTargetLinkDirectoriesCommand.h"
+
+#include "cmGeneratorExpression.h"
+#include "cmListFileCache.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmTargetPropCommandBase.h"
+
+namespace {
+
+class TargetLinkDirectoriesImpl : public cmTargetPropCommandBase
+{
+public:
+ using cmTargetPropCommandBase::cmTargetPropCommandBase;
+
+private:
+ void HandleMissingTarget(const std::string& name) override
+ {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Cannot specify link directories for target \"", name,
+ "\" which is not built by this project."));
+ }
+
+ std::string Join(const std::vector<std::string>& content) override;
+
+ bool HandleDirectContent(cmTarget* tgt,
+ const std::vector<std::string>& content,
+ bool prepend, bool /*system*/) override
+ {
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ tgt->InsertLinkDirectory(this->Join(content), lfbt, prepend);
+ return true; // Successfully handled.
+ }
+};
+
+std::string TargetLinkDirectoriesImpl::Join(
+ const std::vector<std::string>& content)
+{
+ std::vector<std::string> directories;
+
+ for (const auto& dir : content) {
+ auto unixPath = dir;
+ cmSystemTools::ConvertToUnixSlashes(unixPath);
+ if (!cmSystemTools::FileIsFullPath(unixPath) &&
+ !cmGeneratorExpression::StartsWithGeneratorExpression(unixPath)) {
+ auto tmp = this->Makefile->GetCurrentSourceDirectory();
+ tmp += "/";
+ tmp += unixPath;
+ unixPath = tmp;
+ }
+ directories.push_back(unixPath);
+ }
+
+ return cmJoin(directories, ";");
+}
+
+} // namespace
+
+bool cmTargetLinkDirectoriesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return TargetLinkDirectoriesImpl(status).HandleArguments(
+ args, "LINK_DIRECTORIES", TargetLinkDirectoriesImpl::PROCESS_BEFORE);
+}
diff --git a/Source/cmTargetLinkDirectoriesCommand.h b/Source/cmTargetLinkDirectoriesCommand.h
new file mode 100644
index 000000000..3724d6cf8
--- /dev/null
+++ b/Source/cmTargetLinkDirectoriesCommand.h
@@ -0,0 +1,16 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmTargetLinkDirectoriesCommand_h
+#define cmTargetLinkDirectoriesCommand_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+class cmExecutionStatus;
+
+bool cmTargetLinkDirectoriesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+
+#endif
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index e17303645..0d2383a1c 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -2,54 +2,88 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTargetLinkLibrariesCommand.h"
+#include <cstring>
#include <sstream>
-#include <string.h>
+#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmState.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cmTargetLinkLibraryType.h"
#include "cmake.h"
-class cmExecutionStatus;
+namespace {
-const char* cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[3] = {
- "general", "debug", "optimized"
+enum ProcessingState
+{
+ ProcessingLinkLibraries,
+ ProcessingPlainLinkInterface,
+ ProcessingKeywordLinkInterface,
+ ProcessingPlainPublicInterface,
+ ProcessingKeywordPublicInterface,
+ ProcessingPlainPrivateInterface,
+ ProcessingKeywordPrivateInterface
};
-// cmTargetLinkLibrariesCommand
-bool cmTargetLinkLibrariesCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+const char* LinkLibraryTypeNames[3] = { "general", "debug", "optimized" };
+
+} // namespace
+
+static void LinkLibraryTypeSpecifierWarning(cmMakefile& mf, int left,
+ int right);
+
+static bool HandleLibrary(cmMakefile& mf, cmTarget* target,
+ ProcessingState currentProcessingState,
+ const std::string& lib, cmTargetLinkLibraryType llt);
+
+bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- // must have one argument
+ // Must have at least one argument.
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
- if (this->Makefile->IsAlias(args[0])) {
- this->SetError("can not be used on an ALIAS target.");
+ cmMakefile& mf = status.GetMakefile();
+
+ // Alias targets cannot be on the LHS of this command.
+ if (mf.IsAlias(args[0])) {
+ status.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) {
- cmake::MessageType t = cmake::FATAL_ERROR; // fail by default
+ cmTarget* target =
+ mf.GetCMakeInstance()->GetGlobalGenerator()->FindTarget(args[0]);
+ if (!target) {
+ const std::vector<cmTarget*>& importedTargets =
+ mf.GetOwnedImportedTargets();
+ for (cmTarget* importedTarget : importedTargets) {
+ if (importedTarget->GetName() == args[0]) {
+ target = importedTarget;
+ break;
+ }
+ }
+ }
+ if (!target) {
+ MessageType t = MessageType::FATAL_ERROR; // fail by default
std::ostringstream e;
e << "Cannot specify link libraries for target \"" << args[0] << "\" "
<< "which is not built by this project.";
// The bad target is the only argument. Check how policy CMP0016 is set,
// and accept, warn or fail respectively:
if (args.size() < 2) {
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0016)) {
+ switch (mf.GetPolicyStatus(cmPolicies::CMP0016)) {
case cmPolicies::WARN:
- t = cmake::AUTHOR_WARNING;
+ t = MessageType::AUTHOR_WARNING;
// Print the warning.
e << "\n"
<< "CMake does not support this but it used to work accidentally "
@@ -58,7 +92,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
<< cmPolicies::GetPolicyWarning(cmPolicies::CMP0016);
break;
case cmPolicies::OLD: // OLD behavior does not warn.
- t = cmake::MESSAGE;
+ t = MessageType::MESSAGE;
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
@@ -68,14 +102,13 @@ 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());
+ case MessageType::AUTHOR_WARNING:
+ mf.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
break;
- case cmake::FATAL_ERROR:
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ case MessageType::FATAL_ERROR:
+ mf.IssueMessage(MessageType::FATAL_ERROR, e.str());
cmSystemTools::SetFatalErrorOccured();
break;
default:
@@ -84,20 +117,12 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
return true;
}
- if (this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ // Having a UTILITY library on the LHS is a bug.
+ if (target->GetType() == cmStateEnums::UTILITY) {
std::ostringstream e;
- e << "Object library target \"" << args[0] << "\" "
- << "may not link to anything.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
- cmSystemTools::SetFatalErrorOccured();
- return true;
- }
-
- if (this->Target->GetType() == cmStateEnums::UTILITY) {
- std::ostringstream e;
- const char* modal = CM_NULLPTR;
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0039)) {
+ const char* modal = nullptr;
+ MessageType messageType = MessageType::AUTHOR_WARNING;
+ switch (mf.GetPolicyStatus(cmPolicies::CMP0039)) {
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0039) << "\n";
modal = "should";
@@ -107,19 +132,19 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::NEW:
modal = "must";
- messageType = cmake::FATAL_ERROR;
+ messageType = MessageType::FATAL_ERROR;
}
if (modal) {
- e << "Utility target \"" << this->Target->GetName() << "\" " << modal
+ e << "Utility target \"" << target->GetName() << "\" " << modal
<< " not be used as the target of a target_link_libraries call.";
- this->Makefile->IssueMessage(messageType, e.str());
- if (messageType == cmake::FATAL_ERROR) {
+ mf.IssueMessage(messageType, e.str());
+ if (messageType == MessageType::FATAL_ERROR) {
return false;
}
}
}
- // 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;
}
@@ -130,112 +155,111 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
// Start with primary linking and switch to link interface
// specification if the keyword is encountered as the first argument.
- this->CurrentProcessingState = ProcessingLinkLibraries;
+ ProcessingState 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;
+ currentProcessingState = ProcessingPlainLinkInterface;
if (i != 1) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
"The LINK_INTERFACE_LIBRARIES option must appear as the second "
"argument, just after the target name.");
return true;
}
} else if (args[i] == "INTERFACE") {
if (i != 1 &&
- this->CurrentProcessingState != ProcessingKeywordPrivateInterface &&
- 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.");
+ currentProcessingState != ProcessingKeywordPrivateInterface &&
+ currentProcessingState != ProcessingKeywordPublicInterface &&
+ currentProcessingState != ProcessingKeywordLinkInterface) {
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
+ "The INTERFACE, PUBLIC or PRIVATE option must appear as the second "
+ "argument, just after the target name.");
return true;
}
- this->CurrentProcessingState = ProcessingKeywordLinkInterface;
+ currentProcessingState = ProcessingKeywordLinkInterface;
} else if (args[i] == "LINK_PUBLIC") {
if (i != 1 &&
- this->CurrentProcessingState != ProcessingPlainPrivateInterface &&
- this->CurrentProcessingState != ProcessingPlainPublicInterface) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ currentProcessingState != ProcessingPlainPrivateInterface &&
+ currentProcessingState != ProcessingPlainPublicInterface) {
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
"The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
"argument, just after the target name.");
return true;
}
- this->CurrentProcessingState = ProcessingPlainPublicInterface;
+ currentProcessingState = ProcessingPlainPublicInterface;
} else if (args[i] == "PUBLIC") {
if (i != 1 &&
- this->CurrentProcessingState != ProcessingKeywordPrivateInterface &&
- this->CurrentProcessingState != ProcessingKeywordPublicInterface &&
- this->CurrentProcessingState != ProcessingKeywordLinkInterface) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
- "The PUBLIC or PRIVATE option must appear as the second "
+ currentProcessingState != ProcessingKeywordPrivateInterface &&
+ currentProcessingState != ProcessingKeywordPublicInterface &&
+ currentProcessingState != ProcessingKeywordLinkInterface) {
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
+ "The INTERFACE, PUBLIC or PRIVATE option must appear as the second "
"argument, just after the target name.");
return true;
}
- this->CurrentProcessingState = ProcessingKeywordPublicInterface;
+ currentProcessingState = ProcessingKeywordPublicInterface;
} else if (args[i] == "LINK_PRIVATE") {
- if (i != 1 &&
- this->CurrentProcessingState != ProcessingPlainPublicInterface &&
- this->CurrentProcessingState != ProcessingPlainPrivateInterface) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ if (i != 1 && currentProcessingState != ProcessingPlainPublicInterface &&
+ currentProcessingState != ProcessingPlainPrivateInterface) {
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
"The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
"argument, just after the target name.");
return true;
}
- this->CurrentProcessingState = ProcessingPlainPrivateInterface;
+ currentProcessingState = ProcessingPlainPrivateInterface;
} else if (args[i] == "PRIVATE") {
if (i != 1 &&
- this->CurrentProcessingState != ProcessingKeywordPrivateInterface &&
- this->CurrentProcessingState != ProcessingKeywordPublicInterface &&
- this->CurrentProcessingState != ProcessingKeywordLinkInterface) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
- "The PUBLIC or PRIVATE option must appear as the second "
+ currentProcessingState != ProcessingKeywordPrivateInterface &&
+ currentProcessingState != ProcessingKeywordPublicInterface &&
+ currentProcessingState != ProcessingKeywordLinkInterface) {
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
+ "The INTERFACE, PUBLIC or PRIVATE option must appear as the second "
"argument, just after the target name.");
return true;
}
- this->CurrentProcessingState = ProcessingKeywordPrivateInterface;
+ currentProcessingState = ProcessingKeywordPrivateInterface;
} else if (args[i] == "debug") {
if (haveLLT) {
- this->LinkLibraryTypeSpecifierWarning(llt, DEBUG_LibraryType);
+ LinkLibraryTypeSpecifierWarning(mf, llt, DEBUG_LibraryType);
}
llt = DEBUG_LibraryType;
haveLLT = true;
} else if (args[i] == "optimized") {
if (haveLLT) {
- this->LinkLibraryTypeSpecifierWarning(llt, OPTIMIZED_LibraryType);
+ LinkLibraryTypeSpecifierWarning(mf, llt, OPTIMIZED_LibraryType);
}
llt = OPTIMIZED_LibraryType;
haveLLT = true;
} else if (args[i] == "general") {
if (haveLLT) {
- this->LinkLibraryTypeSpecifierWarning(llt, GENERAL_LibraryType);
+ LinkLibraryTypeSpecifierWarning(mf, llt, GENERAL_LibraryType);
}
llt = GENERAL_LibraryType;
haveLLT = true;
} else if (haveLLT) {
// The link type was specified by the previous argument.
haveLLT = false;
- if (!this->HandleLibrary(args[i], llt)) {
+ if (!HandleLibrary(mf, target, currentProcessingState, args[i], llt)) {
return false;
}
} 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;
- std::string linkType = args[0];
- linkType += "_LINK_TYPE";
- const char* linkTypeString = this->Makefile->GetDefinition(linkType);
+ std::string linkType = cmStrCat(args[0], "_LINK_TYPE");
+ const char* linkTypeString = mf.GetDefinition(linkType);
if (linkTypeString) {
if (strcmp(linkTypeString, "debug") == 0) {
llt = DEBUG_LibraryType;
@@ -244,7 +268,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
llt = OPTIMIZED_LibraryType;
}
}
- if (!this->HandleLibrary(args[i], llt)) {
+ if (!HandleLibrary(mf, target, currentProcessingState, args[i], llt)) {
return false;
}
}
@@ -252,15 +276,14 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
// Make sure the last argument was not a library type specifier.
if (haveLLT) {
- std::ostringstream e;
- e << "The \"" << this->LinkLibraryTypeNames[llt]
- << "\" argument must be followed by a library.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf.IssueMessage(MessageType::FATAL_ERROR,
+ cmStrCat("The \"", LinkLibraryTypeNames[llt],
+ "\" argument must be followed by a library."));
cmSystemTools::SetFatalErrorOccured();
}
const cmPolicies::PolicyStatus policy22Status =
- this->Target->GetPolicyStatusCMP0022();
+ target->GetPolicyStatusCMP0022();
// If any of the LINK_ options were given, make sure the
// LINK_INTERFACE_LIBRARIES target property exists.
@@ -269,51 +292,59 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
// result in an empty link interface.
if ((policy22Status == cmPolicies::OLD ||
policy22Status == cmPolicies::WARN) &&
- this->CurrentProcessingState != ProcessingLinkLibraries &&
- !this->Target->GetProperty("LINK_INTERFACE_LIBRARIES")) {
- this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", "");
+ currentProcessingState != ProcessingLinkLibraries &&
+ !target->GetProperty("LINK_INTERFACE_LIBRARIES")) {
+ target->SetProperty("LINK_INTERFACE_LIBRARIES", "");
}
return true;
}
-void cmTargetLinkLibrariesCommand::LinkLibraryTypeSpecifierWarning(int left,
- int right)
+static void LinkLibraryTypeSpecifierWarning(cmMakefile& mf, int left,
+ int right)
{
- std::ostringstream w;
- w << "Link library type specifier \"" << this->LinkLibraryTypeNames[left]
- << "\" is followed by specifier \"" << this->LinkLibraryTypeNames[right]
- << "\" instead of a library name. "
- << "The first specifier will be ignored.";
- this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ mf.IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(
+ "Link library type specifier \"", LinkLibraryTypeNames[left],
+ "\" is followed by specifier \"", LinkLibraryTypeNames[right],
+ "\" instead of a library name. The first specifier will be ignored."));
}
-bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib,
- cmTargetLinkLibraryType llt)
+static bool HandleLibrary(cmMakefile& mf, cmTarget* target,
+ ProcessingState currentProcessingState,
+ const std::string& lib, cmTargetLinkLibraryType llt)
{
- if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
- this->CurrentProcessingState != ProcessingKeywordLinkInterface) {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
+ currentProcessingState != ProcessingKeywordLinkInterface) {
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
"INTERFACE library can only be used with the INTERFACE keyword of "
"target_link_libraries");
return false;
}
+ if (target->IsImported() &&
+ currentProcessingState != ProcessingKeywordLinkInterface) {
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
+ "IMPORTED library can only be used with the INTERFACE keyword of "
+ "target_link_libraries");
+ return false;
+ }
cmTarget::TLLSignature sig =
- (this->CurrentProcessingState == ProcessingPlainPrivateInterface ||
- this->CurrentProcessingState == ProcessingPlainPublicInterface ||
- this->CurrentProcessingState == ProcessingKeywordPrivateInterface ||
- this->CurrentProcessingState == ProcessingKeywordPublicInterface ||
- this->CurrentProcessingState == ProcessingKeywordLinkInterface)
+ (currentProcessingState == ProcessingPlainPrivateInterface ||
+ currentProcessingState == ProcessingPlainPublicInterface ||
+ currentProcessingState == ProcessingKeywordPrivateInterface ||
+ currentProcessingState == ProcessingKeywordPublicInterface ||
+ currentProcessingState == ProcessingKeywordLinkInterface)
? cmTarget::KeywordTLLSignature
: cmTarget::PlainTLLSignature;
- if (!this->Target->PushTLLCommandTrace(
- sig, this->Makefile->GetExecutionContext())) {
+ if (!target->PushTLLCommandTrace(sig, mf.GetExecutionContext())) {
std::ostringstream e;
- const char* modal = CM_NULLPTR;
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0023)) {
+ const char* modal = nullptr;
+ MessageType messageType = MessageType::AUTHOR_WARNING;
+ switch (mf.GetPolicyStatus(cmPolicies::CMP0023)) {
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0023) << "\n";
modal = "should";
@@ -323,7 +354,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib,
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::NEW:
modal = "must";
- messageType = cmake::FATAL_ERROR;
+ messageType = MessageType::FATAL_ERROR;
}
if (modal) {
@@ -331,122 +362,180 @@ 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";
- this->Target->GetTllSignatureTraces(e,
- sig == cmTarget::KeywordTLLSignature
- ? cmTarget::PlainTLLSignature
- : cmTarget::KeywordTLLSignature);
- this->Makefile->IssueMessage(messageType, e.str());
- if (messageType == cmake::FATAL_ERROR) {
+ e << "The " << existingSig
+ << " signature for target_link_libraries has "
+ "already been used with the target \""
+ << target->GetName()
+ << "\". All uses of target_link_libraries with a target " << modal
+ << " be either all-keyword or all-plain.\n";
+ target->GetTllSignatureTraces(e,
+ sig == cmTarget::KeywordTLLSignature
+ ? cmTarget::PlainTLLSignature
+ : cmTarget::KeywordTLLSignature);
+ mf.IssueMessage(messageType, e.str());
+ if (messageType == MessageType::FATAL_ERROR) {
return false;
}
}
}
- // Handle normal case first.
- if (this->CurrentProcessingState != ProcessingKeywordLinkInterface &&
- this->CurrentProcessingState != ProcessingPlainLinkInterface) {
-
- cmTarget* t =
- this->Makefile->FindLocalNonAliasTarget(this->Target->GetName());
- 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 {
+ bool warnRemoteInterface = false;
+ bool rejectRemoteLinking = false;
+ bool encodeRemoteReference = false;
+ if (&mf != target->GetMakefile()) {
+ // The LHS target was created in another directory.
+ switch (mf.GetPolicyStatus(cmPolicies::CMP0079)) {
+ case cmPolicies::WARN:
+ warnRemoteInterface = true;
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ rejectRemoteLinking = true;
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ encodeRemoteReference = true;
+ break;
+ }
+ }
- cmTarget* tgt = this->Makefile->GetGlobalGenerator()->FindTarget(lib);
-
- if (tgt && (tgt->GetType() != cmStateEnums::STATIC_LIBRARY) &&
- (tgt->GetType() != cmStateEnums::SHARED_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());
- }
+ std::string libRef;
+ if (encodeRemoteReference && !cmSystemTools::FileIsFullPath(lib)) {
+ // This is a library name added by a caller that is not in the
+ // same directory as the target was created. Add a suffix to
+ // the name to tell ResolveLinkItem to look up the name in the
+ // caller's directory.
+ cmDirectoryId const dirId = mf.GetDirectoryId();
+ libRef = lib + CMAKE_DIRECTORY_ID_SEP + dirId.String;
+ } else {
+ // This is an absolute path or a library name added by a caller
+ // in the same directory as the target was created. We can use
+ // the original name directly.
+ libRef = lib;
+ }
- this->Target->AddLinkLibrary(*this->Makefile, lib, llt);
+ // 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 (currentProcessingState != ProcessingKeywordLinkInterface &&
+ currentProcessingState != ProcessingPlainLinkInterface) {
+
+ if (rejectRemoteLinking) {
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Attempt to add link library \"", lib, "\" to target \"",
+ target->GetName(),
+ "\" which is not built in this "
+ "directory.\nThis is allowed only when policy CMP0079 "
+ "is set to NEW."));
+ return false;
}
- if (this->CurrentProcessingState == ProcessingLinkLibraries) {
- this->Target->AppendProperty(
- "INTERFACE_LINK_LIBRARIES",
- this->Target->GetDebugGeneratorExpressions(lib, llt).c_str());
- return true;
+ cmTarget* tgt = mf.GetGlobalGenerator()->FindTarget(lib);
+
+ if (tgt && (tgt->GetType() != cmStateEnums::STATIC_LIBRARY) &&
+ (tgt->GetType() != cmStateEnums::SHARED_LIBRARY) &&
+ (tgt->GetType() != cmStateEnums::UNKNOWN_LIBRARY) &&
+ (tgt->GetType() != cmStateEnums::OBJECT_LIBRARY) &&
+ (tgt->GetType() != cmStateEnums::INTERFACE_LIBRARY) &&
+ !tgt->IsExecutableWithExports()) {
+ mf.IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(
+ "Target \"", lib, "\" of type ",
+ cmState::GetTargetTypeName(tgt->GetType()),
+ " may not be linked into another target. One may link only to "
+ "INTERFACE, OBJECT, STATIC or SHARED libraries, or to ",
+ "executables with the ENABLE_EXPORTS property set."));
}
- 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());
+
+ target->AddLinkLibrary(mf, lib, libRef, llt);
+ }
+
+ if (warnRemoteInterface) {
+ mf.IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0079), "\nTarget\n ",
+ target->GetName(),
+ "\nis not created in this "
+ "directory. For compatibility with older versions of CMake, link "
+ "library\n ",
+ lib,
+ "\nwill be looked up in the directory in which "
+ "the target was created rather than in this calling directory."));
+ }
+
+ // 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 (currentProcessingState == ProcessingKeywordPrivateInterface ||
+ currentProcessingState == ProcessingPlainPrivateInterface) {
+ if (target->GetType() == cmStateEnums::STATIC_LIBRARY ||
+ target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ std::string configLib =
+ target->GetDebugGeneratorExpressions(libRef, 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;
+ target->AppendProperty("INTERFACE_LINK_LIBRARIES", configLib.c_str());
}
+ return true;
}
- this->Target->AppendProperty(
+ // 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.)
+ target->AppendProperty(
"INTERFACE_LINK_LIBRARIES",
- this->Target->GetDebugGeneratorExpressions(lib, llt).c_str());
+ target->GetDebugGeneratorExpressions(libRef, llt).c_str());
+ // Stop processing if called without any keyword.
+ if (currentProcessingState == ProcessingLinkLibraries) {
+ return true;
+ }
+ // Stop processing if policy CMP0022 is set to NEW.
const cmPolicies::PolicyStatus policy22Status =
- this->Target->GetPolicyStatusCMP0022();
-
+ target->GetPolicyStatusCMP0022();
if (policy22Status != cmPolicies::OLD &&
policy22Status != cmPolicies::WARN) {
return true;
}
-
- if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ // Stop processing if called with an INTERFACE library on the LHS.
+ if (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::vector<std::string>::const_iterator i = debugConfigs.begin();
- i != debugConfigs.end(); ++i) {
- prop = "LINK_INTERFACE_LIBRARIES_";
- prop += *i;
- 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 =
+ mf.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 = cmStrCat("LINK_INTERFACE_LIBRARIES_", dc);
+ target->AppendProperty(prop, libRef.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::vector<std::string>::const_iterator i = debugConfigs.begin();
- i != debugConfigs.end(); ++i) {
- prop = "LINK_INTERFACE_LIBRARIES_";
- prop += *i;
- if (!this->Target->GetProperty(prop)) {
- this->Target->SetProperty(prop, "");
+ if (llt == OPTIMIZED_LibraryType || llt == GENERAL_LibraryType) {
+ // Put in the non-DEBUG configuration interfaces.
+ target->AppendProperty("LINK_INTERFACE_LIBRARIES", libRef.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 = cmStrCat("LINK_INTERFACE_LIBRARIES_", dc);
+ if (!target->GetProperty(prop)) {
+ target->SetProperty(prop, "");
+ }
}
}
}
diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h
index 3fd20accd..4b2deabea 100644
--- a/Source/cmTargetLinkLibrariesCommand.h
+++ b/Source/cmTargetLinkLibrariesCommand.h
@@ -3,58 +3,14 @@
#ifndef cmTargetLinkLibrariesCommand_h
#define cmTargetLinkLibrariesCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-#include "cmTargetLinkLibraryType.h"
-
class cmExecutionStatus;
-class cmTarget;
-
-/** \class cmTargetLinkLibrariesCommand
- * \brief Specify a list of libraries to link into executables.
- *
- * 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).
- */
-class cmTargetLinkLibrariesCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmTargetLinkLibrariesCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- void LinkLibraryTypeSpecifierWarning(int left, int right);
- static const char* LinkLibraryTypeNames[3];
-
- cmTarget* Target;
- enum ProcessingState
- {
- ProcessingLinkLibraries,
- ProcessingPlainLinkInterface,
- ProcessingKeywordLinkInterface,
- ProcessingPlainPublicInterface,
- ProcessingKeywordPublicInterface,
- ProcessingPlainPrivateInterface,
- ProcessingKeywordPrivateInterface
- };
-
- ProcessingState CurrentProcessingState;
- bool HandleLibrary(const std::string& lib, cmTargetLinkLibraryType llt);
-};
+bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmTargetLinkOptionsCommand.cxx b/Source/cmTargetLinkOptionsCommand.cxx
new file mode 100644
index 000000000..df9416fad
--- /dev/null
+++ b/Source/cmTargetLinkOptionsCommand.cxx
@@ -0,0 +1,50 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmTargetLinkOptionsCommand.h"
+
+#include "cmListFileCache.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
+#include "cmTarget.h"
+#include "cmTargetPropCommandBase.h"
+
+namespace {
+
+class TargetLinkOptionsImpl : public cmTargetPropCommandBase
+{
+public:
+ using cmTargetPropCommandBase::cmTargetPropCommandBase;
+
+private:
+ void HandleMissingTarget(const std::string& name) override
+ {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Cannot specify link options for target \"", name,
+ "\" which is not built by this project."));
+ }
+
+ bool HandleDirectContent(cmTarget* tgt,
+ const std::vector<std::string>& content,
+ bool prepend, bool /*system*/) override
+ {
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ tgt->InsertLinkOption(this->Join(content), lfbt, prepend);
+ return true; // Successfully handled.
+ }
+
+ std::string Join(const std::vector<std::string>& content) override
+ {
+ return cmJoin(content, ";");
+ }
+};
+
+} // namespace
+
+bool cmTargetLinkOptionsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return TargetLinkOptionsImpl(status).HandleArguments(
+ args, "LINK_OPTIONS", TargetLinkOptionsImpl::PROCESS_BEFORE);
+}
diff --git a/Source/cmTargetLinkOptionsCommand.h b/Source/cmTargetLinkOptionsCommand.h
new file mode 100644
index 000000000..13fb40cb6
--- /dev/null
+++ b/Source/cmTargetLinkOptionsCommand.h
@@ -0,0 +1,16 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmTargetLinkOptionsCommand_h
+#define cmTargetLinkOptionsCommand_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+class cmExecutionStatus;
+
+bool cmTargetLinkOptionsCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+
+#endif
diff --git a/Source/cmTargetPrecompileHeadersCommand.cxx b/Source/cmTargetPrecompileHeadersCommand.cxx
new file mode 100644
index 000000000..c6e2e5c4f
--- /dev/null
+++ b/Source/cmTargetPrecompileHeadersCommand.cxx
@@ -0,0 +1,87 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmTargetPrecompileHeadersCommand.h"
+
+#include <utility>
+
+#include "cmGeneratorExpression.h"
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmTargetPropCommandBase.h"
+
+namespace {
+
+std::vector<std::string> ConvertToAbsoluteContent(
+ const std::vector<std::string>& content, std::string const& baseDir)
+{
+ std::vector<std::string> absoluteContent;
+ absoluteContent.reserve(content.size());
+ for (std::string const& src : content) {
+ std::string absoluteSrc;
+ // Use '<foo.h>' and '"foo.h"' includes and absolute paths as-is.
+ // Interpret relative paths with respect to the source directory.
+ // If the path starts in a generator expression, assume it is absolute.
+ if (cmHasLiteralPrefix(src, "<") || cmHasLiteralPrefix(src, "\"") ||
+ cmSystemTools::FileIsFullPath(src) ||
+ cmGeneratorExpression::Find(src) == 0) {
+ absoluteSrc = src;
+ } else {
+ absoluteSrc = cmStrCat(baseDir, '/', src);
+ }
+ absoluteContent.emplace_back(std::move(absoluteSrc));
+ }
+ return absoluteContent;
+}
+
+class TargetPrecompileHeadersImpl : public cmTargetPropCommandBase
+{
+public:
+ using cmTargetPropCommandBase::cmTargetPropCommandBase;
+
+private:
+ bool HandleDirectContent(cmTarget* tgt,
+ const std::vector<std::string>& content,
+ bool /*prepend*/, bool /*system*/) override
+ {
+ std::string const& base = this->Makefile->GetCurrentSourceDirectory();
+ tgt->AppendProperty(
+ "PRECOMPILE_HEADERS",
+ this->Join(ConvertToAbsoluteContent(content, base)).c_str());
+ return true;
+ }
+
+ void HandleInterfaceContent(cmTarget* tgt,
+ const std::vector<std::string>& content,
+ bool prepend, bool system) override
+ {
+ std::string const& base = this->Makefile->GetCurrentSourceDirectory();
+ cmTargetPropCommandBase::HandleInterfaceContent(
+ tgt, ConvertToAbsoluteContent(content, base), prepend, system);
+ }
+
+ void HandleMissingTarget(const std::string& name) override
+ {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Cannot specify precompile headers for target \"", name,
+ "\" which is not built by this project."));
+ }
+
+ std::string Join(const std::vector<std::string>& content) override
+ {
+ return cmJoin(content, ";");
+ }
+};
+
+} // namespace
+
+bool cmTargetPrecompileHeadersCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ return TargetPrecompileHeadersImpl(status).HandleArguments(
+ args, "PRECOMPILE_HEADERS",
+ TargetPrecompileHeadersImpl::PROCESS_REUSE_FROM);
+}
diff --git a/Source/cmTargetPrecompileHeadersCommand.h b/Source/cmTargetPrecompileHeadersCommand.h
new file mode 100644
index 000000000..8b0ac9777
--- /dev/null
+++ b/Source/cmTargetPrecompileHeadersCommand.h
@@ -0,0 +1,16 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmTargetPrecompileHeadersCommand_h
+#define cmTargetPrecompileHeadersCommand_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+class cmExecutionStatus;
+
+bool cmTargetPrecompileHeadersCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
+
+#endif
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index 45fe430c1..bbc1e16f7 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -2,12 +2,24 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTargetPropCommandBase.h"
+#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmStateTypes.h"
#include "cmTarget.h"
#include "cmake.h"
+cmTargetPropCommandBase::cmTargetPropCommandBase(cmExecutionStatus& status)
+ : Makefile(&status.GetMakefile())
+ , Status(status)
+{
+}
+
+void cmTargetPropCommandBase::SetError(std::string const& e)
+{
+ this->Status.SetError(e);
+}
+
bool cmTargetPropCommandBase::HandleArguments(
std::vector<std::string> const& args, const std::string& prop,
ArgumentFlags flags)
@@ -17,11 +29,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]);
@@ -32,12 +44,13 @@ bool cmTargetPropCommandBase::HandleArguments(
this->HandleMissingTarget(args[0]);
return false;
}
- if ((this->Target->GetType() != cmStateEnums::SHARED_LIBRARY) &&
+ if ((this->Target->GetType() != cmStateEnums::EXECUTABLE) &&
(this->Target->GetType() != cmStateEnums::STATIC_LIBRARY) &&
- (this->Target->GetType() != cmStateEnums::OBJECT_LIBRARY) &&
+ (this->Target->GetType() != cmStateEnums::SHARED_LIBRARY) &&
(this->Target->GetType() != cmStateEnums::MODULE_LIBRARY) &&
+ (this->Target->GetType() != cmStateEnums::OBJECT_LIBRARY) &&
(this->Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) &&
- (this->Target->GetType() != cmStateEnums::EXECUTABLE)) {
+ (this->Target->GetType() != cmStateEnums::UNKNOWN_LIBRARY)) {
this->SetError("called with non-compilable target type");
return false;
}
@@ -64,6 +77,19 @@ bool cmTargetPropCommandBase::HandleArguments(
++argIndex;
}
+ if ((flags & PROCESS_REUSE_FROM) && args[argIndex] == "REUSE_FROM") {
+ if (args.size() != 3) {
+ this->SetError("called with incorrect number of arguments");
+ return false;
+ }
+ ++argIndex;
+
+ this->Target->SetProperty("PRECOMPILE_HEADERS_REUSE_FROM",
+ args[argIndex].c_str());
+
+ ++argIndex;
+ }
+
this->Property = prop;
while (argIndex < args.size()) {
@@ -85,18 +111,6 @@ bool cmTargetPropCommandBase::ProcessContentArgs(
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");
- return false;
- }
-
++argIndex;
std::vector<std::string> content;
@@ -104,10 +118,21 @@ bool cmTargetPropCommandBase::ProcessContentArgs(
for (unsigned int i = argIndex; i < args.size(); ++i, ++argIndex) {
if (args[i] == "PUBLIC" || args[i] == "PRIVATE" ||
args[i] == "INTERFACE") {
- return this->PopulateTargetProperies(scope, content, prepend, system);
+ break;
}
content.push_back(args[i]);
}
+ if (!content.empty()) {
+ if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
+ scope != "INTERFACE") {
+ 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;
+ }
+ }
return this->PopulateTargetProperies(scope, content, prepend, system);
}
@@ -115,6 +140,9 @@ bool cmTargetPropCommandBase::PopulateTargetProperies(
const std::string& scope, const std::vector<std::string>& content,
bool prepend, bool system)
{
+ if (content.empty()) {
+ return true;
+ }
if (scope == "PRIVATE" || scope == "PUBLIC") {
if (!this->HandleDirectContent(this->Target, content, prepend, system)) {
return false;
diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h
index 46a2f6b07..601ad0113 100644
--- a/Source/cmTargetPropCommandBase.h
+++ b/Source/cmTargetPropCommandBase.h
@@ -8,18 +8,24 @@
#include <string>
#include <vector>
-#include "cmCommand.h"
-
+class cmExecutionStatus;
+class cmMakefile;
class cmTarget;
-class cmTargetPropCommandBase : public cmCommand
+class cmTargetPropCommandBase
{
public:
+ cmTargetPropCommandBase(cmExecutionStatus& status);
+ virtual ~cmTargetPropCommandBase() = default;
+
+ void SetError(std::string const& e);
+
enum ArgumentFlags
{
- NO_FLAGS = 0,
- PROCESS_BEFORE = 1,
- PROCESS_SYSTEM = 2
+ NO_FLAGS = 0x0,
+ PROCESS_BEFORE = 0x1,
+ PROCESS_SYSTEM = 0x2,
+ PROCESS_REUSE_FROM = 0x3
};
bool HandleArguments(std::vector<std::string> const& args,
@@ -28,14 +34,14 @@ public:
protected:
std::string Property;
- cmTarget* Target;
+ cmTarget* Target = nullptr;
+ cmMakefile* Makefile;
virtual void HandleInterfaceContent(cmTarget* tgt,
const std::vector<std::string>& content,
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,
@@ -49,6 +55,8 @@ private:
bool PopulateTargetProperies(const std::string& scope,
const std::vector<std::string>& content,
bool prepend, bool system);
+
+ cmExecutionStatus& Status;
};
#endif
diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx
index a57bc5aea..baab8da0a 100644
--- a/Source/cmTargetPropertyComputer.cxx
+++ b/Source/cmTargetPropertyComputer.cxx
@@ -3,21 +3,23 @@
#include "cmTargetPropertyComputer.h"
+#include <cctype>
#include <sstream>
+#include <unordered_set>
+#include "cmMessageType.h"
#include "cmMessenger.h"
#include "cmPolicies.h"
#include "cmStateSnapshot.h"
-#include "cm_unordered_set.hxx"
-#include "cmake.h"
+#include "cmStringAlgorithms.h"
bool cmTargetPropertyComputer::HandleLocationPropertyPolicy(
std::string const& tgtName, cmMessenger* messenger,
cmListFileBacktrace const& context)
{
std::ostringstream e;
- const char* modal = CM_NULLPTR;
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ const char* modal = nullptr;
+ MessageType messageType = MessageType::AUTHOR_WARNING;
switch (context.GetBottom().GetPolicy(cmPolicies::CMP0026)) {
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0026) << "\n";
@@ -28,7 +30,7 @@ bool cmTargetPropertyComputer::HandleLocationPropertyPolicy(
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::NEW:
modal = "may";
- messageType = cmake::FATAL_ERROR;
+ messageType = MessageType::FATAL_ERROR;
}
if (modal) {
@@ -40,7 +42,7 @@ bool cmTargetPropertyComputer::HandleLocationPropertyPolicy(
messenger->IssueMessage(messageType, e.str(), context);
}
- return messageType != cmake::FATAL_ERROR;
+ return messageType != MessageType::FATAL_ERROR;
}
bool cmTargetPropertyComputer::WhiteListedInterfaceProperty(
@@ -49,29 +51,46 @@ bool cmTargetPropertyComputer::WhiteListedInterfaceProperty(
if (cmHasLiteralPrefix(prop, "INTERFACE_")) {
return true;
}
- static CM_UNORDERED_SET<std::string> builtIns;
- if (builtIns.empty()) {
- builtIns.insert("COMPATIBLE_INTERFACE_BOOL");
- builtIns.insert("COMPATIBLE_INTERFACE_NUMBER_MAX");
- builtIns.insert("COMPATIBLE_INTERFACE_NUMBER_MIN");
- builtIns.insert("COMPATIBLE_INTERFACE_STRING");
- builtIns.insert("EXPORT_NAME");
- builtIns.insert("IMPORTED");
- builtIns.insert("NAME");
- builtIns.insert("TYPE");
+ if (cmHasLiteralPrefix(prop, "_")) {
+ return true;
+ }
+ if (std::islower(prop[0])) {
+ return true;
}
+ static std::unordered_set<std::string> const builtIns{
+ "COMPATIBLE_INTERFACE_BOOL",
+ "COMPATIBLE_INTERFACE_NUMBER_MAX",
+ "COMPATIBLE_INTERFACE_NUMBER_MIN",
+ "COMPATIBLE_INTERFACE_STRING",
+ "EXPORT_NAME",
+ "EXPORT_PROPERTIES",
+ "IMPORTED",
+ "IMPORTED_GLOBAL",
+ "MANUALLY_ADDED_DEPENDENCIES",
+ "NAME",
+ "PRIVATE_HEADER",
+ "PUBLIC_HEADER",
+ "TYPE"
+ };
if (builtIns.count(prop)) {
return true;
}
if (prop == "IMPORTED_CONFIGURATIONS" || prop == "IMPORTED_LIBNAME" ||
- prop == "NO_SYSTEM_FROM_IMPORTED" ||
cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME_") ||
cmHasLiteralPrefix(prop, "MAP_IMPORTED_CONFIG_")) {
return true;
}
+ // This property should not be allowed but was incorrectly added in
+ // CMake 3.8. We can't remove it from the whitelist without breaking
+ // projects that try to set it. One day we could warn about this, but
+ // for now silently accept it.
+ if (prop == "NO_SYSTEM_FROM_IMPORTED") {
+ return true;
+ }
+
return false;
}
@@ -85,7 +104,7 @@ bool cmTargetPropertyComputer::PassesWhitelist(
e << "INTERFACE_LIBRARY targets may only have whitelisted properties. "
"The property \""
<< prop << "\" is not allowed.";
- messenger->IssueMessage(cmake::FATAL_ERROR, e.str(), context);
+ messenger->IssueMessage(MessageType::FATAL_ERROR, e.str(), context);
return false;
}
return true;
diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h
index 94688e313..3b11acdc1 100644
--- a/Source/cmTargetPropertyComputer.h
+++ b/Source/cmTargetPropertyComputer.h
@@ -7,9 +7,9 @@
#include <string>
-#include "cmAlgorithms.h"
#include "cmListFileCache.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
class cmMessenger;
@@ -26,12 +26,12 @@ public:
return loc;
}
if (cmSystemTools::GetFatalErrorOccured()) {
- return CM_NULLPTR;
+ return nullptr;
}
if (prop == "SOURCES") {
return GetSources(tgt, messenger, context);
}
- return CM_NULLPTR;
+ return nullptr;
}
static bool WhiteListedInterfaceProperty(const std::string& prop);
@@ -69,7 +69,7 @@ private:
if (!tgt->IsImported() &&
!HandleLocationPropertyPolicy(tgt->GetName(), messenger,
context)) {
- return CM_NULLPTR;
+ return nullptr;
}
return ComputeLocationForBuild(tgt);
}
@@ -79,9 +79,9 @@ private:
if (!tgt->IsImported() &&
!HandleLocationPropertyPolicy(tgt->GetName(), messenger,
context)) {
- return CM_NULLPTR;
+ return nullptr;
}
- const char* configName = prop.c_str() + 9;
+ std::string configName = prop.substr(9);
return ComputeLocation(tgt, configName);
}
@@ -93,13 +93,13 @@ private:
if (!tgt->IsImported() &&
!HandleLocationPropertyPolicy(tgt->GetName(), messenger,
context)) {
- return CM_NULLPTR;
+ return nullptr;
}
return ComputeLocation(tgt, configName);
}
}
}
- return CM_NULLPTR;
+ return nullptr;
}
template <typename Target>
diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx
index 058659a52..c2e0b28fe 100644
--- a/Source/cmTargetSourcesCommand.cxx
+++ b/Source/cmTargetSourcesCommand.cxx
@@ -4,44 +4,134 @@
#include <sstream>
-#include "cmAlgorithms.h"
+#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmPolicies.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
#include "cmTarget.h"
-#include "cmake.h"
+#include "cmTargetPropCommandBase.h"
-class cmExecutionStatus;
+namespace {
-bool cmTargetSourcesCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+class TargetSourcesImpl : public cmTargetPropCommandBase
{
- return this->HandleArguments(args, "SOURCES");
-}
+public:
+ using cmTargetPropCommandBase::cmTargetPropCommandBase;
-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());
-}
+protected:
+ void HandleInterfaceContent(cmTarget* tgt,
+ const std::vector<std::string>& content,
+ bool prepend, bool system) override
+ {
+ cmTargetPropCommandBase::HandleInterfaceContent(
+ tgt, ConvertToAbsoluteContent(tgt, content, true), prepend, system);
+ }
+
+private:
+ void HandleMissingTarget(const std::string& name) override
+ {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Cannot specify sources for target \"", name,
+ "\" which is not built by this project."));
+ }
+
+ bool HandleDirectContent(cmTarget* tgt,
+ const std::vector<std::string>& content,
+ bool /*prepend*/, bool /*system*/) override
+ {
+ tgt->AppendProperty(
+ "SOURCES",
+ this->Join(ConvertToAbsoluteContent(tgt, content, false)).c_str());
+ return true; // Successfully handled.
+ }
+
+ std::string Join(const std::vector<std::string>& content) override
+ {
+ return cmJoin(content, ";");
+ }
+
+ std::vector<std::string> ConvertToAbsoluteContent(
+ cmTarget* tgt, const std::vector<std::string>& content,
+ bool isInterfaceContent);
+};
-void cmTargetSourcesCommand::HandleMissingTarget(const std::string& name)
+std::vector<std::string> TargetSourcesImpl::ConvertToAbsoluteContent(
+ cmTarget* tgt, const std::vector<std::string>& content,
+ bool isInterfaceContent)
{
+ // Skip conversion in case old behavior has been explicitly requested
+ if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076) ==
+ cmPolicies::OLD) {
+ return content;
+ }
+
+ bool changedPath = false;
+ std::vector<std::string> absoluteContent;
+ absoluteContent.reserve(content.size());
+ for (std::string const& src : content) {
+ std::string absoluteSrc;
+ if (cmSystemTools::FileIsFullPath(src) ||
+ cmGeneratorExpression::Find(src) == 0 ||
+ (!isInterfaceContent &&
+ (this->Makefile->GetCurrentSourceDirectory() ==
+ tgt->GetMakefile()->GetCurrentSourceDirectory()))) {
+ absoluteSrc = src;
+ } else {
+ changedPath = true;
+ absoluteSrc =
+ cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', src);
+ }
+ absoluteContent.push_back(absoluteSrc);
+ }
+
+ if (!changedPath) {
+ return content;
+ }
+
+ bool issueMessage = true;
+ bool useAbsoluteContent = false;
std::ostringstream e;
- e << "Cannot specify sources for target \"" << name
- << "\" "
- "which is not built by this project.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076)) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0076) << "\n";
+ break;
+ case cmPolicies::OLD:
+ issueMessage = false;
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0076));
+ break;
+ case cmPolicies::NEW: {
+ issueMessage = false;
+ useAbsoluteContent = true;
+ break;
+ }
+ }
-std::string cmTargetSourcesCommand::Join(
- const std::vector<std::string>& content)
-{
- return cmJoin(content, ";");
+ if (issueMessage) {
+ if (isInterfaceContent) {
+ e << "An interface source of target \"" << tgt->GetName()
+ << "\" has a relative path.";
+ } else {
+ e << "A private source from a directory other than that of target \""
+ << tgt->GetName() << "\" has a relative path.";
+ }
+ this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
+ }
+
+ return useAbsoluteContent ? absoluteContent : content;
}
-bool cmTargetSourcesCommand::HandleDirectContent(
- cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
+} // namespace
+
+bool cmTargetSourcesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
- tgt->AppendProperty("SOURCES", this->Join(content).c_str());
- return true;
+ return TargetSourcesImpl(status).HandleArguments(args, "SOURCES");
}
diff --git a/Source/cmTargetSourcesCommand.h b/Source/cmTargetSourcesCommand.h
index 09ba72915..5eecf3454 100644
--- a/Source/cmTargetSourcesCommand.h
+++ b/Source/cmTargetSourcesCommand.h
@@ -3,41 +3,14 @@
#ifndef cmTargetSourcesCommand_h
#define cmTargetSourcesCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmTargetPropCommandBase.h"
-
-class cmCommand;
class cmExecutionStatus;
-class cmTarget;
-
-class cmTargetSourcesCommand : public cmTargetPropCommandBase
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmTargetSourcesCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- void HandleImportedTarget(const std::string& tgt) CM_OVERRIDE;
- void HandleMissingTarget(const std::string& name) CM_OVERRIDE;
-
- bool HandleDirectContent(cmTarget* tgt,
- const std::vector<std::string>& content,
- bool prepend, bool system) CM_OVERRIDE;
- std::string Join(const std::vector<std::string>& content) CM_OVERRIDE;
-};
+bool cmTargetSourcesCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx
index 4d0cbaafc..d5c61c173 100644
--- a/Source/cmTest.cxx
+++ b/Source/cmTest.cxx
@@ -5,18 +5,17 @@
#include "cmMakefile.h"
#include "cmProperty.h"
#include "cmState.h"
-#include "cmSystemTools.h"
+#include "cmStringAlgorithms.h"
cmTest::cmTest(cmMakefile* mf)
- : Backtrace(mf->GetBacktrace())
+ : CommandExpandLists(false)
+ , Backtrace(mf->GetBacktrace())
{
this->Makefile = mf;
this->OldStyle = true;
}
-cmTest::~cmTest()
-{
-}
+cmTest::~cmTest() = default;
cmListFileBacktrace const& cmTest::GetBacktrace() const
{
@@ -48,7 +47,7 @@ const char* cmTest::GetProperty(const std::string& prop) const
bool cmTest::GetPropertyAsBool(const std::string& prop) const
{
- return cmSystemTools::IsOn(this->GetProperty(prop));
+ return cmIsOn(this->GetProperty(prop));
}
void cmTest::SetProperty(const std::string& prop, const char* value)
@@ -61,3 +60,13 @@ void cmTest::AppendProperty(const std::string& prop, const char* value,
{
this->Properties.AppendProperty(prop, value, asString);
}
+
+bool cmTest::GetCommandExpandLists() const
+{
+ return this->CommandExpandLists;
+}
+
+void cmTest::SetCommandExpandLists(bool b)
+{
+ this->CommandExpandLists = b;
+}
diff --git a/Source/cmTest.h b/Source/cmTest.h
index d4839d171..dd246c4e6 100644
--- a/Source/cmTest.h
+++ b/Source/cmTest.h
@@ -5,12 +5,12 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmListFileCache.h"
-#include "cmPropertyMap.h"
-
#include <string>
#include <vector>
+#include "cmListFileCache.h"
+#include "cmPropertyMap.h"
+
class cmMakefile;
/** \class cmTest
@@ -26,14 +26,14 @@ public:
cmTest(cmMakefile* mf);
~cmTest();
- ///! Set the test name
+ //! Set the test name
void SetName(const std::string& name);
std::string GetName() const { return this->Name; }
void SetCommand(std::vector<std::string> const& command);
std::vector<std::string> const& GetCommand() const { return this->Command; }
- ///! Set/Get a property of this source file
+ //! Set/Get a property of this source file
void SetProperty(const std::string& prop, const char* value);
void AppendProperty(const std::string& prop, const char* value,
bool asString = false);
@@ -51,10 +51,15 @@ public:
bool GetOldStyle() const { return this->OldStyle; }
void SetOldStyle(bool b) { this->OldStyle = b; }
+ /** Set/Get whether lists in command lines should be expanded. */
+ bool GetCommandExpandLists() const;
+ void SetCommandExpandLists(bool b);
+
private:
cmPropertyMap Properties;
std::string Name;
std::vector<std::string> Command;
+ bool CommandExpandLists;
bool OldStyle;
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx
index be4b37847..333d4d5ee 100644
--- a/Source/cmTestGenerator.cxx
+++ b/Source/cmTestGenerator.cxx
@@ -2,17 +2,20 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTestGenerator.h"
-#include <map>
+#include <memory>
#include <ostream>
#include <utility>
+#include <vector>
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
+#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmOutputConverter.h"
-#include "cmProperty.h"
#include "cmPropertyMap.h"
+#include "cmRange.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTest.h"
@@ -23,18 +26,26 @@ cmTestGenerator::cmTestGenerator(
{
this->ActionsPerConfig = !test->GetOldStyle();
this->TestGenerated = false;
- this->LG = CM_NULLPTR;
+ this->LG = nullptr;
}
-cmTestGenerator::~cmTestGenerator()
-{
-}
+cmTestGenerator::~cmTestGenerator() = default;
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.
@@ -67,12 +78,22 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
// Start the test command.
os << indent << "add_test(" << this->Test->GetName() << " ";
- // Get the test command line to be executed.
- std::vector<std::string> const& command = this->Test->GetCommand();
+ // Evaluate command line arguments
+ std::vector<std::string> argv =
+ EvaluateCommandLineArguments(this->Test->GetCommand(), ge, config);
+
+ // Expand arguments if COMMAND_EXPAND_LISTS is set
+ if (this->Test->GetCommandExpandLists()) {
+ argv = cmExpandedLists(argv.begin(), argv.end());
+ // Expanding lists on an empty command may have left it empty
+ if (argv.empty()) {
+ argv.emplace_back();
+ }
+ }
// Check whether the command executable is a target whose name is to
// be translated.
- std::string exe = command[0];
+ std::string exe = argv[0];
cmGeneratorTarget* target = this->LG->FindGeneratorTargetToUse(exe);
if (target && target->GetType() == cmStateEnums::EXECUTABLE) {
// Use the target file on disk.
@@ -80,47 +101,40 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
// Prepend with the emulator when cross compiling if required.
const char* emulator = target->GetProperty("CROSSCOMPILING_EMULATOR");
- if (emulator != CM_NULLPTR) {
- std::vector<std::string> emulatorWithArgs;
- cmSystemTools::ExpandListArgument(emulator, emulatorWithArgs);
+ if (emulator != nullptr && *emulator) {
+ std::vector<std::string> emulatorWithArgs = cmExpandedList(emulator);
std::string emulatorExe(emulatorWithArgs[0]);
cmSystemTools::ConvertToUnixSlashes(emulatorExe);
os << cmOutputConverter::EscapeForCMake(emulatorExe) << " ";
- for (std::vector<std::string>::const_iterator ei =
- emulatorWithArgs.begin() + 1;
- ei != emulatorWithArgs.end(); ++ei) {
- os << cmOutputConverter::EscapeForCMake(*ei) << " ";
+ for (std::string const& arg : cmMakeRange(emulatorWithArgs).advance(1)) {
+ os << cmOutputConverter::EscapeForCMake(arg) << " ";
}
}
} else {
// Use the command name given.
- exe = ge.Parse(exe.c_str())->Evaluate(this->LG, config);
cmSystemTools::ConvertToUnixSlashes(exe);
}
// Generate the command line with full escapes.
os << cmOutputConverter::EscapeForCMake(exe);
- for (std::vector<std::string>::const_iterator ci = command.begin() + 1;
- ci != command.end(); ++ci) {
- os << " " << cmOutputConverter::EscapeForCMake(
- ge.Parse(*ci)->Evaluate(this->LG, config));
+
+ for (auto const& arg : cmMakeRange(argv).advance(1)) {
+ os << " " << cmOutputConverter::EscapeForCMake(arg);
}
// Finish the test command.
os << ")\n";
// Output properties for the test.
- cmPropertyMap& pm = this->Test->GetProperties();
- if (!pm.empty()) {
- os << indent << "set_tests_properties(" << this->Test->GetName()
- << " PROPERTIES ";
- for (cmPropertyMap::const_iterator i = pm.begin(); i != pm.end(); ++i) {
- os << " " << i->first << " "
- << cmOutputConverter::EscapeForCMake(
- ge.Parse(i->second.GetValue())->Evaluate(this->LG, config));
- }
- os << ")" << std::endl;
+ os << indent << "set_tests_properties(" << this->Test->GetName()
+ << " PROPERTIES ";
+ for (auto const& i : this->Test->GetProperties().GetList()) {
+ os << " " << i.first << " "
+ << cmOutputConverter::EscapeForCMake(
+ ge.Parse(i.second)->Evaluate(this->LG, config));
}
+ this->GenerateInternalProperties(os);
+ os << ")" << std::endl;
}
void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os, Indent indent)
@@ -149,34 +163,68 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout, Indent indent)
fout << "add_test(";
fout << this->Test->GetName() << " \"" << exe << "\"";
- for (std::vector<std::string>::const_iterator argit = command.begin() + 1;
- argit != command.end(); ++argit) {
+ for (std::string const& arg : cmMakeRange(command).advance(1)) {
// Just double-quote all arguments so they are re-parsed
// correctly by the test system.
fout << " \"";
- for (std::string::const_iterator c = argit->begin(); c != argit->end();
- ++c) {
+ for (char c : arg) {
// Escape quotes within arguments. We should escape
// backslashes too but we cannot because it makes the result
// inconsistent with previous behavior of this command.
- if ((*c == '"')) {
+ if (c == '"') {
fout << '\\';
}
- fout << *c;
+ fout << c;
}
fout << "\"";
}
fout << ")" << std::endl;
// Output properties for the test.
- cmPropertyMap& pm = this->Test->GetProperties();
- if (!pm.empty()) {
- fout << indent << "set_tests_properties(" << this->Test->GetName()
- << " PROPERTIES ";
- for (cmPropertyMap::const_iterator i = pm.begin(); i != pm.end(); ++i) {
- fout << " " << i->first << " "
- << cmOutputConverter::EscapeForCMake(i->second.GetValue());
+ fout << indent << "set_tests_properties(" << this->Test->GetName()
+ << " PROPERTIES ";
+ for (auto const& i : this->Test->GetProperties().GetList()) {
+ fout << " " << i.first << " "
+ << cmOutputConverter::EscapeForCMake(i.second);
+ }
+ this->GenerateInternalProperties(fout);
+ fout << ")" << std::endl;
+}
+
+void cmTestGenerator::GenerateInternalProperties(std::ostream& os)
+{
+ cmListFileBacktrace bt = this->Test->GetBacktrace();
+ if (bt.Empty()) {
+ return;
+ }
+
+ os << " "
+ << "_BACKTRACE_TRIPLES"
+ << " \"";
+
+ bool prependTripleSeparator = false;
+ while (!bt.Empty()) {
+ const auto& entry = bt.Top();
+ if (prependTripleSeparator) {
+ os << ";";
}
- fout << ")" << std::endl;
+ os << entry.FilePath << ";" << entry.Line << ";" << entry.Name;
+ bt = bt.Pop();
+ prependTripleSeparator = true;
}
+
+ os << "\"";
+}
+
+std::vector<std::string> cmTestGenerator::EvaluateCommandLineArguments(
+ const std::vector<std::string>& argv, cmGeneratorExpression& ge,
+ const std::string& config) const
+{
+ // Evaluate executable name and arguments
+ auto evaluatedRange =
+ cmMakeRange(argv).transform([&](const std::string& arg) {
+ return ge.Parse(arg)->Evaluate(this->LG, config);
+ });
+
+ return { evaluatedRange.begin(), evaluatedRange.end() };
}
diff --git a/Source/cmTestGenerator.h b/Source/cmTestGenerator.h
index b2273050f..e388c1643 100644
--- a/Source/cmTestGenerator.h
+++ b/Source/cmTestGenerator.h
@@ -3,14 +3,15 @@
#ifndef cmTestGenerator_h
#define cmTestGenerator_h
-#include "cmConfigure.h"
-
-#include "cmScriptGenerator.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
#include <vector>
+#include "cmScriptGenerator.h"
+
+class cmGeneratorExpression;
class cmLocalGenerator;
class cmTest;
@@ -20,23 +21,35 @@ class cmTest;
*/
class cmTestGenerator : public cmScriptGenerator
{
- CM_DISABLE_COPY(cmTestGenerator)
-
public:
cmTestGenerator(cmTest* test,
std::vector<std::string> const& configurations =
std::vector<std::string>());
- ~cmTestGenerator() CM_OVERRIDE;
+ ~cmTestGenerator() override;
+
+ cmTestGenerator(cmTestGenerator const&) = delete;
+ cmTestGenerator& operator=(cmTestGenerator const&) = delete;
void Compute(cmLocalGenerator* lg);
+ /** Test if this generator installs the test for a given configuration. */
+ bool TestsForConfig(const std::string& config);
+
+ cmTest* GetTest() const;
+
+private:
+ void GenerateInternalProperties(std::ostream& os);
+ std::vector<std::string> EvaluateCommandLineArguments(
+ const std::vector<std::string>& argv, cmGeneratorExpression& ge,
+ const std::string& config) const;
+
protected:
- void GenerateScriptConfigs(std::ostream& os, Indent indent) CM_OVERRIDE;
- void GenerateScriptActions(std::ostream& os, Indent indent) CM_OVERRIDE;
+ void GenerateScriptConfigs(std::ostream& os, Indent indent) override;
+ void GenerateScriptActions(std::ostream& os, Indent indent) override;
void GenerateScriptForConfig(std::ostream& os, const std::string& config,
- Indent indent) CM_OVERRIDE;
- void GenerateScriptNoConfig(std::ostream& os, Indent indent) CM_OVERRIDE;
- bool NeedsScriptNoConfig() const CM_OVERRIDE;
+ Indent indent) override;
+ void GenerateScriptNoConfig(std::ostream& os, Indent indent) override;
+ bool NeedsScriptNoConfig() const override;
void GenerateOldStyle(std::ostream& os, Indent indent);
cmLocalGenerator* LG;
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index 4b9718847..390fd16b0 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -2,17 +2,17 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTimestamp.h"
-#include "cmConfigure.h"
+#include <cstdlib>
#include <cstring>
#include <sstream>
-#include <stdlib.h>
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
std::string cmTimestamp::CurrentTime(const std::string& formatString,
bool utcFlag)
{
- time_t currentTimeT = time(CM_NULLPTR);
+ time_t currentTimeT = time(nullptr);
std::string source_date_epoch;
cmSystemTools::GetEnv("SOURCE_DATE_EPOCH", source_date_epoch);
if (!source_date_epoch.empty()) {
@@ -34,11 +34,14 @@ std::string cmTimestamp::FileModificationTime(const char* path,
const std::string& formatString,
bool utcFlag)
{
- if (!cmsys::SystemTools::FileExists(path)) {
+ std::string real_path =
+ cmSystemTools::GetRealPathResolvingWindowsSubst(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);
}
@@ -56,14 +59,14 @@ std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT,
struct tm timeStruct;
memset(&timeStruct, 0, sizeof(timeStruct));
- struct tm* ptr = (struct tm*)CM_NULLPTR;
+ struct tm* ptr = nullptr;
if (utcFlag) {
ptr = gmtime(&timeT);
} else {
ptr = localtime(&timeT);
}
- if (ptr == CM_NULLPTR) {
+ if (ptr == nullptr) {
return std::string();
}
@@ -94,7 +97,7 @@ time_t cmTimestamp::CreateUtcTimeTFromTm(struct tm& tm) const
// From Linux timegm() manpage.
std::string tz_old;
- cmSystemTools::GetEnv("TZ", tz_old);
+ bool const tz_was_set = cmSystemTools::GetEnv("TZ", tz_old);
tz_old = "TZ=" + tz_old;
// The standard says that "TZ=" or "TZ=[UNRECOGNIZED_TZ]" means UTC.
@@ -107,7 +110,17 @@ time_t cmTimestamp::CreateUtcTimeTFromTm(struct tm& tm) const
time_t result = mktime(&tm);
+# ifndef CMAKE_BOOTSTRAP
+ if (tz_was_set) {
+ cmSystemTools::PutEnv(tz_old);
+ } else {
+ cmSystemTools::UnsetEnv("TZ");
+ }
+# else
+ // No UnsetEnv during bootstrap. This is good enough for CMake itself.
cmSystemTools::PutEnv(tz_old);
+ static_cast<void>(tz_was_set);
+# endif
tzset();
@@ -119,12 +132,13 @@ std::string cmTimestamp::AddTimestampComponent(char flag,
struct tm& timeStruct,
const time_t timeT) const
{
- std::string formatString = "%";
- formatString += flag;
+ std::string formatString = cmStrCat('%', flag);
switch (flag) {
case 'a':
+ case 'A':
case 'b':
+ case 'B':
case 'd':
case 'H':
case 'I':
@@ -150,13 +164,11 @@ 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();
}
- std::ostringstream ss;
- ss << static_cast<long int>(difftime(timeT, unixEpoch));
- return ss.str();
+ return std::to_string(static_cast<long int>(difftime(timeT, unixEpoch)));
}
default: {
return formatString;
diff --git a/Source/cmTimestamp.h b/Source/cmTimestamp.h
index 8dd499a3e..40338f8b2 100644
--- a/Source/cmTimestamp.h
+++ b/Source/cmTimestamp.h
@@ -5,8 +5,8 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <ctime>
#include <string>
-#include <time.h>
/** \class cmTimestamp
* \brief Utility class to generate string representation of a timestamp
@@ -15,20 +15,18 @@
class cmTimestamp
{
public:
- cmTimestamp() {}
-
std::string CurrentTime(const std::string& formatString, bool utcFlag);
std::string FileModificationTime(const char* path,
const std::string& formatString,
bool utcFlag);
-private:
- time_t CreateUtcTimeTFromTm(struct tm& timeStruct) const;
-
std::string CreateTimestampFromTimeT(time_t timeT, std::string formatString,
bool utcFlag) const;
+private:
+ time_t CreateUtcTimeTFromTm(struct tm& timeStruct) const;
+
std::string AddTimestampComponent(char flag, struct tm& timeStruct,
time_t timeT) const;
};
diff --git a/Source/cmTryCompileCommand.cxx b/Source/cmTryCompileCommand.cxx
index b6bfbfa69..05b3f0587 100644
--- a/Source/cmTryCompileCommand.cxx
+++ b/Source/cmTryCompileCommand.cxx
@@ -3,6 +3,7 @@
#include "cmTryCompileCommand.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmake.h"
class cmExecutionStatus;
@@ -18,7 +19,7 @@ bool cmTryCompileCommand::InitialPass(std::vector<std::string> const& argv,
if (this->Makefile->GetCMakeInstance()->GetWorkingMode() ==
cmake::FIND_PACKAGE_MODE) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"The TRY_COMPILE() command is not supported in --find-package mode.");
return false;
}
@@ -28,7 +29,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/cmTryCompileCommand.h b/Source/cmTryCompileCommand.h
index 483654822..e525e851f 100644
--- a/Source/cmTryCompileCommand.h
+++ b/Source/cmTryCompileCommand.h
@@ -3,20 +3,22 @@
#ifndef cmTryCompileCommand_h
#define cmTryCompileCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
+#include <cm/memory>
+
+#include "cmCommand.h"
#include "cmCoreTryCompile.h"
-class cmCommand;
class cmExecutionStatus;
/** \class cmTryCompileCommand
* \brief Specifies where to install some files
*
- * cmTryCompileCommand is used to test if soucre code can be compiled
+ * cmTryCompileCommand is used to test if source code can be compiled
*/
class cmTryCompileCommand : public cmCoreTryCompile
{
@@ -24,14 +26,17 @@ public:
/**
* This is a virtual constructor for the command.
*/
- cmCommand* Clone() CM_OVERRIDE { return new cmTryCompileCommand; }
+ std::unique_ptr<cmCommand> Clone() override
+ {
+ return cm::make_unique<cmTryCompileCommand>();
+ }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
+ cmExecutionStatus& status) override;
};
#endif
diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx
index 07e20e62f..0e8e986ab 100644
--- a/Source/cmTryRunCommand.cxx
+++ b/Source/cmTryRunCommand.cxx
@@ -2,13 +2,17 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTryRunCommand.h"
+#include <cstdio>
+
#include "cmsys/FStream.hxx"
-#include <stdio.h>
-#include <string.h>
+#include "cmDuration.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmRange.h"
#include "cmState.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
@@ -25,7 +29,7 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
if (this->Makefile->GetCMakeInstance()->GetWorkingMode() ==
cmake::FIND_PACKAGE_MODE) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR,
+ MessageType::FATAL_ERROR,
"The TRY_RUN() command is not supported in --find-package mode.");
return false;
}
@@ -33,11 +37,11 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
// build an arg list for TryCompile and extract the runArgs,
std::vector<std::string> tryCompile;
- this->CompileResultVariable = "";
- this->RunResultVariable = "";
- this->OutputVariable = "";
- this->RunOutputVariable = "";
- this->CompileOutputVariable = "";
+ this->CompileResultVariable.clear();
+ this->RunResultVariable.clear();
+ this->OutputVariable.clear();
+ this->RunOutputVariable.clear();
+ this->CompileOutputVariable.clear();
std::string runArgs;
unsigned int i;
@@ -45,7 +49,8 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
if (argv[i] == "ARGS") {
++i;
while (i < argv.size() && argv[i] != "COMPILE_DEFINITIONS" &&
- argv[i] != "CMAKE_FLAGS" && argv[i] != "LINK_LIBRARIES") {
+ argv[i] != "CMAKE_FLAGS" && argv[i] != "LINK_OPTIONS" &&
+ argv[i] != "LINK_LIBRARIES") {
runArgs += " ";
runArgs += argv[i];
++i;
@@ -99,11 +104,11 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
bool captureRunOutput = false;
if (!this->OutputVariable.empty()) {
captureRunOutput = true;
- tryCompile.push_back("OUTPUT_VARIABLE");
+ tryCompile.emplace_back("OUTPUT_VARIABLE");
tryCompile.push_back(this->OutputVariable);
}
if (!this->CompileOutputVariable.empty()) {
- tryCompile.push_back("OUTPUT_VARIABLE");
+ tryCompile.emplace_back("OUTPUT_VARIABLE");
tryCompile.push_back(this->CompileOutputVariable);
}
if (!this->RunOutputVariable.empty()) {
@@ -119,15 +124,14 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
// now try running the command if it compiled
if (!res) {
if (this->OutputFile.empty()) {
- cmSystemTools::Error(this->FindErrorMessage.c_str());
+ cmSystemTools::Error(this->FindErrorMessage);
} else {
// "run" it and capture the output
std::string runOutputContents;
if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING") &&
!this->Makefile->IsDefinitionSet("CMAKE_CROSSCOMPILING_EMULATOR")) {
- this->DoNotRunExecutable(runArgs, argv[3], captureRunOutput
- ? &runOutputContents
- : CM_NULLPTR);
+ this->DoNotRunExecutable(
+ runArgs, argv[3], captureRunOutput ? &runOutputContents : nullptr);
} else {
this->RunExecutable(runArgs, &runOutputContents);
}
@@ -135,7 +139,7 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
// now put the output into the variables
if (!this->RunOutputVariable.empty()) {
this->Makefile->AddDefinition(this->RunOutputVariable,
- runOutputContents.c_str());
+ runOutputContents);
}
if (!this->OutputVariable.empty()) {
@@ -144,17 +148,16 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
const char* compileOutput =
this->Makefile->GetDefinition(this->OutputVariable);
if (compileOutput) {
- runOutputContents = std::string(compileOutput) + runOutputContents;
+ runOutputContents = compileOutput + runOutputContents;
}
- this->Makefile->AddDefinition(this->OutputVariable,
- runOutputContents.c_str());
+ this->Makefile->AddDefinition(this->OutputVariable, runOutputContents);
}
}
}
// 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;
}
@@ -165,40 +168,37 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs,
int retVal = -1;
std::string finalCommand;
- const std::string emulator =
+ const std::string& emulator =
this->Makefile->GetSafeDefinition("CMAKE_CROSSCOMPILING_EMULATOR");
if (!emulator.empty()) {
- std::vector<std::string> emulatorWithArgs;
- cmSystemTools::ExpandListArgument(emulator, emulatorWithArgs);
+ std::vector<std::string> emulatorWithArgs = cmExpandedList(emulator);
finalCommand +=
- cmSystemTools::ConvertToRunCommandPath(emulatorWithArgs[0].c_str());
+ cmSystemTools::ConvertToRunCommandPath(emulatorWithArgs[0]);
finalCommand += " ";
- for (std::vector<std::string>::const_iterator ei =
- emulatorWithArgs.begin() + 1;
- ei != emulatorWithArgs.end(); ++ei) {
+ for (std::string const& arg : cmMakeRange(emulatorWithArgs).advance(1)) {
finalCommand += "\"";
- finalCommand += *ei;
+ finalCommand += arg;
finalCommand += "\"";
finalCommand += " ";
}
}
- finalCommand +=
- cmSystemTools::ConvertToRunCommandPath(this->OutputFile.c_str());
+ finalCommand += cmSystemTools::ConvertToRunCommandPath(this->OutputFile);
if (!runArgs.empty()) {
finalCommand += runArgs;
}
- int timeout = 0;
bool worked = cmSystemTools::RunSingleCommand(
- finalCommand.c_str(), out, out, &retVal, CM_NULLPTR,
- cmSystemTools::OUTPUT_NONE, timeout);
+ finalCommand, out, out, &retVal, nullptr, 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);
}
@@ -214,32 +214,29 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
// copy the executable out of the CMakeFiles/ directory, so it is not
// removed at the end of TRY_RUN and the user can run it manually
// on the target platform.
- std::string copyDest = this->Makefile->GetHomeOutputDirectory();
- copyDest += cmake::GetCMakeFilesDirectory();
- copyDest += "/";
- copyDest += cmSystemTools::GetFilenameWithoutExtension(this->OutputFile);
- copyDest += "-";
- copyDest += this->RunResultVariable;
- copyDest += cmSystemTools::GetFilenameExtension(this->OutputFile);
+ std::string copyDest =
+ cmStrCat(this->Makefile->GetHomeOutputDirectory(), "/CMakeFiles/",
+ cmSystemTools::GetFilenameWithoutExtension(this->OutputFile), '-',
+ this->RunResultVariable,
+ cmSystemTools::GetFilenameExtension(this->OutputFile));
cmSystemTools::CopyFileAlways(this->OutputFile, copyDest);
- std::string resultFileName = this->Makefile->GetHomeOutputDirectory();
- resultFileName += "/TryRunResults.cmake";
+ std::string resultFileName =
+ cmStrCat(this->Makefile->GetHomeOutputDirectory(), "/TryRunResults.cmake");
- std::string detailsString = "For details see ";
- detailsString += resultFileName;
+ std::string detailsString = cmStrCat("For details see ", resultFileName);
std::string internalRunOutputName =
this->RunResultVariable + "__TRYRUN_OUTPUT";
bool error = false;
- if (this->Makefile->GetDefinition(this->RunResultVariable) == CM_NULLPTR) {
+ if (!this->Makefile->GetDefinition(this->RunResultVariable)) {
// if the variables doesn't exist, create it with a helpful error text
// and mark it as advanced
- std::string comment;
- comment += "Run result of TRY_RUN(), indicates whether the executable "
- "would have been able to run on its target platform.\n";
- comment += detailsString;
+ std::string comment =
+ cmStrCat("Run result of TRY_RUN(), indicates whether the executable "
+ "would have been able to run on its target platform.\n",
+ detailsString);
this->Makefile->AddCacheDefinition(this->RunResultVariable,
"PLEASE_FILL_OUT-FAILED_TO_RUN",
comment.c_str(), cmStateEnums::STRING);
@@ -255,15 +252,14 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
}
// is the output from the executable used ?
- if (out != CM_NULLPTR) {
- if (this->Makefile->GetDefinition(internalRunOutputName) == CM_NULLPTR) {
+ if (out) {
+ if (!this->Makefile->GetDefinition(internalRunOutputName)) {
// if the variables doesn't exist, create it with a helpful error text
// and mark it as advanced
- std::string comment;
- comment +=
+ std::string comment = cmStrCat(
"Output of TRY_RUN(), contains the text, which the executable "
- "would have printed on stdout and stderr on its target platform.\n";
- comment += detailsString;
+ "would have printed on stdout and stderr on its target platform.\n",
+ detailsString);
this->Makefile->AddCacheDefinition(
internalRunOutputName, "PLEASE_FILL_OUT-NOTFOUND", comment.c_str(),
@@ -295,16 +291,16 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
/* clang-format on */
}
- std::string comment = "\n";
- comment += this->RunResultVariable;
- comment += "\n indicates whether the executable would have been able "
+ std::string comment =
+ cmStrCat('\n', this->RunResultVariable,
+ "\n indicates whether the executable would have been able "
"to run on its\n"
- " target platform. If so, set ";
- comment += this->RunResultVariable;
- comment += " to\n"
+ " target platform. If so, set ",
+ this->RunResultVariable,
+ " to\n"
" the exit code (in many cases 0 for success), otherwise "
- "enter \"FAILED_TO_RUN\".\n";
- if (out != CM_NULLPTR) {
+ "enter \"FAILED_TO_RUN\".\n");
+ if (out) {
comment += internalRunOutputName;
comment +=
"\n contains the text the executable "
@@ -335,7 +331,7 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
<< this->Makefile->GetDefinition(this->RunResultVariable)
<< "\"\n CACHE STRING \"Result from TRY_RUN\" FORCE)\n\n";
- if (out != CM_NULLPTR) {
+ if (out) {
file << "set( " << internalRunOutputName << " \n \""
<< this->Makefile->GetDefinition(internalRunOutputName)
<< "\"\n CACHE STRING \"Output from TRY_RUN\" FORCE)\n\n";
@@ -344,19 +340,20 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
}
firstTryRun = false;
- std::string errorMessage = "TRY_RUN() invoked in cross-compiling mode, "
- "please set the following cache variables "
- "appropriately:\n";
- errorMessage += " " + this->RunResultVariable + " (advanced)\n";
- if (out != CM_NULLPTR) {
+ std::string errorMessage =
+ cmStrCat("TRY_RUN() invoked in cross-compiling mode, "
+ "please set the following cache variables "
+ "appropriately:\n ",
+ this->RunResultVariable, " (advanced)\n");
+ if (out) {
errorMessage += " " + internalRunOutputName + " (advanced)\n";
}
errorMessage += detailsString;
- cmSystemTools::Error(errorMessage.c_str());
+ cmSystemTools::Error(errorMessage);
return;
}
- if (out != CM_NULLPTR) {
+ if (out) {
(*out) = this->Makefile->GetDefinition(internalRunOutputName);
}
}
diff --git a/Source/cmTryRunCommand.h b/Source/cmTryRunCommand.h
index c27b026ad..c53a69474 100644
--- a/Source/cmTryRunCommand.h
+++ b/Source/cmTryRunCommand.h
@@ -3,20 +3,22 @@
#ifndef cmTryRunCommand_h
#define cmTryRunCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
+#include <cm/memory>
+
+#include "cmCommand.h"
#include "cmCoreTryCompile.h"
-class cmCommand;
class cmExecutionStatus;
/** \class cmTryRunCommand
* \brief Specifies where to install some files
*
- * cmTryRunCommand is used to test if soucre code can be compiled
+ * cmTryRunCommand is used to test if source code can be compiled
*/
class cmTryRunCommand : public cmCoreTryCompile
{
@@ -24,14 +26,17 @@ public:
/**
* This is a virtual constructor for the command.
*/
- cmCommand* Clone() CM_OVERRIDE { return new cmTryRunCommand; }
+ std::unique_ptr<cmCommand> Clone() override
+ {
+ return cm::make_unique<cmTryRunCommand>();
+ }
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
*/
bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
+ cmExecutionStatus& status) override;
private:
void RunExecutable(const std::string& runArgs,
diff --git a/Source/cmUVHandlePtr.cxx b/Source/cmUVHandlePtr.cxx
new file mode 100644
index 000000000..23dabb770
--- /dev/null
+++ b/Source/cmUVHandlePtr.cxx
@@ -0,0 +1,267 @@
+/* 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 <cassert>
+#include <cstdlib>
+#include <mutex>
+
+#include "cm_uv.h"
+
+namespace cm {
+
+struct uv_loop_deleter
+{
+ void operator()(uv_loop_t* loop) const;
+};
+
+void uv_loop_deleter::operator()(uv_loop_t* loop) const
+{
+ uv_run(loop, UV_RUN_DEFAULT);
+ int result = uv_loop_close(loop);
+ (void)result;
+ assert(result >= 0);
+ free(loop);
+}
+
+int uv_loop_ptr::init(void* data)
+{
+ this->reset();
+
+ this->loop.reset(static_cast<uv_loop_t*>(calloc(1, sizeof(uv_loop_t))),
+ uv_loop_deleter());
+ this->loop->data = data;
+
+ return uv_loop_init(this->loop.get());
+}
+
+void uv_loop_ptr::reset()
+{
+ this->loop.reset();
+}
+
+uv_loop_ptr::operator uv_loop_t*()
+{
+ return this->loop.get();
+}
+
+uv_loop_t* uv_loop_ptr::operator->() const noexcept
+{
+ return this->loop.get();
+}
+
+uv_loop_t* uv_loop_ptr::get() const
+{
+ return this->loop.get();
+}
+
+template <typename T>
+static void handle_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, [](uv_handle_t* h) { free(h); });
+ }
+ }
+}
+
+/**
+ * Encapsulates delete logic for a given handle type T
+ */
+template <typename T>
+struct uv_handle_deleter
+{
+ void operator()(T* type_handle) const { handle_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();
+}
+
+#ifndef CMAKE_BOOTSTRAP
+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);
+ handle_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);
+ 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());
+}
+
+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);
+}
+
+#ifndef CMAKE_BOOTSTRAP
+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)
+
+UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(process)
+
+UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(timer)
+
+#ifndef CMAKE_BOOTSTRAP
+UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(async)
+
+UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(tty)
+#endif
+}
diff --git a/Source/cmUVHandlePtr.h b/Source/cmUVHandlePtr.h
new file mode 100644
index 000000000..3083b60c8
--- /dev/null
+++ b/Source/cmUVHandlePtr.h
@@ -0,0 +1,271 @@
+/* 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 <cstddef>
+#include <cstdint>
+#include <memory>
+#include <type_traits>
+
+#include "cm_uv.h"
+
+#if defined(__SUNPRO_CC)
+
+# include <utility>
+
+# define CM_INHERIT_CTOR(Class, Base, Tpl) \
+ template <typename... Args> \
+ Class(Args&&... args) \
+ : Base Tpl(std::forward<Args>(args)...) \
+ { \
+ }
+
+#else
+
+# define CM_INHERIT_CTOR(Class, Base, Tpl) using Base Tpl ::Base;
+
+#endif
+
+namespace cm {
+
+/***
+ * RAII class to simplify and ensure the safe usage of uv_loop_t. This includes
+ * making sure resources are properly freed.
+ */
+class uv_loop_ptr
+{
+protected:
+ std::shared_ptr<uv_loop_t> loop;
+
+public:
+ uv_loop_ptr(uv_loop_ptr const&) = delete;
+ uv_loop_ptr& operator=(uv_loop_ptr const&) = delete;
+ uv_loop_ptr(uv_loop_ptr&&) noexcept;
+ uv_loop_ptr& operator=(uv_loop_ptr&&) noexcept;
+
+ // Dtor and ctor need to be inline defined like this for default ctors and
+ // dtors to work. Some compilers do not like '= default' here.
+ uv_loop_ptr() {} // NOLINT(modernize-use-equals-default)
+ uv_loop_ptr(std::nullptr_t) {}
+ ~uv_loop_ptr() { this->reset(); }
+
+ int init(void* data = nullptr);
+
+ /**
+ * Properly close the handle if needed and sets the inner handle to nullptr
+ */
+ void reset();
+
+ /**
+ * Allow less verbose calling of uv_loop_* functions
+ * @return reinterpreted handle
+ */
+ operator uv_loop_t*();
+
+ uv_loop_t* get() const;
+ uv_loop_t* operator->() const noexcept;
+};
+
+/***
+ * RAII class to simplify and ensure 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:
+ uv_handle_ptr_base_(uv_handle_ptr_base_ const&) = delete;
+ uv_handle_ptr_base_& operator=(uv_handle_ptr_base_ const&) = delete;
+ 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. Some compilers do not like '= default' here.
+ uv_handle_ptr_base_() {} // NOLINT(modernize-use-equals-default)
+ 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_INHERIT_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_INHERIT_CTOR(uv_handle_ptr_, uv_handle_ptr_base_, <uv_handle_t>);
+};
+
+class uv_async_ptr : public uv_handle_ptr_<uv_async_t>
+{
+public:
+ CM_INHERIT_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_INHERIT_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_INHERIT_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_INHERIT_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_INHERIT_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_INHERIT_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);
+};
+
+using uv_stream_ptr = uv_handle_ptr_<uv_stream_t>;
+using uv_handle_ptr = uv_handle_ptr_<uv_handle_t>;
+
+#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/cmUVProcessChain.cxx b/Source/cmUVProcessChain.cxx
new file mode 100644
index 000000000..543c3308a
--- /dev/null
+++ b/Source/cmUVProcessChain.cxx
@@ -0,0 +1,396 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmUVProcessChain.h"
+
+#include <cassert>
+#include <istream> // IWYU pragma: keep
+#include <iterator>
+#include <utility>
+
+#include <cm/memory>
+
+#include "cm_uv.h"
+
+#include "cmGetPipes.h"
+#include "cmUVHandlePtr.h"
+#include "cmUVStreambuf.h"
+
+struct cmUVProcessChain::InternalData
+{
+ struct BasicStreamData
+ {
+ cmUVStreambuf Streambuf;
+ cm::uv_pipe_ptr BuiltinStream;
+ uv_stdio_container_t Stdio;
+ };
+
+ template <typename IOStream>
+ struct StreamData : public BasicStreamData
+ {
+ StreamData()
+ : BuiltinIOStream(&this->Streambuf)
+ {
+ }
+
+ IOStream BuiltinIOStream;
+
+ IOStream* GetBuiltinStream()
+ {
+ if (this->BuiltinStream.get()) {
+ return &this->BuiltinIOStream;
+ }
+ return nullptr;
+ }
+ };
+
+ struct ProcessData
+ {
+ cmUVProcessChain::InternalData* Data;
+ cm::uv_process_ptr Process;
+ cm::uv_pipe_ptr OutputPipe;
+ bool Finished = false;
+ Status ProcessStatus;
+ };
+
+ const cmUVProcessChainBuilder* Builder = nullptr;
+
+ bool Valid = false;
+
+ cm::uv_loop_ptr Loop;
+
+ StreamData<std::istream> OutputStreamData;
+ StreamData<std::istream> ErrorStreamData;
+
+ unsigned int ProcessesCompleted = 0;
+ std::vector<std::unique_ptr<ProcessData>> Processes;
+
+ bool Prepare(const cmUVProcessChainBuilder* builder);
+ bool AddCommand(const cmUVProcessChainBuilder::ProcessConfiguration& config,
+ bool first, bool last);
+ bool Finish();
+
+ static const Status* GetStatus(const ProcessData& data);
+};
+
+cmUVProcessChainBuilder::cmUVProcessChainBuilder()
+{
+ this->SetNoStream(Stream_INPUT)
+ .SetNoStream(Stream_OUTPUT)
+ .SetNoStream(Stream_ERROR);
+}
+
+cmUVProcessChainBuilder& cmUVProcessChainBuilder::AddCommand(
+ const std::vector<std::string>& arguments)
+{
+ if (!arguments.empty()) {
+ this->Processes.emplace_back();
+ this->Processes.back().Arguments = arguments;
+ }
+ return *this;
+}
+
+cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetNoStream(Stream stdio)
+{
+ switch (stdio) {
+ case Stream_INPUT:
+ case Stream_OUTPUT:
+ case Stream_ERROR: {
+ auto& streamData = this->Stdio[stdio];
+ streamData.Type = None;
+ break;
+ }
+ }
+ return *this;
+}
+
+cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetBuiltinStream(
+ Stream stdio)
+{
+ switch (stdio) {
+ case Stream_INPUT:
+ // FIXME
+ break;
+
+ case Stream_OUTPUT:
+ case Stream_ERROR: {
+ auto& streamData = this->Stdio[stdio];
+ streamData.Type = Builtin;
+ break;
+ }
+ }
+ return *this;
+}
+
+cmUVProcessChainBuilder& cmUVProcessChainBuilder::SetExternalStream(
+ Stream stdio, int fd)
+{
+ switch (stdio) {
+ case Stream_INPUT:
+ // FIXME
+ break;
+
+ case Stream_OUTPUT:
+ case Stream_ERROR: {
+ auto& streamData = this->Stdio[stdio];
+ streamData.Type = External;
+ streamData.FileDescriptor = fd;
+ break;
+ }
+ }
+ return *this;
+}
+
+cmUVProcessChain cmUVProcessChainBuilder::Start() const
+{
+ cmUVProcessChain chain;
+
+ if (!chain.Data->Prepare(this)) {
+ return chain;
+ }
+
+ for (auto it = this->Processes.begin(); it != this->Processes.end(); ++it) {
+ if (!chain.Data->AddCommand(*it, it == this->Processes.begin(),
+ it == std::prev(this->Processes.end()))) {
+ return chain;
+ }
+ }
+
+ chain.Data->Finish();
+
+ return chain;
+}
+
+const cmUVProcessChain::Status* cmUVProcessChain::InternalData::GetStatus(
+ const cmUVProcessChain::InternalData::ProcessData& data)
+{
+ if (data.Finished) {
+ return &data.ProcessStatus;
+ }
+ return nullptr;
+}
+
+bool cmUVProcessChain::InternalData::Prepare(
+ const cmUVProcessChainBuilder* builder)
+{
+ this->Builder = builder;
+
+ auto const& output =
+ this->Builder->Stdio[cmUVProcessChainBuilder::Stream_OUTPUT];
+ auto& outputData = this->OutputStreamData;
+ switch (output.Type) {
+ case cmUVProcessChainBuilder::None:
+ outputData.Stdio.flags = UV_IGNORE;
+ break;
+
+ case cmUVProcessChainBuilder::Builtin:
+ outputData.BuiltinStream.init(*this->Loop, 0);
+ outputData.Stdio.flags =
+ static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
+ outputData.Stdio.data.stream = outputData.BuiltinStream;
+ break;
+
+ case cmUVProcessChainBuilder::External:
+ outputData.Stdio.flags = UV_INHERIT_FD;
+ outputData.Stdio.data.fd = output.FileDescriptor;
+ break;
+ }
+
+ auto const& error =
+ this->Builder->Stdio[cmUVProcessChainBuilder::Stream_ERROR];
+ auto& errorData = this->ErrorStreamData;
+ switch (error.Type) {
+ case cmUVProcessChainBuilder::None:
+ errorData.Stdio.flags = UV_IGNORE;
+ break;
+
+ case cmUVProcessChainBuilder::Builtin: {
+ int pipeFd[2];
+ if (cmGetPipes(pipeFd) < 0) {
+ return false;
+ }
+
+ errorData.BuiltinStream.init(*this->Loop, 0);
+ if (uv_pipe_open(errorData.BuiltinStream, pipeFd[0]) < 0) {
+ return false;
+ }
+ errorData.Stdio.flags = UV_INHERIT_FD;
+ errorData.Stdio.data.fd = pipeFd[1];
+ break;
+ }
+
+ case cmUVProcessChainBuilder::External:
+ errorData.Stdio.flags = UV_INHERIT_FD;
+ errorData.Stdio.data.fd = error.FileDescriptor;
+ break;
+ }
+
+ return true;
+}
+
+bool cmUVProcessChain::InternalData::AddCommand(
+ const cmUVProcessChainBuilder::ProcessConfiguration& config, bool first,
+ bool last)
+{
+ this->Processes.emplace_back(cm::make_unique<ProcessData>());
+ auto& process = *this->Processes.back();
+ process.Data = this;
+
+ auto options = uv_process_options_t();
+
+ // Bounds were checked at add time, first element is guaranteed to exist
+ options.file = config.Arguments[0].c_str();
+
+ std::vector<const char*> arguments;
+ for (auto const& arg : config.Arguments) {
+ arguments.push_back(arg.c_str());
+ }
+ arguments.push_back(nullptr);
+ options.args = const_cast<char**>(arguments.data());
+ options.flags = UV_PROCESS_WINDOWS_HIDE;
+
+ std::array<uv_stdio_container_t, 3> stdio;
+ stdio[0] = uv_stdio_container_t();
+ if (first) {
+ stdio[0].flags = UV_IGNORE;
+ } else {
+ assert(this->Processes.size() >= 2);
+ auto& prev = *this->Processes[this->Processes.size() - 2];
+ stdio[0].flags = UV_INHERIT_STREAM;
+ stdio[0].data.stream = prev.OutputPipe;
+ }
+ if (last) {
+ stdio[1] = this->OutputStreamData.Stdio;
+ } else {
+ if (process.OutputPipe.init(*this->Loop, 0) < 0) {
+ return false;
+ }
+ stdio[1] = uv_stdio_container_t();
+ stdio[1].flags =
+ static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
+ stdio[1].data.stream = process.OutputPipe;
+ }
+ stdio[2] = this->ErrorStreamData.Stdio;
+
+ options.stdio = stdio.data();
+ options.stdio_count = 3;
+ options.exit_cb = [](uv_process_t* handle, int64_t exitStatus,
+ int termSignal) {
+ auto* processData = static_cast<ProcessData*>(handle->data);
+ processData->Finished = true;
+ processData->ProcessStatus.ExitStatus = exitStatus;
+ processData->ProcessStatus.TermSignal = termSignal;
+ processData->Data->ProcessesCompleted++;
+ };
+
+ return process.Process.spawn(*this->Loop, options, &process) >= 0;
+}
+
+bool cmUVProcessChain::InternalData::Finish()
+{
+ if (this->Builder->Stdio[cmUVProcessChainBuilder::Stream_OUTPUT].Type ==
+ cmUVProcessChainBuilder::Builtin) {
+ this->OutputStreamData.Streambuf.open(
+ this->OutputStreamData.BuiltinStream);
+ }
+
+ if (this->Builder->Stdio[cmUVProcessChainBuilder::Stream_ERROR].Type ==
+ cmUVProcessChainBuilder::Builtin) {
+ cm::uv_pipe_ptr tmpPipe;
+ if (tmpPipe.init(*this->Loop, 0) < 0) {
+ return false;
+ }
+ if (uv_pipe_open(tmpPipe, this->ErrorStreamData.Stdio.data.fd) < 0) {
+ return false;
+ }
+ tmpPipe.reset();
+
+ this->ErrorStreamData.Streambuf.open(this->ErrorStreamData.BuiltinStream);
+ }
+
+ this->Valid = true;
+ return true;
+}
+
+cmUVProcessChain::cmUVProcessChain()
+ : Data(cm::make_unique<InternalData>())
+{
+ this->Data->Loop.init();
+}
+
+cmUVProcessChain::cmUVProcessChain(cmUVProcessChain&& other) noexcept
+ : Data(std::move(other.Data))
+{
+}
+
+cmUVProcessChain::~cmUVProcessChain() = default;
+
+cmUVProcessChain& cmUVProcessChain::operator=(
+ cmUVProcessChain&& other) noexcept
+{
+ this->Data = std::move(other.Data);
+ return *this;
+}
+
+uv_loop_t& cmUVProcessChain::GetLoop()
+{
+ return *this->Data->Loop;
+}
+
+std::istream* cmUVProcessChain::OutputStream()
+{
+ return this->Data->OutputStreamData.GetBuiltinStream();
+}
+
+std::istream* cmUVProcessChain::ErrorStream()
+{
+ return this->Data->ErrorStreamData.GetBuiltinStream();
+}
+
+bool cmUVProcessChain::Valid() const
+{
+ return this->Data->Valid;
+}
+
+bool cmUVProcessChain::Wait(int64_t milliseconds)
+{
+ bool timeout = false;
+ cm::uv_timer_ptr timer;
+
+ if (milliseconds >= 0) {
+ timer.init(*this->Data->Loop, &timeout);
+ timer.start(
+ [](uv_timer_t* handle) {
+ auto* timeoutPtr = static_cast<bool*>(handle->data);
+ *timeoutPtr = true;
+ },
+ milliseconds, 0);
+ }
+
+ while (!timeout &&
+ this->Data->ProcessesCompleted < this->Data->Processes.size()) {
+ uv_run(this->Data->Loop, UV_RUN_ONCE);
+ }
+
+ return !timeout;
+}
+
+std::vector<const cmUVProcessChain::Status*> cmUVProcessChain::GetStatus()
+ const
+{
+ std::vector<const cmUVProcessChain::Status*> statuses(
+ this->Data->Processes.size(), nullptr);
+ for (std::size_t i = 0; i < statuses.size(); i++) {
+ statuses[i] = this->GetStatus(i);
+ }
+ return statuses;
+}
+
+const cmUVProcessChain::Status* cmUVProcessChain::GetStatus(
+ std::size_t index) const
+{
+ auto const& process = *this->Data->Processes[index];
+ if (process.Finished) {
+ return &process.ProcessStatus;
+ }
+ return nullptr;
+}
diff --git a/Source/cmUVProcessChain.h b/Source/cmUVProcessChain.h
new file mode 100644
index 000000000..05a7cc82c
--- /dev/null
+++ b/Source/cmUVProcessChain.h
@@ -0,0 +1,100 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmUVProcessChain_h
+#define cmUVProcessChain_h
+
+#include <array>
+#include <cstddef>
+#include <cstdint>
+#include <iosfwd>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "cm_uv.h"
+
+class cmUVProcessChain;
+
+class cmUVProcessChainBuilder
+{
+public:
+ enum Stream
+ {
+ Stream_INPUT = 0,
+ Stream_OUTPUT = 1,
+ Stream_ERROR = 2,
+ };
+
+ cmUVProcessChainBuilder();
+
+ cmUVProcessChainBuilder& AddCommand(
+ const std::vector<std::string>& arguments);
+ cmUVProcessChainBuilder& SetNoStream(Stream stdio);
+ cmUVProcessChainBuilder& SetBuiltinStream(Stream stdio);
+ cmUVProcessChainBuilder& SetExternalStream(Stream stdio, int fd);
+
+ cmUVProcessChain Start() const;
+
+private:
+ enum StdioType
+ {
+ None,
+ Builtin,
+ External,
+ };
+
+ friend class cmUVProcessChain;
+
+ struct StdioConfiguration
+ {
+ StdioType Type;
+ int FileDescriptor;
+ };
+
+ struct ProcessConfiguration
+ {
+ std::vector<std::string> Arguments;
+ };
+
+ std::array<StdioConfiguration, 3> Stdio;
+ std::vector<ProcessConfiguration> Processes;
+};
+
+class cmUVProcessChain
+{
+public:
+ struct Status
+ {
+ int64_t ExitStatus;
+ int TermSignal;
+ };
+
+ cmUVProcessChain(const cmUVProcessChain& other) = delete;
+ cmUVProcessChain(cmUVProcessChain&& other) noexcept;
+
+ ~cmUVProcessChain();
+
+ cmUVProcessChain& operator=(const cmUVProcessChain& other) = delete;
+ cmUVProcessChain& operator=(cmUVProcessChain&& other) noexcept;
+
+ uv_loop_t& GetLoop();
+
+ // FIXME: Add stdin support
+ std::istream* OutputStream();
+ std::istream* ErrorStream();
+
+ bool Valid() const;
+ bool Wait(int64_t milliseconds = -1);
+ std::vector<const Status*> GetStatus() const;
+ const Status* GetStatus(std::size_t index) const;
+
+private:
+ friend class cmUVProcessChainBuilder;
+
+ cmUVProcessChain();
+
+ struct InternalData;
+ std::unique_ptr<InternalData> Data;
+};
+
+#endif
diff --git a/Source/cmUVSignalHackRAII.h b/Source/cmUVSignalHackRAII.h
new file mode 100644
index 000000000..63599db82
--- /dev/null
+++ b/Source/cmUVSignalHackRAII.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. */
+#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/cmUVStreambuf.h b/Source/cmUVStreambuf.h
new file mode 100644
index 000000000..1c8a7717c
--- /dev/null
+++ b/Source/cmUVStreambuf.h
@@ -0,0 +1,219 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmUVStreambuf_h
+#define cmUVStreambuf_h
+
+#include <algorithm>
+#include <cstring>
+#include <streambuf>
+#include <vector>
+
+#include "cm_uv.h"
+
+#include "cmUVHandlePtr.h"
+
+/*
+ * This file is based on example code from:
+ *
+ * http://www.voidcn.com/article/p-vjnlygmc-gy.html
+ *
+ * The example code was distributed under the following license:
+ *
+ * Copyright 2007 Edd Dawson.
+ * Distributed under the Boost Software License, Version 1.0.
+ *
+ * Boost Software License - Version 1.0 - August 17th, 2003
+ *
+ * Permission is hereby granted, free of charge, to any person or organization
+ * obtaining a copy of the software and accompanying documentation covered by
+ * this license (the "Software") to use, reproduce, display, distribute,
+ * execute, and transmit the Software, and to prepare derivative works of the
+ * Software, and to permit third-parties to whom the Software is furnished to
+ * do so, all subject to the following:
+ *
+ * The copyright notices in the Software and this entire statement, including
+ * the above license grant, this restriction and the following disclaimer,
+ * must be included in all copies of the Software, in whole or in part, and
+ * all derivative works of the Software, unless such copies or derivative
+ * works are solely in the form of machine-executable object code generated by
+ * a source language processor.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+template <typename CharT, typename Traits = std::char_traits<CharT>>
+class cmBasicUVStreambuf : public std::basic_streambuf<CharT, Traits>
+{
+public:
+ cmBasicUVStreambuf(std::size_t bufSize = 256, std::size_t putBack = 8);
+ ~cmBasicUVStreambuf() override;
+
+ bool is_open() const;
+
+ cmBasicUVStreambuf* open(uv_stream_t* stream);
+
+ cmBasicUVStreambuf* close();
+
+protected:
+ typename cmBasicUVStreambuf<CharT, Traits>::int_type underflow() override;
+ std::streamsize showmanyc() override;
+
+ // FIXME: Add write support
+
+private:
+ uv_stream_t* Stream = nullptr;
+ void* OldStreamData = nullptr;
+ const std::size_t PutBack = 0;
+ std::vector<CharT> InputBuffer;
+ bool EndOfFile = false;
+
+ void StreamReadStartStop();
+
+ void StreamRead(ssize_t nread);
+ void HandleAlloc(uv_buf_t* buf);
+};
+
+template <typename CharT, typename Traits>
+cmBasicUVStreambuf<CharT, Traits>::cmBasicUVStreambuf(std::size_t bufSize,
+ std::size_t putBack)
+ : PutBack(std::max<std::size_t>(putBack, 1))
+ , InputBuffer(std::max<std::size_t>(this->PutBack, bufSize) + this->PutBack)
+{
+ this->close();
+}
+
+template <typename CharT, typename Traits>
+cmBasicUVStreambuf<CharT, Traits>::~cmBasicUVStreambuf()
+{
+ this->close();
+}
+
+template <typename CharT, typename Traits>
+bool cmBasicUVStreambuf<CharT, Traits>::is_open() const
+{
+ return this->Stream != nullptr;
+}
+
+template <typename CharT, typename Traits>
+cmBasicUVStreambuf<CharT, Traits>* cmBasicUVStreambuf<CharT, Traits>::open(
+ uv_stream_t* stream)
+{
+ this->close();
+ this->Stream = stream;
+ this->EndOfFile = false;
+ if (this->Stream) {
+ this->OldStreamData = this->Stream->data;
+ this->Stream->data = this;
+ }
+ this->StreamReadStartStop();
+ return this;
+}
+
+template <typename CharT, typename Traits>
+cmBasicUVStreambuf<CharT, Traits>* cmBasicUVStreambuf<CharT, Traits>::close()
+{
+ if (this->Stream) {
+ uv_read_stop(this->Stream);
+ this->Stream->data = this->OldStreamData;
+ }
+ this->Stream = nullptr;
+ CharT* readEnd = this->InputBuffer.data() + this->InputBuffer.size();
+ this->setg(readEnd, readEnd, readEnd);
+ return this;
+}
+
+template <typename CharT, typename Traits>
+typename cmBasicUVStreambuf<CharT, Traits>::int_type
+cmBasicUVStreambuf<CharT, Traits>::underflow()
+{
+ if (!this->is_open()) {
+ return Traits::eof();
+ }
+
+ if (this->gptr() < this->egptr()) {
+ return Traits::to_int_type(*this->gptr());
+ }
+
+ this->StreamReadStartStop();
+ while (this->in_avail() == 0) {
+ uv_run(this->Stream->loop, UV_RUN_ONCE);
+ }
+ if (this->in_avail() == -1) {
+ return Traits::eof();
+ }
+ return Traits::to_int_type(*this->gptr());
+}
+
+template <typename CharT, typename Traits>
+std::streamsize cmBasicUVStreambuf<CharT, Traits>::showmanyc()
+{
+ if (!this->is_open() || this->EndOfFile) {
+ return -1;
+ }
+ return 0;
+}
+
+template <typename CharT, typename Traits>
+void cmBasicUVStreambuf<CharT, Traits>::StreamReadStartStop()
+{
+ if (this->Stream) {
+ uv_read_stop(this->Stream);
+ if (this->gptr() >= this->egptr()) {
+ uv_read_start(
+ this->Stream,
+ [](uv_handle_t* handle, size_t /* unused */, uv_buf_t* buf) {
+ auto streambuf =
+ static_cast<cmBasicUVStreambuf<CharT, Traits>*>(handle->data);
+ streambuf->HandleAlloc(buf);
+ },
+ [](uv_stream_t* stream2, ssize_t nread, const uv_buf_t* /* unused */) {
+ auto streambuf =
+ static_cast<cmBasicUVStreambuf<CharT, Traits>*>(stream2->data);
+ streambuf->StreamRead(nread);
+ });
+ }
+ }
+}
+
+template <typename CharT, typename Traits>
+void cmBasicUVStreambuf<CharT, Traits>::HandleAlloc(uv_buf_t* buf)
+{
+ auto size = this->egptr() - this->gptr();
+ std::memmove(this->InputBuffer.data(), this->gptr(),
+ this->egptr() - this->gptr());
+ this->setg(this->InputBuffer.data(), this->InputBuffer.data(),
+ this->InputBuffer.data() + size);
+ buf->base = this->egptr();
+#ifdef _WIN32
+# define BUF_LEN_TYPE ULONG
+#else
+# define BUF_LEN_TYPE size_t
+#endif
+ buf->len = BUF_LEN_TYPE(
+ (this->InputBuffer.data() + this->InputBuffer.size() - this->egptr()) *
+ sizeof(CharT));
+#undef BUF_LEN_TYPE
+}
+
+template <typename CharT, typename Traits>
+void cmBasicUVStreambuf<CharT, Traits>::StreamRead(ssize_t nread)
+{
+ if (nread > 0) {
+ this->setg(this->eback(), this->gptr(),
+ this->egptr() + nread / sizeof(CharT));
+ uv_read_stop(this->Stream);
+ } else if (nread < 0 /*|| nread == UV_EOF*/) {
+ this->EndOfFile = true;
+ uv_read_stop(this->Stream);
+ }
+}
+
+using cmUVStreambuf = cmBasicUVStreambuf<char>;
+
+#endif
diff --git a/Source/cmUnexpectedCommand.cxx b/Source/cmUnexpectedCommand.cxx
deleted file mode 100644
index a8de9e689..000000000
--- a/Source/cmUnexpectedCommand.cxx
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmUnexpectedCommand.h"
-
-#include <stdlib.h>
-
-#include "cmMakefile.h"
-
-class cmExecutionStatus;
-
-bool cmUnexpectedCommand::InitialPass(std::vector<std::string> const&,
- cmExecutionStatus&)
-{
- const char* versionValue =
- this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
- if (this->Name == "endif" && (!versionValue || atof(versionValue) <= 1.4)) {
- return true;
- }
-
- this->SetError(this->Error);
- return false;
-}
diff --git a/Source/cmUnexpectedCommand.h b/Source/cmUnexpectedCommand.h
deleted file mode 100644
index 995d8a5d6..000000000
--- a/Source/cmUnexpectedCommand.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmUnexpectedCommand_h
-#define cmUnexpectedCommand_h
-
-#include "cmConfigure.h"
-
-#include <string>
-#include <vector>
-
-#include "cmCommand.h"
-
-class cmExecutionStatus;
-
-class cmUnexpectedCommand : public cmCommand
-{
-public:
- cmUnexpectedCommand(std::string const& name, const char* error)
- : Name(name)
- , Error(error)
- {
- }
-
- cmCommand* Clone() CM_OVERRIDE
- {
- return new cmUnexpectedCommand(this->Name, this->Error);
- }
-
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-private:
- std::string Name;
- const char* Error;
-};
-
-#endif
diff --git a/Source/cmUnsetCommand.cxx b/Source/cmUnsetCommand.cxx
index 31525ba4a..3ba95e99f 100644
--- a/Source/cmUnsetCommand.cxx
+++ b/Source/cmUnsetCommand.cxx
@@ -2,54 +2,48 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmUnsetCommand.h"
-#include <string.h>
-
-#include "cmAlgorithms.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
-
// cmUnsetCommand
-bool cmUnsetCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmUnsetCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty() || args.size() > 2) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
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);
+#ifndef CMAKE_BOOTSTRAP
+ cmSystemTools::UnsetEnv(envVarName.c_str());
#endif
- delete[] envVarName;
return true;
}
// unset(VAR)
if (args.size() == 1) {
- this->Makefile->RemoveDefinition(variable);
+ status.GetMakefile().RemoveDefinition(variable);
return true;
}
// unset(VAR CACHE)
if ((args.size() == 2) && (args[1] == "CACHE")) {
- this->Makefile->RemoveCacheDefinition(variable);
+ status.GetMakefile().RemoveCacheDefinition(variable);
return true;
}
// unset(VAR PARENT_SCOPE)
if ((args.size() == 2) && (args[1] == "PARENT_SCOPE")) {
- this->Makefile->RaiseScope(variable, CM_NULLPTR);
+ status.GetMakefile().RaiseScope(variable, nullptr);
return true;
}
// ERROR: second argument isn't CACHE or PARENT_SCOPE
- this->SetError("called with an invalid second argument");
+ status.SetError("called with an invalid second argument");
return false;
}
diff --git a/Source/cmUnsetCommand.h b/Source/cmUnsetCommand.h
index 2a1f3f0a6..be4c166e8 100644
--- a/Source/cmUnsetCommand.h
+++ b/Source/cmUnsetCommand.h
@@ -3,34 +3,19 @@
#ifndef cmUnsetCommand_h
#define cmUnsetCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmUnsetCommand
+/**
* \brief Unset a CMAKE variable
*
* cmUnsetCommand unsets or removes a variable.
*/
-class cmUnsetCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmUnsetCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmUnsetCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx
index 07095b137..1fd386bda 100644
--- a/Source/cmUseMangledMesaCommand.cxx
+++ b/Source/cmUseMangledMesaCommand.cxx
@@ -5,70 +5,67 @@
#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"
+#include "cmExecutionStatus.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
+namespace {
+void CopyAndFullPathMesaHeader(const std::string& source,
+ const std::string& outdir);
+}
-bool cmUseMangledMesaCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmUseMangledMesaCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
// 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");
+ status.SetError("called with incorrect number of arguments");
return false;
}
- const char* inputDir = args[0].c_str();
- std::string glh = inputDir;
- glh += "/";
- glh += "gl.h";
- if (!cmSystemTools::FileExists(glh.c_str())) {
- std::string e = "Bad path to Mesa, could not find: ";
- e += glh;
- e += " ";
- this->SetError(e);
+ const std::string& inputDir = args[0];
+ std::string glh = cmStrCat(inputDir, "/gl.h");
+ if (!cmSystemTools::FileExists(glh)) {
+ std::string e = cmStrCat("Bad path to Mesa, could not find: ", glh, ' ');
+ status.SetError(e);
return false;
}
- const char* destDir = args[1].c_str();
+ const std::string& destDir = args[1];
std::vector<std::string> files;
cmSystemTools::Glob(inputDir, "\\.h$", files);
if (files.empty()) {
- cmSystemTools::Error("Could not open Mesa Directory ", inputDir);
+ cmSystemTools::Error("Could not open Mesa Directory " + inputDir);
return false;
}
cmSystemTools::MakeDirectory(destDir);
- for (std::vector<std::string>::iterator i = files.begin(); i != files.end();
- ++i) {
- std::string path = inputDir;
- path += "/";
- path += *i;
- this->CopyAndFullPathMesaHeader(path.c_str(), destDir);
+ for (std::string const& f : files) {
+ std::string path = cmStrCat(inputDir, '/', f);
+ CopyAndFullPathMesaHeader(path, destDir);
}
return true;
}
-void cmUseMangledMesaCommand::CopyAndFullPathMesaHeader(const char* source,
- const char* outdir)
+namespace {
+void CopyAndFullPathMesaHeader(const std::string& source,
+ const std::string& outdir)
{
- std::string dir, file;
+ std::string dir;
+ std::string file;
cmSystemTools::SplitProgramPath(source, dir, file);
- std::string outFile = outdir;
- outFile += "/";
- outFile += file;
- std::string tempOutputFile = outFile;
- tempOutputFile += ".tmp";
+ std::string outFile = cmStrCat(outdir, '/', file);
+ std::string tempOutputFile = cmStrCat(outFile, ".tmp");
cmsys::ofstream fout(tempOutputFile.c_str());
if (!fout) {
- cmSystemTools::Error("Could not open file for write in copy operation: ",
- tempOutputFile.c_str(), outdir);
+ cmSystemTools::Error("Could not open file for write in copy operation: " +
+ tempOutputFile + outdir);
cmSystemTools::ReportLastSystemError("");
return;
}
- cmsys::ifstream fin(source);
+ cmsys::ifstream fin(source.c_str());
if (!fin) {
- cmSystemTools::Error("Could not open file for read in copy operation",
+ cmSystemTools::Error("Could not open file for read in copy operation" +
source);
return;
}
@@ -79,16 +76,16 @@ void cmUseMangledMesaCommand::CopyAndFullPathMesaHeader(const char* source,
cmsys::RegularExpression includeLine(
"^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)[\">]");
// regular expression for gl/ or GL/ in a file (match(1) of above)
- cmsys::RegularExpression glDirLine("(gl|GL)(/|\\\\)([^<\"]+)");
+ cmsys::RegularExpression glDirLine(R"((gl|GL)(/|\\)([^<"]+))");
// regular expression for gl GL or xmesa in a file (match(1) of above)
cmsys::RegularExpression glLine("(gl|GL|xmesa)");
while (cmSystemTools::GetLineFromStream(fin, inLine)) {
- if (includeLine.find(inLine.c_str())) {
+ if (includeLine.find(inLine)) {
std::string includeFile = includeLine.match(1);
- if (glDirLine.find(includeFile.c_str())) {
+ if (glDirLine.find(includeFile)) {
std::string gfile = glDirLine.match(3);
fout << "#include \"" << outdir << "/" << gfile << "\"\n";
- } else if (glLine.find(includeFile.c_str())) {
+ } else if (glLine.find(includeFile)) {
fout << "#include \"" << outdir << "/" << includeLine.match(1)
<< "\"\n";
} else {
@@ -101,6 +98,6 @@ void cmUseMangledMesaCommand::CopyAndFullPathMesaHeader(const char* source,
// close the files before attempting to copy
fin.close();
fout.close();
- cmSystemTools::CopyFileIfDifferent(tempOutputFile.c_str(), outFile.c_str());
- cmSystemTools::RemoveFile(tempOutputFile);
+ cmSystemTools::MoveFileIfDifferent(tempOutputFile, outFile);
+}
}
diff --git a/Source/cmUseMangledMesaCommand.h b/Source/cmUseMangledMesaCommand.h
index 511882989..215e4a3cc 100644
--- a/Source/cmUseMangledMesaCommand.h
+++ b/Source/cmUseMangledMesaCommand.h
@@ -3,24 +3,14 @@
#ifndef cmUseMangledMesaCommand_h
#define cmUseMangledMesaCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmUseMangledMesaCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE { return new cmUseMangledMesaCommand; }
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
-protected:
- void CopyAndFullPathMesaHeader(const char* source, const char* outdir);
-};
+bool cmUseMangledMesaCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx
index eabd7ef31..a43165cce 100644
--- a/Source/cmUtilitySourceCommand.cxx
+++ b/Source/cmUtilitySourceCommand.cxx
@@ -2,53 +2,53 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmUtilitySourceCommand.h"
-#include <string.h>
+#include <cstring>
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
-
// cmUtilitySourceCommand
-bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmUtilitySourceCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 3) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
- std::vector<std::string>::const_iterator arg = args.begin();
+ auto arg = args.begin();
// The first argument is the cache entry name.
std::string const& cacheEntry = *arg++;
- const char* cacheValue = this->Makefile->GetDefinition(cacheEntry);
+ const char* cacheValue = status.GetMakefile().GetDefinition(cacheEntry);
// If it exists already and appears up to date then we are done. If
// the string contains "(IntDir)" but that is not the
// CMAKE_CFG_INTDIR setting then the value is out of date.
- const char* intDir =
- this->Makefile->GetRequiredDefinition("CMAKE_CFG_INTDIR");
+ std::string const& intDir =
+ status.GetMakefile().GetRequiredDefinition("CMAKE_CFG_INTDIR");
bool haveCacheValue = false;
- if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING")) {
- haveCacheValue = (cacheValue != CM_NULLPTR);
+ if (status.GetMakefile().IsOn("CMAKE_CROSSCOMPILING")) {
+ haveCacheValue = (cacheValue != nullptr);
if (!haveCacheValue) {
- std::string msg = "UTILITY_SOURCE is used in cross compiling mode for ";
- msg += cacheEntry;
- msg += ". If your intention is to run this executable, you need to "
- "preload the cache with the full path to a version of that "
- "program, which runs on this build machine.";
- cmSystemTools::Message(msg.c_str(), "Warning");
+ std::string msg = cmStrCat(
+ "UTILITY_SOURCE is used in cross compiling mode for ", cacheEntry,
+ ". If your intention is to run this executable, you need to "
+ "preload the cache with the full path to a version of that "
+ "program, which runs on this build machine.");
+ cmSystemTools::Message(msg, "Warning");
}
} else {
- cmState* state = this->Makefile->GetState();
- haveCacheValue =
- (cacheValue && (strstr(cacheValue, "(IntDir)") == CM_NULLPTR ||
- (intDir && strcmp(intDir, "$(IntDir)") == 0)) &&
- (state->GetCacheMajorVersion() != 0 &&
- state->GetCacheMinorVersion() != 0));
+ cmState* state = status.GetMakefile().GetState();
+ haveCacheValue = (cacheValue &&
+ (strstr(cacheValue, "(IntDir)") == nullptr ||
+ (intDir == "$(IntDir)")) &&
+ (state->GetCacheMajorVersion() != 0 &&
+ state->GetCacheMinorVersion() != 0));
}
if (haveCacheValue) {
@@ -62,29 +62,30 @@ bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args,
// The third argument specifies the relative directory of the source
// of the utility.
std::string const& relativeSource = *arg++;
- std::string utilitySource = this->Makefile->GetCurrentSourceDirectory();
+ std::string utilitySource = status.GetMakefile().GetCurrentSourceDirectory();
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;
}
}
// The source exists.
- std::string cmakeCFGout =
- this->Makefile->GetRequiredDefinition("CMAKE_CFG_INTDIR");
- std::string utilityDirectory = this->Makefile->GetCurrentBinaryDirectory();
+ const std::string& cmakeCFGout =
+ status.GetMakefile().GetRequiredDefinition("CMAKE_CFG_INTDIR");
+ std::string utilityDirectory =
+ status.GetMakefile().GetCurrentBinaryDirectory();
std::string exePath;
- if (this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH")) {
- exePath = this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
+ if (status.GetMakefile().GetDefinition("EXECUTABLE_OUTPUT_PATH")) {
+ exePath = status.GetMakefile().GetDefinition("EXECUTABLE_OUTPUT_PATH");
}
if (!exePath.empty()) {
utilityDirectory = exePath;
@@ -94,21 +95,22 @@ bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args,
// Construct the cache entry for the executable's location.
std::string utilityExecutable = utilityDirectory + "/" + cmakeCFGout + "/" +
- utilityName + this->Makefile->GetDefinition("CMAKE_EXECUTABLE_SUFFIX");
+ utilityName +
+ status.GetMakefile().GetDefinition("CMAKE_EXECUTABLE_SUFFIX");
// make sure we remove any /./ in the name
cmSystemTools::ReplaceString(utilityExecutable, "/./", "/");
// Enter the value into the cache.
- this->Makefile->AddCacheDefinition(cacheEntry, utilityExecutable.c_str(),
- "Path to an internal program.",
- cmStateEnums::FILEPATH);
+ status.GetMakefile().AddCacheDefinition(
+ cacheEntry, utilityExecutable.c_str(), "Path to an internal program.",
+ cmStateEnums::FILEPATH);
// add a value into the cache that maps from the
// full path to the name of the project
cmSystemTools::ConvertToUnixSlashes(utilityExecutable);
- this->Makefile->AddCacheDefinition(utilityExecutable, utilityName.c_str(),
- "Executable to project name.",
- cmStateEnums::INTERNAL);
+ status.GetMakefile().AddCacheDefinition(
+ utilityExecutable, utilityName.c_str(), "Executable to project name.",
+ cmStateEnums::INTERNAL);
return true;
}
diff --git a/Source/cmUtilitySourceCommand.h b/Source/cmUtilitySourceCommand.h
index a95b48d6a..934d53905 100644
--- a/Source/cmUtilitySourceCommand.h
+++ b/Source/cmUtilitySourceCommand.h
@@ -3,21 +3,14 @@
#ifndef cmUtilitySourceCommand_h
#define cmUtilitySourceCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmUtilitySourceCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE { return new cmUtilitySourceCommand; }
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmUtilitySourceCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
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/cmUuid.cxx b/Source/cmUuid.cxx
index 201e1ccef..cd52b3f30 100644
--- a/Source/cmUuid.cxx
+++ b/Source/cmUuid.cxx
@@ -2,18 +2,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmUuid.h"
-#include "cmCryptoHash.h"
+#include <array>
+#include <cstring>
-#include <string.h>
+#include "cmCryptoHash.h"
-cmUuid::cmUuid()
-{
- Groups.push_back(4);
- Groups.push_back(2);
- Groups.push_back(2);
- Groups.push_back(2);
- Groups.push_back(6);
-}
+static const std::array<int, 5> kUuidGroups = { { 4, 2, 2, 2, 6 } };
std::string cmUuid::FromMd5(std::vector<unsigned char> const& uuidNamespace,
std::string const& name) const
@@ -59,7 +53,7 @@ void cmUuid::CreateHashInput(std::vector<unsigned char> const& uuidNamespace,
std::string cmUuid::FromDigest(const unsigned char* digest,
unsigned char version) const
{
- typedef unsigned char byte_t;
+ using byte_t = unsigned char;
byte_t uuid[16] = { 0 };
memcpy(uuid, digest, 16);
@@ -83,11 +77,11 @@ bool cmUuid::StringToBinary(std::string const& input,
return false;
}
size_t index = 0;
- for (size_t i = 0; i < this->Groups.size(); ++i) {
+ for (size_t i = 0; i < kUuidGroups.size(); ++i) {
if (i != 0 && input[index++] != '-') {
return false;
}
- size_t digits = this->Groups[i] * 2;
+ size_t digits = kUuidGroups[i] * 2;
if (!StringToBinaryImpl(input.substr(index, digits), output)) {
return false;
}
@@ -103,12 +97,12 @@ std::string cmUuid::BinaryToString(const unsigned char* input) const
std::string output;
size_t inputIndex = 0;
- for (size_t i = 0; i < this->Groups.size(); ++i) {
+ for (size_t i = 0; i < kUuidGroups.size(); ++i) {
if (i != 0) {
output += '-';
}
- size_t bytes = this->Groups[i];
+ size_t bytes = kUuidGroups[i];
for (size_t j = 0; j < bytes; ++j) {
unsigned char byte = input[inputIndex++];
output += this->ByteToHex(byte);
@@ -120,14 +114,12 @@ std::string cmUuid::BinaryToString(const unsigned char* input) const
std::string cmUuid::ByteToHex(unsigned char byte) const
{
- std::string result;
+ std::string result(" ");
for (int i = 0; i < 2; ++i) {
unsigned char rest = byte % 16;
byte /= 16;
-
char c = (rest < 0xA) ? char('0' + rest) : char('a' + (rest - 0xA));
-
- result = c + result;
+ result.at(1 - i) = c;
}
return result;
diff --git a/Source/cmUuid.h b/Source/cmUuid.h
index 158ce6ee4..7de20dd29 100644
--- a/Source/cmUuid.h
+++ b/Source/cmUuid.h
@@ -15,8 +15,6 @@
class cmUuid
{
public:
- cmUuid();
-
std::string FromMd5(std::vector<unsigned char> const& uuidNamespace,
std::string const& name) const;
@@ -42,8 +40,6 @@ private:
std::string BinaryToString(const unsigned char* input) const;
bool IntFromHexDigit(char input, char& output) const;
-
- std::vector<int> Groups;
};
#endif
diff --git a/Source/cmVS10CLFlagTable.h b/Source/cmVS10CLFlagTable.h
deleted file mode 100644
index dbd760ed1..000000000
--- a/Source/cmVS10CLFlagTable.h
+++ /dev/null
@@ -1,204 +0,0 @@
-static cmVS7FlagTable cmVS10CLFlagTable[] = {
-
- // Enum Properties
- { "DebugInformationFormat", "Z7", "C7 compatible", "OldStyle", 0 },
- { "DebugInformationFormat", "Zi", "Program Database", "ProgramDatabase", 0 },
- { "DebugInformationFormat", "ZI", "Program Database for Edit And Continue",
- "EditAndContinue", 0 },
-
- { "WarningLevel", "W0", "Turn Off All Warnings", "TurnOffAllWarnings", 0 },
- { "WarningLevel", "W1", "Level1", "Level1", 0 },
- { "WarningLevel", "W2", "Level2", "Level2", 0 },
- { "WarningLevel", "W3", "Level3", "Level3", 0 },
- { "WarningLevel", "W4", "Level4", "Level4", 0 },
- { "WarningLevel", "Wall", "EnableAllWarnings", "EnableAllWarnings", 0 },
-
- { "Optimization", "Od", "Disabled", "Disabled", 0 },
- { "Optimization", "O1", "Minimize Size", "MinSpace", 0 },
- { "Optimization", "O2", "Maximize Speed", "MaxSpeed", 0 },
- { "Optimization", "Ox", "Full Optimization", "Full", 0 },
-
- { "InlineFunctionExpansion", "", "Default", "Default", 0 },
- { "InlineFunctionExpansion", "Ob0", "Disabled", "Disabled", 0 },
- { "InlineFunctionExpansion", "Ob1", "Only __inline", "OnlyExplicitInline",
- 0 },
- { "InlineFunctionExpansion", "Ob2", "Any Suitable", "AnySuitable", 0 },
-
- { "FavorSizeOrSpeed", "Os", "Favor small code", "Size", 0 },
- { "FavorSizeOrSpeed", "Ot", "Favor fast code", "Speed", 0 },
- { "FavorSizeOrSpeed", "", "Neither", "Neither", 0 },
-
- { "ExceptionHandling", "EHa", "Yes with SEH Exceptions", "Async", 0 },
- { "ExceptionHandling", "EHsc", "Yes", "Sync", 0 },
- { "ExceptionHandling", "EHs", "Yes with Extern C functions", "SyncCThrow",
- 0 },
- { "ExceptionHandling", "", "No", "false", 0 },
-
- { "BasicRuntimeChecks", "RTCs", "Stack Frames", "StackFrameRuntimeCheck",
- 0 },
- { "BasicRuntimeChecks", "RTCu", "Uninitialized variables",
- "UninitializedLocalUsageCheck", 0 },
- { "BasicRuntimeChecks", "RTC1", "Both (/RTC1, equiv. to /RTCsu)",
- "EnableFastChecks", 0 },
- { "BasicRuntimeChecks", "", "Default", "Default", 0 },
-
- { "RuntimeLibrary", "MT", "Multi-threaded", "MultiThreaded", 0 },
- { "RuntimeLibrary", "MTd", "Multi-threaded Debug", "MultiThreadedDebug", 0 },
- { "RuntimeLibrary", "MD", "Multi-threaded DLL", "MultiThreadedDLL", 0 },
- { "RuntimeLibrary", "MDd", "Multi-threaded Debug DLL",
- "MultiThreadedDebugDLL", 0 },
-
- { "StructMemberAlignment", "Zp1", "1 Byte", "1Byte", 0 },
- { "StructMemberAlignment", "Zp2", "2 Bytes", "2Bytes", 0 },
- { "StructMemberAlignment", "Zp4", "4 Byte", "4Bytes", 0 },
- { "StructMemberAlignment", "Zp8", "8 Bytes", "8Bytes", 0 },
- { "StructMemberAlignment", "Zp16", "16 Bytes", "16Bytes", 0 },
- { "StructMemberAlignment", "", "Default", "Default", 0 },
-
- { "EnableEnhancedInstructionSet", "arch:SSE",
- "Streaming SIMD Extensions (/arch:SSE)", "StreamingSIMDExtensions", 0 },
- { "EnableEnhancedInstructionSet", "arch:SSE2",
- "Streaming SIMD Extensions 2 (/arch:SSE2)", "StreamingSIMDExtensions2",
- 0 },
- { "EnableEnhancedInstructionSet", "", "Not Set", "NotSet", 0 },
-
- { "FloatingPointModel", "fp:precise", "Precise", "Precise", 0 },
- { "FloatingPointModel", "fp:strict", "Strict", "Strict", 0 },
- { "FloatingPointModel", "fp:fast", "Fast", "Fast", 0 },
-
- { "PrecompiledHeader", "Yc", "Create", "Create",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "PrecompiledHeader", "Yu", "Use", "Use",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "PrecompiledHeader", "", "Not Using Precompiled Headers", "NotUsing", 0 },
-
- { "AssemblerOutput", "", "No Listing", "NoListing", 0 },
- { "AssemblerOutput", "FA", "Assembly-Only Listing", "AssemblyCode", 0 },
- { "AssemblerOutput", "FAc", "Assembly With Machine Code",
- "AssemblyAndMachineCode", 0 },
- { "AssemblerOutput", "FAs", "Assembly With Source Code",
- "AssemblyAndSourceCode", 0 },
- { "AssemblerOutput", "FAcs", "Assembly, Machine Code and Source", "All", 0 },
-
- { "CallingConvention", "Gd", "__cdecl", "Cdecl", 0 },
- { "CallingConvention", "Gr", "__fastcall", "FastCall", 0 },
- { "CallingConvention", "Gz", "__stdcall", "StdCall", 0 },
-
- { "CompileAs", "", "Default", "Default", 0 },
- { "CompileAs", "TC", "Compile as C Code", "CompileAsC", 0 },
- { "CompileAs", "TP", "Compile as C++ Code", "CompileAsCpp", 0 },
-
- { "ErrorReporting", "errorReport:none", "Do Not Send Report", "None", 0 },
- { "ErrorReporting", "errorReport:prompt", "Prompt Immediately", "Prompt",
- 0 },
- { "ErrorReporting", "errorReport:queue", "Queue For Next Login", "Queue",
- 0 },
- { "ErrorReporting", "errorReport:send", "Send Automatically", "Send", 0 },
-
- { "CompileAsManaged", "", "No Common Language RunTime Support", "false", 0 },
- { "CompileAsManaged", "clr", "Common Language RunTime Support", "true", 0 },
- { "CompileAsManaged", "clr:pure",
- "Pure MSIL Common Language RunTime Support", "Pure", 0 },
- { "CompileAsManaged", "clr:safe",
- "Safe MSIL Common Language RunTime Support", "Safe", 0 },
- { "CompileAsManaged", "clr:oldSyntax",
- "Common Language RunTime Support, Old Syntax", "OldSyntax", 0 },
-
- // Bool Properties
- { "SuppressStartupBanner", "nologo-", "", "false", 0 },
- { "SuppressStartupBanner", "nologo", "", "true", 0 },
- { "TreatWarningAsError", "WX-", "", "false", 0 },
- { "TreatWarningAsError", "WX", "", "true", 0 },
- { "IntrinsicFunctions", "Oi", "", "true", 0 },
- { "OmitFramePointers", "Oy-", "", "false", 0 },
- { "OmitFramePointers", "Oy", "", "true", 0 },
- { "EnableFiberSafeOptimizations", "GT", "", "true", 0 },
- { "WholeProgramOptimization", "GL", "", "true", 0 },
- { "UndefineAllPreprocessorDefinitions", "u", "", "true", 0 },
- { "IgnoreStandardIncludePath", "X", "", "true", 0 },
- { "PreprocessToFile", "P", "", "true", 0 },
- { "PreprocessSuppressLineNumbers", "EP", "", "true", 0 },
- { "PreprocessKeepComments", "C", "", "true", 0 },
- { "StringPooling", "GF-", "", "false", 0 },
- { "StringPooling", "GF", "", "true", 0 },
- { "MinimalRebuild", "Gm-", "", "false", 0 },
- { "MinimalRebuild", "Gm", "", "true", 0 },
- { "SmallerTypeCheck", "RTCc", "", "true", 0 },
- { "BufferSecurityCheck", "GS-", "", "false", 0 },
- { "BufferSecurityCheck", "GS", "", "true", 0 },
- { "FunctionLevelLinking", "Gy-", "", "false", 0 },
- { "FunctionLevelLinking", "Gy", "", "true", 0 },
- { "FloatingPointExceptions", "fp:except-", "", "false", 0 },
- { "FloatingPointExceptions", "fp:except", "", "true", 0 },
- { "CreateHotpatchableImage", "hotpatch", "", "true", 0 },
- { "DisableLanguageExtensions", "Za", "", "true", 0 },
- { "TreatWChar_tAsBuiltInType", "Zc:wchar_t-", "", "false", 0 },
- { "TreatWChar_tAsBuiltInType", "Zc:wchar_t", "", "true", 0 },
- { "ForceConformanceInForLoopScope", "Zc:forScope-", "", "false", 0 },
- { "ForceConformanceInForLoopScope", "Zc:forScope", "", "true", 0 },
- { "RuntimeTypeInfo", "GR-", "", "false", 0 },
- { "RuntimeTypeInfo", "GR", "", "true", 0 },
- { "OpenMPSupport", "openmp-", "", "false", 0 },
- { "OpenMPSupport", "openmp", "", "true", 0 },
- { "ExpandAttributedSource", "Fx", "", "true", 0 },
- { "ShowIncludes", "showIncludes", "", "true", 0 },
- { "EnablePREfast", "analyze-", "", "false", 0 },
- { "EnablePREfast", "analyze", "", "true", 0 },
- { "UseFullPaths", "FC", "", "true", 0 },
- { "OmitDefaultLibName", "Zl", "", "true", 0 },
- { "UseUnicodeForAssemblerListing", "FAu", "", "true", 0 },
-
- // Bool Properties With Argument
- { "MultiProcessorCompilation", "MP", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "ProcessorNumber", "MP", "Multi-processor Compilation", "",
- cmVS7FlagTable::UserValueRequired },
- { "GenerateXMLDocumentationFiles", "doc", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "XMLDocumentationFileName", "doc", "Generate XML Documentation Files", "",
- cmVS7FlagTable::UserValueRequired },
- { "BrowseInformation", "FR", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "BrowseInformationFile", "FR", "Enable Browse Information", "",
- cmVS7FlagTable::UserValueRequired },
-
- // String List Properties
- { "AdditionalIncludeDirectories", "I", "Additional Include Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AdditionalUsingDirectories", "AI", "Resolve #using References", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "PreprocessorDefinitions", "D ", "Preprocessor Definitions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "UndefinePreprocessorDefinitions", "U",
- "Undefine Preprocessor Definitions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "DisableSpecificWarnings", "wd", "Disable Specific Warnings", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ForcedIncludeFiles", "FI", "Forced Include File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ForcedUsingFiles", "FU", "Forced #using File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "TreatSpecificWarningsAsErrors", "we", "Treat Specific Warnings As Errors",
- "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-
- // String Properties
- // Skip [TrackerLogDirectory] - no command line Switch.
- { "PreprocessOutputPath", "Fi", "Preprocess Output Path", "",
- cmVS7FlagTable::UserValue },
- { "PrecompiledHeaderFile", "Yc", "Precompiled Header Name", "",
- cmVS7FlagTable::UserValueRequired },
- { "PrecompiledHeaderFile", "Yu", "Precompiled Header Name", "",
- cmVS7FlagTable::UserValueRequired },
- { "PrecompiledHeaderOutputFile", "Fp", "Precompiled Header Output File", "",
- cmVS7FlagTable::UserValue },
- { "AssemblerListingLocation", "Fa", "ASM List Location", "",
- cmVS7FlagTable::UserValue },
- { "ObjectFileName", "Fo", "Object File Name", "",
- cmVS7FlagTable::UserValue },
- { "ProgramDataBaseFileName", "Fd", "Program Database File Name", "",
- cmVS7FlagTable::UserValue },
- // Skip [XMLDocumentationFileName] - no command line Switch.
- // Skip [BrowseInformationFile] - no command line Switch.
- // Skip [AdditionalOptions] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS10CSharpFlagTable.h b/Source/cmVS10CSharpFlagTable.h
deleted file mode 100644
index 493ec2b12..000000000
--- a/Source/cmVS10CSharpFlagTable.h
+++ /dev/null
@@ -1,120 +0,0 @@
-static cmVS7FlagTable cmVS10CSharpFlagTable[] = {
- { "ProjectName", "out:", "", "", cmIDEFlagTable::UserValueRequired },
-
- { "OutputType", "target:exe", "", "Exe", 0 },
- { "OutputType", "target:winexe", "", "Winexe", 0 },
- { "OutputType", "target:library", "", "Library", 0 },
- { "OutputType", "target:module", "", "Module", 0 },
-
- { "DocumentationFile", "doc", "", "", cmIDEFlagTable::UserValueRequired },
-
- { "Platform", "platform:x86", "", "x86", 0 },
- { "Platform", "platform:Itanium", "", "Itanium", 0 },
- { "Platform", "platform:x64", "", "x64", 0 },
- { "Platform", "platform:arm", "", "arm", 0 },
- { "Platform", "platform:anycpu32bitpreferred", "", "anycpu32bitpreferred",
- 0 },
- { "Platform", "platform:anycpu", "", "anycpu", 0 },
-
- { "References", "reference:", "mit alias", "", 0 },
- { "References", "reference:", "dateiliste", "", 0 },
- { "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable },
- { "", "link", "", "", 0 },
-
- { "Win32Resource", "win32res", "", "", cmIDEFlagTable::UserValueRequired },
- { "ApplicationIcon", "win32icon", "", "",
- cmIDEFlagTable::UserValueRequired },
-
- { "Win32Manifest", "win32manifest:", "", "true", 0 },
-
- { "NoWin32Manifest", "nowin32manifest", "", "true", 0 },
-
- { "DefineDebug", "debug", "", "true", cmIDEFlagTable::Continue },
-
- { "DebugSymbols", "debug", "", "true", 0 },
- { "DebugSymbols", "debug-", "", "false", 0 },
- { "DebugSymbols", "debug+", "", "true", 0 },
-
- { "DebugType", "debug:none", "", "none", 0 },
- { "DebugType", "debug:full", "", "full", 0 },
- { "DebugType", "debug:pdbonly", "", "pdbonly", 0 },
-
- { "Optimize", "optimize", "", "true", 0 },
- { "Optimize", "optimize-", "", "false", 0 },
- { "Optimize", "optimize+", "", "true", 0 },
-
- { "TreatWarningsAsErrors", "warnaserror", "", "true", 0 },
- { "TreatWarningsAsErrors", "warnaserror-", "", "false", 0 },
- { "TreatWarningsAsErrors", "warnaserror+", "", "true", 0 },
-
- { "WarningsAsErrors", "warnaserror", "", "", 0 },
- { "WarningsAsErrors", "warnaserror-", "", "", 0 },
- { "WarningsAsErrors", "warnaserror+", "", "", 0 },
-
- { "WarningLevel", "warn:0", "", "0", 0 },
- { "WarningLevel", "warn:1", "", "1", 0 },
- { "WarningLevel", "warn:2", "", "2", 0 },
- { "WarningLevel", "warn:3", "", "3", 0 },
- { "WarningLevel", "warn:4", "", "4", 0 },
- { "DisabledWarnings", "nowarn", "", "", 0 },
-
- { "CheckForOverflowUnderflow", "checked", "", "true", 0 },
- { "CheckForOverflowUnderflow", "checked-", "", "false", 0 },
- { "CheckForOverflowUnderflow", "checked+", "", "true", 0 },
-
- { "AllowUnsafeBlocks", "unsafe", "", "true", 0 },
- { "AllowUnsafeBlocks", "unsafe-", "", "false", 0 },
- { "AllowUnsafeBlocks", "unsafe+", "", "true", 0 },
-
- { "DefineConstants", "define:", "", "",
- cmIDEFlagTable::SemicolonAppendable | cmIDEFlagTable::UserValue },
-
- { "LangVersion", "langversion:ISO-1", "", "ISO-1", 0 },
- { "LangVersion", "langversion:ISO-2", "", "ISO-2", 0 },
- { "LangVersion", "langversion:3", "", "3", 0 },
- { "LangVersion", "langversion:4", "", "4", 0 },
- { "LangVersion", "langversion:5", "", "5", 0 },
- { "LangVersion", "langversion:6", "", "6", 0 },
- { "LangVersion", "langversion:default", "", "default", 0 },
-
- { "DelaySign", "delaysign", "", "true", 0 },
- { "DelaySign", "delaysign-", "", "false", 0 },
- { "DelaySign", "delaysign+", "", "true", 0 },
-
- { "AssemblyOriginatorKeyFile", "keyfile", "", "", 0 },
-
- { "KeyContainerName", "keycontainer", "", "", 0 },
-
- { "NoLogo", "nologo", "", "", 0 },
-
- { "NoConfig", "noconfig", "", "true", 0 },
-
- { "BaseAddress", "baseaddress:", "", "", 0 },
-
- { "CodePage", "codepage", "", "", 0 },
-
- { "Utf8Output", "utf8output", "", "", 0 },
-
- { "MainEntryPoint", "main:", "", "", 0 },
-
- { "GenerateFullPaths", "fullpaths", "", "true", 0 },
-
- { "FileAlignment", "filealign", "", "", 0 },
-
- { "PdbFile", "pdb:", "", "", 0 },
-
- { "NoStandardLib", "nostdlib", "", "true", 0 },
- { "NoStandardLib", "nostdlib-", "", "false", 0 },
- { "NoStandardLib", "nostdlib+", "", "true", 0 },
-
- { "SubsystemVersion", "subsystemversion", "", "", 0 },
-
- { "AdditionalLibPaths", "lib:", "", "", 0 },
-
- { "ErrorReport", "errorreport:none", "Do Not Send Report", "none", 0 },
- { "ErrorReport", "errorreport:prompt", "Prompt Immediately", "prompt", 0 },
- { "ErrorReport", "errorreport:queue", "Queue For Next Login", "queue", 0 },
- { "ErrorReport", "errorreport:send", "Send Automatically", "send", 0 },
-
- { 0, 0, 0, 0, 0 },
-};
diff --git a/Source/cmVS10CudaFlagTable.h b/Source/cmVS10CudaFlagTable.h
deleted file mode 100644
index da19d649b..000000000
--- a/Source/cmVS10CudaFlagTable.h
+++ /dev/null
@@ -1,51 +0,0 @@
-static cmVS7FlagTable cmVS10CudaFlagTable[] = {
- // Collect options meant for the host compiler.
- { "AdditionalCompilerOptions", "Xcompiler=", "Host compiler options", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SpaceAppendable },
- { "AdditionalCompilerOptions", "Xcompiler", "Host compiler options", "",
- cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SpaceAppendable },
-
- // Select the CUDA runtime library.
- { "CudaRuntime", "cudart=none", "No CUDA runtime library", "None", 0 },
- { "CudaRuntime", "cudart=shared", "Shared/dynamic CUDA runtime library",
- "Shared", 0 },
- { "CudaRuntime", "cudart=static", "Static CUDA runtime library", "Static",
- 0 },
- { "CudaRuntime", "cudart", "CUDA runtime library", "",
- cmVS7FlagTable::UserFollowing },
-
- // Capture arch/code arguments into temporaries for post-processing.
- { "cmake-temp-gencode", "gencode=", "", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "cmake-temp-gencode", "gencode", "", "",
- cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SemicolonAppendable },
- { "cmake-temp-gencode", "-generate-code=", "", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "cmake-temp-gencode", "-generate-code", "", "",
- cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SemicolonAppendable },
-
- { "cmake-temp-code", "code=", "", "", cmVS7FlagTable::UserValue },
- { "cmake-temp-code", "code", "", "", cmVS7FlagTable::UserFollowing },
- { "cmake-temp-code", "-gpu-code=", "", "", cmVS7FlagTable::UserValue },
- { "cmake-temp-code", "-gpu-code", "", "", cmVS7FlagTable::UserFollowing },
-
- { "cmake-temp-arch", "arch=", "", "", cmVS7FlagTable::UserValue },
- { "cmake-temp-arch", "arch", "", "", cmVS7FlagTable::UserFollowing },
- { "cmake-temp-arch", "-gpu-architecture=", "", "",
- cmVS7FlagTable::UserValue },
- { "cmake-temp-arch", "-gpu-architecture", "", "",
- cmVS7FlagTable::UserFollowing },
-
- // Other flags.
-
- { "FastMath", "use_fast_math", "", "true", 0 },
- { "FastMath", "-use_fast_math", "", "true", 0 },
-
- { "GPUDebugInfo", "G", "", "true", 0 },
- { "GPUDebugInfo", "-device-debug", "", "true", 0 },
-
- { "HostDebugInfo", "g", "", "true", 0 },
- { "HostDebugInfo", "-debug", "", "true", 0 },
-
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS10CudaHostFlagTable.h b/Source/cmVS10CudaHostFlagTable.h
deleted file mode 100644
index 5b61066ca..000000000
--- a/Source/cmVS10CudaHostFlagTable.h
+++ /dev/null
@@ -1,35 +0,0 @@
-static cmVS7FlagTable cmVS10CudaHostFlagTable[] = {
- //{"Optimization", "", "<inherit from host>", "InheritFromHost", 0},
- { "Optimization", "Od", "Disabled", "Od", 0 },
- { "Optimization", "O1", "Minimize Size", "O1", 0 },
- { "Optimization", "O2", "Maximize Speed", "O2", 0 },
- { "Optimization", "Ox", "Full Optimization", "O3", 0 },
-
- //{"Runtime", "", "<inherit from host>", "InheritFromHost", 0},
- { "Runtime", "MT", "Multi-Threaded", "MT", 0 },
- { "Runtime", "MTd", "Multi-Threaded Debug", "MTd", 0 },
- { "Runtime", "MD", "Multi-Threaded DLL", "MD", 0 },
- { "Runtime", "MDd", "Multi-threaded Debug DLL", "MDd", 0 },
- { "Runtime", "ML", "Single-Threaded", "ML", 0 },
- { "Runtime", "MLd", "Single-Threaded Debug", "MLd", 0 },
-
- //{"RuntimeChecks", "", "<inherit from host>", "InheritFromHost", 0},
- //{"RuntimeChecks", "", "Default", "Default", 0},
- { "RuntimeChecks", "RTCs", "Stack Frames", "RTCs", 0 },
- { "RuntimeChecks", "RTCu", "Uninitialized Variables", "RTCu", 0 },
- { "RuntimeChecks", "RTC1", "Both", "RTC1", 0 },
-
- //{"TypeInfo", "", "<inherit from host>", "InheritFromHost", 0},
- { "TypeInfo", "GR", "Yes", "true", 0 },
- { "TypeInfo", "GR-", "No", "false", 0 },
-
- //{"Warning", "", "<inherit from host>", "InheritFromHost", 0},
- { "Warning", "W0", "Off: Turn Off All Warnings", "W0", 0 },
- { "Warning", "W1", "Level 1", "W1", 0 },
- { "Warning", "W2", "Level 2", "W2", 0 },
- { "Warning", "W3", "Level 3", "W3", 0 },
- { "Warning", "W4", "Level 4", "W4", 0 },
- { "Warning", "Wall", "Enable All Warnings", "Wall", 0 },
-
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS10LibFlagTable.h b/Source/cmVS10LibFlagTable.h
deleted file mode 100644
index 65f28ef40..000000000
--- a/Source/cmVS10LibFlagTable.h
+++ /dev/null
@@ -1,76 +0,0 @@
-static cmVS7FlagTable cmVS10LibFlagTable[] = {
-
- // Enum Properties
- { "ErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately",
- "PromptImmediately", 0 },
- { "ErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login",
- "QueueForNextLogin", 0 },
- { "ErrorReporting", "ERRORREPORT:SEND", "Send Error Report",
- "SendErrorReport", 0 },
- { "ErrorReporting", "ERRORREPORT:NONE", "No Error Report", "NoErrorReport",
- 0 },
-
- { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 },
- { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 },
- { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 },
- { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 },
- { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 },
- { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU",
- 0 },
- { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16",
- "MachineMIPSFPU16", 0 },
- { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 },
- { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 },
- { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 },
- { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 },
-
- { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 },
- { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 },
- { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application",
- "EFI Application", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER",
- "EFI Boot Service Driver", "EFI Boot Service Driver", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime",
- 0 },
- { "SubSystem", "SUBSYSTEM:WINDOWSCE", "WindowsCE", "WindowsCE", 0 },
- { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 },
-
- // Bool Properties
- { "SuppressStartupBanner", "NOLOGO", "", "true", 0 },
- { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 },
- { "TreatLibWarningAsErrors", "WX:NO", "", "false", 0 },
- { "TreatLibWarningAsErrors", "WX", "", "true", 0 },
- { "Verbose", "VERBOSE", "", "true", 0 },
- { "LinkTimeCodeGeneration", "LTCG", "", "true", 0 },
-
- // Bool Properties With Argument
-
- // String List Properties
- // Skip [AdditionalDependencies] - no command line Switch.
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ExportNamedFunctions", "EXPORT:", "Export Named Functions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "RemoveObjects", "REMOVE:", "Remove Objects", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-
- // String Properties
- { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue },
- { "ModuleDefinitionFile", "DEF:", "Module Definition File Name", "",
- cmVS7FlagTable::UserValue },
- { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "",
- cmVS7FlagTable::UserValue },
- { "DisplayLibrary", "LIST:", "Display Library to standard output", "",
- cmVS7FlagTable::UserValue },
- // Skip [MinimumRequiredVersion] - no command line Switch.
- { "Name", "NAME:", "Name", "", cmVS7FlagTable::UserValue },
- // Skip [TrackerLogDirectory] - no command line Switch.
- // Skip [AdditionalOptions] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS10LinkFlagTable.h b/Source/cmVS10LinkFlagTable.h
deleted file mode 100644
index c30ea9a66..000000000
--- a/Source/cmVS10LinkFlagTable.h
+++ /dev/null
@@ -1,244 +0,0 @@
-static cmVS7FlagTable cmVS10LinkFlagTable[] = {
-
- // Enum Properties
- { "ShowProgress", "", "Not Set", "NotSet", 0 },
- { "ShowProgress", "VERBOSE", "Display all progress messages", "LinkVerbose",
- 0 },
- { "ShowProgress", "VERBOSE:Lib", "For Libraries Searched", "LinkVerboseLib",
- 0 },
- { "ShowProgress", "VERBOSE:ICF",
- "About COMDAT folding during optimized linking", "LinkVerboseICF", 0 },
- { "ShowProgress", "VERBOSE:REF",
- "About data removed during optimized linking", "LinkVerboseREF", 0 },
- { "ShowProgress", "VERBOSE:SAFESEH", "About Modules incompatible with SEH",
- "LinkVerboseSAFESEH", 0 },
- { "ShowProgress", "VERBOSE:CLR",
- "About linker activity related to managed code", "LinkVerboseCLR", 0 },
-
- { "ForceFileOutput", "FORCE", "Enabled", "Enabled", 0 },
- { "ForceFileOutput", "FORCE:MULTIPLE", "Multiply Defined Symbol Only",
- "MultiplyDefinedSymbolOnly", 0 },
- { "ForceFileOutput", "FORCE:UNRESOLVED", "Undefined Symbol Only",
- "UndefinedSymbolOnly", 0 },
-
- { "CreateHotPatchableImage", "FUNCTIONPADMIN", "Enabled", "Enabled", 0 },
- { "CreateHotPatchableImage", "FUNCTIONPADMIN:5", "X86 Image Only",
- "X86Image", 0 },
- { "CreateHotPatchableImage", "FUNCTIONPADMIN:6", "X64 Image Only",
- "X64Image", 0 },
- { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only",
- "ItaniumImage", 0 },
-
- { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 },
- { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable",
- "HighestAvailable", 0 },
- { "UACExecutionLevel", "level='requireAdministrator'",
- "requireAdministrator", "RequireAdministrator", 0 },
-
- { "SubSystem", "", "Not Set", "NotSet", 0 },
- { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 },
- { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 },
- { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application",
- "EFI Application", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER",
- "EFI Boot Service Driver", "EFI Boot Service Driver", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime",
- 0 },
- { "SubSystem", "SUBSYSTEM:WINDOWSCE", "WindowsCE", "WindowsCE", 0 },
- { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 },
-
- { "Driver", "", "Not Set", "NotSet", 0 },
- { "Driver", "Driver", "Driver", "Driver", 0 },
- { "Driver", "DRIVER:UPONLY", "UP Only", "UpOnly", 0 },
- { "Driver", "DRIVER:WDM", "WDM", "WDM", 0 },
-
- { "LinkTimeCodeGeneration", "", "Default", "Default", 0 },
- { "LinkTimeCodeGeneration", "LTCG", "Use Link Time Code Generation",
- "UseLinkTimeCodeGeneration", 0 },
- { "LinkTimeCodeGeneration", "LTCG:PGInstrument",
- "Profile Guided Optimization - Instrument", "PGInstrument", 0 },
- { "LinkTimeCodeGeneration", "LTCG:PGOptimize",
- "Profile Guided Optimization - Optimization", "PGOptimization", 0 },
- { "LinkTimeCodeGeneration", "LTCG:PGUpdate",
- "Profile Guided Optimization - Update", "PGUpdate", 0 },
-
- { "TargetMachine", "", "Not Set", "NotSet", 0 },
- { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 },
- { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 },
- { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 },
- { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 },
- { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 },
- { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU",
- 0 },
- { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16",
- "MachineMIPSFPU16", 0 },
- { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 },
- { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 },
- { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 },
- { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 },
-
- { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:MTA", "MTA threading attribute",
- "MTAThreadingAttribute", 0 },
- { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:STA", "STA threading attribute",
- "STAThreadingAttribute", 0 },
- { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:NONE",
- "Default threading attribute", "DefaultThreadingAttribute", 0 },
-
- { "CLRImageType", "CLRIMAGETYPE:IJW", "Force IJW image", "ForceIJWImage",
- 0 },
- { "CLRImageType", "CLRIMAGETYPE:PURE", "Force Pure IL Image",
- "ForcePureILImage", 0 },
- { "CLRImageType", "CLRIMAGETYPE:SAFE", "Force Safe IL Image",
- "ForceSafeILImage", 0 },
- { "CLRImageType", "", "Default image type", "Default", 0 },
-
- { "LinkErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately",
- "PromptImmediately", 0 },
- { "LinkErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login",
- "QueueForNextLogin", 0 },
- { "LinkErrorReporting", "ERRORREPORT:SEND", "Send Error Report",
- "SendErrorReport", 0 },
- { "LinkErrorReporting", "ERRORREPORT:NONE", "No Error Report",
- "NoErrorReport", 0 },
-
- { "CLRSupportLastError", "CLRSupportLastError", "Enabled", "Enabled", 0 },
- { "CLRSupportLastError", "CLRSupportLastError:NO", "Disabled", "Disabled",
- 0 },
- { "CLRSupportLastError", "CLRSupportLastError:SYSTEMDLL", "System Dlls Only",
- "SystemDlls", 0 },
-
- // Bool Properties
- { "LinkIncremental", "INCREMENTAL:NO", "", "false", 0 },
- { "LinkIncremental", "INCREMENTAL", "", "true", 0 },
- { "SuppressStartupBanner", "NOLOGO", "", "true", 0 },
- { "LinkStatus", "LTCG:NOSTATUS", "", "false", 0 },
- { "LinkStatus", "LTCG:STATUS", "", "true", 0 },
- { "PreventDllBinding", "ALLOWBIND:NO", "", "false", 0 },
- { "PreventDllBinding", "ALLOWBIND", "", "true", 0 },
- { "TreatLinkerWarningAsErrors", "WX:NO", "", "false", 0 },
- { "TreatLinkerWarningAsErrors", "WX", "", "true", 0 },
- { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 },
- { "GenerateManifest", "MANIFEST:NO", "", "false", 0 },
- { "GenerateManifest", "MANIFEST", "", "true", 0 },
- { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 },
- { "UACUIAccess", "uiAccess='false'", "", "false", 0 },
- { "UACUIAccess", "uiAccess='true'", "", "true", 0 },
- { "GenerateDebugInformation", "DEBUG", "", "true",
- cmVS7FlagTable::CaseInsensitive },
- { "MapExports", "MAPINFO:EXPORTS", "", "true", 0 },
- { "AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0 },
- { "AssemblyDebug", "ASSEMBLYDEBUG", "", "true", 0 },
- { "LargeAddressAware", "LARGEADDRESSAWARE:NO", "", "false", 0 },
- { "LargeAddressAware", "LARGEADDRESSAWARE", "", "true", 0 },
- { "TerminalServerAware", "TSAWARE:NO", "", "false", 0 },
- { "TerminalServerAware", "TSAWARE", "", "true", 0 },
- { "SwapRunFromCD", "SWAPRUN:CD", "", "true", 0 },
- { "SwapRunFromNET", "SWAPRUN:NET", "", "true", 0 },
- { "OptimizeReferences", "OPT:NOREF", "", "false", 0 },
- { "OptimizeReferences", "OPT:REF", "", "true", 0 },
- { "EnableCOMDATFolding", "OPT:NOICF", "", "false", 0 },
- { "EnableCOMDATFolding", "OPT:ICF", "", "true", 0 },
- { "IgnoreEmbeddedIDL", "IGNOREIDL", "", "true", 0 },
- { "NoEntryPoint", "NOENTRY", "", "true", 0 },
- { "SetChecksum", "RELEASE", "", "true", 0 },
- { "RandomizedBaseAddress", "DYNAMICBASE:NO", "", "false", 0 },
- { "RandomizedBaseAddress", "DYNAMICBASE", "", "true", 0 },
- { "FixedBaseAddress", "FIXED:NO", "", "false", 0 },
- { "FixedBaseAddress", "FIXED", "", "true", 0 },
- { "DataExecutionPrevention", "NXCOMPAT:NO", "", "false", 0 },
- { "DataExecutionPrevention", "NXCOMPAT", "", "true", 0 },
- { "TurnOffAssemblyGeneration", "NOASSEMBLY", "", "true", 0 },
- { "SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0 },
- { "SupportNobindOfDelayLoadedDLL", "DELAY:NOBIND", "", "true", 0 },
- { "Profile", "PROFILE", "", "true", 0 },
- { "LinkDelaySign", "DELAYSIGN:NO", "", "false", 0 },
- { "LinkDelaySign", "DELAYSIGN", "", "true", 0 },
- { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0 },
- { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0 },
- { "ImageHasSafeExceptionHandlers", "SAFESEH:NO", "", "false", 0 },
- { "ImageHasSafeExceptionHandlers", "SAFESEH", "", "true", 0 },
- { "LinkDLL", "DLL", "", "true", 0 },
-
- // Bool Properties With Argument
- { "EnableUAC", "MANIFESTUAC:NO", "", "false", 0 },
- { "EnableUAC", "MANIFESTUAC:", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "UACUIAccess", "MANIFESTUAC:", "Enable User Account Control (UAC)", "",
- cmVS7FlagTable::UserValueRequired },
- { "GenerateMapFile", "MAP", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "MapFileName", "MAP:", "Generate Map File", "",
- cmVS7FlagTable::UserValueRequired },
-
- // String List Properties
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- // Skip [AdditionalDependencies] - no command line Switch.
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly",
- "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "EmbedManagedResourceFile", "ASSEMBLYRESOURCE:",
- "Embed Managed Resource File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "DelayLoadDLLs", "DELAYLOAD:", "Delay Loaded Dlls", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource",
- "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AdditionalManifestDependencies", "MANIFESTDEPENDENCY:",
- "Additional Manifest Dependencies", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-
- // String Properties
- { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue },
- { "Version", "VERSION:", "Version", "", cmVS7FlagTable::UserValue },
- { "SpecifySectionAttributes", "SECTION:", "Specify Section Attributes", "",
- cmVS7FlagTable::UserValue },
- { "MSDOSStubFileName", "STUB:", "MS-DOS Stub File Name", "",
- cmVS7FlagTable::UserValue },
- // Skip [TrackerLogDirectory] - no command line Switch.
- { "ModuleDefinitionFile", "DEF:", "Module Definition File", "",
- cmVS7FlagTable::UserValue },
- { "ManifestFile", "ManifestFile:", "Manifest File", "",
- cmVS7FlagTable::UserValue },
- { "ProgramDatabaseFile", "PDB:", "Generate Program Database File", "",
- cmVS7FlagTable::UserValue },
- { "StripPrivateSymbols", "PDBSTRIPPED:", "Strip Private Symbols", "",
- cmVS7FlagTable::UserValue },
- // Skip [MapFileName] - no command line Switch.
- // Skip [MinimumRequiredVersion] - no command line Switch.
- { "HeapReserveSize", "HEAP:", "Heap Reserve Size", "",
- cmVS7FlagTable::UserValue },
- // Skip [HeapCommitSize] - no command line Switch.
- { "StackReserveSize", "STACK:", "Stack Reserve Size", "",
- cmVS7FlagTable::UserValue },
- // Skip [StackCommitSize] - no command line Switch.
- { "FunctionOrder", "ORDER:@", "Function Order", "",
- cmVS7FlagTable::UserValue },
- { "ProfileGuidedDatabase", "PGD:", "Profile Guided Database", "",
- cmVS7FlagTable::UserValue },
- { "MidlCommandFile", "MIDL:@", "MIDL Commands", "",
- cmVS7FlagTable::UserValue },
- { "MergedIDLBaseFileName", "IDLOUT:", "Merged IDL Base File Name", "",
- cmVS7FlagTable::UserValue },
- { "TypeLibraryFile", "TLBOUT:", "Type Library", "",
- cmVS7FlagTable::UserValue },
- { "EntryPointSymbol", "ENTRY:", "Entry Point", "",
- cmVS7FlagTable::UserValue },
- { "BaseAddress", "BASE:", "Base Address", "", cmVS7FlagTable::UserValue },
- { "ImportLibrary", "IMPLIB:", "Import Library", "",
- cmVS7FlagTable::UserValue },
- { "MergeSections", "MERGE:", "Merge Sections", "",
- cmVS7FlagTable::UserValue },
- { "LinkKeyFile", "KEYFILE:", "Key File", "", cmVS7FlagTable::UserValue },
- { "KeyContainer", "KEYCONTAINER:", "Key Container", "",
- cmVS7FlagTable::UserValue },
- // Skip [AdditionalOptions] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS10MASMFlagTable.h b/Source/cmVS10MASMFlagTable.h
deleted file mode 100644
index 0a452453f..000000000
--- a/Source/cmVS10MASMFlagTable.h
+++ /dev/null
@@ -1,76 +0,0 @@
-static cmVS7FlagTable cmVS10MASMFlagTable[] = {
-
- // Enum Properties
- { "PreserveIdentifierCase", "", "Default", "0", 0 },
- { "PreserveIdentifierCase", "Cp", "Preserves Identifier Case (/Cp)", "1",
- 0 },
- { "PreserveIdentifierCase", "Cu",
- "Maps all identifiers to upper case. (/Cu)", "2", 0 },
- { "PreserveIdentifierCase", "Cx",
- "Preserves case in public and extern symbols. (/Cx)", "3", 0 },
-
- { "WarningLevel", "W0", "Warning Level 0 (/W0)", "0", 0 },
- { "WarningLevel", "W1", "Warning Level 1 (/W1)", "1", 0 },
- { "WarningLevel", "W2", "Warning Level 2 (/W2)", "2", 0 },
- { "WarningLevel", "W3", "Warning Level 3 (/W3)", "3", 0 },
-
- { "PackAlignmentBoundary", "", "Default", "0", 0 },
- { "PackAlignmentBoundary", "Zp1", "One Byte Boundary (/Zp1)", "1", 0 },
- { "PackAlignmentBoundary", "Zp2", "Two Byte Boundary (/Zp2)", "2", 0 },
- { "PackAlignmentBoundary", "Zp4", "Four Byte Boundary (/Zp4)", "3", 0 },
- { "PackAlignmentBoundary", "Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 },
- { "PackAlignmentBoundary", "Zp16", "Sixteen Byte Boundary (/Zp16)", "5", 0 },
-
- { "CallingConvention", "", "Default", "0", 0 },
- { "CallingConvention", "Gd", "Use C-style Calling Convention (/Gd)", "1",
- 0 },
- { "CallingConvention", "Gz", "Use stdcall Calling Convention (/Gz)", "2",
- 0 },
- { "CallingConvention", "Gc", "Use Pascal Calling Convention (/Gc)", "3", 0 },
-
- { "ErrorReporting", "errorReport:prompt",
- "Prompt to send report immediately (/errorReport:prompt)", "0", 0 },
- { "ErrorReporting", "errorReport:queue",
- "Prompt to send report at the next logon (/errorReport:queue)", "1", 0 },
- { "ErrorReporting", "errorReport:send",
- "Automatically send report (/errorReport:send)", "2", 0 },
- { "ErrorReporting", "errorReport:none",
- "Do not send report (/errorReport:none)", "3", 0 },
-
- // Bool Properties
- { "NoLogo", "nologo", "", "true", 0 },
- { "GeneratePreprocessedSourceListing", "EP", "", "true", 0 },
- { "ListAllAvailableInformation", "Sa", "", "true", 0 },
- { "UseSafeExceptionHandlers", "safeseh", "", "true", 0 },
- { "AddFirstPassListing", "Sf", "", "true", 0 },
- { "EnableAssemblyGeneratedCodeListing", "Sg", "", "true", 0 },
- { "DisableSymbolTable", "Sn", "", "true", 0 },
- { "EnableFalseConditionalsInListing", "Sx", "", "true", 0 },
- { "TreatWarningsAsErrors", "WX", "", "true", 0 },
- { "MakeAllSymbolsPublic", "Zf", "", "true", 0 },
- { "GenerateDebugInformation", "Zi", "", "true", 0 },
- { "EnableMASM51Compatibility", "Zm", "", "true", 0 },
- { "PerformSyntaxCheckOnly", "Zs", "", "true", 0 },
-
- // Bool Properties With Argument
-
- // String List Properties
- { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "IncludePaths", "I", "Include Paths", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "BrowseFile", "FR", "Generate Browse Information File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- // Skip [AdditionalDependencies] - no command line Switch.
-
- // String Properties
- // Skip [Inputs] - no command line Switch.
- { "ObjectFileName", "Fo", "Object File Name", "",
- cmVS7FlagTable::UserValue },
- { "AssembledCodeListingFile", "Fl", "Assembled Code Listing File", "",
- cmVS7FlagTable::UserValue },
- // Skip [CommandLineTemplate] - no command line Switch.
- // Skip [ExecutionDescription] - no command line Switch.
- // Skip [AdditionalOptions] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS10NASMFlagTable.h b/Source/cmVS10NASMFlagTable.h
deleted file mode 100644
index b91af9270..000000000
--- a/Source/cmVS10NASMFlagTable.h
+++ /dev/null
@@ -1,50 +0,0 @@
-static cmVS7FlagTable cmVS10NASMFlagTable[] = {
-
- // Enum Properties
- { "Outputswitch", "fwin32", "", "0", 0 },
- { "Outputswitch", "fwin", "", "0", 0 },
- { "Outputswitch", "fwin64", "", "1", 0 },
- { "Outputswitch", "felf", "", "2", 0 },
- { "Outputswitch", "felf32", "", "2", 0 },
- { "Outputswitch", "felf64", "", "3", 0 },
-
- { "ErrorReportingFormat", "Xgnu", "", "-Xgnu GNU format: Default format",
- 0 },
- { "ErrorReportingFormat", "Xvc", "",
- "-Xvc Style used by Microsoft Visual C++", 0 },
-
- // Bool Properties
- { "TreatWarningsAsErrors", "Werror", "", "true", 0 },
- { "GenerateDebugInformation", "g", "", "true", 0 },
- { "floatunderflow", "w+float-underflow", "", "true", 0 },
- { "macrodefaults", "w-macro-defaults", "", "true", 0 },
- { "user", "w-user", "%warning directives (default on)", "true", 0 },
- { "floatoverflow", "w-float-overflow", "", "true", 0 },
- { "floatdenorm", "w+float-denorm", "", "true", 0 },
- { "numberoverflow", "w-number-overflow", "", "true", 0 },
- { "macroselfref", "w+macro-selfref", "", "true", 0 },
- { "floattoolong", "w-float-toolong", "", "true", 0 },
- { "orphanlabels", "w-orphan-labels", "", "true", 0 },
- { "tasmmode", "t", "", "true", 0 },
-
- // Bool Properties With Argument
-
- // String List Properties
- { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "UndefinePreprocessorDefinitions", "U",
- "Undefine Preprocessor Definitions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "IncludePaths", "I", "Include Paths", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AssembledCodeListingFile", "l",
- "Generates an assembled code listing file.", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-
- // String Properties
- // Skip [Inputs] - no command line Switch.
- // Skip [CommandLineTemplate] - no command line Switch.
- // Skip [ExecutionDescription] - no command line Switch.
- // Skip [AdditionalOptions] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS10RCFlagTable.h b/Source/cmVS10RCFlagTable.h
deleted file mode 100644
index 6e2b8344c..000000000
--- a/Source/cmVS10RCFlagTable.h
+++ /dev/null
@@ -1,7 +0,0 @@
-static cmVS7FlagTable cmVS10RCFlagTable[] = {
- // Bool Properties
- { "NullTerminateStrings", "n", "", "true", 0 },
- { "SuppressStartupBanner", "nologo", "", "true", 0 },
-
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS11CLFlagTable.h b/Source/cmVS11CLFlagTable.h
deleted file mode 100644
index 75317093f..000000000
--- a/Source/cmVS11CLFlagTable.h
+++ /dev/null
@@ -1,219 +0,0 @@
-static cmVS7FlagTable cmVS11CLFlagTable[] = {
-
- // Enum Properties
- { "DebugInformationFormat", "", "None", "None", 0 },
- { "DebugInformationFormat", "Z7", "C7 compatible", "OldStyle", 0 },
- { "DebugInformationFormat", "Zi", "Program Database", "ProgramDatabase", 0 },
- { "DebugInformationFormat", "ZI", "Program Database for Edit And Continue",
- "EditAndContinue", 0 },
-
- { "WarningLevel", "W0", "Turn Off All Warnings", "TurnOffAllWarnings", 0 },
- { "WarningLevel", "W1", "Level1", "Level1", 0 },
- { "WarningLevel", "W2", "Level2", "Level2", 0 },
- { "WarningLevel", "W3", "Level3", "Level3", 0 },
- { "WarningLevel", "W4", "Level4", "Level4", 0 },
- { "WarningLevel", "Wall", "EnableAllWarnings", "EnableAllWarnings", 0 },
-
- { "Optimization", "Od", "Disabled", "Disabled", 0 },
- { "Optimization", "O1", "Minimize Size", "MinSpace", 0 },
- { "Optimization", "O2", "Maximize Speed", "MaxSpeed", 0 },
- { "Optimization", "Ox", "Full Optimization", "Full", 0 },
-
- { "InlineFunctionExpansion", "", "Default", "Default", 0 },
- { "InlineFunctionExpansion", "Ob0", "Disabled", "Disabled", 0 },
- { "InlineFunctionExpansion", "Ob1", "Only __inline", "OnlyExplicitInline",
- 0 },
- { "InlineFunctionExpansion", "Ob2", "Any Suitable", "AnySuitable", 0 },
-
- { "FavorSizeOrSpeed", "Os", "Favor small code", "Size", 0 },
- { "FavorSizeOrSpeed", "Ot", "Favor fast code", "Speed", 0 },
- { "FavorSizeOrSpeed", "", "Neither", "Neither", 0 },
-
- { "ExceptionHandling", "EHa", "Yes with SEH Exceptions", "Async", 0 },
- { "ExceptionHandling", "EHsc", "Yes", "Sync", 0 },
- { "ExceptionHandling", "EHs", "Yes with Extern C functions", "SyncCThrow",
- 0 },
- { "ExceptionHandling", "", "No", "false", 0 },
-
- { "BasicRuntimeChecks", "RTCs", "Stack Frames", "StackFrameRuntimeCheck",
- 0 },
- { "BasicRuntimeChecks", "RTCu", "Uninitialized variables",
- "UninitializedLocalUsageCheck", 0 },
- { "BasicRuntimeChecks", "RTC1", "Both (/RTC1, equiv. to /RTCsu)",
- "EnableFastChecks", 0 },
- { "BasicRuntimeChecks", "", "Default", "Default", 0 },
-
- { "RuntimeLibrary", "MT", "Multi-threaded", "MultiThreaded", 0 },
- { "RuntimeLibrary", "MTd", "Multi-threaded Debug", "MultiThreadedDebug", 0 },
- { "RuntimeLibrary", "MD", "Multi-threaded DLL", "MultiThreadedDLL", 0 },
- { "RuntimeLibrary", "MDd", "Multi-threaded Debug DLL",
- "MultiThreadedDebugDLL", 0 },
-
- { "StructMemberAlignment", "Zp1", "1 Byte", "1Byte", 0 },
- { "StructMemberAlignment", "Zp2", "2 Bytes", "2Bytes", 0 },
- { "StructMemberAlignment", "Zp4", "4 Byte", "4Bytes", 0 },
- { "StructMemberAlignment", "Zp8", "8 Bytes", "8Bytes", 0 },
- { "StructMemberAlignment", "Zp16", "16 Bytes", "16Bytes", 0 },
- { "StructMemberAlignment", "", "Default", "Default", 0 },
-
- { "EnableEnhancedInstructionSet", "arch:SSE", "Streaming SIMD Extensions",
- "StreamingSIMDExtensions", 0 },
- { "EnableEnhancedInstructionSet", "arch:SSE2", "Streaming SIMD Extensions 2",
- "StreamingSIMDExtensions2", 0 },
- { "EnableEnhancedInstructionSet", "arch:AVX", "Advanced Vector Extensions",
- "AdvancedVectorExtensions", 0 },
- { "EnableEnhancedInstructionSet", "arch:IA32", "No Enhanced Instructions",
- "NoExtensions", 0 },
- { "EnableEnhancedInstructionSet", "", "Not Set", "NotSet", 0 },
-
- { "FloatingPointModel", "fp:precise", "Precise", "Precise", 0 },
- { "FloatingPointModel", "fp:strict", "Strict", "Strict", 0 },
- { "FloatingPointModel", "fp:fast", "Fast", "Fast", 0 },
-
- { "PrecompiledHeader", "Yc", "Create", "Create",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "PrecompiledHeader", "Yu", "Use", "Use",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "PrecompiledHeader", "", "Not Using Precompiled Headers", "NotUsing", 0 },
-
- { "AssemblerOutput", "", "No Listing", "NoListing", 0 },
- { "AssemblerOutput", "FA", "Assembly-Only Listing", "AssemblyCode", 0 },
- { "AssemblerOutput", "FAc", "Assembly With Machine Code",
- "AssemblyAndMachineCode", 0 },
- { "AssemblerOutput", "FAs", "Assembly With Source Code",
- "AssemblyAndSourceCode", 0 },
- { "AssemblerOutput", "FAcs", "Assembly, Machine Code and Source", "All", 0 },
-
- { "CallingConvention", "Gd", "__cdecl", "Cdecl", 0 },
- { "CallingConvention", "Gr", "__fastcall", "FastCall", 0 },
- { "CallingConvention", "Gz", "__stdcall", "StdCall", 0 },
-
- { "CompileAs", "", "Default", "Default", 0 },
- { "CompileAs", "TC", "Compile as C Code", "CompileAsC", 0 },
- { "CompileAs", "TP", "Compile as C++ Code", "CompileAsCpp", 0 },
-
- { "ErrorReporting", "errorReport:none", "Do Not Send Report", "None", 0 },
- { "ErrorReporting", "errorReport:prompt", "Prompt Immediately", "Prompt",
- 0 },
- { "ErrorReporting", "errorReport:queue", "Queue For Next Login", "Queue",
- 0 },
- { "ErrorReporting", "errorReport:send", "Send Automatically", "Send", 0 },
-
- { "CompileAsManaged", "", "No Common Language RunTime Support", "false", 0 },
- { "CompileAsManaged", "clr", "Common Language RunTime Support", "true", 0 },
- { "CompileAsManaged", "clr:pure",
- "Pure MSIL Common Language RunTime Support", "Pure", 0 },
- { "CompileAsManaged", "clr:safe",
- "Safe MSIL Common Language RunTime Support", "Safe", 0 },
- { "CompileAsManaged", "clr:oldSyntax",
- "Common Language RunTime Support, Old Syntax", "OldSyntax", 0 },
-
- // Bool Properties
- { "CompileAsWinRT", "ZW", "", "true", 0 },
- { "WinRTNoStdLib", "ZW:nostdlib", "", "true", 0 },
- { "SuppressStartupBanner", "nologo-", "", "false", 0 },
- { "SuppressStartupBanner", "nologo", "", "true", 0 },
- { "TreatWarningAsError", "WX-", "", "false", 0 },
- { "TreatWarningAsError", "WX", "", "true", 0 },
- { "SDLCheck", "sdl-", "", "false", 0 },
- { "SDLCheck", "sdl", "", "true", 0 },
- { "IntrinsicFunctions", "Oi", "", "true", 0 },
- { "OmitFramePointers", "Oy-", "", "false", 0 },
- { "OmitFramePointers", "Oy", "", "true", 0 },
- { "EnableFiberSafeOptimizations", "GT", "", "true", 0 },
- { "WholeProgramOptimization", "GL", "", "true", 0 },
- { "UndefineAllPreprocessorDefinitions", "u", "", "true", 0 },
- { "IgnoreStandardIncludePath", "X", "", "true", 0 },
- { "PreprocessToFile", "P", "", "true", 0 },
- { "PreprocessSuppressLineNumbers", "EP", "", "true", 0 },
- { "PreprocessKeepComments", "C", "", "true", 0 },
- { "StringPooling", "GF-", "", "false", 0 },
- { "StringPooling", "GF", "", "true", 0 },
- { "MinimalRebuild", "Gm-", "", "false", 0 },
- { "MinimalRebuild", "Gm", "", "true", 0 },
- { "SmallerTypeCheck", "RTCc", "", "true", 0 },
- { "BufferSecurityCheck", "GS-", "", "false", 0 },
- { "BufferSecurityCheck", "GS", "", "true", 0 },
- { "FunctionLevelLinking", "Gy-", "", "false", 0 },
- { "FunctionLevelLinking", "Gy", "", "true", 0 },
- { "EnableParallelCodeGeneration", "Qpar-", "", "false", 0 },
- { "EnableParallelCodeGeneration", "Qpar", "", "true", 0 },
- { "FloatingPointExceptions", "fp:except-", "", "false", 0 },
- { "FloatingPointExceptions", "fp:except", "", "true", 0 },
- { "CreateHotpatchableImage", "hotpatch", "", "true", 0 },
- { "DisableLanguageExtensions", "Za", "", "true", 0 },
- { "TreatWChar_tAsBuiltInType", "Zc:wchar_t-", "", "false", 0 },
- { "TreatWChar_tAsBuiltInType", "Zc:wchar_t", "", "true", 0 },
- { "ForceConformanceInForLoopScope", "Zc:forScope-", "", "false", 0 },
- { "ForceConformanceInForLoopScope", "Zc:forScope", "", "true", 0 },
- { "RuntimeTypeInfo", "GR-", "", "false", 0 },
- { "RuntimeTypeInfo", "GR", "", "true", 0 },
- { "OpenMPSupport", "openmp-", "", "false", 0 },
- { "OpenMPSupport", "openmp", "", "true", 0 },
- { "ExpandAttributedSource", "Fx", "", "true", 0 },
- { "UseUnicodeForAssemblerListing", "FAu", "", "true", 0 },
- { "ShowIncludes", "showIncludes", "", "true", 0 },
- { "EnablePREfast", "analyze-", "", "false", 0 },
- { "EnablePREfast", "analyze", "", "true", 0 },
- { "UseFullPaths", "FC", "", "true", 0 },
- { "OmitDefaultLibName", "Zl", "", "true", 0 },
-
- // Bool Properties With Argument
- { "MultiProcessorCompilation", "MP", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "ProcessorNumber", "MP", "Multi-processor Compilation", "",
- cmVS7FlagTable::UserValueRequired },
- { "GenerateXMLDocumentationFiles", "doc", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "XMLDocumentationFileName", "doc", "Generate XML Documentation Files", "",
- cmVS7FlagTable::UserValueRequired },
- { "BrowseInformation", "FR", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "BrowseInformationFile", "FR", "Enable Browse Information", "",
- cmVS7FlagTable::UserValueRequired },
-
- // String List Properties
- { "AdditionalIncludeDirectories", "I", "Additional Include Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AdditionalUsingDirectories", "AI", "Additional #using Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "PreprocessorDefinitions", "D ", "Preprocessor Definitions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "UndefinePreprocessorDefinitions", "U",
- "Undefine Preprocessor Definitions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "DisableSpecificWarnings", "wd", "Disable Specific Warnings", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ForcedIncludeFiles", "FI", "Forced Include File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ForcedUsingFiles", "FU", "Forced #using File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "PREfastLog", "analyze:log", "Code Analysis Log", "",
- cmVS7FlagTable::UserFollowing },
- { "PREfastAdditionalPlugins", "analyze:plugin",
- "Additional Code Analysis Native plugins", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "TreatSpecificWarningsAsErrors", "we", "Treat Specific Warnings As Errors",
- "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-
- // String Properties
- // Skip [TrackerLogDirectory] - no command line Switch.
- { "PreprocessOutputPath", "Fi", "Preprocess Output Path", "",
- cmVS7FlagTable::UserValue },
- { "PrecompiledHeaderFile", "Yc", "Precompiled Header Name", "",
- cmVS7FlagTable::UserValueRequired },
- { "PrecompiledHeaderFile", "Yu", "Precompiled Header Name", "",
- cmVS7FlagTable::UserValueRequired },
- { "PrecompiledHeaderOutputFile", "Fp", "Precompiled Header Output File", "",
- cmVS7FlagTable::UserValue },
- { "AssemblerListingLocation", "Fa", "ASM List Location", "",
- cmVS7FlagTable::UserValue },
- { "ObjectFileName", "Fo", "Object File Name", "",
- cmVS7FlagTable::UserValue },
- { "ProgramDataBaseFileName", "Fd", "Program Database File Name", "",
- cmVS7FlagTable::UserValue },
- // Skip [XMLDocumentationFileName] - no command line Switch.
- // Skip [BrowseInformationFile] - no command line Switch.
- // Skip [AdditionalOptions] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS11CSharpFlagTable.h b/Source/cmVS11CSharpFlagTable.h
deleted file mode 100644
index 71870b698..000000000
--- a/Source/cmVS11CSharpFlagTable.h
+++ /dev/null
@@ -1,120 +0,0 @@
-static cmVS7FlagTable cmVS11CSharpFlagTable[] = {
- { "ProjectName", "out:", "", "", cmIDEFlagTable::UserValueRequired },
-
- { "OutputType", "target:exe", "", "Exe", 0 },
- { "OutputType", "target:winexe", "", "Winexe", 0 },
- { "OutputType", "target:library", "", "Library", 0 },
- { "OutputType", "target:module", "", "Module", 0 },
-
- { "DocumentationFile", "doc", "", "", cmIDEFlagTable::UserValueRequired },
-
- { "Platform", "platform:x86", "", "x86", 0 },
- { "Platform", "platform:Itanium", "", "Itanium", 0 },
- { "Platform", "platform:x64", "", "x64", 0 },
- { "Platform", "platform:arm", "", "arm", 0 },
- { "Platform", "platform:anycpu32bitpreferred", "", "anycpu32bitpreferred",
- 0 },
- { "Platform", "platform:anycpu", "", "anycpu", 0 },
-
- { "References", "reference:", "mit alias", "", 0 },
- { "References", "reference:", "dateiliste", "", 0 },
- { "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable },
- { "", "link", "", "", 0 },
-
- { "Win32Resource", "win32res", "", "", cmIDEFlagTable::UserValueRequired },
- { "ApplicationIcon", "win32icon", "", "",
- cmIDEFlagTable::UserValueRequired },
-
- { "Win32Manifest", "win32manifest:", "", "true", 0 },
-
- { "NoWin32Manifest", "nowin32manifest", "", "true", 0 },
-
- { "DefineDebug", "debug", "", "true", cmIDEFlagTable::Continue },
-
- { "DebugSymbols", "debug", "", "true", 0 },
- { "DebugSymbols", "debug-", "", "false", 0 },
- { "DebugSymbols", "debug+", "", "true", 0 },
-
- { "DebugType", "debug:none", "", "none", 0 },
- { "DebugType", "debug:full", "", "full", 0 },
- { "DebugType", "debug:pdbonly", "", "pdbonly", 0 },
-
- { "Optimize", "optimize", "", "true", 0 },
- { "Optimize", "optimize-", "", "false", 0 },
- { "Optimize", "optimize+", "", "true", 0 },
-
- { "TreatWarningsAsErrors", "warnaserror", "", "true", 0 },
- { "TreatWarningsAsErrors", "warnaserror-", "", "false", 0 },
- { "TreatWarningsAsErrors", "warnaserror+", "", "true", 0 },
-
- { "WarningsAsErrors", "warnaserror", "", "", 0 },
- { "WarningsAsErrors", "warnaserror-", "", "", 0 },
- { "WarningsAsErrors", "warnaserror+", "", "", 0 },
-
- { "WarningLevel", "warn:0", "", "0", 0 },
- { "WarningLevel", "warn:1", "", "1", 0 },
- { "WarningLevel", "warn:2", "", "2", 0 },
- { "WarningLevel", "warn:3", "", "3", 0 },
- { "WarningLevel", "warn:4", "", "4", 0 },
- { "DisabledWarnings", "nowarn", "", "", 0 },
-
- { "CheckForOverflowUnderflow", "checked", "", "true", 0 },
- { "CheckForOverflowUnderflow", "checked-", "", "false", 0 },
- { "CheckForOverflowUnderflow", "checked+", "", "true", 0 },
-
- { "AllowUnsafeBlocks", "unsafe", "", "true", 0 },
- { "AllowUnsafeBlocks", "unsafe-", "", "false", 0 },
- { "AllowUnsafeBlocks", "unsafe+", "", "true", 0 },
-
- { "DefineConstants", "define:", "", "",
- cmIDEFlagTable::SemicolonAppendable | cmIDEFlagTable::UserValue },
-
- { "LangVersion", "langversion:ISO-1", "", "ISO-1", 0 },
- { "LangVersion", "langversion:ISO-2", "", "ISO-2", 0 },
- { "LangVersion", "langversion:3", "", "3", 0 },
- { "LangVersion", "langversion:4", "", "4", 0 },
- { "LangVersion", "langversion:5", "", "5", 0 },
- { "LangVersion", "langversion:6", "", "6", 0 },
- { "LangVersion", "langversion:default", "", "default", 0 },
-
- { "DelaySign", "delaysign", "", "true", 0 },
- { "DelaySign", "delaysign-", "", "false", 0 },
- { "DelaySign", "delaysign+", "", "true", 0 },
-
- { "AssemblyOriginatorKeyFile", "keyfile", "", "", 0 },
-
- { "KeyContainerName", "keycontainer", "", "", 0 },
-
- { "NoLogo", "nologo", "", "", 0 },
-
- { "NoConfig", "noconfig", "", "true", 0 },
-
- { "BaseAddress", "baseaddress:", "", "", 0 },
-
- { "CodePage", "codepage", "", "", 0 },
-
- { "Utf8Output", "utf8output", "", "", 0 },
-
- { "MainEntryPoint", "main:", "", "", 0 },
-
- { "GenerateFullPaths", "fullpaths", "", "true", 0 },
-
- { "FileAlignment", "filealign", "", "", 0 },
-
- { "PdbFile", "pdb:", "", "", 0 },
-
- { "NoStandardLib", "nostdlib", "", "true", 0 },
- { "NoStandardLib", "nostdlib-", "", "false", 0 },
- { "NoStandardLib", "nostdlib+", "", "true", 0 },
-
- { "SubsystemVersion", "subsystemversion", "", "", 0 },
-
- { "AdditionalLibPaths", "lib:", "", "", 0 },
-
- { "ErrorReport", "errorreport:none", "Do Not Send Report", "none", 0 },
- { "ErrorReport", "errorreport:prompt", "Prompt Immediately", "prompt", 0 },
- { "ErrorReport", "errorreport:queue", "Queue For Next Login", "queue", 0 },
- { "ErrorReport", "errorreport:send", "Send Automatically", "send", 0 },
-
- { 0, 0, 0, 0, 0 },
-};
diff --git a/Source/cmVS11LibFlagTable.h b/Source/cmVS11LibFlagTable.h
deleted file mode 100644
index 8aacaacd3..000000000
--- a/Source/cmVS11LibFlagTable.h
+++ /dev/null
@@ -1,76 +0,0 @@
-static cmVS7FlagTable cmVS11LibFlagTable[] = {
-
- // Enum Properties
- { "ErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately",
- "PromptImmediately", 0 },
- { "ErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login",
- "QueueForNextLogin", 0 },
- { "ErrorReporting", "ERRORREPORT:SEND", "Send Error Report",
- "SendErrorReport", 0 },
- { "ErrorReporting", "ERRORREPORT:NONE", "No Error Report", "NoErrorReport",
- 0 },
-
- { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 },
- { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 },
- { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 },
- { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 },
- { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 },
- { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU",
- 0 },
- { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16",
- "MachineMIPSFPU16", 0 },
- { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 },
- { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 },
- { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 },
- { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 },
-
- { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 },
- { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 },
- { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application",
- "EFI Application", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER",
- "EFI Boot Service Driver", "EFI Boot Service Driver", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime",
- 0 },
- { "SubSystem", "SUBSYSTEM:WINDOWSCE", "WindowsCE", "WindowsCE", 0 },
- { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 },
-
- // Bool Properties
- { "SuppressStartupBanner", "NOLOGO", "", "true", 0 },
- { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 },
- { "TreatLibWarningAsErrors", "WX:NO", "", "false", 0 },
- { "TreatLibWarningAsErrors", "WX", "", "true", 0 },
- { "Verbose", "VERBOSE", "", "true", 0 },
- { "LinkTimeCodeGeneration", "LTCG", "", "true", 0 },
-
- // Bool Properties With Argument
-
- // String List Properties
- // Skip [AdditionalDependencies] - no command line Switch.
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ExportNamedFunctions", "EXPORT:", "Export Named Functions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "RemoveObjects", "REMOVE:", "Remove Objects", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-
- // String Properties
- { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue },
- { "ModuleDefinitionFile", "DEF:", "Module Definition File Name", "",
- cmVS7FlagTable::UserValue },
- { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "",
- cmVS7FlagTable::UserValue },
- { "DisplayLibrary", "LIST:", "Display Library to standard output", "",
- cmVS7FlagTable::UserValue },
- // Skip [MinimumRequiredVersion] - no command line Switch.
- { "Name", "NAME:", "Name", "", cmVS7FlagTable::UserValue },
- // Skip [AdditionalOptions] - no command line Switch.
- // Skip [TrackerLogDirectory] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS11LinkFlagTable.h b/Source/cmVS11LinkFlagTable.h
deleted file mode 100644
index 1b3a046f6..000000000
--- a/Source/cmVS11LinkFlagTable.h
+++ /dev/null
@@ -1,269 +0,0 @@
-static cmVS7FlagTable cmVS11LinkFlagTable[] = {
-
- // Enum Properties
- { "ShowProgress", "", "Not Set", "NotSet", 0 },
- { "ShowProgress", "VERBOSE", "Display all progress messages", "LinkVerbose",
- 0 },
- { "ShowProgress", "VERBOSE:Lib", "For Libraries Searched", "LinkVerboseLib",
- 0 },
- { "ShowProgress", "VERBOSE:ICF",
- "About COMDAT folding during optimized linking", "LinkVerboseICF", 0 },
- { "ShowProgress", "VERBOSE:REF",
- "About data removed during optimized linking", "LinkVerboseREF", 0 },
- { "ShowProgress", "VERBOSE:SAFESEH", "About Modules incompatible with SEH",
- "LinkVerboseSAFESEH", 0 },
- { "ShowProgress", "VERBOSE:CLR",
- "About linker activity related to managed code", "LinkVerboseCLR", 0 },
-
- { "ForceFileOutput", "FORCE", "Enabled", "Enabled", 0 },
- { "ForceFileOutput", "FORCE:MULTIPLE", "Multiply Defined Symbol Only",
- "MultiplyDefinedSymbolOnly", 0 },
- { "ForceFileOutput", "FORCE:UNRESOLVED", "Undefined Symbol Only",
- "UndefinedSymbolOnly", 0 },
-
- { "CreateHotPatchableImage", "FUNCTIONPADMIN", "Enabled", "Enabled", 0 },
- { "CreateHotPatchableImage", "FUNCTIONPADMIN:5", "X86 Image Only",
- "X86Image", 0 },
- { "CreateHotPatchableImage", "FUNCTIONPADMIN:6", "X64 Image Only",
- "X64Image", 0 },
- { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only",
- "ItaniumImage", 0 },
-
- { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 },
- { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable",
- "HighestAvailable", 0 },
- { "UACExecutionLevel", "level='requireAdministrator'",
- "requireAdministrator", "RequireAdministrator", 0 },
-
- { "SubSystem", "", "Not Set", "NotSet", 0 },
- { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 },
- { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 },
- { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application",
- "EFI Application", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER",
- "EFI Boot Service Driver", "EFI Boot Service Driver", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime",
- 0 },
- { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 },
-
- { "Driver", "", "Not Set", "NotSet", 0 },
- { "Driver", "Driver", "Driver", "Driver", 0 },
- { "Driver", "DRIVER:UPONLY", "UP Only", "UpOnly", 0 },
- { "Driver", "DRIVER:WDM", "WDM", "WDM", 0 },
-
- { "LinkTimeCodeGeneration", "", "Default", "Default", 0 },
- { "LinkTimeCodeGeneration", "LTCG", "Use Link Time Code Generation",
- "UseLinkTimeCodeGeneration", 0 },
- { "LinkTimeCodeGeneration", "LTCG:PGInstrument",
- "Profile Guided Optimization - Instrument", "PGInstrument", 0 },
- { "LinkTimeCodeGeneration", "LTCG:PGOptimize",
- "Profile Guided Optimization - Optimization", "PGOptimization", 0 },
- { "LinkTimeCodeGeneration", "LTCG:PGUpdate",
- "Profile Guided Optimization - Update", "PGUpdate", 0 },
-
- { "GenerateWindowsMetadata", "WINMD", "Yes", "true", 0 },
- { "GenerateWindowsMetadata", "WINMD:NO", "No", "false", 0 },
-
- { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA1", "SHA1", "SHA1", 0 },
- { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA256", "SHA256", "SHA256", 0 },
- { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA384", "SHA384", "SHA384", 0 },
- { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA512", "SHA512", "SHA512", 0 },
-
- { "TargetMachine", "", "Not Set", "NotSet", 0 },
- { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 },
- { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 },
- { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 },
- { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 },
- { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 },
- { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU",
- 0 },
- { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16",
- "MachineMIPSFPU16", 0 },
- { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 },
- { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 },
- { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 },
- { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 },
-
- { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:MTA", "MTA threading attribute",
- "MTAThreadingAttribute", 0 },
- { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:STA", "STA threading attribute",
- "STAThreadingAttribute", 0 },
- { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:NONE",
- "Default threading attribute", "DefaultThreadingAttribute", 0 },
-
- { "CLRImageType", "CLRIMAGETYPE:IJW", "Force IJW image", "ForceIJWImage",
- 0 },
- { "CLRImageType", "CLRIMAGETYPE:PURE", "Force Pure IL Image",
- "ForcePureILImage", 0 },
- { "CLRImageType", "CLRIMAGETYPE:SAFE", "Force Safe IL Image",
- "ForceSafeILImage", 0 },
- { "CLRImageType", "", "Default image type", "Default", 0 },
-
- { "SignHash", "CLRSIGNHASH:SHA1", "SHA1", "SHA1", 0 },
- { "SignHash", "CLRSIGNHASH:SHA256", "SHA256", "SHA256", 0 },
- { "SignHash", "CLRSIGNHASH:SHA384", "SHA384", "SHA384", 0 },
- { "SignHash", "CLRSIGNHASH:SHA512", "SHA512", "SHA512", 0 },
-
- { "LinkErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately",
- "PromptImmediately", 0 },
- { "LinkErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login",
- "QueueForNextLogin", 0 },
- { "LinkErrorReporting", "ERRORREPORT:SEND", "Send Error Report",
- "SendErrorReport", 0 },
- { "LinkErrorReporting", "ERRORREPORT:NONE", "No Error Report",
- "NoErrorReport", 0 },
-
- { "CLRSupportLastError", "CLRSupportLastError", "Enabled", "Enabled", 0 },
- { "CLRSupportLastError", "CLRSupportLastError:NO", "Disabled", "Disabled",
- 0 },
- { "CLRSupportLastError", "CLRSupportLastError:SYSTEMDLL", "System Dlls Only",
- "SystemDlls", 0 },
-
- // Bool Properties
- { "LinkIncremental", "INCREMENTAL:NO", "", "false", 0 },
- { "LinkIncremental", "INCREMENTAL", "", "true", 0 },
- { "SuppressStartupBanner", "NOLOGO", "", "true", 0 },
- { "LinkStatus", "LTCG:NOSTATUS", "", "false", 0 },
- { "LinkStatus", "LTCG:STATUS", "", "true", 0 },
- { "PreventDllBinding", "ALLOWBIND:NO", "", "false", 0 },
- { "PreventDllBinding", "ALLOWBIND", "", "true", 0 },
- { "TreatLinkerWarningAsErrors", "WX:NO", "", "false", 0 },
- { "TreatLinkerWarningAsErrors", "WX", "", "true", 0 },
- { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 },
- { "GenerateManifest", "MANIFEST:NO", "", "false", 0 },
- { "GenerateManifest", "MANIFEST", "", "true", 0 },
- { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 },
- { "UACUIAccess", "uiAccess='false'", "", "false", 0 },
- { "UACUIAccess", "uiAccess='true'", "", "true", 0 },
- { "ManifestEmbed", "manifest:embed", "", "true", 0 },
- { "GenerateDebugInformation", "DEBUG", "", "true",
- cmVS7FlagTable::CaseInsensitive },
- { "MapExports", "MAPINFO:EXPORTS", "", "true", 0 },
- { "AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0 },
- { "AssemblyDebug", "ASSEMBLYDEBUG", "", "true", 0 },
- { "LargeAddressAware", "LARGEADDRESSAWARE:NO", "", "false", 0 },
- { "LargeAddressAware", "LARGEADDRESSAWARE", "", "true", 0 },
- { "TerminalServerAware", "TSAWARE:NO", "", "false", 0 },
- { "TerminalServerAware", "TSAWARE", "", "true", 0 },
- { "SwapRunFromCD", "SWAPRUN:CD", "", "true", 0 },
- { "SwapRunFromNET", "SWAPRUN:NET", "", "true", 0 },
- { "OptimizeReferences", "OPT:NOREF", "", "false", 0 },
- { "OptimizeReferences", "OPT:REF", "", "true", 0 },
- { "EnableCOMDATFolding", "OPT:NOICF", "", "false", 0 },
- { "EnableCOMDATFolding", "OPT:ICF", "", "true", 0 },
- { "IgnoreEmbeddedIDL", "IGNOREIDL", "", "true", 0 },
- { "AppContainer", "APPCONTAINER", "", "true", 0 },
- { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN:NO", "", "false", 0 },
- { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN", "", "true", 0 },
- { "NoEntryPoint", "NOENTRY", "", "true", 0 },
- { "SetChecksum", "RELEASE", "", "true", 0 },
- { "RandomizedBaseAddress", "DYNAMICBASE:NO", "", "false", 0 },
- { "RandomizedBaseAddress", "DYNAMICBASE", "", "true", 0 },
- { "FixedBaseAddress", "FIXED:NO", "", "false", 0 },
- { "FixedBaseAddress", "FIXED", "", "true", 0 },
- { "DataExecutionPrevention", "NXCOMPAT:NO", "", "false", 0 },
- { "DataExecutionPrevention", "NXCOMPAT", "", "true", 0 },
- { "TurnOffAssemblyGeneration", "NOASSEMBLY", "", "true", 0 },
- { "SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0 },
- { "SupportNobindOfDelayLoadedDLL", "DELAY:NOBIND", "", "true", 0 },
- { "Profile", "PROFILE", "", "true", 0 },
- { "LinkDelaySign", "DELAYSIGN:NO", "", "false", 0 },
- { "LinkDelaySign", "DELAYSIGN", "", "true", 0 },
- { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0 },
- { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0 },
- { "DetectOneDefinitionRule", "ODR", "", "true", 0 },
- { "ImageHasSafeExceptionHandlers", "SAFESEH:NO", "", "false", 0 },
- { "ImageHasSafeExceptionHandlers", "SAFESEH", "", "true", 0 },
- { "LinkDLL", "DLL", "", "true", 0 },
-
- // Bool Properties With Argument
- { "EnableUAC", "MANIFESTUAC:NO", "", "false", 0 },
- { "EnableUAC", "MANIFESTUAC:", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "UACUIAccess", "MANIFESTUAC:", "Enable User Account Control (UAC)", "",
- cmVS7FlagTable::UserValueRequired },
- { "GenerateMapFile", "MAP", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "MapFileName", "MAP:", "Generate Map File", "",
- cmVS7FlagTable::UserValueRequired },
-
- // String List Properties
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- // Skip [AdditionalDependencies] - no command line Switch.
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly",
- "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "EmbedManagedResourceFile", "ASSEMBLYRESOURCE:",
- "Embed Managed Resource File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "DelayLoadDLLs", "DELAYLOAD:", "Delay Loaded Dlls", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource",
- "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AdditionalManifestDependencies", "MANIFESTDEPENDENCY:",
- "Additional Manifest Dependencies", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ManifestInput", "manifestinput:", "Manifest Input", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-
- // String Properties
- { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue },
- { "Version", "VERSION:", "Version", "", cmVS7FlagTable::UserValue },
- { "SpecifySectionAttributes", "SECTION:", "Specify Section Attributes", "",
- cmVS7FlagTable::UserValue },
- { "MSDOSStubFileName", "STUB:", "MS-DOS Stub File Name", "",
- cmVS7FlagTable::UserValue },
- // Skip [TrackerLogDirectory] - no command line Switch.
- { "ModuleDefinitionFile", "DEF:", "Module Definition File", "",
- cmVS7FlagTable::UserValue },
- { "ManifestFile", "ManifestFile:", "Manifest File", "",
- cmVS7FlagTable::UserValue },
- { "ProgramDatabaseFile", "PDB:", "Generate Program Database File", "",
- cmVS7FlagTable::UserValue },
- { "StripPrivateSymbols", "PDBSTRIPPED:", "Strip Private Symbols", "",
- cmVS7FlagTable::UserValue },
- // Skip [MapFileName] - no command line Switch.
- // Skip [MinimumRequiredVersion] - no command line Switch.
- { "HeapReserveSize", "HEAP:", "Heap Reserve Size", "",
- cmVS7FlagTable::UserValue },
- // Skip [HeapCommitSize] - no command line Switch.
- { "StackReserveSize", "STACK:", "Stack Reserve Size", "",
- cmVS7FlagTable::UserValue },
- // Skip [StackCommitSize] - no command line Switch.
- { "FunctionOrder", "ORDER:@", "Function Order", "",
- cmVS7FlagTable::UserValue },
- { "ProfileGuidedDatabase", "PGD:", "Profile Guided Database", "",
- cmVS7FlagTable::UserValue },
- { "MidlCommandFile", "MIDL:@", "MIDL Commands", "",
- cmVS7FlagTable::UserValue },
- { "MergedIDLBaseFileName", "IDLOUT:", "Merged IDL Base File Name", "",
- cmVS7FlagTable::UserValue },
- { "TypeLibraryFile", "TLBOUT:", "Type Library", "",
- cmVS7FlagTable::UserValue },
- { "WindowsMetadataFile", "WINMDFILE:", "Windows Metadata File", "",
- cmVS7FlagTable::UserValue },
- { "WindowsMetadataLinkKeyFile", "WINMDKEYFILE:", "Windows Metadata Key File",
- "", cmVS7FlagTable::UserValue },
- { "WindowsMetadataKeyContainer", "WINMDKEYCONTAINER:",
- "Windows Metadata Key Container", "", cmVS7FlagTable::UserValue },
- { "EntryPointSymbol", "ENTRY:", "Entry Point", "",
- cmVS7FlagTable::UserValue },
- { "BaseAddress", "BASE:", "Base Address", "", cmVS7FlagTable::UserValue },
- { "ImportLibrary", "IMPLIB:", "Import Library", "",
- cmVS7FlagTable::UserValue },
- { "MergeSections", "MERGE:", "Merge Sections", "",
- cmVS7FlagTable::UserValue },
- { "LinkKeyFile", "KEYFILE:", "Key File", "", cmVS7FlagTable::UserValue },
- { "KeyContainer", "KEYCONTAINER:", "Key Container", "",
- cmVS7FlagTable::UserValue },
- // Skip [AdditionalOptions] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS11MASMFlagTable.h b/Source/cmVS11MASMFlagTable.h
deleted file mode 100644
index fdf8239da..000000000
--- a/Source/cmVS11MASMFlagTable.h
+++ /dev/null
@@ -1,76 +0,0 @@
-static cmVS7FlagTable cmVS11MASMFlagTable[] = {
-
- // Enum Properties
- { "PreserveIdentifierCase", "", "Default", "0", 0 },
- { "PreserveIdentifierCase", "Cp", "Preserves Identifier Case (/Cp)", "1",
- 0 },
- { "PreserveIdentifierCase", "Cu",
- "Maps all identifiers to upper case. (/Cu)", "2", 0 },
- { "PreserveIdentifierCase", "Cx",
- "Preserves case in public and extern symbols. (/Cx)", "3", 0 },
-
- { "WarningLevel", "W0", "Warning Level 0 (/W0)", "0", 0 },
- { "WarningLevel", "W1", "Warning Level 1 (/W1)", "1", 0 },
- { "WarningLevel", "W2", "Warning Level 2 (/W2)", "2", 0 },
- { "WarningLevel", "W3", "Warning Level 3 (/W3)", "3", 0 },
-
- { "PackAlignmentBoundary", "", "Default", "0", 0 },
- { "PackAlignmentBoundary", "Zp1", "One Byte Boundary (/Zp1)", "1", 0 },
- { "PackAlignmentBoundary", "Zp2", "Two Byte Boundary (/Zp2)", "2", 0 },
- { "PackAlignmentBoundary", "Zp4", "Four Byte Boundary (/Zp4)", "3", 0 },
- { "PackAlignmentBoundary", "Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 },
- { "PackAlignmentBoundary", "Zp16", "Sixteen Byte Boundary (/Zp16)", "5", 0 },
-
- { "CallingConvention", "", "Default", "0", 0 },
- { "CallingConvention", "Gd", "Use C-style Calling Convention (/Gd)", "1",
- 0 },
- { "CallingConvention", "Gz", "Use stdcall Calling Convention (/Gz)", "2",
- 0 },
- { "CallingConvention", "Gc", "Use Pascal Calling Convention (/Gc)", "3", 0 },
-
- { "ErrorReporting", "errorReport:prompt",
- "Prompt to send report immediately (/errorReport:prompt)", "0", 0 },
- { "ErrorReporting", "errorReport:queue",
- "Prompt to send report at the next logon (/errorReport:queue)", "1", 0 },
- { "ErrorReporting", "errorReport:send",
- "Automatically send report (/errorReport:send)", "2", 0 },
- { "ErrorReporting", "errorReport:none",
- "Do not send report (/errorReport:none)", "3", 0 },
-
- // Bool Properties
- { "NoLogo", "nologo", "", "true", 0 },
- { "GeneratePreprocessedSourceListing", "EP", "", "true", 0 },
- { "ListAllAvailableInformation", "Sa", "", "true", 0 },
- { "UseSafeExceptionHandlers", "safeseh", "", "true", 0 },
- { "AddFirstPassListing", "Sf", "", "true", 0 },
- { "EnableAssemblyGeneratedCodeListing", "Sg", "", "true", 0 },
- { "DisableSymbolTable", "Sn", "", "true", 0 },
- { "EnableFalseConditionalsInListing", "Sx", "", "true", 0 },
- { "TreatWarningsAsErrors", "WX", "", "true", 0 },
- { "MakeAllSymbolsPublic", "Zf", "", "true", 0 },
- { "GenerateDebugInformation", "Zi", "", "true", 0 },
- { "EnableMASM51Compatibility", "Zm", "", "true", 0 },
- { "PerformSyntaxCheckOnly", "Zs", "", "true", 0 },
-
- // Bool Properties With Argument
-
- // String List Properties
- { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "IncludePaths", "I", "Include Paths", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "BrowseFile", "FR", "Generate Browse Information File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- // Skip [AdditionalDependencies] - no command line Switch.
-
- // String Properties
- // Skip [Inputs] - no command line Switch.
- { "ObjectFileName", "Fo", "Object File Name", "",
- cmVS7FlagTable::UserValue },
- { "AssembledCodeListingFile", "Fl", "Assembled Code Listing File", "",
- cmVS7FlagTable::UserValue },
- // Skip [CommandLineTemplate] - no command line Switch.
- // Skip [ExecutionDescription] - no command line Switch.
- // Skip [AdditionalOptions] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS11RCFlagTable.h b/Source/cmVS11RCFlagTable.h
deleted file mode 100644
index 4997fe115..000000000
--- a/Source/cmVS11RCFlagTable.h
+++ /dev/null
@@ -1,7 +0,0 @@
-static cmVS7FlagTable cmVS11RCFlagTable[] = {
- // Bool Properties
- { "NullTerminateStrings", "n", "", "true", 0 },
- { "SuppressStartupBanner", "nologo", "", "true", 0 },
-
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS12CLFlagTable.h b/Source/cmVS12CLFlagTable.h
deleted file mode 100644
index 9515c91b8..000000000
--- a/Source/cmVS12CLFlagTable.h
+++ /dev/null
@@ -1,221 +0,0 @@
-static cmVS7FlagTable cmVS12CLFlagTable[] = {
-
- // Enum Properties
- { "DebugInformationFormat", "", "None", "None", 0 },
- { "DebugInformationFormat", "Z7", "C7 compatible", "OldStyle", 0 },
- { "DebugInformationFormat", "Zi", "Program Database", "ProgramDatabase", 0 },
- { "DebugInformationFormat", "ZI", "Program Database for Edit And Continue",
- "EditAndContinue", 0 },
-
- { "WarningLevel", "W0", "Turn Off All Warnings", "TurnOffAllWarnings", 0 },
- { "WarningLevel", "W1", "Level1", "Level1", 0 },
- { "WarningLevel", "W2", "Level2", "Level2", 0 },
- { "WarningLevel", "W3", "Level3", "Level3", 0 },
- { "WarningLevel", "W4", "Level4", "Level4", 0 },
- { "WarningLevel", "Wall", "EnableAllWarnings", "EnableAllWarnings", 0 },
-
- { "Optimization", "", "Custom", "Custom", 0 },
- { "Optimization", "Od", "Disabled", "Disabled", 0 },
- { "Optimization", "O1", "Minimize Size", "MinSpace", 0 },
- { "Optimization", "O2", "Maximize Speed", "MaxSpeed", 0 },
- { "Optimization", "Ox", "Full Optimization", "Full", 0 },
-
- { "InlineFunctionExpansion", "", "Default", "Default", 0 },
- { "InlineFunctionExpansion", "Ob0", "Disabled", "Disabled", 0 },
- { "InlineFunctionExpansion", "Ob1", "Only __inline", "OnlyExplicitInline",
- 0 },
- { "InlineFunctionExpansion", "Ob2", "Any Suitable", "AnySuitable", 0 },
-
- { "FavorSizeOrSpeed", "Os", "Favor small code", "Size", 0 },
- { "FavorSizeOrSpeed", "Ot", "Favor fast code", "Speed", 0 },
- { "FavorSizeOrSpeed", "", "Neither", "Neither", 0 },
-
- { "ExceptionHandling", "EHa", "Yes with SEH Exceptions", "Async", 0 },
- { "ExceptionHandling", "EHsc", "Yes", "Sync", 0 },
- { "ExceptionHandling", "EHs", "Yes with Extern C functions", "SyncCThrow",
- 0 },
- { "ExceptionHandling", "", "No", "false", 0 },
-
- { "BasicRuntimeChecks", "RTCs", "Stack Frames", "StackFrameRuntimeCheck",
- 0 },
- { "BasicRuntimeChecks", "RTCu", "Uninitialized variables",
- "UninitializedLocalUsageCheck", 0 },
- { "BasicRuntimeChecks", "RTC1", "Both (/RTC1, equiv. to /RTCsu)",
- "EnableFastChecks", 0 },
- { "BasicRuntimeChecks", "", "Default", "Default", 0 },
-
- { "RuntimeLibrary", "MT", "Multi-threaded", "MultiThreaded", 0 },
- { "RuntimeLibrary", "MTd", "Multi-threaded Debug", "MultiThreadedDebug", 0 },
- { "RuntimeLibrary", "MD", "Multi-threaded DLL", "MultiThreadedDLL", 0 },
- { "RuntimeLibrary", "MDd", "Multi-threaded Debug DLL",
- "MultiThreadedDebugDLL", 0 },
-
- { "StructMemberAlignment", "Zp1", "1 Byte", "1Byte", 0 },
- { "StructMemberAlignment", "Zp2", "2 Bytes", "2Bytes", 0 },
- { "StructMemberAlignment", "Zp4", "4 Byte", "4Bytes", 0 },
- { "StructMemberAlignment", "Zp8", "8 Bytes", "8Bytes", 0 },
- { "StructMemberAlignment", "Zp16", "16 Bytes", "16Bytes", 0 },
- { "StructMemberAlignment", "", "Default", "Default", 0 },
-
- { "BufferSecurityCheck", "GS-", "Disable Security Check", "false", 0 },
- { "BufferSecurityCheck", "GS", "Enable Security Check", "true", 0 },
-
- { "EnableEnhancedInstructionSet", "arch:SSE", "Streaming SIMD Extensions",
- "StreamingSIMDExtensions", 0 },
- { "EnableEnhancedInstructionSet", "arch:SSE2", "Streaming SIMD Extensions 2",
- "StreamingSIMDExtensions2", 0 },
- { "EnableEnhancedInstructionSet", "arch:AVX", "Advanced Vector Extensions",
- "AdvancedVectorExtensions", 0 },
- { "EnableEnhancedInstructionSet", "arch:IA32", "No Enhanced Instructions",
- "NoExtensions", 0 },
- { "EnableEnhancedInstructionSet", "", "Not Set", "NotSet", 0 },
-
- { "FloatingPointModel", "fp:precise", "Precise", "Precise", 0 },
- { "FloatingPointModel", "fp:strict", "Strict", "Strict", 0 },
- { "FloatingPointModel", "fp:fast", "Fast", "Fast", 0 },
-
- { "PrecompiledHeader", "Yc", "Create", "Create",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "PrecompiledHeader", "Yu", "Use", "Use",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "PrecompiledHeader", "", "Not Using Precompiled Headers", "NotUsing", 0 },
-
- { "AssemblerOutput", "", "No Listing", "NoListing", 0 },
- { "AssemblerOutput", "FA", "Assembly-Only Listing", "AssemblyCode", 0 },
- { "AssemblerOutput", "FAc", "Assembly With Machine Code",
- "AssemblyAndMachineCode", 0 },
- { "AssemblerOutput", "FAs", "Assembly With Source Code",
- "AssemblyAndSourceCode", 0 },
- { "AssemblerOutput", "FAcs", "Assembly, Machine Code and Source", "All", 0 },
-
- { "CallingConvention", "Gd", "__cdecl", "Cdecl", 0 },
- { "CallingConvention", "Gr", "__fastcall", "FastCall", 0 },
- { "CallingConvention", "Gz", "__stdcall", "StdCall", 0 },
- { "CallingConvention", "Gv", "__vectorcall", "VectorCall", 0 },
-
- { "CompileAs", "", "Default", "Default", 0 },
- { "CompileAs", "TC", "Compile as C Code", "CompileAsC", 0 },
- { "CompileAs", "TP", "Compile as C++ Code", "CompileAsCpp", 0 },
-
- { "ErrorReporting", "errorReport:none", "Do Not Send Report", "None", 0 },
- { "ErrorReporting", "errorReport:prompt", "Prompt Immediately", "Prompt",
- 0 },
- { "ErrorReporting", "errorReport:queue", "Queue For Next Login", "Queue",
- 0 },
- { "ErrorReporting", "errorReport:send", "Send Automatically", "Send", 0 },
-
- { "CompileAsManaged", "", "No Common Language RunTime Support", "false", 0 },
- { "CompileAsManaged", "clr", "Common Language RunTime Support", "true", 0 },
- { "CompileAsManaged", "clr:pure",
- "Pure MSIL Common Language RunTime Support", "Pure", 0 },
- { "CompileAsManaged", "clr:safe",
- "Safe MSIL Common Language RunTime Support", "Safe", 0 },
- { "CompileAsManaged", "clr:oldSyntax",
- "Common Language RunTime Support, Old Syntax", "OldSyntax", 0 },
-
- // Bool Properties
- { "CompileAsWinRT", "ZW", "", "true", 0 },
- { "WinRTNoStdLib", "ZW:nostdlib", "", "true", 0 },
- { "SuppressStartupBanner", "nologo", "", "true", 0 },
- { "TreatWarningAsError", "WX-", "", "false", 0 },
- { "TreatWarningAsError", "WX", "", "true", 0 },
- { "SDLCheck", "sdl-", "", "false", 0 },
- { "SDLCheck", "sdl", "", "true", 0 },
- { "IntrinsicFunctions", "Oi", "", "true", 0 },
- { "OmitFramePointers", "Oy-", "", "false", 0 },
- { "OmitFramePointers", "Oy", "", "true", 0 },
- { "EnableFiberSafeOptimizations", "GT", "", "true", 0 },
- { "WholeProgramOptimization", "GL", "", "true", 0 },
- { "UndefineAllPreprocessorDefinitions", "u", "", "true", 0 },
- { "IgnoreStandardIncludePath", "X", "", "true", 0 },
- { "PreprocessToFile", "P", "", "true", 0 },
- { "PreprocessSuppressLineNumbers", "EP", "", "true", 0 },
- { "PreprocessKeepComments", "C", "", "true", 0 },
- { "StringPooling", "GF-", "", "false", 0 },
- { "StringPooling", "GF", "", "true", 0 },
- { "MinimalRebuild", "Gm-", "", "false", 0 },
- { "MinimalRebuild", "Gm", "", "true", 0 },
- { "SmallerTypeCheck", "RTCc", "", "true", 0 },
- { "FunctionLevelLinking", "Gy-", "", "false", 0 },
- { "FunctionLevelLinking", "Gy", "", "true", 0 },
- { "EnableParallelCodeGeneration", "Qpar-", "", "false", 0 },
- { "EnableParallelCodeGeneration", "Qpar", "", "true", 0 },
- { "FloatingPointExceptions", "fp:except-", "", "false", 0 },
- { "FloatingPointExceptions", "fp:except", "", "true", 0 },
- { "CreateHotpatchableImage", "hotpatch", "", "true", 0 },
- { "DisableLanguageExtensions", "Za", "", "true", 0 },
- { "TreatWChar_tAsBuiltInType", "Zc:wchar_t-", "", "false", 0 },
- { "TreatWChar_tAsBuiltInType", "Zc:wchar_t", "", "true", 0 },
- { "ForceConformanceInForLoopScope", "Zc:forScope-", "", "false", 0 },
- { "ForceConformanceInForLoopScope", "Zc:forScope", "", "true", 0 },
- { "RuntimeTypeInfo", "GR-", "", "false", 0 },
- { "RuntimeTypeInfo", "GR", "", "true", 0 },
- { "OpenMPSupport", "openmp-", "", "false", 0 },
- { "OpenMPSupport", "openmp", "", "true", 0 },
- { "ExpandAttributedSource", "Fx", "", "true", 0 },
- { "UseUnicodeForAssemblerListing", "FAu", "", "true", 0 },
- { "ShowIncludes", "showIncludes", "", "true", 0 },
- { "EnablePREfast", "analyze-", "", "false", 0 },
- { "EnablePREfast", "analyze", "", "true", 0 },
- { "UseFullPaths", "FC", "", "true", 0 },
- { "OmitDefaultLibName", "Zl", "", "true", 0 },
-
- // Bool Properties With Argument
- { "MultiProcessorCompilation", "MP", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "ProcessorNumber", "MP", "Multi-processor Compilation", "",
- cmVS7FlagTable::UserValueRequired },
- { "GenerateXMLDocumentationFiles", "doc", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "XMLDocumentationFileName", "doc", "Generate XML Documentation Files", "",
- cmVS7FlagTable::UserValueRequired },
- { "BrowseInformation", "FR", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "BrowseInformationFile", "FR", "Enable Browse Information", "",
- cmVS7FlagTable::UserValueRequired },
-
- // String List Properties
- { "AdditionalIncludeDirectories", "I", "Additional Include Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AdditionalUsingDirectories", "AI", "Additional #using Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "PreprocessorDefinitions", "D ", "Preprocessor Definitions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "UndefinePreprocessorDefinitions", "U",
- "Undefine Preprocessor Definitions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "DisableSpecificWarnings", "wd", "Disable Specific Warnings", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ForcedIncludeFiles", "FI", "Forced Include File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ForcedUsingFiles", "FU", "Forced #using File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "PREfastLog", "analyze:log", "Code Analysis Log", "",
- cmVS7FlagTable::UserFollowing },
- { "PREfastAdditionalPlugins", "analyze:plugin",
- "Additional Code Analysis Native plugins", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "TreatSpecificWarningsAsErrors", "we", "Treat Specific Warnings As Errors",
- "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-
- // String Properties
- // Skip [TrackerLogDirectory] - no command line Switch.
- { "PreprocessOutputPath", "Fi", "Preprocess Output Path", "",
- cmVS7FlagTable::UserValue },
- { "PrecompiledHeaderFile", "Yc", "Precompiled Header Name", "",
- cmVS7FlagTable::UserValueRequired },
- { "PrecompiledHeaderFile", "Yu", "Precompiled Header Name", "",
- cmVS7FlagTable::UserValueRequired },
- { "PrecompiledHeaderOutputFile", "Fp", "Precompiled Header Output File", "",
- cmVS7FlagTable::UserValue },
- { "AssemblerListingLocation", "Fa", "ASM List Location", "",
- cmVS7FlagTable::UserValue },
- { "ObjectFileName", "Fo", "Object File Name", "",
- cmVS7FlagTable::UserValue },
- { "ProgramDataBaseFileName", "Fd", "Program Database File Name", "",
- cmVS7FlagTable::UserValue },
- // Skip [XMLDocumentationFileName] - no command line Switch.
- // Skip [BrowseInformationFile] - no command line Switch.
- // Skip [AdditionalOptions] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS12CSharpFlagTable.h b/Source/cmVS12CSharpFlagTable.h
deleted file mode 100644
index f98b1840d..000000000
--- a/Source/cmVS12CSharpFlagTable.h
+++ /dev/null
@@ -1,120 +0,0 @@
-static cmVS7FlagTable cmVS12CSharpFlagTable[] = {
- { "ProjectName", "out:", "", "", cmIDEFlagTable::UserValueRequired },
-
- { "OutputType", "target:exe", "", "Exe", 0 },
- { "OutputType", "target:winexe", "", "Winexe", 0 },
- { "OutputType", "target:library", "", "Library", 0 },
- { "OutputType", "target:module", "", "Module", 0 },
-
- { "DocumentationFile", "doc", "", "", cmIDEFlagTable::UserValueRequired },
-
- { "Platform", "platform:x86", "", "x86", 0 },
- { "Platform", "platform:Itanium", "", "Itanium", 0 },
- { "Platform", "platform:x64", "", "x64", 0 },
- { "Platform", "platform:arm", "", "arm", 0 },
- { "Platform", "platform:anycpu32bitpreferred", "", "anycpu32bitpreferred",
- 0 },
- { "Platform", "platform:anycpu", "", "anycpu", 0 },
-
- { "References", "reference:", "mit alias", "", 0 },
- { "References", "reference:", "dateiliste", "", 0 },
- { "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable },
- { "", "link", "", "", 0 },
-
- { "Win32Resource", "win32res", "", "", cmIDEFlagTable::UserValueRequired },
- { "ApplicationIcon", "win32icon", "", "",
- cmIDEFlagTable::UserValueRequired },
-
- { "Win32Manifest", "win32manifest:", "", "true", 0 },
-
- { "NoWin32Manifest", "nowin32manifest", "", "true", 0 },
-
- { "DefineDebug", "debug", "", "true", cmIDEFlagTable::Continue },
-
- { "DebugSymbols", "debug", "", "true", 0 },
- { "DebugSymbols", "debug-", "", "false", 0 },
- { "DebugSymbols", "debug+", "", "true", 0 },
-
- { "DebugType", "debug:none", "", "none", 0 },
- { "DebugType", "debug:full", "", "full", 0 },
- { "DebugType", "debug:pdbonly", "", "pdbonly", 0 },
-
- { "Optimize", "optimize", "", "true", 0 },
- { "Optimize", "optimize-", "", "false", 0 },
- { "Optimize", "optimize+", "", "true", 0 },
-
- { "TreatWarningsAsErrors", "warnaserror", "", "true", 0 },
- { "TreatWarningsAsErrors", "warnaserror-", "", "false", 0 },
- { "TreatWarningsAsErrors", "warnaserror+", "", "true", 0 },
-
- { "WarningsAsErrors", "warnaserror", "", "", 0 },
- { "WarningsAsErrors", "warnaserror-", "", "", 0 },
- { "WarningsAsErrors", "warnaserror+", "", "", 0 },
-
- { "WarningLevel", "warn:0", "", "0", 0 },
- { "WarningLevel", "warn:1", "", "1", 0 },
- { "WarningLevel", "warn:2", "", "2", 0 },
- { "WarningLevel", "warn:3", "", "3", 0 },
- { "WarningLevel", "warn:4", "", "4", 0 },
- { "DisabledWarnings", "nowarn", "", "", 0 },
-
- { "CheckForOverflowUnderflow", "checked", "", "true", 0 },
- { "CheckForOverflowUnderflow", "checked-", "", "false", 0 },
- { "CheckForOverflowUnderflow", "checked+", "", "true", 0 },
-
- { "AllowUnsafeBlocks", "unsafe", "", "true", 0 },
- { "AllowUnsafeBlocks", "unsafe-", "", "false", 0 },
- { "AllowUnsafeBlocks", "unsafe+", "", "true", 0 },
-
- { "DefineConstants", "define:", "", "",
- cmIDEFlagTable::SemicolonAppendable | cmIDEFlagTable::UserValue },
-
- { "LangVersion", "langversion:ISO-1", "", "ISO-1", 0 },
- { "LangVersion", "langversion:ISO-2", "", "ISO-2", 0 },
- { "LangVersion", "langversion:3", "", "3", 0 },
- { "LangVersion", "langversion:4", "", "4", 0 },
- { "LangVersion", "langversion:5", "", "5", 0 },
- { "LangVersion", "langversion:6", "", "6", 0 },
- { "LangVersion", "langversion:default", "", "default", 0 },
-
- { "DelaySign", "delaysign", "", "true", 0 },
- { "DelaySign", "delaysign-", "", "false", 0 },
- { "DelaySign", "delaysign+", "", "true", 0 },
-
- { "AssemblyOriginatorKeyFile", "keyfile", "", "", 0 },
-
- { "KeyContainerName", "keycontainer", "", "", 0 },
-
- { "NoLogo", "nologo", "", "", 0 },
-
- { "NoConfig", "noconfig", "", "true", 0 },
-
- { "BaseAddress", "baseaddress:", "", "", 0 },
-
- { "CodePage", "codepage", "", "", 0 },
-
- { "Utf8Output", "utf8output", "", "", 0 },
-
- { "MainEntryPoint", "main:", "", "", 0 },
-
- { "GenerateFullPaths", "fullpaths", "", "true", 0 },
-
- { "FileAlignment", "filealign", "", "", 0 },
-
- { "PdbFile", "pdb:", "", "", 0 },
-
- { "NoStandardLib", "nostdlib", "", "true", 0 },
- { "NoStandardLib", "nostdlib-", "", "false", 0 },
- { "NoStandardLib", "nostdlib+", "", "true", 0 },
-
- { "SubsystemVersion", "subsystemversion", "", "", 0 },
-
- { "AdditionalLibPaths", "lib:", "", "", 0 },
-
- { "ErrorReport", "errorreport:none", "Do Not Send Report", "none", 0 },
- { "ErrorReport", "errorreport:prompt", "Prompt Immediately", "prompt", 0 },
- { "ErrorReport", "errorreport:queue", "Queue For Next Login", "queue", 0 },
- { "ErrorReport", "errorreport:send", "Send Automatically", "send", 0 },
-
- { 0, 0, 0, 0, 0 },
-};
diff --git a/Source/cmVS12LibFlagTable.h b/Source/cmVS12LibFlagTable.h
deleted file mode 100644
index 0f7a25955..000000000
--- a/Source/cmVS12LibFlagTable.h
+++ /dev/null
@@ -1,76 +0,0 @@
-static cmVS7FlagTable cmVS12LibFlagTable[] = {
-
- // Enum Properties
- { "ErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately",
- "PromptImmediately", 0 },
- { "ErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login",
- "QueueForNextLogin", 0 },
- { "ErrorReporting", "ERRORREPORT:SEND", "Send Error Report",
- "SendErrorReport", 0 },
- { "ErrorReporting", "ERRORREPORT:NONE", "No Error Report", "NoErrorReport",
- 0 },
-
- { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 },
- { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 },
- { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 },
- { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 },
- { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 },
- { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU",
- 0 },
- { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16",
- "MachineMIPSFPU16", 0 },
- { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 },
- { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 },
- { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 },
- { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 },
-
- { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 },
- { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 },
- { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application",
- "EFI Application", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER",
- "EFI Boot Service Driver", "EFI Boot Service Driver", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime",
- 0 },
- { "SubSystem", "SUBSYSTEM:WINDOWSCE", "WindowsCE", "WindowsCE", 0 },
- { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 },
-
- // Bool Properties
- { "SuppressStartupBanner", "NOLOGO", "", "true", 0 },
- { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 },
- { "TreatLibWarningAsErrors", "WX:NO", "", "false", 0 },
- { "TreatLibWarningAsErrors", "WX", "", "true", 0 },
- { "Verbose", "VERBOSE", "", "true", 0 },
- { "LinkTimeCodeGeneration", "LTCG", "", "true", 0 },
-
- // Bool Properties With Argument
-
- // String List Properties
- // Skip [AdditionalDependencies] - no command line Switch.
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ExportNamedFunctions", "EXPORT:", "Export Named Functions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "RemoveObjects", "REMOVE:", "Remove Objects", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-
- // String Properties
- { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue },
- { "ModuleDefinitionFile", "DEF:", "Module Definition File Name", "",
- cmVS7FlagTable::UserValue },
- { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "",
- cmVS7FlagTable::UserValue },
- { "DisplayLibrary", "LIST:", "Display Library to standard output", "",
- cmVS7FlagTable::UserValue },
- // Skip [MinimumRequiredVersion] - no command line Switch.
- { "Name", "NAME:", "Name", "", cmVS7FlagTable::UserValue },
- // Skip [AdditionalOptions] - no command line Switch.
- // Skip [TrackerLogDirectory] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS12LinkFlagTable.h b/Source/cmVS12LinkFlagTable.h
deleted file mode 100644
index 168c34c22..000000000
--- a/Source/cmVS12LinkFlagTable.h
+++ /dev/null
@@ -1,269 +0,0 @@
-static cmVS7FlagTable cmVS12LinkFlagTable[] = {
-
- // Enum Properties
- { "ShowProgress", "", "Not Set", "NotSet", 0 },
- { "ShowProgress", "VERBOSE", "Display all progress messages", "LinkVerbose",
- 0 },
- { "ShowProgress", "VERBOSE:Lib", "For Libraries Searched", "LinkVerboseLib",
- 0 },
- { "ShowProgress", "VERBOSE:ICF",
- "About COMDAT folding during optimized linking", "LinkVerboseICF", 0 },
- { "ShowProgress", "VERBOSE:REF",
- "About data removed during optimized linking", "LinkVerboseREF", 0 },
- { "ShowProgress", "VERBOSE:SAFESEH", "About Modules incompatible with SEH",
- "LinkVerboseSAFESEH", 0 },
- { "ShowProgress", "VERBOSE:CLR",
- "About linker activity related to managed code", "LinkVerboseCLR", 0 },
-
- { "ForceFileOutput", "FORCE", "Enabled", "Enabled", 0 },
- { "ForceFileOutput", "FORCE:MULTIPLE", "Multiply Defined Symbol Only",
- "MultiplyDefinedSymbolOnly", 0 },
- { "ForceFileOutput", "FORCE:UNRESOLVED", "Undefined Symbol Only",
- "UndefinedSymbolOnly", 0 },
-
- { "CreateHotPatchableImage", "FUNCTIONPADMIN", "Enabled", "Enabled", 0 },
- { "CreateHotPatchableImage", "FUNCTIONPADMIN:5", "X86 Image Only",
- "X86Image", 0 },
- { "CreateHotPatchableImage", "FUNCTIONPADMIN:6", "X64 Image Only",
- "X64Image", 0 },
- { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only",
- "ItaniumImage", 0 },
-
- { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 },
- { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable",
- "HighestAvailable", 0 },
- { "UACExecutionLevel", "level='requireAdministrator'",
- "requireAdministrator", "RequireAdministrator", 0 },
-
- { "SubSystem", "", "Not Set", "NotSet", 0 },
- { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 },
- { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 },
- { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application",
- "EFI Application", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER",
- "EFI Boot Service Driver", "EFI Boot Service Driver", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime",
- 0 },
- { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 },
-
- { "Driver", "", "Not Set", "NotSet", 0 },
- { "Driver", "Driver", "Driver", "Driver", 0 },
- { "Driver", "DRIVER:UPONLY", "UP Only", "UpOnly", 0 },
- { "Driver", "DRIVER:WDM", "WDM", "WDM", 0 },
-
- { "LinkTimeCodeGeneration", "", "Default", "Default", 0 },
- { "LinkTimeCodeGeneration", "LTCG", "Use Link Time Code Generation",
- "UseLinkTimeCodeGeneration", 0 },
- { "LinkTimeCodeGeneration", "LTCG:PGInstrument",
- "Profile Guided Optimization - Instrument", "PGInstrument", 0 },
- { "LinkTimeCodeGeneration", "LTCG:PGOptimize",
- "Profile Guided Optimization - Optimization", "PGOptimization", 0 },
- { "LinkTimeCodeGeneration", "LTCG:PGUpdate",
- "Profile Guided Optimization - Update", "PGUpdate", 0 },
-
- { "GenerateWindowsMetadata", "WINMD", "Yes", "true", 0 },
- { "GenerateWindowsMetadata", "WINMD:NO", "No", "false", 0 },
-
- { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA1", "SHA1", "SHA1", 0 },
- { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA256", "SHA256", "SHA256", 0 },
- { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA384", "SHA384", "SHA384", 0 },
- { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA512", "SHA512", "SHA512", 0 },
-
- { "TargetMachine", "", "Not Set", "NotSet", 0 },
- { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 },
- { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 },
- { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 },
- { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 },
- { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 },
- { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU",
- 0 },
- { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16",
- "MachineMIPSFPU16", 0 },
- { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 },
- { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 },
- { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 },
- { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 },
-
- { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:MTA", "MTA threading attribute",
- "MTAThreadingAttribute", 0 },
- { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:STA", "STA threading attribute",
- "STAThreadingAttribute", 0 },
- { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:NONE",
- "Default threading attribute", "DefaultThreadingAttribute", 0 },
-
- { "CLRImageType", "CLRIMAGETYPE:IJW", "Force IJW image", "ForceIJWImage",
- 0 },
- { "CLRImageType", "CLRIMAGETYPE:PURE", "Force Pure IL Image",
- "ForcePureILImage", 0 },
- { "CLRImageType", "CLRIMAGETYPE:SAFE", "Force Safe IL Image",
- "ForceSafeILImage", 0 },
- { "CLRImageType", "", "Default image type", "Default", 0 },
-
- { "SignHash", "CLRSIGNHASH:SHA1", "SHA1", "SHA1", 0 },
- { "SignHash", "CLRSIGNHASH:SHA256", "SHA256", "SHA256", 0 },
- { "SignHash", "CLRSIGNHASH:SHA384", "SHA384", "SHA384", 0 },
- { "SignHash", "CLRSIGNHASH:SHA512", "SHA512", "SHA512", 0 },
-
- { "LinkErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately",
- "PromptImmediately", 0 },
- { "LinkErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login",
- "QueueForNextLogin", 0 },
- { "LinkErrorReporting", "ERRORREPORT:SEND", "Send Error Report",
- "SendErrorReport", 0 },
- { "LinkErrorReporting", "ERRORREPORT:NONE", "No Error Report",
- "NoErrorReport", 0 },
-
- { "CLRSupportLastError", "CLRSupportLastError", "Enabled", "Enabled", 0 },
- { "CLRSupportLastError", "CLRSupportLastError:NO", "Disabled", "Disabled",
- 0 },
- { "CLRSupportLastError", "CLRSupportLastError:SYSTEMDLL", "System Dlls Only",
- "SystemDlls", 0 },
-
- // Bool Properties
- { "LinkIncremental", "INCREMENTAL:NO", "", "false", 0 },
- { "LinkIncremental", "INCREMENTAL", "", "true", 0 },
- { "SuppressStartupBanner", "NOLOGO", "", "true", 0 },
- { "LinkStatus", "LTCG:NOSTATUS", "", "false", 0 },
- { "LinkStatus", "LTCG:STATUS", "", "true", 0 },
- { "PreventDllBinding", "ALLOWBIND:NO", "", "false", 0 },
- { "PreventDllBinding", "ALLOWBIND", "", "true", 0 },
- { "TreatLinkerWarningAsErrors", "WX:NO", "", "false", 0 },
- { "TreatLinkerWarningAsErrors", "WX", "", "true", 0 },
- { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 },
- { "GenerateManifest", "MANIFEST:NO", "", "false", 0 },
- { "GenerateManifest", "MANIFEST", "", "true", 0 },
- { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 },
- { "UACUIAccess", "uiAccess='false'", "", "false", 0 },
- { "UACUIAccess", "uiAccess='true'", "", "true", 0 },
- { "ManifestEmbed", "manifest:embed", "", "true", 0 },
- { "GenerateDebugInformation", "DEBUG", "", "true",
- cmVS7FlagTable::CaseInsensitive },
- { "MapExports", "MAPINFO:EXPORTS", "", "true", 0 },
- { "AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0 },
- { "AssemblyDebug", "ASSEMBLYDEBUG", "", "true", 0 },
- { "LargeAddressAware", "LARGEADDRESSAWARE:NO", "", "false", 0 },
- { "LargeAddressAware", "LARGEADDRESSAWARE", "", "true", 0 },
- { "TerminalServerAware", "TSAWARE:NO", "", "false", 0 },
- { "TerminalServerAware", "TSAWARE", "", "true", 0 },
- { "SwapRunFromCD", "SWAPRUN:CD", "", "true", 0 },
- { "SwapRunFromNET", "SWAPRUN:NET", "", "true", 0 },
- { "OptimizeReferences", "OPT:NOREF", "", "false", 0 },
- { "OptimizeReferences", "OPT:REF", "", "true", 0 },
- { "EnableCOMDATFolding", "OPT:NOICF", "", "false", 0 },
- { "EnableCOMDATFolding", "OPT:ICF", "", "true", 0 },
- { "IgnoreEmbeddedIDL", "IGNOREIDL", "", "true", 0 },
- { "AppContainer", "APPCONTAINER", "", "true", 0 },
- { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN:NO", "", "false", 0 },
- { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN", "", "true", 0 },
- { "NoEntryPoint", "NOENTRY", "", "true", 0 },
- { "SetChecksum", "RELEASE", "", "true", 0 },
- { "RandomizedBaseAddress", "DYNAMICBASE:NO", "", "false", 0 },
- { "RandomizedBaseAddress", "DYNAMICBASE", "", "true", 0 },
- { "FixedBaseAddress", "FIXED:NO", "", "false", 0 },
- { "FixedBaseAddress", "FIXED", "", "true", 0 },
- { "DataExecutionPrevention", "NXCOMPAT:NO", "", "false", 0 },
- { "DataExecutionPrevention", "NXCOMPAT", "", "true", 0 },
- { "TurnOffAssemblyGeneration", "NOASSEMBLY", "", "true", 0 },
- { "SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0 },
- { "SupportNobindOfDelayLoadedDLL", "DELAY:NOBIND", "", "true", 0 },
- { "Profile", "PROFILE", "", "true", 0 },
- { "LinkDelaySign", "DELAYSIGN:NO", "", "false", 0 },
- { "LinkDelaySign", "DELAYSIGN", "", "true", 0 },
- { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0 },
- { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0 },
- { "DetectOneDefinitionRule", "ODR", "", "true", 0 },
- { "ImageHasSafeExceptionHandlers", "SAFESEH:NO", "", "false", 0 },
- { "ImageHasSafeExceptionHandlers", "SAFESEH", "", "true", 0 },
- { "LinkDLL", "DLL", "", "true", 0 },
-
- // Bool Properties With Argument
- { "EnableUAC", "MANIFESTUAC:NO", "", "false", 0 },
- { "EnableUAC", "MANIFESTUAC:", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "UACUIAccess", "MANIFESTUAC:", "Enable User Account Control (UAC)", "",
- cmVS7FlagTable::UserValueRequired },
- { "GenerateMapFile", "MAP", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "MapFileName", "MAP:", "Generate Map File", "",
- cmVS7FlagTable::UserValueRequired },
-
- // String List Properties
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- // Skip [AdditionalDependencies] - no command line Switch.
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly",
- "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "EmbedManagedResourceFile", "ASSEMBLYRESOURCE:",
- "Embed Managed Resource File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "DelayLoadDLLs", "DELAYLOAD:", "Delay Loaded Dlls", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource",
- "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AdditionalManifestDependencies", "MANIFESTDEPENDENCY:",
- "Additional Manifest Dependencies", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ManifestInput", "manifestinput:", "Manifest Input", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-
- // String Properties
- { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue },
- { "Version", "VERSION:", "Version", "", cmVS7FlagTable::UserValue },
- { "SpecifySectionAttributes", "SECTION:", "Specify Section Attributes", "",
- cmVS7FlagTable::UserValue },
- { "MSDOSStubFileName", "STUB:", "MS-DOS Stub File Name", "",
- cmVS7FlagTable::UserValue },
- // Skip [TrackerLogDirectory] - no command line Switch.
- { "ModuleDefinitionFile", "DEF:", "Module Definition File", "",
- cmVS7FlagTable::UserValue },
- { "ManifestFile", "ManifestFile:", "Manifest File", "",
- cmVS7FlagTable::UserValue },
- { "ProgramDatabaseFile", "PDB:", "Generate Program Database File", "",
- cmVS7FlagTable::UserValue },
- { "StripPrivateSymbols", "PDBSTRIPPED:", "Strip Private Symbols", "",
- cmVS7FlagTable::UserValue },
- // Skip [MapFileName] - no command line Switch.
- // Skip [MinimumRequiredVersion] - no command line Switch.
- { "HeapReserveSize", "HEAP:", "Heap Reserve Size", "",
- cmVS7FlagTable::UserValue },
- // Skip [HeapCommitSize] - no command line Switch.
- { "StackReserveSize", "STACK:", "Stack Reserve Size", "",
- cmVS7FlagTable::UserValue },
- // Skip [StackCommitSize] - no command line Switch.
- { "FunctionOrder", "ORDER:@", "Function Order", "",
- cmVS7FlagTable::UserValue },
- { "ProfileGuidedDatabase", "PGD:", "Profile Guided Database", "",
- cmVS7FlagTable::UserValue },
- { "MidlCommandFile", "MIDL:@", "MIDL Commands", "",
- cmVS7FlagTable::UserValue },
- { "MergedIDLBaseFileName", "IDLOUT:", "Merged IDL Base File Name", "",
- cmVS7FlagTable::UserValue },
- { "TypeLibraryFile", "TLBOUT:", "Type Library", "",
- cmVS7FlagTable::UserValue },
- { "WindowsMetadataFile", "WINMDFILE:", "Windows Metadata File", "",
- cmVS7FlagTable::UserValue },
- { "WindowsMetadataLinkKeyFile", "WINMDKEYFILE:", "Windows Metadata Key File",
- "", cmVS7FlagTable::UserValue },
- { "WindowsMetadataKeyContainer", "WINMDKEYCONTAINER:",
- "Windows Metadata Key Container", "", cmVS7FlagTable::UserValue },
- { "EntryPointSymbol", "ENTRY:", "Entry Point", "",
- cmVS7FlagTable::UserValue },
- { "BaseAddress", "BASE:", "Base Address", "", cmVS7FlagTable::UserValue },
- { "ImportLibrary", "IMPLIB:", "Import Library", "",
- cmVS7FlagTable::UserValue },
- { "MergeSections", "MERGE:", "Merge Sections", "",
- cmVS7FlagTable::UserValue },
- { "LinkKeyFile", "KEYFILE:", "Key File", "", cmVS7FlagTable::UserValue },
- { "KeyContainer", "KEYCONTAINER:", "Key Container", "",
- cmVS7FlagTable::UserValue },
- // Skip [AdditionalOptions] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS12MASMFlagTable.h b/Source/cmVS12MASMFlagTable.h
deleted file mode 100644
index acc0d48e1..000000000
--- a/Source/cmVS12MASMFlagTable.h
+++ /dev/null
@@ -1,76 +0,0 @@
-static cmVS7FlagTable cmVS12MASMFlagTable[] = {
-
- // Enum Properties
- { "PreserveIdentifierCase", "", "Default", "0", 0 },
- { "PreserveIdentifierCase", "Cp", "Preserves Identifier Case (/Cp)", "1",
- 0 },
- { "PreserveIdentifierCase", "Cu",
- "Maps all identifiers to upper case. (/Cu)", "2", 0 },
- { "PreserveIdentifierCase", "Cx",
- "Preserves case in public and extern symbols. (/Cx)", "3", 0 },
-
- { "WarningLevel", "W0", "Warning Level 0 (/W0)", "0", 0 },
- { "WarningLevel", "W1", "Warning Level 1 (/W1)", "1", 0 },
- { "WarningLevel", "W2", "Warning Level 2 (/W2)", "2", 0 },
- { "WarningLevel", "W3", "Warning Level 3 (/W3)", "3", 0 },
-
- { "PackAlignmentBoundary", "", "Default", "0", 0 },
- { "PackAlignmentBoundary", "Zp1", "One Byte Boundary (/Zp1)", "1", 0 },
- { "PackAlignmentBoundary", "Zp2", "Two Byte Boundary (/Zp2)", "2", 0 },
- { "PackAlignmentBoundary", "Zp4", "Four Byte Boundary (/Zp4)", "3", 0 },
- { "PackAlignmentBoundary", "Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 },
- { "PackAlignmentBoundary", "Zp16", "Sixteen Byte Boundary (/Zp16)", "5", 0 },
-
- { "CallingConvention", "", "Default", "0", 0 },
- { "CallingConvention", "Gd", "Use C-style Calling Convention (/Gd)", "1",
- 0 },
- { "CallingConvention", "Gz", "Use stdcall Calling Convention (/Gz)", "2",
- 0 },
- { "CallingConvention", "Gc", "Use Pascal Calling Convention (/Gc)", "3", 0 },
-
- { "ErrorReporting", "errorReport:prompt",
- "Prompt to send report immediately (/errorReport:prompt)", "0", 0 },
- { "ErrorReporting", "errorReport:queue",
- "Prompt to send report at the next logon (/errorReport:queue)", "1", 0 },
- { "ErrorReporting", "errorReport:send",
- "Automatically send report (/errorReport:send)", "2", 0 },
- { "ErrorReporting", "errorReport:none",
- "Do not send report (/errorReport:none)", "3", 0 },
-
- // Bool Properties
- { "NoLogo", "nologo", "", "true", 0 },
- { "GeneratePreprocessedSourceListing", "EP", "", "true", 0 },
- { "ListAllAvailableInformation", "Sa", "", "true", 0 },
- { "UseSafeExceptionHandlers", "safeseh", "", "true", 0 },
- { "AddFirstPassListing", "Sf", "", "true", 0 },
- { "EnableAssemblyGeneratedCodeListing", "Sg", "", "true", 0 },
- { "DisableSymbolTable", "Sn", "", "true", 0 },
- { "EnableFalseConditionalsInListing", "Sx", "", "true", 0 },
- { "TreatWarningsAsErrors", "WX", "", "true", 0 },
- { "MakeAllSymbolsPublic", "Zf", "", "true", 0 },
- { "GenerateDebugInformation", "Zi", "", "true", 0 },
- { "EnableMASM51Compatibility", "Zm", "", "true", 0 },
- { "PerformSyntaxCheckOnly", "Zs", "", "true", 0 },
-
- // Bool Properties With Argument
-
- // String List Properties
- { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "IncludePaths", "I", "Include Paths", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "BrowseFile", "FR", "Generate Browse Information File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- // Skip [AdditionalDependencies] - no command line Switch.
-
- // String Properties
- // Skip [Inputs] - no command line Switch.
- { "ObjectFileName", "Fo", "Object File Name", "",
- cmVS7FlagTable::UserValue },
- { "AssembledCodeListingFile", "Fl", "Assembled Code Listing File", "",
- cmVS7FlagTable::UserValue },
- // Skip [CommandLineTemplate] - no command line Switch.
- // Skip [ExecutionDescription] - no command line Switch.
- // Skip [AdditionalOptions] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS12RCFlagTable.h b/Source/cmVS12RCFlagTable.h
deleted file mode 100644
index a650f8522..000000000
--- a/Source/cmVS12RCFlagTable.h
+++ /dev/null
@@ -1,7 +0,0 @@
-static cmVS7FlagTable cmVS12RCFlagTable[] = {
- // Bool Properties
- { "NullTerminateStrings", "n", "", "true", 0 },
- { "SuppressStartupBanner", "nologo", "", "true", 0 },
-
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS140CLFlagTable.h b/Source/cmVS140CLFlagTable.h
deleted file mode 100644
index 60b437974..000000000
--- a/Source/cmVS140CLFlagTable.h
+++ /dev/null
@@ -1,239 +0,0 @@
-static cmVS7FlagTable cmVS140CLFlagTable[] = {
-
- // Enum Properties
- { "DebugInformationFormat", "", "None", "None", 0 },
- { "DebugInformationFormat", "Z7", "C7 compatible", "OldStyle", 0 },
- { "DebugInformationFormat", "Zi", "Program Database", "ProgramDatabase", 0 },
- { "DebugInformationFormat", "ZI", "Program Database for Edit And Continue",
- "EditAndContinue", 0 },
-
- { "WarningLevel", "W0", "Turn Off All Warnings", "TurnOffAllWarnings", 0 },
- { "WarningLevel", "W1", "Level1", "Level1", 0 },
- { "WarningLevel", "W2", "Level2", "Level2", 0 },
- { "WarningLevel", "W3", "Level3", "Level3", 0 },
- { "WarningLevel", "W4", "Level4", "Level4", 0 },
- { "WarningLevel", "Wall", "EnableAllWarnings", "EnableAllWarnings", 0 },
-
- { "Optimization", "", "Custom", "Custom", 0 },
- { "Optimization", "Od", "Disabled", "Disabled", 0 },
- { "Optimization", "O1", "Minimize Size", "MinSpace", 0 },
- { "Optimization", "O2", "Maximize Speed", "MaxSpeed", 0 },
- { "Optimization", "Ox", "Full Optimization", "Full", 0 },
-
- { "InlineFunctionExpansion", "", "Default", "Default", 0 },
- { "InlineFunctionExpansion", "Ob0", "Disabled", "Disabled", 0 },
- { "InlineFunctionExpansion", "Ob1", "Only __inline", "OnlyExplicitInline",
- 0 },
- { "InlineFunctionExpansion", "Ob2", "Any Suitable", "AnySuitable", 0 },
-
- { "FavorSizeOrSpeed", "Os", "Favor small code", "Size", 0 },
- { "FavorSizeOrSpeed", "Ot", "Favor fast code", "Speed", 0 },
- { "FavorSizeOrSpeed", "", "Neither", "Neither", 0 },
-
- { "ExceptionHandling", "EHa", "Yes with SEH Exceptions", "Async", 0 },
- { "ExceptionHandling", "EHsc", "Yes", "Sync", 0 },
- { "ExceptionHandling", "EHs", "Yes with Extern C functions", "SyncCThrow",
- 0 },
- { "ExceptionHandling", "", "No", "false", 0 },
-
- { "BasicRuntimeChecks", "RTCs", "Stack Frames", "StackFrameRuntimeCheck",
- 0 },
- { "BasicRuntimeChecks", "RTCu", "Uninitialized variables",
- "UninitializedLocalUsageCheck", 0 },
- { "BasicRuntimeChecks", "RTC1", "Both (/RTC1, equiv. to /RTCsu)",
- "EnableFastChecks", 0 },
- { "BasicRuntimeChecks", "", "Default", "Default", 0 },
-
- { "RuntimeLibrary", "MT", "Multi-threaded", "MultiThreaded", 0 },
- { "RuntimeLibrary", "MTd", "Multi-threaded Debug", "MultiThreadedDebug", 0 },
- { "RuntimeLibrary", "MD", "Multi-threaded DLL", "MultiThreadedDLL", 0 },
- { "RuntimeLibrary", "MDd", "Multi-threaded Debug DLL",
- "MultiThreadedDebugDLL", 0 },
-
- { "StructMemberAlignment", "Zp1", "1 Byte", "1Byte", 0 },
- { "StructMemberAlignment", "Zp2", "2 Bytes", "2Bytes", 0 },
- { "StructMemberAlignment", "Zp4", "4 Byte", "4Bytes", 0 },
- { "StructMemberAlignment", "Zp8", "8 Bytes", "8Bytes", 0 },
- { "StructMemberAlignment", "Zp16", "16 Bytes", "16Bytes", 0 },
- { "StructMemberAlignment", "", "Default", "Default", 0 },
-
- { "BufferSecurityCheck", "GS-", "Disable Security Check", "false", 0 },
- { "BufferSecurityCheck", "GS", "Enable Security Check", "true", 0 },
-
- { "EnableEnhancedInstructionSet", "arch:SSE", "Streaming SIMD Extensions",
- "StreamingSIMDExtensions", 0 },
- { "EnableEnhancedInstructionSet", "arch:SSE2", "Streaming SIMD Extensions 2",
- "StreamingSIMDExtensions2", 0 },
- { "EnableEnhancedInstructionSet", "arch:AVX", "Advanced Vector Extensions",
- "AdvancedVectorExtensions", 0 },
- { "EnableEnhancedInstructionSet", "arch:AVX2",
- "Advanced Vector Extensions 2", "AdvancedVectorExtensions2", 0 },
- { "EnableEnhancedInstructionSet", "arch:IA32", "No Enhanced Instructions",
- "NoExtensions", 0 },
- { "EnableEnhancedInstructionSet", "", "Not Set", "NotSet", 0 },
-
- { "FloatingPointModel", "fp:precise", "Precise", "Precise", 0 },
- { "FloatingPointModel", "fp:strict", "Strict", "Strict", 0 },
- { "FloatingPointModel", "fp:fast", "Fast", "Fast", 0 },
-
- { "PrecompiledHeader", "Yc", "Create", "Create",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "PrecompiledHeader", "Yu", "Use", "Use",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "PrecompiledHeader", "", "Not Using Precompiled Headers", "NotUsing", 0 },
-
- { "AssemblerOutput", "", "No Listing", "NoListing", 0 },
- { "AssemblerOutput", "FA", "Assembly-Only Listing", "AssemblyCode", 0 },
- { "AssemblerOutput", "FAc", "Assembly With Machine Code",
- "AssemblyAndMachineCode", 0 },
- { "AssemblerOutput", "FAs", "Assembly With Source Code",
- "AssemblyAndSourceCode", 0 },
- { "AssemblerOutput", "FAcs", "Assembly, Machine Code and Source", "All", 0 },
-
- { "CallingConvention", "Gd", "__cdecl", "Cdecl", 0 },
- { "CallingConvention", "Gr", "__fastcall", "FastCall", 0 },
- { "CallingConvention", "Gz", "__stdcall", "StdCall", 0 },
- { "CallingConvention", "Gv", "__vectorcall", "VectorCall", 0 },
-
- { "CompileAs", "", "Default", "Default", 0 },
- { "CompileAs", "TC", "Compile as C Code", "CompileAsC", 0 },
- { "CompileAs", "TP", "Compile as C++ Code", "CompileAsCpp", 0 },
-
- { "ErrorReporting", "errorReport:none", "Do Not Send Report", "None", 0 },
- { "ErrorReporting", "errorReport:prompt", "Prompt Immediately", "Prompt",
- 0 },
- { "ErrorReporting", "errorReport:queue", "Queue For Next Login", "Queue",
- 0 },
- { "ErrorReporting", "errorReport:send", "Send Automatically", "Send", 0 },
-
- { "CompileAsManaged", "", "No Common Language RunTime Support", "false", 0 },
- { "CompileAsManaged", "clr", "Common Language RunTime Support", "true", 0 },
- { "CompileAsManaged", "clr:pure",
- "Pure MSIL Common Language RunTime Support", "Pure", 0 },
- { "CompileAsManaged", "clr:safe",
- "Safe MSIL Common Language RunTime Support", "Safe", 0 },
- { "CompileAsManaged", "clr:oldSyntax",
- "Common Language RunTime Support, Old Syntax", "OldSyntax", 0 },
-
- { "CppLanguageStandard", "", "Default", "Default", 0 },
- { "CppLanguageStandard", "std=c++98", "C++03", "c++98", 0 },
- { "CppLanguageStandard", "std=c++11", "C++11", "c++11", 0 },
- { "CppLanguageStandard", "std=c++1y", "C++14", "c++1y", 0 },
- { "CppLanguageStandard", "std=c++14", "C++14", "c++1y", 0 },
- { "CppLanguageStandard", "std=gnu++98", "C++03 (GNU Dialect)", "gnu++98",
- 0 },
- { "CppLanguageStandard", "std=gnu++11", "C++11 (GNU Dialect)", "gnu++11",
- 0 },
- { "CppLanguageStandard", "std=gnu++1y", "C++14 (GNU Dialect)", "gnu++1y",
- 0 },
- { "CppLanguageStandard", "std=gnu++14", "C++14 (GNU Dialect)", "gnu++1y",
- 0 },
-
- // Bool Properties
- { "CompileAsWinRT", "ZW", "", "true", 0 },
- { "WinRTNoStdLib", "ZW:nostdlib", "", "true", 0 },
- { "SuppressStartupBanner", "nologo", "", "true", 0 },
- { "TreatWarningAsError", "WX-", "", "false", 0 },
- { "TreatWarningAsError", "WX", "", "true", 0 },
- { "SDLCheck", "sdl-", "", "false", 0 },
- { "SDLCheck", "sdl", "", "true", 0 },
- { "IntrinsicFunctions", "Oi", "", "true", 0 },
- { "OmitFramePointers", "Oy-", "", "false", 0 },
- { "OmitFramePointers", "Oy", "", "true", 0 },
- { "EnableFiberSafeOptimizations", "GT", "", "true", 0 },
- { "WholeProgramOptimization", "GL", "", "true", 0 },
- { "UndefineAllPreprocessorDefinitions", "u", "", "true", 0 },
- { "IgnoreStandardIncludePath", "X", "", "true", 0 },
- { "PreprocessToFile", "P", "", "true", 0 },
- { "PreprocessSuppressLineNumbers", "EP", "", "true", 0 },
- { "PreprocessKeepComments", "C", "", "true", 0 },
- { "StringPooling", "GF-", "", "false", 0 },
- { "StringPooling", "GF", "", "true", 0 },
- { "MinimalRebuild", "Gm-", "", "false", 0 },
- { "MinimalRebuild", "Gm", "", "true", 0 },
- { "SmallerTypeCheck", "RTCc", "", "true", 0 },
- { "FunctionLevelLinking", "Gy-", "", "false", 0 },
- { "FunctionLevelLinking", "Gy", "", "true", 0 },
- { "EnableParallelCodeGeneration", "Qpar-", "", "false", 0 },
- { "EnableParallelCodeGeneration", "Qpar", "", "true", 0 },
- { "FloatingPointExceptions", "fp:except-", "", "false", 0 },
- { "FloatingPointExceptions", "fp:except", "", "true", 0 },
- { "CreateHotpatchableImage", "hotpatch", "", "true", 0 },
- { "DisableLanguageExtensions", "Za", "", "true", 0 },
- { "TreatWChar_tAsBuiltInType", "Zc:wchar_t-", "", "false", 0 },
- { "TreatWChar_tAsBuiltInType", "Zc:wchar_t", "", "true", 0 },
- { "ForceConformanceInForLoopScope", "Zc:forScope-", "", "false", 0 },
- { "ForceConformanceInForLoopScope", "Zc:forScope", "", "true", 0 },
- { "RemoveUnreferencedCodeData", "Zc:inline-", "", "false", 0 },
- { "RemoveUnreferencedCodeData", "Zc:inline", "", "true", 0 },
- { "RuntimeTypeInfo", "GR-", "", "false", 0 },
- { "RuntimeTypeInfo", "GR", "", "true", 0 },
- { "OpenMPSupport", "openmp-", "", "false", 0 },
- { "OpenMPSupport", "openmp", "", "true", 0 },
- { "ExpandAttributedSource", "Fx", "", "true", 0 },
- { "UseUnicodeForAssemblerListing", "FAu", "", "true", 0 },
- { "ShowIncludes", "showIncludes", "", "true", 0 },
- { "EnablePREfast", "analyze-", "", "false", 0 },
- { "EnablePREfast", "analyze", "", "true", 0 },
- { "UseFullPaths", "FC", "", "true", 0 },
- { "OmitDefaultLibName", "Zl", "", "true", 0 },
-
- // Bool Properties With Argument
- { "MultiProcessorCompilation", "MP", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "ProcessorNumber", "MP", "Multi-processor Compilation", "",
- cmVS7FlagTable::UserValueRequired },
- { "GenerateXMLDocumentationFiles", "doc", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "XMLDocumentationFileName", "doc", "Generate XML Documentation Files", "",
- cmVS7FlagTable::UserValueRequired },
- { "BrowseInformation", "FR", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "BrowseInformationFile", "FR", "Enable Browse Information", "",
- cmVS7FlagTable::UserValueRequired },
-
- // String List Properties
- { "AdditionalIncludeDirectories", "I", "Additional Include Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AdditionalUsingDirectories", "AI", "Additional #using Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "PreprocessorDefinitions", "D ", "Preprocessor Definitions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "UndefinePreprocessorDefinitions", "U",
- "Undefine Preprocessor Definitions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "DisableSpecificWarnings", "wd", "Disable Specific Warnings", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ForcedIncludeFiles", "FI", "Forced Include File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ForcedUsingFiles", "FU", "Forced #using File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "PREfastLog", "analyze:log", "Code Analysis Log", "",
- cmVS7FlagTable::UserFollowing },
- { "PREfastAdditionalPlugins", "analyze:plugin",
- "Additional Code Analysis Native plugins", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "TreatSpecificWarningsAsErrors", "we", "Treat Specific Warnings As Errors",
- "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-
- // String Properties
- // Skip [TrackerLogDirectory] - no command line Switch.
- { "PreprocessOutputPath", "Fi", "Preprocess Output Path", "",
- cmVS7FlagTable::UserValue },
- { "PrecompiledHeaderFile", "Yc", "Precompiled Header Name", "",
- cmVS7FlagTable::UserValueRequired },
- { "PrecompiledHeaderFile", "Yu", "Precompiled Header Name", "",
- cmVS7FlagTable::UserValueRequired },
- { "PrecompiledHeaderOutputFile", "Fp", "Precompiled Header Output File", "",
- cmVS7FlagTable::UserValue },
- { "AssemblerListingLocation", "Fa", "ASM List Location", "",
- cmVS7FlagTable::UserValue },
- { "ObjectFileName", "Fo", "Object File Name", "",
- cmVS7FlagTable::UserValue },
- { "ProgramDataBaseFileName", "Fd", "Program Database File Name", "",
- cmVS7FlagTable::UserValue },
- // Skip [XMLDocumentationFileName] - no command line Switch.
- // Skip [BrowseInformationFile] - no command line Switch.
- // Skip [AdditionalOptions] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS140CSharpFlagTable.h b/Source/cmVS140CSharpFlagTable.h
deleted file mode 100644
index 256c35f70..000000000
--- a/Source/cmVS140CSharpFlagTable.h
+++ /dev/null
@@ -1,120 +0,0 @@
-static cmVS7FlagTable cmVS140CSharpFlagTable[] = {
- { "ProjectName", "out:", "", "", cmIDEFlagTable::UserValueRequired },
-
- { "OutputType", "target:exe", "", "Exe", 0 },
- { "OutputType", "target:winexe", "", "Winexe", 0 },
- { "OutputType", "target:library", "", "Library", 0 },
- { "OutputType", "target:module", "", "Module", 0 },
-
- { "DocumentationFile", "doc", "", "", cmIDEFlagTable::UserValueRequired },
-
- { "Platform", "platform:x86", "", "x86", 0 },
- { "Platform", "platform:Itanium", "", "Itanium", 0 },
- { "Platform", "platform:x64", "", "x64", 0 },
- { "Platform", "platform:arm", "", "arm", 0 },
- { "Platform", "platform:anycpu32bitpreferred", "", "anycpu32bitpreferred",
- 0 },
- { "Platform", "platform:anycpu", "", "anycpu", 0 },
-
- { "References", "reference:", "mit alias", "", 0 },
- { "References", "reference:", "dateiliste", "", 0 },
- { "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable },
- { "", "link", "", "", 0 },
-
- { "Win32Resource", "win32res", "", "", cmIDEFlagTable::UserValueRequired },
- { "ApplicationIcon", "win32icon", "", "",
- cmIDEFlagTable::UserValueRequired },
-
- { "Win32Manifest", "win32manifest:", "", "true", 0 },
-
- { "NoWin32Manifest", "nowin32manifest", "", "true", 0 },
-
- { "DefineDebug", "debug", "", "true", cmIDEFlagTable::Continue },
-
- { "DebugSymbols", "debug", "", "true", 0 },
- { "DebugSymbols", "debug-", "", "false", 0 },
- { "DebugSymbols", "debug+", "", "true", 0 },
-
- { "DebugType", "debug:none", "", "none", 0 },
- { "DebugType", "debug:full", "", "full", 0 },
- { "DebugType", "debug:pdbonly", "", "pdbonly", 0 },
-
- { "Optimize", "optimize", "", "true", 0 },
- { "Optimize", "optimize-", "", "false", 0 },
- { "Optimize", "optimize+", "", "true", 0 },
-
- { "TreatWarningsAsErrors", "warnaserror", "", "true", 0 },
- { "TreatWarningsAsErrors", "warnaserror-", "", "false", 0 },
- { "TreatWarningsAsErrors", "warnaserror+", "", "true", 0 },
-
- { "WarningsAsErrors", "warnaserror", "", "", 0 },
- { "WarningsAsErrors", "warnaserror-", "", "", 0 },
- { "WarningsAsErrors", "warnaserror+", "", "", 0 },
-
- { "WarningLevel", "warn:0", "", "0", 0 },
- { "WarningLevel", "warn:1", "", "1", 0 },
- { "WarningLevel", "warn:2", "", "2", 0 },
- { "WarningLevel", "warn:3", "", "3", 0 },
- { "WarningLevel", "warn:4", "", "4", 0 },
- { "DisabledWarnings", "nowarn", "", "", 0 },
-
- { "CheckForOverflowUnderflow", "checked", "", "true", 0 },
- { "CheckForOverflowUnderflow", "checked-", "", "false", 0 },
- { "CheckForOverflowUnderflow", "checked+", "", "true", 0 },
-
- { "AllowUnsafeBlocks", "unsafe", "", "true", 0 },
- { "AllowUnsafeBlocks", "unsafe-", "", "false", 0 },
- { "AllowUnsafeBlocks", "unsafe+", "", "true", 0 },
-
- { "DefineConstants", "define:", "", "",
- cmIDEFlagTable::SemicolonAppendable | cmIDEFlagTable::UserValue },
-
- { "LangVersion", "langversion:ISO-1", "", "ISO-1", 0 },
- { "LangVersion", "langversion:ISO-2", "", "ISO-2", 0 },
- { "LangVersion", "langversion:3", "", "3", 0 },
- { "LangVersion", "langversion:4", "", "4", 0 },
- { "LangVersion", "langversion:5", "", "5", 0 },
- { "LangVersion", "langversion:6", "", "6", 0 },
- { "LangVersion", "langversion:default", "", "default", 0 },
-
- { "DelaySign", "delaysign", "", "true", 0 },
- { "DelaySign", "delaysign-", "", "false", 0 },
- { "DelaySign", "delaysign+", "", "true", 0 },
-
- { "AssemblyOriginatorKeyFile", "keyfile", "", "", 0 },
-
- { "KeyContainerName", "keycontainer", "", "", 0 },
-
- { "NoLogo", "nologo", "", "", 0 },
-
- { "NoConfig", "noconfig", "", "true", 0 },
-
- { "BaseAddress", "baseaddress:", "", "", 0 },
-
- { "CodePage", "codepage", "", "", 0 },
-
- { "Utf8Output", "utf8output", "", "", 0 },
-
- { "MainEntryPoint", "main:", "", "", 0 },
-
- { "GenerateFullPaths", "fullpaths", "", "true", 0 },
-
- { "FileAlignment", "filealign", "", "", 0 },
-
- { "PdbFile", "pdb:", "", "", 0 },
-
- { "NoStandardLib", "nostdlib", "", "true", 0 },
- { "NoStandardLib", "nostdlib-", "", "false", 0 },
- { "NoStandardLib", "nostdlib+", "", "true", 0 },
-
- { "SubsystemVersion", "subsystemversion", "", "", 0 },
-
- { "AdditionalLibPaths", "lib:", "", "", 0 },
-
- { "ErrorReport", "errorreport:none", "Do Not Send Report", "none", 0 },
- { "ErrorReport", "errorreport:prompt", "Prompt Immediately", "prompt", 0 },
- { "ErrorReport", "errorreport:queue", "Queue For Next Login", "queue", 0 },
- { "ErrorReport", "errorreport:send", "Send Automatically", "send", 0 },
-
- { 0, 0, 0, 0, 0 },
-};
diff --git a/Source/cmVS140LinkFlagTable.h b/Source/cmVS140LinkFlagTable.h
deleted file mode 100644
index b9a4dc30a..000000000
--- a/Source/cmVS140LinkFlagTable.h
+++ /dev/null
@@ -1,282 +0,0 @@
-static cmVS7FlagTable cmVS140LinkFlagTable[] = {
-
- // Enum Properties
- { "ShowProgress", "", "Not Set", "NotSet", 0 },
- { "ShowProgress", "VERBOSE", "Display all progress messages", "LinkVerbose",
- 0 },
- { "ShowProgress", "VERBOSE:Lib", "For Libraries Searched", "LinkVerboseLib",
- 0 },
- { "ShowProgress", "VERBOSE:ICF",
- "About COMDAT folding during optimized linking", "LinkVerboseICF", 0 },
- { "ShowProgress", "VERBOSE:REF",
- "About data removed during optimized linking", "LinkVerboseREF", 0 },
- { "ShowProgress", "VERBOSE:SAFESEH", "About Modules incompatible with SEH",
- "LinkVerboseSAFESEH", 0 },
- { "ShowProgress", "VERBOSE:CLR",
- "About linker activity related to managed code", "LinkVerboseCLR", 0 },
-
- { "ForceFileOutput", "FORCE", "Enabled", "Enabled", 0 },
- { "ForceFileOutput", "FORCE:MULTIPLE", "Multiply Defined Symbol Only",
- "MultiplyDefinedSymbolOnly", 0 },
- { "ForceFileOutput", "FORCE:UNRESOLVED", "Undefined Symbol Only",
- "UndefinedSymbolOnly", 0 },
-
- { "CreateHotPatchableImage", "FUNCTIONPADMIN", "Enabled", "Enabled", 0 },
- { "CreateHotPatchableImage", "FUNCTIONPADMIN:5", "X86 Image Only",
- "X86Image", 0 },
- { "CreateHotPatchableImage", "FUNCTIONPADMIN:6", "X64 Image Only",
- "X64Image", 0 },
- { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only",
- "ItaniumImage", 0 },
-
- { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 },
- { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable",
- "HighestAvailable", 0 },
- { "UACExecutionLevel", "level='requireAdministrator'",
- "requireAdministrator", "RequireAdministrator", 0 },
-
- { "GenerateDebugInformation", "DEBUG:FASTLINK",
- "Optimize for faster linking", "DebugFastLink",
- cmVS7FlagTable::CaseInsensitive },
- { "GenerateDebugInformation", "DEBUG:FULL", "Optimize for debugging", "true",
- cmVS7FlagTable::CaseInsensitive },
- { "GenerateDebugInformation", "DEBUG:NONE",
- "Produces no debugging information", "false",
- cmVS7FlagTable::CaseInsensitive },
- { "GenerateDebugInformation", "DEBUG", "Optimize for debugging", "true",
- cmVS7FlagTable::CaseInsensitive },
-
- { "SubSystem", "", "Not Set", "NotSet", 0 },
- { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 },
- { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 },
- { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application",
- "EFI Application", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER",
- "EFI Boot Service Driver", "EFI Boot Service Driver", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime",
- 0 },
- { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 },
-
- { "Driver", "", "Not Set", "NotSet", 0 },
- { "Driver", "Driver", "Driver", "Driver", 0 },
- { "Driver", "DRIVER:UPONLY", "UP Only", "UpOnly", 0 },
- { "Driver", "DRIVER:WDM", "WDM", "WDM", 0 },
-
- { "LinkTimeCodeGeneration", "", "Default", "Default", 0 },
- { "LinkTimeCodeGeneration", "LTCG:incremental",
- "Use Fast Link Time Code Generation", "UseFastLinkTimeCodeGeneration", 0 },
- { "LinkTimeCodeGeneration", "LTCG", "Use Link Time Code Generation",
- "UseLinkTimeCodeGeneration", 0 },
- { "LinkTimeCodeGeneration", "LTCG:PGInstrument",
- "Profile Guided Optimization - Instrument", "PGInstrument", 0 },
- { "LinkTimeCodeGeneration", "LTCG:PGOptimize",
- "Profile Guided Optimization - Optimization", "PGOptimization", 0 },
- { "LinkTimeCodeGeneration", "LTCG:PGUpdate",
- "Profile Guided Optimization - Update", "PGUpdate", 0 },
-
- { "GenerateWindowsMetadata", "WINMD", "Yes", "true", 0 },
- { "GenerateWindowsMetadata", "WINMD:NO", "No", "false", 0 },
-
- { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA1", "SHA1", "SHA1", 0 },
- { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA256", "SHA256", "SHA256", 0 },
- { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA384", "SHA384", "SHA384", 0 },
- { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA512", "SHA512", "SHA512", 0 },
-
- { "TargetMachine", "", "Not Set", "NotSet", 0 },
- { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 },
- { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 },
- { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 },
- { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 },
- { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 },
- { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU",
- 0 },
- { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16",
- "MachineMIPSFPU16", 0 },
- { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 },
- { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 },
- { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 },
- { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 },
-
- { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:MTA", "MTA threading attribute",
- "MTAThreadingAttribute", 0 },
- { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:STA", "STA threading attribute",
- "STAThreadingAttribute", 0 },
- { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:NONE",
- "Default threading attribute", "DefaultThreadingAttribute", 0 },
-
- { "CLRImageType", "CLRIMAGETYPE:IJW", "Force IJW image", "ForceIJWImage",
- 0 },
- { "CLRImageType", "CLRIMAGETYPE:PURE", "Force Pure IL Image",
- "ForcePureILImage", 0 },
- { "CLRImageType", "CLRIMAGETYPE:SAFE", "Force Safe IL Image",
- "ForceSafeILImage", 0 },
- { "CLRImageType", "", "Default image type", "Default", 0 },
-
- { "SignHash", "CLRSIGNHASH:SHA1", "SHA1", "SHA1", 0 },
- { "SignHash", "CLRSIGNHASH:SHA256", "SHA256", "SHA256", 0 },
- { "SignHash", "CLRSIGNHASH:SHA384", "SHA384", "SHA384", 0 },
- { "SignHash", "CLRSIGNHASH:SHA512", "SHA512", "SHA512", 0 },
-
- { "LinkErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately",
- "PromptImmediately", 0 },
- { "LinkErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login",
- "QueueForNextLogin", 0 },
- { "LinkErrorReporting", "ERRORREPORT:SEND", "Send Error Report",
- "SendErrorReport", 0 },
- { "LinkErrorReporting", "ERRORREPORT:NONE", "No Error Report",
- "NoErrorReport", 0 },
-
- { "CLRSupportLastError", "CLRSupportLastError", "Enabled", "Enabled", 0 },
- { "CLRSupportLastError", "CLRSupportLastError:NO", "Disabled", "Disabled",
- 0 },
- { "CLRSupportLastError", "CLRSupportLastError:SYSTEMDLL", "System Dlls Only",
- "SystemDlls", 0 },
-
- // Bool Properties
- { "LinkIncremental", "INCREMENTAL:NO", "", "false", 0 },
- { "LinkIncremental", "INCREMENTAL", "", "true", 0 },
- { "SuppressStartupBanner", "NOLOGO", "", "true", 0 },
- { "LinkStatus", "LTCG:NOSTATUS", "", "false", 0 },
- { "LinkStatus", "LTCG:STATUS", "", "true", 0 },
- { "PreventDllBinding", "ALLOWBIND:NO", "", "false", 0 },
- { "PreventDllBinding", "ALLOWBIND", "", "true", 0 },
- { "TreatLinkerWarningAsErrors", "WX:NO", "", "false", 0 },
- { "TreatLinkerWarningAsErrors", "WX", "", "true", 0 },
- { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 },
- { "GenerateManifest", "MANIFEST:NO", "", "false", 0 },
- { "GenerateManifest", "MANIFEST", "", "true", 0 },
- { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 },
- { "UACUIAccess", "uiAccess='false'", "", "false", 0 },
- { "UACUIAccess", "uiAccess='true'", "", "true", 0 },
- { "ManifestEmbed", "manifest:embed", "", "true", 0 },
- { "MapExports", "MAPINFO:EXPORTS", "", "true", 0 },
- { "AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0 },
- { "AssemblyDebug", "ASSEMBLYDEBUG", "", "true", 0 },
- { "LargeAddressAware", "LARGEADDRESSAWARE:NO", "", "false", 0 },
- { "LargeAddressAware", "LARGEADDRESSAWARE", "", "true", 0 },
- { "TerminalServerAware", "TSAWARE:NO", "", "false", 0 },
- { "TerminalServerAware", "TSAWARE", "", "true", 0 },
- { "SwapRunFromCD", "SWAPRUN:CD", "", "true", 0 },
- { "SwapRunFromNET", "SWAPRUN:NET", "", "true", 0 },
- { "OptimizeReferences", "OPT:NOREF", "", "false", 0 },
- { "OptimizeReferences", "OPT:REF", "", "true", 0 },
- { "EnableCOMDATFolding", "OPT:NOICF", "", "false", 0 },
- { "EnableCOMDATFolding", "OPT:ICF", "", "true", 0 },
- { "IgnoreEmbeddedIDL", "IGNOREIDL", "", "true", 0 },
- { "AppContainer", "APPCONTAINER", "", "true", 0 },
- { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN:NO", "", "false", 0 },
- { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN", "", "true", 0 },
- { "NoEntryPoint", "NOENTRY", "", "true", 0 },
- { "SetChecksum", "RELEASE", "", "true", 0 },
- { "RandomizedBaseAddress", "DYNAMICBASE:NO", "", "false", 0 },
- { "RandomizedBaseAddress", "DYNAMICBASE", "", "true", 0 },
- { "FixedBaseAddress", "FIXED:NO", "", "false", 0 },
- { "FixedBaseAddress", "FIXED", "", "true", 0 },
- { "DataExecutionPrevention", "NXCOMPAT:NO", "", "false", 0 },
- { "DataExecutionPrevention", "NXCOMPAT", "", "true", 0 },
- { "TurnOffAssemblyGeneration", "NOASSEMBLY", "", "true", 0 },
- { "SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0 },
- { "SupportNobindOfDelayLoadedDLL", "DELAY:NOBIND", "", "true", 0 },
- { "Profile", "PROFILE", "", "true", 0 },
- { "LinkDelaySign", "DELAYSIGN:NO", "", "false", 0 },
- { "LinkDelaySign", "DELAYSIGN", "", "true", 0 },
- { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0 },
- { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0 },
- { "DetectOneDefinitionRule", "ODR", "", "true", 0 },
- { "ImageHasSafeExceptionHandlers", "SAFESEH:NO", "", "false", 0 },
- { "ImageHasSafeExceptionHandlers", "SAFESEH", "", "true", 0 },
- { "LinkDLL", "DLL", "", "true", 0 },
-
- // Bool Properties With Argument
- { "EnableUAC", "MANIFESTUAC:NO", "", "false", 0 },
- { "EnableUAC", "MANIFESTUAC:", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "UACUIAccess", "MANIFESTUAC:", "Enable User Account Control (UAC)", "",
- cmVS7FlagTable::UserValueRequired },
- { "GenerateMapFile", "MAP", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "MapFileName", "MAP:", "Generate Map File", "",
- cmVS7FlagTable::UserValueRequired },
-
- // String List Properties
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "Natvis", "NATVIS:", "Natvis files", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- // Skip [AdditionalDependencies] - no command line Switch.
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly",
- "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "EmbedManagedResourceFile", "ASSEMBLYRESOURCE:",
- "Embed Managed Resource File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "DelayLoadDLLs", "DELAYLOAD:", "Delay Loaded Dlls", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource",
- "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AdditionalManifestDependencies", "MANIFESTDEPENDENCY:",
- "Additional Manifest Dependencies", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ManifestInput", "manifestinput:", "Manifest Input", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-
- // String Properties
- { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue },
- { "Version", "VERSION:", "Version", "", cmVS7FlagTable::UserValue },
- { "SpecifySectionAttributes", "SECTION:", "Specify Section Attributes", "",
- cmVS7FlagTable::UserValue },
- { "MSDOSStubFileName", "STUB:", "MS-DOS Stub File Name", "",
- cmVS7FlagTable::UserValue },
- // Skip [TrackerLogDirectory] - no command line Switch.
- { "ModuleDefinitionFile", "DEF:", "Module Definition File", "",
- cmVS7FlagTable::UserValue },
- { "ManifestFile", "ManifestFile:", "Manifest File", "",
- cmVS7FlagTable::UserValue },
- { "ProgramDatabaseFile", "PDB:", "Generate Program Database File", "",
- cmVS7FlagTable::UserValue },
- { "StripPrivateSymbols", "PDBSTRIPPED:", "Strip Private Symbols", "",
- cmVS7FlagTable::UserValue },
- // Skip [MapFileName] - no command line Switch.
- // Skip [MinimumRequiredVersion] - no command line Switch.
- { "HeapReserveSize", "HEAP:", "Heap Reserve Size", "",
- cmVS7FlagTable::UserValue },
- // Skip [HeapCommitSize] - no command line Switch.
- { "StackReserveSize", "STACK:", "Stack Reserve Size", "",
- cmVS7FlagTable::UserValue },
- // Skip [StackCommitSize] - no command line Switch.
- { "FunctionOrder", "ORDER:@", "Function Order", "",
- cmVS7FlagTable::UserValue },
- { "ProfileGuidedDatabase", "PGD:", "Profile Guided Database", "",
- cmVS7FlagTable::UserValue },
- { "MidlCommandFile", "MIDL:@", "MIDL Commands", "",
- cmVS7FlagTable::UserValue },
- { "MergedIDLBaseFileName", "IDLOUT:", "Merged IDL Base File Name", "",
- cmVS7FlagTable::UserValue },
- { "TypeLibraryFile", "TLBOUT:", "Type Library", "",
- cmVS7FlagTable::UserValue },
- { "WindowsMetadataFile", "WINMDFILE:", "Windows Metadata File", "",
- cmVS7FlagTable::UserValue },
- { "WindowsMetadataLinkKeyFile", "WINMDKEYFILE:", "Windows Metadata Key File",
- "", cmVS7FlagTable::UserValue },
- { "WindowsMetadataKeyContainer", "WINMDKEYCONTAINER:",
- "Windows Metadata Key Container", "", cmVS7FlagTable::UserValue },
- { "EntryPointSymbol", "ENTRY:", "Entry Point", "",
- cmVS7FlagTable::UserValue },
- { "BaseAddress", "BASE:", "Base Address", "", cmVS7FlagTable::UserValue },
- { "ImportLibrary", "IMPLIB:", "Import Library", "",
- cmVS7FlagTable::UserValue },
- { "MergeSections", "MERGE:", "Merge Sections", "",
- cmVS7FlagTable::UserValue },
- { "LinkKeyFile", "KEYFILE:", "Key File", "", cmVS7FlagTable::UserValue },
- { "KeyContainer", "KEYCONTAINER:", "Key Container", "",
- cmVS7FlagTable::UserValue },
- // Skip [AdditionalOptions] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS141CLFlagTable.h b/Source/cmVS141CLFlagTable.h
deleted file mode 100644
index f751fc875..000000000
--- a/Source/cmVS141CLFlagTable.h
+++ /dev/null
@@ -1,250 +0,0 @@
-static cmVS7FlagTable cmVS141CLFlagTable[] = {
-
- // Enum Properties
- { "DebugInformationFormat", "", "None", "None", 0 },
- { "DebugInformationFormat", "Z7", "C7 compatible", "OldStyle", 0 },
- { "DebugInformationFormat", "Zi", "Program Database", "ProgramDatabase", 0 },
- { "DebugInformationFormat", "ZI", "Program Database for Edit And Continue",
- "EditAndContinue", 0 },
-
- { "WarningLevel", "W0", "Turn Off All Warnings", "TurnOffAllWarnings", 0 },
- { "WarningLevel", "W1", "Level1", "Level1", 0 },
- { "WarningLevel", "W2", "Level2", "Level2", 0 },
- { "WarningLevel", "W3", "Level3", "Level3", 0 },
- { "WarningLevel", "W4", "Level4", "Level4", 0 },
- { "WarningLevel", "Wall", "EnableAllWarnings", "EnableAllWarnings", 0 },
-
- { "Optimization", "", "Custom", "Custom", 0 },
- { "Optimization", "Od", "Disabled", "Disabled", 0 },
- { "Optimization", "O1", "Minimize Size", "MinSpace", 0 },
- { "Optimization", "O2", "Maximize Speed", "MaxSpeed", 0 },
- { "Optimization", "Ox", "Full Optimization", "Full", 0 },
-
- { "InlineFunctionExpansion", "", "Default", "Default", 0 },
- { "InlineFunctionExpansion", "Ob0", "Disabled", "Disabled", 0 },
- { "InlineFunctionExpansion", "Ob1", "Only __inline", "OnlyExplicitInline",
- 0 },
- { "InlineFunctionExpansion", "Ob2", "Any Suitable", "AnySuitable", 0 },
-
- { "FavorSizeOrSpeed", "Os", "Favor small code", "Size", 0 },
- { "FavorSizeOrSpeed", "Ot", "Favor fast code", "Speed", 0 },
- { "FavorSizeOrSpeed", "", "Neither", "Neither", 0 },
-
- { "ExceptionHandling", "EHa", "Yes with SEH Exceptions", "Async", 0 },
- { "ExceptionHandling", "EHsc", "Yes", "Sync", 0 },
- { "ExceptionHandling", "EHs", "Yes with Extern C functions", "SyncCThrow",
- 0 },
- { "ExceptionHandling", "", "No", "false", 0 },
-
- { "BasicRuntimeChecks", "RTCs", "Stack Frames", "StackFrameRuntimeCheck",
- 0 },
- { "BasicRuntimeChecks", "RTCu", "Uninitialized variables",
- "UninitializedLocalUsageCheck", 0 },
- { "BasicRuntimeChecks", "RTC1", "Both (/RTC1, equiv. to /RTCsu)",
- "EnableFastChecks", 0 },
- { "BasicRuntimeChecks", "", "Default", "Default", 0 },
-
- { "RuntimeLibrary", "MT", "Multi-threaded", "MultiThreaded", 0 },
- { "RuntimeLibrary", "MTd", "Multi-threaded Debug", "MultiThreadedDebug", 0 },
- { "RuntimeLibrary", "MD", "Multi-threaded DLL", "MultiThreadedDLL", 0 },
- { "RuntimeLibrary", "MDd", "Multi-threaded Debug DLL",
- "MultiThreadedDebugDLL", 0 },
-
- { "StructMemberAlignment", "Zp1", "1 Byte", "1Byte", 0 },
- { "StructMemberAlignment", "Zp2", "2 Bytes", "2Bytes", 0 },
- { "StructMemberAlignment", "Zp4", "4 Byte", "4Bytes", 0 },
- { "StructMemberAlignment", "Zp8", "8 Bytes", "8Bytes", 0 },
- { "StructMemberAlignment", "Zp16", "16 Bytes", "16Bytes", 0 },
- { "StructMemberAlignment", "", "Default", "Default", 0 },
-
- { "BufferSecurityCheck", "GS-", "Disable Security Check", "false", 0 },
- { "BufferSecurityCheck", "GS", "Enable Security Check", "true", 0 },
-
- { "ControlFlowGuard", "guard:cf", "Yes", "Guard", 0 },
- { "ControlFlowGuard", "", "No", "false", 0 },
-
- { "EnableEnhancedInstructionSet", "arch:SSE", "Streaming SIMD Extensions",
- "StreamingSIMDExtensions", 0 },
- { "EnableEnhancedInstructionSet", "arch:SSE2", "Streaming SIMD Extensions 2",
- "StreamingSIMDExtensions2", 0 },
- { "EnableEnhancedInstructionSet", "arch:AVX", "Advanced Vector Extensions",
- "AdvancedVectorExtensions", 0 },
- { "EnableEnhancedInstructionSet", "arch:AVX2",
- "Advanced Vector Extensions 2", "AdvancedVectorExtensions2", 0 },
- { "EnableEnhancedInstructionSet", "arch:IA32", "No Enhanced Instructions",
- "NoExtensions", 0 },
- { "EnableEnhancedInstructionSet", "", "Not Set", "NotSet", 0 },
-
- { "FloatingPointModel", "fp:precise", "Precise", "Precise", 0 },
- { "FloatingPointModel", "fp:strict", "Strict", "Strict", 0 },
- { "FloatingPointModel", "fp:fast", "Fast", "Fast", 0 },
-
- { "LanguageStandard", "std:c++14", "ISO C++14 Standard", "stdcpp14", 0 },
- { "LanguageStandard", "std:c++latest", "ISO C++ Latest Draft Standard",
- "stdcpplatest", 0 },
-
- { "PrecompiledHeader", "Yc", "Create", "Create",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "PrecompiledHeader", "Yu", "Use", "Use",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "PrecompiledHeader", "", "Not Using Precompiled Headers", "NotUsing", 0 },
-
- { "AssemblerOutput", "", "No Listing", "NoListing", 0 },
- { "AssemblerOutput", "FA", "Assembly-Only Listing", "AssemblyCode", 0 },
- { "AssemblerOutput", "FAc", "Assembly With Machine Code",
- "AssemblyAndMachineCode", 0 },
- { "AssemblerOutput", "FAs", "Assembly With Source Code",
- "AssemblyAndSourceCode", 0 },
- { "AssemblerOutput", "FAcs", "Assembly, Machine Code and Source", "All", 0 },
-
- { "CallingConvention", "Gd", "__cdecl", "Cdecl", 0 },
- { "CallingConvention", "Gr", "__fastcall", "FastCall", 0 },
- { "CallingConvention", "Gz", "__stdcall", "StdCall", 0 },
- { "CallingConvention", "Gv", "__vectorcall", "VectorCall", 0 },
-
- { "CompileAs", "", "Default", "Default", 0 },
- { "CompileAs", "TC", "Compile as C Code", "CompileAsC", 0 },
- { "CompileAs", "TP", "Compile as C++ Code", "CompileAsCpp", 0 },
-
- { "ErrorReporting", "errorReport:none", "Do Not Send Report", "None", 0 },
- { "ErrorReporting", "errorReport:prompt", "Prompt Immediately", "Prompt",
- 0 },
- { "ErrorReporting", "errorReport:queue", "Queue For Next Login", "Queue",
- 0 },
- { "ErrorReporting", "errorReport:send", "Send Automatically", "Send", 0 },
-
- { "CompileAsManaged", "", "No Common Language RunTime Support", "false", 0 },
- { "CompileAsManaged", "clr", "Common Language RunTime Support", "true", 0 },
- { "CompileAsManaged", "clr:pure",
- "Pure MSIL Common Language RunTime Support", "Pure", 0 },
- { "CompileAsManaged", "clr:safe",
- "Safe MSIL Common Language RunTime Support", "Safe", 0 },
- { "CompileAsManaged", "clr:oldSyntax",
- "Common Language RunTime Support, Old Syntax", "OldSyntax", 0 },
-
- { "CppLanguageStandard", "", "Default", "Default", 0 },
- { "CppLanguageStandard", "std=c++98", "C++03", "c++98", 0 },
- { "CppLanguageStandard", "std=c++11", "C++11", "c++11", 0 },
- { "CppLanguageStandard", "std=c++1y", "C++14", "c++1y", 0 },
- { "CppLanguageStandard", "std=c++14", "C++14", "c++1y", 0 },
- { "CppLanguageStandard", "std=gnu++98", "C++03 (GNU Dialect)", "gnu++98",
- 0 },
- { "CppLanguageStandard", "std=gnu++11", "C++11 (GNU Dialect)", "gnu++11",
- 0 },
- { "CppLanguageStandard", "std=gnu++1y", "C++14 (GNU Dialect)", "gnu++1y",
- 0 },
- { "CppLanguageStandard", "std=gnu++14", "C++14 (GNU Dialect)", "gnu++1y",
- 0 },
-
- // Bool Properties
- { "CompileAsWinRT", "ZW", "", "true", 0 },
- { "WinRTNoStdLib", "ZW:nostdlib", "", "true", 0 },
- { "SuppressStartupBanner", "nologo", "", "true", 0 },
- { "TreatWarningAsError", "WX-", "", "false", 0 },
- { "TreatWarningAsError", "WX", "", "true", 0 },
- { "SDLCheck", "sdl-", "", "false", 0 },
- { "SDLCheck", "sdl", "", "true", 0 },
- { "IntrinsicFunctions", "Oi", "", "true", 0 },
- { "OmitFramePointers", "Oy-", "", "false", 0 },
- { "OmitFramePointers", "Oy", "", "true", 0 },
- { "EnableFiberSafeOptimizations", "GT", "", "true", 0 },
- { "WholeProgramOptimization", "GL", "", "true", 0 },
- { "UndefineAllPreprocessorDefinitions", "u", "", "true", 0 },
- { "IgnoreStandardIncludePath", "X", "", "true", 0 },
- { "PreprocessToFile", "P", "", "true", 0 },
- { "PreprocessSuppressLineNumbers", "EP", "", "true", 0 },
- { "PreprocessKeepComments", "C", "", "true", 0 },
- { "StringPooling", "GF-", "", "false", 0 },
- { "StringPooling", "GF", "", "true", 0 },
- { "MinimalRebuild", "Gm-", "", "false", 0 },
- { "MinimalRebuild", "Gm", "", "true", 0 },
- { "SmallerTypeCheck", "RTCc", "", "true", 0 },
- { "FunctionLevelLinking", "Gy-", "", "false", 0 },
- { "FunctionLevelLinking", "Gy", "", "true", 0 },
- { "EnableParallelCodeGeneration", "Qpar-", "", "false", 0 },
- { "EnableParallelCodeGeneration", "Qpar", "", "true", 0 },
- { "FloatingPointExceptions", "fp:except-", "", "false", 0 },
- { "FloatingPointExceptions", "fp:except", "", "true", 0 },
- { "CreateHotpatchableImage", "hotpatch", "", "true", 0 },
- { "DisableLanguageExtensions", "Za", "", "true", 0 },
- { "TreatWChar_tAsBuiltInType", "Zc:wchar_t-", "", "false", 0 },
- { "TreatWChar_tAsBuiltInType", "Zc:wchar_t", "", "true", 0 },
- { "ForceConformanceInForLoopScope", "Zc:forScope-", "", "false", 0 },
- { "ForceConformanceInForLoopScope", "Zc:forScope", "", "true", 0 },
- { "RemoveUnreferencedCodeData", "Zc:inline-", "", "false", 0 },
- { "RemoveUnreferencedCodeData", "Zc:inline", "", "true", 0 },
- { "EnforceTypeConversionRules", "Zc:rvalueCast-", "", "false", 0 },
- { "EnforceTypeConversionRules", "Zc:rvalueCast", "", "true", 0 },
- { "RuntimeTypeInfo", "GR-", "", "false", 0 },
- { "RuntimeTypeInfo", "GR", "", "true", 0 },
- { "OpenMPSupport", "openmp-", "", "false", 0 },
- { "OpenMPSupport", "openmp", "", "true", 0 },
- { "ExpandAttributedSource", "Fx", "", "true", 0 },
- { "UseUnicodeForAssemblerListing", "FAu", "", "true", 0 },
- { "ShowIncludes", "showIncludes", "", "true", 0 },
- { "EnablePREfast", "analyze-", "", "false", 0 },
- { "EnablePREfast", "analyze", "", "true", 0 },
- { "UseFullPaths", "FC", "", "true", 0 },
- { "OmitDefaultLibName", "Zl", "", "true", 0 },
-
- // Bool Properties With Argument
- { "MultiProcessorCompilation", "MP", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "ProcessorNumber", "MP", "Multi-processor Compilation", "",
- cmVS7FlagTable::UserValueRequired },
- { "GenerateXMLDocumentationFiles", "doc", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "XMLDocumentationFileName", "doc", "Generate XML Documentation Files", "",
- cmVS7FlagTable::UserValueRequired },
- { "BrowseInformation", "FR", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "BrowseInformationFile", "FR", "Enable Browse Information", "",
- cmVS7FlagTable::UserValueRequired },
-
- // String List Properties
- { "AdditionalIncludeDirectories", "I", "Additional Include Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AdditionalUsingDirectories", "AI", "Additional #using Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "PreprocessorDefinitions", "D ", "Preprocessor Definitions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "UndefinePreprocessorDefinitions", "U",
- "Undefine Preprocessor Definitions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "DisableSpecificWarnings", "wd", "Disable Specific Warnings", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ForcedIncludeFiles", "FI", "Forced Include File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ForcedUsingFiles", "FU", "Forced #using File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "PREfastLog", "analyze:log", "Code Analysis Log", "",
- cmVS7FlagTable::UserFollowing },
- { "PREfastAdditionalPlugins", "analyze:plugin",
- "Additional Code Analysis Native plugins", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "TreatSpecificWarningsAsErrors", "we", "Treat Specific Warnings As Errors",
- "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-
- // String Properties
- { "WarningVersion", "Wv:", "Warning Version", "",
- cmVS7FlagTable::UserValue },
- // Skip [TrackerLogDirectory] - no command line Switch.
- { "PreprocessOutputPath", "Fi", "Preprocess Output Path", "",
- cmVS7FlagTable::UserValue },
- { "PrecompiledHeaderFile", "Yc", "Precompiled Header Name", "",
- cmVS7FlagTable::UserValueRequired },
- { "PrecompiledHeaderFile", "Yu", "Precompiled Header Name", "",
- cmVS7FlagTable::UserValueRequired },
- { "PrecompiledHeaderOutputFile", "Fp", "Precompiled Header Output File", "",
- cmVS7FlagTable::UserValue },
- { "AssemblerListingLocation", "Fa", "ASM List Location", "",
- cmVS7FlagTable::UserValue },
- { "ObjectFileName", "Fo", "Object File Name", "",
- cmVS7FlagTable::UserValue },
- { "ProgramDataBaseFileName", "Fd", "Program Database File Name", "",
- cmVS7FlagTable::UserValue },
- // Skip [XMLDocumentationFileName] - no command line Switch.
- // Skip [BrowseInformationFile] - no command line Switch.
- // Skip [AdditionalOptions] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS141CSharpFlagTable.h b/Source/cmVS141CSharpFlagTable.h
deleted file mode 100644
index 85085817c..000000000
--- a/Source/cmVS141CSharpFlagTable.h
+++ /dev/null
@@ -1,120 +0,0 @@
-static cmVS7FlagTable cmVS141CSharpFlagTable[] = {
- { "ProjectName", "out:", "", "", cmIDEFlagTable::UserValueRequired },
-
- { "OutputType", "target:exe", "", "Exe", 0 },
- { "OutputType", "target:winexe", "", "Winexe", 0 },
- { "OutputType", "target:library", "", "Library", 0 },
- { "OutputType", "target:module", "", "Module", 0 },
-
- { "DocumentationFile", "doc", "", "", cmIDEFlagTable::UserValueRequired },
-
- { "Platform", "platform:x86", "", "x86", 0 },
- { "Platform", "platform:Itanium", "", "Itanium", 0 },
- { "Platform", "platform:x64", "", "x64", 0 },
- { "Platform", "platform:arm", "", "arm", 0 },
- { "Platform", "platform:anycpu32bitpreferred", "", "anycpu32bitpreferred",
- 0 },
- { "Platform", "platform:anycpu", "", "anycpu", 0 },
-
- { "References", "reference:", "mit alias", "", 0 },
- { "References", "reference:", "dateiliste", "", 0 },
- { "AddModules", "addmodule:", "", "", cmIDEFlagTable::SemicolonAppendable },
- { "", "link", "", "", 0 },
-
- { "Win32Resource", "win32res", "", "", cmIDEFlagTable::UserValueRequired },
- { "ApplicationIcon", "win32icon", "", "",
- cmIDEFlagTable::UserValueRequired },
-
- { "Win32Manifest", "win32manifest:", "", "true", 0 },
-
- { "NoWin32Manifest", "nowin32manifest", "", "true", 0 },
-
- { "DefineDebug", "debug", "", "true", cmIDEFlagTable::Continue },
-
- { "DebugSymbols", "debug", "", "true", 0 },
- { "DebugSymbols", "debug-", "", "false", 0 },
- { "DebugSymbols", "debug+", "", "true", 0 },
-
- { "DebugType", "debug:none", "", "none", 0 },
- { "DebugType", "debug:full", "", "full", 0 },
- { "DebugType", "debug:pdbonly", "", "pdbonly", 0 },
-
- { "Optimize", "optimize", "", "true", 0 },
- { "Optimize", "optimize-", "", "false", 0 },
- { "Optimize", "optimize+", "", "true", 0 },
-
- { "TreatWarningsAsErrors", "warnaserror", "", "true", 0 },
- { "TreatWarningsAsErrors", "warnaserror-", "", "false", 0 },
- { "TreatWarningsAsErrors", "warnaserror+", "", "true", 0 },
-
- { "WarningsAsErrors", "warnaserror", "", "", 0 },
- { "WarningsAsErrors", "warnaserror-", "", "", 0 },
- { "WarningsAsErrors", "warnaserror+", "", "", 0 },
-
- { "WarningLevel", "warn:0", "", "0", 0 },
- { "WarningLevel", "warn:1", "", "1", 0 },
- { "WarningLevel", "warn:2", "", "2", 0 },
- { "WarningLevel", "warn:3", "", "3", 0 },
- { "WarningLevel", "warn:4", "", "4", 0 },
- { "DisabledWarnings", "nowarn", "", "", 0 },
-
- { "CheckForOverflowUnderflow", "checked", "", "true", 0 },
- { "CheckForOverflowUnderflow", "checked-", "", "false", 0 },
- { "CheckForOverflowUnderflow", "checked+", "", "true", 0 },
-
- { "AllowUnsafeBlocks", "unsafe", "", "true", 0 },
- { "AllowUnsafeBlocks", "unsafe-", "", "false", 0 },
- { "AllowUnsafeBlocks", "unsafe+", "", "true", 0 },
-
- { "DefineConstants", "define:", "", "",
- cmIDEFlagTable::SemicolonAppendable | cmIDEFlagTable::UserValue },
-
- { "LangVersion", "langversion:ISO-1", "", "ISO-1", 0 },
- { "LangVersion", "langversion:ISO-2", "", "ISO-2", 0 },
- { "LangVersion", "langversion:3", "", "3", 0 },
- { "LangVersion", "langversion:4", "", "4", 0 },
- { "LangVersion", "langversion:5", "", "5", 0 },
- { "LangVersion", "langversion:6", "", "6", 0 },
- { "LangVersion", "langversion:default", "", "default", 0 },
-
- { "DelaySign", "delaysign", "", "true", 0 },
- { "DelaySign", "delaysign-", "", "false", 0 },
- { "DelaySign", "delaysign+", "", "true", 0 },
-
- { "AssemblyOriginatorKeyFile", "keyfile", "", "", 0 },
-
- { "KeyContainerName", "keycontainer", "", "", 0 },
-
- { "NoLogo", "nologo", "", "", 0 },
-
- { "NoConfig", "noconfig", "", "true", 0 },
-
- { "BaseAddress", "baseaddress:", "", "", 0 },
-
- { "CodePage", "codepage", "", "", 0 },
-
- { "Utf8Output", "utf8output", "", "", 0 },
-
- { "MainEntryPoint", "main:", "", "", 0 },
-
- { "GenerateFullPaths", "fullpaths", "", "true", 0 },
-
- { "FileAlignment", "filealign", "", "", 0 },
-
- { "PdbFile", "pdb:", "", "", 0 },
-
- { "NoStandardLib", "nostdlib", "", "true", 0 },
- { "NoStandardLib", "nostdlib-", "", "false", 0 },
- { "NoStandardLib", "nostdlib+", "", "true", 0 },
-
- { "SubsystemVersion", "subsystemversion", "", "", 0 },
-
- { "AdditionalLibPaths", "lib:", "", "", 0 },
-
- { "ErrorReport", "errorreport:none", "Do Not Send Report", "none", 0 },
- { "ErrorReport", "errorreport:prompt", "Prompt Immediately", "prompt", 0 },
- { "ErrorReport", "errorreport:queue", "Queue For Next Login", "queue", 0 },
- { "ErrorReport", "errorreport:send", "Send Automatically", "send", 0 },
-
- { 0, 0, 0, 0, 0 },
-};
diff --git a/Source/cmVS141LinkFlagTable.h b/Source/cmVS141LinkFlagTable.h
deleted file mode 100644
index 8f0f1f42d..000000000
--- a/Source/cmVS141LinkFlagTable.h
+++ /dev/null
@@ -1,283 +0,0 @@
-static cmVS7FlagTable cmVS141LinkFlagTable[] = {
-
- // Enum Properties
- { "ShowProgress", "", "Not Set", "NotSet", 0 },
- { "ShowProgress", "VERBOSE", "Display all progress messages", "LinkVerbose",
- 0 },
- { "ShowProgress", "VERBOSE:Lib", "For Libraries Searched", "LinkVerboseLib",
- 0 },
- { "ShowProgress", "VERBOSE:ICF",
- "About COMDAT folding during optimized linking", "LinkVerboseICF", 0 },
- { "ShowProgress", "VERBOSE:REF",
- "About data removed during optimized linking", "LinkVerboseREF", 0 },
- { "ShowProgress", "VERBOSE:SAFESEH", "About Modules incompatible with SEH",
- "LinkVerboseSAFESEH", 0 },
- { "ShowProgress", "VERBOSE:CLR",
- "About linker activity related to managed code", "LinkVerboseCLR", 0 },
-
- { "ForceFileOutput", "FORCE", "Enabled", "Enabled", 0 },
- { "ForceFileOutput", "FORCE:MULTIPLE", "Multiply Defined Symbol Only",
- "MultiplyDefinedSymbolOnly", 0 },
- { "ForceFileOutput", "FORCE:UNRESOLVED", "Undefined Symbol Only",
- "UndefinedSymbolOnly", 0 },
-
- { "CreateHotPatchableImage", "FUNCTIONPADMIN", "Enabled", "Enabled", 0 },
- { "CreateHotPatchableImage", "FUNCTIONPADMIN:5", "X86 Image Only",
- "X86Image", 0 },
- { "CreateHotPatchableImage", "FUNCTIONPADMIN:6", "X64 Image Only",
- "X64Image", 0 },
- { "CreateHotPatchableImage", "FUNCTIONPADMIN:16", "Itanium Image Only",
- "ItaniumImage", 0 },
-
- { "UACExecutionLevel", "level='asInvoker'", "asInvoker", "AsInvoker", 0 },
- { "UACExecutionLevel", "level='highestAvailable'", "highestAvailable",
- "HighestAvailable", 0 },
- { "UACExecutionLevel", "level='requireAdministrator'",
- "requireAdministrator", "RequireAdministrator", 0 },
-
- { "GenerateDebugInformation", "DEBUG:FASTLINK",
- "Generate Debug Information optimized for faster links", "DebugFastLink",
- cmVS7FlagTable::CaseInsensitive },
- { "GenerateDebugInformation", "DEBUG:FULL",
- "Generate Debug Information optimized for sharing and publishing",
- "DebugFull", cmVS7FlagTable::CaseInsensitive },
- { "GenerateDebugInformation", "DEBUG:NONE",
- "Produces no debugging information", "false",
- cmVS7FlagTable::CaseInsensitive },
- { "GenerateDebugInformation", "DEBUG", "Generate Debug Information", "true",
- cmVS7FlagTable::CaseInsensitive },
-
- { "SubSystem", "", "Not Set", "NotSet", 0 },
- { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 },
- { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 },
- { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application",
- "EFI Application", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER",
- "EFI Boot Service Driver", "EFI Boot Service Driver", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime",
- 0 },
- { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 },
-
- { "Driver", "", "Not Set", "NotSet", 0 },
- { "Driver", "Driver", "Driver", "Driver", 0 },
- { "Driver", "DRIVER:UPONLY", "UP Only", "UpOnly", 0 },
- { "Driver", "DRIVER:WDM", "WDM", "WDM", 0 },
-
- { "LinkTimeCodeGeneration", "", "Default", "Default", 0 },
- { "LinkTimeCodeGeneration", "LTCG:incremental",
- "Use Fast Link Time Code Generation", "UseFastLinkTimeCodeGeneration", 0 },
- { "LinkTimeCodeGeneration", "LTCG", "Use Link Time Code Generation",
- "UseLinkTimeCodeGeneration", 0 },
- { "LinkTimeCodeGeneration", "LTCG:PGInstrument",
- "Profile Guided Optimization - Instrument", "PGInstrument", 0 },
- { "LinkTimeCodeGeneration", "LTCG:PGOptimize",
- "Profile Guided Optimization - Optimization", "PGOptimization", 0 },
- { "LinkTimeCodeGeneration", "LTCG:PGUpdate",
- "Profile Guided Optimization - Update", "PGUpdate", 0 },
-
- { "GenerateWindowsMetadata", "WINMD", "Yes", "true", 0 },
- { "GenerateWindowsMetadata", "WINMD:NO", "No", "false", 0 },
-
- { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA1", "SHA1", "SHA1", 0 },
- { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA256", "SHA256", "SHA256", 0 },
- { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA384", "SHA384", "SHA384", 0 },
- { "WindowsMetadataSignHash", "WINMDSIGNHASH:SHA512", "SHA512", "SHA512", 0 },
-
- { "TargetMachine", "", "Not Set", "NotSet", 0 },
- { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 },
- { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 },
- { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 },
- { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 },
- { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 },
- { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU",
- 0 },
- { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16",
- "MachineMIPSFPU16", 0 },
- { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 },
- { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 },
- { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 },
- { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 },
-
- { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:MTA", "MTA threading attribute",
- "MTAThreadingAttribute", 0 },
- { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:STA", "STA threading attribute",
- "STAThreadingAttribute", 0 },
- { "CLRThreadAttribute", "CLRTHREADATTRIBUTE:NONE",
- "Default threading attribute", "DefaultThreadingAttribute", 0 },
-
- { "CLRImageType", "CLRIMAGETYPE:IJW", "Force IJW image", "ForceIJWImage",
- 0 },
- { "CLRImageType", "CLRIMAGETYPE:PURE", "Force Pure IL Image",
- "ForcePureILImage", 0 },
- { "CLRImageType", "CLRIMAGETYPE:SAFE", "Force Safe IL Image",
- "ForceSafeILImage", 0 },
- { "CLRImageType", "", "Default image type", "Default", 0 },
-
- { "SignHash", "CLRSIGNHASH:SHA1", "SHA1", "SHA1", 0 },
- { "SignHash", "CLRSIGNHASH:SHA256", "SHA256", "SHA256", 0 },
- { "SignHash", "CLRSIGNHASH:SHA384", "SHA384", "SHA384", 0 },
- { "SignHash", "CLRSIGNHASH:SHA512", "SHA512", "SHA512", 0 },
-
- { "LinkErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately",
- "PromptImmediately", 0 },
- { "LinkErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login",
- "QueueForNextLogin", 0 },
- { "LinkErrorReporting", "ERRORREPORT:SEND", "Send Error Report",
- "SendErrorReport", 0 },
- { "LinkErrorReporting", "ERRORREPORT:NONE", "No Error Report",
- "NoErrorReport", 0 },
-
- { "CLRSupportLastError", "CLRSupportLastError", "Enabled", "Enabled", 0 },
- { "CLRSupportLastError", "CLRSupportLastError:NO", "Disabled", "Disabled",
- 0 },
- { "CLRSupportLastError", "CLRSupportLastError:SYSTEMDLL", "System Dlls Only",
- "SystemDlls", 0 },
-
- // Bool Properties
- { "LinkIncremental", "INCREMENTAL:NO", "", "false", 0 },
- { "LinkIncremental", "INCREMENTAL", "", "true", 0 },
- { "SuppressStartupBanner", "NOLOGO", "", "true", 0 },
- { "LinkStatus", "LTCG:NOSTATUS", "", "false", 0 },
- { "LinkStatus", "LTCG:STATUS", "", "true", 0 },
- { "PreventDllBinding", "ALLOWBIND:NO", "", "false", 0 },
- { "PreventDllBinding", "ALLOWBIND", "", "true", 0 },
- { "TreatLinkerWarningAsErrors", "WX:NO", "", "false", 0 },
- { "TreatLinkerWarningAsErrors", "WX", "", "true", 0 },
- { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 },
- { "GenerateManifest", "MANIFEST:NO", "", "false", 0 },
- { "GenerateManifest", "MANIFEST", "", "true", 0 },
- { "AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0 },
- { "UACUIAccess", "uiAccess='false'", "", "false", 0 },
- { "UACUIAccess", "uiAccess='true'", "", "true", 0 },
- { "ManifestEmbed", "manifest:embed", "", "true", 0 },
- { "MapExports", "MAPINFO:EXPORTS", "", "true", 0 },
- { "AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0 },
- { "AssemblyDebug", "ASSEMBLYDEBUG", "", "true", 0 },
- { "LargeAddressAware", "LARGEADDRESSAWARE:NO", "", "false", 0 },
- { "LargeAddressAware", "LARGEADDRESSAWARE", "", "true", 0 },
- { "TerminalServerAware", "TSAWARE:NO", "", "false", 0 },
- { "TerminalServerAware", "TSAWARE", "", "true", 0 },
- { "SwapRunFromCD", "SWAPRUN:CD", "", "true", 0 },
- { "SwapRunFromNET", "SWAPRUN:NET", "", "true", 0 },
- { "OptimizeReferences", "OPT:NOREF", "", "false", 0 },
- { "OptimizeReferences", "OPT:REF", "", "true", 0 },
- { "EnableCOMDATFolding", "OPT:NOICF", "", "false", 0 },
- { "EnableCOMDATFolding", "OPT:ICF", "", "true", 0 },
- { "IgnoreEmbeddedIDL", "IGNOREIDL", "", "true", 0 },
- { "AppContainer", "APPCONTAINER", "", "true", 0 },
- { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN:NO", "", "false", 0 },
- { "WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN", "", "true", 0 },
- { "NoEntryPoint", "NOENTRY", "", "true", 0 },
- { "SetChecksum", "RELEASE", "", "true", 0 },
- { "RandomizedBaseAddress", "DYNAMICBASE:NO", "", "false", 0 },
- { "RandomizedBaseAddress", "DYNAMICBASE", "", "true", 0 },
- { "FixedBaseAddress", "FIXED:NO", "", "false", 0 },
- { "FixedBaseAddress", "FIXED", "", "true", 0 },
- { "DataExecutionPrevention", "NXCOMPAT:NO", "", "false", 0 },
- { "DataExecutionPrevention", "NXCOMPAT", "", "true", 0 },
- { "TurnOffAssemblyGeneration", "NOASSEMBLY", "", "true", 0 },
- { "SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0 },
- { "SupportNobindOfDelayLoadedDLL", "DELAY:NOBIND", "", "true", 0 },
- { "Profile", "PROFILE", "", "true", 0 },
- { "LinkDelaySign", "DELAYSIGN:NO", "", "false", 0 },
- { "LinkDelaySign", "DELAYSIGN", "", "true", 0 },
- { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0 },
- { "CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0 },
- { "DetectOneDefinitionRule", "ODR", "", "true", 0 },
- { "ImageHasSafeExceptionHandlers", "SAFESEH:NO", "", "false", 0 },
- { "ImageHasSafeExceptionHandlers", "SAFESEH", "", "true", 0 },
- { "LinkDLL", "DLL", "", "true", 0 },
-
- // Bool Properties With Argument
- { "EnableUAC", "MANIFESTUAC:NO", "", "false", 0 },
- { "EnableUAC", "MANIFESTUAC:", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "UACUIAccess", "MANIFESTUAC:", "Enable User Account Control (UAC)", "",
- cmVS7FlagTable::UserValueRequired },
- { "GenerateMapFile", "MAP", "", "true",
- cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
- { "MapFileName", "MAP:", "Generate Map File", "",
- cmVS7FlagTable::UserValueRequired },
-
- // String List Properties
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "Natvis", "NATVIS:", "Natvis files", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- // Skip [AdditionalDependencies] - no command line Switch.
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AddModuleNamesToAssembly", "ASSEMBLYMODULE:", "Add Module to Assembly",
- "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "EmbedManagedResourceFile", "ASSEMBLYRESOURCE:",
- "Embed Managed Resource File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "DelayLoadDLLs", "DELAYLOAD:", "Delay Loaded Dlls", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:", "Assembly Link Resource",
- "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "AdditionalManifestDependencies", "MANIFESTDEPENDENCY:",
- "Additional Manifest Dependencies", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ManifestInput", "manifestinput:", "Manifest Input", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-
- // String Properties
- { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue },
- { "Version", "VERSION:", "Version", "", cmVS7FlagTable::UserValue },
- { "SpecifySectionAttributes", "SECTION:", "Specify Section Attributes", "",
- cmVS7FlagTable::UserValue },
- { "MSDOSStubFileName", "STUB:", "MS-DOS Stub File Name", "",
- cmVS7FlagTable::UserValue },
- // Skip [TrackerLogDirectory] - no command line Switch.
- { "ModuleDefinitionFile", "DEF:", "Module Definition File", "",
- cmVS7FlagTable::UserValue },
- { "ManifestFile", "ManifestFile:", "Manifest File", "",
- cmVS7FlagTable::UserValue },
- { "ProgramDatabaseFile", "PDB:", "Generate Program Database File", "",
- cmVS7FlagTable::UserValue },
- { "StripPrivateSymbols", "PDBSTRIPPED:", "Strip Private Symbols", "",
- cmVS7FlagTable::UserValue },
- // Skip [MapFileName] - no command line Switch.
- // Skip [MinimumRequiredVersion] - no command line Switch.
- { "HeapReserveSize", "HEAP:", "Heap Reserve Size", "",
- cmVS7FlagTable::UserValue },
- // Skip [HeapCommitSize] - no command line Switch.
- { "StackReserveSize", "STACK:", "Stack Reserve Size", "",
- cmVS7FlagTable::UserValue },
- // Skip [StackCommitSize] - no command line Switch.
- { "FunctionOrder", "ORDER:@", "Function Order", "",
- cmVS7FlagTable::UserValue },
- { "ProfileGuidedDatabase", "PGD:", "Profile Guided Database", "",
- cmVS7FlagTable::UserValue },
- { "MidlCommandFile", "MIDL:@", "MIDL Commands", "",
- cmVS7FlagTable::UserValue },
- { "MergedIDLBaseFileName", "IDLOUT:", "Merged IDL Base File Name", "",
- cmVS7FlagTable::UserValue },
- { "TypeLibraryFile", "TLBOUT:", "Type Library", "",
- cmVS7FlagTable::UserValue },
- { "WindowsMetadataFile", "WINMDFILE:", "Windows Metadata File", "",
- cmVS7FlagTable::UserValue },
- { "WindowsMetadataLinkKeyFile", "WINMDKEYFILE:", "Windows Metadata Key File",
- "", cmVS7FlagTable::UserValue },
- { "WindowsMetadataKeyContainer", "WINMDKEYCONTAINER:",
- "Windows Metadata Key Container", "", cmVS7FlagTable::UserValue },
- { "EntryPointSymbol", "ENTRY:", "Entry Point", "",
- cmVS7FlagTable::UserValue },
- { "BaseAddress", "BASE:", "Base Address", "", cmVS7FlagTable::UserValue },
- { "ImportLibrary", "IMPLIB:", "Import Library", "",
- cmVS7FlagTable::UserValue },
- { "MergeSections", "MERGE:", "Merge Sections", "",
- cmVS7FlagTable::UserValue },
- { "LinkKeyFile", "KEYFILE:", "Key File", "", cmVS7FlagTable::UserValue },
- { "KeyContainer", "KEYCONTAINER:", "Key Container", "",
- cmVS7FlagTable::UserValue },
- // Skip [AdditionalOptions] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS14LibFlagTable.h b/Source/cmVS14LibFlagTable.h
deleted file mode 100644
index 7fa713893..000000000
--- a/Source/cmVS14LibFlagTable.h
+++ /dev/null
@@ -1,76 +0,0 @@
-static cmVS7FlagTable cmVS14LibFlagTable[] = {
-
- // Enum Properties
- { "ErrorReporting", "ERRORREPORT:PROMPT", "PromptImmediately",
- "PromptImmediately", 0 },
- { "ErrorReporting", "ERRORREPORT:QUEUE", "Queue For Next Login",
- "QueueForNextLogin", 0 },
- { "ErrorReporting", "ERRORREPORT:SEND", "Send Error Report",
- "SendErrorReport", 0 },
- { "ErrorReporting", "ERRORREPORT:NONE", "No Error Report", "NoErrorReport",
- 0 },
-
- { "TargetMachine", "MACHINE:ARM", "MachineARM", "MachineARM", 0 },
- { "TargetMachine", "MACHINE:EBC", "MachineEBC", "MachineEBC", 0 },
- { "TargetMachine", "MACHINE:IA64", "MachineIA64", "MachineIA64", 0 },
- { "TargetMachine", "MACHINE:MIPS", "MachineMIPS", "MachineMIPS", 0 },
- { "TargetMachine", "MACHINE:MIPS16", "MachineMIPS16", "MachineMIPS16", 0 },
- { "TargetMachine", "MACHINE:MIPSFPU", "MachineMIPSFPU", "MachineMIPSFPU",
- 0 },
- { "TargetMachine", "MACHINE:MIPSFPU16", "MachineMIPSFPU16",
- "MachineMIPSFPU16", 0 },
- { "TargetMachine", "MACHINE:SH4", "MachineSH4", "MachineSH4", 0 },
- { "TargetMachine", "MACHINE:THUMB", "MachineTHUMB", "MachineTHUMB", 0 },
- { "TargetMachine", "MACHINE:X64", "MachineX64", "MachineX64", 0 },
- { "TargetMachine", "MACHINE:X86", "MachineX86", "MachineX86", 0 },
-
- { "SubSystem", "SUBSYSTEM:CONSOLE", "Console", "Console", 0 },
- { "SubSystem", "SUBSYSTEM:WINDOWS", "Windows", "Windows", 0 },
- { "SubSystem", "SUBSYSTEM:NATIVE", "Native", "Native", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_APPLICATION", "EFI Application",
- "EFI Application", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER",
- "EFI Boot Service Driver", "EFI Boot Service Driver", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_ROM", "EFI ROM", "EFI ROM", 0 },
- { "SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER", "EFI Runtime", "EFI Runtime",
- 0 },
- { "SubSystem", "SUBSYSTEM:WINDOWSCE", "WindowsCE", "WindowsCE", 0 },
- { "SubSystem", "SUBSYSTEM:POSIX", "POSIX", "POSIX", 0 },
-
- // Bool Properties
- { "SuppressStartupBanner", "NOLOGO", "", "true", 0 },
- { "IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0 },
- { "TreatLibWarningAsErrors", "WX:NO", "", "false", 0 },
- { "TreatLibWarningAsErrors", "WX", "", "true", 0 },
- { "Verbose", "VERBOSE", "", "true", 0 },
- { "LinkTimeCodeGeneration", "LTCG", "", "true", 0 },
-
- // Bool Properties With Argument
-
- // String List Properties
- // Skip [AdditionalDependencies] - no command line Switch.
- { "AdditionalLibraryDirectories", "LIBPATH:",
- "Additional Library Directories", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
- "Ignore Specific Default Libraries", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "ExportNamedFunctions", "EXPORT:", "Export Named Functions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "RemoveObjects", "REMOVE:", "Remove Objects", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
-
- // String Properties
- { "OutputFile", "OUT:", "Output File", "", cmVS7FlagTable::UserValue },
- { "ModuleDefinitionFile", "DEF:", "Module Definition File Name", "",
- cmVS7FlagTable::UserValue },
- { "ForceSymbolReferences", "INCLUDE:", "Force Symbol References", "",
- cmVS7FlagTable::UserValue },
- { "DisplayLibrary", "LIST:", "Display Library to standard output", "",
- cmVS7FlagTable::UserValue },
- // Skip [MinimumRequiredVersion] - no command line Switch.
- { "Name", "NAME:", "Name", "", cmVS7FlagTable::UserValue },
- // Skip [AdditionalOptions] - no command line Switch.
- // Skip [TrackerLogDirectory] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS14MASMFlagTable.h b/Source/cmVS14MASMFlagTable.h
deleted file mode 100644
index 82ec9f1d0..000000000
--- a/Source/cmVS14MASMFlagTable.h
+++ /dev/null
@@ -1,76 +0,0 @@
-static cmVS7FlagTable cmVS14MASMFlagTable[] = {
-
- // Enum Properties
- { "PreserveIdentifierCase", "", "Default", "0", 0 },
- { "PreserveIdentifierCase", "Cp", "Preserves Identifier Case (/Cp)", "1",
- 0 },
- { "PreserveIdentifierCase", "Cu",
- "Maps all identifiers to upper case. (/Cu)", "2", 0 },
- { "PreserveIdentifierCase", "Cx",
- "Preserves case in public and extern symbols. (/Cx)", "3", 0 },
-
- { "WarningLevel", "W0", "Warning Level 0 (/W0)", "0", 0 },
- { "WarningLevel", "W1", "Warning Level 1 (/W1)", "1", 0 },
- { "WarningLevel", "W2", "Warning Level 2 (/W2)", "2", 0 },
- { "WarningLevel", "W3", "Warning Level 3 (/W3)", "3", 0 },
-
- { "PackAlignmentBoundary", "", "Default", "0", 0 },
- { "PackAlignmentBoundary", "Zp1", "One Byte Boundary (/Zp1)", "1", 0 },
- { "PackAlignmentBoundary", "Zp2", "Two Byte Boundary (/Zp2)", "2", 0 },
- { "PackAlignmentBoundary", "Zp4", "Four Byte Boundary (/Zp4)", "3", 0 },
- { "PackAlignmentBoundary", "Zp8", "Eight Byte Boundary (/Zp8)", "4", 0 },
- { "PackAlignmentBoundary", "Zp16", "Sixteen Byte Boundary (/Zp16)", "5", 0 },
-
- { "CallingConvention", "", "Default", "0", 0 },
- { "CallingConvention", "Gd", "Use C-style Calling Convention (/Gd)", "1",
- 0 },
- { "CallingConvention", "Gz", "Use stdcall Calling Convention (/Gz)", "2",
- 0 },
- { "CallingConvention", "Gc", "Use Pascal Calling Convention (/Gc)", "3", 0 },
-
- { "ErrorReporting", "errorReport:prompt",
- "Prompt to send report immediately (/errorReport:prompt)", "0", 0 },
- { "ErrorReporting", "errorReport:queue",
- "Prompt to send report at the next logon (/errorReport:queue)", "1", 0 },
- { "ErrorReporting", "errorReport:send",
- "Automatically send report (/errorReport:send)", "2", 0 },
- { "ErrorReporting", "errorReport:none",
- "Do not send report (/errorReport:none)", "3", 0 },
-
- // Bool Properties
- { "NoLogo", "nologo", "", "true", 0 },
- { "GeneratePreprocessedSourceListing", "EP", "", "true", 0 },
- { "ListAllAvailableInformation", "Sa", "", "true", 0 },
- { "UseSafeExceptionHandlers", "safeseh", "", "true", 0 },
- { "AddFirstPassListing", "Sf", "", "true", 0 },
- { "EnableAssemblyGeneratedCodeListing", "Sg", "", "true", 0 },
- { "DisableSymbolTable", "Sn", "", "true", 0 },
- { "EnableFalseConditionalsInListing", "Sx", "", "true", 0 },
- { "TreatWarningsAsErrors", "WX", "", "true", 0 },
- { "MakeAllSymbolsPublic", "Zf", "", "true", 0 },
- { "GenerateDebugInformation", "Zi", "", "true", 0 },
- { "EnableMASM51Compatibility", "Zm", "", "true", 0 },
- { "PerformSyntaxCheckOnly", "Zs", "", "true", 0 },
-
- // Bool Properties With Argument
-
- // String List Properties
- { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "IncludePaths", "I", "Include Paths", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- { "BrowseFile", "FR", "Generate Browse Information File", "",
- cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
- // Skip [AdditionalDependencies] - no command line Switch.
-
- // String Properties
- // Skip [Inputs] - no command line Switch.
- { "ObjectFileName", "Fo", "Object File Name", "",
- cmVS7FlagTable::UserValue },
- { "AssembledCodeListingFile", "Fl", "Assembled Code Listing File", "",
- cmVS7FlagTable::UserValue },
- // Skip [CommandLineTemplate] - no command line Switch.
- // Skip [ExecutionDescription] - no command line Switch.
- // Skip [AdditionalOptions] - no command line Switch.
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVS14RCFlagTable.h b/Source/cmVS14RCFlagTable.h
deleted file mode 100644
index 5dc8d5ada..000000000
--- a/Source/cmVS14RCFlagTable.h
+++ /dev/null
@@ -1,7 +0,0 @@
-static cmVS7FlagTable cmVS14RCFlagTable[] = {
- // Bool Properties
- { "NullTerminateStrings", "n", "", "true", 0 },
- { "SuppressStartupBanner", "nologo", "", "true", 0 },
-
- { 0, 0, 0, 0, 0 }
-};
diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx
index 7168f266c..dd9f058b8 100644
--- a/Source/cmVSSetupHelper.cxx
+++ b/Source/cmVSSetupHelper.cxx
@@ -1,10 +1,15 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVSSetupHelper.h"
+
+#include "cmsys/Encoding.hxx"
+#include "cmsys/FStream.hxx"
+
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#ifndef VSSetupConstants
-#define VSSetupConstants
+# define VSSetupConstants
/* clang-format off */
const IID IID_ISetupConfiguration = {
0x42843719, 0xDB4C, 0x46C2,
@@ -41,16 +46,22 @@ const CLSID CLSID_SetupConfiguration = {
/* clang-format on */
#endif
-const WCHAR* VCToolsetComponent =
- L"Microsoft.VisualStudio.Component.VC.Tools.x86.x64";
const WCHAR* Win10SDKComponent =
L"Microsoft.VisualStudio.Component.Windows10SDK";
const WCHAR* Win81SDKComponent =
L"Microsoft.VisualStudio.Component.Windows81SDK";
const WCHAR* ComponentType = L"Component";
-cmVSSetupAPIHelper::cmVSSetupAPIHelper()
- : setupConfig(NULL)
+std::string VSInstanceInfo::GetInstallLocation() const
+{
+ std::string loc = cmsys::Encoding::ToNarrow(this->VSInstallLocation);
+ cmSystemTools::ConvertToUnixSlashes(loc);
+ return loc;
+}
+
+cmVSSetupAPIHelper::cmVSSetupAPIHelper(unsigned int version)
+ : Version(version)
+ , setupConfig(NULL)
, setupConfig2(NULL)
, setupHelper(NULL)
, initializationFailure(false)
@@ -72,7 +83,15 @@ cmVSSetupAPIHelper::~cmVSSetupAPIHelper()
CoUninitialize();
}
-bool cmVSSetupAPIHelper::IsVS2017Installed()
+bool cmVSSetupAPIHelper::SetVSInstance(std::string const& vsInstallLocation)
+{
+ this->SpecifiedVSInstallLocation = vsInstallLocation;
+ cmSystemTools::ConvertToUnixSlashes(this->SpecifiedVSInstallLocation);
+ chosenInstanceInfo = VSInstanceInfo();
+ return this->EnumerateAndChooseVSInstance();
+}
+
+bool cmVSSetupAPIHelper::IsVSInstalled()
{
return this->EnumerateAndChooseVSInstance();
}
@@ -90,11 +109,11 @@ bool cmVSSetupAPIHelper::IsWin81SDKInstalled()
}
bool cmVSSetupAPIHelper::CheckInstalledComponent(
- SmartCOMPtr<ISetupPackageReference> package, bool& bVCToolset,
- bool& bWin10SDK, bool& bWin81SDK)
+ SmartCOMPtr<ISetupPackageReference> package, bool& bWin10SDK,
+ bool& bWin81SDK)
{
bool ret = false;
- bVCToolset = bWin10SDK = bWin81SDK = false;
+ bWin10SDK = bWin81SDK = false;
SmartBSTR bstrId;
if (FAILED(package->GetId(&bstrId))) {
return ret;
@@ -107,11 +126,6 @@ bool cmVSSetupAPIHelper::CheckInstalledComponent(
std::wstring id = std::wstring(bstrId);
std::wstring type = std::wstring(bstrType);
- if (id.compare(VCToolsetComponent) == 0 &&
- type.compare(ComponentType) == 0) {
- bVCToolset = true;
- ret = true;
- }
// Checks for any version of Win10 SDK. The version is appended at the end of
// the
@@ -135,7 +149,6 @@ bool cmVSSetupAPIHelper::CheckInstalledComponent(
bool cmVSSetupAPIHelper::GetVSInstanceInfo(
SmartCOMPtr<ISetupInstance2> pInstance, VSInstanceInfo& vsInstanceInfo)
{
- bool isVCToolSetInstalled = false;
if (pInstance == NULL)
return false;
@@ -174,6 +187,24 @@ bool cmVSSetupAPIHelper::GetVSInstanceInfo(
}
}
+ // Check if a compiler is installed with this instance.
+ {
+ std::string const vcRoot = vsInstanceInfo.GetInstallLocation();
+ std::string vcToolsVersionFile =
+ vcRoot + "/VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt";
+ std::string vcToolsVersion;
+ cmsys::ifstream fin(vcToolsVersionFile.c_str());
+ if (!fin || !cmSystemTools::GetLineFromStream(fin, vcToolsVersion)) {
+ return false;
+ }
+ vcToolsVersion = cmTrimWhitespace(vcToolsVersion);
+ std::string const vcToolsDir = vcRoot + "/VC/Tools/MSVC/" + vcToolsVersion;
+ if (!cmSystemTools::FileIsDirectory(vcToolsDir)) {
+ return false;
+ }
+ vsInstanceInfo.VCToolsetVersion = vcToolsVersion;
+ }
+
// Reboot may have been required before the product package was registered
// (last).
if ((eRegistered & state) == eRegistered) {
@@ -199,12 +230,11 @@ bool cmVSSetupAPIHelper::GetVSInstanceInfo(
package == NULL)
continue;
- bool vcToolsetInstalled = false, win10SDKInstalled = false,
- win81SDkInstalled = false;
- bool ret = CheckInstalledComponent(package, vcToolsetInstalled,
- win10SDKInstalled, win81SDkInstalled);
+ bool win10SDKInstalled = false;
+ bool win81SDkInstalled = false;
+ bool ret =
+ CheckInstalledComponent(package, win10SDKInstalled, win81SDkInstalled);
if (ret) {
- isVCToolSetInstalled |= vcToolsetInstalled;
vsInstanceInfo.IsWin10SDKInstalled |= win10SDKInstalled;
vsInstanceInfo.IsWin81SDKInstalled |= win81SDkInstalled;
}
@@ -213,23 +243,46 @@ bool cmVSSetupAPIHelper::GetVSInstanceInfo(
SafeArrayDestroy(lpsaPackages);
}
- return isVCToolSetInstalled;
+ return true;
}
bool cmVSSetupAPIHelper::GetVSInstanceInfo(std::string& vsInstallLocation)
{
- vsInstallLocation = "";
+ vsInstallLocation.clear();
bool isInstalled = this->EnumerateAndChooseVSInstance();
if (isInstalled) {
- std::string str(chosenInstanceInfo.VSInstallLocation.begin(),
- chosenInstanceInfo.VSInstallLocation.end());
- vsInstallLocation = str;
+ vsInstallLocation = chosenInstanceInfo.GetInstallLocation();
}
return isInstalled;
}
+bool cmVSSetupAPIHelper::GetVCToolsetVersion(std::string& vsToolsetVersion)
+{
+ vsToolsetVersion.clear();
+ bool isInstalled = this->EnumerateAndChooseVSInstance();
+
+ if (isInstalled) {
+ vsToolsetVersion = chosenInstanceInfo.VCToolsetVersion;
+ }
+
+ return isInstalled && !vsToolsetVersion.empty();
+}
+
+bool cmVSSetupAPIHelper::IsEWDKEnabled()
+{
+ std::string envEnterpriseWDK, envDisableRegistryUse;
+ cmSystemTools::GetEnv("EnterpriseWDK", envEnterpriseWDK);
+ cmSystemTools::GetEnv("DisableRegistryUse", envDisableRegistryUse);
+ if (!cmSystemTools::Strucmp(envEnterpriseWDK.c_str(), "True") &&
+ !cmSystemTools::Strucmp(envDisableRegistryUse.c_str(), "True")) {
+ return true;
+ }
+
+ return false;
+}
+
bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
{
bool isVSInstanceExists = false;
@@ -237,25 +290,38 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
return true;
}
+ if (this->IsEWDKEnabled()) {
+ std::string envWindowsSdkDir81, envVSVersion, envVsInstallDir;
+
+ cmSystemTools::GetEnv("WindowsSdkDir_81", envWindowsSdkDir81);
+ cmSystemTools::GetEnv("VisualStudioVersion", envVSVersion);
+ cmSystemTools::GetEnv("VSINSTALLDIR", envVsInstallDir);
+ if (envVSVersion.empty() || envVsInstallDir.empty())
+ return false;
+
+ chosenInstanceInfo.VSInstallLocation =
+ std::wstring(envVsInstallDir.begin(), envVsInstallDir.end());
+ chosenInstanceInfo.Version =
+ std::wstring(envVSVersion.begin(), envVSVersion.end());
+ chosenInstanceInfo.VCToolsetVersion = envVSVersion;
+ chosenInstanceInfo.ullVersion = std::stoi(envVSVersion);
+ chosenInstanceInfo.IsWin10SDKInstalled = true;
+ chosenInstanceInfo.IsWin81SDKInstalled = !envWindowsSdkDir81.empty();
+ return true;
+ }
+
if (initializationFailure || setupConfig == NULL || setupConfig2 == NULL ||
setupHelper == NULL)
return false;
std::string envVSCommonToolsDir;
+ std::string envVSCommonToolsDirEnvName =
+ "VS" + std::to_string(this->Version) + "0COMNTOOLS";
- // FIXME: When we support VS versions beyond 2017, the version
- // to choose will be passed in by the caller. We need to map that
- // to a per-version name of this environment variable.
- if (cmSystemTools::GetEnv("VS150COMNTOOLS", envVSCommonToolsDir)) {
+ if (cmSystemTools::GetEnv(envVSCommonToolsDirEnvName.c_str(),
+ 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;
@@ -265,6 +331,8 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
return false;
}
+ std::wstring const wantVersion = std::to_wstring(this->Version) + L'.';
+
SmartCOMPtr<ISetupInstance> instance;
while (SUCCEEDED(enumInstances->Next(1, &instance, NULL)) && instance) {
SmartCOMPtr<ISetupInstance2> instance2 = NULL;
@@ -280,18 +348,35 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
instance = instance2 = NULL;
if (isInstalled) {
- if (!envVSCommonToolsDir.empty()) {
- std::string currentVSLocation(instanceInfo.VSInstallLocation.begin(),
- instanceInfo.VSInstallLocation.end());
- cmSystemTools::ConvertToUnixSlashes(currentVSLocation);
- currentVSLocation += "/Common7/Tools";
+ // We are looking for a specific major version.
+ if (instanceInfo.Version.size() < wantVersion.size() ||
+ instanceInfo.Version.substr(0, wantVersion.size()) != wantVersion) {
+ continue;
+ }
+
+ if (!this->SpecifiedVSInstallLocation.empty()) {
+ // We are looking for a specific instance.
+ std::string currentVSLocation = instanceInfo.GetInstallLocation();
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 =
+ cmStrCat(instanceInfo.GetInstallLocation(), "/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 d2f514c63..0980cef53 100644
--- a/Source/cmVSSetupHelper.h
+++ b/Source/cmVSSetupHelper.h
@@ -4,17 +4,17 @@
#define cmVSSetupHelper_h
#ifndef NOMINMAX
-#define NOMINMAX // Undefine min and max defined by windows.h
+# define NOMINMAX // Undefine min and max defined by windows.h
#endif
// Published by Visual Studio Setup team
-#include "cmvssetup/Setup.Configuration.h"
-
#include <string>
#include <vector>
#include <windows.h>
+#include "cmvssetup/Setup.Configuration.h"
+
template <class T>
class SmartCOMPtr
{
@@ -74,29 +74,12 @@ class SmartBSTR
{
public:
SmartBSTR() { str = NULL; }
- SmartBSTR(const SmartBSTR& src)
- {
- if (src.str != NULL) {
- str = ::SysAllocStringByteLen((char*)str, ::SysStringByteLen(str));
- } else {
- str = ::SysAllocStringByteLen(NULL, 0);
- }
- }
- SmartBSTR& operator=(const SmartBSTR& src)
- {
- if (str != src.str) {
- ::SysFreeString(str);
- if (src.str != NULL) {
- str = ::SysAllocStringByteLen((char*)str, ::SysStringByteLen(str));
- } else {
- str = ::SysAllocStringByteLen(NULL, 0);
- }
- }
- return *this;
- }
+ SmartBSTR(const SmartBSTR& src) = delete;
+ SmartBSTR& operator=(const SmartBSTR& src) = delete;
operator BSTR() const { return str; }
BSTR* operator&() throw() { return &str; }
~SmartBSTR() throw() { ::SysFreeString(str); }
+
private:
BSTR str;
};
@@ -106,26 +89,25 @@ struct VSInstanceInfo
std::wstring InstanceId;
std::wstring VSInstallLocation;
std::wstring Version;
- ULONGLONG ullVersion;
- bool IsWin10SDKInstalled;
- bool IsWin81SDKInstalled;
+ std::string VCToolsetVersion;
+ ULONGLONG ullVersion = 0;
+ bool IsWin10SDKInstalled = false;
+ bool IsWin81SDKInstalled = false;
- VSInstanceInfo()
- {
- InstanceId = VSInstallLocation = Version = L"";
- ullVersion = 0;
- IsWin10SDKInstalled = IsWin81SDKInstalled = false;
- }
+ std::string GetInstallLocation() const;
};
class cmVSSetupAPIHelper
{
public:
- cmVSSetupAPIHelper();
+ cmVSSetupAPIHelper(unsigned int version);
~cmVSSetupAPIHelper();
- bool IsVS2017Installed();
+ bool SetVSInstance(std::string const& vsInstallLocation);
+
+ bool IsVSInstalled();
bool GetVSInstanceInfo(std::string& vsInstallLocation);
+ bool GetVCToolsetVersion(std::string& vsToolsetVersion);
bool IsWin10SDKInstalled();
bool IsWin81SDKInstalled();
@@ -134,11 +116,12 @@ private:
bool GetVSInstanceInfo(SmartCOMPtr<ISetupInstance2> instance2,
VSInstanceInfo& vsInstanceInfo);
bool CheckInstalledComponent(SmartCOMPtr<ISetupPackageReference> package,
- bool& bVCToolset, bool& bWin10SDK,
- bool& bWin81SDK);
+ bool& bWin10SDK, bool& bWin81SDK);
int ChooseVSInstance(const std::vector<VSInstanceInfo>& vecVSInstances);
bool EnumerateAndChooseVSInstance();
+ unsigned int Version;
+
// COM ptrs to query about VS instances
SmartCOMPtr<ISetupConfiguration> setupConfig;
SmartCOMPtr<ISetupConfiguration2> setupConfig2;
@@ -149,6 +132,9 @@ private:
HRESULT comInitialized;
// current best instance of VS selected
VSInstanceInfo chosenInstanceInfo;
+ bool IsEWDKEnabled();
+
+ std::string SpecifiedVSInstallLocation;
};
#endif
diff --git a/Source/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx
index 06ca53c0a..6b93c636a 100644
--- a/Source/cmVariableRequiresCommand.cxx
+++ b/Source/cmVariableRequiresCommand.cxx
@@ -2,32 +2,32 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVariableRequiresCommand.h"
+#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmState.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-class cmExecutionStatus;
-
// cmLibraryCommand
-bool cmVariableRequiresCommand::InitialPass(
- std::vector<std::string> const& args, cmExecutionStatus&)
+bool cmVariableRequiresCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 3) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
std::string const& testVariable = args[0];
- if (!this->Makefile->IsOn(testVariable)) {
+ if (!status.GetMakefile().IsOn(testVariable)) {
return true;
}
std::string const& resultVariable = args[1];
bool requirementsMet = true;
std::string notSet;
bool hasAdvanced = false;
- cmState* state = this->Makefile->GetState();
+ cmState* state = status.GetMakefile().GetState();
for (unsigned int i = 2; i < args.size(); ++i) {
- if (!this->Makefile->IsOn(args[i])) {
+ if (!status.GetMakefile().IsOn(args[i])) {
requirementsMet = false;
notSet += args[i];
notSet += "\n";
@@ -37,27 +37,26 @@ bool cmVariableRequiresCommand::InitialPass(
}
}
}
- const char* reqVar = this->Makefile->GetDefinition(resultVariable);
+ const char* reqVar = status.GetMakefile().GetDefinition(resultVariable);
// if reqVar is unset, then set it to requirementsMet
// if reqVar is set to true, but requirementsMet is false , then
// set reqVar to false.
- if (!reqVar || (!requirementsMet && this->Makefile->IsOn(reqVar))) {
- this->Makefile->AddDefinition(resultVariable, requirementsMet);
+ if (!reqVar || (!requirementsMet && status.GetMakefile().IsOn(reqVar))) {
+ status.GetMakefile().AddDefinitionBool(resultVariable, requirementsMet);
}
if (!requirementsMet) {
- std::string message = "Variable assertion failed:\n";
- message +=
- testVariable + " Requires that the following unset variables are set:\n";
- message += notSet;
- message += "\nPlease set them, or set ";
- message += testVariable + " to false, and re-configure.\n";
+ std::string message =
+ cmStrCat("Variable assertion failed:\n", testVariable,
+ " Requires that the following unset variables are set:\n",
+ notSet, "\nPlease set them, or set ", testVariable,
+ " to false, and re-configure.\n");
if (hasAdvanced) {
message +=
"One or more of the required variables is advanced."
" To set the variable, you must turn on advanced mode in cmake.";
}
- cmSystemTools::Error(message.c_str());
+ cmSystemTools::Error(message);
}
return true;
diff --git a/Source/cmVariableRequiresCommand.h b/Source/cmVariableRequiresCommand.h
index 9808d5f0c..fb0520ed7 100644
--- a/Source/cmVariableRequiresCommand.h
+++ b/Source/cmVariableRequiresCommand.h
@@ -3,21 +3,14 @@
#ifndef cmVariableRequiresCommand_h
#define cmVariableRequiresCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-class cmVariableRequiresCommand : public cmCommand
-{
-public:
- cmCommand* Clone() CM_OVERRIDE { return new cmVariableRequiresCommand; }
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmVariableRequiresCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmVariableWatch.cxx b/Source/cmVariableWatch.cxx
index 419e1a411..4995da972 100644
--- a/Source/cmVariableWatch.cxx
+++ b/Source/cmVariableWatch.cxx
@@ -2,11 +2,9 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVariableWatch.h"
-#include "cmAlgorithms.h"
-
-#include "cm_auto_ptr.hxx"
-#include <algorithm>
+#include <memory>
#include <utility>
+#include <vector>
static const char* const cmVariableWatchAccessStrings[] = {
"READ_ACCESS", "UNKNOWN_READ_ACCESS", "UNKNOWN_DEFINED_ACCESS",
@@ -21,41 +19,27 @@ const char* cmVariableWatch::GetAccessAsString(int access_type)
return cmVariableWatchAccessStrings[access_type];
}
-cmVariableWatch::cmVariableWatch()
-{
-}
+cmVariableWatch::cmVariableWatch() = default;
-template <typename C>
-void deleteAllSecond(typename C::value_type it)
-{
- cmDeleteAll(it.second);
-}
-
-cmVariableWatch::~cmVariableWatch()
-{
- std::for_each(this->WatchMap.begin(), this->WatchMap.end(),
- deleteAllSecond<cmVariableWatch::StringToVectorOfPairs>);
-}
+cmVariableWatch::~cmVariableWatch() = default;
bool cmVariableWatch::AddWatch(const std::string& variable, WatchMethod method,
void* client_data /*=0*/,
DeleteData delete_data /*=0*/)
{
- CM_AUTO_PTR<cmVariableWatch::Pair> p(new cmVariableWatch::Pair);
+ auto p = std::make_shared<cmVariableWatch::Pair>();
p->Method = method;
p->ClientData = client_data;
p->DeleteDataCall = delete_data;
- cmVariableWatch::VectorOfPairs* vp = &this->WatchMap[variable];
- cmVariableWatch::VectorOfPairs::size_type cc;
- for (cc = 0; cc < vp->size(); cc++) {
- cmVariableWatch::Pair* pair = (*vp)[cc];
+ cmVariableWatch::VectorOfPairs& vp = this->WatchMap[variable];
+ for (auto& pair : vp) {
if (pair->Method == method && client_data &&
client_data == pair->ClientData) {
// Callback already exists
return false;
}
}
- vp->push_back(p.release());
+ vp.push_back(std::move(p));
return true;
}
@@ -72,7 +56,6 @@ void cmVariableWatch::RemoveWatch(const std::string& variable,
// If client_data is NULL, we want to disconnect all watches against
// the given method; otherwise match ClientData as well.
(!client_data || (client_data == (*it)->ClientData))) {
- delete *it;
vp->erase(it);
return;
}
@@ -83,13 +66,19 @@ bool cmVariableWatch::VariableAccessed(const std::string& variable,
int access_type, const char* newValue,
const cmMakefile* mf) const
{
- cmVariableWatch::StringToVectorOfPairs::const_iterator mit =
- this->WatchMap.find(variable);
+ auto mit = this->WatchMap.find(variable);
if (mit != this->WatchMap.end()) {
- const cmVariableWatch::VectorOfPairs* vp = &mit->second;
- cmVariableWatch::VectorOfPairs::const_iterator it;
- for (it = vp->begin(); it != vp->end(); it++) {
- (*it)->Method(variable, access_type, (*it)->ClientData, newValue, mf);
+ // The strategy here is to copy the list of callbacks, and ignore
+ // new callbacks that existing ones may add.
+ std::vector<std::weak_ptr<Pair>> vp(mit->second.begin(),
+ mit->second.end());
+ for (auto& weak_it : vp) {
+ // In the case where a callback was removed, the weak_ptr will not be
+ // lockable, and so this ensures we don't attempt to call into freed
+ // memory
+ if (auto it = weak_it.lock()) {
+ it->Method(variable, access_type, it->ClientData, newValue, mf);
+ }
}
return true;
}
diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h
index a575afe9d..e4b3b7c47 100644
--- a/Source/cmVariableWatch.h
+++ b/Source/cmVariableWatch.h
@@ -6,6 +6,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
+#include <memory>
#include <string>
#include <vector>
@@ -19,10 +20,9 @@ class cmMakefile;
class cmVariableWatch
{
public:
- typedef void (*WatchMethod)(const std::string& variable, int access_type,
- void* client_data, const char* newValue,
- const cmMakefile* mf);
- typedef void (*DeleteData)(void* client_data);
+ using WatchMethod = void (*)(const std::string&, int, void*, const char*,
+ const cmMakefile*);
+ using DeleteData = void (*)(void*);
cmVariableWatch();
~cmVariableWatch();
@@ -31,10 +31,9 @@ public:
* Add watch to the variable
*/
bool AddWatch(const std::string& variable, WatchMethod method,
- void* client_data = CM_NULLPTR,
- DeleteData delete_data = CM_NULLPTR);
+ void* client_data = nullptr, DeleteData delete_data = nullptr);
void RemoveWatch(const std::string& variable, WatchMethod method,
- void* client_data = CM_NULLPTR);
+ void* client_data = nullptr);
/**
* This method is called when variable is accessed
@@ -63,25 +62,22 @@ public:
protected:
struct Pair
{
- WatchMethod Method;
- void* ClientData;
- DeleteData DeleteDataCall;
- Pair()
- : Method(CM_NULLPTR)
- , ClientData(CM_NULLPTR)
- , DeleteDataCall(CM_NULLPTR)
- {
- }
+ WatchMethod Method = nullptr;
+ void* ClientData = nullptr;
+ DeleteData DeleteDataCall = nullptr;
~Pair()
{
if (this->DeleteDataCall && this->ClientData) {
this->DeleteDataCall(this->ClientData);
}
}
+ Pair() = default;
+ Pair(const Pair&) = delete;
+ Pair& operator=(const Pair&) = delete;
};
- typedef std::vector<Pair*> VectorOfPairs;
- typedef std::map<std::string, VectorOfPairs> StringToVectorOfPairs;
+ using VectorOfPairs = std::vector<std::shared_ptr<Pair>>;
+ using StringToVectorOfPairs = std::map<std::string, VectorOfPairs>;
StringToVectorOfPairs WatchMap;
};
diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx
index 281850ecc..f2c8f3cdb 100644
--- a/Source/cmVariableWatchCommand.cxx
+++ b/Source/cmVariableWatchCommand.cxx
@@ -2,11 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVariableWatchCommand.h"
-#include <sstream>
+#include <memory>
+#include <utility>
#include "cmExecutionStatus.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmVariableWatch.h"
#include "cmake.h"
@@ -43,36 +46,32 @@ 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;
+ cmExecutionStatus status(*makefile);
if (!makefile->ExecuteCommand(newLFF, status)) {
- std::ostringstream error;
- error << "Error in cmake code at\nUnknown:0:\n"
- << "A command failed during the invocation of callback \""
- << data->Command << "\".";
- cmSystemTools::Error(error.str().c_str());
+ cmSystemTools::Error(
+ cmStrCat("Error in cmake code at\nUnknown:0:\nA command failed "
+ "during the invocation of callback \"",
+ data->Command, "\"."));
data->InCallback = false;
return;
}
processed = true;
}
if (!processed) {
- std::ostringstream msg;
- msg << "Variable \"" << variable << "\" was accessed using "
- << accessString << " with value \"" << (newValue ? newValue : "")
- << "\".";
- makefile->IssueMessage(cmake::LOG, msg.str());
+ makefile->IssueMessage(
+ MessageType::LOG,
+ cmStrCat("Variable \"", variable, "\" was accessed using ", accessString,
+ " with value \"", (newValue ? newValue : ""), "\"."));
}
data->InCallback = false;
@@ -85,25 +84,46 @@ static void deleteVariableWatchCallbackData(void* client_data)
delete data;
}
-cmVariableWatchCommand::cmVariableWatchCommand()
+/** This command does not really have a final pass but it needs to
+ stay alive since it owns variable watch callback information. */
+class FinalAction
{
-}
-
-cmVariableWatchCommand::~cmVariableWatchCommand()
-{
- std::set<std::string>::const_iterator it;
- for (it = this->WatchedVariables.begin(); it != this->WatchedVariables.end();
- ++it) {
- this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch(
- *it, cmVariableWatchCommandVariableAccessed);
+public:
+ /* NOLINTNEXTLINE(performance-unnecessary-value-param) */
+ FinalAction(cmMakefile* makefile, std::string variable)
+ : Action(std::make_shared<Impl>(makefile, std::move(variable)))
+ {
}
-}
-bool cmVariableWatchCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+ void operator()(cmMakefile&) const {}
+
+private:
+ struct Impl
+ {
+ Impl(cmMakefile* makefile, std::string variable)
+ : Makefile(makefile)
+ , Variable(std::move(variable))
+ {
+ }
+
+ ~Impl()
+ {
+ this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch(
+ this->Variable, cmVariableWatchCommandVariableAccessed);
+ }
+
+ cmMakefile* Makefile;
+ std::string Variable;
+ };
+
+ std::shared_ptr<Impl const> Action;
+};
+
+bool cmVariableWatchCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("must be called with at least one argument.");
+ status.SetError("must be called with at least one argument.");
return false;
}
std::string const& variable = args[0];
@@ -112,9 +132,7 @@ bool cmVariableWatchCommand::InitialPass(std::vector<std::string> const& args,
command = args[1];
}
if (variable == "CMAKE_CURRENT_LIST_FILE") {
- std::ostringstream ostr;
- ostr << "cannot be set on the variable: " << variable;
- this->SetError(ostr.str());
+ status.SetError(cmStrCat("cannot be set on the variable: ", variable));
return false;
}
@@ -123,13 +141,14 @@ bool cmVariableWatchCommand::InitialPass(std::vector<std::string> const& args,
data->InCallback = false;
data->Command = command;
- this->WatchedVariables.insert(variable);
- if (!this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch(
+ if (!status.GetMakefile().GetCMakeInstance()->GetVariableWatch()->AddWatch(
variable, cmVariableWatchCommandVariableAccessed, data,
deleteVariableWatchCallbackData)) {
deleteVariableWatchCallbackData(data);
return false;
}
+ status.GetMakefile().AddFinalAction(
+ FinalAction(&status.GetMakefile(), variable));
return true;
}
diff --git a/Source/cmVariableWatchCommand.h b/Source/cmVariableWatchCommand.h
index 9f0439175..3f9f2443a 100644
--- a/Source/cmVariableWatchCommand.h
+++ b/Source/cmVariableWatchCommand.h
@@ -3,47 +3,18 @@
#ifndef cmVariableWatchCommand_h
#define cmVariableWatchCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include <set>
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmVariableWatchCommand
+/**
* \brief Watch when the variable changes and invoke command
*
*/
-class cmVariableWatchCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmVariableWatchCommand; }
-
- //! Default constructor
- cmVariableWatchCommand();
-
- //! Destructor.
- ~cmVariableWatchCommand() CM_OVERRIDE;
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-
- /** This command does not really have a final pass but it needs to
- stay alive since it owns variable watch callback information. */
- bool HasFinalPass() const CM_OVERRIDE { return true; }
-
-protected:
- std::set<std::string> WatchedVariables;
-};
+bool cmVariableWatchCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmVersionMacros.h b/Source/cmVersionMacros.h
index 1b617bd2b..e8ac4f862 100644
--- a/Source/cmVersionMacros.h
+++ b/Source/cmVersionMacros.h
@@ -7,7 +7,7 @@
#define CMake_VERSION_PATCH_IS_RELEASE(patch) ((patch) < 20000000)
#if CMake_VERSION_PATCH_IS_RELEASE(CMake_VERSION_PATCH)
-#define CMake_VERSION_IS_RELEASE 1
+# define CMake_VERSION_IS_RELEASE 1
#endif
#endif
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index dee153f6b..58574776e 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -2,20 +2,29 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVisualStudio10TargetGenerator.h"
+#include <iterator>
+#include <set>
+
+#include <cm/memory>
+
+#include "windows.h"
+
#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
+#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalVisualStudio10Generator.h"
-#include "cmLocalVisualStudio7Generator.h"
+#include "cmLinkLineDeviceComputer.h"
+#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmSystemTools.h"
#include "cmVisualStudioGeneratorOptions.h"
-#include "windows.h"
-#include "cm_auto_ptr.hxx"
+static void ConvertToWindowsSlash(std::string& s);
static std::string cmVS10EscapeXML(std::string arg)
{
@@ -25,14 +34,157 @@ static std::string cmVS10EscapeXML(std::string arg)
return arg;
}
+static std::string cmVS10EscapeAttr(std::string arg)
+{
+ cmSystemTools::ReplaceString(arg, "&", "&amp;");
+ cmSystemTools::ReplaceString(arg, "<", "&lt;");
+ cmSystemTools::ReplaceString(arg, ">", "&gt;");
+ cmSystemTools::ReplaceString(arg, "\"", "&quot;");
+ cmSystemTools::ReplaceString(arg, "\n", "&#10;");
+ return arg;
+}
+
+struct cmVisualStudio10TargetGenerator::Elem
+{
+ std::ostream& S;
+ const int Indent;
+ bool HasElements = false;
+ bool HasContent = false;
+ std::string Tag;
+
+ Elem(std::ostream& s, const char* tag)
+ : S(s)
+ , Indent(0)
+ , Tag(tag)
+ {
+ this->StartElement();
+ }
+ Elem(const Elem&) = delete;
+ Elem(Elem& par, const char* tag)
+ : S(par.S)
+ , Indent(par.Indent + 1)
+ , Tag(tag)
+ {
+ par.SetHasElements();
+ this->StartElement();
+ }
+ void SetHasElements()
+ {
+ if (!HasElements) {
+ this->S << ">\n";
+ HasElements = true;
+ }
+ }
+ std::ostream& WriteString(const char* line);
+ void StartElement() { this->WriteString("<") << this->Tag; }
+ void Element(const char* tag, const std::string& val)
+ {
+ Elem(*this, tag).Content(val);
+ }
+ Elem& Attribute(const char* an, const std::string& av)
+ {
+ this->S << " " << an << "=\"" << cmVS10EscapeAttr(av) << "\"";
+ return *this;
+ }
+ void Content(const std::string& val)
+ {
+ if (!this->HasContent) {
+ this->S << ">";
+ this->HasContent = true;
+ }
+ this->S << cmVS10EscapeXML(val);
+ }
+ ~Elem()
+ {
+ // Do not emit element which has not been started
+ if (Tag.empty()) {
+ return;
+ }
+
+ if (HasElements) {
+ this->WriteString("</") << this->Tag << ">";
+ if (this->Indent > 0) {
+ this->S << '\n';
+ } else {
+ // special case: don't print EOL at EOF
+ }
+ } else if (HasContent) {
+ this->S << "</" << this->Tag << ">\n";
+ } else {
+ this->S << " />\n";
+ }
+ }
+
+ void WritePlatformConfigTag(const char* tag, const std::string& cond,
+ const std::string& content);
+};
+
+class cmVS10GeneratorOptions : public cmVisualStudioGeneratorOptions
+{
+public:
+ using Elem = cmVisualStudio10TargetGenerator::Elem;
+ cmVS10GeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool,
+ cmVS7FlagTable const* table,
+ cmVisualStudio10TargetGenerator* g = nullptr)
+ : cmVisualStudioGeneratorOptions(lg, tool, table)
+ , TargetGenerator(g)
+ {
+ }
+
+ void OutputFlag(std::ostream& /*fout*/, int /*indent*/, const char* tag,
+ const std::string& content) override
+ {
+ if (!this->GetConfiguration().empty()) {
+ // if there are configuration specific flags, then
+ // use the configuration specific tag for PreprocessorDefinitions
+ const std::string cond =
+ this->TargetGenerator->CalcCondition(this->GetConfiguration());
+ this->Parent->WritePlatformConfigTag(tag, cond, content);
+ } else {
+ this->Parent->Element(tag, content);
+ }
+ }
+
+private:
+ cmVisualStudio10TargetGenerator* const TargetGenerator;
+ Elem* Parent = nullptr;
+ friend cmVisualStudio10TargetGenerator::OptionsHelper;
+};
+
+struct cmVisualStudio10TargetGenerator::OptionsHelper
+{
+ cmVS10GeneratorOptions& O;
+ OptionsHelper(cmVS10GeneratorOptions& o, Elem& e)
+ : O(o)
+ {
+ O.Parent = &e;
+ }
+ ~OptionsHelper() { O.Parent = nullptr; }
+
+ void OutputPreprocessorDefinitions(const std::string& lang)
+ {
+ O.OutputPreprocessorDefinitions(O.Parent->S, O.Parent->Indent + 1, lang);
+ }
+ void OutputAdditionalIncludeDirectories(const std::string& lang)
+ {
+ O.OutputAdditionalIncludeDirectories(O.Parent->S, O.Parent->Indent + 1,
+ lang);
+ }
+ void OutputFlagMap() { O.OutputFlagMap(O.Parent->S, O.Parent->Indent + 1); }
+ void PrependInheritedString(std::string const& key)
+ {
+ O.PrependInheritedString(key);
+ }
+};
+
static std::string cmVS10EscapeComment(std::string comment)
{
// MSBuild takes the CDATA of a <Message></Message> element and just
// 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':
@@ -45,8 +197,9 @@ static std::string cmVS10EscapeComment(std::string comment)
case '>': /* no break */
case '^':
echoable += '^'; /* no break */
+ CM_FALLTHROUGH;
default:
- echoable += *c;
+ echoable += c;
break;
}
}
@@ -63,7 +216,7 @@ static std::string computeProjectFileExtension(cmGeneratorTarget const* t)
{
std::string res;
res = ".vcxproj";
- if (cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(t)) {
+ if (t->IsCSharpOnly()) {
res = ".csproj";
}
return res;
@@ -71,16 +224,16 @@ static std::string computeProjectFileExtension(cmGeneratorTarget const* t)
cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
cmGeneratorTarget* target, cmGlobalVisualStudio10Generator* gg)
+ : GeneratorTarget(target)
+ , Makefile(target->Target->GetMakefile())
+ , Platform(gg->GetPlatformName())
+ , Name(target->GetName())
+ , GUID(gg->GetGUID(this->Name))
+ , GlobalGenerator(gg)
+ , LocalGenerator(
+ (cmLocalVisualStudio10Generator*)target->GetLocalGenerator())
{
- this->GlobalGenerator = gg;
- this->GeneratorTarget = target;
- this->Makefile = target->Target->GetMakefile();
this->Makefile->GetConfigurations(this->Configurations);
- this->LocalGenerator =
- (cmLocalVisualStudio7Generator*)this->GeneratorTarget->GetLocalGenerator();
- this->Name = this->GeneratorTarget->GetName();
- this->GUID = this->GlobalGenerator->GetGUID(this->Name.c_str());
- this->Platform = gg->GetPlatformName();
this->NsightTegra = gg->IsNsightTegra();
for (int i = 0; i < 4; ++i) {
this->NsightTegraVersion[i] = 0;
@@ -91,84 +244,50 @@ cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
this->MSTools = !this->NsightTegra;
this->Managed = false;
this->TargetCompileAsWinRT = false;
- this->BuildFileStream = 0;
this->IsMissingFiles = false;
this->DefaultArtifactDir =
- this->LocalGenerator->GetCurrentBinaryDirectory() + std::string("/") +
+ this->LocalGenerator->GetCurrentBinaryDirectory() + "/" +
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
- this->InSourceBuild =
- (strcmp(this->Makefile->GetCurrentSourceDirectory(),
- this->Makefile->GetCurrentBinaryDirectory()) == 0);
+ this->InSourceBuild = (this->Makefile->GetCurrentSourceDirectory() ==
+ this->Makefile->GetCurrentBinaryDirectory());
}
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;
- }
- if (this->BuildFileStream->Close()) {
- this->GlobalGenerator->FileReplacedDuringGenerate(this->PathToProjectFile);
- }
- delete this->BuildFileStream;
}
-void cmVisualStudio10TargetGenerator::WritePlatformConfigTag(
- const char* tag, const std::string& config, int indentLevel,
- const char* attribute, const char* end, std::ostream* stream)
-
+std::string cmVisualStudio10TargetGenerator::CalcCondition(
+ const std::string& config) const
{
- if (!stream) {
- stream = this->BuildFileStream;
- }
- stream->fill(' ');
- stream->width(indentLevel * 2);
- (*stream) << ""; // applies indentation
- (*stream) << "<" << tag << " Condition=\"";
- (*stream) << "'$(Configuration)|$(Platform)'=='";
- (*stream) << config << "|" << this->Platform;
- (*stream) << "'";
+ std::ostringstream oss;
+ oss << "'$(Configuration)|$(Platform)'=='";
+ oss << config << "|" << this->Platform;
+ oss << "'";
// handle special case for 32 bit C# targets
- if (csproj == this->ProjectType && this->Platform == "Win32") {
- (*stream) << " Or ";
- (*stream) << "'$(Configuration)|$(Platform)'=='";
- (*stream) << config << "|x86";
- (*stream) << "'";
- }
- (*stream) << "\"";
- if (attribute) {
- (*stream) << attribute;
- }
- // close the tag
- (*stream) << ">";
- if (end) {
- (*stream) << end;
+ if (this->ProjectType == csproj && this->Platform == "Win32") {
+ oss << " Or ";
+ oss << "'$(Configuration)|$(Platform)'=='";
+ oss << config << "|x86";
+ oss << "'";
}
+ return oss.str();
}
-void cmVisualStudio10TargetGenerator::WriteString(const char* line,
- int indentLevel)
+void cmVisualStudio10TargetGenerator::Elem::WritePlatformConfigTag(
+ const char* tag, const std::string& cond, const std::string& content)
{
- this->BuildFileStream->fill(' ');
- this->BuildFileStream->width(indentLevel * 2);
+ Elem(*this, tag).Attribute("Condition", cond).Content(content);
+}
+
+std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString(
+ const char* line)
+{
+ this->S.fill(' ');
+ this->S.width(this->Indent * 2);
// write an empty string to get the fill level indent to print
- (*this->BuildFileStream) << "";
- (*this->BuildFileStream) << line;
+ this->S << "";
+ this->S << line;
+ return this->S;
}
#define VS10_CXX_DEFAULT_PROPS "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"
@@ -185,6 +304,11 @@ void cmVisualStudio10TargetGenerator::WriteString(const char* line,
"$(UserRootDir)\\Microsoft.CSharp.$(Platform).user.props"
#define VS10_CSharp_TARGETS "$(MSBuildToolsPath)\\Microsoft.CSharp.targets"
+#define VS10_CSharp_NETCF_TARGETS \
+ "$(MSBuildExtensionsPath)\\Microsoft\\$(TargetFrameworkIdentifier)\\" \
+ "$(TargetFrameworkTargetsVersion)\\Microsoft.$(TargetFrameworkIdentifier)" \
+ ".CSharp.targets"
+
void cmVisualStudio10TargetGenerator::Generate()
{
// do not generate external ms projects
@@ -192,20 +316,29 @@ void cmVisualStudio10TargetGenerator::Generate()
this->GeneratorTarget->GetProperty("EXTERNAL_MSPROJECT")) {
return;
}
- this->ProjectFileExtension =
+ const std::string ProjectFileExtension =
computeProjectFileExtension(this->GeneratorTarget);
- if (this->ProjectFileExtension == ".vcxproj") {
+ if (ProjectFileExtension == ".vcxproj") {
this->ProjectType = vcxproj;
this->Managed = false;
- } else if (this->ProjectFileExtension == ".csproj") {
+ } else if (ProjectFileExtension == ".csproj") {
+ if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ std::string message = "The C# target \"" +
+ this->GeneratorTarget->GetName() +
+ "\" is of type STATIC_LIBRARY. This is discouraged (and may be "
+ "disabled in future). Make it a SHARED library instead.";
+ this->Makefile->IssueMessage(MessageType::DEPRECATION_WARNING, message);
+ }
this->ProjectType = csproj;
this->Managed = true;
}
// Tell the global generator the name of the project file
this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME",
this->Name.c_str());
- this->GeneratorTarget->Target->SetProperty(
- "GENERATOR_FILE_NAME_EXT", this->ProjectFileExtension.c_str());
+ this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME_EXT",
+ ProjectFileExtension.c_str());
+ this->DotNetHintReferences.clear();
+ this->AdditionalUsingDirectories.clear();
if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
if (!this->ComputeClOptions()) {
return;
@@ -232,483 +365,594 @@ void cmVisualStudio10TargetGenerator::Generate()
return;
}
}
- std::string path = this->LocalGenerator->GetCurrentBinaryDirectory();
- path += "/";
- path += this->Name;
- path += this->ProjectFileExtension;
- this->BuildFileStream = new cmGeneratedFileStream(path.c_str());
- this->PathToProjectFile = path;
- this->BuildFileStream->SetCopyIfDifferent(true);
+ std::string path =
+ cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+ this->Name, ProjectFileExtension);
+ cmGeneratedFileStream BuildFileStream(path);
+ const std::string PathToProjectFile = path;
+ BuildFileStream.SetCopyIfDifferent(true);
// Write the encoding header into the file
char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
- this->BuildFileStream->write(magic, 3);
-
- // get the tools version to use
- const std::string toolsVer(this->GlobalGenerator->GetToolsVersion());
- std::string project_defaults = "<?xml version=\"1.0\" encoding=\"" +
- this->GlobalGenerator->Encoding() + "\"?>\n";
- project_defaults.append("<Project DefaultTargets=\"Build\" ToolsVersion=\"");
- project_defaults.append(toolsVer + "\" ");
- project_defaults.append(
- "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n");
- this->WriteString(project_defaults.c_str(), 0);
-
- if (this->NsightTegra) {
- this->WriteString("<PropertyGroup Label=\"NsightTegraProject\">\n", 1);
- const int nsightTegraMajorVersion = this->NsightTegraVersion[0];
- const int nsightTegraMinorVersion = this->NsightTegraVersion[1];
- if (nsightTegraMajorVersion >= 2) {
- this->WriteString("<NsightTegraProjectRevisionNumber>", 2);
- if (nsightTegraMajorVersion > 3 ||
- (nsightTegraMajorVersion == 3 && nsightTegraMinorVersion >= 1)) {
- (*this->BuildFileStream) << "11";
+ BuildFileStream.write(magic, 3);
+ BuildFileStream << "<?xml version=\"1.0\" encoding=\""
+ << this->GlobalGenerator->Encoding() << "\"?>"
+ << "\n";
+ {
+ Elem e0(BuildFileStream, "Project");
+ e0.Attribute("DefaultTargets", "Build");
+ const char* toolsVersion = this->GlobalGenerator->GetToolsVersion();
+ if (this->GlobalGenerator->GetVersion() ==
+ cmGlobalVisualStudioGenerator::VS12 &&
+ this->GlobalGenerator->TargetsWindowsCE()) {
+ toolsVersion = "4.0";
+ }
+ e0.Attribute("ToolsVersion", toolsVersion);
+ e0.Attribute("xmlns",
+ "http://schemas.microsoft.com/developer/msbuild/2003");
+
+ if (this->NsightTegra) {
+ Elem e1(e0, "PropertyGroup");
+ e1.Attribute("Label", "NsightTegraProject");
+ const unsigned int nsightTegraMajorVersion = this->NsightTegraVersion[0];
+ const unsigned int nsightTegraMinorVersion = this->NsightTegraVersion[1];
+ if (nsightTegraMajorVersion >= 2) {
+ if (nsightTegraMajorVersion > 3 ||
+ (nsightTegraMajorVersion == 3 && nsightTegraMinorVersion >= 1)) {
+ e1.Element("NsightTegraProjectRevisionNumber", "11");
+ } else {
+ // Nsight Tegra 2.0 uses project revision 9.
+ e1.Element("NsightTegraProjectRevisionNumber", "9");
+ }
+ // Tell newer versions to upgrade silently when loading.
+ e1.Element("NsightTegraUpgradeOnceWithoutPrompt", "true");
} else {
- // Nsight Tegra 2.0 uses project revision 9.
- (*this->BuildFileStream) << "9";
+ // Require Nsight Tegra 1.6 for JCompile support.
+ e1.Element("NsightTegraProjectRevisionNumber", "7");
}
- (*this->BuildFileStream) << "</NsightTegraProjectRevisionNumber>\n";
- // Tell newer versions to upgrade silently when loading.
- this->WriteString("<NsightTegraUpgradeOnceWithoutPrompt>"
- "true"
- "</NsightTegraUpgradeOnceWithoutPrompt>\n",
- 2);
- } else {
- // Require Nsight Tegra 1.6 for JCompile support.
- this->WriteString("<NsightTegraProjectRevisionNumber>"
- "7"
- "</NsightTegraProjectRevisionNumber>\n",
- 2);
}
- this->WriteString("</PropertyGroup>\n", 1);
- }
- if (const char* hostArch =
- this->GlobalGenerator->GetPlatformToolsetHostArchitecture()) {
- this->WriteString("<PropertyGroup>\n", 1);
- this->WriteString("<PreferredToolArchitecture>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(hostArch)
- << "</PreferredToolArchitecture>\n";
- this->WriteString("</PropertyGroup>\n", 1);
- }
+ if (const char* hostArch =
+ this->GlobalGenerator->GetPlatformToolsetHostArchitecture()) {
+ Elem e1(e0, "PropertyGroup");
+ e1.Element("PreferredToolArchitecture", hostArch);
+ }
- if (csproj != this->ProjectType) {
- this->WriteProjectConfigurations();
- }
- this->WriteString("<PropertyGroup Label=\"Globals\">\n", 1);
- this->WriteString("<ProjectGuid>", 2);
- (*this->BuildFileStream) << "{" << this->GUID << "}</ProjectGuid>\n";
+ if (this->ProjectType != csproj) {
+ this->WriteProjectConfigurations(e0);
+ }
- if (this->MSTools &&
- this->GeneratorTarget->GetType() <= cmStateEnums::GLOBAL_TARGET) {
- this->WriteApplicationTypeSettings();
- this->VerifyNecessaryFiles();
- }
+ {
+ Elem e1(e0, "PropertyGroup");
+ e1.Attribute("Label", "Globals");
+ e1.Element("ProjectGuid", "{" + this->GUID + "}");
+
+ if (this->MSTools &&
+ this->GeneratorTarget->GetType() <= cmStateEnums::GLOBAL_TARGET) {
+ this->WriteApplicationTypeSettings(e1);
+ this->VerifyNecessaryFiles();
+ }
- const char* vsProjectTypes =
- this->GeneratorTarget->GetProperty("VS_GLOBAL_PROJECT_TYPES");
- if (vsProjectTypes) {
- std::string tagName = "ProjectTypes";
- if (csproj == this->ProjectType) {
- tagName = "ProjectTypeGuids";
- }
- this->WriteString("", 2);
- (*this->BuildFileStream) << "<" << tagName << ">"
- << cmVS10EscapeXML(vsProjectTypes) << "</"
- << tagName << ">\n";
- }
+ const char* vsProjectTypes =
+ this->GeneratorTarget->GetProperty("VS_GLOBAL_PROJECT_TYPES");
+ if (vsProjectTypes) {
+ const char* tagName = "ProjectTypes";
+ if (this->ProjectType == csproj) {
+ tagName = "ProjectTypeGuids";
+ }
+ e1.Element(tagName, vsProjectTypes);
+ }
- const char* vsProjectName =
- this->GeneratorTarget->GetProperty("VS_SCC_PROJECTNAME");
- const char* vsLocalPath =
- this->GeneratorTarget->GetProperty("VS_SCC_LOCALPATH");
- const char* vsProvider =
- this->GeneratorTarget->GetProperty("VS_SCC_PROVIDER");
+ const char* vsProjectName =
+ this->GeneratorTarget->GetProperty("VS_SCC_PROJECTNAME");
+ const char* vsLocalPath =
+ this->GeneratorTarget->GetProperty("VS_SCC_LOCALPATH");
+ const char* vsProvider =
+ this->GeneratorTarget->GetProperty("VS_SCC_PROVIDER");
+
+ if (vsProjectName && vsLocalPath && vsProvider) {
+ e1.Element("SccProjectName", vsProjectName);
+ e1.Element("SccLocalPath", vsLocalPath);
+ e1.Element("SccProvider", vsProvider);
+
+ const char* vsAuxPath =
+ this->GeneratorTarget->GetProperty("VS_SCC_AUXPATH");
+ if (vsAuxPath) {
+ e1.Element("SccAuxPath", vsAuxPath);
+ }
+ }
- if (vsProjectName && vsLocalPath && vsProvider) {
- this->WriteString("<SccProjectName>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsProjectName)
- << "</SccProjectName>\n";
- this->WriteString("<SccLocalPath>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsLocalPath)
- << "</SccLocalPath>\n";
- this->WriteString("<SccProvider>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsProvider)
- << "</SccProvider>\n";
+ if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) {
+ e1.Element("WinMDAssembly", "true");
+ }
- const char* vsAuxPath =
- this->GeneratorTarget->GetProperty("VS_SCC_AUXPATH");
- if (vsAuxPath) {
- this->WriteString("<SccAuxPath>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsAuxPath)
- << "</SccAuxPath>\n";
- }
- }
+ const char* vsGlobalKeyword =
+ this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD");
+ if (!vsGlobalKeyword) {
+ e1.Element("Keyword", "Win32Proj");
+ } else {
+ e1.Element("Keyword", vsGlobalKeyword);
+ }
- if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) {
- this->WriteString("<WinMDAssembly>true</WinMDAssembly>\n", 2);
- }
+ const char* vsGlobalRootNamespace =
+ this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
+ if (vsGlobalRootNamespace) {
+ e1.Element("RootNamespace", vsGlobalRootNamespace);
+ }
- const char* vsGlobalKeyword =
- this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD");
- if (!vsGlobalKeyword) {
- this->WriteString("<Keyword>Win32Proj</Keyword>\n", 2);
- } else {
- this->WriteString("<Keyword>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsGlobalKeyword)
- << "</Keyword>\n";
- }
-
- const char* vsGlobalRootNamespace =
- this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
- if (vsGlobalRootNamespace) {
- this->WriteString("<RootNamespace>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsGlobalRootNamespace)
- << "</RootNamespace>\n";
- }
-
- this->WriteString("<Platform>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform)
- << "</Platform>\n";
- const char* projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL");
- if (!projLabel) {
- projLabel = this->Name.c_str();
- }
- this->WriteString("<ProjectName>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(projLabel) << "</ProjectName>\n";
- if (const char* targetFrameworkVersion = this->GeneratorTarget->GetProperty(
- "VS_DOTNET_TARGET_FRAMEWORK_VERSION")) {
- this->WriteString("<TargetFrameworkVersion>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(targetFrameworkVersion)
- << "</TargetFrameworkVersion>\n";
- }
-
- // Disable the project upgrade prompt that is displayed the first time a
- // project using an older toolset version is opened in a newer version of
- // the IDE (respected by VS 2013 and above).
- if (this->GlobalGenerator->GetVersion() >=
- cmGlobalVisualStudioGenerator::VS12) {
- this->WriteString("<VCProjectUpgraderObjectName>NoUpgrade"
- "</VCProjectUpgraderObjectName>\n",
- 2);
- }
-
- std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
- for (std::vector<std::string>::const_iterator keyIt = keys.begin();
- keyIt != keys.end(); ++keyIt) {
- static const char* prefix = "VS_GLOBAL_";
- if (keyIt->find(prefix) != 0)
- continue;
- std::string globalKey = keyIt->substr(strlen(prefix));
- // Skip invalid or separately-handled properties.
- if (globalKey == "" || globalKey == "PROJECT_TYPES" ||
- globalKey == "ROOTNAMESPACE" || globalKey == "KEYWORD") {
- continue;
+ e1.Element("Platform", this->Platform);
+ const char* projLabel =
+ this->GeneratorTarget->GetProperty("PROJECT_LABEL");
+ if (!projLabel) {
+ projLabel = this->Name.c_str();
+ }
+ e1.Element("ProjectName", projLabel);
+ {
+ // TODO: add deprecation warning for VS_* property?
+ const char* targetFrameworkVersion =
+ this->GeneratorTarget->GetProperty(
+ "VS_DOTNET_TARGET_FRAMEWORK_VERSION");
+ if (!targetFrameworkVersion) {
+ targetFrameworkVersion = this->GeneratorTarget->GetProperty(
+ "DOTNET_TARGET_FRAMEWORK_VERSION");
+ }
+ if (!targetFrameworkVersion && this->ProjectType == csproj &&
+ this->GlobalGenerator->TargetsWindowsCE() &&
+ this->GlobalGenerator->GetVersion() ==
+ cmGlobalVisualStudioGenerator::VS12) {
+ // VS12 .NETCF default to .NET framework 3.9
+ targetFrameworkVersion = "v3.9";
+ }
+ if (targetFrameworkVersion) {
+ e1.Element("TargetFrameworkVersion", targetFrameworkVersion);
+ }
+ if (this->ProjectType == vcxproj &&
+ this->GlobalGenerator->TargetsWindowsCE()) {
+ e1.Element("EnableRedirectPlatform", "true");
+ e1.Element("RedirectPlatformValue", this->Platform);
+ }
+ if (this->ProjectType == csproj &&
+ this->GlobalGenerator->TargetsWindowsCE()) {
+ const char* targetFrameworkId = this->GeneratorTarget->GetProperty(
+ "VS_TARGET_FRAMEWORK_IDENTIFIER");
+ if (!targetFrameworkId) {
+ targetFrameworkId = "WindowsEmbeddedCompact";
+ }
+ e1.Element("TargetFrameworkIdentifier", targetFrameworkId);
+ const char* targetFrameworkVer = this->GeneratorTarget->GetProperty(
+ "VS_TARGET_FRAMEWORKS_TARGET_VERSION");
+ if (!targetFrameworkVer) {
+ targetFrameworkVer = "v8.0";
+ }
+ e1.Element("TargetFrameworkTargetsVersion", targetFrameworkVer);
+ }
+ if (!this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString()
+ .empty()) {
+ e1.Element(
+ "CudaToolkitCustomDir",
+ this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString() +
+ "nvcc");
+ }
+ }
+
+ // Disable the project upgrade prompt that is displayed the first time a
+ // project using an older toolset version is opened in a newer version of
+ // the IDE (respected by VS 2013 and above).
+ if (this->GlobalGenerator->GetVersion() >=
+ cmGlobalVisualStudioGenerator::VS12) {
+ e1.Element("VCProjectUpgraderObjectName", "NoUpgrade");
+ }
+
+ std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
+ for (std::string const& keyIt : keys) {
+ static const char* prefix = "VS_GLOBAL_";
+ if (keyIt.find(prefix) != 0)
+ continue;
+ 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);
+ if (!value)
+ continue;
+ e1.Element(globalKey.c_str(), value);
+ }
+
+ if (this->Managed) {
+ std::string outputType;
+ switch (this->GeneratorTarget->GetType()) {
+ case cmStateEnums::OBJECT_LIBRARY:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ outputType = "Library";
+ break;
+ case cmStateEnums::MODULE_LIBRARY:
+ outputType = "Module";
+ break;
+ case cmStateEnums::EXECUTABLE:
+ if (this->GeneratorTarget->Target->GetPropertyAsBool(
+ "WIN32_EXECUTABLE")) {
+ outputType = "WinExe";
+ } else {
+ outputType = "Exe";
+ }
+ break;
+ case cmStateEnums::UTILITY:
+ case cmStateEnums::GLOBAL_TARGET:
+ outputType = "Utility";
+ break;
+ case cmStateEnums::UNKNOWN_LIBRARY:
+ case cmStateEnums::INTERFACE_LIBRARY:
+ break;
+ }
+ e1.Element("OutputType", outputType);
+ e1.Element("AppDesignerFolder", "Properties");
+ }
}
- const char* value = this->GeneratorTarget->GetProperty(keyIt->c_str());
- if (!value)
- continue;
- this->WriteString("<", 2);
- (*this->BuildFileStream) << globalKey << ">" << cmVS10EscapeXML(value)
- << "</" << globalKey << ">\n";
- }
- if (this->Managed) {
- std::string outputType = "<OutputType>";
- switch (this->GeneratorTarget->GetType()) {
- case cmStateEnums::OBJECT_LIBRARY:
- case cmStateEnums::STATIC_LIBRARY:
- case cmStateEnums::SHARED_LIBRARY:
- outputType += "Library";
- break;
- case cmStateEnums::MODULE_LIBRARY:
- outputType += "Module";
- break;
- case cmStateEnums::EXECUTABLE:
- if (this->GeneratorTarget->Target->GetPropertyAsBool(
- "WIN32_EXECUTABLE")) {
- outputType += "WinExe";
- } else {
- outputType += "Exe";
+ switch (this->ProjectType) {
+ case vcxproj:
+ if (this->GlobalGenerator->GetPlatformToolsetVersion()) {
+ Elem(e0, "Import")
+ .Attribute("Project",
+ this->GlobalGenerator->GetAuxiliaryToolset());
}
+ Elem(e0, "Import").Attribute("Project", VS10_CXX_DEFAULT_PROPS);
break;
- case cmStateEnums::UTILITY:
- case cmStateEnums::GLOBAL_TARGET:
- outputType += "Utility";
- break;
- case cmStateEnums::UNKNOWN_LIBRARY:
- case cmStateEnums::INTERFACE_LIBRARY:
+ case csproj:
+ Elem(e0, "Import")
+ .Attribute("Project", VS10_CSharp_DEFAULT_PROPS)
+ .Attribute("Condition", "Exists('" VS10_CSharp_DEFAULT_PROPS "')");
break;
}
- outputType += "</OutputType>\n";
- this->WriteString(outputType.c_str(), 2);
- this->WriteString("<AppDesignerFolder>Properties</AppDesignerFolder>\n",
- 2);
- }
- this->WriteString("</PropertyGroup>\n", 1);
+ this->WriteProjectConfigurationValues(e0);
- switch (this->ProjectType) {
- case vcxproj:
- this->WriteString("<Import Project=\"" VS10_CXX_DEFAULT_PROPS "\" />\n",
- 1);
- break;
- case csproj:
- this->WriteString("<Import Project=\"" VS10_CSharp_DEFAULT_PROPS "\" "
- "Condition=\"Exists('" VS10_CSharp_DEFAULT_PROPS "')\""
- "/>\n",
- 1);
- break;
- }
+ if (this->ProjectType == vcxproj) {
+ Elem(e0, "Import").Attribute("Project", VS10_CXX_PROPS);
+ }
+ {
+ Elem e1(e0, "ImportGroup");
+ e1.Attribute("Label", "ExtensionSettings");
+ e1.SetHasElements();
+
+ if (this->GlobalGenerator->IsCudaEnabled()) {
+ auto customDir =
+ this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString();
+ std::string cudaPath = customDir.empty()
+ ? "$(VCTargetsPath)\\BuildCustomizations\\"
+ : customDir +
+ "CUDAVisualStudioIntegration\\extras\\"
+ "visual_studio_integration\\MSBuildExtensions\\";
+ Elem(e1, "Import")
+ .Attribute("Project",
+ std::move(cudaPath) + "CUDA " +
+ this->GlobalGenerator->GetPlatformToolsetCuda() +
+ ".props");
+ }
+ if (this->GlobalGenerator->IsMasmEnabled()) {
+ Elem(e1, "Import")
+ .Attribute("Project",
+ "$(VCTargetsPath)\\BuildCustomizations\\masm.props");
+ }
+ if (this->GlobalGenerator->IsNasmEnabled()) {
+ // Always search in the standard modules location.
+ std::string propsTemplate =
+ GetCMakeFilePath("Templates/MSBuild/nasm.props.in");
+
+ std::string propsLocal =
+ cmStrCat(this->DefaultArtifactDir, "\\nasm.props");
+ ConvertToWindowsSlash(propsLocal);
+ this->Makefile->ConfigureFile(propsTemplate, propsLocal, false, true,
+ true);
+ Elem(e1, "Import").Attribute("Project", propsLocal);
+ }
+ }
+ {
+ Elem e1(e0, "ImportGroup");
+ e1.Attribute("Label", "PropertySheets");
+ std::string props;
+ switch (this->ProjectType) {
+ case vcxproj:
+ props = VS10_CXX_USER_PROPS;
+ break;
+ case csproj:
+ props = VS10_CSharp_USER_PROPS;
+ break;
+ }
+ if (const char* p =
+ this->GeneratorTarget->GetProperty("VS_USER_PROPS")) {
+ props = p;
+ }
+ if (!props.empty()) {
+ ConvertToWindowsSlash(props);
+ Elem(e1, "Import")
+ .Attribute("Project", props)
+ .Attribute("Condition", "exists('" + props + "')")
+ .Attribute("Label", "LocalAppDataPlatform");
+ }
- this->WriteProjectConfigurationValues();
-
- if (vcxproj == this->ProjectType) {
- this->WriteString("<Import Project=\"" VS10_CXX_PROPS "\" />\n", 1);
- }
- this->WriteString("<ImportGroup Label=\"ExtensionSettings\">\n", 1);
- if (this->GlobalGenerator->IsCudaEnabled()) {
- this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
- "BuildCustomizations\\CUDA ",
- 2);
- (*this->BuildFileStream)
- << cmVS10EscapeXML(this->GlobalGenerator->GetPlatformToolsetCudaString())
- << ".props\" />\n";
- }
- if (this->GlobalGenerator->IsMasmEnabled()) {
- this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
- "BuildCustomizations\\masm.props\" />\n",
- 2);
- }
- if (this->GlobalGenerator->IsNasmEnabled()) {
- // Always search in the standard modules location.
- std::string propsTemplate =
- GetCMakeFilePath("Templates/MSBuild/nasm.props.in");
-
- std::string propsLocal;
- propsLocal += this->DefaultArtifactDir;
- propsLocal += "\\nasm.props";
- this->ConvertToWindowsSlash(propsLocal);
- this->Makefile->ConfigureFile(propsTemplate.c_str(), propsLocal.c_str(),
- false, true, true);
- std::string import = std::string("<Import Project=\"") +
- cmVS10EscapeXML(propsLocal) + "\" />\n";
- this->WriteString(import.c_str(), 2);
- }
- this->WriteString("</ImportGroup>\n", 1);
- this->WriteString("<ImportGroup Label=\"PropertySheets\">\n", 1);
- {
- std::string props;
+ this->WritePlatformExtensions(e1);
+ }
+ Elem(e0, "PropertyGroup").Attribute("Label", "UserMacros");
+ this->WriteWinRTPackageCertificateKeyFile(e0);
+ this->WritePathAndIncrementalLinkOptions(e0);
+ this->WriteCEDebugProjectConfigurationValues(e0);
+ this->WriteItemDefinitionGroups(e0);
+ this->WriteCustomCommands(e0);
+ this->WriteAllSources(e0);
+ this->WriteDotNetReferences(e0);
+ this->WritePackageReferences(e0);
+ this->WriteImports(e0);
+ this->WriteEmbeddedResourceGroup(e0);
+ this->WriteXamlFilesGroup(e0);
+ this->WriteWinRTReferences(e0);
+ this->WriteProjectReferences(e0);
+ this->WriteSDKReferences(e0);
switch (this->ProjectType) {
case vcxproj:
- props = VS10_CXX_USER_PROPS;
+ Elem(e0, "Import").Attribute("Project", VS10_CXX_TARGETS);
break;
case csproj:
- props = VS10_CSharp_USER_PROPS;
+ if (this->GlobalGenerator->TargetsWindowsCE()) {
+ Elem(e0, "Import").Attribute("Project", VS10_CSharp_NETCF_TARGETS);
+ } else {
+ Elem(e0, "Import").Attribute("Project", VS10_CSharp_TARGETS);
+ }
break;
}
- if (const char* p = this->GeneratorTarget->GetProperty("VS_USER_PROPS")) {
- props = p;
- }
- if (!props.empty()) {
- this->ConvertToWindowsSlash(props);
- this->WriteString("", 2);
- (*this->BuildFileStream)
- << "<Import Project=\"" << cmVS10EscapeXML(props) << "\""
- << " Condition=\"exists('" << cmVS10EscapeXML(props) << "')\""
- << " Label=\"LocalAppDataPlatform\" />\n";
- }
- }
- this->WritePlatformExtensions();
- this->WriteString("</ImportGroup>\n", 1);
- this->WriteString("<PropertyGroup Label=\"UserMacros\" />\n", 1);
- this->WriteWinRTPackageCertificateKeyFile();
- this->WritePathAndIncrementalLinkOptions();
- this->WriteItemDefinitionGroups();
- this->WriteCustomCommands();
- this->WriteAllSources();
- this->WriteDotNetReferences();
- this->WriteEmbeddedResourceGroup();
- this->WriteXamlFilesGroup();
- this->WriteWinRTReferences();
- this->WriteProjectReferences();
- this->WriteSDKReferences();
- switch (this->ProjectType) {
- case vcxproj:
- this->WriteString("<Import Project=\"" VS10_CXX_TARGETS "\" />\n", 1);
- break;
- case csproj:
- this->WriteString("<Import Project=\"" VS10_CSharp_TARGETS "\" />\n", 1);
- break;
+
+ this->WriteTargetSpecificReferences(e0);
+ {
+ Elem e1(e0, "ImportGroup");
+ e1.Attribute("Label", "ExtensionTargets");
+ e1.SetHasElements();
+ this->WriteTargetsFileReferences(e1);
+ if (this->GlobalGenerator->IsCudaEnabled()) {
+ auto customDir =
+ this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString();
+ std::string cudaPath = customDir.empty()
+ ? "$(VCTargetsPath)\\BuildCustomizations\\"
+ : customDir +
+ "CUDAVisualStudioIntegration\\extras\\"
+ "visual_studio_integration\\MSBuildExtensions\\";
+ Elem(e1, "Import")
+ .Attribute("Project",
+ std::move(cudaPath) + "CUDA " +
+ this->GlobalGenerator->GetPlatformToolsetCuda() +
+ ".targets");
+ }
+ if (this->GlobalGenerator->IsMasmEnabled()) {
+ Elem(e1, "Import")
+ .Attribute("Project",
+ "$(VCTargetsPath)\\BuildCustomizations\\masm.targets");
+ }
+ if (this->GlobalGenerator->IsNasmEnabled()) {
+ std::string nasmTargets =
+ GetCMakeFilePath("Templates/MSBuild/nasm.targets");
+ Elem(e1, "Import").Attribute("Project", nasmTargets);
+ }
+ }
+ if (this->ProjectType == csproj) {
+ for (std::string const& c : this->Configurations) {
+ Elem e1(e0, "PropertyGroup");
+ e1.Attribute("Condition", "'$(Configuration)' == '" + c + "'");
+ e1.SetHasElements();
+ this->WriteEvents(e1, c);
+ }
+ // make sure custom commands are executed before build (if necessary)
+ {
+ Elem e1(e0, "PropertyGroup");
+ std::ostringstream oss;
+ oss << "\n";
+ for (std::string const& i : this->CSharpCustomCommandNames) {
+ oss << " " << i << ";\n";
+ }
+ oss << " "
+ << "$(BuildDependsOn)\n";
+ e1.Element("BuildDependsOn", oss.str());
+ }
+ }
+ }
+
+ if (BuildFileStream.Close()) {
+ this->GlobalGenerator->FileReplacedDuringGenerate(PathToProjectFile);
}
- this->WriteTargetSpecificReferences();
- this->WriteString("<ImportGroup Label=\"ExtensionTargets\">\n", 1);
- this->WriteTargetsFileReferences();
- if (this->GlobalGenerator->IsCudaEnabled()) {
- this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
- "BuildCustomizations\\CUDA ",
- 2);
- (*this->BuildFileStream)
- << cmVS10EscapeXML(this->GlobalGenerator->GetPlatformToolsetCudaString())
- << ".targets\" />\n";
- }
- if (this->GlobalGenerator->IsMasmEnabled()) {
- this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
- "BuildCustomizations\\masm.targets\" />\n",
- 2);
- }
- if (this->GlobalGenerator->IsNasmEnabled()) {
- std::string nasmTargets =
- GetCMakeFilePath("Templates/MSBuild/nasm.targets");
- std::string import = "<Import Project=\"";
- import += cmVS10EscapeXML(nasmTargets) + "\" />\n";
- this->WriteString(import.c_str(), 2);
- }
- this->WriteString("</ImportGroup>\n", 1);
- if (csproj == this->ProjectType) {
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- this->WriteString("<PropertyGroup Condition=\"'$(Configuration)' == '",
- 1);
- (*this->BuildFileStream) << *i << "'\">\n";
- this->WriteEvents(*i);
- this->WriteString("</PropertyGroup>\n", 1);
- }
- }
- this->WriteString("</Project>", 0);
// The groups are stored in a separate file for VS 10
this->WriteGroups();
}
-void cmVisualStudio10TargetGenerator::WriteDotNetReferences()
+void cmVisualStudio10TargetGenerator::WritePackageReferences(Elem& e0)
+{
+ std::vector<std::string> packageReferences;
+ if (const char* vsPackageReferences =
+ this->GeneratorTarget->GetProperty("VS_PACKAGE_REFERENCES")) {
+ cmExpandList(vsPackageReferences, packageReferences);
+ }
+ if (!packageReferences.empty()) {
+ Elem e1(e0, "ItemGroup");
+ for (std::string const& ri : packageReferences) {
+ size_t versionIndex = ri.find_last_of('_');
+ if (versionIndex != std::string::npos) {
+ WritePackageReference(e1, ri.substr(0, versionIndex),
+ ri.substr(versionIndex + 1));
+ }
+ }
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WritePackageReference(
+ Elem& e1, std::string const& ref, std::string const& version)
+{
+ Elem e2(e1, "PackageReference");
+ e2.Attribute("Include", ref);
+ e2.Attribute("Version", version);
+}
+
+void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0)
{
std::vector<std::string> references;
- typedef std::pair<std::string, std::string> HintReference;
- std::vector<HintReference> hintReferences;
if (const char* vsDotNetReferences =
this->GeneratorTarget->GetProperty("VS_DOTNET_REFERENCES")) {
- cmSystemTools::ExpandListArgument(vsDotNetReferences, references);
+ cmExpandList(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);
- if (name != "") {
- std::string path = i->second.GetValue();
+ for (auto const& i : props.GetList()) {
+ if (i.first.find("VS_DOTNET_REFERENCE_") == 0) {
+ std::string name = i.first.substr(20);
+ if (!name.empty()) {
+ std::string path = i.second;
if (!cmsys::SystemTools::FileIsFullPath(path)) {
- path = std::string(this->GeneratorTarget->Target->GetMakefile()
- ->GetCurrentSourceDirectory()) +
- "/" + path;
+ path = this->Makefile->GetCurrentSourceDirectory() + "/" + path;
}
- this->ConvertToWindowsSlash(path);
- hintReferences.push_back(HintReference(name, path));
+ ConvertToWindowsSlash(path);
+ this->DotNetHintReferences[""].push_back(
+ DotNetHintReference(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) {
+ if (!references.empty() || !this->DotNetHintReferences.empty()) {
+ Elem e1(e0, "ItemGroup");
+ 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)) {
+ if (cmsys::SystemTools::FileExists(ri, true)) {
std::string name =
- cmsys::SystemTools::GetFilenameWithoutExtension(*ri);
- std::string path = *ri;
- this->ConvertToWindowsSlash(path);
- hintReferences.push_back(HintReference(name, path));
+ cmsys::SystemTools::GetFilenameWithoutLastExtension(ri);
+ std::string path = ri;
+ ConvertToWindowsSlash(path);
+ this->DotNetHintReferences[""].push_back(
+ DotNetHintReference(name, path));
} else {
- this->WriteDotNetReference(*ri, "");
+ this->WriteDotNetReference(e1, 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& h : this->DotNetHintReferences) {
+ // DotNetHintReferences is also populated from AddLibraries().
+ // The configuration specific hint references are added there.
+ for (const auto& i : h.second) {
+ this->WriteDotNetReference(e1, i.first, i.second, h.first);
+ }
}
- this->WriteString("</ItemGroup>\n", 1);
}
}
void cmVisualStudio10TargetGenerator::WriteDotNetReference(
- std::string const& ref, std::string const& hint)
+ Elem& e1, std::string const& ref, std::string const& hint,
+ std::string const& config)
{
- this->WriteString("<Reference Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(ref) << "\">\n";
- this->WriteString("<CopyLocalSatelliteAssemblies>true"
- "</CopyLocalSatelliteAssemblies>\n",
- 3);
- this->WriteString("<ReferenceOutputAssembly>true"
- "</ReferenceOutputAssembly>\n",
- 3);
+ Elem e2(e1, "Reference");
+ // If 'config' is not empty, the reference is only added for the given
+ // configuration. This is used when referencing imported managed assemblies.
+ // See also cmVisualStudio10TargetGenerator::AddLibraries().
+ if (!config.empty()) {
+ e2.Attribute("Condition", this->CalcCondition(config));
+ }
+ e2.Attribute("Include", ref);
+ e2.Element("CopyLocalSatelliteAssemblies", "true");
+ e2.Element("ReferenceOutputAssembly", "true");
if (!hint.empty()) {
const char* privateReference = "True";
if (const char* value = this->GeneratorTarget->GetProperty(
"VS_DOTNET_REFERENCES_COPY_LOCAL")) {
- if (cmSystemTools::IsOff(value)) {
+ if (cmIsOff(value)) {
privateReference = "False";
}
}
- this->WriteString("<Private>", 3);
- (*this->BuildFileStream) << privateReference << "</Private>\n";
- this->WriteString("<HintPath>", 3);
- (*this->BuildFileStream) << hint << "</HintPath>\n";
+ e2.Element("Private", privateReference);
+ e2.Element("HintPath", hint);
}
- this->WriteString("</Reference>\n", 2);
+ this->WriteDotNetReferenceCustomTags(e2, ref);
}
-void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
+void cmVisualStudio10TargetGenerator::WriteImports(Elem& e0)
+{
+ const char* imports =
+ this->GeneratorTarget->Target->GetProperty("VS_PROJECT_IMPORT");
+ if (imports) {
+ std::vector<std::string> argsSplit =
+ cmExpandedList(std::string(imports), false);
+ for (auto& path : argsSplit) {
+ if (!cmsys::SystemTools::FileIsFullPath(path)) {
+ path = this->Makefile->GetCurrentSourceDirectory() + "/" + path;
+ }
+ ConvertToWindowsSlash(path);
+ Elem e1(e0, "Import");
+ e1.Attribute("Project", path);
+ }
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteDotNetReferenceCustomTags(
+ Elem& e2, std::string const& ref)
+{
+
+ static const std::string refpropPrefix = "VS_DOTNET_REFERENCEPROP_";
+ static const std::string refpropInfix = "_TAG_";
+ const std::string refPropFullPrefix = refpropPrefix + ref + refpropInfix;
+ using CustomTags = std::map<std::string, std::string>;
+ CustomTags tags;
+ cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties();
+ for (const auto& i : props.GetList()) {
+ if (i.first.find(refPropFullPrefix) == 0) {
+ std::string refTag = i.first.substr(refPropFullPrefix.length());
+ std::string refVal = i.second;
+ if (!refTag.empty() && !refVal.empty()) {
+ tags[refTag] = refVal;
+ }
+ }
+ }
+ for (auto const& tag : tags) {
+ e2.Element(tag.first.c_str(), tag.second);
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0)
{
std::vector<cmSourceFile const*> resxObjs;
this->GeneratorTarget->GetResxSources(resxObjs, "");
if (!resxObjs.empty()) {
- this->WriteString("<ItemGroup>\n", 1);
+ Elem e1(e0, "ItemGroup");
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();
- this->WriteString("<EmbeddedResource Include=\"", 2);
- this->ConvertToWindowsSlash(obj);
+ ConvertToWindowsSlash(srcDir);
+ for (cmSourceFile const* oi : resxObjs) {
+ std::string obj = oi->GetFullPath();
+ ConvertToWindowsSlash(obj);
bool useRelativePath = false;
- if (csproj == this->ProjectType && this->InSourceBuild) {
+ if (this->ProjectType == csproj && this->InSourceBuild) {
// If we do an in-source build and the resource file is in a
// subdirectory
// of the .csproj file, we have to use relative pathnames, otherwise
// 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;
}
}
- (*this->BuildFileStream) << obj << "\">\n";
+ Elem e2(e1, "EmbeddedResource");
+ e2.Attribute("Include", obj);
- if (csproj != this->ProjectType) {
- this->WriteString("<DependentUpon>", 3);
+ if (this->ProjectType != csproj) {
std::string hFileName = obj.substr(0, obj.find_last_of(".")) + ".h";
- (*this->BuildFileStream) << hFileName << "</DependentUpon>\n";
+ e2.Element("DependentUpon", hFileName);
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- this->WritePlatformConfigTag("LogicalName", i->c_str(), 3);
+ for (std::string const& c : this->Configurations) {
+ std::string s;
if (this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE") ||
// Handle variant of VS_GLOBAL_<variable> for RootNamespace.
this->GeneratorTarget->GetProperty("VS_GLOBAL_RootNamespace")) {
- (*this->BuildFileStream) << "$(RootNamespace).";
+ s = "$(RootNamespace).";
}
- (*this->BuildFileStream) << "%(Filename)";
- (*this->BuildFileStream) << ".resources";
- (*this->BuildFileStream) << "</LogicalName>\n";
+ s += "%(Filename).resources";
+ e2.WritePlatformConfigTag("LogicalName", this->CalcCondition(c), s);
}
} 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) {
@@ -721,25 +965,21 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
link = cmsys::SystemTools::GetFilenameName(obj);
}
if (!link.empty()) {
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << link << "</Link>\n";
+ e2.Element("Link", link);
}
}
// 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()) {
- this->WriteString("<Generator>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(generator)
- << "</Generator>\n";
+ e2.Element("Generator", generator);
if (designerResource.find(srcDir) == 0) {
designerResource = designerResource.substr(srcDir.length() + 1);
} else if (designerResource.find(binDir) == 0) {
@@ -748,60 +988,53 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
designerResource =
cmsys::SystemTools::GetFilenameName(designerResource);
}
- this->ConvertToWindowsSlash(designerResource);
- this->WriteString("<LastGenOutput>", 3);
- (*this->BuildFileStream) << designerResource
- << "</LastGenOutput>\n";
+ ConvertToWindowsSlash(designerResource);
+ e2.Element("LastGenOutput", designerResource);
}
}
- const cmPropertyMap& props = (*oi)->GetProperties();
- for (cmPropertyMap::const_iterator p = props.begin(); p != props.end();
- ++p) {
+ const cmPropertyMap& props = oi->GetProperties();
+ for (const std::string& p : props.GetKeys()) {
static const std::string propNamePrefix = "VS_CSHARP_";
- if (p->first.find(propNamePrefix.c_str()) == 0) {
- std::string tagName = p->first.substr(propNamePrefix.length());
+ if (p.find(propNamePrefix) == 0) {
+ std::string tagName = p.substr(propNamePrefix.length());
if (!tagName.empty()) {
- std::string value = props.GetPropertyValue(p->first);
+ std::string value = props.GetPropertyValue(p);
if (!value.empty()) {
- this->WriteString("<", 3);
- (*this->BuildFileStream) << tagName << ">";
- (*this->BuildFileStream) << cmVS10EscapeXML(value);
- (*this->BuildFileStream) << "</" << tagName << ">\n";
+ e2.Element(tagName.c_str(), value);
}
}
}
}
}
-
- this->WriteString("</EmbeddedResource>\n", 2);
}
- this->WriteString("</ItemGroup>\n", 1);
}
}
-void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup()
+void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup(Elem& e0)
{
std::vector<cmSourceFile const*> xamlObjs;
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();
- std::string xamlType;
- const char* xamlTypeProperty = (*oi)->GetProperty("VS_XAML_TYPE");
+ Elem e1(e0, "ItemGroup");
+ for (cmSourceFile const* oi : xamlObjs) {
+ std::string obj = oi->GetFullPath();
+ const char* xamlType;
+ const char* xamlTypeProperty = oi->GetProperty("VS_XAML_TYPE");
if (xamlTypeProperty) {
xamlType = xamlTypeProperty;
} else {
xamlType = "Page";
}
- this->WriteSource(xamlType, *oi, ">\n");
- if (csproj == this->ProjectType && !this->InSourceBuild) {
+ Elem e2(e1, xamlType);
+ this->WriteSource(e2, oi);
+ e2.SetHasElements();
+ if (this->ProjectType == csproj && !this->InSourceBuild) {
// add <Link> tag to written XAML source if necessary
- const std::string srcDir = this->Makefile->GetCurrentSourceDirectory();
- const std::string binDir = this->Makefile->GetCurrentBinaryDirectory();
+ const std::string& srcDir =
+ this->Makefile->GetCurrentSourceDirectory();
+ const std::string& binDir =
+ this->Makefile->GetCurrentBinaryDirectory();
std::string link;
if (obj.find(srcDir) == 0) {
link = obj.substr(srcDir.length() + 1);
@@ -811,64 +1044,57 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup()
link = cmsys::SystemTools::GetFilenameName(obj);
}
if (!link.empty()) {
- this->ConvertToWindowsSlash(link);
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << link << "</Link>\n";
+ ConvertToWindowsSlash(link);
+ e2.Element("Link", link);
}
}
- this->WriteString("<SubType>Designer</SubType>\n", 3);
- this->WriteString("</", 2);
- (*this->BuildFileStream) << xamlType << ">\n";
+ e2.Element("SubType", "Designer");
}
- this->WriteString("</ItemGroup>\n", 1);
}
}
-void cmVisualStudio10TargetGenerator::WriteTargetSpecificReferences()
+void cmVisualStudio10TargetGenerator::WriteTargetSpecificReferences(Elem& e0)
{
if (this->MSTools) {
if (this->GlobalGenerator->TargetsWindowsPhone() &&
this->GlobalGenerator->GetSystemVersion() == "8.0") {
- this->WriteString("<Import Project=\""
- "$(MSBuildExtensionsPath)\\Microsoft\\WindowsPhone\\v"
- "$(TargetPlatformVersion)\\Microsoft.Cpp.WindowsPhone."
- "$(TargetPlatformVersion).targets\" />\n",
- 1);
+ Elem(e0, "Import")
+ .Attribute("Project",
+ "$(MSBuildExtensionsPath)\\Microsoft\\WindowsPhone\\v"
+ "$(TargetPlatformVersion)\\Microsoft.Cpp.WindowsPhone."
+ "$(TargetPlatformVersion).targets");
}
}
}
-void cmVisualStudio10TargetGenerator::WriteTargetsFileReferences()
+void cmVisualStudio10TargetGenerator::WriteTargetsFileReferences(Elem& e1)
{
- for (std::vector<TargetsFileAndConfigs>::iterator i =
- this->TargetsFileAndConfigsVec.begin();
- i != this->TargetsFileAndConfigsVec.end(); ++i) {
- TargetsFileAndConfigs const& tac = *i;
- this->WriteString("<Import Project=\"", 3);
- (*this->BuildFileStream) << tac.File << "\" ";
- (*this->BuildFileStream) << "Condition=\"";
- (*this->BuildFileStream) << "Exists('" << tac.File << "')";
+ for (TargetsFileAndConfigs const& tac : this->TargetsFileAndConfigsVec) {
+ std::ostringstream oss;
+ oss << "Exists('" << tac.File << "')";
if (!tac.Configs.empty()) {
- (*this->BuildFileStream) << " And (";
+ oss << " And (";
for (size_t j = 0; j < tac.Configs.size(); ++j) {
if (j > 0) {
- (*this->BuildFileStream) << " Or ";
+ oss << " Or ";
}
- (*this->BuildFileStream) << "'$(Configuration)'=='" << tac.Configs[j]
- << "'";
+ oss << "'$(Configuration)'=='" << tac.Configs[j] << "'";
}
- (*this->BuildFileStream) << ")";
+ oss << ")";
}
- (*this->BuildFileStream) << "\" />\n";
+
+ Elem(e1, "Import")
+ .Attribute("Project", tac.File)
+ .Attribute("Condition", oss.str());
}
}
-void cmVisualStudio10TargetGenerator::WriteWinRTReferences()
+void cmVisualStudio10TargetGenerator::WriteWinRTReferences(Elem& e0)
{
std::vector<std::string> references;
if (const char* vsWinRTReferences =
this->GeneratorTarget->GetProperty("VS_WINRT_REFERENCES")) {
- cmSystemTools::ExpandListArgument(vsWinRTReferences, references);
+ cmExpandList(vsWinRTReferences, references);
}
if (this->GlobalGenerator->TargetsWindowsPhone() &&
@@ -877,77 +1103,68 @@ void cmVisualStudio10TargetGenerator::WriteWinRTReferences()
references.push_back("platform.winmd");
}
if (!references.empty()) {
- this->WriteString("<ItemGroup>\n", 1);
- for (std::vector<std::string>::iterator ri = references.begin();
- ri != references.end(); ++ri) {
- this->WriteString("<Reference Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(*ri) << "\">\n";
- this->WriteString("<IsWinMDFile>true</IsWinMDFile>\n", 3);
- this->WriteString("</Reference>\n", 2);
+ Elem e1(e0, "ItemGroup");
+ for (std::string const& ri : references) {
+ Elem e2(e1, "Reference");
+ e2.Attribute("Include", ri);
+ e2.Element("IsWinMDFile", "true");
}
- this->WriteString("</ItemGroup>\n", 1);
}
}
// ConfigurationType Application, Utility StaticLibrary DynamicLibrary
-void cmVisualStudio10TargetGenerator::WriteProjectConfigurations()
+void cmVisualStudio10TargetGenerator::WriteProjectConfigurations(Elem& e0)
{
- this->WriteString("<ItemGroup Label=\"ProjectConfigurations\">\n", 1);
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- this->WriteString("<ProjectConfiguration Include=\"", 2);
- (*this->BuildFileStream) << *i << "|" << this->Platform << "\">\n";
- this->WriteString("<Configuration>", 3);
- (*this->BuildFileStream) << *i << "</Configuration>\n";
- this->WriteString("<Platform>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform)
- << "</Platform>\n";
- this->WriteString("</ProjectConfiguration>\n", 2);
- }
- this->WriteString("</ItemGroup>\n", 1);
+ Elem e1(e0, "ItemGroup");
+ e1.Attribute("Label", "ProjectConfigurations");
+ for (std::string const& c : this->Configurations) {
+ Elem e2(e1, "ProjectConfiguration");
+ e2.Attribute("Include", c + "|" + this->Platform);
+ e2.Element("Configuration", c);
+ e2.Element("Platform", this->Platform);
+ }
}
-void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
+void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0)
{
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- this->WritePlatformConfigTag("PropertyGroup", i->c_str(), 1,
- " Label=\"Configuration\"", "\n");
-
- if (csproj != this->ProjectType) {
- std::string configType = "<ConfigurationType>";
+ for (std::string const& c : this->Configurations) {
+ Elem e1(e0, "PropertyGroup");
+ e1.Attribute("Condition", this->CalcCondition(c));
+ e1.Attribute("Label", "Configuration");
+
+ if (this->ProjectType != csproj) {
+ std::string configType;
if (const char* vsConfigurationType =
this->GeneratorTarget->GetProperty("VS_CONFIGURATION_TYPE")) {
- configType += cmVS10EscapeXML(vsConfigurationType);
+ configType = cmGeneratorExpression::Evaluate(vsConfigurationType,
+ this->LocalGenerator, c);
} else {
switch (this->GeneratorTarget->GetType()) {
case cmStateEnums::SHARED_LIBRARY:
case cmStateEnums::MODULE_LIBRARY:
- configType += "DynamicLibrary";
+ configType = "DynamicLibrary";
break;
case cmStateEnums::OBJECT_LIBRARY:
case cmStateEnums::STATIC_LIBRARY:
- configType += "StaticLibrary";
+ configType = "StaticLibrary";
break;
case cmStateEnums::EXECUTABLE:
if (this->NsightTegra &&
!this->GeneratorTarget->GetPropertyAsBool("ANDROID_GUI")) {
// Android executables are .so too.
- configType += "DynamicLibrary";
+ configType = "DynamicLibrary";
} else {
- configType += "Application";
+ configType = "Application";
}
break;
case cmStateEnums::UTILITY:
case cmStateEnums::GLOBAL_TARGET:
if (this->NsightTegra) {
// Tegra-Android platform does not understand "Utility".
- configType += "StaticLibrary";
+ configType = "StaticLibrary";
} else {
- configType += "Utility";
+ configType = "Utility";
}
break;
case cmStateEnums::UNKNOWN_LIBRARY:
@@ -955,32 +1172,52 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
break;
}
}
- configType += "</ConfigurationType>\n";
- this->WriteString(configType.c_str(), 2);
+ e1.Element("ConfigurationType", configType);
}
if (this->MSTools) {
if (!this->Managed) {
- this->WriteMSToolConfigurationValues(*i);
+ this->WriteMSToolConfigurationValues(e1, c);
} else {
- this->WriteMSToolConfigurationValuesManaged(*i);
+ this->WriteMSToolConfigurationValuesManaged(e1, c);
}
} else if (this->NsightTegra) {
- this->WriteNsightTegraConfigurationValues(*i);
+ this->WriteNsightTegraConfigurationValues(e1, c);
}
+ }
+}
- this->WriteString("</PropertyGroup>\n", 1);
+void cmVisualStudio10TargetGenerator::WriteCEDebugProjectConfigurationValues(
+ Elem& e0)
+{
+ if (!this->GlobalGenerator->TargetsWindowsCE()) {
+ return;
+ }
+ const char* additionalFiles =
+ this->GeneratorTarget->GetProperty("DEPLOYMENT_ADDITIONAL_FILES");
+ const char* remoteDirectory =
+ this->GeneratorTarget->GetProperty("DEPLOYMENT_REMOTE_DIRECTORY");
+ if (!(additionalFiles || remoteDirectory)) {
+ return;
+ }
+ for (std::string const& c : this->Configurations) {
+ Elem e1(e0, "PropertyGroup");
+ e1.Attribute("Condition", this->CalcCondition(c));
+
+ if (remoteDirectory) {
+ e1.Element("RemoteDirectory", remoteDirectory);
+ }
+ if (additionalFiles) {
+ e1.Element("CEAdditionalFiles", additionalFiles);
+ }
}
}
void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
- std::string const& config)
+ Elem& e1, std::string const& config)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- const char* mfcFlag =
- this->GeneratorTarget->Target->GetMakefile()->GetDefinition(
- "CMAKE_MFC_FLAG");
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
if (mfcFlag) {
std::string const mfcFlagValue = mfcFlag;
@@ -992,9 +1229,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
useOfMfcValue = "Dynamic";
}
}
- std::string mfcLine = "<UseOfMfc>";
- mfcLine += useOfMfcValue + "</UseOfMfc>\n";
- this->WriteString(mfcLine.c_str(), 2);
+ e1.Element("UseOfMfc", useOfMfcValue);
}
if ((this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY &&
@@ -1003,161 +1238,158 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
this->GlobalGenerator->TargetsWindowsPhone() ||
this->GlobalGenerator->TargetsWindowsStore() ||
this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) {
- this->WriteString("<CharacterSet>Unicode</CharacterSet>\n", 2);
+ e1.Element("CharacterSet", "Unicode");
} else if (this->GeneratorTarget->GetType() <=
- cmStateEnums::MODULE_LIBRARY &&
+ cmStateEnums::OBJECT_LIBRARY &&
this->ClOptions[config]->UsingSBCS()) {
- this->WriteString("<CharacterSet>NotSet</CharacterSet>\n", 2);
+ e1.Element("CharacterSet", "NotSet");
} else {
- this->WriteString("<CharacterSet>MultiByte</CharacterSet>\n", 2);
+ e1.Element("CharacterSet", "MultiByte");
}
if (const char* toolset = gg->GetPlatformToolset()) {
- std::string pts = "<PlatformToolset>";
- pts += toolset;
- pts += "</PlatformToolset>\n";
- this->WriteString(pts.c_str(), 2);
+ e1.Element("PlatformToolset", toolset);
}
if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") ||
this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) {
- this->WriteString("<WindowsAppContainer>true"
- "</WindowsAppContainer>\n",
- 2);
+ e1.Element("WindowsAppContainer", "true");
+ }
+ if (this->IPOEnabledConfigurations.count(config) > 0) {
+ e1.Element("WholeProgramOptimization", "true");
+ }
+ {
+ auto s = this->SpectreMitigation.find(config);
+ if (s != this->SpectreMitigation.end()) {
+ e1.Element("SpectreMitigation", s->second);
+ }
}
}
void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
- std::string const& config)
+ Elem& e1, std::string const& config)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ if (this->GeneratorTarget->GetType() > cmStateEnums::OBJECT_LIBRARY) {
+ return;
+ }
+
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
Options& o = *(this->ClOptions[config]);
if (o.IsDebug()) {
- this->WriteString("<DebugSymbols>true</DebugSymbols>\n", 2);
- this->WriteString("<DefineDebug>true</DefineDebug>\n", 2);
+ e1.Element("DebugSymbols", "true");
+ e1.Element("DefineDebug", "true");
}
- std::string outDir =
- this->GeneratorTarget->GetDirectory(config.c_str()) + "/";
- this->ConvertToWindowsSlash(outDir);
- this->WriteString("<OutputPath>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(outDir) << "</OutputPath>\n";
+ std::string outDir = this->GeneratorTarget->GetDirectory(config) + "/";
+ ConvertToWindowsSlash(outDir);
+ e1.Element("OutputPath", outDir);
if (o.HasFlag("Platform")) {
- this->WriteString("<PlatformTarget>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(o.GetFlag("Platform"))
- << "</PlatformTarget>\n";
+ e1.Element("PlatformTarget", o.GetFlag("Platform"));
o.RemoveFlag("Platform");
}
if (const char* toolset = gg->GetPlatformToolset()) {
- this->WriteString("<PlatformToolset>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(toolset)
- << "</PlatformToolset>\n";
+ e1.Element("PlatformToolset", toolset);
}
- std::string postfixName = cmSystemTools::UpperCase(config);
- postfixName += "_POSTFIX";
+ std::string postfixName =
+ cmStrCat(cmSystemTools::UpperCase(config), "_POSTFIX");
std::string assemblyName = this->GeneratorTarget->GetOutputName(
config, cmStateEnums::RuntimeBinaryArtifact);
if (const char* postfix = this->GeneratorTarget->GetProperty(postfixName)) {
assemblyName += postfix;
}
- this->WriteString("<AssemblyName>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(assemblyName)
- << "</AssemblyName>\n";
+ e1.Element("AssemblyName", assemblyName);
if (cmStateEnums::EXECUTABLE == this->GeneratorTarget->GetType()) {
- this->WriteString("<StartAction>Program</StartAction>\n", 2);
- this->WriteString("<StartProgram>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(outDir)
- << cmVS10EscapeXML(assemblyName)
- << ".exe</StartProgram>\n";
+ e1.Element("StartAction", "Program");
+ e1.Element("StartProgram", outDir + assemblyName + ".exe");
}
- o.OutputFlagMap(*this->BuildFileStream, " ");
+ OptionsHelper oh(o, e1);
+ oh.OutputFlagMap();
}
//----------------------------------------------------------------------------
void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues(
- std::string const&)
+ Elem& e1, std::string const&)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
const char* toolset = gg->GetPlatformToolset();
- std::string ntv = "<NdkToolchainVersion>";
- ntv += toolset ? toolset : "Default";
- ntv += "</NdkToolchainVersion>\n";
- this->WriteString(ntv.c_str(), 2);
+ e1.Element("NdkToolchainVersion", toolset ? toolset : "Default");
if (const char* minApi =
this->GeneratorTarget->GetProperty("ANDROID_API_MIN")) {
- this->WriteString("<AndroidMinAPI>", 2);
- (*this->BuildFileStream) << "android-" << cmVS10EscapeXML(minApi)
- << "</AndroidMinAPI>\n";
+ e1.Element("AndroidMinAPI", "android-" + std::string(minApi));
}
if (const char* api = this->GeneratorTarget->GetProperty("ANDROID_API")) {
- this->WriteString("<AndroidTargetAPI>", 2);
- (*this->BuildFileStream) << "android-" << cmVS10EscapeXML(api)
- << "</AndroidTargetAPI>\n";
+ e1.Element("AndroidTargetAPI", "android-" + std::string(api));
}
if (const char* cpuArch =
this->GeneratorTarget->GetProperty("ANDROID_ARCH")) {
- this->WriteString("<AndroidArch>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(cpuArch) << "</AndroidArch>\n";
+ e1.Element("AndroidArch", cpuArch);
}
if (const char* stlType =
this->GeneratorTarget->GetProperty("ANDROID_STL_TYPE")) {
- this->WriteString("<AndroidStlType>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(stlType)
- << "</AndroidStlType>\n";
+ e1.Element("AndroidStlType", stlType);
}
}
-void cmVisualStudio10TargetGenerator::WriteCustomCommands()
+void cmVisualStudio10TargetGenerator::WriteCustomCommands(Elem& e0)
{
- this->SourcesVisited.clear();
+ this->CSharpCustomCommandNames.clear();
std::vector<cmSourceFile const*> customCommands;
this->GeneratorTarget->GetCustomCommands(customCommands, "");
- for (std::vector<cmSourceFile const*>::const_iterator si =
- customCommands.begin();
- si != customCommands.end(); ++si) {
- this->WriteCustomCommand(*si);
+ for (cmSourceFile const* si : customCommands) {
+ this->WriteCustomCommand(e0, 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()) {
+ // Write directly rather than through WriteCustomCommand because
+ // we do not want the de-duplication and it has no dependencies.
+ if (cmCustomCommand const* command = sf->GetCustomCommand()) {
+ this->WriteCustomRule(e0, sf, *command);
+ }
+ }
}
}
void cmVisualStudio10TargetGenerator::WriteCustomCommand(
- cmSourceFile const* sf)
+ Elem& e0, cmSourceFile const* sf)
{
- if (this->SourcesVisited.insert(sf).second) {
+ if (this->LocalGenerator->GetSourcesVisited(this->GeneratorTarget)
+ .insert(sf)
+ .second) {
if (std::vector<cmSourceFile*> const* depends =
this->GeneratorTarget->GetSourceDepends(sf)) {
- for (std::vector<cmSourceFile*>::const_iterator di = depends->begin();
- di != depends->end(); ++di) {
- this->WriteCustomCommand(*di);
+ for (cmSourceFile const* di : *depends) {
+ this->WriteCustomCommand(e0, di);
}
}
if (cmCustomCommand const* command = sf->GetCustomCommand()) {
- this->WriteString("<ItemGroup>\n", 1);
- this->WriteCustomRule(sf, *command);
- this->WriteString("</ItemGroup>\n", 1);
+ // C# projects write their <Target> within WriteCustomRule()
+ this->WriteCustomRule(e0, sf, *command);
}
}
}
void cmVisualStudio10TargetGenerator::WriteCustomRule(
- cmSourceFile const* source, cmCustomCommand const& command)
+ Elem& e0, cmSourceFile const* source, cmCustomCommand const& command)
{
std::string sourcePath = source->GetFullPath();
// VS 10 will always rebuild a custom command attached to a .rule
// file that doesn't exist so create the file explicitly.
if (source->GetPropertyAsBool("__CMAKE_RULE")) {
- if (!cmSystemTools::FileExists(sourcePath.c_str())) {
+ if (!cmSystemTools::FileExists(sourcePath)) {
// Make sure the path exists for the file
std::string path = cmSystemTools::GetFilenamePath(sourcePath);
- cmSystemTools::MakeDirectory(path.c_str());
+ cmSystemTools::MakeDirectory(path);
cmsys::ofstream fout(sourcePath.c_str());
if (fout) {
fout << "# generated from CMake\n";
@@ -1167,60 +1399,144 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
// preventing dependent rebuilds.
this->ForceOld(sourcePath);
} else {
- std::string error = "Could not create file: [";
- error += sourcePath;
- error += "] ";
- cmSystemTools::Error(error.c_str(),
- cmSystemTools::GetLastSystemError().c_str());
+ std::string error =
+ cmStrCat("Could not create file: [", sourcePath, "] ");
+ cmSystemTools::Error(error + cmSystemTools::GetLastSystemError());
}
}
}
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
- this->WriteSource("CustomBuild", source, ">\n");
-
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- cmCustomCommandGenerator ccg(command, *i, this->LocalGenerator);
+ std::unique_ptr<Elem> spe1;
+ std::unique_ptr<Elem> spe2;
+ if (this->ProjectType != csproj) {
+ spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
+ spe2 = cm::make_unique<Elem>(*spe1, "CustomBuild");
+ this->WriteSource(*spe2, source);
+ spe2->SetHasElements();
+ } else {
+ Elem e1(e0, "ItemGroup");
+ Elem e2(e1, "None");
+ std::string link;
+ this->GetCSharpSourceLink(source, link);
+ this->WriteSource(e2, source);
+ e2.SetHasElements();
+ if (!link.empty()) {
+ e2.Element("Link", link);
+ }
+ }
+ for (std::string const& c : this->Configurations) {
+ cmCustomCommandGenerator ccg(command, c, lg);
std::string comment = lg->ConstructComment(ccg);
comment = cmVS10EscapeComment(comment);
- std::string script = cmVS10EscapeXML(lg->ConstructScript(ccg));
- this->WritePlatformConfigTag("Message", i->c_str(), 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(comment) << "</Message>\n";
- this->WritePlatformConfigTag("Command", i->c_str(), 3);
- (*this->BuildFileStream) << script << "</Command>\n";
- this->WritePlatformConfigTag("AdditionalInputs", i->c_str(), 3);
-
- (*this->BuildFileStream) << cmVS10EscapeXML(source->GetFullPath());
- for (std::vector<std::string>::const_iterator d = ccg.GetDepends().begin();
- d != ccg.GetDepends().end(); ++d) {
- std::string dep;
- if (this->LocalGenerator->GetRealDependency(d->c_str(), i->c_str(),
- dep)) {
- this->ConvertToWindowsSlash(dep);
- (*this->BuildFileStream) << ";" << cmVS10EscapeXML(dep);
+ std::string script = lg->ConstructScript(ccg);
+ bool symbolic = false;
+ // input files for custom command
+ std::stringstream additional_inputs;
+ {
+ const char* sep = "";
+ if (this->ProjectType == csproj) {
+ // csproj files do not attach the command to a specific file
+ // so the primary input must be listed explicitly.
+ additional_inputs << source->GetFullPath();
+ sep = ";";
+ }
+
+ // Avoid listing an input more than once.
+ std::set<std::string> unique_inputs;
+ // The source is either implicit an input or has been added above.
+ unique_inputs.insert(source->GetFullPath());
+
+ for (std::string const& d : ccg.GetDepends()) {
+ std::string dep;
+ if (lg->GetRealDependency(d, c, dep)) {
+ if (!unique_inputs.insert(dep).second) {
+ // already listed
+ continue;
+ }
+ ConvertToWindowsSlash(dep);
+ additional_inputs << sep << dep;
+ sep = ";";
+ if (!symbolic) {
+ if (cmSourceFile* sf = this->Makefile->GetSource(
+ dep, cmSourceFileLocationKind::Known)) {
+ symbolic = sf->GetPropertyAsBool("SYMBOLIC");
+ }
+ }
+ }
+ }
+ if (this->ProjectType != csproj) {
+ additional_inputs << sep << "%(AdditionalInputs)";
}
}
- (*this->BuildFileStream) << ";%(AdditionalInputs)</AdditionalInputs>\n";
- this->WritePlatformConfigTag("Outputs", i->c_str(), 3);
- const char* sep = "";
- for (std::vector<std::string>::const_iterator o = ccg.GetOutputs().begin();
- o != ccg.GetOutputs().end(); ++o) {
- std::string out = *o;
- this->ConvertToWindowsSlash(out);
- (*this->BuildFileStream) << sep << cmVS10EscapeXML(out);
- sep = ";";
- }
- (*this->BuildFileStream) << "</Outputs>\n";
- if (this->LocalGenerator->GetVersion() >
- cmGlobalVisualStudioGenerator::VS10) {
- // VS >= 11 let us turn off linking of custom command outputs.
- this->WritePlatformConfigTag("LinkObjects", i->c_str(), 3);
- (*this->BuildFileStream) << "false</LinkObjects>\n";
- }
- }
- this->WriteString("</CustomBuild>\n", 2);
+ // output files for custom command
+ std::stringstream outputs;
+ {
+ const char* sep = "";
+ for (std::string const& o : ccg.GetOutputs()) {
+ std::string out = o;
+ ConvertToWindowsSlash(out);
+ outputs << sep << out;
+ sep = ";";
+ if (!symbolic) {
+ if (cmSourceFile* sf = this->Makefile->GetSource(
+ o, cmSourceFileLocationKind::Known)) {
+ symbolic = sf->GetPropertyAsBool("SYMBOLIC");
+ }
+ }
+ }
+ }
+ if (this->ProjectType == csproj) {
+ std::string name = "CustomCommand_" + c + "_" +
+ cmSystemTools::ComputeStringMD5(sourcePath);
+ this->WriteCustomRuleCSharp(e0, c, name, script, additional_inputs.str(),
+ outputs.str(), comment);
+ } else {
+ this->WriteCustomRuleCpp(*spe2, c, script, additional_inputs.str(),
+ outputs.str(), comment, symbolic);
+ }
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp(
+ Elem& e2, std::string const& config, std::string const& script,
+ std::string const& additional_inputs, std::string const& outputs,
+ std::string const& comment, bool symbolic)
+{
+ const std::string cond = this->CalcCondition(config);
+ e2.WritePlatformConfigTag("Message", cond, comment);
+ e2.WritePlatformConfigTag("Command", cond, script);
+ e2.WritePlatformConfigTag("AdditionalInputs", cond, additional_inputs);
+ e2.WritePlatformConfigTag("Outputs", cond, outputs);
+ if (this->LocalGenerator->GetVersion() >
+ cmGlobalVisualStudioGenerator::VS10) {
+ // VS >= 11 let us turn off linking of custom command outputs.
+ e2.WritePlatformConfigTag("LinkObjects", cond, "false");
+ }
+ if (symbolic &&
+ this->LocalGenerator->GetVersion() >=
+ cmGlobalVisualStudioGenerator::VS16) {
+ // VS >= 16.4 warn if outputs are not created, but one of our
+ // outputs is marked SYMBOLIC and not expected to be created.
+ e2.WritePlatformConfigTag("VerifyInputsAndOutputsExist", cond, "false");
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteCustomRuleCSharp(
+ Elem& e0, std::string const& config, std::string const& name,
+ std::string const& script, std::string const& inputs,
+ std::string const& outputs, std::string const& comment)
+{
+ this->CSharpCustomCommandNames.insert(name);
+ Elem e1(e0, "Target");
+ e1.Attribute("Condition", this->CalcCondition(config));
+ e1.S << "\n Name=\"" << name << "\"";
+ e1.S << "\n Inputs=\"" << cmVS10EscapeAttr(inputs) << "\"";
+ e1.S << "\n Outputs=\"" << cmVS10EscapeAttr(outputs) << "\"";
+ if (!comment.empty()) {
+ Elem(e1, "Exec").Attribute("Command", "echo " + comment);
+ }
+ Elem(e1, "Exec").Attribute("Command", script);
}
std::string cmVisualStudio10TargetGenerator::ConvertPath(
@@ -1228,22 +1544,23 @@ std::string cmVisualStudio10TargetGenerator::ConvertPath(
{
return forceRelative
? cmSystemTools::RelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), path.c_str())
- : path.c_str();
+ this->LocalGenerator->GetCurrentBinaryDirectory(), path)
+ : path;
}
-void cmVisualStudio10TargetGenerator::ConvertToWindowsSlash(std::string& s)
+static void ConvertToWindowsSlash(std::string& s)
{
// first convert all of the slashes
- std::string::size_type pos = 0;
- while ((pos = s.find('/', pos)) != std::string::npos) {
- s[pos] = '\\';
- pos++;
+ for (auto& ch : s) {
+ if (ch == '/') {
+ ch = '\\';
+ }
}
}
+
void cmVisualStudio10TargetGenerator::WriteGroups()
{
- if (csproj == this->ProjectType) {
+ if (this->ProjectType == csproj) {
return;
}
@@ -1253,132 +1570,119 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
this->GeneratorTarget->GetAllConfigSources();
- std::set<cmSourceGroup*> groupsUsed;
- for (std::vector<cmGeneratorTarget::AllConfigSource>::const_iterator si =
- sources.begin();
- si != sources.end(); ++si) {
- std::string const& source = si->Source->GetFullPath();
+ std::set<cmSourceGroup const*> groupsUsed;
+ for (cmGeneratorTarget::AllConfigSource const& si : sources) {
+ std::string const& source = si.Source->GetFullPath();
cmSourceGroup* sourceGroup =
- this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
+ this->Makefile->FindSourceGroup(source, sourceGroups);
+ groupsUsed.insert(sourceGroup);
+ }
+
+ if (cmSourceFile const* srcCMakeLists =
+ this->LocalGenerator->CreateVCProjBuildRule()) {
+ std::string const& source = srcCMakeLists->GetFullPath();
+ cmSourceGroup* sourceGroup =
+ this->Makefile->FindSourceGroup(source, sourceGroups);
groupsUsed.insert(sourceGroup);
}
this->AddMissingSourceGroups(groupsUsed, sourceGroups);
// Write out group file
- std::string path = this->LocalGenerator->GetCurrentBinaryDirectory();
- path += "/";
- path += this->Name;
- path += computeProjectFileExtension(this->GeneratorTarget);
- path += ".filters";
- cmGeneratedFileStream fout(path.c_str());
+ std::string path = cmStrCat(
+ this->LocalGenerator->GetCurrentBinaryDirectory(), '/', this->Name,
+ computeProjectFileExtension(this->GeneratorTarget), ".filters");
+ cmGeneratedFileStream fout(path);
fout.SetCopyIfDifferent(true);
char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
fout.write(magic, 3);
- cmGeneratedFileStream* save = this->BuildFileStream;
- this->BuildFileStream = &fout;
-
- // get the tools version to use
- const std::string toolsVer(this->GlobalGenerator->GetToolsVersion());
- std::string project_defaults = "<?xml version=\"1.0\" encoding=\"" +
- this->GlobalGenerator->Encoding() + "\"?>\n";
- project_defaults.append("<Project ToolsVersion=\"");
- project_defaults.append(toolsVer + "\" ");
- project_defaults.append(
- "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n");
- this->WriteString(project_defaults.c_str(), 0);
-
- for (ToolSourceMap::const_iterator ti = this->Tools.begin();
- ti != this->Tools.end(); ++ti) {
- this->WriteGroupSources(ti->first.c_str(), ti->second, sourceGroups);
- }
-
- // 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) {
- std::string fileName =
- cmSystemTools::LowerCase(cmSystemTools::GetFilenameName(*oi));
- if (fileName == "wmappmanifest.xml") {
- this->WriteString("<XML Include=\"", 2);
- (*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->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->WriteString("<Filter>Resource Files</Filter>\n", 3);
- this->WriteString("</None>\n", 2);
- } else {
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << *oi << "\">\n";
- this->WriteString("<Filter>Resource Files</Filter>\n", 3);
- this->WriteString("</Image>\n", 2);
+
+ fout << "<?xml version=\"1.0\" encoding=\""
+ << this->GlobalGenerator->Encoding() << "\"?>"
+ << "\n";
+ {
+ Elem e0(fout, "Project");
+ e0.Attribute("ToolsVersion", this->GlobalGenerator->GetToolsVersion());
+ e0.Attribute("xmlns",
+ "http://schemas.microsoft.com/developer/msbuild/2003");
+
+ for (auto const& ti : this->Tools) {
+ this->WriteGroupSources(e0, ti.first, ti.second, sourceGroups);
+ }
+
+ // Added files are images and the manifest.
+ if (!this->AddedFiles.empty()) {
+ Elem e1(e0, "ItemGroup");
+ e1.SetHasElements();
+ for (std::string const& oi : this->AddedFiles) {
+ std::string fileName =
+ cmSystemTools::LowerCase(cmSystemTools::GetFilenameName(oi));
+ if (fileName == "wmappmanifest.xml") {
+ Elem e2(e1, "XML");
+ e2.Attribute("Include", oi);
+ e2.Element("Filter", "Resource Files");
+ } else if (cmSystemTools::GetFilenameExtension(fileName) ==
+ ".appxmanifest") {
+ Elem e2(e1, "AppxManifest");
+ e2.Attribute("Include", oi);
+ e2.Element("Filter", "Resource Files");
+ } else if (cmSystemTools::GetFilenameExtension(fileName) == ".pfx") {
+ Elem e2(e1, "None");
+ e2.Attribute("Include", oi);
+ e2.Element("Filter", "Resource Files");
+ } else {
+ Elem e2(e1, "Image");
+ e2.Attribute("Include", oi);
+ e2.Element("Filter", "Resource Files");
+ }
}
}
- this->WriteString("</ItemGroup>\n", 1);
- }
- std::vector<cmSourceFile const*> resxObjs;
- 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();
- this->WriteString("<EmbeddedResource Include=\"", 2);
- this->ConvertToWindowsSlash(obj);
- (*this->BuildFileStream) << cmVS10EscapeXML(obj) << "\">\n";
- this->WriteString("<Filter>Resource Files</Filter>\n", 3);
- this->WriteString("</EmbeddedResource>\n", 2);
- }
- this->WriteString("</ItemGroup>\n", 1);
- }
-
- 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) {
- this->WriteString("<Filter Include=\"", 2);
- (*this->BuildFileStream) << name << "\">\n";
- std::string guidName = "SG_Filter_";
- guidName += name;
- this->WriteString("<UniqueIdentifier>", 3);
- std::string guid = this->GlobalGenerator->GetGUID(guidName.c_str());
- (*this->BuildFileStream) << "{" << guid << "}"
- << "</UniqueIdentifier>\n";
- this->WriteString("</Filter>\n", 2);
- }
- }
-
- if (!resxObjs.empty() || !this->AddedFiles.empty()) {
- this->WriteString("<Filter Include=\"Resource Files\">\n", 2);
- std::string guidName = "SG_Filter_Resource Files";
- this->WriteString("<UniqueIdentifier>", 3);
- std::string guid = this->GlobalGenerator->GetGUID(guidName.c_str());
- (*this->BuildFileStream) << "{" << guid << "}"
- << "</UniqueIdentifier>\n";
- this->WriteString("<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;", 3);
- (*this->BuildFileStream) << "gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;";
- (*this->BuildFileStream) << "mfcribbon-ms</Extensions>\n";
- this->WriteString("</Filter>\n", 2);
- }
-
- this->WriteString("</ItemGroup>\n", 1);
- this->WriteString("</Project>\n", 0);
- // restore stream pointer
- this->BuildFileStream = save;
+ std::vector<cmSourceFile const*> resxObjs;
+ this->GeneratorTarget->GetResxSources(resxObjs, "");
+ if (!resxObjs.empty()) {
+ Elem e1(e0, "ItemGroup");
+ for (cmSourceFile const* oi : resxObjs) {
+ std::string obj = oi->GetFullPath();
+ ConvertToWindowsSlash(obj);
+ Elem e2(e1, "EmbeddedResource");
+ e2.Attribute("Include", obj);
+ e2.Element("Filter", "Resource Files");
+ }
+ }
+ {
+ Elem e1(e0, "ItemGroup");
+ e1.SetHasElements();
+ std::vector<cmSourceGroup const*> groupsVec(groupsUsed.begin(),
+ groupsUsed.end());
+ std::sort(groupsVec.begin(), groupsVec.end(),
+ [](cmSourceGroup const* l, cmSourceGroup const* r) {
+ return l->GetFullName() < r->GetFullName();
+ });
+ for (cmSourceGroup const* sg : groupsVec) {
+ std::string const& name = sg->GetFullName();
+ if (!name.empty()) {
+ std::string guidName = "SG_Filter_" + name;
+ std::string guid = this->GlobalGenerator->GetGUID(guidName);
+ Elem e2(e1, "Filter");
+ e2.Attribute("Include", name);
+ e2.Element("UniqueIdentifier", "{" + guid + "}");
+ }
+ }
+
+ if (!resxObjs.empty() || !this->AddedFiles.empty()) {
+ std::string guidName = "SG_Filter_Resource Files";
+ std::string guid = this->GlobalGenerator->GetGUID(guidName);
+ Elem e2(e1, "Filter");
+ e2.Attribute("Include", "Resource Files");
+ e2.Element("UniqueIdentifier", "{" + guid + "}");
+ e2.Element("Extensions",
+ "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;"
+ "gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms");
+ }
+ }
+ }
+ fout << '\n';
if (fout.Close()) {
this->GlobalGenerator->FileReplacedDuringGenerate(path);
@@ -1387,29 +1691,26 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
// Add to groupsUsed empty source groups that have non-empty children.
void cmVisualStudio10TargetGenerator::AddMissingSourceGroups(
- std::set<cmSourceGroup*>& groupsUsed,
+ std::set<cmSourceGroup const*>& 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));
- if (groupsUsed.find(current_ptr) != groupsUsed.end()) {
+ if (groupsUsed.count(&current) > 0) {
continue; // group has already been added to set
}
// check if it least one of the group's descendants is not empty
// (at least one child must already have been added)
- std::vector<cmSourceGroup>::const_iterator child_it = children.begin();
+ auto child_it = children.begin();
while (child_it != children.end()) {
- cmSourceGroup* child_ptr = const_cast<cmSourceGroup*>(&(*child_it));
- if (groupsUsed.find(child_ptr) != groupsUsed.end()) {
+ if (groupsUsed.count(&(*child_it)) > 0) {
break; // found a child that was already added => add current group too
}
child_it++;
@@ -1419,65 +1720,60 @@ void cmVisualStudio10TargetGenerator::AddMissingSourceGroups(
continue; // no descendants have source files => ignore this group
}
- groupsUsed.insert(current_ptr);
+ groupsUsed.insert(&current);
}
}
void cmVisualStudio10TargetGenerator::WriteGroupSources(
- const char* name, ToolSources const& sources,
+ Elem& e0, std::string const& name, ToolSources const& sources,
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;
+ Elem e1(e0, "ItemGroup");
+ e1.SetHasElements();
+ 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->WriteString("<", 2);
- std::string path = this->ConvertPath(source, s->RelativePath);
- this->ConvertToWindowsSlash(path);
- (*this->BuildFileStream) << name << " Include=\"" << cmVS10EscapeXML(path);
- if (strlen(filter)) {
- (*this->BuildFileStream) << "\">\n";
- this->WriteString("<Filter>", 3);
- (*this->BuildFileStream) << filter << "</Filter>\n";
- this->WriteString("</", 2);
- (*this->BuildFileStream) << name << ">\n";
- } else {
- (*this->BuildFileStream) << "\" />\n";
+ this->Makefile->FindSourceGroup(source, sourceGroups);
+ std::string const& filter = sourceGroup->GetFullName();
+ std::string path = this->ConvertPath(source, s.RelativePath);
+ ConvertToWindowsSlash(path);
+ Elem e2(e1, name.c_str());
+ e2.Attribute("Include", path);
+ if (!filter.empty()) {
+ e2.Element("Filter", filter);
}
}
- this->WriteString("</ItemGroup>\n", 1);
}
-void cmVisualStudio10TargetGenerator::WriteHeaderSource(cmSourceFile const* sf)
+void cmVisualStudio10TargetGenerator::WriteHeaderSource(Elem& e1,
+ cmSourceFile const* sf)
{
std::string const& fileName = sf->GetFullPath();
+ Elem e2(e1, "ClInclude");
+ this->WriteSource(e2, sf);
if (this->IsResxHeader(fileName)) {
- this->WriteSource("ClInclude", sf, ">\n");
- this->WriteString("<FileType>CppForm</FileType>\n", 3);
- this->WriteString("</ClInclude>\n", 2);
+ e2.Element("FileType", "CppForm");
} else if (this->IsXamlHeader(fileName)) {
- this->WriteSource("ClInclude", sf, ">\n");
- this->WriteString("<DependentUpon>", 3);
std::string xamlFileName = fileName.substr(0, fileName.find_last_of("."));
- (*this->BuildFileStream) << xamlFileName << "</DependentUpon>\n";
- this->WriteString("</ClInclude>\n", 2);
- } else {
- this->WriteSource("ClInclude", sf);
+ e2.Element("DependentUpon", xamlFileName);
}
}
-void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
+void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
+ cmSourceFile const* sf)
{
bool toolHasSettings = false;
- std::string tool = "None";
+ const char* tool = "None";
std::string shaderType;
std::string shaderEntryPoint;
std::string shaderModel;
std::string shaderAdditionalFlags;
+ std::string shaderDisableOptimizations;
+ std::string shaderEnableDebug;
+ std::string shaderObjectFileName;
+ std::string outputHeaderFile;
+ std::string variableName;
std::string settingsGenerator;
std::string settingsLastGenOutput;
std::string sourceLink;
@@ -1485,7 +1781,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
std::string copyToOutDir;
std::string includeInVsix;
std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
- if (csproj == this->ProjectType) {
+ if (this->ProjectType == csproj) {
// EVERY extra source file must have a <Link>, otherwise it might not
// be visible in Visual Studio at all. The path relative to current
// source- or binary-dir is used within the link, if the file is
@@ -1498,7 +1794,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
std::string srcDir = this->Makefile->GetCurrentSourceDirectory();
std::string binDir = this->Makefile->GetCurrentBinaryDirectory();
if (fullFileName.find(binDir) != std::string::npos) {
- sourceLink = "";
+ sourceLink.clear();
} else if (fullFileName.find(srcDir) != std::string::npos) {
sourceLink = fullFileName.substr(srcDir.length() + 1);
} else {
@@ -1506,7 +1802,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
sourceLink = cmsys::SystemTools::GetFilenameName(fullFileName);
}
if (!sourceLink.empty()) {
- this->ConvertToWindowsSlash(sourceLink);
+ ConvertToWindowsSlash(sourceLink);
}
}
}
@@ -1527,11 +1823,35 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
shaderModel = sm;
toolHasSettings = true;
}
+ // Figure out which output header file to use if any
+ if (const char* ohf = sf->GetProperty("VS_SHADER_OUTPUT_HEADER_FILE")) {
+ outputHeaderFile = ohf;
+ toolHasSettings = true;
+ }
+ // Figure out which variable name to use if any
+ if (const char* vn = sf->GetProperty("VS_SHADER_VARIABLE_NAME")) {
+ variableName = vn;
+ toolHasSettings = true;
+ }
// Figure out if there's any additional flags to use
if (const char* saf = sf->GetProperty("VS_SHADER_FLAGS")) {
shaderAdditionalFlags = saf;
toolHasSettings = true;
}
+ // Figure out if debug information should be generated
+ if (const char* sed = sf->GetProperty("VS_SHADER_ENABLE_DEBUG")) {
+ shaderEnableDebug = sed;
+ toolHasSettings = true;
+ }
+ // Figure out if optimizations should be disabled
+ if (const char* sdo = sf->GetProperty("VS_SHADER_DISABLE_OPTIMIZATIONS")) {
+ shaderDisableOptimizations = sdo;
+ toolHasSettings = true;
+ }
+ if (const char* sofn = sf->GetProperty("VS_SHADER_OBJECT_FILE_NAME")) {
+ shaderObjectFileName = sofn;
+ toolHasSettings = true;
+ }
} else if (ext == "jpg" || ext == "png") {
tool = "Image";
} else if (ext == "resw") {
@@ -1541,12 +1861,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";
@@ -1555,6 +1871,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
subType = "Designer";
}
if (const char* c = sf->GetProperty("VS_COPY_TO_OUT_DIR")) {
+ tool = "Content";
copyToOutDir = c;
toolHasSettings = true;
}
@@ -1564,6 +1881,10 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
toolHasSettings = true;
}
+ // Collect VS_CSHARP_* property values (if some are set)
+ std::map<std::string, std::string> sourceFileTags;
+ this->GetCSharpSourceProperties(sf, sourceFileTags);
+
if (this->NsightTegra) {
// Nsight Tegra needs specific file types to check up-to-dateness.
std::string name = cmSystemTools::LowerCase(sf->GetLocation().GetName());
@@ -1599,98 +1920,128 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
}
}
+ Elem e2(e1, tool);
+ this->WriteSource(e2, sf);
if (toolHasSettings) {
- this->WriteSource(tool, sf, ">\n");
+ e2.SetHasElements();
if (!deployContent.empty()) {
cmGeneratorExpression ge;
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(deployContent);
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(deployContent);
// Deployment location cannot be set on a configuration basis
if (!deployLocation.empty()) {
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << deployLocation
- << "\\%(FileName)%(Extension)";
- this->WriteString("</Link>\n", 0);
+ e2.Element("Link", deployLocation + "\\%(FileName)%(Extension)");
}
for (size_t i = 0; i != this->Configurations.size(); ++i) {
- if (0 == strcmp(cge->Evaluate(this->LocalGenerator,
- this->Configurations[i]),
- "1")) {
- this->WriteString("<DeploymentContent Condition=\""
- "'$(Configuration)|$(Platform)'=='",
- 3);
- (*this->BuildFileStream) << this->Configurations[i] << "|"
- << this->Platform << "'\">true";
- this->WriteString("</DeploymentContent>\n", 0);
+ if (cge->Evaluate(this->LocalGenerator, this->Configurations[i]) ==
+ "1") {
+ e2.WritePlatformConfigTag("DeploymentContent",
+ "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[i] + "|" +
+ this->Platform + "'",
+ "true");
} else {
- this->WriteString("<ExcludedFromBuild Condition=\""
- "'$(Configuration)|$(Platform)'=='",
- 3);
- (*this->BuildFileStream) << this->Configurations[i] << "|"
- << this->Platform << "'\">true";
- this->WriteString("</ExcludedFromBuild>\n", 0);
+ e2.WritePlatformConfigTag("ExcludedFromBuild",
+ "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[i] + "|" +
+ this->Platform + "'",
+ "true");
}
}
}
if (!shaderType.empty()) {
- this->WriteString("<ShaderType>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderType)
- << "</ShaderType>\n";
+ e2.Element("ShaderType", shaderType);
}
if (!shaderEntryPoint.empty()) {
- this->WriteString("<EntryPointName>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderEntryPoint)
- << "</EntryPointName>\n";
+ e2.Element("EntryPointName", shaderEntryPoint);
}
if (!shaderModel.empty()) {
- this->WriteString("<ShaderModel>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderModel)
- << "</ShaderModel>\n";
+ e2.Element("ShaderModel", shaderModel);
+ }
+ if (!outputHeaderFile.empty()) {
+ for (size_t i = 0; i != this->Configurations.size(); ++i) {
+ e2.WritePlatformConfigTag("HeaderFileOutput",
+ "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[i] + "|" +
+ this->Platform + "'",
+ outputHeaderFile);
+ }
+ }
+ if (!variableName.empty()) {
+ for (size_t i = 0; i != this->Configurations.size(); ++i) {
+ e2.WritePlatformConfigTag("VariableName",
+ "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[i] + "|" +
+ this->Platform + "'",
+ variableName);
+ }
+ }
+ if (!shaderEnableDebug.empty()) {
+ cmGeneratorExpression ge;
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(shaderEnableDebug);
+
+ for (size_t i = 0; i != this->Configurations.size(); ++i) {
+ const std::string& enableDebug =
+ cge->Evaluate(this->LocalGenerator, this->Configurations[i]);
+ if (!enableDebug.empty()) {
+ e2.WritePlatformConfigTag("EnableDebuggingInformation",
+ "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[i] + "|" +
+ this->Platform + "'",
+ cmIsOn(enableDebug) ? "true" : "false");
+ }
+ }
+ }
+ if (!shaderDisableOptimizations.empty()) {
+ cmGeneratorExpression ge;
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(shaderDisableOptimizations);
+
+ for (size_t i = 0; i != this->Configurations.size(); ++i) {
+ const std::string& disableOptimizations =
+ cge->Evaluate(this->LocalGenerator, this->Configurations[i]);
+ if (!disableOptimizations.empty()) {
+ e2.WritePlatformConfigTag(
+ "DisableOptimizations",
+ "'$(Configuration)|$(Platform)'=='" + this->Configurations[i] +
+ "|" + this->Platform + "'",
+ (cmIsOn(disableOptimizations) ? "true" : "false"));
+ }
+ }
+ }
+ if (!shaderObjectFileName.empty()) {
+ e2.Element("ObjectFileOutput", shaderObjectFileName);
}
if (!shaderAdditionalFlags.empty()) {
- this->WriteString("<AdditionalOptions>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderAdditionalFlags)
- << "</AdditionalOptions>\n";
+ e2.Element("AdditionalOptions", shaderAdditionalFlags);
}
if (!settingsGenerator.empty()) {
- this->WriteString("<Generator>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(settingsGenerator)
- << "</Generator>\n";
+ e2.Element("Generator", settingsGenerator);
}
if (!settingsLastGenOutput.empty()) {
- this->WriteString("<LastGenOutput>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(settingsLastGenOutput)
- << "</LastGenOutput>\n";
+ e2.Element("LastGenOutput", settingsLastGenOutput);
}
if (!sourceLink.empty()) {
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(sourceLink) << "</Link>\n";
+ e2.Element("Link", sourceLink);
}
if (!subType.empty()) {
- this->WriteString("<SubType>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(subType) << "</SubType>\n";
+ e2.Element("SubType", subType);
}
if (!copyToOutDir.empty()) {
- this->WriteString("<CopyToOutputDirectory>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(copyToOutDir)
- << "</CopyToOutputDirectory>\n";
+ e2.Element("CopyToOutputDirectory", copyToOutDir);
}
if (!includeInVsix.empty()) {
- this->WriteString("<IncludeInVSIX>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(includeInVsix)
- << "</IncludeInVSIX>\n";
+ e2.Element("IncludeInVSIX", includeInVsix);
}
-
- this->WriteString("</", 2);
- (*this->BuildFileStream) << tool << ">\n";
- } else {
- this->WriteSource(tool, sf);
+ // write source file specific tags
+ this->WriteCSharpSourceProperties(e2, sourceFileTags);
}
}
-void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
- cmSourceFile const* sf,
- const char* end)
+void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2,
+ cmSourceFile const* sf)
{
// Visual Studio tools append relative paths to the current dir, as in:
//
@@ -1704,7 +2055,7 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
std::string sourceFile = this->ConvertPath(sf->GetFullPath(), forceRelative);
if (this->LocalGenerator->GetVersion() ==
cmGlobalVisualStudioGenerator::VS10 &&
- cmSystemTools::FileIsFullPath(sourceFile.c_str())) {
+ cmSystemTools::FileIsFullPath(sourceFile)) {
// Normal path conversion resulted in a full path. VS 10 (but not 11)
// refuses to show the property page in the IDE for a source file with a
// full path (not starting in a '.' or '/' AFAICT). CMake <= 2.8.4 used a
@@ -1716,7 +2067,7 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
std::string sourceRel = this->ConvertPath(sf->GetFullPath(), true);
size_t const maxLen = 250;
if (sf->GetCustomCommand() ||
- ((strlen(this->LocalGenerator->GetCurrentBinaryDirectory()) + 1 +
+ ((this->LocalGenerator->GetCurrentBinaryDirectory().length() + 1 +
sourceRel.length()) <= maxLen)) {
forceRelative = true;
sourceFile = sourceRel;
@@ -1724,22 +2075,29 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
this->GlobalGenerator->PathTooLong(this->GeneratorTarget, sf, sourceRel);
}
}
- this->ConvertToWindowsSlash(sourceFile);
- this->WriteString("<", 2);
- (*this->BuildFileStream) << tool << " Include=\""
- << cmVS10EscapeXML(sourceFile) << "\""
- << (end ? end : " />\n");
+ ConvertToWindowsSlash(sourceFile);
+ e2.Attribute("Include", sourceFile);
ToolSource toolSource = { sf, forceRelative };
- this->Tools[tool].push_back(toolSource);
+ this->Tools[e2.Tag].push_back(toolSource);
}
-void cmVisualStudio10TargetGenerator::WriteAllSources()
+void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
{
if (this->GeneratorTarget->GetType() > cmStateEnums::UTILITY) {
return;
}
- this->WriteString("<ItemGroup>\n", 1);
+
+ const bool haveUnityBuild =
+ this->GeneratorTarget->GetPropertyAsBool("UNITY_BUILD");
+
+ if (haveUnityBuild && this->GlobalGenerator->GetSupportsUnityBuilds()) {
+ Elem e1(e0, "PropertyGroup");
+ e1.Element("EnableUnitySupport", "true");
+ }
+
+ Elem e1(e0, "ItemGroup");
+ e1.SetHasElements();
std::vector<size_t> all_configs;
for (size_t ci = 0; ci < this->Configurations.size(); ++ci) {
@@ -1749,11 +2107,16 @@ 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) {
- std::string tool;
- switch (si->Kind) {
+ cmSourceFile const* srcCMakeLists =
+ this->LocalGenerator->CreateVCProjBuildRule();
+
+ for (cmGeneratorTarget::AllConfigSource const& si : sources) {
+ if (si.Source == srcCMakeLists) {
+ // Skip explicit reference to CMakeLists.txt source.
+ continue;
+ }
+ const char* tool = nullptr;
+ switch (si.Kind) {
case cmGeneratorTarget::SourceKindAppManifest:
tool = "AppxManifest";
break;
@@ -1772,17 +2135,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(e1, si.Source);
break;
case cmGeneratorTarget::SourceKindHeader:
- this->WriteHeaderSource(si->Source);
+ this->WriteHeaderSource(e1, si.Source);
break;
case cmGeneratorTarget::SourceKindIDL:
tool = "Midl";
@@ -1793,8 +2156,9 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
case cmGeneratorTarget::SourceKindModuleDefinition:
tool = "None";
break;
+ case cmGeneratorTarget::SourceKindUnityBatched:
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" &&
@@ -1821,51 +2185,72 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
break;
}
- if (!tool.empty()) {
+ if (tool) {
// 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) {
- // FIXME: refactor generation to avoid tracking XML syntax state.
- this->WriteSource(tool, si->Source, " ");
- bool have_nested = this->OutputSourceSpecificFlags(si->Source);
- if (!exclude_configs.empty()) {
- if (!have_nested) {
- (*this->BuildFileStream) << ">\n";
- }
- this->WriteExcludeFromBuild(exclude_configs);
- have_nested = true;
+ Elem e2(e1, tool);
+ this->WriteSource(e2, si.Source);
+
+ bool useNativeUnityBuild = false;
+ if (haveUnityBuild && this->GlobalGenerator->GetSupportsUnityBuilds()) {
+ // Magic value taken from cmGlobalVisualStudioVersionedGenerator.cxx
+ static const std::string vs15 = "141";
+ std::string toolset =
+ this->GlobalGenerator->GetPlatformToolsetString();
+ cmSystemTools::ReplaceString(toolset, "v", "");
+
+ if (toolset.empty() ||
+ cmSystemTools::VersionCompareGreaterEq(toolset, vs15)) {
+ useNativeUnityBuild = true;
}
- if (have_nested) {
- this->WriteString("</", 2);
- (*this->BuildFileStream) << tool << ">\n";
+ }
+
+ if (haveUnityBuild && strcmp(tool, "ClCompile") == 0 &&
+ si.Source->GetProperty("UNITY_SOURCE_FILE")) {
+ if (useNativeUnityBuild) {
+ e2.Attribute(
+ "IncludeInUnityFile",
+ si.Source->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION")
+ ? "false"
+ : "true");
+ e2.Attribute("CustomUnityFile", "true");
+
+ std::string unityDir = cmSystemTools::GetFilenamePath(
+ si.Source->GetProperty("UNITY_SOURCE_FILE"));
+ e2.Attribute("UnityFilesDirectory", unityDir);
} else {
- (*this->BuildFileStream) << " />\n";
+ // Visual Studio versions prior to 2017 15.8 do not know about unity
+ // builds, thus we exclude the files alredy part of unity sources.
+ if (!si.Source->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION")) {
+ exclude_configs = si.Configs;
+ }
}
- } else if (!exclude_configs.empty()) {
- this->WriteSource(tool, si->Source, ">\n");
- this->WriteExcludeFromBuild(exclude_configs);
- this->WriteString("</", 2);
- (*this->BuildFileStream) << tool << ">\n";
- } else {
- this->WriteSource(tool, si->Source);
+ }
+
+ if (si.Kind == cmGeneratorTarget::SourceKindObjectSource) {
+ this->OutputSourceSpecificFlags(e2, si.Source);
+ }
+ if (si.Source->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) {
+ e2.Element("PrecompiledHeader", "NotUsing");
+ }
+ if (!exclude_configs.empty()) {
+ this->WriteExcludeFromBuild(e2, exclude_configs);
}
}
}
if (this->IsMissingFiles) {
- this->WriteMissingFiles();
+ this->WriteMissingFiles(e1);
}
-
- this->WriteString("</ItemGroup>\n", 1);
}
-bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
- cmSourceFile const* source)
+void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
+ Elem& e2, cmSourceFile const* source)
{
cmSourceFile const& sf = *source;
@@ -1875,17 +2260,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);
@@ -1910,41 +2310,51 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
}
}
bool noWinRT = this->TargetCompileAsWinRT && lang == "C";
- bool hasFlags = false;
// for the first time we need a new line if there is something
// produced here.
- const char* firstString = ">\n";
if (!objectName.empty()) {
- (*this->BuildFileStream) << firstString;
- firstString = "";
- hasFlags = true;
- 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);
+ if (lang == "CUDA") {
+ e2.Element("CompileOut", "$(IntDir)/" + objectName);
+ } else {
+ e2.Element("ObjectFileName", "$(IntDir)/" + objectName);
+ }
+ }
+ for (std::string const& config : this->Configurations) {
+ std::string configUpper = cmSystemTools::UpperCase(config);
std::string configDefines = defines;
- std::string defPropName = "COMPILE_DEFINITIONS_";
- defPropName += configUpper;
- if (const char* ccdefs = sf.GetProperty(defPropName.c_str())) {
+ std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper);
+ if (const char* ccdefs = sf.GetProperty(defPropName)) {
if (!configDefines.empty()) {
configDefines += ";";
}
+ configDependentDefines |=
+ cmGeneratorExpression::Find(ccdefs) != std::string::npos;
configDefines += ccdefs;
}
+
+ // Add precompile headers compile options.
+ std::string customAndPchOptions = options;
+ const std::string pchSource =
+ this->GeneratorTarget->GetPchSource(config, lang);
+ if (!pchSource.empty() && !sf.GetProperty("SKIP_PRECOMPILE_HEADERS")) {
+ std::string pchOptions;
+ if (sf.GetFullPath() == pchSource) {
+ pchOptions =
+ this->GeneratorTarget->GetPchCreateCompileOptions(config, lang);
+ } else {
+ pchOptions =
+ this->GeneratorTarget->GetPchUseCompileOptions(config, lang);
+ }
+ customAndPchOptions += pchOptions;
+ }
+
// if we have flags or defines for this config then
// use them
- if (!flags.empty() || configDependentFlags || !configDefines.empty() ||
- compileAs || noWinRT) {
- (*this->BuildFileStream) << firstString;
- firstString = ""; // only do firstString once
- hasFlags = true;
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- cmIDEFlagTable const* flagtable = CM_NULLPTR;
+ if (!flags.empty() || !options.empty() || !configDefines.empty() ||
+ !includes.empty() || compileAs || noWinRT ||
+ !customAndPchOptions.empty()) {
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ cmIDEFlagTable const* flagtable = nullptr;
const std::string& srclang = source->GetLanguage();
if (srclang == "C" || srclang == "CXX") {
flagtable = gg->GetClFlagTable();
@@ -1959,9 +2369,11 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
} else if (srclang == "CSharp") {
flagtable = gg->GetCSharpFlagTable();
}
- cmVisualStudioGeneratorOptions clOptions(
+ cmGeneratorExpressionInterpreter genexInterpreter(
+ this->LocalGenerator, config, this->GeneratorTarget, lang);
+ cmVS10GeneratorOptions clOptions(
this->LocalGenerator, cmVisualStudioGeneratorOptions::Compiler,
- flagtable, 0, this);
+ flagtable, this);
if (compileAs) {
clOptions.AddFlag("CompileAs", compileAs);
}
@@ -1969,160 +2381,202 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
clOptions.AddFlag("CompileAsWinRT", "false");
}
if (configDependentFlags) {
- cmGeneratorExpression ge;
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(flags);
- std::string evaluatedFlags =
- cge->Evaluate(this->LocalGenerator, *config);
- clOptions.Parse(evaluatedFlags.c_str());
+ clOptions.Parse(genexInterpreter.Evaluate(flags, "COMPILE_FLAGS"));
} else {
- clOptions.Parse(flags.c_str());
+ clOptions.Parse(flags);
}
- if (clOptions.HasFlag("AdditionalIncludeDirectories")) {
- clOptions.AppendFlag("AdditionalIncludeDirectories",
- "%(AdditionalIncludeDirectories)");
+ if (!customAndPchOptions.empty()) {
+ std::string expandedOptions;
+ if (configDependentOptions) {
+ this->LocalGenerator->AppendCompileOptions(
+ expandedOptions,
+ genexInterpreter.Evaluate(customAndPchOptions, "COMPILE_OPTIONS"));
+ } else {
+ this->LocalGenerator->AppendCompileOptions(expandedOptions,
+ customAndPchOptions);
+ }
+ clOptions.Parse(expandedOptions);
}
if (clOptions.HasFlag("DisableSpecificWarnings")) {
clOptions.AppendFlag("DisableSpecificWarnings",
"%(DisableSpecificWarnings)");
}
- clOptions.AddDefines(configDefines.c_str());
- clOptions.SetConfiguration((*config).c_str());
- clOptions.PrependInheritedString("AdditionalOptions");
- clOptions.OutputFlagMap(*this->BuildFileStream, " ");
- clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", lang);
+ if (clOptions.HasFlag("ForcedIncludeFiles")) {
+ clOptions.AppendFlag("ForcedIncludeFiles", "%(ForcedIncludeFiles)");
+ }
+ if (configDependentDefines) {
+ clOptions.AddDefines(
+ genexInterpreter.Evaluate(configDefines, "COMPILE_DEFINITIONS"));
+ } else {
+ clOptions.AddDefines(configDefines);
+ }
+ 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);
+ OptionsHelper oh(clOptions, e2);
+ oh.PrependInheritedString("AdditionalOptions");
+ oh.OutputAdditionalIncludeDirectories(lang);
+ oh.OutputFlagMap();
+ oh.OutputPreprocessorDefinitions(lang);
}
}
if (this->IsXamlSource(source->GetFullPath())) {
- (*this->BuildFileStream) << firstString;
- firstString = ""; // only do firstString once
- hasFlags = true;
- this->WriteString("<DependentUpon>", 3);
const std::string& fileName = source->GetFullPath();
std::string xamlFileName = fileName.substr(0, fileName.find_last_of("."));
- (*this->BuildFileStream) << xamlFileName << "</DependentUpon>\n";
+ e2.Element("DependentUpon", xamlFileName);
}
- if (csproj == this->ProjectType) {
+ if (this->ProjectType == csproj) {
std::string f = source->GetFullPath();
- typedef std::map<std::string, std::string> CsPropMap;
+ using CsPropMap = std::map<std::string, std::string>;
CsPropMap sourceFileTags;
// set <Link> tag if necessary
- if (!this->InSourceBuild) {
- const std::string stripFromPath =
- this->Makefile->GetCurrentSourceDirectory();
- if (f.find(stripFromPath) != std::string::npos) {
- std::string link = f.substr(stripFromPath.length() + 1);
- this->ConvertToWindowsSlash(link);
- sourceFileTags["Link"] = link;
- }
- }
- const cmPropertyMap& props = sf.GetProperties();
- for (cmPropertyMap::const_iterator p = props.begin(); p != props.end();
- ++p) {
- static const std::string propNamePrefix = "VS_CSHARP_";
- if (p->first.find(propNamePrefix.c_str()) == 0) {
- std::string tagName = p->first.substr(propNamePrefix.length());
- if (!tagName.empty()) {
- const std::string val = props.GetPropertyValue(p->first);
- if (!val.empty()) {
- sourceFileTags[tagName] = val;
- } else {
- sourceFileTags.erase(tagName);
- }
- }
- }
+ std::string link;
+ this->GetCSharpSourceLink(source, link);
+ if (!link.empty()) {
+ sourceFileTags["Link"] = link;
}
+ this->GetCSharpSourceProperties(&sf, sourceFileTags);
// write source file specific tags
if (!sourceFileTags.empty()) {
- hasFlags = true;
- (*this->BuildFileStream) << firstString;
- firstString = "";
- for (CsPropMap::const_iterator i = sourceFileTags.begin();
- i != sourceFileTags.end(); ++i) {
- this->WriteString("<", 3);
- (*this->BuildFileStream)
- << i->first << ">" << cmVS10EscapeXML(i->second) << "</" << i->first
- << ">\n";
- }
+ this->WriteCSharpSourceProperties(e2, sourceFileTags);
}
}
-
- return hasFlags;
}
void cmVisualStudio10TargetGenerator::WriteExcludeFromBuild(
- std::vector<size_t> const& exclude_configs)
+ Elem& e2, std::vector<size_t> const& exclude_configs)
{
- for (std::vector<size_t>::const_iterator ci = exclude_configs.begin();
- ci != exclude_configs.end(); ++ci) {
- this->WriteString("", 3);
- (*this->BuildFileStream)
- << "<ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='"
- << cmVS10EscapeXML(this->Configurations[*ci]) << "|"
- << cmVS10EscapeXML(this->Platform) << "'\">true</ExcludedFromBuild>\n";
+ for (size_t ci : exclude_configs) {
+ e2.WritePlatformConfigTag("ExcludedFromBuild",
+ "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[ci] + "|" +
+ this->Platform + "'",
+ "true");
}
}
-void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
+void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
+ Elem& e0)
{
cmStateEnums::TargetType ttype = this->GeneratorTarget->GetType();
if (ttype > cmStateEnums::GLOBAL_TARGET) {
return;
}
- if (csproj == this->ProjectType) {
+ if (this->ProjectType == csproj) {
return;
}
- this->WriteString("<PropertyGroup>\n", 1);
- 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) {
+ Elem e1(e0, "PropertyGroup");
+ e1.Element("_ProjectFileVersion", "10.0.20506.1");
+ for (std::string const& config : this->Configurations) {
+ const std::string cond = this->CalcCondition(config);
+
+ if (ttype <= cmStateEnums::UTILITY) {
+ if (const char* workingDir = this->GeneratorTarget->GetProperty(
+ "VS_DEBUGGER_WORKING_DIRECTORY")) {
+ std::string genWorkingDir = cmGeneratorExpression::Evaluate(
+ workingDir, this->LocalGenerator, config);
+ e1.WritePlatformConfigTag("LocalDebuggerWorkingDirectory", cond,
+ genWorkingDir);
+ }
+
+ if (const char* environment =
+ this->GeneratorTarget->GetProperty("VS_DEBUGGER_ENVIRONMENT")) {
+ std::string genEnvironment = cmGeneratorExpression::Evaluate(
+ environment, this->LocalGenerator, config);
+ e1.WritePlatformConfigTag("LocalDebuggerEnvironment", cond,
+ genEnvironment);
+ }
+
+ if (const char* debuggerCommand =
+ this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) {
+ std::string genDebuggerCommand = cmGeneratorExpression::Evaluate(
+ debuggerCommand, this->LocalGenerator, config);
+ e1.WritePlatformConfigTag("LocalDebuggerCommand", cond,
+ genDebuggerCommand);
+ }
+
+ if (const char* commandArguments = this->GeneratorTarget->GetProperty(
+ "VS_DEBUGGER_COMMAND_ARGUMENTS")) {
+ std::string genCommandArguments = cmGeneratorExpression::Evaluate(
+ commandArguments, this->LocalGenerator, config);
+ e1.WritePlatformConfigTag("LocalDebuggerCommandArguments", cond,
+ genCommandArguments);
+ }
+ }
+
if (ttype >= cmStateEnums::UTILITY) {
- this->WritePlatformConfigTag("IntDir", config->c_str(), 2);
- *this->BuildFileStream
- << "$(Platform)\\$(Configuration)\\$(ProjectName)\\"
- << "</IntDir>\n";
+ e1.WritePlatformConfigTag(
+ "IntDir", cond, "$(Platform)\\$(Configuration)\\$(ProjectName)\\");
} else {
- std::string intermediateDir =
- this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
- intermediateDir += "/";
- intermediateDir += *config;
- intermediateDir += "/";
+ std::string intermediateDir = cmStrCat(
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), '/',
+ config, '/');
std::string outDir;
std::string targetNameFull;
if (ttype == cmStateEnums::OBJECT_LIBRARY) {
outDir = intermediateDir;
- targetNameFull = this->GeneratorTarget->GetName();
- targetNameFull += ".lib";
+ targetNameFull = cmStrCat(this->GeneratorTarget->GetName(), ".lib");
} else {
- outDir = this->GeneratorTarget->GetDirectory(config->c_str()) + "/";
- targetNameFull = this->GeneratorTarget->GetFullName(config->c_str());
+ outDir = this->GeneratorTarget->GetDirectory(config) + "/";
+ targetNameFull = this->GeneratorTarget->GetFullName(config);
}
- this->ConvertToWindowsSlash(intermediateDir);
- this->ConvertToWindowsSlash(outDir);
+ ConvertToWindowsSlash(intermediateDir);
+ ConvertToWindowsSlash(outDir);
- this->WritePlatformConfigTag("OutDir", config->c_str(), 2);
- *this->BuildFileStream << cmVS10EscapeXML(outDir) << "</OutDir>\n";
+ e1.WritePlatformConfigTag("OutDir", cond, outDir);
- this->WritePlatformConfigTag("IntDir", config->c_str(), 2);
- *this->BuildFileStream << cmVS10EscapeXML(intermediateDir)
- << "</IntDir>\n";
+ e1.WritePlatformConfigTag("IntDir", cond, intermediateDir);
- if (const char* workingDir = this->GeneratorTarget->GetProperty(
- "VS_DEBUGGER_WORKING_DIRECTORY")) {
- this->WritePlatformConfigTag("LocalDebuggerWorkingDirectory",
- config->c_str(), 2);
- *this->BuildFileStream << cmVS10EscapeXML(workingDir)
- << "</LocalDebuggerWorkingDirectory>\n";
+ if (const char* sdkExecutableDirectories = this->Makefile->GetDefinition(
+ "CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES")) {
+ e1.WritePlatformConfigTag("ExecutablePath", cond,
+ sdkExecutableDirectories);
+ }
+
+ if (const char* sdkIncludeDirectories = this->Makefile->GetDefinition(
+ "CMAKE_VS_SDK_INCLUDE_DIRECTORIES")) {
+ e1.WritePlatformConfigTag("IncludePath", cond, sdkIncludeDirectories);
+ }
+
+ if (const char* sdkReferenceDirectories = this->Makefile->GetDefinition(
+ "CMAKE_VS_SDK_REFERENCE_DIRECTORIES")) {
+ e1.WritePlatformConfigTag("ReferencePath", cond,
+ sdkReferenceDirectories);
+ }
+
+ if (const char* sdkLibraryDirectories = this->Makefile->GetDefinition(
+ "CMAKE_VS_SDK_LIBRARY_DIRECTORIES")) {
+ e1.WritePlatformConfigTag("LibraryPath", cond, sdkLibraryDirectories);
+ }
+
+ if (const char* sdkLibraryWDirectories = this->Makefile->GetDefinition(
+ "CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES")) {
+ e1.WritePlatformConfigTag("LibraryWPath", cond,
+ sdkLibraryWDirectories);
+ }
+
+ if (const char* sdkSourceDirectories =
+ this->Makefile->GetDefinition("CMAKE_VS_SDK_SOURCE_DIRECTORIES")) {
+ e1.WritePlatformConfigTag("SourcePath", cond, sdkSourceDirectories);
+ }
+
+ if (const char* sdkExcludeDirectories = this->Makefile->GetDefinition(
+ "CMAKE_VS_SDK_EXCLUDE_DIRECTORIES")) {
+ e1.WritePlatformConfigTag("ExcludePath", cond, sdkExcludeDirectories);
}
std::string name =
cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull);
- this->WritePlatformConfigTag("TargetName", config->c_str(), 2);
- *this->BuildFileStream << cmVS10EscapeXML(name) << "</TargetName>\n";
+ e1.WritePlatformConfigTag("TargetName", cond, name);
std::string ext =
cmSystemTools::GetFilenameLastExtension(targetNameFull);
@@ -2131,22 +2585,20 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
// A single "." appears to be treated as an empty extension.
ext = ".";
}
- this->WritePlatformConfigTag("TargetExt", config->c_str(), 2);
- *this->BuildFileStream << cmVS10EscapeXML(ext) << "</TargetExt>\n";
+ e1.WritePlatformConfigTag("TargetExt", cond, ext);
- this->OutputLinkIncremental(*config);
+ this->OutputLinkIncremental(e1, config);
}
}
- this->WriteString("</PropertyGroup>\n", 1);
}
void cmVisualStudio10TargetGenerator::OutputLinkIncremental(
- std::string const& configName)
+ Elem& e1, std::string const& configName)
{
if (!this->MSTools) {
return;
}
- if (csproj == this->ProjectType) {
+ if (this->ProjectType == csproj) {
return;
}
// static libraries and things greater than modules do not need
@@ -2156,17 +2608,18 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental(
return;
}
Options& linkOptions = *(this->LinkOptions[configName]);
+ const std::string cond = this->CalcCondition(configName);
- const char* incremental = linkOptions.GetFlag("LinkIncremental");
- this->WritePlatformConfigTag("LinkIncremental", configName.c_str(), 2);
- *this->BuildFileStream << (incremental ? incremental : "true")
- << "</LinkIncremental>\n";
+ if (this->IPOEnabledConfigurations.count(configName) == 0) {
+ const char* incremental = linkOptions.GetFlag("LinkIncremental");
+ e1.WritePlatformConfigTag("LinkIncremental", cond,
+ (incremental ? incremental : "true"));
+ }
linkOptions.RemoveFlag("LinkIncremental");
const char* manifest = linkOptions.GetFlag("GenerateManifest");
- this->WritePlatformConfigTag("GenerateManifest", configName.c_str(), 2);
- *this->BuildFileStream << (manifest ? manifest : "true")
- << "</GenerateManifest>\n";
+ e1.WritePlatformConfigTag("GenerateManifest", cond,
+ (manifest ? manifest : "true"));
linkOptions.RemoveFlag("GenerateManifest");
// Some link options belong here. Use them now and remove them so that
@@ -2175,19 +2628,28 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental(
for (const char** f = flags; *f; ++f) {
const char* flag = *f;
if (const char* value = linkOptions.GetFlag(flag)) {
- this->WritePlatformConfigTag(flag, configName.c_str(), 2);
- *this->BuildFileStream << value << "</" << flag << ">\n";
+ e1.WritePlatformConfigTag(flag, cond, value);
linkOptions.RemoveFlag(flag);
}
}
}
+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& c : this->Configurations) {
+ if (!this->ComputeClOptions(c)) {
return false;
}
}
@@ -2201,62 +2663,51 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
// copied from cmLocalVisualStudio7Generator.cxx 805
// TODO: Integrate code below with cmLocalVisualStudio7Generator.
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- CM_AUTO_PTR<Options> pOptions;
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ std::unique_ptr<Options> pOptions;
switch (this->ProjectType) {
case vcxproj:
- pOptions = CM_AUTO_PTR<Options>(new Options(
- this->LocalGenerator, Options::Compiler, gg->GetClFlagTable()));
+ pOptions = cm::make_unique<Options>(
+ this->LocalGenerator, Options::Compiler, gg->GetClFlagTable());
break;
case csproj:
- pOptions = CM_AUTO_PTR<Options>(new Options(this->LocalGenerator,
- Options::CSharpCompiler,
- gg->GetCSharpFlagTable()));
+ pOptions =
+ cm::make_unique<Options>(this->LocalGenerator, Options::CSharpCompiler,
+ gg->GetCSharpFlagTable());
break;
}
Options& clOptions = *pOptions;
std::string flags;
const std::string& linkLanguage =
- this->GeneratorTarget->GetLinkerLanguage(configName.c_str());
+ this->GeneratorTarget->GetLinkerLanguage(configName);
if (linkLanguage.empty()) {
cmSystemTools::Error(
- "CMake can not determine linker language for target: ",
- this->Name.c_str());
+ "CMake can not determine linker language for target: " + this->Name);
return false;
}
// Choose a language whose flags to use for ClCompile.
- static const char* clLangs[] = { "CXX", "C", "Fortran", "CSharp" };
+ static const char* clLangs[] = { "CXX", "C", "Fortran" };
std::string langForClCompile;
- if (std::find(cmArrayBegin(clLangs), cmArrayEnd(clLangs), linkLanguage) !=
- cmArrayEnd(clLangs)) {
+ if (this->ProjectType == csproj) {
+ langForClCompile = "CSharp";
+ } else if (cmContains(clLangs, linkLanguage)) {
langForClCompile = linkLanguage;
} else {
std::set<std::string> languages;
this->GeneratorTarget->GetLanguages(languages, configName);
- for (const char* const* l = cmArrayBegin(clLangs);
- l != cmArrayEnd(clLangs); ++l) {
- if (languages.find(*l) != languages.end()) {
- langForClCompile = *l;
+ for (const char* l : clLangs) {
+ if (languages.count(l)) {
+ langForClCompile = l;
break;
}
}
}
+ this->LangForClCompile = langForClCompile;
if (!langForClCompile.empty()) {
- std::string baseFlagVar = "CMAKE_";
- baseFlagVar += langForClCompile;
- baseFlagVar += "_FLAGS";
- flags =
- this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
- baseFlagVar.c_str());
- std::string flagVar =
- baseFlagVar + std::string("_") + cmSystemTools::UpperCase(configName);
- flags += " ";
- flags +=
- this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
- flagVar.c_str());
+ this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
+ langForClCompile, configName);
this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
langForClCompile, configName);
}
@@ -2268,51 +2719,109 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
clOptions.AddFlag("CompileAs", "CompileAsCpp");
}
- // Check IPO related warning/error.
- this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName);
+ // Put the IPO enabled configurations into a set.
+ if (this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName)) {
+ this->IPOEnabledConfigurations.insert(configName);
+ }
+
+ // Precompile Headers
+ std::string pchHeader =
+ this->GeneratorTarget->GetPchHeader(configName, linkLanguage);
+ if (this->MSTools && vcxproj == this->ProjectType && pchHeader.empty()) {
+ clOptions.AddFlag("PrecompiledHeader", "NotUsing");
+ }
// Get preprocessor definitions for this directory.
- std::string defineFlags =
- this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags();
+ std::string defineFlags = this->Makefile->GetDefineFlags();
if (this->MSTools) {
- if (vcxproj == this->ProjectType) {
+ if (this->ProjectType == vcxproj) {
clOptions.FixExceptionHandlingDefault();
- clOptions.AddFlag("PrecompiledHeader", "NotUsing");
- std::string asmLocation = configName + "/";
- clOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str());
+ if (this->GlobalGenerator->GetVersion() >=
+ cmGlobalVisualStudioGenerator::VS15) {
+ // Toolsets that come with VS 2017 may now enable UseFullPaths
+ // by default and there is no negative /FC option that projects
+ // can use to switch it back. Older toolsets disable this by
+ // default anyway so this will not hurt them. If the project
+ // is using an explicit /FC option then parsing flags will
+ // replace this setting with "true" below.
+ clOptions.AddFlag("UseFullPaths", "false");
+ }
+ clOptions.AddFlag("AssemblerListingLocation", "$(IntDir)");
+ }
+ }
+
+ // check for managed C++ assembly compiler flag. This overrides any
+ // /clr* compiler flags which may be defined in the flags variable(s).
+ if (this->ProjectType != csproj) {
+ // Warn if /clr was added manually. This should not be done
+ // anymore, because cmGeneratorTarget may not be aware that the
+ // target uses C++/CLI.
+ if (flags.find("/clr") != std::string::npos ||
+ defineFlags.find("/clr") != std::string::npos) {
+ if (configName == this->Configurations[0]) {
+ std::string message = "For the target \"" +
+ this->GeneratorTarget->GetName() +
+ "\" the /clr compiler flag was added manually. " +
+ "Set usage of C++/CLI by setting COMMON_LANGUAGE_RUNTIME "
+ "target property.";
+ this->Makefile->IssueMessage(MessageType::WARNING, message);
+ }
+ }
+ if (auto* clr =
+ this->GeneratorTarget->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
+ std::string clrString = clr;
+ if (!clrString.empty()) {
+ clrString = ":" + clrString;
+ }
+ flags += " /clr" + clrString;
}
}
- clOptions.Parse(flags.c_str());
- clOptions.Parse(defineFlags.c_str());
+
+ clOptions.Parse(flags);
+ clOptions.Parse(defineFlags);
std::vector<std::string> targetDefines;
switch (this->ProjectType) {
case vcxproj:
- this->GeneratorTarget->GetCompileDefinitions(targetDefines,
- configName.c_str(), "CXX");
+ if (!langForClCompile.empty()) {
+ this->GeneratorTarget->GetCompileDefinitions(targetDefines, configName,
+ langForClCompile);
+ }
break;
case csproj:
- this->GeneratorTarget->GetCompileDefinitions(
- targetDefines, configName.c_str(), "CSharp");
+ this->GeneratorTarget->GetCompileDefinitions(targetDefines, configName,
+ "CSharp");
break;
}
clOptions.AddDefines(targetDefines);
+
+ if (this->ProjectType == csproj) {
+ clOptions.AppendFlag("DefineConstants", 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"));
}
// Add a definition for the configuration name.
- std::string configDefine = "CMAKE_INTDIR=\"";
- configDefine += configName;
- configDefine += "\"";
+ std::string configDefine = cmStrCat("CMAKE_INTDIR=\"", configName, '"');
clOptions.AddDefine(configDefine);
- if (const char* exportMacro = this->GeneratorTarget->GetExportMacro()) {
- clOptions.AddDefine(exportMacro);
+ if (const std::string* exportMacro =
+ this->GeneratorTarget->GetExportMacro()) {
+ clOptions.AddDefine(*exportMacro);
}
if (this->MSTools) {
- // If we have the VS_WINRT_COMPONENT set then force Compile as WinRT.
- if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) {
+ // If we have the VS_WINRT_COMPONENT or CMAKE_VS_WINRT_BY_DEFAULT
+ // set then force Compile as WinRT.
+ if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") ||
+ this->Makefile->IsOn("CMAKE_VS_WINRT_BY_DEFAULT")) {
clOptions.AddFlag("CompileAsWinRT", "true");
// For WinRT components, add the _WINRT_DLL define to produce a lib
if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
@@ -2326,91 +2835,112 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
}
}
if (const char* winRT = clOptions.GetFlag("CompileAsWinRT")) {
- if (cmSystemTools::IsOn(winRT)) {
+ if (cmIsOn(winRT)) {
this->TargetCompileAsWinRT = true;
}
}
}
- if (csproj != this->ProjectType && clOptions.IsManaged()) {
+ if (this->ProjectType != csproj && clOptions.IsManaged()) {
this->Managed = true;
std::string managedType = clOptions.GetFlag("CompileAsManaged");
- if (managedType == "Safe") {
+ if (managedType == "Safe" || managedType == "Pure") {
// force empty calling convention if safe clr is used
clOptions.AddFlag("CallingConvention", "");
}
+ // The default values of these flags are incompatible to
+ // managed assemblies. We have to force valid values if
+ // the target is a managed C++ target.
+ clOptions.AddFlag("ExceptionHandling", "Async");
+ clOptions.AddFlag("BasicRuntimeChecks", "Default");
+ }
+ if (this->ProjectType == csproj) {
+ // /nowin32manifest overrides /win32manifest: parameter
+ if (clOptions.HasFlag("NoWin32Manifest")) {
+ clOptions.RemoveFlag("ApplicationManifest");
+ }
}
- this->ClOptions[configName] = pOptions.release();
+ if (const char* s = clOptions.GetFlag("SpectreMitigation")) {
+ this->SpectreMitigation[configName] = s;
+ clOptions.RemoveFlag("SpectreMitigation");
+ }
+
+ this->ClOptions[configName] = std::move(pOptions);
return true;
}
void cmVisualStudio10TargetGenerator::WriteClOptions(
- std::string const& configName, std::vector<std::string> const& includes)
+ Elem& e1, std::string const& configName)
{
Options& clOptions = *(this->ClOptions[configName]);
if (this->ProjectType == csproj) {
return;
}
- this->WriteString("<ClCompile>\n", 2);
- clOptions.PrependInheritedString("AdditionalOptions");
- clOptions.AppendFlag("AdditionalIncludeDirectories", includes);
- clOptions.AppendFlag("AdditionalIncludeDirectories",
- "%(AdditionalIncludeDirectories)");
- clOptions.OutputFlagMap(*this->BuildFileStream, " ");
- clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "CXX");
+ Elem e2(e1, "ClCompile");
+ OptionsHelper oh(clOptions, e2);
+ oh.PrependInheritedString("AdditionalOptions");
+ oh.OutputAdditionalIncludeDirectories(this->LangForClCompile);
+ oh.OutputFlagMap();
+ oh.OutputPreprocessorDefinitions(this->LangForClCompile);
if (this->NsightTegra) {
if (const char* processMax =
this->GeneratorTarget->GetProperty("ANDROID_PROCESS_MAX")) {
- this->WriteString("<ProcessMax>", 3);
- *this->BuildFileStream << cmVS10EscapeXML(processMax)
- << "</ProcessMax>\n";
+ e2.Element("ProcessMax", processMax);
}
}
if (this->MSTools) {
- cmsys::RegularExpression clangToolset(
- "(v[0-9]+_clang_.*|LLVM-vs[0-9]+.*)");
+ cmsys::RegularExpression clangToolset("v[0-9]+_clang_.*");
const char* toolset = this->GlobalGenerator->GetPlatformToolset();
if (toolset && clangToolset.find(toolset)) {
- this->WriteString("<ObjectFileName>"
- "$(IntDir)%(filename).obj"
- "</ObjectFileName>\n",
- 3);
+ e2.Element("ObjectFileName", "$(IntDir)%(filename).obj");
} else {
- this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3);
+ e2.Element("ObjectFileName", "$(IntDir)");
}
// 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);
+ Elem e3(e2, "DebugInformationFormat");
+ e3.SetHasElements();
}
// Specify the compiler program database file if configured.
- std::string pdb =
- this->GeneratorTarget->GetCompilePDBPath(configName.c_str());
+ std::string pdb = this->GeneratorTarget->GetCompilePDBPath(configName);
if (!pdb.empty()) {
- this->ConvertToWindowsSlash(pdb);
- this->WriteString("<ProgramDataBaseFileName>", 3);
- *this->BuildFileStream << cmVS10EscapeXML(pdb)
- << "</ProgramDataBaseFileName>\n";
+ if (this->GlobalGenerator->IsCudaEnabled()) {
+ // CUDA does not quote paths with spaces correctly when forwarding
+ // this to the host compiler. Use a relative path to avoid spaces.
+ // FIXME: We can likely do this even when CUDA is not involved,
+ // but for now we will make a minimal change.
+ pdb = this->ConvertPath(pdb, true);
+ }
+ ConvertToWindowsSlash(pdb);
+ e2.Element("ProgramDataBaseFileName", pdb);
}
- }
- this->WriteString("</ClCompile>\n", 2);
+ // add AdditionalUsingDirectories
+ if (this->AdditionalUsingDirectories.count(configName) > 0) {
+ std::string dirs;
+ for (auto u : this->AdditionalUsingDirectories[configName]) {
+ if (!dirs.empty()) {
+ dirs.append(";");
+ }
+ dirs.append(u);
+ }
+ e2.Element("AdditionalUsingDirectories", dirs);
+ }
+ }
}
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& c : this->Configurations) {
+ if (!this->ComputeRcOptions(c)) {
return false;
}
}
@@ -2420,47 +2950,42 @@ bool cmVisualStudio10TargetGenerator::ComputeRcOptions()
bool cmVisualStudio10TargetGenerator::ComputeRcOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- CM_AUTO_PTR<Options> pOptions(new Options(
- this->LocalGenerator, Options::ResourceCompiler, gg->GetRcFlagTable()));
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ auto pOptions = cm::make_unique<Options>(
+ this->LocalGenerator, Options::ResourceCompiler, gg->GetRcFlagTable());
Options& rcOptions = *pOptions;
std::string CONFIG = cmSystemTools::UpperCase(configName);
- std::string rcConfigFlagsVar = std::string("CMAKE_RC_FLAGS_") + CONFIG;
- std::string flags =
- std::string(this->Makefile->GetSafeDefinition("CMAKE_RC_FLAGS")) +
- std::string(" ") +
- std::string(this->Makefile->GetSafeDefinition(rcConfigFlagsVar));
+ std::string rcConfigFlagsVar = "CMAKE_RC_FLAGS_" + CONFIG;
+ std::string flags = this->Makefile->GetSafeDefinition("CMAKE_RC_FLAGS") +
+ " " + this->Makefile->GetSafeDefinition(rcConfigFlagsVar);
- rcOptions.Parse(flags.c_str());
+ rcOptions.Parse(flags);
// For historical reasons, add the C preprocessor defines to RC.
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)
+ Elem& e1, std::string const& configName)
{
if (!this->MSTools) {
return;
}
- this->WriteString("<ResourceCompile>\n", 2);
+ Elem e2(e1, "ResourceCompile");
- Options& rcOptions = *(this->RcOptions[configName]);
- rcOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "RC");
- rcOptions.AppendFlag("AdditionalIncludeDirectories", includes);
- rcOptions.AppendFlag("AdditionalIncludeDirectories",
- "%(AdditionalIncludeDirectories)");
+ OptionsHelper rcOptions(*(this->RcOptions[configName]), e2);
+ rcOptions.OutputPreprocessorDefinitions("RC");
+ rcOptions.OutputAdditionalIncludeDirectories("RC");
rcOptions.PrependInheritedString("AdditionalOptions");
- rcOptions.OutputFlagMap(*this->BuildFileStream, " ");
-
- this->WriteString("</ResourceCompile>\n", 2);
+ rcOptions.OutputFlagMap();
}
bool cmVisualStudio10TargetGenerator::ComputeCudaOptions()
@@ -2468,10 +2993,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& c : this->Configurations) {
+ if (!this->ComputeCudaOptions(c)) {
return false;
}
}
@@ -2481,30 +3004,37 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions()
bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- CM_AUTO_PTR<Options> pOptions(new Options(
- this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable()));
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ auto pOptions = cm::make_unique<Options>(
+ this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable());
Options& cudaOptions = *pOptions;
// Get compile flags for CUDA in this directory.
- std::string CONFIG = cmSystemTools::UpperCase(configName);
- std::string configFlagsVar = std::string("CMAKE_CUDA_FLAGS_") + CONFIG;
- std::string flags =
- std::string(this->Makefile->GetSafeDefinition("CMAKE_CUDA_FLAGS")) +
- std::string(" ") +
- std::string(this->Makefile->GetSafeDefinition(configFlagsVar));
+ std::string flags;
+ this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, "CUDA",
+ configName);
this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, "CUDA",
configName);
// Get preprocessor definitions for this directory.
- std::string defineFlags =
- this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags();
+ std::string defineFlags = this->Makefile->GetDefineFlags();
- cudaOptions.Parse(flags.c_str());
- cudaOptions.Parse(defineFlags.c_str());
+ cudaOptions.Parse(flags);
+ cudaOptions.Parse(defineFlags);
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(
@@ -2513,6 +3043,41 @@ 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");
+ }
+
+ // Specify the compiler program database file if configured.
+ std::string pdb = this->GeneratorTarget->GetCompilePDBPath(configName);
+ if (!pdb.empty()) {
+ // CUDA does not make the directory if it is non-standard.
+ std::string const pdbDir = cmSystemTools::GetFilenamePath(pdb);
+ cmSystemTools::MakeDirectory(pdbDir);
+ if (cmSystemTools::VersionCompareGreaterEq(
+ "9.2", this->GlobalGenerator->GetPlatformToolsetCudaString())) {
+ // CUDA does not have a field for this and does not honor the
+ // ProgramDataBaseFileName field in ClCompile. Work around this
+ // limitation by creating the directory and passing the flag ourselves.
+ pdb = this->ConvertPath(pdb, true);
+ ConvertToWindowsSlash(pdb);
+ std::string const clFd = "-Xcompiler=\"-Fd\\\"" + pdb + "\\\"\"";
+ cudaOptions.AppendFlagString("AdditionalOptions", clFd);
+ }
+ }
+
+ // CUDA automatically passes the proper '--machine' flag to nvcc
+ // for the current architecture, but does not reflect this default
+ // in the user-visible IDE settings. Set it explicitly.
+ if (this->Platform == "x64") {
+ cudaOptions.AddFlag("TargetMachinePlatform", "64");
}
// Convert the host compiler options to the toolset's abstractions
@@ -2535,40 +3100,39 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
cudaOptions.FixCudaCodeGeneration();
std::vector<std::string> targetDefines;
- this->GeneratorTarget->GetCompileDefinitions(targetDefines,
- configName.c_str(), "CUDA");
+ this->GeneratorTarget->GetCompileDefinitions(targetDefines, configName,
+ "CUDA");
cudaOptions.AddDefines(targetDefines);
// Add a definition for the configuration name.
- std::string configDefine = "CMAKE_INTDIR=\"";
- configDefine += configName;
- configDefine += "\"";
+ std::string configDefine = cmStrCat("CMAKE_INTDIR=\"", configName, '"');
cudaOptions.AddDefine(configDefine);
- if (const char* exportMacro = this->GeneratorTarget->GetExportMacro()) {
- cudaOptions.AddDefine(exportMacro);
+ if (const std::string* exportMacro =
+ this->GeneratorTarget->GetExportMacro()) {
+ cudaOptions.AddDefine(*exportMacro);
}
- this->CudaOptions[configName] = pOptions.release();
+ // Get includes for this target
+ cudaOptions.AddIncludes(this->GetIncludes(configName, "CUDA"));
+ cudaOptions.AddFlag("UseHostInclude", "false");
+
+ this->CudaOptions[configName] = std::move(pOptions);
return true;
}
void cmVisualStudio10TargetGenerator::WriteCudaOptions(
- std::string const& configName, std::vector<std::string> const& includes)
+ Elem& e1, std::string const& configName)
{
if (!this->MSTools || !this->GlobalGenerator->IsCudaEnabled()) {
return;
}
- this->WriteString("<CudaCompile>\n", 2);
+ Elem e2(e1, "CudaCompile");
- Options& cudaOptions = *(this->CudaOptions[configName]);
- cudaOptions.AppendFlag("Include", includes);
- cudaOptions.AppendFlag("Include", "%(Include)");
- cudaOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "CUDA");
+ OptionsHelper cudaOptions(*(this->CudaOptions[configName]), e2);
+ cudaOptions.OutputAdditionalIncludeDirectories("CUDA");
+ cudaOptions.OutputPreprocessorDefinitions("CUDA");
cudaOptions.PrependInheritedString("AdditionalOptions");
- cudaOptions.OutputFlagMap(*this->BuildFileStream, " ");
-
- this->WriteString("</CudaCompile>\n", 2);
+ cudaOptions.OutputFlagMap();
}
bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions()
@@ -2576,10 +3140,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& c : this->Configurations) {
+ if (!this->ComputeCudaLinkOptions(c)) {
return false;
}
}
@@ -2589,27 +3151,14 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions()
bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- CM_AUTO_PTR<Options> pOptions(new Options(
- this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable()));
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ auto pOptions = cm::make_unique<Options>(
+ this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable());
Options& cudaLinkOptions = *pOptions;
// Determine if we need to do a device link
- bool doDeviceLinking = false;
- switch (this->GeneratorTarget->GetType()) {
- case cmStateEnums::SHARED_LIBRARY:
- case cmStateEnums::MODULE_LIBRARY:
- case cmStateEnums::EXECUTABLE:
- doDeviceLinking = true;
- break;
- case cmStateEnums::STATIC_LIBRARY:
- doDeviceLinking = this->GeneratorTarget->GetPropertyAsBool(
- "CUDA_RESOLVE_DEVICE_SYMBOLS");
- break;
- default:
- break;
- }
+ const bool doDeviceLinking = requireDeviceLinking(
+ *this->GeneratorTarget, *this->LocalGenerator, configName);
cudaLinkOptions.AddFlag("PerformDeviceLink",
doDeviceLinking ? "true" : "false");
@@ -2621,12 +3170,88 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
"-Wno-deprecated-gpu-targets");
}
- this->CudaLinkOptions[configName] = pOptions.release();
+ // For static libraries that have device linking enabled compute
+ // the libraries
+ if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY &&
+ doDeviceLinking) {
+ cmComputeLinkInformation* pcli =
+ this->GeneratorTarget->GetLinkInformation(configName);
+ if (!pcli) {
+ cmSystemTools::Error(
+ "CMake can not compute cmComputeLinkInformation for target: " +
+ this->Name);
+ return false;
+ }
+
+ // Would like to use:
+ // cmLinkLineDeviceComputer computer(this->LocalGenerator,
+ // this->LocalGenerator->GetStateSnapshot().GetDirectory());
+ // std::string computed_libs = computer.ComputeLinkLibraries(cli,
+ // std::string{}); but it outputs in "<libA> <libB>" format instead of
+ // "<libA>;<libB>"
+ // Note:
+ // Any modification of this algorithm should be reflected also in
+ // cmLinkLineDeviceComputer
+ cmComputeLinkInformation& cli = *pcli;
+ std::vector<std::string> libVec;
+ const std::string currentBinDir =
+ this->LocalGenerator->GetCurrentBinaryDirectory();
+ const auto& libs = cli.GetItems();
+ for (cmComputeLinkInformation::Item const& l : libs) {
+
+ if (l.Target) {
+ auto managedType = l.Target->GetManagedType(configName);
+ // Do not allow C# targets to be added to the LIB listing. LIB files
+ // are used for linking C++ dependencies. C# libraries do not have lib
+ // files. Instead, they compile down to C# reference libraries (DLL
+ // files). The
+ // `<ProjectReference>` elements added to the vcxproj are enough for
+ // the IDE to deduce the DLL file required by other C# projects that
+ // need its reference library.
+ if (managedType == cmGeneratorTarget::ManagedType::Managed) {
+ continue;
+ }
+ const auto type = l.Target->GetType();
+
+ bool skip = false;
+ switch (type) {
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::INTERFACE_LIBRARY:
+ skip = true;
+ break;
+ case cmStateEnums::STATIC_LIBRARY:
+ skip = l.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
+ break;
+ default:
+ break;
+ }
+ if (skip) {
+ continue;
+ }
+ }
+
+ if (l.IsPath) {
+ std::string path = this->LocalGenerator->MaybeConvertToRelativePath(
+ currentBinDir, l.Value);
+ ConvertToWindowsSlash(path);
+ if (!cmVS10IsTargetsFile(l.Value)) {
+ libVec.push_back(path);
+ }
+ } else {
+ libVec.push_back(l.Value);
+ }
+ }
+
+ cudaLinkOptions.AddFlag("AdditionalDependencies", libVec);
+ }
+
+ this->CudaLinkOptions[configName] = std::move(pOptions);
return true;
}
void cmVisualStudio10TargetGenerator::WriteCudaLinkOptions(
- std::string const& configName)
+ Elem& e1, std::string const& configName)
{
if (this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) {
return;
@@ -2636,10 +3261,9 @@ void cmVisualStudio10TargetGenerator::WriteCudaLinkOptions(
return;
}
- this->WriteString("<CudaLink>\n", 2);
- Options& cudaLinkOptions = *(this->CudaLinkOptions[configName]);
- cudaLinkOptions.OutputFlagMap(*this->BuildFileStream, " ");
- this->WriteString("</CudaLink>\n", 2);
+ Elem e2(e1, "CudaLink");
+ OptionsHelper cudaLinkOptions(*(this->CudaLinkOptions[configName]), e2);
+ cudaLinkOptions.OutputFlagMap();
}
bool cmVisualStudio10TargetGenerator::ComputeMasmOptions()
@@ -2647,10 +3271,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& c : this->Configurations) {
+ if (!this->ComputeMasmOptions(c)) {
return false;
}
}
@@ -2660,44 +3282,40 @@ bool cmVisualStudio10TargetGenerator::ComputeMasmOptions()
bool cmVisualStudio10TargetGenerator::ComputeMasmOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- CM_AUTO_PTR<Options> pOptions(new Options(
- this->LocalGenerator, Options::MasmCompiler, gg->GetMasmFlagTable()));
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ auto pOptions = cm::make_unique<Options>(
+ this->LocalGenerator, Options::MasmCompiler, gg->GetMasmFlagTable());
Options& masmOptions = *pOptions;
- std::string CONFIG = cmSystemTools::UpperCase(configName);
- std::string configFlagsVar = std::string("CMAKE_ASM_MASM_FLAGS_") + CONFIG;
- std::string flags =
- std::string(this->Makefile->GetSafeDefinition("CMAKE_ASM_MASM_FLAGS")) +
- std::string(" ") +
- std::string(this->Makefile->GetSafeDefinition(configFlagsVar));
-
- masmOptions.Parse(flags.c_str());
- this->MasmOptions[configName] = pOptions.release();
+ std::string flags;
+ this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
+ "ASM_MASM", configName);
+
+ masmOptions.Parse(flags);
+
+ // 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)
+ Elem& e1, std::string const& configName)
{
if (!this->MSTools || !this->GlobalGenerator->IsMasmEnabled()) {
return;
}
- this->WriteString("<MASM>\n", 2);
+ Elem e2(e1, "MASM");
// Preprocessor definitions and includes are shared with clOptions.
- Options& clOptions = *(this->ClOptions[configName]);
- clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "ASM_MASM");
+ OptionsHelper clOptions(*(this->ClOptions[configName]), e2);
+ clOptions.OutputPreprocessorDefinitions("ASM_MASM");
- Options& masmOptions = *(this->MasmOptions[configName]);
- masmOptions.AppendFlag("IncludePaths", includes);
- masmOptions.AppendFlag("IncludePaths", "%(IncludePaths)");
+ OptionsHelper masmOptions(*(this->MasmOptions[configName]), e2);
+ masmOptions.OutputAdditionalIncludeDirectories("ASM_MASM");
masmOptions.PrependInheritedString("AdditionalOptions");
- masmOptions.OutputFlagMap(*this->BuildFileStream, " ");
-
- this->WriteString("</MASM>\n", 2);
+ masmOptions.OutputFlagMap();
}
bool cmVisualStudio10TargetGenerator::ComputeNasmOptions()
@@ -2705,10 +3323,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& c : this->Configurations) {
+ if (!this->ComputeNasmOptions(c)) {
return false;
}
}
@@ -2718,74 +3334,71 @@ bool cmVisualStudio10TargetGenerator::ComputeNasmOptions()
bool cmVisualStudio10TargetGenerator::ComputeNasmOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- CM_AUTO_PTR<Options> pOptions(new Options(
- this->LocalGenerator, Options::NasmCompiler, gg->GetNasmFlagTable()));
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ auto pOptions = cm::make_unique<Options>(
+ this->LocalGenerator, Options::NasmCompiler, gg->GetNasmFlagTable());
Options& nasmOptions = *pOptions;
- std::string CONFIG = cmSystemTools::UpperCase(configName);
- std::string configFlagsVar = std::string("CMAKE_ASM_NASM_FLAGS_") + CONFIG;
- std::string flags =
- std::string(this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_FLAGS")) +
- std::string(" -f") + std::string(this->Makefile->GetSafeDefinition(
- "CMAKE_ASM_NASM_OBJECT_FORMAT")) +
- std::string(" ") +
- std::string(this->Makefile->GetSafeDefinition(configFlagsVar));
- nasmOptions.Parse(flags.c_str());
- this->NasmOptions[configName] = pOptions.release();
+ std::string flags;
+ this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget,
+ "ASM_NASM", configName);
+ flags += " -f";
+ flags += this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_OBJECT_FORMAT");
+ nasmOptions.Parse(flags);
+
+ // 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)
+ Elem& e1, std::string const& configName)
{
if (!this->GlobalGenerator->IsNasmEnabled()) {
return;
}
- this->WriteString("<NASM>\n", 2);
-
- Options& nasmOptions = *(this->NasmOptions[configName]);
- for (size_t i = 0; i < includes.size(); i++) {
- includes[i] += "\\";
- }
+ Elem e2(e1, "NASM");
- nasmOptions.AppendFlag("IncludePaths", includes);
- nasmOptions.AppendFlag("IncludePaths", "%(IncludePaths)");
- nasmOptions.OutputFlagMap(*this->BuildFileStream, " ");
+ std::vector<std::string> includes =
+ this->GetIncludes(configName, "ASM_NASM");
+ OptionsHelper nasmOptions(*(this->NasmOptions[configName]), e2);
+ nasmOptions.OutputAdditionalIncludeDirectories("ASM_NASM");
+ nasmOptions.OutputFlagMap();
nasmOptions.PrependInheritedString("AdditionalOptions");
- nasmOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "ASM_NASM");
+ nasmOptions.OutputPreprocessorDefinitions("ASM_NASM");
// Preprocessor definitions and includes are shared with clOptions.
- Options& clOptions = *(this->ClOptions[configName]);
- clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "ASM_NASM");
-
- this->WriteString("</NASM>\n", 2);
+ OptionsHelper clOptions(*(this->ClOptions[configName]), e2);
+ clOptions.OutputPreprocessorDefinitions("ASM_NASM");
}
void cmVisualStudio10TargetGenerator::WriteLibOptions(
- std::string const& config)
+ Elem& e1, std::string const& config)
{
if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY &&
this->GeneratorTarget->GetType() != cmStateEnums::OBJECT_LIBRARY) {
return;
}
+
+ const std::string& linkLanguage =
+ this->GeneratorTarget->GetLinkClosure(config)->LinkerLanguage;
+
std::string libflags;
this->LocalGenerator->GetStaticLibraryFlags(
- libflags, cmSystemTools::UpperCase(config), this->GeneratorTarget);
+ libflags, cmSystemTools::UpperCase(config), linkLanguage,
+ this->GeneratorTarget);
if (!libflags.empty()) {
- this->WriteString("<Lib>\n", 2);
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- cmVisualStudioGeneratorOptions libOptions(
- this->LocalGenerator, cmVisualStudioGeneratorOptions::Linker,
- gg->GetLibFlagTable(), 0, this);
- libOptions.Parse(libflags.c_str());
- libOptions.PrependInheritedString("AdditionalOptions");
- libOptions.OutputFlagMap(*this->BuildFileStream, " ");
- this->WriteString("</Lib>\n", 2);
+ Elem e2(e1, "Lib");
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ cmVS10GeneratorOptions libOptions(this->LocalGenerator,
+ cmVisualStudioGeneratorOptions::Linker,
+ gg->GetLibFlagTable(), this);
+ libOptions.Parse(libflags);
+ OptionsHelper oh(libOptions, e2);
+ oh.PrependInheritedString("AdditionalOptions");
+ oh.OutputFlagMap();
}
// We cannot generate metadata for static libraries. WindowsPhone
@@ -2793,16 +3406,13 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions(
// Link tool options even for static libraries.
if (this->GlobalGenerator->TargetsWindowsPhone() ||
this->GlobalGenerator->TargetsWindowsStore()) {
- this->WriteString("<Link>\n", 2);
- this->WriteString("<GenerateWindowsMetadata>false"
- "</GenerateWindowsMetadata>\n",
- 3);
- this->WriteString("</Link>\n", 2);
+ Elem e2(e1, "Link");
+ e2.Element("GenerateWindowsMetadata", "false");
}
}
void cmVisualStudio10TargetGenerator::WriteManifestOptions(
- std::string const& config)
+ Elem& e1, std::string const& config)
{
if (this->GeneratorTarget->GetType() != cmStateEnums::EXECUTABLE &&
this->GeneratorTarget->GetType() != cmStateEnums::SHARED_LIBRARY &&
@@ -2812,23 +3422,37 @@ void cmVisualStudio10TargetGenerator::WriteManifestOptions(
std::vector<cmSourceFile const*> manifest_srcs;
this->GeneratorTarget->GetManifests(manifest_srcs, config);
- 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);
- (*this->BuildFileStream) << m << ";";
- }
- (*this->BuildFileStream) << "</AdditionalManifestFiles>\n";
- this->WriteString("</Manifest>\n", 2);
+
+ const char* dpiAware = this->GeneratorTarget->GetProperty("VS_DPI_AWARE");
+
+ if (!manifest_srcs.empty() || dpiAware) {
+ Elem e2(e1, "Manifest");
+ if (!manifest_srcs.empty()) {
+ std::ostringstream oss;
+ for (cmSourceFile const* mi : manifest_srcs) {
+ std::string m = this->ConvertPath(mi->GetFullPath(), false);
+ ConvertToWindowsSlash(m);
+ oss << m << ";";
+ }
+ e2.Element("AdditionalManifestFiles", oss.str());
+ }
+ if (dpiAware) {
+ if (!strcmp(dpiAware, "PerMonitor")) {
+ e2.Element("EnableDpiAwareness", "PerMonitorHighDPIAware");
+ } else if (cmIsOn(dpiAware)) {
+ e2.Element("EnableDpiAwareness", "true");
+ } else if (cmIsOff(dpiAware)) {
+ e2.Element("EnableDpiAwareness", "false");
+ } else {
+ cmSystemTools::Error("Bad parameter for VS_DPI_AWARE: " +
+ std::string(dpiAware));
+ }
+ }
}
}
void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
- std::string const& configName)
+ Elem& e1, std::string const& configName)
{
// Look through the sources for AndroidManifest.xml and use
// its location as the root source directory.
@@ -2836,123 +3460,89 @@ 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;
}
}
}
// Tell MSBuild to launch Ant.
+ Elem e2(e1, "AntBuild");
{
std::string antBuildPath = rootDir;
- this->WriteString("<AntBuild>\n", 2);
- this->WriteString("<AntBuildPath>", 3);
- this->ConvertToWindowsSlash(antBuildPath);
- (*this->BuildFileStream) << cmVS10EscapeXML(antBuildPath)
- << "</AntBuildPath>\n";
+ ConvertToWindowsSlash(antBuildPath);
+ e2.Element("AntBuildPath", antBuildPath);
}
if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_SKIP_ANT_STEP")) {
- this->WriteString("<SkipAntStep>true</SkipAntStep>\n", 3);
+ e2.Element("SkipAntStep", "true");
}
if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_PROGUARD")) {
- this->WriteString("<EnableProGuard>true</EnableProGuard>\n", 3);
+ e2.Element("EnableProGuard", "true");
}
if (const char* proGuardConfigLocation =
this->GeneratorTarget->GetProperty("ANDROID_PROGUARD_CONFIG_PATH")) {
- this->WriteString("<ProGuardConfigLocation>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(proGuardConfigLocation)
- << "</ProGuardConfigLocation>\n";
+ e2.Element("ProGuardConfigLocation", proGuardConfigLocation);
}
if (const char* securePropertiesLocation =
this->GeneratorTarget->GetProperty("ANDROID_SECURE_PROPS_PATH")) {
- this->WriteString("<SecurePropertiesLocation>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(securePropertiesLocation)
- << "</SecurePropertiesLocation>\n";
+ e2.Element("SecurePropertiesLocation", securePropertiesLocation);
}
if (const char* nativeLibDirectoriesExpression =
this->GeneratorTarget->GetProperty("ANDROID_NATIVE_LIB_DIRECTORIES")) {
- cmGeneratorExpression ge;
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge =
- ge.Parse(nativeLibDirectoriesExpression);
- std::string nativeLibDirs =
- cge->Evaluate(this->LocalGenerator, configName);
- this->WriteString("<NativeLibDirectories>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(nativeLibDirs)
- << "</NativeLibDirectories>\n";
+ std::string nativeLibDirs = cmGeneratorExpression::Evaluate(
+ nativeLibDirectoriesExpression, this->LocalGenerator, configName);
+ e2.Element("NativeLibDirectories", nativeLibDirs);
}
if (const char* nativeLibDependenciesExpression =
this->GeneratorTarget->GetProperty(
"ANDROID_NATIVE_LIB_DEPENDENCIES")) {
- cmGeneratorExpression ge;
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge =
- ge.Parse(nativeLibDependenciesExpression);
- std::string nativeLibDeps =
- cge->Evaluate(this->LocalGenerator, configName);
- this->WriteString("<NativeLibDependencies>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(nativeLibDeps)
- << "</NativeLibDependencies>\n";
+ std::string nativeLibDeps = cmGeneratorExpression::Evaluate(
+ nativeLibDependenciesExpression, this->LocalGenerator, configName);
+ e2.Element("NativeLibDependencies", nativeLibDeps);
}
if (const char* javaSourceDir =
this->GeneratorTarget->GetProperty("ANDROID_JAVA_SOURCE_DIR")) {
- this->WriteString("<JavaSourceDir>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(javaSourceDir)
- << "</JavaSourceDir>\n";
+ e2.Element("JavaSourceDir", javaSourceDir);
}
if (const char* jarDirectoriesExpression =
this->GeneratorTarget->GetProperty("ANDROID_JAR_DIRECTORIES")) {
- cmGeneratorExpression ge;
- CM_AUTO_PTR<cmCompiledGeneratorExpression> cge =
- ge.Parse(jarDirectoriesExpression);
- std::string jarDirectories =
- cge->Evaluate(this->LocalGenerator, configName);
- this->WriteString("<JarDirectories>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(jarDirectories)
- << "</JarDirectories>\n";
+ std::string jarDirectories = cmGeneratorExpression::Evaluate(
+ jarDirectoriesExpression, this->LocalGenerator, configName);
+ e2.Element("JarDirectories", jarDirectories);
}
if (const char* jarDeps =
this->GeneratorTarget->GetProperty("ANDROID_JAR_DEPENDENCIES")) {
- this->WriteString("<JarDependencies>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(jarDeps)
- << "</JarDependencies>\n";
+ e2.Element("JarDependencies", jarDeps);
}
if (const char* assetsDirectories =
this->GeneratorTarget->GetProperty("ANDROID_ASSETS_DIRECTORIES")) {
- this->WriteString("<AssetsDirectories>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(assetsDirectories)
- << "</AssetsDirectories>\n";
+ e2.Element("AssetsDirectories", assetsDirectories);
}
{
std::string manifest_xml = rootDir + "/AndroidManifest.xml";
- this->ConvertToWindowsSlash(manifest_xml);
- this->WriteString("<AndroidManifestLocation>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(manifest_xml)
- << "</AndroidManifestLocation>\n";
+ ConvertToWindowsSlash(manifest_xml);
+ e2.Element("AndroidManifestLocation", manifest_xml);
}
if (const char* antAdditionalOptions =
this->GeneratorTarget->GetProperty("ANDROID_ANT_ADDITIONAL_OPTIONS")) {
- this->WriteString("<AdditionalOptions>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(antAdditionalOptions)
- << " %(AdditionalOptions)</AdditionalOptions>\n";
+ e2.Element("AdditionalOptions",
+ std::string(antAdditionalOptions) + " %(AdditionalOptions)");
}
-
- this->WriteString("</AntBuild>\n", 2);
}
bool cmVisualStudio10TargetGenerator::ComputeLinkOptions()
@@ -2960,10 +3550,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& c : this->Configurations) {
+ if (!this->ComputeLinkOptions(c)) {
return false;
}
}
@@ -2974,10 +3562,9 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions()
bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
std::string const& config)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- CM_AUTO_PTR<Options> pOptions(new Options(
- this->LocalGenerator, Options::Linker, gg->GetLinkFlagTable(), 0, this));
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ auto pOptions = cm::make_unique<Options>(
+ this->LocalGenerator, Options::Linker, gg->GetLinkFlagTable(), this);
Options& linkOptions = *pOptions;
cmGeneratorTarget::LinkClosure const* linkClosure =
@@ -2986,8 +3573,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
const std::string& linkLanguage = linkClosure->LinkerLanguage;
if (linkLanguage.empty()) {
cmSystemTools::Error(
- "CMake can not determine linker language for target: ",
- this->Name.c_str());
+ "CMake can not determine linker language for target: " + this->Name);
return false;
}
@@ -3001,100 +3587,88 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
linkType = "EXE";
}
std::string flags;
- std::string linkFlagVarBase = "CMAKE_";
- linkFlagVarBase += linkType;
- linkFlagVarBase += "_LINKER_FLAGS";
+ std::string linkFlagVarBase = cmStrCat("CMAKE_", linkType, "_LINKER_FLAGS");
flags += " ";
- flags += this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
- linkFlagVarBase.c_str());
+ flags += this->Makefile->GetRequiredDefinition(linkFlagVarBase);
std::string linkFlagVar = linkFlagVarBase + "_" + CONFIG;
flags += " ";
- flags += this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
- linkFlagVar.c_str());
+ flags += this->Makefile->GetRequiredDefinition(linkFlagVar);
const char* targetLinkFlags =
this->GeneratorTarget->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
flags += " ";
flags += targetLinkFlags;
}
- std::string flagsProp = "LINK_FLAGS_";
- flagsProp += CONFIG;
+ std::string flagsProp = cmStrCat("LINK_FLAGS_", CONFIG);
if (const char* flagsConfig =
- this->GeneratorTarget->GetProperty(flagsProp.c_str())) {
+ this->GeneratorTarget->GetProperty(flagsProp)) {
flags += " ";
flags += flagsConfig;
}
+ std::vector<std::string> opts;
+ this->GeneratorTarget->GetLinkOptions(opts, config, linkLanguage);
+ // LINK_OPTIONS are escaped.
+ this->LocalGenerator->AppendCompileOptions(flags, opts);
+
cmComputeLinkInformation* pcli =
- this->GeneratorTarget->GetLinkInformation(config.c_str());
+ this->GeneratorTarget->GetLinkInformation(config);
if (!pcli) {
cmSystemTools::Error(
- "CMake can not compute cmComputeLinkInformation for target: ",
- this->Name.c_str());
+ "CMake can not compute cmComputeLinkInformation for target: " +
+ this->Name);
return false;
}
cmComputeLinkInformation& cli = *pcli;
std::vector<std::string> libVec;
std::vector<std::string> vsTargetVec;
- this->AddLibraries(cli, libVec, vsTargetVec);
- if (std::find(linkClosure->Languages.begin(), linkClosure->Languages.end(),
- "CUDA") != linkClosure->Languages.end()) {
+ this->AddLibraries(cli, libVec, vsTargetVec, config);
+ if (cmContains(linkClosure->Languages, "CUDA") &&
+ this->CudaOptions[config] != nullptr) {
switch (this->CudaOptions[config]->GetCudaRuntime()) {
case cmVisualStudioGeneratorOptions::CudaRuntimeStatic:
+ libVec.push_back("cudadevrt.lib");
libVec.push_back("cudart_static.lib");
break;
case cmVisualStudioGeneratorOptions::CudaRuntimeShared:
+ libVec.push_back("cudadevrt.lib");
libVec.push_back("cudart.lib");
break;
case cmVisualStudioGeneratorOptions::CudaRuntimeNone:
break;
}
}
- std::string standardLibsVar = "CMAKE_";
- standardLibsVar += linkLanguage;
- standardLibsVar += "_STANDARD_LIBRARIES";
- std::string const libs =
- this->Makefile->GetSafeDefinition(standardLibsVar.c_str());
+ std::string standardLibsVar =
+ cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LIBRARIES");
+ std::string const& libs = this->Makefile->GetSafeDefinition(standardLibsVar);
cmSystemTools::ParseWindowsCommandLine(libs.c_str(), libVec);
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);
- std::string targetName;
- std::string targetNameSO;
- std::string targetNameFull;
- std::string targetNameImport;
- std::string targetNamePDB;
+ cmGeneratorTarget::Names targetNames;
if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) {
- this->GeneratorTarget->GetExecutableNames(targetName, targetNameFull,
- targetNameImport, targetNamePDB,
- config.c_str());
+ targetNames = this->GeneratorTarget->GetExecutableNames(config);
} else {
- this->GeneratorTarget->GetLibraryNames(targetName, targetNameSO,
- targetNameFull, targetNameImport,
- targetNamePDB, config.c_str());
+ targetNames = this->GeneratorTarget->GetLibraryNames(config);
}
if (this->MSTools) {
- linkOptions.AddFlag("Version", "");
-
if (this->GeneratorTarget->GetPropertyAsBool("WIN32_EXECUTABLE")) {
if (this->GlobalGenerator->TargetsWindowsCE()) {
linkOptions.AddFlag("SubSystem", "WindowsCE");
@@ -3130,16 +3704,15 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
linkOptions.AddFlag("GenerateDebugInformation", "false");
- std::string pdb = this->GeneratorTarget->GetPDBDirectory(config.c_str());
- pdb += "/";
- pdb += targetNamePDB;
- std::string imLib = this->GeneratorTarget->GetDirectory(
- config.c_str(), cmStateEnums::ImportLibraryArtifact);
- imLib += "/";
- imLib += targetNameImport;
+ std::string pdb = cmStrCat(this->GeneratorTarget->GetPDBDirectory(config),
+ '/', targetNames.PDB);
+ std::string imLib =
+ cmStrCat(this->GeneratorTarget->GetDirectory(
+ config, cmStateEnums::ImportLibraryArtifact),
+ '/', targetNames.ImportLibrary);
- 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.
@@ -3160,16 +3733,17 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries", "ole32.lib");
}
} else if (this->NsightTegra) {
- linkOptions.AddFlag("SoName", targetNameSO.c_str());
+ linkOptions.AddFlag("SoName", targetNames.SharedObject);
}
- linkOptions.Parse(flags.c_str());
+ linkOptions.Parse(flags);
+ linkOptions.FixManifestUACFlags();
if (this->MSTools) {
cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
this->GeneratorTarget->GetModuleDefinitionInfo(config);
if (mdi && !mdi->DefFile.empty()) {
- linkOptions.AddFlag("ModuleDefinitionFile", mdi->DefFile.c_str());
+ linkOptions.AddFlag("ModuleDefinitionFile", mdi->DefFile);
}
linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries",
"%(IgnoreSpecificDefaultLibraries)");
@@ -3187,17 +3761,24 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
}
}
- this->LinkOptions[config] = pOptions.release();
+ // Managed code cannot be linked with /DEBUG:FASTLINK
+ if (this->Managed) {
+ if (const char* debug = linkOptions.GetFlag("GenerateDebugInformation")) {
+ if (strcmp(debug, "DebugFastLink") == 0) {
+ linkOptions.AddFlag("GenerateDebugInformation", "Debug");
+ }
+ }
+ }
+
+ 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& c : this->Configurations) {
+ if (!this->ComputeLibOptions(c)) {
return false;
}
}
@@ -3209,24 +3790,24 @@ bool cmVisualStudio10TargetGenerator::ComputeLibOptions(
std::string const& config)
{
cmComputeLinkInformation* pcli =
- this->GeneratorTarget->GetLinkInformation(config.c_str());
+ this->GeneratorTarget->GetLinkInformation(config);
if (!pcli) {
cmSystemTools::Error(
- "CMake can not compute cmComputeLinkInformation for target: ",
- this->Name.c_str());
+ "CMake can not compute cmComputeLinkInformation for target: " +
+ this->Name);
return false;
}
cmComputeLinkInformation& cli = *pcli;
- typedef cmComputeLinkInformation::ItemVector ItemVector;
+ using ItemVector = cmComputeLinkInformation::ItemVector;
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)) {
- std::string path = this->LocalGenerator->ConvertToRelativePath(
- currentBinDir, l->Value.c_str());
- this->ConvertToWindowsSlash(path);
+ for (cmComputeLinkInformation::Item const& l : libs) {
+ if (l.IsPath && cmVS10IsTargetsFile(l.Value)) {
+ std::string path = this->LocalGenerator->MaybeConvertToRelativePath(
+ currentBinDir, l.Value);
+ ConvertToWindowsSlash(path);
this->AddTargetsFileAndConfigPair(path, config);
}
}
@@ -3235,52 +3816,90 @@ bool cmVisualStudio10TargetGenerator::ComputeLibOptions(
}
void cmVisualStudio10TargetGenerator::WriteLinkOptions(
- std::string const& config)
+ Elem& e1, std::string const& config)
{
if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) {
return;
}
- if (csproj == this->ProjectType) {
+ if (this->ProjectType == csproj) {
return;
}
- Options& linkOptions = *(this->LinkOptions[config]);
- this->WriteString("<Link>\n", 2);
- linkOptions.PrependInheritedString("AdditionalOptions");
- linkOptions.OutputFlagMap(*this->BuildFileStream, " ");
+ {
+ Elem e2(e1, "Link");
+ OptionsHelper linkOptions(*(this->LinkOptions[config]), e2);
+ linkOptions.PrependInheritedString("AdditionalOptions");
+ linkOptions.OutputFlagMap();
+ }
- this->WriteString("</Link>\n", 2);
if (!this->GlobalGenerator->NeedLinkLibraryDependencies(
this->GeneratorTarget)) {
- this->WriteString("<ProjectReference>\n", 2);
- this->WriteString(
- "<LinkLibraryDependencies>false</LinkLibraryDependencies>\n", 3);
- this->WriteString("</ProjectReference>\n", 2);
+ Elem e2(e1, "ProjectReference");
+ e2.Element("LinkLibraryDependencies", "false");
}
}
void cmVisualStudio10TargetGenerator::AddLibraries(
- cmComputeLinkInformation& cli, std::vector<std::string>& libVec,
- std::vector<std::string>& vsTargetVec)
+ const cmComputeLinkInformation& cli, std::vector<std::string>& libVec,
+ std::vector<std::string>& vsTargetVec, const std::string& config)
{
- typedef cmComputeLinkInformation::ItemVector ItemVector;
+ using ItemVector = cmComputeLinkInformation::ItemVector;
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) {
- std::string path = this->LocalGenerator->ConvertToRelativePath(
- currentBinDir, l->Value.c_str());
- this->ConvertToWindowsSlash(path);
- if (cmVS10IsTargetsFile(l->Value)) {
+ for (cmComputeLinkInformation::Item const& l : libs) {
+ if (l.Target) {
+ auto managedType = l.Target->GetManagedType(config);
+ if (managedType != cmGeneratorTarget::ManagedType::Native &&
+ this->GeneratorTarget->GetManagedType(config) !=
+ cmGeneratorTarget::ManagedType::Native &&
+ l.Target->IsImported()) {
+ auto location = l.Target->GetFullPath(config);
+ if (!location.empty()) {
+ ConvertToWindowsSlash(location);
+ switch (this->ProjectType) {
+ case csproj:
+ // If the target we want to "link" to is an imported managed
+ // target and this is a C# project, we add a hint reference. This
+ // reference is written to project file in
+ // WriteDotNetReferences().
+ this->DotNetHintReferences[config].push_back(
+ DotNetHintReference(l.Target->GetName(), location));
+ break;
+ case vcxproj:
+ // Add path of assembly to list of using-directories, so the
+ // managed assembly can be used by '#using <assembly.dll>' in
+ // code.
+ this->AdditionalUsingDirectories[config].insert(
+ cmSystemTools::GetFilenamePath(location));
+ break;
+ }
+ }
+ }
+ // Do not allow C# targets to be added to the LIB listing. LIB files are
+ // used for linking C++ dependencies. C# libraries do not have lib files.
+ // Instead, they compile down to C# reference libraries (DLL files). The
+ // `<ProjectReference>` elements added to the vcxproj are enough for the
+ // IDE to deduce the DLL file required by other C# projects that need its
+ // reference library.
+ if (managedType == cmGeneratorTarget::ManagedType::Managed) {
+ continue;
+ }
+ }
+
+ if (l.IsPath) {
+ std::string path = this->LocalGenerator->MaybeConvertToRelativePath(
+ 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);
}
}
}
@@ -3288,13 +3907,10 @@ 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 (!cmContains(i.Configs, config)) {
+ i.Configs.push_back(config);
}
return;
}
@@ -3306,12 +3922,12 @@ void cmVisualStudio10TargetGenerator::AddTargetsFileAndConfigPair(
}
void cmVisualStudio10TargetGenerator::WriteMidlOptions(
- std::string const& /*config*/, std::vector<std::string> const& includes)
+ Elem& e1, std::string const& configName)
{
if (!this->MSTools) {
return;
}
- if (csproj == this->ProjectType) {
+ if (this->ProjectType == csproj) {
return;
}
@@ -3330,74 +3946,64 @@ void cmVisualStudio10TargetGenerator::WriteMidlOptions(
// up (for non-directory form, it ends up looking in project binary dir
// only). Perhaps there's something to be done to make this more automatic
// 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) << ";";
- }
- this->WriteString("%(AdditionalIncludeDirectories)"
- "</AdditionalIncludeDirectories>\n",
- 0);
- this->WriteString("<OutputDirectory>$(ProjectDir)/$(IntDir)"
- "</OutputDirectory>\n",
- 3);
- this->WriteString("<HeaderFileName>%(Filename).h</HeaderFileName>\n", 3);
- this->WriteString("<TypeLibraryName>%(Filename).tlb</TypeLibraryName>\n", 3);
- this->WriteString("<InterfaceIdentifierFileName>"
- "%(Filename)_i.c</InterfaceIdentifierFileName>\n",
- 3);
- this->WriteString("<ProxyFileName>%(Filename)_p.c</ProxyFileName>\n", 3);
- this->WriteString("</Midl>\n", 2);
+ std::vector<std::string> const includes =
+ this->GetIncludes(configName, "MIDL");
+ std::ostringstream oss;
+ for (std::string const& i : includes) {
+ oss << i << ";";
+ }
+ oss << "%(AdditionalIncludeDirectories)";
+
+ Elem e2(e1, "Midl");
+ e2.Element("AdditionalIncludeDirectories", oss.str());
+ e2.Element("OutputDirectory", "$(ProjectDir)/$(IntDir)");
+ e2.Element("HeaderFileName", "%(Filename).h");
+ e2.Element("TypeLibraryName", "%(Filename).tlb");
+ e2.Element("InterfaceIdentifierFileName", "%(Filename)_i.c");
+ e2.Element("ProxyFileName", "%(Filename)_p.c");
}
-void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups()
+void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups(Elem& e0)
{
- 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->c_str());
- for (std::vector<std::string>::iterator ii = includes.begin();
- ii != includes.end(); ++ii) {
- this->ConvertToWindowsSlash(*ii);
- }
- this->WritePlatformConfigTag("ItemDefinitionGroup", i->c_str(), 1);
- *this->BuildFileStream << "\n";
+ if (this->ProjectType == csproj) {
+ return;
+ }
+ for (const std::string& c : this->Configurations) {
+ Elem e1(e0, "ItemDefinitionGroup");
+ e1.Attribute("Condition", this->CalcCondition(c));
+
// output cl compile flags <ClCompile></ClCompile>
if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
- this->WriteClOptions(*i, includes);
+ this->WriteClOptions(e1, c);
// output rc compile flags <ResourceCompile></ResourceCompile>
- this->WriteRCOptions(*i, includes);
- this->WriteCudaOptions(*i, includes);
- this->WriteMasmOptions(*i, includes);
- this->WriteNasmOptions(*i, includes);
+ this->WriteRCOptions(e1, c);
+ this->WriteCudaOptions(e1, c);
+ this->WriteMasmOptions(e1, c);
+ this->WriteNasmOptions(e1, c);
}
// output midl flags <Midl></Midl>
- this->WriteMidlOptions(*i, includes);
+ this->WriteMidlOptions(e1, c);
// write events
- if (csproj != this->ProjectType) {
- this->WriteEvents(*i);
+ if (this->ProjectType != csproj) {
+ this->WriteEvents(e1, c);
}
// output link flags <Link></Link>
- this->WriteLinkOptions(*i);
- this->WriteCudaLinkOptions(*i);
+ this->WriteLinkOptions(e1, c);
+ this->WriteCudaLinkOptions(e1, c);
// output lib flags <Lib></Lib>
- this->WriteLibOptions(*i);
+ this->WriteLibOptions(e1, c);
// output manifest flags <Manifest></Manifest>
- this->WriteManifestOptions(*i);
+ this->WriteManifestOptions(e1, c);
if (this->NsightTegra &&
this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE &&
this->GeneratorTarget->GetPropertyAsBool("ANDROID_GUI")) {
- this->WriteAntBuildOptions(*i);
+ this->WriteAntBuildOptions(e1, c);
}
- this->WriteString("</ItemDefinitionGroup>\n", 1);
}
}
void cmVisualStudio10TargetGenerator::WriteEvents(
- std::string const& configName)
+ Elem& e1, std::string const& configName)
{
bool addedPrelink = false;
cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
@@ -3408,80 +4014,76 @@ void cmVisualStudio10TargetGenerator::WriteEvents(
this->GeneratorTarget->GetPreLinkCommands();
this->GlobalGenerator->AddSymbolExportCommand(this->GeneratorTarget,
commands, configName);
- this->WriteEvent("PreLinkEvent", commands, configName);
+ this->WriteEvent(e1, "PreLinkEvent", commands, configName);
}
if (!addedPrelink) {
- this->WriteEvent("PreLinkEvent",
+ this->WriteEvent(e1, "PreLinkEvent",
this->GeneratorTarget->GetPreLinkCommands(), configName);
}
- this->WriteEvent("PreBuildEvent",
+ this->WriteEvent(e1, "PreBuildEvent",
this->GeneratorTarget->GetPreBuildCommands(), configName);
- this->WriteEvent("PostBuildEvent",
+ this->WriteEvent(e1, "PostBuildEvent",
this->GeneratorTarget->GetPostBuildCommands(), configName);
}
void cmVisualStudio10TargetGenerator::WriteEvent(
- const char* name, std::vector<cmCustomCommand> const& commands,
+ Elem& e1, const char* name, std::vector<cmCustomCommand> const& commands,
std::string const& configName)
{
if (commands.empty()) {
return;
}
- this->WriteString("<", 2);
- (*this->BuildFileStream) << name << ">\n";
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
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);
- comment += pre;
- comment += lg->ConstructComment(ccg);
- script += pre;
- pre = "\n";
- script += cmVS10EscapeXML(lg->ConstructScript(ccg));
+ for (cmCustomCommand const& cc : commands) {
+ cmCustomCommandGenerator ccg(cc, configName, lg);
+ if (!ccg.HasOnlyEmptyCommandLines()) {
+ comment += pre;
+ comment += lg->ConstructComment(ccg);
+ script += pre;
+ pre = "\n";
+ script += lg->ConstructScript(ccg);
+ }
}
comment = cmVS10EscapeComment(comment);
- if (csproj != this->ProjectType) {
- this->WriteString("<Message>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(comment) << "</Message>\n";
- this->WriteString("<Command>", 3);
+ if (this->ProjectType != csproj) {
+ Elem e2(e1, name);
+ e2.Element("Message", comment);
+ e2.Element("Command", script);
} else {
- if (!comment.empty()) {
- (*this->BuildFileStream) << "echo " << cmVS10EscapeXML(comment) << "\n";
+ std::string strippedComment = comment;
+ strippedComment.erase(
+ std::remove(strippedComment.begin(), strippedComment.end(), '\t'),
+ strippedComment.end());
+ std::ostringstream oss;
+ if (!comment.empty() && !strippedComment.empty()) {
+ oss << "echo " << comment << "\n";
}
+ oss << script << "\n";
+ e1.Element(name, oss.str());
}
- (*this->BuildFileStream) << script;
- if (csproj != this->ProjectType) {
- (*this->BuildFileStream) << "</Command>";
- }
- (*this->BuildFileStream) << "\n";
- this->WriteString("</", 2);
- (*this->BuildFileStream) << name << ">\n";
}
-void cmVisualStudio10TargetGenerator::WriteProjectReferences()
+void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0)
{
cmGlobalGenerator::TargetDependSet const& unordered =
this->GlobalGenerator->GetTargetDirectDepends(this->GeneratorTarget);
- typedef cmGlobalVisualStudioGenerator::OrderedTargetDependSet
- OrderedTargetDependSet;
+ using OrderedTargetDependSet =
+ cmGlobalVisualStudioGenerator::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;
+ Elem e1(e0, "ItemGroup");
+ e1.SetHasElements();
+ for (cmGeneratorTarget const* dt : depends) {
if (dt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
// skip fortran targets as they can not be processed by MSBuild
// the only reference will be in the .sln file
- if (static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
- ->TargetIsFortranOnly(dt)) {
+ if (this->GlobalGenerator->TargetIsFortranOnly(dt)) {
continue;
}
- this->WriteString("<ProjectReference Include=\"", 2);
cmLocalGenerator* lg = dt->GetLocalGenerator();
std::string name = dt->GetName();
std::string path;
@@ -3489,32 +4091,25 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
if (p) {
path = p;
} else {
- path = lg->GetCurrentBinaryDirectory();
- path += "/";
- path += dt->GetName();
- path += computeProjectFileExtension(dt);
- }
- this->ConvertToWindowsSlash(path);
- (*this->BuildFileStream) << cmVS10EscapeXML(path) << "\">\n";
- this->WriteString("<Project>", 3);
- (*this->BuildFileStream)
- << "{" << this->GlobalGenerator->GetGUID(name.c_str()) << "}";
- (*this->BuildFileStream) << "</Project>\n";
- this->WriteString("<Name>", 3);
- (*this->BuildFileStream) << name << "</Name>\n";
- if (csproj == this->ProjectType) {
- if (!static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
- ->TargetCanBeReferenced(dt)) {
- this->WriteString(
- "<ReferenceOutputAssembly>false</ReferenceOutputAssembly>\n", 3);
- }
+ path = cmStrCat(lg->GetCurrentBinaryDirectory(), '/', dt->GetName(),
+ computeProjectFileExtension(dt));
+ }
+ ConvertToWindowsSlash(path);
+ Elem e2(e1, "ProjectReference");
+ e2.Attribute("Include", path);
+ e2.Element("Project", "{" + this->GlobalGenerator->GetGUID(name) + "}");
+ e2.Element("Name", name);
+ this->WriteDotNetReferenceCustomTags(e2, name);
+
+ // Don't reference targets that don't produce any output.
+ if (dt->GetManagedType("") == cmGeneratorTarget::ManagedType::Undefined) {
+ e2.Element("ReferenceOutputAssembly", "false");
+ e2.Element("CopyToOutputDirectory", "Never");
}
- this->WriteString("</ProjectReference>\n", 2);
}
- this->WriteString("</ItemGroup>\n", 1);
}
-void cmVisualStudio10TargetGenerator::WritePlatformExtensions()
+void cmVisualStudio10TargetGenerator::WritePlatformExtensions(Elem& e1)
{
// This only applies to Windows 10 apps
if (this->GlobalGenerator->TargetsWindowsStore() &&
@@ -3522,53 +4117,44 @@ void cmVisualStudio10TargetGenerator::WritePlatformExtensions()
const char* desktopExtensionsVersion =
this->GeneratorTarget->GetProperty("VS_DESKTOP_EXTENSIONS_VERSION");
if (desktopExtensionsVersion) {
- this->WriteSinglePlatformExtension("WindowsDesktop",
+ this->WriteSinglePlatformExtension(e1, "WindowsDesktop",
desktopExtensionsVersion);
}
const char* mobileExtensionsVersion =
this->GeneratorTarget->GetProperty("VS_MOBILE_EXTENSIONS_VERSION");
if (mobileExtensionsVersion) {
- this->WriteSinglePlatformExtension("WindowsMobile",
+ this->WriteSinglePlatformExtension(e1, "WindowsMobile",
mobileExtensionsVersion);
}
}
}
void cmVisualStudio10TargetGenerator::WriteSinglePlatformExtension(
- std::string const& extension, std::string const& version)
+ Elem& e1, std::string const& extension, std::string const& version)
{
- this->WriteString("<Import Project=", 2);
- (*this->BuildFileStream)
- << "\"$([Microsoft.Build.Utilities.ToolLocationHelper]"
- << "::GetPlatformExtensionSDKLocation(`" << extension
- << ", Version=" << version
- << "`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), null, "
- << "$(ExtensionSDKDirectoryRoot), null))"
- << "\\DesignTime\\CommonConfiguration\\Neutral\\" << extension
- << ".props\" "
- << "Condition=\"exists('$("
- << "[Microsoft.Build.Utilities.ToolLocationHelper]"
- << "::GetPlatformExtensionSDKLocation(`" << extension
- << ", Version=" << version
- << "`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), null, "
- << "$(ExtensionSDKDirectoryRoot), null))"
- << "\\DesignTime\\CommonConfiguration\\Neutral\\" << extension
- << ".props')\" />\n";
+ const std::string s = "$([Microsoft.Build.Utilities.ToolLocationHelper]"
+ "::GetPlatformExtensionSDKLocation(`" +
+ extension + ", Version=" + version +
+ "`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), null, "
+ "$(ExtensionSDKDirectoryRoot), null))"
+ "\\DesignTime\\CommonConfiguration\\Neutral\\" +
+ extension + ".props";
+
+ Elem e2(e1, "Import");
+ e2.Attribute("Project", s);
+ e2.Attribute("Condition", "exists('" + s + "')");
}
-void cmVisualStudio10TargetGenerator::WriteSDKReferences()
+void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0)
{
std::vector<std::string> sdkReferences;
- bool hasWrittenItemGroup = false;
+ std::unique_ptr<Elem> spe1;
if (const char* vsSDKReferences =
this->GeneratorTarget->GetProperty("VS_SDK_REFERENCES")) {
- cmSystemTools::ExpandListArgument(vsSDKReferences, sdkReferences);
- this->WriteString("<ItemGroup>\n", 1);
- hasWrittenItemGroup = true;
- for (std::vector<std::string>::iterator ri = sdkReferences.begin();
- ri != sdkReferences.end(); ++ri) {
- this->WriteString("<SDKReference Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(*ri) << "\"/>\n";
+ cmExpandList(vsSDKReferences, sdkReferences);
+ spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
+ for (std::string const& ri : sdkReferences) {
+ Elem(*spe1, "SDKReference").Attribute("Include", ri);
}
}
@@ -3584,38 +4170,34 @@ void cmVisualStudio10TargetGenerator::WriteSDKReferences()
if (desktopExtensionsVersion || mobileExtensionsVersion ||
iotExtensionsVersion) {
- if (!hasWrittenItemGroup) {
- this->WriteString("<ItemGroup>\n", 1);
- hasWrittenItemGroup = true;
+ if (!spe1) {
+ spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
}
if (desktopExtensionsVersion) {
- this->WriteSingleSDKReference("WindowsDesktop",
+ this->WriteSingleSDKReference(*spe1, "WindowsDesktop",
desktopExtensionsVersion);
}
if (mobileExtensionsVersion) {
- this->WriteSingleSDKReference("WindowsMobile",
+ this->WriteSingleSDKReference(*spe1, "WindowsMobile",
mobileExtensionsVersion);
}
if (iotExtensionsVersion) {
- this->WriteSingleSDKReference("WindowsIoT", iotExtensionsVersion);
+ this->WriteSingleSDKReference(*spe1, "WindowsIoT",
+ iotExtensionsVersion);
}
}
-
- if (hasWrittenItemGroup) {
- this->WriteString("</ItemGroup>\n", 1);
- }
}
}
void cmVisualStudio10TargetGenerator::WriteSingleSDKReference(
- std::string const& extension, std::string const& version)
+ Elem& e1, std::string const& extension, std::string const& version)
{
- this->WriteString("<SDKReference Include=\"", 2);
- (*this->BuildFileStream) << extension << ", Version=" << version
- << "\" />\n";
+ Elem(e1, "SDKReference")
+ .Attribute("Include", extension + ", Version=" + version);
}
-void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile()
+void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile(
+ Elem& e0)
{
if ((this->GlobalGenerator->TargetsWindowsStore() ||
this->GlobalGenerator->TargetsWindowsPhone()) &&
@@ -3623,11 +4205,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;
}
@@ -3637,16 +4217,13 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile()
// Move the manifest to a project directory to avoid clashes
std::string artifactDir =
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
- this->ConvertToWindowsSlash(artifactDir);
- this->WriteString("<PropertyGroup>\n", 1);
- this->WriteString("<AppxPackageArtifactsDir>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(artifactDir)
- << "\\</AppxPackageArtifactsDir>\n";
- this->WriteString("<ProjectPriFullPath>", 2);
+ ConvertToWindowsSlash(artifactDir);
+ Elem e1(e0, "PropertyGroup");
+ e1.Element("AppxPackageArtifactsDir", artifactDir + "\\");
std::string resourcePriFile =
this->DefaultArtifactDir + "/resources.pri";
- this->ConvertToWindowsSlash(resourcePriFile);
- (*this->BuildFileStream) << resourcePriFile << "</ProjectPriFullPath>\n";
+ ConvertToWindowsSlash(resourcePriFile);
+ e1.Element("ProjectPriFullPath", resourcePriFile);
// If we are missing files and we don't have a certificate and
// aren't targeting WP8.0, add a default certificate
@@ -3656,32 +4233,23 @@ 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);
+ this->AddedDefaultCertificate = true;
}
- this->WriteString("<", 2);
- (*this->BuildFileStream) << "PackageCertificateKeyFile>" << pfxFile
- << "</PackageCertificateKeyFile>\n";
+ e1.Element("PackageCertificateKeyFile", pfxFile);
std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile);
if (!thumb.empty()) {
- this->WriteString("<PackageCertificateThumbprint>", 2);
- (*this->BuildFileStream) << thumb
- << "</PackageCertificateThumbprint>\n";
+ e1.Element("PackageCertificateThumbprint", thumb);
}
- this->WriteString("</PropertyGroup>\n", 1);
} else if (!pfxFile.empty()) {
- this->WriteString("<PropertyGroup>\n", 1);
- this->WriteString("<", 2);
- (*this->BuildFileStream) << "PackageCertificateKeyFile>" << pfxFile
- << "</PackageCertificateKeyFile>\n";
+ Elem e1(e0, "PropertyGroup");
+ e1.Element("PackageCertificateKeyFile", pfxFile);
std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile);
if (!thumb.empty()) {
- this->WriteString("<PackageCertificateThumbprint>", 2);
- (*this->BuildFileStream) << thumb
- << "</PackageCertificateThumbprint>\n";
+ e1.Element("PackageCertificateThumbprint", thumb);
}
- this->WriteString("</PropertyGroup>\n", 1);
}
}
}
@@ -3691,10 +4259,7 @@ bool cmVisualStudio10TargetGenerator::IsResxHeader(
{
std::set<std::string> expectedResxHeaders;
this->GeneratorTarget->GetExpectedResxHeaders(expectedResxHeaders, "");
-
- std::set<std::string>::const_iterator it =
- expectedResxHeaders.find(headerFile);
- return it != expectedResxHeaders.end();
+ return expectedResxHeaders.count(headerFile) > 0;
}
bool cmVisualStudio10TargetGenerator::IsXamlHeader(
@@ -3702,10 +4267,7 @@ bool cmVisualStudio10TargetGenerator::IsXamlHeader(
{
std::set<std::string> expectedXamlHeaders;
this->GeneratorTarget->GetExpectedXamlHeaders(expectedXamlHeaders, "");
-
- std::set<std::string>::const_iterator it =
- expectedXamlHeaders.find(headerFile);
- return it != expectedXamlHeaders.end();
+ return expectedXamlHeaders.count(headerFile) > 0;
}
bool cmVisualStudio10TargetGenerator::IsXamlSource(
@@ -3713,60 +4275,40 @@ bool cmVisualStudio10TargetGenerator::IsXamlSource(
{
std::set<std::string> expectedXamlSources;
this->GeneratorTarget->GetExpectedXamlSources(expectedXamlSources, "");
-
- std::set<std::string>::const_iterator it =
- expectedXamlSources.find(sourceFile);
- return it != expectedXamlSources.end();
+ return expectedXamlSources.count(sourceFile) > 0;
}
-void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings()
+void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings(Elem& e1)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
bool isAppContainer = false;
bool const isWindowsPhone = this->GlobalGenerator->TargetsWindowsPhone();
bool const isWindowsStore = this->GlobalGenerator->TargetsWindowsStore();
- std::string const& v = this->GlobalGenerator->GetSystemVersion();
+ std::string const& rev = this->GlobalGenerator->GetApplicationTypeRevision();
if (isWindowsPhone || isWindowsStore) {
- this->WriteString("<ApplicationType>", 2);
- (*this->BuildFileStream)
- << (isWindowsPhone ? "Windows Phone" : "Windows Store")
- << "</ApplicationType>\n";
- this->WriteString("<DefaultLanguage>en-US"
- "</DefaultLanguage>\n",
- 2);
- if (cmHasLiteralPrefix(v, "10.0")) {
- this->WriteString("<ApplicationTypeRevision>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML("10.0")
- << "</ApplicationTypeRevision>\n";
+ e1.Element("ApplicationType",
+ (isWindowsPhone ? "Windows Phone" : "Windows Store"));
+ e1.Element("DefaultLanguage", "en-US");
+ if (rev == "10.0") {
+ e1.Element("ApplicationTypeRevision", rev);
// Visual Studio 14.0 is necessary for building 10.0 apps
- this->WriteString("<MinimumVisualStudioVersion>14.0"
- "</MinimumVisualStudioVersion>\n",
- 2);
+ e1.Element("MinimumVisualStudioVersion", "14.0");
if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
isAppContainer = true;
}
- } else if (v == "8.1") {
- this->WriteString("<ApplicationTypeRevision>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(v)
- << "</ApplicationTypeRevision>\n";
+ } else if (rev == "8.1") {
+ e1.Element("ApplicationTypeRevision", rev);
// Visual Studio 12.0 is necessary for building 8.1 apps
- this->WriteString("<MinimumVisualStudioVersion>12.0"
- "</MinimumVisualStudioVersion>\n",
- 2);
+ e1.Element("MinimumVisualStudioVersion", "12.0");
if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
isAppContainer = true;
}
- } else if (v == "8.0") {
- this->WriteString("<ApplicationTypeRevision>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(v)
- << "</ApplicationTypeRevision>\n";
+ } else if (rev == "8.0") {
+ e1.Element("ApplicationTypeRevision", rev);
// Visual Studio 11.0 is necessary for building 8.0 apps
- this->WriteString("<MinimumVisualStudioVersion>11.0"
- "</MinimumVisualStudioVersion>\n",
- 2);
+ e1.Element("MinimumVisualStudioVersion", "11.0");
if (isWindowsStore &&
this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
@@ -3774,48 +4316,38 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings()
} else if (isWindowsPhone &&
this->GeneratorTarget->GetType() ==
cmStateEnums::EXECUTABLE) {
- this->WriteString("<XapOutputs>true</XapOutputs>\n", 2);
- this->WriteString("<XapFilename>", 2);
- (*this->BuildFileStream)
- << cmVS10EscapeXML(this->Name.c_str())
- << "_$(Configuration)_$(Platform).xap</XapFilename>\n";
+ e1.Element("XapOutputs", "true");
+ e1.Element("XapFilename",
+ this->Name + "_$(Configuration)_$(Platform).xap");
}
}
}
if (isAppContainer) {
- this->WriteString("<AppContainerApplication>true"
- "</AppContainerApplication>\n",
- 2);
+ e1.Element("AppContainerApplication", "true");
+ } else if (this->Platform == "ARM64") {
+ e1.Element("WindowsSDKDesktopARM64Support", "true");
} else if (this->Platform == "ARM") {
- this->WriteString("<WindowsSDKDesktopARMSupport>true"
- "</WindowsSDKDesktopARMSupport>\n",
- 2);
+ e1.Element("WindowsSDKDesktopARMSupport", "true");
}
std::string const& targetPlatformVersion =
gg->GetWindowsTargetPlatformVersion();
if (!targetPlatformVersion.empty()) {
- this->WriteString("<WindowsTargetPlatformVersion>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformVersion)
- << "</WindowsTargetPlatformVersion>\n";
+ e1.Element("WindowsTargetPlatformVersion", targetPlatformVersion);
}
const char* targetPlatformMinVersion = this->GeneratorTarget->GetProperty(
"VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION");
if (targetPlatformMinVersion) {
- this->WriteString("<WindowsTargetPlatformMinVersion>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformMinVersion)
- << "</WindowsTargetPlatformMinVersion>\n";
- } else if (isWindowsStore && cmHasLiteralPrefix(v, "10.0")) {
+ e1.Element("WindowsTargetPlatformMinVersion", targetPlatformMinVersion);
+ } else if (isWindowsStore && rev == "10.0") {
// If the min version is not set, then use the TargetPlatformVersion
if (!targetPlatformVersion.empty()) {
- this->WriteString("<WindowsTargetPlatformMinVersion>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformVersion)
- << "</WindowsTargetPlatformMinVersion>\n";
+ e1.Element("WindowsTargetPlatformMinVersion", targetPlatformVersion);
}
}
// Added IoT Startup Task support
if (this->GeneratorTarget->GetPropertyAsBool("VS_IOT_STARTUP_TASK")) {
- this->WriteString("<ContainsStartupTask>true</ContainsStartupTask>\n", 2);
+ e1.Element("ContainsStartupTask", "true");
}
}
@@ -3834,12 +4366,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;
}
@@ -3865,27 +4395,27 @@ void cmVisualStudio10TargetGenerator::VerifyNecessaryFiles()
}
}
-void cmVisualStudio10TargetGenerator::WriteMissingFiles()
+void cmVisualStudio10TargetGenerator::WriteMissingFiles(Elem& e1)
{
std::string const& v = this->GlobalGenerator->GetSystemVersion();
if (this->GlobalGenerator->TargetsWindowsPhone()) {
if (v == "8.0") {
- this->WriteMissingFilesWP80();
+ this->WriteMissingFilesWP80(e1);
} else if (v == "8.1") {
- this->WriteMissingFilesWP81();
+ this->WriteMissingFilesWP81(e1);
}
} else if (this->GlobalGenerator->TargetsWindowsStore()) {
if (v == "8.0") {
- this->WriteMissingFilesWS80();
+ this->WriteMissingFilesWS80(e1);
} else if (v == "8.1") {
- this->WriteMissingFilesWS81();
+ this->WriteMissingFilesWS81(e1);
} else if (cmHasLiteralPrefix(v, "10.0")) {
- this->WriteMissingFilesWS10_0();
+ this->WriteMissingFilesWS10_0(e1);
}
}
}
-void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80()
+void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80(Elem& e1)
{
std::string templateFolder =
cmSystemTools::GetCMakeRoot() + "/Templates/Windows";
@@ -3894,16 +4424,15 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80()
// this can cause an overwrite problem if projects aren't organized in
// folders
std::string manifestFile =
- this->LocalGenerator->GetCurrentBinaryDirectory() +
- std::string("/WMAppManifest.xml");
+ this->LocalGenerator->GetCurrentBinaryDirectory() + "/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());
- cmGeneratedFileStream fout(manifestFile.c_str());
+ cmGeneratedFileStream fout(manifestFile);
fout.SetCopyIfDifferent(true);
/* clang-format off */
@@ -3945,50 +4474,48 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80()
/* clang-format on */
std::string sourceFile = this->ConvertPath(manifestFile, false);
- this->ConvertToWindowsSlash(sourceFile);
- this->WriteString("<Xml Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(sourceFile) << "\">\n";
- this->WriteString("<SubType>Designer</SubType>\n", 3);
- this->WriteString("</Xml>\n", 2);
+ ConvertToWindowsSlash(sourceFile);
+ {
+ Elem e2(e1, "Xml");
+ e2.Attribute("Include", sourceFile);
+ e2.Element("SubType", "Designer");
+ }
this->AddedFiles.push_back(sourceFile);
std::string smallLogo = this->DefaultArtifactDir + "/SmallLogo.png";
cmSystemTools::CopyAFile(templateFolder + "/SmallLogo.png", smallLogo,
false);
- this->ConvertToWindowsSlash(smallLogo);
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(smallLogo) << "\" />\n";
+ ConvertToWindowsSlash(smallLogo);
+ Elem(e1, "Image").Attribute("Include", smallLogo);
this->AddedFiles.push_back(smallLogo);
std::string logo = this->DefaultArtifactDir + "/Logo.png";
cmSystemTools::CopyAFile(templateFolder + "/Logo.png", logo, false);
- this->ConvertToWindowsSlash(logo);
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(logo) << "\" />\n";
+ ConvertToWindowsSlash(logo);
+ Elem(e1, "Image").Attribute("Include", logo);
this->AddedFiles.push_back(logo);
std::string applicationIcon =
this->DefaultArtifactDir + "/ApplicationIcon.png";
cmSystemTools::CopyAFile(templateFolder + "/ApplicationIcon.png",
applicationIcon, false);
- this->ConvertToWindowsSlash(applicationIcon);
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(applicationIcon) << "\" />\n";
+ ConvertToWindowsSlash(applicationIcon);
+ Elem(e1, "Image").Attribute("Include", applicationIcon);
this->AddedFiles.push_back(applicationIcon);
}
-void cmVisualStudio10TargetGenerator::WriteMissingFilesWP81()
+void cmVisualStudio10TargetGenerator::WriteMissingFilesWP81(Elem& e1)
{
std::string manifestFile =
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());
- cmGeneratedFileStream fout(manifestFile.c_str());
+ cmGeneratedFileStream fout(manifestFile);
fout.SetCopyIfDifferent(true);
/* clang-format off */
@@ -4037,21 +4564,21 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP81()
"</Package>\n";
/* clang-format on */
- this->WriteCommonMissingFiles(manifestFile);
+ this->WriteCommonMissingFiles(e1, manifestFile);
}
-void cmVisualStudio10TargetGenerator::WriteMissingFilesWS80()
+void cmVisualStudio10TargetGenerator::WriteMissingFilesWS80(Elem& e1)
{
std::string manifestFile =
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());
- cmGeneratedFileStream fout(manifestFile.c_str());
+ cmGeneratedFileStream fout(manifestFile);
fout.SetCopyIfDifferent(true);
/* clang-format off */
@@ -4092,21 +4619,21 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWS80()
"</Package>\n";
/* clang-format on */
- this->WriteCommonMissingFiles(manifestFile);
+ this->WriteCommonMissingFiles(e1, manifestFile);
}
-void cmVisualStudio10TargetGenerator::WriteMissingFilesWS81()
+void cmVisualStudio10TargetGenerator::WriteMissingFilesWS81(Elem& e1)
{
std::string manifestFile =
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());
- cmGeneratedFileStream fout(manifestFile.c_str());
+ cmGeneratedFileStream fout(manifestFile);
fout.SetCopyIfDifferent(true);
/* clang-format off */
@@ -4152,21 +4679,21 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWS81()
"</Package>\n";
/* clang-format on */
- this->WriteCommonMissingFiles(manifestFile);
+ this->WriteCommonMissingFiles(e1, manifestFile);
}
-void cmVisualStudio10TargetGenerator::WriteMissingFilesWS10_0()
+void cmVisualStudio10TargetGenerator::WriteMissingFilesWS10_0(Elem& e1)
{
std::string manifestFile =
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());
- cmGeneratedFileStream fout(manifestFile.c_str());
+ cmGeneratedFileStream fout(manifestFile);
fout.SetCopyIfDifferent(true);
/* clang-format off */
@@ -4213,67 +4740,65 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWS10_0()
"</Package>\n";
/* clang-format on */
- this->WriteCommonMissingFiles(manifestFile);
+ this->WriteCommonMissingFiles(e1, manifestFile);
}
void cmVisualStudio10TargetGenerator::WriteCommonMissingFiles(
- const std::string& manifestFile)
+ Elem& e1, const std::string& manifestFile)
{
std::string templateFolder =
cmSystemTools::GetCMakeRoot() + "/Templates/Windows";
std::string sourceFile = this->ConvertPath(manifestFile, false);
- this->ConvertToWindowsSlash(sourceFile);
- this->WriteString("<AppxManifest Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(sourceFile) << "\">\n";
- this->WriteString("<SubType>Designer</SubType>\n", 3);
- this->WriteString("</AppxManifest>\n", 2);
+ ConvertToWindowsSlash(sourceFile);
+ {
+ Elem e2(e1, "AppxManifest");
+ e2.Attribute("Include", sourceFile);
+ e2.Element("SubType", "Designer");
+ }
this->AddedFiles.push_back(sourceFile);
std::string smallLogo = this->DefaultArtifactDir + "/SmallLogo.png";
cmSystemTools::CopyAFile(templateFolder + "/SmallLogo.png", smallLogo,
false);
- this->ConvertToWindowsSlash(smallLogo);
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(smallLogo) << "\" />\n";
+ ConvertToWindowsSlash(smallLogo);
+ Elem(e1, "Image").Attribute("Include", smallLogo);
this->AddedFiles.push_back(smallLogo);
std::string smallLogo44 = this->DefaultArtifactDir + "/SmallLogo44x44.png";
cmSystemTools::CopyAFile(templateFolder + "/SmallLogo44x44.png", smallLogo44,
false);
- this->ConvertToWindowsSlash(smallLogo44);
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(smallLogo44) << "\" />\n";
+ ConvertToWindowsSlash(smallLogo44);
+ Elem(e1, "Image").Attribute("Include", smallLogo44);
this->AddedFiles.push_back(smallLogo44);
std::string logo = this->DefaultArtifactDir + "/Logo.png";
cmSystemTools::CopyAFile(templateFolder + "/Logo.png", logo, false);
- this->ConvertToWindowsSlash(logo);
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(logo) << "\" />\n";
+ ConvertToWindowsSlash(logo);
+ Elem(e1, "Image").Attribute("Include", logo);
this->AddedFiles.push_back(logo);
std::string storeLogo = this->DefaultArtifactDir + "/StoreLogo.png";
cmSystemTools::CopyAFile(templateFolder + "/StoreLogo.png", storeLogo,
false);
- this->ConvertToWindowsSlash(storeLogo);
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(storeLogo) << "\" />\n";
+ ConvertToWindowsSlash(storeLogo);
+ Elem(e1, "Image").Attribute("Include", storeLogo);
this->AddedFiles.push_back(storeLogo);
std::string splashScreen = this->DefaultArtifactDir + "/SplashScreen.png";
cmSystemTools::CopyAFile(templateFolder + "/SplashScreen.png", splashScreen,
false);
- this->ConvertToWindowsSlash(splashScreen);
- this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(splashScreen) << "\" />\n";
+ ConvertToWindowsSlash(splashScreen);
+ Elem(e1, "Image").Attribute("Include", splashScreen);
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);
- this->WriteString("<None Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(keyFile) << "\" />\n";
+ if (this->AddedDefaultCertificate) {
+ // This file has already been added to the build so don't copy it
+ std::string keyFile =
+ this->DefaultArtifactDir + "/Windows_TemporaryKey.pfx";
+ ConvertToWindowsSlash(keyFile);
+ Elem(e1, "None").Attribute("Include", keyFile);
+ }
}
bool cmVisualStudio10TargetGenerator::ForceOld(const std::string& source) const
@@ -4296,13 +4821,63 @@ bool cmVisualStudio10TargetGenerator::ForceOld(const std::string& source) const
return true;
}
+void cmVisualStudio10TargetGenerator::GetCSharpSourceProperties(
+ cmSourceFile const* sf, std::map<std::string, std::string>& tags)
+{
+ if (this->ProjectType == csproj) {
+ const cmPropertyMap& props = sf->GetProperties();
+ for (const std::string& p : props.GetKeys()) {
+ static const std::string propNamePrefix = "VS_CSHARP_";
+ if (p.find(propNamePrefix) == 0) {
+ std::string tagName = p.substr(propNamePrefix.length());
+ if (!tagName.empty()) {
+ const std::string val = props.GetPropertyValue(p);
+ if (!val.empty()) {
+ tags[tagName] = val;
+ } else {
+ tags.erase(tagName);
+ }
+ }
+ }
+ }
+ }
+}
+
+void cmVisualStudio10TargetGenerator::WriteCSharpSourceProperties(
+ Elem& e2, const std::map<std::string, std::string>& tags)
+{
+ for (const auto& i : tags) {
+ e2.Element(i.first.c_str(), i.second);
+ }
+}
+
+void cmVisualStudio10TargetGenerator::GetCSharpSourceLink(
+ cmSourceFile const* sf, std::string& link)
+{
+ std::string const& sourceFilePath = sf->GetFullPath();
+ std::string const& binaryDir = LocalGenerator->GetCurrentBinaryDirectory();
+
+ if (!cmSystemTools::IsSubDirectory(sourceFilePath, binaryDir)) {
+ const std::string& stripFromPath =
+ this->Makefile->GetCurrentSourceDirectory();
+ if (sourceFilePath.find(stripFromPath) == 0) {
+ if (const char* l = sf->GetProperty("VS_CSHARP_Link")) {
+ link = l;
+ } else {
+ link = sourceFilePath.substr(stripFromPath.length() + 1);
+ }
+ ConvertToWindowsSlash(link);
+ }
+ }
+}
+
std::string cmVisualStudio10TargetGenerator::GetCMakeFilePath(
const char* relativeFilePath) const
{
// Always search in the standard modules location.
- std::string path = cmSystemTools::GetCMakeRoot() + "/";
- path += relativeFilePath;
- this->ConvertToWindowsSlash(path);
+ std::string path =
+ cmStrCat(cmSystemTools::GetCMakeRoot(), '/', relativeFilePath);
+ ConvertToWindowsSlash(path);
return path;
}
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 61066158c..a18a33dd8 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -3,10 +3,11 @@
#ifndef cmVisualStudioTargetGenerator_h
#define cmVisualStudioTargetGenerator_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <map>
+#include <memory>
#include <set>
#include <string>
#include <vector>
@@ -16,11 +17,11 @@ class cmCustomCommand;
class cmGeneratedFileStream;
class cmGeneratorTarget;
class cmGlobalVisualStudio10Generator;
-class cmLocalVisualStudio7Generator;
+class cmLocalVisualStudio10Generator;
class cmMakefile;
class cmSourceFile;
class cmSourceGroup;
-class cmVisualStudioGeneratorOptions;
+class cmVS10GeneratorOptions;
class cmVisualStudio10TargetGenerator
{
@@ -28,11 +29,13 @@ public:
cmVisualStudio10TargetGenerator(cmGeneratorTarget* target,
cmGlobalVisualStudio10Generator* gg);
~cmVisualStudio10TargetGenerator();
+
+ cmVisualStudio10TargetGenerator(cmVisualStudio10TargetGenerator const&) =
+ delete;
+ cmVisualStudio10TargetGenerator& operator=(
+ cmVisualStudio10TargetGenerator const&) = delete;
+
void Generate();
- // used by cmVisualStudioGeneratorOptions
- void WritePlatformConfigTag(const char* tag, const std::string& config,
- int indentLevel, const char* attribute = 0,
- const char* end = 0, std::ostream* strm = 0);
private:
struct ToolSource
@@ -50,102 +53,124 @@ private:
std::vector<std::string> Configs;
};
+ struct Elem;
+ struct OptionsHelper;
+
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();
- void WriteMSToolConfigurationValues(std::string const& config);
- void WriteMSToolConfigurationValuesManaged(std::string const& config);
- void WriteHeaderSource(cmSourceFile const* sf);
- void WriteExtraSource(cmSourceFile const* sf);
- void WriteNsightTegraConfigurationValues(std::string const& config);
- void WriteSource(std::string const& tool, cmSourceFile const* sf,
- const char* end = 0);
- void WriteExcludeFromBuild(std::vector<size_t> const& exclude_configs);
- void WriteAllSources();
- void WriteDotNetReferences();
- void WriteDotNetReference(std::string const& ref, std::string const& hint);
- void WriteEmbeddedResourceGroup();
- void WriteWinRTReferences();
- void WriteWinRTPackageCertificateKeyFile();
- void WriteXamlFilesGroup();
- void WritePathAndIncrementalLinkOptions();
- void WriteItemDefinitionGroups();
+ std::string CalcCondition(const std::string& config) const;
+ void WriteProjectConfigurations(Elem& e0);
+ void WriteProjectConfigurationValues(Elem& e0);
+ void WriteMSToolConfigurationValues(Elem& e1, std::string const& config);
+ void WriteCEDebugProjectConfigurationValues(Elem& e0);
+ void WriteMSToolConfigurationValuesManaged(Elem& e1,
+ std::string const& config);
+ void WriteHeaderSource(Elem& e1, cmSourceFile const* sf);
+ void WriteExtraSource(Elem& e1, cmSourceFile const* sf);
+ void WriteNsightTegraConfigurationValues(Elem& e1,
+ std::string const& config);
+ void WriteSource(Elem& e2, cmSourceFile const* sf);
+ void WriteExcludeFromBuild(Elem& e2,
+ std::vector<size_t> const& exclude_configs);
+ void WriteAllSources(Elem& e0);
+ void WritePackageReferences(Elem& e0);
+ void WritePackageReference(Elem& e1, std::string const& ref,
+ std::string const& version);
+ void WriteDotNetReferences(Elem& e0);
+ void WriteDotNetReference(Elem& e1, std::string const& ref,
+ std::string const& hint,
+ std::string const& config);
+ void WriteImports(Elem& e0);
+ void WriteDotNetReferenceCustomTags(Elem& e2, std::string const& ref);
+ void WriteEmbeddedResourceGroup(Elem& e0);
+ void WriteWinRTReferences(Elem& e0);
+ void WriteWinRTPackageCertificateKeyFile(Elem& e0);
+ void WriteXamlFilesGroup(Elem& e0);
+ void WritePathAndIncrementalLinkOptions(Elem& e0);
+ void WriteItemDefinitionGroups(Elem& e0);
void VerifyNecessaryFiles();
- void WriteMissingFiles();
- void WriteMissingFilesWP80();
- void WriteMissingFilesWP81();
- void WriteMissingFilesWS80();
- void WriteMissingFilesWS81();
- void WriteMissingFilesWS10_0();
- void WritePlatformExtensions();
- void WriteSinglePlatformExtension(std::string const& extension,
+ void WriteMissingFiles(Elem& e1);
+ void WriteMissingFilesWP80(Elem& e1);
+ void WriteMissingFilesWP81(Elem& e1);
+ void WriteMissingFilesWS80(Elem& e1);
+ void WriteMissingFilesWS81(Elem& e1);
+ void WriteMissingFilesWS10_0(Elem& e1);
+ void WritePlatformExtensions(Elem& e1);
+ void WriteSinglePlatformExtension(Elem& e1, std::string const& extension,
std::string const& version);
- void WriteSDKReferences();
- void WriteSingleSDKReference(std::string const& extension,
+ void WriteSDKReferences(Elem& e0);
+ void WriteSingleSDKReference(Elem& e1, std::string const& extension,
std::string const& version);
- void WriteCommonMissingFiles(const std::string& manifestFile);
- void WriteTargetSpecificReferences();
- void WriteTargetsFileReferences();
+ void WriteCommonMissingFiles(Elem& e1, const std::string& manifestFile);
+ void WriteTargetSpecificReferences(Elem& e0);
+ void WriteTargetsFileReferences(Elem& e1);
+
+ 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(Elem& e1, 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(Elem& e1, 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(Elem& e1, std::string const& config);
bool ComputeCudaLinkOptions();
bool ComputeCudaLinkOptions(std::string const& config);
- void WriteCudaLinkOptions(std::string const& config);
+ void WriteCudaLinkOptions(Elem& e1, std::string const& config);
bool ComputeMasmOptions();
bool ComputeMasmOptions(std::string const& config);
- void WriteMasmOptions(std::string const& config,
- std::vector<std::string> const& includes);
+ void WriteMasmOptions(Elem& e1, 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(Elem& e1, 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 WriteAntBuildOptions(std::string const& config);
- void OutputLinkIncremental(std::string const& configName);
- void WriteCustomRule(cmSourceFile const* source,
+ void WriteLinkOptions(Elem& e1, std::string const& config);
+ void WriteMidlOptions(Elem& e1, std::string const& config);
+ void WriteAntBuildOptions(Elem& e1, std::string const& config);
+ void OutputLinkIncremental(Elem& e1, std::string const& configName);
+ void WriteCustomRule(Elem& e0, cmSourceFile const* source,
cmCustomCommand const& command);
- void WriteCustomCommands();
- void WriteCustomCommand(cmSourceFile const* sf);
+ void WriteCustomRuleCpp(Elem& e2, std::string const& config,
+ std::string const& script,
+ std::string const& additional_inputs,
+ std::string const& outputs,
+ std::string const& comment, bool symbolic);
+ void WriteCustomRuleCSharp(Elem& e0, std::string const& config,
+ std::string const& commandName,
+ std::string const& script,
+ std::string const& inputs,
+ std::string const& outputs,
+ std::string const& comment);
+ void WriteCustomCommands(Elem& e0);
+ void WriteCustomCommand(Elem& e0, cmSourceFile const* sf);
void WriteGroups();
- void WriteProjectReferences();
- void WriteApplicationTypeSettings();
- bool OutputSourceSpecificFlags(cmSourceFile const* source);
- void AddLibraries(cmComputeLinkInformation& cli,
+ void WriteProjectReferences(Elem& e0);
+ void WriteApplicationTypeSettings(Elem& e1);
+ void OutputSourceSpecificFlags(Elem& e2, cmSourceFile const* source);
+ void AddLibraries(const cmComputeLinkInformation& cli,
std::vector<std::string>& libVec,
- std::vector<std::string>& vsTargetVec);
+ std::vector<std::string>& vsTargetVec,
+ const std::string& config);
void AddTargetsFileAndConfigPair(std::string const& targetsFile,
std::string const& config);
- void WriteLibOptions(std::string const& config);
- void WriteManifestOptions(std::string const& config);
- void WriteEvents(std::string const& configName);
- void WriteEvent(const char* name,
+ void WriteLibOptions(Elem& e1, std::string const& config);
+ void WriteManifestOptions(Elem& e1, std::string const& config);
+ void WriteEvents(Elem& e1, std::string const& configName);
+ void WriteEvent(Elem& e1, const char* name,
std::vector<cmCustomCommand> const& commands,
std::string const& configName);
- void WriteGroupSources(const char* name, ToolSources const& sources,
+ void WriteGroupSources(Elem& e0, std::string const& name,
+ ToolSources const& sources,
std::vector<cmSourceGroup>&);
- void AddMissingSourceGroups(std::set<cmSourceGroup*>& groupsUsed,
+ void AddMissingSourceGroups(std::set<cmSourceGroup const*>& groupsUsed,
const std::vector<cmSourceGroup>& allGroups);
bool IsResxHeader(const std::string& headerFile);
bool IsXamlHeader(const std::string& headerFile);
@@ -153,9 +178,16 @@ private:
bool ForceOld(const std::string& source) const;
+ void GetCSharpSourceProperties(cmSourceFile const* sf,
+ std::map<std::string, std::string>& tags);
+ void WriteCSharpSourceProperties(
+ Elem& e2, const std::map<std::string, std::string>& tags);
+ void GetCSharpSourceLink(cmSourceFile const* sf, std::string& link);
+
private:
- typedef cmVisualStudioGeneratorOptions Options;
- typedef std::map<std::string, Options*> OptionsMap;
+ friend class cmVS10GeneratorOptions;
+ using Options = cmVS10GeneratorOptions;
+ using OptionsMap = std::map<std::string, std::unique_ptr<Options>>;
OptionsMap ClOptions;
OptionsMap RcOptions;
OptionsMap CudaOptions;
@@ -163,8 +195,7 @@ private:
OptionsMap MasmOptions;
OptionsMap NasmOptions;
OptionsMap LinkOptions;
- std::string PathToProjectFile;
- std::string ProjectFileExtension;
+ std::string LangForClCompile;
enum VsProjectType
{
vcxproj,
@@ -173,25 +204,36 @@ private:
bool InSourceBuild;
std::vector<std::string> Configurations;
std::vector<TargetsFileAndConfigs> TargetsFileAndConfigsVec;
- cmGeneratorTarget* GeneratorTarget;
- cmMakefile* Makefile;
- std::string Platform;
- std::string GUID;
- std::string Name;
+ cmGeneratorTarget* const GeneratorTarget;
+ cmMakefile* const Makefile;
+ std::string const Platform;
+ std::string const Name;
+ std::string const GUID;
bool MSTools;
bool Managed;
bool NsightTegra;
- int NsightTegraVersion[4];
+ unsigned int NsightTegraVersion[4];
bool TargetCompileAsWinRT;
- cmGlobalVisualStudio10Generator* GlobalGenerator;
- cmGeneratedFileStream* BuildFileStream;
- cmLocalVisualStudio7Generator* LocalGenerator;
- std::set<cmSourceFile const*> SourcesVisited;
+ std::set<std::string> IPOEnabledConfigurations;
+ std::map<std::string, std::string> SpectreMitigation;
+ cmGlobalVisualStudio10Generator* const GlobalGenerator;
+ cmLocalVisualStudio10Generator* const LocalGenerator;
+ std::set<std::string> CSharpCustomCommandNames;
bool IsMissingFiles;
std::vector<std::string> AddedFiles;
std::string DefaultArtifactDir;
+ bool AddedDefaultCertificate = false;
+ // managed C++/C# relevant members
+ using DotNetHintReference = std::pair<std::string, std::string>;
+ using DotNetHintReferenceList = std::vector<DotNetHintReference>;
+ using DotNetHintReferenceMap =
+ std::map<std::string, DotNetHintReferenceList>;
+ DotNetHintReferenceMap DotNetHintReferences;
+ using UsingDirectories = std::set<std::string>;
+ using UsingDirectoriesMap = std::map<std::string, UsingDirectories>;
+ UsingDirectoriesMap AdditionalUsingDirectories;
- typedef std::map<std::string, ToolSources> ToolSourceMap;
+ using ToolSourceMap = std::map<std::string, ToolSources>;
ToolSourceMap Tools;
std::string GetCMakeFilePath(const char* name) const;
};
diff --git a/Source/cmVisualStudio10ToolsetOptions.cxx b/Source/cmVisualStudio10ToolsetOptions.cxx
index 9a1d95078..7fc33e63e 100644
--- a/Source/cmVisualStudio10ToolsetOptions.cxx
+++ b/Source/cmVisualStudio10ToolsetOptions.cxx
@@ -6,145 +6,126 @@
#include "cmIDEFlagTable.h"
#include "cmVisualStudioGeneratorOptions.h"
-#include "cmVS10CLFlagTable.h"
-#include "cmVS10CSharpFlagTable.h"
-#include "cmVS10LibFlagTable.h"
-#include "cmVS10LinkFlagTable.h"
-#include "cmVS10MASMFlagTable.h"
-#include "cmVS10RCFlagTable.h"
-#include "cmVS11CLFlagTable.h"
-#include "cmVS11CSharpFlagTable.h"
-#include "cmVS11LibFlagTable.h"
-#include "cmVS11LinkFlagTable.h"
-#include "cmVS11MASMFlagTable.h"
-#include "cmVS11RCFlagTable.h"
-#include "cmVS12CLFlagTable.h"
-#include "cmVS12CSharpFlagTable.h"
-#include "cmVS12LibFlagTable.h"
-#include "cmVS12LinkFlagTable.h"
-#include "cmVS12MASMFlagTable.h"
-#include "cmVS12RCFlagTable.h"
-#include "cmVS140CLFlagTable.h"
-#include "cmVS140CSharpFlagTable.h"
-#include "cmVS140LinkFlagTable.h"
-#include "cmVS141CLFlagTable.h"
-#include "cmVS141CSharpFlagTable.h"
-#include "cmVS141LinkFlagTable.h"
-#include "cmVS14LibFlagTable.h"
-#include "cmVS14MASMFlagTable.h"
-#include "cmVS14RCFlagTable.h"
-
-cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetClFlagTable(
+std::string cmVisualStudio10ToolsetOptions::GetClFlagTableName(
std::string const& name, std::string const& toolset) const
{
std::string const useToolset = this->GetToolsetName(name, toolset);
- if (toolset == "v141") {
- return cmVS141CLFlagTable;
+ if (toolset == "v142") {
+ return "v142";
+ } else if (toolset == "v141") {
+ return "v141";
} else if (useToolset == "v140") {
- return cmVS140CLFlagTable;
+ return "v140";
} else if (useToolset == "v120") {
- return cmVS12CLFlagTable;
+ return "v12";
} else if (useToolset == "v110") {
- return cmVS11CLFlagTable;
+ return "v11";
} else if (useToolset == "v100") {
- return cmVS10CLFlagTable;
+ return "v10";
} else {
- return 0;
+ return "";
}
}
-cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetCSharpFlagTable(
+std::string cmVisualStudio10ToolsetOptions::GetCSharpFlagTableName(
std::string const& name, std::string const& toolset) const
{
std::string const useToolset = this->GetToolsetName(name, toolset);
- if ((useToolset == "v141")) {
- return cmVS141CSharpFlagTable;
+ if (useToolset == "v142") {
+ return "v142";
+ } else if (useToolset == "v141") {
+ return "v141";
} else if (useToolset == "v140") {
- return cmVS140CSharpFlagTable;
+ return "v140";
} else if (useToolset == "v120") {
- return cmVS12CSharpFlagTable;
+ return "v12";
} else if (useToolset == "v110") {
- return cmVS11CSharpFlagTable;
+ return "v11";
} else if (useToolset == "v100") {
- return cmVS10CSharpFlagTable;
+ return "v10";
} else {
- return 0;
+ return "";
}
}
-cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetRcFlagTable(
+std::string cmVisualStudio10ToolsetOptions::GetRcFlagTableName(
std::string const& name, std::string const& toolset) const
{
std::string const useToolset = this->GetToolsetName(name, toolset);
- if ((useToolset == "v140") || (useToolset == "v141")) {
- return cmVS14RCFlagTable;
+ if ((useToolset == "v140") || (useToolset == "v141") ||
+ (useToolset == "v142")) {
+ return "v14";
} else if (useToolset == "v120") {
- return cmVS12RCFlagTable;
+ return "v12";
} else if (useToolset == "v110") {
- return cmVS11RCFlagTable;
+ return "v11";
} else if (useToolset == "v100") {
- return cmVS10RCFlagTable;
+ return "v10";
} else {
- return 0;
+ return "";
}
}
-cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetLibFlagTable(
+std::string cmVisualStudio10ToolsetOptions::GetLibFlagTableName(
std::string const& name, std::string const& toolset) const
{
std::string const useToolset = this->GetToolsetName(name, toolset);
- if ((useToolset == "v140") || (useToolset == "v141")) {
- return cmVS14LibFlagTable;
+ if ((useToolset == "v140") || (useToolset == "v141") ||
+ (useToolset == "v142")) {
+ return "v14";
} else if (useToolset == "v120") {
- return cmVS12LibFlagTable;
+ return "v12";
} else if (useToolset == "v110") {
- return cmVS11LibFlagTable;
+ return "v11";
} else if (useToolset == "v100") {
- return cmVS10LibFlagTable;
+ return "v10";
} else {
- return 0;
+ return "";
}
}
-cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetLinkFlagTable(
+std::string cmVisualStudio10ToolsetOptions::GetLinkFlagTableName(
std::string const& name, std::string const& toolset) const
{
std::string const useToolset = this->GetToolsetName(name, toolset);
- if (useToolset == "v141") {
- return cmVS141LinkFlagTable;
+ if (useToolset == "v142") {
+ return "v142";
+ } else if (useToolset == "v141") {
+ return "v141";
} else if (useToolset == "v140") {
- return cmVS140LinkFlagTable;
+ return "v140";
} else if (useToolset == "v120") {
- return cmVS12LinkFlagTable;
+ return "v12";
} else if (useToolset == "v110") {
- return cmVS11LinkFlagTable;
+ return "v11";
} else if (useToolset == "v100") {
- return cmVS10LinkFlagTable;
+ return "v10";
} else {
- return 0;
+ return "";
}
}
-cmIDEFlagTable const* cmVisualStudio10ToolsetOptions::GetMasmFlagTable(
+std::string cmVisualStudio10ToolsetOptions::GetMasmFlagTableName(
std::string const& name, std::string const& toolset) const
{
std::string const useToolset = this->GetToolsetName(name, toolset);
- if ((useToolset == "v140") || (useToolset == "v141")) {
- return cmVS14MASMFlagTable;
+ if ((useToolset == "v140") || (useToolset == "v141") ||
+ (useToolset == "v142")) {
+ return "v14";
} else if (useToolset == "v120") {
- return cmVS12MASMFlagTable;
+ return "v12";
} else if (useToolset == "v110") {
- return cmVS11MASMFlagTable;
+ return "v11";
} else if (useToolset == "v100") {
- return cmVS10MASMFlagTable;
+ return "v10";
} else {
- return 0;
+ return "";
}
}
diff --git a/Source/cmVisualStudio10ToolsetOptions.h b/Source/cmVisualStudio10ToolsetOptions.h
index 4233337ba..875a35b24 100644
--- a/Source/cmVisualStudio10ToolsetOptions.h
+++ b/Source/cmVisualStudio10ToolsetOptions.h
@@ -3,12 +3,10 @@
#ifndef cmVisualStudio10ToolsetOptions_h
#define cmVisualStudio10ToolsetOptions_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
-struct cmIDEFlagTable;
-
/** \class cmVisualStudio10ToolsetOptions
* \brief Retrieves toolset options for MSBuild.
*
@@ -17,20 +15,18 @@ struct cmIDEFlagTable;
class cmVisualStudio10ToolsetOptions
{
public:
- cmIDEFlagTable const* GetClFlagTable(std::string const& name,
- std::string const& toolset) const;
- cmIDEFlagTable const* GetCSharpFlagTable(std::string const& name,
- std::string const& toolset) const;
- cmIDEFlagTable const* GetRcFlagTable(std::string const& name,
- std::string const& toolset) const;
- cmIDEFlagTable const* GetLibFlagTable(std::string const& name,
- std::string const& toolset) const;
- cmIDEFlagTable const* GetLinkFlagTable(std::string const& name,
- std::string const& toolset) const;
- cmIDEFlagTable const* GetMasmFlagTable(std::string const& name,
- std::string const& toolset) const;
-
-private:
+ std::string GetClFlagTableName(std::string const& name,
+ std::string const& toolset) const;
+ std::string GetCSharpFlagTableName(std::string const& name,
+ std::string const& toolset) const;
+ std::string GetRcFlagTableName(std::string const& name,
+ std::string const& toolset) const;
+ std::string GetLibFlagTableName(std::string const& name,
+ std::string const& toolset) const;
+ std::string GetLinkFlagTableName(std::string const& name,
+ std::string const& toolset) const;
+ std::string GetMasmFlagTableName(std::string const& name,
+ std::string const& toolset) const;
std::string GetToolsetName(std::string const& name,
std::string const& toolset) const;
};
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index 1f808c8b2..1139aa974 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -1,61 +1,24 @@
#include "cmVisualStudioGeneratorOptions.h"
+#include <cm/iterator>
+
#include "cmAlgorithms.h"
#include "cmLocalVisualStudioGenerator.h"
#include "cmOutputConverter.h"
#include "cmSystemTools.h"
-#include "cmVisualStudio10TargetGenerator.h"
-static std::string cmVisualStudio10GeneratorOptionsEscapeForXML(
- std::string ret)
+static void cmVS10EscapeForMSBuild(std::string& ret)
{
cmSystemTools::ReplaceString(ret, ";", "%3B");
- cmSystemTools::ReplaceString(ret, "&", "&amp;");
- cmSystemTools::ReplaceString(ret, "<", "&lt;");
- cmSystemTools::ReplaceString(ret, ">", "&gt;");
- return ret;
-}
-
-static std::string cmVisualStudioGeneratorOptionsEscapeForXML(std::string ret)
-{
- cmSystemTools::ReplaceString(ret, "&", "&amp;");
- cmSystemTools::ReplaceString(ret, "\"", "&quot;");
- cmSystemTools::ReplaceString(ret, "<", "&lt;");
- cmSystemTools::ReplaceString(ret, ">", "&gt;");
- cmSystemTools::ReplaceString(ret, "\n", "&#x0D;&#x0A;");
- return ret;
-}
-
-cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
- cmLocalVisualStudioGenerator* lg, Tool tool,
- cmVisualStudio10TargetGenerator* g)
- : cmIDEOptions()
- , LocalGenerator(lg)
- , Version(lg->GetVersion())
- , CurrentTool(tool)
- , TargetGenerator(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(
cmLocalVisualStudioGenerator* lg, Tool tool, cmVS7FlagTable const* table,
- cmVS7FlagTable const* extraTable, cmVisualStudio10TargetGenerator* g)
+ cmVS7FlagTable const* extraTable)
: cmIDEOptions()
, LocalGenerator(lg)
, Version(lg->GetVersion())
, CurrentTool(tool)
- , TargetGenerator(g)
{
// Store the given flag tables.
this->AddTable(table);
@@ -64,6 +27,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;
@@ -89,7 +55,7 @@ void cmVisualStudioGeneratorOptions::AddTable(cmVS7FlagTable const* table)
void cmVisualStudioGeneratorOptions::ClearTables()
{
for (int i = 0; i < FlagTableCount; ++i) {
- this->FlagTable[i] = CM_NULLPTR;
+ this->FlagTable[i] = nullptr;
}
}
@@ -106,6 +72,7 @@ void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault()
case cmGlobalVisualStudioGenerator::VS12:
case cmGlobalVisualStudioGenerator::VS14:
case cmGlobalVisualStudioGenerator::VS15:
+ case cmGlobalVisualStudioGenerator::VS16:
// by default VS puts <ExceptionHandling></ExceptionHandling> empty
// for a project, to make our projects look the same put a new line
// and space over for the closing </ExceptionHandling> as the default
@@ -163,10 +130,9 @@ bool cmVisualStudioGeneratorOptions::IsManaged() const
bool cmVisualStudioGeneratorOptions::UsingUnicode() const
{
- // Look for the a _UNICODE definition.
- for (std::vector<std::string>::const_iterator di = this->Defines.begin();
- di != this->Defines.end(); ++di) {
- if (*di == "_UNICODE") {
+ // Look for a _UNICODE definition.
+ for (std::string const& di : this->Defines) {
+ if (di == "_UNICODE") {
return true;
}
}
@@ -174,10 +140,9 @@ bool cmVisualStudioGeneratorOptions::UsingUnicode() const
}
bool cmVisualStudioGeneratorOptions::UsingSBCS() const
{
- // Look for the a _SBCS definition.
- for (std::vector<std::string>::const_iterator di = this->Defines.begin();
- di != this->Defines.end(); ++di) {
- if (*di == "_SBCS") {
+ // Look for a _SBCS definition.
+ for (std::string const& di : this->Defines) {
+ if (di == "_SBCS") {
return true;
}
}
@@ -230,7 +195,7 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
std::string arch_name = arch[0];
std::vector<std::string> codes;
if (!code.empty()) {
- codes = cmSystemTools::tokenize(code[0], ",");
+ codes = cmTokenize(code[0], ",");
}
if (codes.empty()) {
codes.push_back(arch_name);
@@ -239,35 +204,113 @@ 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 (std::string 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 (std::string 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 = cmTokenize(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::Parse(const char* flags)
+void cmVisualStudioGeneratorOptions::FixManifestUACFlags()
+{
+ static std::string const ENABLE_UAC = "EnableUAC";
+ if (!HasFlag(ENABLE_UAC)) {
+ return;
+ }
+
+ const std::string uacFlag = GetFlag(ENABLE_UAC);
+ std::vector<std::string> subOptions;
+ cmsys::SystemTools::Split(uacFlag, subOptions, ' ');
+ if (subOptions.empty()) {
+ AddFlag(ENABLE_UAC, "true");
+ return;
+ }
+
+ if (subOptions.size() == 1 && subOptions[0] == "NO") {
+ AddFlag(ENABLE_UAC, "false");
+ return;
+ }
+
+ std::map<std::string, std::string> uacMap;
+ uacMap["level"] = "UACExecutionLevel";
+ uacMap["uiAccess"] = "UACUIAccess";
+
+ std::map<std::string, std::string> uacExecuteLevelMap;
+ uacExecuteLevelMap["asInvoker"] = "AsInvoker";
+ uacExecuteLevelMap["highestAvailable"] = "HighestAvailable";
+ uacExecuteLevelMap["requireAdministrator"] = "RequireAdministrator";
+
+ for (std::string const& subopt : subOptions) {
+ std::vector<std::string> keyValue;
+ cmsys::SystemTools::Split(subopt, keyValue, '=');
+ if (keyValue.size() != 2 || (uacMap.find(keyValue[0]) == uacMap.end())) {
+ // ignore none key=value option or unknown flags
+ continue;
+ }
+
+ if (keyValue[1].front() == '\'' && keyValue[1].back() == '\'') {
+ keyValue[1] = keyValue[1].substr(
+ 1, std::max(std::string::size_type(0), keyValue[1].length() - 2));
+ }
+
+ if (keyValue[0] == "level") {
+ if (uacExecuteLevelMap.find(keyValue[1]) == uacExecuteLevelMap.end()) {
+ // unknown level value
+ continue;
+ }
+
+ AddFlag(uacMap[keyValue[0]], uacExecuteLevelMap[keyValue[1]]);
+ continue;
+ }
+
+ if (keyValue[0] == "uiAccess") {
+ if (keyValue[1] != "true" && keyValue[1] != "false") {
+ // unknown uiAccess value
+ continue;
+ }
+ AddFlag(uacMap[keyValue[0]], keyValue[1]);
+ continue;
+ }
+
+ // unknown sub option
+ }
+
+ AddFlag(ENABLE_UAC, "true");
+}
+
+void cmVisualStudioGeneratorOptions::Parse(const std::string& flags)
{
// Parse the input string as a windows command line since the string
// is intended for writing directly into the build files.
std::vector<std::string> args;
- cmSystemTools::ParseWindowsCommandLine(flags, args);
+ cmSystemTools::ParseWindowsCommandLine(flags.c_str(), args);
// Process flags that need to be represented specially in the IDE
// project file.
- for (std::vector<std::string>::iterator ai = args.begin(); ai != args.end();
- ++ai) {
- this->HandleFlag(ai->c_str());
+ for (std::string const& ai : args) {
+ this->HandleFlag(ai);
}
}
@@ -284,9 +327,9 @@ void cmVisualStudioGeneratorOptions::ParseFinish()
// "rtSingleThreadedDLL", "10", /libs:dll
// "rtSingleThreadedDebug", "5", /dbglibs /libs:static
// "rtSingleThreadedDebugDLL", "11", /dbglibs /libs:dll
- std::string rl = "rtMultiThreaded";
- rl += this->FortranRuntimeDebug ? "Debug" : "";
- rl += this->FortranRuntimeDLL ? "DLL" : "";
+ std::string rl =
+ cmStrCat("rtMultiThreaded", this->FortranRuntimeDebug ? "Debug" : "",
+ this->FortranRuntimeDLL ? "DLL" : "");
this->FlagMap["RuntimeLibrary"] = rl;
}
@@ -326,26 +369,26 @@ void cmVisualStudioGeneratorOptions::Reparse(std::string const& key)
std::string const original = i->second[0];
i->second[0] = "";
this->UnknownFlagField = key;
- this->Parse(original.c_str());
+ this->Parse(original);
}
-void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag)
+void cmVisualStudioGeneratorOptions::StoreUnknownFlag(std::string const& flag)
{
// Look for Intel Fortran flags that do not map well in the flag table.
if (this->CurrentTool == FortranCompiler) {
- if (strcmp(flag, "/dbglibs") == 0) {
+ if (flag == "/dbglibs" || flag == "-dbglibs") {
this->FortranRuntimeDebug = true;
return;
}
- if (strcmp(flag, "/threads") == 0) {
+ if (flag == "/threads" || flag == "-threads") {
this->FortranRuntimeMT = true;
return;
}
- if (strcmp(flag, "/libs:dll") == 0) {
+ if (flag == "/libs:dll" || flag == "-libs:dll") {
this->FortranRuntimeDLL = true;
return;
}
- if (strcmp(flag, "/libs:static") == 0) {
+ if (flag == "/libs:static" || flag == "-libs:static") {
this->FortranRuntimeDLL = false;
return;
}
@@ -353,7 +396,8 @@ void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag)
// This option is not known. Store it in the output flags.
std::string const opts = cmOutputConverter::EscapeWindowsShellArgument(
- flag, cmOutputConverter::Shell_Flag_AllowMakeVariables |
+ flag.c_str(),
+ cmOutputConverter::Shell_Flag_AllowMakeVariables |
cmOutputConverter::Shell_Flag_VSIDE);
this->AppendFlagString(this->UnknownFlagField, opts);
}
@@ -370,14 +414,19 @@ cmIDEOptions::FlagValue cmVisualStudioGeneratorOptions::TakeFlag(
return value;
}
-void cmVisualStudioGeneratorOptions::SetConfiguration(const char* config)
+void cmVisualStudioGeneratorOptions::SetConfiguration(
+ const std::string& config)
{
this->Configuration = config;
}
+const std::string& cmVisualStudioGeneratorOptions::GetConfiguration() const
+{
+ return this->Configuration;
+}
+
void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
- std::ostream& fout, const char* prefix, const char* suffix,
- const std::string& lang)
+ std::ostream& fout, int indent, const std::string& lang)
{
if (this->Defines.empty()) {
return;
@@ -386,84 +435,99 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
if (lang == "CUDA") {
tag = "Defines";
}
- 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 << "=\"";
- }
+
+ std::ostringstream oss;
const char* sep = "";
std::vector<std::string>::const_iterator de =
cmRemoveDuplicates(this->Defines);
- for (std::vector<std::string>::const_iterator di = this->Defines.begin();
- di != de; ++di) {
+ for (std::string const& di : cmMakeRange(this->Defines.cbegin(), de)) {
// Escape the definition for the compiler.
std::string define;
if (this->Version < cmGlobalVisualStudioGenerator::VS10) {
- define = this->LocalGenerator->EscapeForShell(di->c_str(), true);
+ define = this->LocalGenerator->EscapeForShell(di, true);
} else {
- define = *di;
+ define = di;
}
- // Escape this flag for the IDE.
+ // Escape this flag for the MSBuild.
if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- define = cmVisualStudio10GeneratorOptionsEscapeForXML(define);
-
+ cmVS10EscapeForMSBuild(define);
if (lang == "RC") {
cmSystemTools::ReplaceString(define, "\"", "\\\"");
}
- } else {
- define = cmVisualStudioGeneratorOptionsEscapeForXML(define);
}
// Store the flag in the project file.
- fout << sep << define;
+ oss << sep << define;
sep = ";";
}
if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- fout << ";%(" << tag << ")</" << tag << ">" << suffix;
- } else {
- fout << "\"" << suffix;
+ oss << ";%(" << tag << ")";
}
+
+ this->OutputFlag(fout, indent, tag, oss.str());
}
-void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout,
- const char* indent)
+void cmVisualStudioGeneratorOptions::OutputAdditionalIncludeDirectories(
+ std::ostream& fout, int indent, const std::string& lang)
{
- if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- for (std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin();
- m != this->FlagMap.end(); ++m) {
- fout << indent;
- if (!this->Configuration.empty()) {
- this->TargetGenerator->WritePlatformConfigTag(
- m->first.c_str(), this->Configuration.c_str(), 0, 0, 0, &fout);
- } else {
- fout << "<" << m->first << ">";
- }
- const char* sep = "";
- for (std::vector<std::string>::iterator i = m->second.begin();
- i != m->second.end(); ++i) {
- fout << sep << cmVisualStudio10GeneratorOptionsEscapeForXML(*i);
- sep = ";";
- }
- fout << "</" << m->first << ">\n";
+ if (this->Includes.empty()) {
+ return;
+ }
+
+ const char* tag = "AdditionalIncludeDirectories";
+ if (lang == "CUDA") {
+ tag = "Include";
+ } else if (lang == "ASM_MASM" || lang == "ASM_NASM") {
+ tag = "IncludePaths";
+ }
+
+ std::ostringstream oss;
+ 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 MSBuild.
+ if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+ cmVS10EscapeForMSBuild(include);
+ }
+ oss << sep << include;
+ sep = ";";
+
+ if (lang == "Fortran") {
+ include += "/$(ConfigurationName)";
+ oss << sep << include;
}
- } else {
- for (std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin();
- m != this->FlagMap.end(); ++m) {
- fout << indent << m->first << "=\"";
- const char* sep = "";
- for (std::vector<std::string>::iterator i = m->second.begin();
- i != m->second.end(); ++i) {
- fout << sep << cmVisualStudioGeneratorOptionsEscapeForXML(*i);
- sep = ";";
+ }
+
+ if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+ oss << sep << "%(" << tag << ")";
+ }
+
+ this->OutputFlag(fout, indent, tag, oss.str());
+}
+
+void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout,
+ int indent)
+{
+ for (auto const& m : this->FlagMap) {
+ std::ostringstream oss;
+ const char* sep = "";
+ for (std::string i : m.second) {
+ if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+ cmVS10EscapeForMSBuild(i);
}
- fout << "\"\n";
+ oss << sep << i;
+ sep = ";";
}
+
+ this->OutputFlag(fout, indent, m.first.c_str(), oss.str());
}
}
diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h
index 44d271908..560593e01 100644
--- a/Source/cmVisualStudioGeneratorOptions.h
+++ b/Source/cmVisualStudioGeneratorOptions.h
@@ -3,7 +3,7 @@
#ifndef cmVisualStudioGeneratorOptions_h
#define cmVisualStudioGeneratorOptions_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
@@ -14,9 +14,7 @@
class cmLocalVisualStudioGenerator;
-typedef cmIDEFlagTable cmVS7FlagTable;
-
-class cmVisualStudio10TargetGenerator;
+using cmVS7FlagTable = cmIDEFlagTable;
class cmVisualStudioGeneratorOptions : public cmIDEOptions
{
@@ -34,12 +32,8 @@ public:
CSharpCompiler
};
cmVisualStudioGeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool,
- cmVS7FlagTable const* table,
- cmVS7FlagTable const* extraTable = 0,
- cmVisualStudio10TargetGenerator* g = 0);
-
- cmVisualStudioGeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool,
- cmVisualStudio10TargetGenerator* g = 0);
+ cmVS7FlagTable const* table = nullptr,
+ cmVS7FlagTable const* extraTable = nullptr);
// Add a table of flags.
void AddTable(cmVS7FlagTable const* table);
@@ -48,7 +42,7 @@ public:
void ClearTables();
// Store options from command line flags.
- void Parse(const char* flags);
+ void Parse(const std::string& flags);
void ParseFinish();
void PrependInheritedString(std::string const& key);
@@ -77,15 +71,23 @@ public:
void FixCudaCodeGeneration();
+ void FixManifestUACFlags();
+
bool IsDebug() const;
bool IsWinRt() const;
bool IsManaged() const;
// Write options to output.
- void OutputPreprocessorDefinitions(std::ostream& fout, const char* prefix,
- const char* suffix,
+ void OutputPreprocessorDefinitions(std::ostream& fout, int indent,
const std::string& lang);
- void OutputFlagMap(std::ostream& fout, const char* indent);
- void SetConfiguration(const char* config);
+ void OutputAdditionalIncludeDirectories(std::ostream& fout, int indent,
+ const std::string& lang);
+ void OutputFlagMap(std::ostream& fout, int indent);
+ void SetConfiguration(const std::string& config);
+ const std::string& GetConfiguration() const;
+
+protected:
+ virtual void OutputFlag(std::ostream& fout, int indent, const char* tag,
+ const std::string& content) = 0;
private:
cmLocalVisualStudioGenerator* LocalGenerator;
@@ -93,7 +95,6 @@ private:
std::string Configuration;
Tool CurrentTool;
- cmVisualStudio10TargetGenerator* TargetGenerator;
bool FortranRuntimeDebug;
bool FortranRuntimeDLL;
@@ -101,7 +102,7 @@ private:
std::string UnknownFlagField;
- virtual void StoreUnknownFlag(const char* flag);
+ void StoreUnknownFlag(std::string const& flag) override;
FlagValue TakeFlag(std::string const& key);
};
diff --git a/Source/cmVisualStudioSlnData.h b/Source/cmVisualStudioSlnData.h
index e12047fb5..5ce7d74f8 100644
--- a/Source/cmVisualStudioSlnData.h
+++ b/Source/cmVisualStudioSlnData.h
@@ -3,7 +3,7 @@
#ifndef cmVisualStudioSlnData_h
#define cmVisualStudioSlnData_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
#include <string>
@@ -45,9 +45,9 @@ public:
const std::string& projectRelativePath);
private:
- typedef std::map<std::string, cmSlnProjectEntry> ProjectStorage;
+ using ProjectStorage = std::map<std::string, cmSlnProjectEntry>;
ProjectStorage ProjectsByGUID;
- typedef std::map<std::string, ProjectStorage::iterator> ProjectStringIndex;
+ using ProjectStringIndex = std::map<std::string, ProjectStorage::iterator>;
ProjectStringIndex ProjectNameIndex;
};
diff --git a/Source/cmVisualStudioSlnParser.cxx b/Source/cmVisualStudioSlnParser.cxx
index 1a32abacf..4533e9b69 100644
--- a/Source/cmVisualStudioSlnParser.cxx
+++ b/Source/cmVisualStudioSlnParser.cxx
@@ -2,13 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVisualStudioSlnParser.h"
-#include "cmSystemTools.h"
-#include "cmVisualStudioSlnData.h"
-#include "cmsys/FStream.hxx"
-
#include <cassert>
#include <stack>
+#include "cmsys/FStream.hxx"
+
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmVisualStudioSlnData.h"
+
namespace {
enum LineFormat
{
@@ -50,7 +52,7 @@ public:
void CopyVerbatim(const std::string& line) { this->Tag = line; }
private:
- typedef std::pair<std::string, bool> StringData;
+ using StringData = std::pair<std::string, bool>;
std::string Tag;
StringData Arg;
std::vector<StringData> Values;
@@ -192,8 +194,8 @@ bool cmVisualStudioSlnParser::State::Process(
assert(!line.IsComment());
switch (this->Stack.top()) {
case FileStateStart:
- if (!cmSystemTools::StringStartsWith(
- line.GetTag().c_str(), "Microsoft Visual Studio Solution File")) {
+ if (!cmHasLiteralPrefix(line.GetTag(),
+ "Microsoft Visual Studio Solution File")) {
result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
return false;
}
@@ -329,7 +331,7 @@ bool cmVisualStudioSlnParser::State::Process(
case FileStateIgnore:
if (line.GetTag() == this->EndIgnoreTag) {
this->Stack.pop();
- this->EndIgnoreTag = "";
+ this->EndIgnoreTag.clear();
}
break;
default:
@@ -462,7 +464,7 @@ bool cmVisualStudioSlnParser::ParseImpl(std::istream& input, cmSlnData& output,
if (!this->ParseBOM(input, line, state))
return false;
do {
- line = cmSystemTools::TrimWhitespace(line);
+ line = cmTrimWhitespace(line);
if (line.empty())
continue;
ParsedLine parsedLine;
@@ -578,9 +580,9 @@ bool cmVisualStudioSlnParser::ParseKeyValuePair(const std::string& line,
return true;
}
const std::string& key = line.substr(0, idxEqualSign);
- parsedLine.SetTag(cmSystemTools::TrimWhitespace(key));
+ parsedLine.SetTag(cmTrimWhitespace(key));
const std::string& value = line.substr(idxEqualSign + 1);
- parsedLine.AddValue(cmSystemTools::TrimWhitespace(value));
+ parsedLine.AddValue(cmTrimWhitespace(value));
return true;
}
@@ -589,21 +591,20 @@ bool cmVisualStudioSlnParser::ParseTag(const std::string& fullTag,
{
size_t idxLeftParen = fullTag.find('(');
if (idxLeftParen == fullTag.npos) {
- parsedLine.SetTag(cmSystemTools::TrimWhitespace(fullTag));
+ parsedLine.SetTag(cmTrimWhitespace(fullTag));
return true;
}
- parsedLine.SetTag(
- cmSystemTools::TrimWhitespace(fullTag.substr(0, idxLeftParen)));
+ parsedLine.SetTag(cmTrimWhitespace(fullTag.substr(0, idxLeftParen)));
size_t idxRightParen = fullTag.rfind(')');
if (idxRightParen == fullTag.npos) {
this->LastResult.SetError(ResultErrorInputStructure,
state.GetCurrentLine());
return false;
}
- const std::string& arg = cmSystemTools::TrimWhitespace(
+ const std::string& arg = cmTrimWhitespace(
fullTag.substr(idxLeftParen + 1, idxRightParen - idxLeftParen - 1));
- if (arg[0] == '"') {
- if (arg[arg.size() - 1] != '"') {
+ if (arg.front() == '"') {
+ if (arg.back() != '"') {
this->LastResult.SetError(ResultErrorInputStructure,
state.GetCurrentLine());
return false;
@@ -617,10 +618,10 @@ bool cmVisualStudioSlnParser::ParseTag(const std::string& fullTag,
bool cmVisualStudioSlnParser::ParseValue(const std::string& value,
ParsedLine& parsedLine)
{
- const std::string& trimmed = cmSystemTools::TrimWhitespace(value);
+ const std::string& trimmed = cmTrimWhitespace(value);
if (trimmed.empty())
parsedLine.AddValue(trimmed);
- else if (trimmed[0] == '"' && trimmed[trimmed.size() - 1] == '"')
+ else if (trimmed.front() == '"' && trimmed.back() == '"')
parsedLine.AddQuotedValue(trimmed.substr(1, trimmed.size() - 2));
else
parsedLine.AddValue(trimmed);
diff --git a/Source/cmVisualStudioSlnParser.h b/Source/cmVisualStudioSlnParser.h
index d51732407..6c05633b8 100644
--- a/Source/cmVisualStudioSlnParser.h
+++ b/Source/cmVisualStudioSlnParser.h
@@ -3,13 +3,14 @@
#ifndef cmVisualStudioSlnParser_h
#define cmVisualStudioSlnParser_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <bitset>
#include <iosfwd>
-#include <stddef.h>
#include <string>
+#include <stddef.h>
+
class cmSlnData;
class cmVisualStudioSlnParser
@@ -42,7 +43,7 @@ public:
DataGroupCount
};
- typedef std::bitset<DataGroupCount> DataGroupSet;
+ using DataGroupSet = std::bitset<DataGroupCount>;
static const DataGroupSet DataGroupProjects;
static const DataGroupSet DataGroupProjectDependencies;
diff --git a/Source/cmVisualStudioWCEPlatformParser.cxx b/Source/cmVisualStudioWCEPlatformParser.cxx
index fc64d0fb0..3b113aadb 100644
--- a/Source/cmVisualStudioWCEPlatformParser.cxx
+++ b/Source/cmVisualStudioWCEPlatformParser.cxx
@@ -56,12 +56,12 @@ void cmVisualStudioWCEPlatformParser::StartElement(const std::string& name,
return;
}
- this->CharacterData = "";
+ this->CharacterData.clear();
if (name == "PlatformData") {
- this->PlatformName = "";
- this->OSMajorVersion = "";
- this->OSMinorVersion = "";
+ this->PlatformName.clear();
+ this->OSMajorVersion.clear();
+ this->OSMinorVersion.clear();
this->Macros.clear();
}
diff --git a/Source/cmVisualStudioWCEPlatformParser.h b/Source/cmVisualStudioWCEPlatformParser.h
index 75c3d1a39..60a66113e 100644
--- a/Source/cmVisualStudioWCEPlatformParser.h
+++ b/Source/cmVisualStudioWCEPlatformParser.h
@@ -3,13 +3,14 @@
#ifndef cmVisualStudioWCEPlatformParser_h
#define cmVisualStudioWCEPlatformParser_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
-#include <stddef.h>
#include <string>
#include <vector>
+#include <stddef.h>
+
#include "cmXMLParser.h"
// This class is used to parse XML with configuration
diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx
index 24d7bf1bf..26e7c7537 100644
--- a/Source/cmWhileCommand.cxx
+++ b/Source/cmWhileCommand.cxx
@@ -2,17 +2,46 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmWhileCommand.h"
+#include <string>
+#include <utility>
+
+#include <cm/memory>
+#include <cm/string_view>
+
+#include "cm_static_string_view.hxx"
+
#include "cmConditionEvaluator.h"
#include "cmExecutionStatus.h"
#include "cmExpandedCommandArgument.h"
+#include "cmFunctionBlocker.h"
+#include "cmListFileCache.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmSystemTools.h"
-#include "cm_auto_ptr.hxx"
-#include "cmake.h"
+
+class cmWhileFunctionBlocker : public cmFunctionBlocker
+{
+public:
+ cmWhileFunctionBlocker(cmMakefile* mf);
+ ~cmWhileFunctionBlocker() override;
+
+ cm::string_view StartCommandName() const override { return "while"_s; }
+ cm::string_view EndCommandName() const override { return "endwhile"_s; }
+
+ bool ArgumentsMatch(cmListFileFunction const& lff,
+ cmMakefile& mf) const override;
+
+ bool Replay(std::vector<cmListFileFunction> functions,
+ cmExecutionStatus& inStatus) override;
+
+ std::vector<cmListFileArgument> Args;
+
+private:
+ cmMakefile* Makefile;
+};
cmWhileFunctionBlocker::cmWhileFunctionBlocker(cmMakefile* mf)
: Makefile(mf)
- , Depth(0)
{
this->Makefile->PushLoopBlock();
}
@@ -22,122 +51,93 @@ cmWhileFunctionBlocker::~cmWhileFunctionBlocker()
this->Makefile->PopLoopBlock();
}
-bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
- cmMakefile& mf,
- cmExecutionStatus& inStatus)
+bool cmWhileFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
+ cmMakefile&) const
{
- // at end of for each execute recorded commands
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "while")) {
- // record the number of while commands past this one
- this->Depth++;
- } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endwhile")) {
- // if this is the endwhile for this while loop then execute
- if (!this->Depth) {
- // Remove the function blocker for this scope or bail.
- CM_AUTO_PTR<cmFunctionBlocker> fb(mf.RemoveFunctionBlocker(this, lff));
- if (!fb.get()) {
- return false;
- }
+ return lff.Arguments.empty() || lff.Arguments == this->Args;
+}
- std::string errorString;
-
- std::vector<cmExpandedCommandArgument> expandedArguments;
- mf.ExpandArguments(this->Args, expandedArguments);
- cmake::MessageType messageType;
-
- cmListFileContext execContext = this->GetStartingContext();
-
- cmCommandContext commandContext;
- commandContext.Line = execContext.Line;
- commandContext.Name = execContext.Name;
-
- cmConditionEvaluator conditionEvaluator(mf, this->GetStartingContext(),
- mf.GetBacktrace(commandContext));
-
- bool isTrue =
- conditionEvaluator.IsTrue(expandedArguments, errorString, messageType);
-
- while (isTrue) {
- if (!errorString.empty()) {
- std::string err = "had incorrect arguments: ";
- unsigned int i;
- for (i = 0; i < this->Args.size(); ++i) {
- err += (this->Args[i].Delim ? "\"" : "");
- err += this->Args[i].Value;
- err += (this->Args[i].Delim ? "\"" : "");
- err += " ";
- }
- err += "(";
- err += errorString;
- err += ").";
- mf.IssueMessage(messageType, err);
- if (messageType == cmake::FATAL_ERROR) {
- cmSystemTools::SetFatalErrorOccured();
- return true;
- }
- }
-
- // Invoke all the functions that were collected in the block.
- for (unsigned int c = 0; c < this->Functions.size(); ++c) {
- cmExecutionStatus status;
- mf.ExecuteCommand(this->Functions[c], status);
- if (status.GetReturnInvoked()) {
- inStatus.SetReturnInvoked();
- return true;
- }
- if (status.GetBreakInvoked()) {
- return true;
- }
- if (status.GetContinueInvoked()) {
- break;
- }
- if (cmSystemTools::GetFatalErrorOccured()) {
- return true;
- }
- }
- expandedArguments.clear();
- mf.ExpandArguments(this->Args, expandedArguments);
- isTrue = conditionEvaluator.IsTrue(expandedArguments, errorString,
- messageType);
- }
- return true;
- }
- // decrement for each nested while that ends
- this->Depth--;
- }
+bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,
+ cmExecutionStatus& inStatus)
+{
+ cmMakefile& mf = inStatus.GetMakefile();
+ std::string errorString;
- // record the command
- this->Functions.push_back(lff);
+ std::vector<cmExpandedCommandArgument> expandedArguments;
+ mf.ExpandArguments(this->Args, expandedArguments);
+ MessageType messageType;
- // always return true
- return true;
-}
+ cmListFileContext execContext = this->GetStartingContext();
-bool cmWhileFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
- cmMakefile&)
-{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endwhile")) {
- // if the endwhile has arguments, then make sure
- // they match the arguments of the matching while
- if (lff.Arguments.empty() || lff.Arguments == this->Args) {
- return true;
+ cmCommandContext commandContext;
+ commandContext.Line = execContext.Line;
+ commandContext.Name = execContext.Name;
+
+ cmConditionEvaluator conditionEvaluator(mf, this->GetStartingContext(),
+ mf.GetBacktrace(commandContext));
+
+ bool isTrue =
+ conditionEvaluator.IsTrue(expandedArguments, errorString, messageType);
+
+ while (isTrue) {
+ if (!errorString.empty()) {
+ std::string err = "had incorrect arguments: ";
+ for (cmListFileArgument const& arg : this->Args) {
+ err += (arg.Delim ? "\"" : "");
+ err += arg.Value;
+ err += (arg.Delim ? "\"" : "");
+ err += " ";
+ }
+ err += "(";
+ err += errorString;
+ err += ").";
+ mf.IssueMessage(messageType, err);
+ if (messageType == MessageType::FATAL_ERROR) {
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+ }
+
+ // Invoke all the functions that were collected in the block.
+ for (cmListFileFunction const& fn : functions) {
+ cmExecutionStatus status(mf);
+ mf.ExecuteCommand(fn, status);
+ if (status.GetReturnInvoked()) {
+ inStatus.SetReturnInvoked();
+ return true;
+ }
+ if (status.GetBreakInvoked()) {
+ return true;
+ }
+ if (status.GetContinueInvoked()) {
+ break;
+ }
+ if (cmSystemTools::GetFatalErrorOccured()) {
+ return true;
+ }
}
+ expandedArguments.clear();
+ mf.ExpandArguments(this->Args, expandedArguments);
+ isTrue =
+ conditionEvaluator.IsTrue(expandedArguments, errorString, messageType);
}
- return false;
+ return true;
}
-bool cmWhileCommand::InvokeInitialPass(
- const std::vector<cmListFileArgument>& args, cmExecutionStatus&)
+bool cmWhileCommand(std::vector<cmListFileArgument> const& args,
+ cmExecutionStatus& status)
{
if (args.empty()) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
// create a function blocker
- cmWhileFunctionBlocker* f = new cmWhileFunctionBlocker(this->Makefile);
- f->Args = args;
- this->Makefile->AddFunctionBlocker(f);
-
+ {
+ cmMakefile& makefile = status.GetMakefile();
+ auto fb = cm::make_unique<cmWhileFunctionBlocker>(&makefile);
+ fb->Args = args;
+ makefile.AddFunctionBlocker(std::move(fb));
+ }
return true;
}
diff --git a/Source/cmWhileCommand.h b/Source/cmWhileCommand.h
index a95e4c30c..beca652c6 100644
--- a/Source/cmWhileCommand.h
+++ b/Source/cmWhileCommand.h
@@ -3,60 +3,15 @@
#ifndef cmWhileCommand_h
#define cmWhileCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
-#include <string>
#include <vector>
-#include "cmCommand.h"
-#include "cmFunctionBlocker.h"
-#include "cmListFileCache.h"
-
class cmExecutionStatus;
-class cmMakefile;
-
-class cmWhileFunctionBlocker : public cmFunctionBlocker
-{
-public:
- cmWhileFunctionBlocker(cmMakefile* mf);
- ~cmWhileFunctionBlocker() CM_OVERRIDE;
- bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf,
- cmExecutionStatus&) CM_OVERRIDE;
- bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) CM_OVERRIDE;
-
- std::vector<cmListFileArgument> Args;
- std::vector<cmListFileFunction> Functions;
-
-private:
- cmMakefile* Makefile;
- int Depth;
-};
+struct cmListFileArgument;
/// \brief Starts a while loop
-class cmWhileCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmWhileCommand; }
-
- /**
- * This overrides the default InvokeInitialPass implementation.
- * It records the arguments before expansion.
- */
- bool InvokeInitialPass(const std::vector<cmListFileArgument>& args,
- cmExecutionStatus&) CM_OVERRIDE;
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const&,
- cmExecutionStatus&) CM_OVERRIDE
- {
- return false;
- }
-};
+bool cmWhileCommand(std::vector<cmListFileArgument> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmWorkerPool.cxx b/Source/cmWorkerPool.cxx
new file mode 100644
index 000000000..aa0d6b3d5
--- /dev/null
+++ b/Source/cmWorkerPool.cxx
@@ -0,0 +1,763 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmWorkerPool.h"
+
+#include <algorithm>
+#include <array>
+#include <condition_variable>
+#include <cstddef>
+#include <deque>
+#include <functional>
+#include <mutex>
+#include <thread>
+
+#include <cm/memory>
+
+#include "cm_uv.h"
+
+#include "cmRange.h"
+#include "cmStringAlgorithms.h"
+#include "cmUVHandlePtr.h"
+#include "cmUVSignalHackRAII.h" // IWYU pragma: keep
+
+/**
+ * @brief libuv pipe buffer class
+ */
+class cmUVPipeBuffer
+{
+public:
+ using DataRange = cmRange<const char*>;
+ using DataFunction = std::function<void(DataRange)>;
+ /// On error the ssize_t argument is a non zero libuv error code
+ using EndFunction = std::function<void(ssize_t)>;
+
+public:
+ /**
+ * Reset to construction state
+ */
+ void reset();
+
+ /**
+ * Initializes uv_pipe(), uv_stream() and uv_handle()
+ * @return true on success
+ */
+ bool init(uv_loop_t* uv_loop);
+
+ /**
+ * Start reading
+ * @return true on success
+ */
+ bool startRead(DataFunction dataFunction, EndFunction endFunction);
+
+ //! libuv pipe
+ uv_pipe_t* uv_pipe() const { return UVPipe_.get(); }
+ //! uv_pipe() casted to libuv stream
+ uv_stream_t* uv_stream() const { return static_cast<uv_stream_t*>(UVPipe_); }
+ //! uv_pipe() casted to libuv handle
+ uv_handle_t* uv_handle() { return static_cast<uv_handle_t*>(UVPipe_); }
+
+private:
+ // -- 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:
+ cm::uv_pipe_ptr UVPipe_;
+ std::vector<char> Buffer_;
+ DataFunction DataFunction_;
+ EndFunction EndFunction_;
+};
+
+void cmUVPipeBuffer::reset()
+{
+ if (UVPipe_.get() != nullptr) {
+ EndFunction_ = nullptr;
+ DataFunction_ = nullptr;
+ Buffer_.clear();
+ Buffer_.shrink_to_fit();
+ UVPipe_.reset();
+ }
+}
+
+bool cmUVPipeBuffer::init(uv_loop_t* uv_loop)
+{
+ reset();
+ if (uv_loop == nullptr) {
+ return false;
+ }
+ int ret = UVPipe_.init(*uv_loop, 0, this);
+ return (ret == 0);
+}
+
+bool cmUVPipeBuffer::startRead(DataFunction dataFunction,
+ EndFunction endFunction)
+{
+ if (UVPipe_.get() == nullptr) {
+ return false;
+ }
+ if (!dataFunction || !endFunction) {
+ return false;
+ }
+ DataFunction_ = std::move(dataFunction);
+ EndFunction_ = std::move(endFunction);
+ int ret = uv_read_start(uv_stream(), &cmUVPipeBuffer::UVAlloc,
+ &cmUVPipeBuffer::UVData);
+ return (ret == 0);
+}
+
+void cmUVPipeBuffer::UVAlloc(uv_handle_t* handle, size_t suggestedSize,
+ uv_buf_t* buf)
+{
+ auto& pipe = *reinterpret_cast<cmUVPipeBuffer*>(handle->data);
+ pipe.Buffer_.resize(suggestedSize);
+ buf->base = pipe.Buffer_.data();
+ buf->len = static_cast<unsigned long>(pipe.Buffer_.size());
+}
+
+void cmUVPipeBuffer::UVData(uv_stream_t* stream, ssize_t nread,
+ const uv_buf_t* buf)
+{
+ auto& pipe = *reinterpret_cast<cmUVPipeBuffer*>(stream->data);
+ if (nread > 0) {
+ if (buf->base != nullptr) {
+ // Call data function
+ pipe.DataFunction_(DataRange(buf->base, buf->base + nread));
+ }
+ } else if (nread < 0) {
+ // Save the end function on the stack before resetting the pipe
+ EndFunction efunc;
+ efunc.swap(pipe.EndFunction_);
+ // Reset pipe before calling the end function
+ pipe.reset();
+ // Call end function
+ efunc((nread == UV_EOF) ? 0 : nread);
+ }
+}
+
+/**
+ * @brief External process management class
+ */
+class cmUVReadOnlyProcess
+{
+public:
+ // -- Types
+ //! @brief Process settings
+ struct SetupT
+ {
+ std::string WorkingDirectory;
+ std::vector<std::string> Command;
+ cmWorkerPool::ProcessResultT* Result = nullptr;
+ bool MergedOutput = false;
+ };
+
+public:
+ // -- Const accessors
+ SetupT const& Setup() const { return Setup_; }
+ cmWorkerPool::ProcessResultT* Result() const { return Setup_.Result; }
+ bool IsStarted() const { return IsStarted_; }
+ bool IsFinished() const { return IsFinished_; }
+
+ // -- Runtime
+ void setup(cmWorkerPool::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:
+ // -- Libuv callbacks
+ static void UVExit(uv_process_t* handle, int64_t exitStatus, int termSignal);
+ void UVPipeOutData(cmUVPipeBuffer::DataRange data);
+ void UVPipeOutEnd(ssize_t error);
+ void UVPipeErrData(cmUVPipeBuffer::DataRange data);
+ void UVPipeErrEnd(ssize_t error);
+ void UVTryFinish();
+
+private:
+ // -- 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_;
+ cmUVPipeBuffer UVPipeOut_;
+ cmUVPipeBuffer UVPipeErr_;
+};
+
+void cmUVReadOnlyProcess::setup(cmWorkerPool::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 cmUVReadOnlyProcess::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)) {
+ Result()->ErrorMessage = "libuv stdout pipe initialization failed";
+ }
+ }
+ if (!Result()->error()) {
+ if (!UVPipeErr_.init(uv_loop)) {
+ 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 = &cmUVReadOnlyProcess::UVExit;
+ UVOptions_.file = CommandPtr_[0];
+ UVOptions_.args = const_cast<char**>(CommandPtr_.data());
+ UVOptions_.cwd = Setup_.WorkingDirectory.c_str();
+ UVOptions_.flags = UV_PROCESS_WINDOWS_HIDE;
+ UVOptions_.stdio_count = static_cast<int>(UVOptionsStdIO_.size());
+ UVOptions_.stdio = UVOptionsStdIO_.data();
+
+ // -- Spawn process
+ int uvErrorCode = UVProcess_.spawn(*uv_loop, UVOptions_, this);
+ if (uvErrorCode != 0) {
+ Result()->ErrorMessage = "libuv process spawn failed";
+ if (const char* uvErr = uv_strerror(uvErrorCode)) {
+ Result()->ErrorMessage += ": ";
+ Result()->ErrorMessage += uvErr;
+ }
+ }
+ }
+ // -- Start reading from stdio streams
+ if (!Result()->error()) {
+ if (!UVPipeOut_.startRead(
+ [this](cmUVPipeBuffer::DataRange range) {
+ this->UVPipeOutData(range);
+ },
+ [this](ssize_t error) { this->UVPipeOutEnd(error); })) {
+ Result()->ErrorMessage = "libuv start reading from stdout pipe failed";
+ }
+ }
+ if (!Result()->error()) {
+ if (!UVPipeErr_.startRead(
+ [this](cmUVPipeBuffer::DataRange range) {
+ this->UVPipeErrData(range);
+ },
+ [this](ssize_t error) { this->UVPipeErrEnd(error); })) {
+ 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 cmUVReadOnlyProcess::UVExit(uv_process_t* handle, int64_t exitStatus,
+ int termSignal)
+{
+ auto& proc = *reinterpret_cast<cmUVReadOnlyProcess*>(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 = cmStrCat(
+ "Process was terminated by signal ", proc.Result()->TermSignal);
+ } else if (exitStatus != 0) {
+ proc.Result()->ErrorMessage = cmStrCat(
+ "Process failed with return value ", proc.Result()->ExitStatus);
+ }
+ }
+
+ // Reset process handle
+ proc.UVProcess_.reset();
+ // Try finish
+ proc.UVTryFinish();
+ }
+}
+
+void cmUVReadOnlyProcess::UVPipeOutData(cmUVPipeBuffer::DataRange data)
+{
+ Result()->StdOut.append(data.begin(), data.end());
+}
+
+void cmUVReadOnlyProcess::UVPipeOutEnd(ssize_t error)
+{
+ // Process pipe error
+ if ((error != 0) && !Result()->error()) {
+ Result()->ErrorMessage = cmStrCat(
+ "Reading from stdout pipe failed with libuv error code ", error);
+ }
+ // Try finish
+ UVTryFinish();
+}
+
+void cmUVReadOnlyProcess::UVPipeErrData(cmUVPipeBuffer::DataRange data)
+{
+ std::string* str =
+ Setup_.MergedOutput ? &Result()->StdOut : &Result()->StdErr;
+ str->append(data.begin(), data.end());
+}
+
+void cmUVReadOnlyProcess::UVPipeErrEnd(ssize_t error)
+{
+ // Process pipe error
+ if ((error != 0) && !Result()->error()) {
+ Result()->ErrorMessage = cmStrCat(
+ "Reading from stderr pipe failed with libuv error code ", error);
+ }
+ // Try finish
+ UVTryFinish();
+}
+
+void cmUVReadOnlyProcess::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) || (UVPipeOut_.uv_pipe() != nullptr) ||
+ (UVPipeErr_.uv_pipe() != nullptr)) {
+ return;
+ }
+ IsFinished_ = true;
+ FinishedCallback_();
+}
+
+/**
+ * @brief Worker pool worker thread
+ */
+class cmWorkerPoolWorker
+{
+public:
+ cmWorkerPoolWorker(uv_loop_t& uvLoop);
+ ~cmWorkerPoolWorker();
+
+ cmWorkerPoolWorker(cmWorkerPoolWorker const&) = delete;
+ cmWorkerPoolWorker& operator=(cmWorkerPoolWorker const&) = delete;
+
+ /**
+ * Set the internal thread
+ */
+ void SetThread(std::thread&& aThread) { Thread_ = std::move(aThread); }
+
+ /**
+ * Run an external process
+ */
+ bool RunProcess(cmWorkerPool::ProcessResultT& result,
+ std::vector<std::string> const& command,
+ std::string const& workingDirectory);
+
+private:
+ // -- Libuv callbacks
+ static void UVProcessStart(uv_async_t* handle);
+ void UVProcessFinished();
+
+private:
+ // -- Process management
+ struct
+ {
+ std::mutex Mutex;
+ cm::uv_async_ptr Request;
+ std::condition_variable Condition;
+ std::unique_ptr<cmUVReadOnlyProcess> ROP;
+ } Proc_;
+ // -- System thread
+ std::thread Thread_;
+};
+
+cmWorkerPoolWorker::cmWorkerPoolWorker(uv_loop_t& uvLoop)
+{
+ Proc_.Request.init(uvLoop, &cmWorkerPoolWorker::UVProcessStart, this);
+}
+
+cmWorkerPoolWorker::~cmWorkerPoolWorker()
+{
+ if (Thread_.joinable()) {
+ Thread_.join();
+ }
+}
+
+bool cmWorkerPoolWorker::RunProcess(cmWorkerPool::ProcessResultT& result,
+ std::vector<std::string> const& command,
+ std::string const& workingDirectory)
+{
+ if (command.empty()) {
+ return false;
+ }
+ // Create process instance
+ {
+ std::lock_guard<std::mutex> lock(Proc_.Mutex);
+ Proc_.ROP = cm::make_unique<cmUVReadOnlyProcess>();
+ Proc_.ROP->setup(&result, true, command, workingDirectory);
+ }
+ // Send asynchronous process start request to libuv loop
+ Proc_.Request.send();
+ // Wait until the process has been finished and destroyed
+ {
+ std::unique_lock<std::mutex> ulock(Proc_.Mutex);
+ while (Proc_.ROP) {
+ Proc_.Condition.wait(ulock);
+ }
+ }
+ return !result.error();
+}
+
+void cmWorkerPoolWorker::UVProcessStart(uv_async_t* handle)
+{
+ auto* wrk = reinterpret_cast<cmWorkerPoolWorker*>(handle->data);
+ bool startFailed = false;
+ {
+ auto& Proc = wrk->Proc_;
+ std::lock_guard<std::mutex> lock(Proc.Mutex);
+ if (Proc.ROP && !Proc.ROP->IsStarted()) {
+ startFailed =
+ !Proc.ROP->start(handle->loop, [wrk] { wrk->UVProcessFinished(); });
+ }
+ }
+ // Clean up if starting of the process failed
+ if (startFailed) {
+ wrk->UVProcessFinished();
+ }
+}
+
+void cmWorkerPoolWorker::UVProcessFinished()
+{
+ {
+ std::lock_guard<std::mutex> lock(Proc_.Mutex);
+ if (Proc_.ROP && (Proc_.ROP->IsFinished() || !Proc_.ROP->IsStarted())) {
+ Proc_.ROP.reset();
+ }
+ }
+ // Notify idling thread
+ Proc_.Condition.notify_one();
+}
+
+/**
+ * @brief Private worker pool internals
+ */
+class cmWorkerPoolInternal
+{
+public:
+ // -- Constructors
+ cmWorkerPoolInternal(cmWorkerPool* pool);
+ ~cmWorkerPoolInternal();
+
+ /**
+ * Runs the libuv loop.
+ */
+ bool Process();
+
+ /**
+ * Clear queue and abort threads.
+ */
+ void Abort();
+
+ /**
+ * Push a job to the queue and notify a worker.
+ */
+ bool PushJob(cmWorkerPool::JobHandleT&& jobHandle);
+
+ /**
+ * Worker thread main loop method.
+ */
+ void Work(unsigned int workerIndex);
+
+ // -- Request slots
+ static void UVSlotBegin(uv_async_t* handle);
+ static void UVSlotEnd(uv_async_t* handle);
+
+public:
+ // -- UV loop
+#ifdef CMAKE_UV_SIGNAL_HACK
+ std::unique_ptr<cmUVSignalHackRAII> UVHackRAII;
+#endif
+ std::unique_ptr<uv_loop_t> UVLoop;
+ cm::uv_async_ptr UVRequestBegin;
+ cm::uv_async_ptr UVRequestEnd;
+
+ // -- Thread pool and job queue
+ std::mutex Mutex;
+ bool Processing = false;
+ bool Aborting = false;
+ bool FenceProcessing = false;
+ unsigned int WorkersRunning = 0;
+ unsigned int WorkersIdle = 0;
+ unsigned int JobsProcessing = 0;
+ std::deque<cmWorkerPool::JobHandleT> Queue;
+ std::condition_variable Condition;
+ std::vector<std::unique_ptr<cmWorkerPoolWorker>> Workers;
+
+ // -- References
+ cmWorkerPool* Pool = nullptr;
+};
+
+void cmWorkerPool::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();
+ }
+}
+
+cmWorkerPoolInternal::cmWorkerPoolInternal(cmWorkerPool* pool)
+ : Pool(pool)
+{
+ // 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.get());
+}
+
+cmWorkerPoolInternal::~cmWorkerPoolInternal()
+{
+ uv_loop_close(UVLoop.get());
+}
+
+bool cmWorkerPoolInternal::Process()
+{
+ // Reset state flags
+ Processing = true;
+ Aborting = false;
+ // Initialize libuv asynchronous request
+ UVRequestBegin.init(*UVLoop, &cmWorkerPoolInternal::UVSlotBegin, this);
+ UVRequestEnd.init(*UVLoop, &cmWorkerPoolInternal::UVSlotEnd, this);
+ // Send begin request
+ UVRequestBegin.send();
+ // Run libuv loop
+ bool success = (uv_run(UVLoop.get(), UV_RUN_DEFAULT) == 0);
+ // Update state flags
+ Processing = false;
+ Aborting = false;
+ return success;
+}
+
+void cmWorkerPoolInternal::Abort()
+{
+ bool notifyThreads = false;
+ // Clear all jobs and set abort flag
+ {
+ std::lock_guard<std::mutex> guard(Mutex);
+ if (Processing && !Aborting) {
+ // Register abort and clear queue
+ Aborting = true;
+ Queue.clear();
+ notifyThreads = true;
+ }
+ }
+ if (notifyThreads) {
+ // Wake threads
+ Condition.notify_all();
+ }
+}
+
+inline bool cmWorkerPoolInternal::PushJob(cmWorkerPool::JobHandleT&& jobHandle)
+{
+ std::lock_guard<std::mutex> guard(Mutex);
+ if (Aborting) {
+ return false;
+ }
+ // Append the job to the queue
+ Queue.emplace_back(std::move(jobHandle));
+ // Notify an idle worker if there's one
+ if (WorkersIdle != 0) {
+ Condition.notify_one();
+ }
+ // Return success
+ return true;
+}
+
+void cmWorkerPoolInternal::UVSlotBegin(uv_async_t* handle)
+{
+ auto& gint = *reinterpret_cast<cmWorkerPoolInternal*>(handle->data);
+ // Create worker threads
+ {
+ unsigned int const num = gint.Pool->ThreadCount();
+ // Create workers
+ gint.Workers.reserve(num);
+ for (unsigned int ii = 0; ii != num; ++ii) {
+ gint.Workers.emplace_back(
+ cm::make_unique<cmWorkerPoolWorker>(*gint.UVLoop));
+ }
+ // Start worker threads
+ for (unsigned int ii = 0; ii != num; ++ii) {
+ gint.Workers[ii]->SetThread(
+ std::thread(&cmWorkerPoolInternal::Work, &gint, ii));
+ }
+ }
+ // Destroy begin request
+ gint.UVRequestBegin.reset();
+}
+
+void cmWorkerPoolInternal::UVSlotEnd(uv_async_t* handle)
+{
+ auto& gint = *reinterpret_cast<cmWorkerPoolInternal*>(handle->data);
+ // Join and destroy worker threads
+ gint.Workers.clear();
+ // Destroy end request
+ gint.UVRequestEnd.reset();
+}
+
+void cmWorkerPoolInternal::Work(unsigned int workerIndex)
+{
+ cmWorkerPool::JobHandleT jobHandle;
+ std::unique_lock<std::mutex> uLock(Mutex);
+ // Increment running workers count
+ ++WorkersRunning;
+ // Enter worker main loop
+ while (true) {
+ // Abort on request
+ if (Aborting) {
+ break;
+ }
+ // Wait for new jobs
+ if (Queue.empty()) {
+ ++WorkersIdle;
+ Condition.wait(uLock);
+ --WorkersIdle;
+ continue;
+ }
+
+ // Check for fence jobs
+ if (FenceProcessing || Queue.front()->IsFence()) {
+ if (JobsProcessing != 0) {
+ Condition.wait(uLock);
+ continue;
+ }
+ // No jobs get processed. Set the fence job processing flag.
+ FenceProcessing = true;
+ }
+
+ // Pop next job from queue
+ jobHandle = std::move(Queue.front());
+ Queue.pop_front();
+
+ // Unlocked scope for job processing
+ ++JobsProcessing;
+ {
+ uLock.unlock();
+ jobHandle->Work(Pool, workerIndex); // Process job
+ jobHandle.reset(); // Destroy job
+ uLock.lock();
+ }
+ --JobsProcessing;
+
+ // Was this a fence job?
+ if (FenceProcessing) {
+ FenceProcessing = false;
+ Condition.notify_all();
+ }
+ }
+
+ // Decrement running workers count
+ if (--WorkersRunning == 0) {
+ // Last worker thread about to finish. Send libuv event.
+ UVRequestEnd.send();
+ }
+}
+
+cmWorkerPool::JobT::~JobT() = default;
+
+bool cmWorkerPool::JobT::RunProcess(ProcessResultT& result,
+ std::vector<std::string> const& command,
+ std::string const& workingDirectory)
+{
+ // Get worker by index
+ auto* wrk = Pool_->Int_->Workers.at(WorkerIndex_).get();
+ return wrk->RunProcess(result, command, workingDirectory);
+}
+
+cmWorkerPool::cmWorkerPool()
+ : Int_(cm::make_unique<cmWorkerPoolInternal>(this))
+{
+}
+
+cmWorkerPool::~cmWorkerPool() = default;
+
+void cmWorkerPool::SetThreadCount(unsigned int threadCount)
+{
+ if (!Int_->Processing) {
+ ThreadCount_ = (threadCount > 0) ? threadCount : 1u;
+ }
+}
+
+bool cmWorkerPool::Process(void* userData)
+{
+ // Setup user data
+ UserData_ = userData;
+ // Run libuv loop
+ bool success = Int_->Process();
+ // Clear user data
+ UserData_ = nullptr;
+ // Return
+ return success;
+}
+
+bool cmWorkerPool::PushJob(JobHandleT&& jobHandle)
+{
+ return Int_->PushJob(std::move(jobHandle));
+}
+
+void cmWorkerPool::Abort()
+{
+ Int_->Abort();
+}
diff --git a/Source/cmWorkerPool.h b/Source/cmWorkerPool.h
new file mode 100644
index 000000000..91799223a
--- /dev/null
+++ b/Source/cmWorkerPool.h
@@ -0,0 +1,225 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmWorkerPool_h
+#define cmWorkerPool_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cstdint>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm/memory>
+
+// -- Types
+class cmWorkerPoolInternal;
+
+/** @class cmWorkerPool
+ * @brief Thread pool with job queue
+ */
+class cmWorkerPool
+{
+public:
+ /**
+ * 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;
+ };
+
+ /**
+ * Abstract job class for concurrent job processing.
+ */
+ class JobT
+ {
+ public:
+ JobT(JobT const&) = delete;
+ JobT& operator=(JobT const&) = delete;
+
+ /**
+ * Virtual destructor.
+ */
+ virtual ~JobT();
+
+ /**
+ * Fence job flag
+ *
+ * Fence jobs require that:
+ * - all jobs before in the queue have been processed
+ * - no jobs later in the queue will be processed before this job was
+ * processed
+ */
+ bool IsFence() const { return Fence_; }
+
+ protected:
+ /**
+ * Protected default constructor
+ */
+ JobT(bool fence = false)
+ : Fence_(fence)
+ {
+ }
+
+ /**
+ * Abstract processing interface that must be implement in derived classes.
+ */
+ virtual void Process() = 0;
+
+ /**
+ * Get the worker pool.
+ * Only valid during the JobT::Process() call!
+ */
+ cmWorkerPool* Pool() const { return Pool_; }
+
+ /**
+ * Get the user data.
+ * Only valid during the JobT::Process() call!
+ */
+ void* UserData() const { return Pool_->UserData(); };
+
+ /**
+ * Get the worker index.
+ * This is the index of the thread processing this job and is in the range
+ * [0..ThreadCount).
+ * Concurrently processing jobs will never have the same WorkerIndex().
+ * Only valid during the JobT::Process() call!
+ */
+ unsigned int WorkerIndex() const { return WorkerIndex_; }
+
+ /**
+ * Run an external read only process.
+ * Use only during JobT::Process() call!
+ */
+ bool RunProcess(ProcessResultT& result,
+ std::vector<std::string> const& command,
+ std::string const& workingDirectory);
+
+ private:
+ //! Needs access to Work()
+ friend class cmWorkerPoolInternal;
+ //! Worker thread entry method.
+ void Work(cmWorkerPool* pool, unsigned int workerIndex)
+ {
+ Pool_ = pool;
+ WorkerIndex_ = workerIndex;
+ this->Process();
+ }
+
+ private:
+ cmWorkerPool* Pool_ = nullptr;
+ unsigned int WorkerIndex_ = 0;
+ bool Fence_ = false;
+ };
+
+ /**
+ * Job handle type
+ */
+ using JobHandleT = std::unique_ptr<JobT>;
+
+ /**
+ * Fence job base class
+ */
+ class JobFenceT : public JobT
+ {
+ public:
+ JobFenceT()
+ : JobT(true)
+ {
+ }
+ //! Does nothing
+ void Process() override{};
+ };
+
+ /**
+ * Fence job that aborts the worker pool.
+ *
+ * Useful as the last job in the job queue.
+ */
+ class JobEndT : JobFenceT
+ {
+ public:
+ //! Does nothing
+ void Process() override { Pool()->Abort(); }
+ };
+
+public:
+ // -- Methods
+ cmWorkerPool();
+ ~cmWorkerPool();
+
+ /**
+ * Number of worker threads.
+ */
+ unsigned int ThreadCount() const { return ThreadCount_; }
+
+ /**
+ * Set the number of worker threads.
+ *
+ * Calling this method during Process() has no effect.
+ */
+ void SetThreadCount(unsigned int threadCount);
+
+ /**
+ * Blocking function that starts threads to process all Jobs in the queue.
+ *
+ * This method blocks until a job calls the Abort() method.
+ * @arg threadCount Number of threads to process jobs.
+ * @arg userData Common user data pointer available in all Jobs.
+ */
+ bool Process(void* userData = nullptr);
+
+ /**
+ * User data reference passed to Process().
+ *
+ * Only valid during Process().
+ */
+ void* UserData() const { return UserData_; }
+
+ // -- Job processing interface
+
+ /**
+ * Clears the job queue and aborts all worker threads.
+ *
+ * This method is thread safe and can be called from inside a job.
+ */
+ void Abort();
+
+ /**
+ * Push job to the queue.
+ *
+ * This method is thread safe and can be called from inside a job or before
+ * Process().
+ */
+ bool PushJob(JobHandleT&& jobHandle);
+
+ /**
+ * Push job to the queue
+ *
+ * This method is thread safe and can be called from inside a job or before
+ * Process().
+ */
+ template <class T, typename... Args>
+ bool EmplaceJob(Args&&... args)
+ {
+ return PushJob(cm::make_unique<T>(std::forward<Args>(args)...));
+ }
+
+private:
+ void* UserData_ = nullptr;
+ unsigned int ThreadCount_ = 1;
+ std::unique_ptr<cmWorkerPoolInternal> Int_;
+};
+
+#endif
diff --git a/Source/cmWorkingDirectory.cxx b/Source/cmWorkingDirectory.cxx
index 99c9ba86a..5700b1cc7 100644
--- a/Source/cmWorkingDirectory.cxx
+++ b/Source/cmWorkingDirectory.cxx
@@ -2,12 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmWorkingDirectory.h"
+#include <cerrno>
+
#include "cmSystemTools.h"
cmWorkingDirectory::cmWorkingDirectory(std::string const& newdir)
{
this->OldDir = cmSystemTools::GetCurrentWorkingDirectory();
- cmSystemTools::ChangeDirectory(newdir);
+ this->SetDirectory(newdir);
}
cmWorkingDirectory::~cmWorkingDirectory()
@@ -15,10 +17,20 @@ cmWorkingDirectory::~cmWorkingDirectory()
this->Pop();
}
+bool cmWorkingDirectory::SetDirectory(std::string const& newdir)
+{
+ if (cmSystemTools::ChangeDirectory(newdir) == 0) {
+ this->ResultCode = 0;
+ return true;
+ }
+ this->ResultCode = errno;
+ return false;
+}
+
void cmWorkingDirectory::Pop()
{
if (!this->OldDir.empty()) {
- cmSystemTools::ChangeDirectory(this->OldDir);
+ this->SetDirectory(this->OldDir);
this->OldDir.clear();
}
}
diff --git a/Source/cmWorkingDirectory.h b/Source/cmWorkingDirectory.h
index aff926755..d4a164de6 100644
--- a/Source/cmWorkingDirectory.h
+++ b/Source/cmWorkingDirectory.h
@@ -9,6 +9,12 @@
/** \class cmWorkingDirectory
* \brief An RAII class to manipulate the working directory.
+ *
+ * The current working directory is set to the location given to the
+ * constructor. The working directory can be changed again as needed
+ * by calling SetDirectory(). When the object is destroyed, the destructor
+ * will restore the working directory to what it was when the object was
+ * created, regardless of any calls to SetDirectory() in the meantime.
*/
class cmWorkingDirectory
{
@@ -16,10 +22,24 @@ public:
cmWorkingDirectory(std::string const& newdir);
~cmWorkingDirectory();
+ cmWorkingDirectory(const cmWorkingDirectory&) = delete;
+ cmWorkingDirectory& operator=(const cmWorkingDirectory&) = delete;
+
+ bool SetDirectory(std::string const& newdir);
void Pop();
+ bool Failed() const { return ResultCode != 0; }
+
+ /** \return 0 if the last attempt to set the working directory was
+ * successful. If it failed, the value returned will be the
+ * \c errno value associated with the failure. A description
+ * of the error code can be obtained by passing the result
+ * to \c std::strerror().
+ */
+ int GetLastResult() const { return ResultCode; }
private:
std::string OldDir;
+ int ResultCode;
};
#endif
diff --git a/Source/cmWriteFileCommand.cxx b/Source/cmWriteFileCommand.cxx
index fc5fd2111..34e21b2f2 100644
--- a/Source/cmWriteFileCommand.cxx
+++ b/Source/cmWriteFileCommand.cxx
@@ -4,22 +4,23 @@
#include "cmsys/FStream.hxx"
-#include "cmMakefile.h"
-#include "cmSystemTools.h"
#include "cm_sys_stat.h"
-class cmExecutionStatus;
+#include "cmExecutionStatus.h"
+#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
// cmLibraryCommand
-bool cmWriteFileCommand::InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus&)
+bool cmWriteFileCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
{
if (args.size() < 2) {
- this->SetError("called with incorrect number of arguments");
+ status.SetError("called with incorrect number of arguments");
return false;
}
std::string message;
- std::vector<std::string>::const_iterator i = args.begin();
+ auto i = args.begin();
std::string const& fileName = *i;
bool overwrite = true;
@@ -33,43 +34,47 @@ bool cmWriteFileCommand::InitialPass(std::vector<std::string> const& args,
}
}
- if (!this->Makefile->CanIWriteThisFile(fileName.c_str())) {
+ if (!status.GetMakefile().CanIWriteThisFile(fileName)) {
std::string e =
"attempted to write a file: " + fileName + " into a source directory.";
- this->SetError(e);
+ status.SetError(e);
cmSystemTools::SetFatalErrorOccured();
return false;
}
std::string dir = cmSystemTools::GetFilenamePath(fileName);
- cmSystemTools::MakeDirectory(dir.c_str());
+ cmSystemTools::MakeDirectory(dir);
mode_t mode = 0;
+ bool writable = false;
// Set permissions to writable
if (cmSystemTools::GetPermissions(fileName.c_str(), mode)) {
- cmSystemTools::SetPermissions(fileName.c_str(),
#if defined(_MSC_VER) || defined(__MINGW32__)
- mode | S_IWRITE
+ writable = (mode & S_IWRITE) != 0;
+ mode_t newMode = mode | S_IWRITE;
#else
- mode | S_IWUSR | S_IWGRP
+ writable = mode & S_IWUSR;
+ mode_t newMode = mode | S_IWUSR | S_IWGRP;
#endif
- );
+ if (!writable) {
+ cmSystemTools::SetPermissions(fileName.c_str(), newMode);
+ }
}
// If GetPermissions fails, pretend like it is ok. File open will fail if
// the file is not writable
cmsys::ofstream file(fileName.c_str(),
overwrite ? std::ios::out : std::ios::app);
if (!file) {
- std::string error = "Internal CMake error when trying to open file: ";
- error += fileName;
- error += " for writing.";
- this->SetError(error);
+ std::string error =
+ cmStrCat("Internal CMake error when trying to open file: ", fileName,
+ " for writing.");
+ status.SetError(error);
return false;
}
file << message << std::endl;
file.close();
- if (mode) {
+ if (mode && !writable) {
cmSystemTools::SetPermissions(fileName.c_str(), mode);
}
diff --git a/Source/cmWriteFileCommand.h b/Source/cmWriteFileCommand.h
index 19922cdf3..3e0e04376 100644
--- a/Source/cmWriteFileCommand.h
+++ b/Source/cmWriteFileCommand.h
@@ -3,33 +3,18 @@
#ifndef cmWriteFileCommand_h
#define cmWriteFileCommand_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <vector>
-#include "cmCommand.h"
-
class cmExecutionStatus;
-/** \class cmWriteFileCommand
+/**
* \brief Writes a message to a file
*
*/
-class cmWriteFileCommand : public cmCommand
-{
-public:
- /**
- * This is a virtual constructor for the command.
- */
- cmCommand* Clone() CM_OVERRIDE { return new cmWriteFileCommand; }
-
- /**
- * This is called when the command is first encountered in
- * the CMakeLists.txt file.
- */
- bool InitialPass(std::vector<std::string> const& args,
- cmExecutionStatus& status) CM_OVERRIDE;
-};
+bool cmWriteFileCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status);
#endif
diff --git a/Source/cmXCode21Object.cxx b/Source/cmXCode21Object.cxx
index 719e62765..a9bb2ef54 100644
--- a/Source/cmXCode21Object.cxx
+++ b/Source/cmXCode21Object.cxx
@@ -34,9 +34,7 @@ void cmXCode21Object::PrintList(std::vector<cmXCodeObject*> const& v,
std::ostream& out, PBXType t)
{
bool hasOne = false;
- for (std::vector<cmXCodeObject*>::const_iterator i = v.begin(); i != v.end();
- ++i) {
- cmXCodeObject* obj = *i;
+ for (auto obj : v) {
if (obj->GetType() == OBJECT && obj->GetIsA() == t) {
hasOne = true;
break;
@@ -46,9 +44,7 @@ void cmXCode21Object::PrintList(std::vector<cmXCodeObject*> const& v,
return;
}
out << "\n/* Begin " << PBXTypeNames[t] << " section */\n";
- for (std::vector<cmXCodeObject*>::const_iterator i = v.begin(); i != v.end();
- ++i) {
- cmXCodeObject* obj = *i;
+ for (auto obj : v) {
if (obj->GetType() == OBJECT && obj->GetIsA() == t) {
obj->Print(out);
}
diff --git a/Source/cmXCode21Object.h b/Source/cmXCode21Object.h
index bcd8d93e1..8e4b80fc1 100644
--- a/Source/cmXCode21Object.h
+++ b/Source/cmXCode21Object.h
@@ -14,7 +14,7 @@ class cmXCode21Object : public cmXCodeObject
{
public:
cmXCode21Object(PBXType ptype, Type type);
- virtual void PrintComment(std::ostream&);
+ void PrintComment(std::ostream&) override;
static void PrintList(std::vector<cmXCodeObject*> const&, std::ostream& out,
PBXType t);
static void PrintList(std::vector<cmXCodeObject*> const&, std::ostream& out);
diff --git a/Source/cmXCodeObject.cxx b/Source/cmXCodeObject.cxx
index 0def8c321..b301ab121 100644
--- a/Source/cmXCodeObject.cxx
+++ b/Source/cmXCodeObject.cxx
@@ -2,9 +2,10 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmXCodeObject.h"
-#include <CoreFoundation/CoreFoundation.h>
#include <ostream>
+#include <CoreFoundation/CoreFoundation.h>
+
#include "cmSystemTools.h"
const char* cmXCodeObject::PBXTypeNames[] = {
@@ -42,8 +43,8 @@ cmXCodeObject::~cmXCodeObject()
cmXCodeObject::cmXCodeObject(PBXType ptype, Type type)
{
this->Version = 15;
- this->Target = 0;
- this->Object = 0;
+ this->Target = nullptr;
+ this->Object = nullptr;
this->IsA = ptype;
@@ -71,7 +72,7 @@ cmXCodeObject::cmXCodeObject(PBXType ptype, Type type)
this->TypeValue = type;
if (this->TypeValue == OBJECT) {
- this->AddAttribute("isa", 0);
+ this->AddAttribute("isa", nullptr);
}
}
@@ -86,7 +87,7 @@ bool cmXCodeObject::IsEmpty() const
return this->ObjectAttributes.empty();
case OBJECT_REF:
case OBJECT:
- return this->Object == 0;
+ return this->Object == nullptr;
}
return true; // unreachable, but quiets warnings
}
@@ -115,23 +116,23 @@ 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";
}
-void cmXCodeObject::PrintAttribute(std::ostream& out, const int level,
- const std::string separator,
- const int factor, const std::string& name,
+void cmXCodeObject::PrintAttribute(std::ostream& out, int level,
+ const std::string& separator, int factor,
+ const std::string& name,
const cmXCodeObject* object,
const cmXCodeObject* parent)
{
@@ -166,11 +167,9 @@ void cmXCodeObject::PrintAttribute(std::ostream& out, const 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;
@@ -203,9 +202,9 @@ void cmXCodeObject::PrintList(std::vector<cmXCodeObject*> const& objs,
{
cmXCodeObject::Indent(1, out);
out << "objects = {\n";
- for (unsigned int i = 0; i < objs.size(); ++i) {
- if (objs[i]->TypeValue == OBJECT) {
- objs[i]->Print(out);
+ for (auto obj : objs) {
+ if (obj->TypeValue == OBJECT) {
+ obj->Print(out);
}
}
cmXCodeObject::Indent(1, out);
@@ -220,7 +219,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.
@@ -233,13 +232,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 b92e6e33e..d9be3d2db 100644
--- a/Source/cmXCodeObject.h
+++ b/Source/cmXCodeObject.h
@@ -12,6 +12,8 @@
#include <utility>
#include <vector>
+#include "cmAlgorithms.h"
+
class cmGeneratorTarget;
class cmXCodeObject
@@ -80,22 +82,17 @@ public:
void SetObject(cmXCodeObject* value) { this->Object = value; }
cmXCodeObject* GetObject() { return this->Object; }
void AddObject(cmXCodeObject* value) { this->List.push_back(value); }
- bool HasObject(cmXCodeObject* o) const
- {
- return !(std::find(this->List.begin(), this->List.end(), o) ==
- this->List.end());
- }
+ bool HasObject(cmXCodeObject* o) const { return cmContains(this->List, o); }
void AddUniqueObject(cmXCodeObject* value)
{
- if (std::find(this->List.begin(), this->List.end(), value) ==
- this->List.end()) {
+ if (!cmContains(this->List, value)) {
this->List.push_back(value);
}
}
static void Indent(int level, std::ostream& out);
void Print(std::ostream& out);
- void PrintAttribute(std::ostream& out, const int level,
- const std::string separator, const int factor,
+ void PrintAttribute(std::ostream& out, int level,
+ const std::string& separator, int factor,
const std::string& name, const cmXCodeObject* object,
const cmXCodeObject* parent);
virtual void PrintComment(std::ostream&) {}
@@ -109,24 +106,21 @@ public:
bool HasComment() const { return (!this->Comment.empty()); }
cmXCodeObject* GetObject(const char* name) const
{
- std::map<std::string, cmXCodeObject*>::const_iterator i =
- this->ObjectAttributes.find(name);
+ auto const i = this->ObjectAttributes.find(name);
if (i != this->ObjectAttributes.end()) {
return i->second;
}
- return 0;
+ return nullptr;
}
// search the attribute list for an object of the specified type
cmXCodeObject* GetObject(cmXCodeObject::PBXType t) const
{
- for (std::vector<cmXCodeObject*>::const_iterator i = this->List.begin();
- i != this->List.end(); ++i) {
- cmXCodeObject* o = *i;
+ for (auto o : this->List) {
if (o->IsA == t) {
return o;
}
}
- return 0;
+ return nullptr;
}
void CopyAttributes(cmXCodeObject*);
@@ -152,7 +146,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/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx
index 5c22531d4..afc95f56c 100644
--- a/Source/cmXCodeScheme.cxx
+++ b/Source/cmXCodeScheme.cxx
@@ -5,18 +5,18 @@
#include <iomanip>
#include <iostream>
#include <sstream>
+#include <utility>
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmXMLSafe.h"
-cmXCodeScheme::cmXCodeScheme(cmXCodeObject* xcObj,
+cmXCodeScheme::cmXCodeScheme(cmXCodeObject* xcObj, TestObjects tests,
const std::vector<std::string>& configList,
unsigned int xcVersion)
: Target(xcObj)
+ , Tests(std::move(tests))
, TargetName(xcObj->GetTarget()->GetName())
- , BuildableName(xcObj->GetTarget()->GetFullName())
- , TargetId(xcObj->GetId())
, ConfigList(configList)
, XcodeVersion(xcVersion)
{
@@ -27,16 +27,13 @@ void cmXCodeScheme::WriteXCodeSharedScheme(const std::string& xcProjDir,
{
// Create shared scheme sub-directory tree
//
- std::string xcodeSchemeDir = xcProjDir;
- xcodeSchemeDir += "/xcshareddata/xcschemes";
+ std::string xcodeSchemeDir = cmStrCat(xcProjDir, "/xcshareddata/xcschemes");
cmSystemTools::MakeDirectory(xcodeSchemeDir.c_str());
- std::string xcodeSchemeFile = xcodeSchemeDir;
- xcodeSchemeFile += "/";
- xcodeSchemeFile += this->TargetName;
- xcodeSchemeFile += ".xcscheme";
+ std::string xcodeSchemeFile =
+ cmStrCat(xcodeSchemeDir, '/', this->TargetName, ".xcscheme");
- cmGeneratedFileStream fout(xcodeSchemeFile.c_str());
+ cmGeneratedFileStream fout(xcodeSchemeFile);
fout.SetCopyIfDifferent(true);
if (!fout) {
return;
@@ -58,7 +55,7 @@ void cmXCodeScheme::WriteXCodeXCScheme(std::ostream& fout,
xout.Attribute("version", "1.3");
WriteBuildAction(xout, container);
- WriteTestAction(xout, FindConfiguration("Debug"));
+ WriteTestAction(xout, FindConfiguration("Debug"), container);
WriteLaunchAction(xout, FindConfiguration("Debug"), container);
WriteProfileAction(xout, FindConfiguration("Release"));
WriteAnalyzeAction(xout, FindConfiguration("Debug"));
@@ -84,14 +81,7 @@ void cmXCodeScheme::WriteBuildAction(cmXMLWriter& xout,
xout.Attribute("buildForArchiving", "YES");
xout.Attribute("buildForAnalyzing", "YES");
- xout.StartElement("BuildableReference");
- xout.BreakAttributes();
- xout.Attribute("BuildableIdentifier", "primary");
- xout.Attribute("BlueprintIdentifier", this->TargetId);
- xout.Attribute("BuildableName", this->BuildableName);
- xout.Attribute("BlueprintName", this->TargetName);
- xout.Attribute("ReferencedContainer", "container:" + container);
- xout.EndElement();
+ WriteBuildableReference(xout, this->Target, container);
xout.EndElement(); // BuildActionEntry
xout.EndElement(); // BuildActionEntries
@@ -99,7 +89,8 @@ void cmXCodeScheme::WriteBuildAction(cmXMLWriter& xout,
}
void cmXCodeScheme::WriteTestAction(cmXMLWriter& xout,
- std::string configuration)
+ const std::string& configuration,
+ const std::string& container)
{
xout.StartElement("TestAction");
xout.BreakAttributes();
@@ -111,8 +102,21 @@ void cmXCodeScheme::WriteTestAction(cmXMLWriter& xout,
xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES");
xout.StartElement("Testables");
+ for (auto test : this->Tests) {
+ xout.StartElement("TestableReference");
+ xout.BreakAttributes();
+ xout.Attribute("skipped", "NO");
+ WriteBuildableReference(xout, test, container);
+ xout.EndElement(); // TestableReference
+ }
xout.EndElement();
+ if (IsTestable()) {
+ xout.StartElement("MacroExpansion");
+ WriteBuildableReference(xout, this->Target, container);
+ xout.EndElement(); // MacroExpansion
+ }
+
xout.StartElement("AdditionalOptions");
xout.EndElement();
@@ -120,7 +124,7 @@ void cmXCodeScheme::WriteTestAction(cmXMLWriter& xout,
}
void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout,
- std::string configuration,
+ const std::string& configuration,
const std::string& container)
{
xout.StartElement("LaunchAction");
@@ -133,10 +137,52 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout,
xout.Attribute("launchStyle", "0");
xout.Attribute("useCustomWorkingDirectory", "NO");
xout.Attribute("ignoresPersistentStateOnLaunch", "NO");
- xout.Attribute("debugDocumentVersioning", "YES");
+ WriteLaunchActionBooleanAttribute(xout, "debugDocumentVersioning",
+ "XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING",
+ true);
xout.Attribute("debugServiceExtension", "internal");
xout.Attribute("allowLocationSimulation", "YES");
+ // Diagnostics tab begin
+
+ bool useAddressSanitizer = WriteLaunchActionAttribute(
+ xout, "enableAddressSanitizer",
+ "XCODE_SCHEME_ADDRESS_SANITIZER"); // not allowed with
+ // enableThreadSanitizer=YES
+ WriteLaunchActionAttribute(
+ xout, "enableASanStackUseAfterReturn",
+ "XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN");
+
+ bool useThreadSanitizer = false;
+ if (!useAddressSanitizer) {
+ useThreadSanitizer = WriteLaunchActionAttribute(
+ xout, "enableThreadSanitizer",
+ "XCODE_SCHEME_THREAD_SANITIZER"); // not allowed with
+ // enableAddressSanitizer=YES
+ }
+
+ WriteLaunchActionAttribute(xout, "stopOnEveryThreadSanitizerIssue",
+ "XCODE_SCHEME_THREAD_SANITIZER_STOP");
+
+ WriteLaunchActionAttribute(xout, "enableUBSanitizer",
+ "XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER");
+ WriteLaunchActionAttribute(
+ xout, "stopOnEveryUBSanitizerIssue",
+ "XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP");
+
+ WriteLaunchActionAttribute(
+ xout, "disableMainThreadChecker",
+ "XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER"); // negative enabled!
+ WriteLaunchActionAttribute(xout, "stopOnEveryMainThreadCheckerIssue",
+ "XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP");
+
+ if (this->Target->GetTarget()->GetPropertyAsBool(
+ "XCODE_SCHEME_DEBUG_AS_ROOT")) {
+ xout.Attribute("debugAsWhichUser", "root");
+ }
+
+ // Diagnostics tab end
+
if (IsExecutable(this->Target)) {
xout.StartElement("BuildableProductRunnable");
xout.BreakAttributes();
@@ -146,25 +192,163 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout,
xout.StartElement("MacroExpansion");
}
- xout.StartElement("BuildableReference");
- xout.BreakAttributes();
- xout.Attribute("BuildableIdentifier", "primary");
- xout.Attribute("BlueprintIdentifier", this->TargetId);
- xout.Attribute("BuildableName", this->BuildableName);
- xout.Attribute("BlueprintName", this->TargetName);
- xout.Attribute("ReferencedContainer", "container:" + container);
- xout.EndElement();
+ WriteBuildableReference(xout, this->Target, container);
xout.EndElement(); // MacroExpansion
+ // Info tab begin
+
+ if (const char* exe =
+ this->Target->GetTarget()->GetProperty("XCODE_SCHEME_EXECUTABLE")) {
+
+ xout.StartElement("PathRunnable");
+ xout.BreakAttributes();
+
+ xout.Attribute("runnableDebuggingMode", "0");
+ xout.Attribute("FilePath", exe);
+
+ xout.EndElement(); // PathRunnable
+ }
+
+ // Info tab end
+
+ // Arguments tab begin
+
+ if (const char* argList =
+ this->Target->GetTarget()->GetProperty("XCODE_SCHEME_ARGUMENTS")) {
+ std::vector<std::string> arguments = cmExpandedList(argList);
+ if (!arguments.empty()) {
+ xout.StartElement("CommandLineArguments");
+
+ for (auto const& argument : arguments) {
+ xout.StartElement("CommandLineArgument");
+ xout.BreakAttributes();
+
+ xout.Attribute("argument", argument);
+ xout.Attribute("isEnabled", "YES");
+
+ xout.EndElement(); // CommandLineArgument
+ }
+
+ xout.EndElement(); // CommandLineArguments
+ }
+ }
+
+ if (const char* envList =
+ this->Target->GetTarget()->GetProperty("XCODE_SCHEME_ENVIRONMENT")) {
+ std::vector<std::string> envs = cmExpandedList(envList);
+ if (!envs.empty()) {
+ xout.StartElement("EnvironmentVariables");
+
+ for (auto env : envs) {
+
+ xout.StartElement("EnvironmentVariable");
+ xout.BreakAttributes();
+
+ std::string envValue;
+ const auto p = env.find_first_of('=');
+ if (p != std::string::npos) {
+ envValue = env.substr(p + 1);
+ env.resize(p);
+ }
+
+ xout.Attribute("key", env);
+ xout.Attribute("value", envValue);
+ xout.Attribute("isEnabled", "YES");
+
+ xout.EndElement(); // EnvironmentVariable
+ }
+
+ xout.EndElement(); // EnvironmentVariables
+ }
+ }
+
+ // Arguments tab end
+
xout.StartElement("AdditionalOptions");
+
+ if (!useThreadSanitizer) {
+ WriteLaunchActionAdditionalOption(xout, "MallocScribble", "",
+ "XCODE_SCHEME_MALLOC_SCRIBBLE");
+ }
+
+ if (!useThreadSanitizer && !useAddressSanitizer) {
+ WriteLaunchActionAdditionalOption(xout, "MallocGuardEdges", "",
+ "XCODE_SCHEME_MALLOC_GUARD_EDGES");
+ }
+
+ if (!useThreadSanitizer && !useAddressSanitizer) {
+ WriteLaunchActionAdditionalOption(xout, "DYLD_INSERT_LIBRARIES",
+ "/usr/lib/libgmalloc.dylib",
+ "XCODE_SCHEME_GUARD_MALLOC");
+ }
+
+ WriteLaunchActionAdditionalOption(xout, "NSZombieEnabled", "YES",
+ "XCODE_SCHEME_ZOMBIE_OBJECTS");
+
+ if (!useThreadSanitizer && !useAddressSanitizer) {
+ WriteLaunchActionAdditionalOption(xout, "MallocStackLogging", "",
+ "XCODE_SCHEME_MALLOC_STACK");
+ }
+
+ WriteLaunchActionAdditionalOption(xout, "DYLD_PRINT_APIS", "",
+ "XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE");
+
+ WriteLaunchActionAdditionalOption(xout, "DYLD_PRINT_LIBRARIES", "",
+ "XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS");
+
xout.EndElement();
xout.EndElement(); // LaunchAction
}
+bool cmXCodeScheme::WriteLaunchActionAttribute(cmXMLWriter& xout,
+ const std::string& attrName,
+ const std::string& varName)
+{
+ if (Target->GetTarget()->GetPropertyAsBool(varName)) {
+ xout.Attribute(attrName.c_str(), "YES");
+ return true;
+ }
+ return false;
+}
+
+bool cmXCodeScheme::WriteLaunchActionBooleanAttribute(
+ cmXMLWriter& xout, const std::string& attrName, const std::string& varName,
+ bool defaultValue)
+{
+ auto property = Target->GetTarget()->GetProperty(varName);
+ bool isOn = (property == nullptr && defaultValue) || cmIsOn(property);
+
+ if (isOn) {
+ xout.Attribute(attrName.c_str(), "YES");
+ } else {
+ xout.Attribute(attrName.c_str(), "NO");
+ }
+ return isOn;
+}
+
+bool cmXCodeScheme::WriteLaunchActionAdditionalOption(
+ cmXMLWriter& xout, const std::string& key, const std::string& value,
+ const std::string& varName)
+{
+ if (Target->GetTarget()->GetPropertyAsBool(varName)) {
+ xout.StartElement("AdditionalOption");
+ xout.BreakAttributes();
+
+ xout.Attribute("key", key);
+ xout.Attribute("value", value);
+ xout.Attribute("isEnabled", "YES");
+
+ xout.EndElement(); // AdditionalOption
+
+ return true;
+ }
+ return false;
+}
+
void cmXCodeScheme::WriteProfileAction(cmXMLWriter& xout,
- std::string configuration)
+ const std::string& configuration)
{
xout.StartElement("ProfileAction");
xout.BreakAttributes();
@@ -172,12 +356,14 @@ void cmXCodeScheme::WriteProfileAction(cmXMLWriter& xout,
xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES");
xout.Attribute("savedToolIdentifier", "");
xout.Attribute("useCustomWorkingDirectory", "NO");
- xout.Attribute("debugDocumentVersioning", "YES");
+ WriteLaunchActionBooleanAttribute(xout, "debugDocumentVersioning",
+ "XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING",
+ true);
xout.EndElement();
}
void cmXCodeScheme::WriteAnalyzeAction(cmXMLWriter& xout,
- std::string configuration)
+ const std::string& configuration)
{
xout.StartElement("AnalyzeAction");
xout.BreakAttributes();
@@ -186,7 +372,7 @@ void cmXCodeScheme::WriteAnalyzeAction(cmXMLWriter& xout,
}
void cmXCodeScheme::WriteArchiveAction(cmXMLWriter& xout,
- std::string configuration)
+ const std::string& configuration)
{
xout.StartElement("ArchiveAction");
xout.BreakAttributes();
@@ -195,6 +381,20 @@ void cmXCodeScheme::WriteArchiveAction(cmXMLWriter& xout,
xout.EndElement();
}
+void cmXCodeScheme::WriteBuildableReference(cmXMLWriter& xout,
+ const cmXCodeObject* xcObj,
+ const std::string& container)
+{
+ xout.StartElement("BuildableReference");
+ xout.BreakAttributes();
+ xout.Attribute("BuildableIdentifier", "primary");
+ xout.Attribute("BlueprintIdentifier", xcObj->GetId());
+ xout.Attribute("BuildableName", xcObj->GetTarget()->GetFullName());
+ xout.Attribute("BlueprintName", xcObj->GetTarget()->GetName());
+ xout.Attribute("ReferencedContainer", "container:" + container);
+ xout.EndElement();
+}
+
std::string cmXCodeScheme::WriteVersionString()
{
std::ostringstream v;
@@ -207,14 +407,18 @@ std::string cmXCodeScheme::FindConfiguration(const std::string& name)
// Try to find the desired configuration by name,
// and if it's not found return first from the list
//
- if (std::find(this->ConfigList.begin(), this->ConfigList.end(), name) ==
- this->ConfigList.end() &&
- this->ConfigList.size() > 0)
+ if (!cmContains(this->ConfigList, name) && !this->ConfigList.empty()) {
return this->ConfigList[0];
+ }
return name;
}
+bool cmXCodeScheme::IsTestable() const
+{
+ return !this->Tests.empty() || IsExecutable(this->Target);
+}
+
bool cmXCodeScheme::IsExecutable(const cmXCodeObject* target)
{
cmGeneratorTarget* gt = target->GetTarget();
diff --git a/Source/cmXCodeScheme.h b/Source/cmXCodeScheme.h
index 379afed42..dff5e35e3 100644
--- a/Source/cmXCodeScheme.h
+++ b/Source/cmXCodeScheme.h
@@ -5,6 +5,8 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <vector>
+
#include "cmGlobalXCodeGenerator.h"
#include "cmSystemTools.h"
#include "cmXCodeObject.h"
@@ -16,7 +18,9 @@
class cmXCodeScheme
{
public:
- cmXCodeScheme(cmXCodeObject* xcObj,
+ using TestObjects = std::vector<const cmXCodeObject*>;
+
+ cmXCodeScheme(cmXCodeObject* xcObj, TestObjects tests,
const std::vector<std::string>& configList,
unsigned int xcVersion);
@@ -25,25 +29,45 @@ public:
private:
const cmXCodeObject* const Target;
+ const TestObjects Tests;
const std::string& TargetName;
- const std::string BuildableName;
- const std::string& TargetId;
const std::vector<std::string>& ConfigList;
const unsigned int XcodeVersion;
void WriteXCodeXCScheme(std::ostream& fout, const std::string& container);
void WriteBuildAction(cmXMLWriter& xout, const std::string& container);
- void WriteTestAction(cmXMLWriter& xout, std::string configuration);
- void WriteLaunchAction(cmXMLWriter& xout, std::string configuration,
+ void WriteTestAction(cmXMLWriter& xout, const std::string& configuration,
+ const std::string& container);
+ void WriteLaunchAction(cmXMLWriter& xout, const std::string& configuration,
const std::string& container);
- void WriteProfileAction(cmXMLWriter& xout, std::string configuration);
- void WriteAnalyzeAction(cmXMLWriter& xout, std::string configuration);
- void WriteArchiveAction(cmXMLWriter& xout, std::string configuration);
+
+ bool WriteLaunchActionAttribute(cmXMLWriter& xout,
+ const std::string& attrName,
+ const std::string& varName);
+
+ bool WriteLaunchActionBooleanAttribute(cmXMLWriter& xout,
+ const std::string& attrName,
+ const std::string& varName,
+ bool defaultValue);
+
+ bool WriteLaunchActionAdditionalOption(cmXMLWriter& xout,
+ const std::string& attrName,
+ const std::string& value,
+ const std::string& varName);
+
+ void WriteProfileAction(cmXMLWriter& xout, const std::string& configuration);
+ void WriteAnalyzeAction(cmXMLWriter& xout, const std::string& configuration);
+ void WriteArchiveAction(cmXMLWriter& xout, const std::string& configuration);
+
+ void WriteBuildableReference(cmXMLWriter& xout, const cmXCodeObject* xcObj,
+ const std::string& container);
std::string WriteVersionString();
std::string FindConfiguration(const std::string& name);
+ bool IsTestable() const;
+
static bool IsExecutable(const cmXCodeObject* target);
};
diff --git a/Source/cmXMLParser.cxx b/Source/cmXMLParser.cxx
index 18afbf370..ad5c4ba28 100644
--- a/Source/cmXMLParser.cxx
+++ b/Source/cmXMLParser.cxx
@@ -2,19 +2,21 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmXMLParser.h"
-#include "cm_expat.h"
-#include "cmsys/FStream.hxx"
-#include <ctype.h>
+#include <cctype>
+#include <cstring>
#include <iostream>
#include <sstream>
-#include <string.h>
+
+#include "cmsys/FStream.hxx"
+
+#include "cm_expat.h"
cmXMLParser::cmXMLParser()
{
- this->Parser = CM_NULLPTR;
+ this->Parser = nullptr;
this->ParseError = 0;
- this->ReportCallback = CM_NULLPTR;
- this->ReportCallbackData = CM_NULLPTR;
+ this->ReportCallback = nullptr;
+ this->ReportCallbackData = nullptr;
}
cmXMLParser::~cmXMLParser()
@@ -26,7 +28,7 @@ cmXMLParser::~cmXMLParser()
int cmXMLParser::Parse(const char* string)
{
- return (int)this->InitializeParser() &&
+ return this->InitializeParser() &&
this->ParseChunk(string, strlen(string)) && this->CleanupParser();
}
@@ -55,7 +57,7 @@ int cmXMLParser::InitializeParser()
}
// Create the expat XML parser.
- this->Parser = XML_ParserCreate(CM_NULLPTR);
+ this->Parser = XML_ParserCreate(nullptr);
XML_SetElementHandler(static_cast<XML_Parser>(this->Parser),
&cmXMLParserStartElement, &cmXMLParserEndElement);
XML_SetCharacterDataHandler(static_cast<XML_Parser>(this->Parser),
@@ -99,7 +101,7 @@ int cmXMLParser::CleanupParser()
// Clean up the parser.
XML_ParserFree(static_cast<XML_Parser>(this->Parser));
- this->Parser = CM_NULLPTR;
+ this->Parser = nullptr;
return result;
}
@@ -156,7 +158,7 @@ const char* cmXMLParser::FindAttribute(const char** atts,
}
}
}
- return CM_NULLPTR;
+ return nullptr;
}
void cmXMLParserStartElement(void* parser, const char* name, const char** atts)
@@ -186,8 +188,8 @@ void cmXMLParserCharacterDataHandler(void* parser, const char* data,
void cmXMLParser::ReportXmlParseError()
{
XML_Parser parser = static_cast<XML_Parser>(this->Parser);
- this->ReportError(XML_GetCurrentLineNumber(parser),
- XML_GetCurrentColumnNumber(parser),
+ this->ReportError(static_cast<int>(XML_GetCurrentLineNumber(parser)),
+ static_cast<int>(XML_GetCurrentColumnNumber(parser)),
XML_ErrorString(XML_GetErrorCode(parser)));
}
diff --git a/Source/cmXMLParser.h b/Source/cmXMLParser.h
index 98ba04956..1bc8d6469 100644
--- a/Source/cmXMLParser.h
+++ b/Source/cmXMLParser.h
@@ -42,7 +42,7 @@ public:
virtual int ParseChunk(const char* inputString,
std::string::size_type length);
virtual int CleanupParser();
- typedef void (*ReportFunction)(int, const char*, void*);
+ using ReportFunction = void (*)(int, const char*, void*);
void SetErrorCallback(ReportFunction f, void* d)
{
this->ReportCallback = f;
diff --git a/Source/cmXMLSafe.cxx b/Source/cmXMLSafe.cxx
index d9bdc023b..8cd5f6e0d 100644
--- a/Source/cmXMLSafe.cxx
+++ b/Source/cmXMLSafe.cxx
@@ -2,11 +2,11 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmXMLSafe.h"
-#include "cm_utf8.h"
-
+#include <cstdio>
+#include <cstring>
#include <sstream>
-#include <stdio.h>
-#include <string.h>
+
+#include "cm_utf8.h"
cmXMLSafe::cmXMLSafe(const char* s)
: Data(s)
diff --git a/Source/cmXMLWriter.cxx b/Source/cmXMLWriter.cxx
index 3cbc70dbd..0811bd029 100644
--- a/Source/cmXMLWriter.cxx
+++ b/Source/cmXMLWriter.cxx
@@ -2,13 +2,15 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmXMLWriter.h"
-#include "cmsys/FStream.hxx"
#include <cassert>
+#include "cmsys/FStream.hxx"
+
cmXMLWriter::cmXMLWriter(std::ostream& output, std::size_t level)
: Output(output)
, IndentationElement(1, '\t')
, Level(level)
+ , Indent(0)
, ElementOpen(false)
, BreakAttrib(false)
, IsContent(false)
@@ -17,37 +19,39 @@ cmXMLWriter::cmXMLWriter(std::ostream& output, std::size_t level)
cmXMLWriter::~cmXMLWriter()
{
- assert(this->Elements.empty());
+ assert(this->Indent == 0);
}
void cmXMLWriter::StartDocument(const char* encoding)
{
- this->Output << "<?xml version=\"1.0\" encoding=\"" << encoding << "\"?>";
+ this->Output << R"(<?xml version="1.0" encoding=")" << encoding << "\"?>";
}
void cmXMLWriter::EndDocument()
{
- assert(this->Elements.empty());
+ assert(this->Indent == 0);
this->Output << '\n';
}
void cmXMLWriter::StartElement(std::string const& name)
{
this->CloseStartElement();
- this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->ConditionalLineBreak(!this->IsContent);
this->Output << '<' << name;
this->Elements.push(name);
+ ++this->Indent;
this->ElementOpen = true;
this->BreakAttrib = false;
}
void cmXMLWriter::EndElement()
{
- assert(!this->Elements.empty());
+ assert(this->Indent > 0);
+ --this->Indent;
if (this->ElementOpen) {
this->Output << "/>";
} else {
- this->ConditionalLineBreak(!this->IsContent, this->Elements.size() - 1);
+ this->ConditionalLineBreak(!this->IsContent);
this->IsContent = false;
this->Output << "</" << this->Elements.top() << '>';
}
@@ -58,7 +62,7 @@ void cmXMLWriter::EndElement()
void cmXMLWriter::Element(const char* name)
{
this->CloseStartElement();
- this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->ConditionalLineBreak(!this->IsContent);
this->Output << '<' << name << "/>";
}
@@ -70,7 +74,7 @@ void cmXMLWriter::BreakAttributes()
void cmXMLWriter::Comment(const char* comment)
{
this->CloseStartElement();
- this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->ConditionalLineBreak(!this->IsContent);
this->Output << "<!-- " << comment << " -->";
}
@@ -83,14 +87,14 @@ void cmXMLWriter::CData(std::string const& data)
void cmXMLWriter::Doctype(const char* doctype)
{
this->CloseStartElement();
- this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->ConditionalLineBreak(!this->IsContent);
this->Output << "<!DOCTYPE " << doctype << ">";
}
void cmXMLWriter::ProcessingInstruction(const char* target, const char* data)
{
this->CloseStartElement();
- this->ConditionalLineBreak(!this->IsContent, this->Elements.size());
+ this->ConditionalLineBreak(!this->IsContent);
this->Output << "<?" << target << ' ' << data << "?>";
}
@@ -106,11 +110,11 @@ void cmXMLWriter::SetIndentationElement(std::string const& element)
this->IndentationElement = element;
}
-void cmXMLWriter::ConditionalLineBreak(bool condition, std::size_t indent)
+void cmXMLWriter::ConditionalLineBreak(bool condition)
{
if (condition) {
this->Output << '\n';
- for (std::size_t i = 0; i < indent + this->Level; ++i) {
+ for (std::size_t i = 0; i < this->Indent + this->Level; ++i) {
this->Output << this->IndentationElement;
}
}
@@ -119,7 +123,7 @@ void cmXMLWriter::ConditionalLineBreak(bool condition, std::size_t indent)
void cmXMLWriter::PreAttribute()
{
assert(this->ElementOpen);
- this->ConditionalLineBreak(this->BreakAttrib, this->Elements.size());
+ this->ConditionalLineBreak(this->BreakAttrib);
if (!this->BreakAttrib) {
this->Output << ' ';
}
@@ -134,7 +138,7 @@ void cmXMLWriter::PreContent()
void cmXMLWriter::CloseStartElement()
{
if (this->ElementOpen) {
- this->ConditionalLineBreak(this->BreakAttrib, this->Elements.size());
+ this->ConditionalLineBreak(this->BreakAttrib);
this->Output << '>';
this->ElementOpen = false;
}
diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h
index ed76a88c7..bc445aa5b 100644
--- a/Source/cmXMLWriter.h
+++ b/Source/cmXMLWriter.h
@@ -3,23 +3,27 @@
#ifndef cmXMLWiter_h
#define cmXMLWiter_h
-#include "cmConfigure.h"
-
-#include "cmXMLSafe.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+#include <chrono>
+#include <cstddef>
+#include <ctime>
#include <ostream>
#include <stack>
#include <string>
#include <vector>
+#include "cmXMLSafe.h"
+
class cmXMLWriter
{
- CM_DISABLE_COPY(cmXMLWriter)
-
public:
cmXMLWriter(std::ostream& output, std::size_t level = 0);
~cmXMLWriter();
+ cmXMLWriter(cmXMLWriter const&) = delete;
+ cmXMLWriter& operator=(cmXMLWriter const&) = delete;
+
void StartDocument(const char* encoding = "UTF-8");
void EndDocument();
@@ -65,7 +69,7 @@ public:
void SetIndentationElement(std::string const& element);
private:
- void ConditionalLineBreak(bool condition, std::size_t indent);
+ void ConditionalLineBreak(bool condition);
void PreAttribute();
void PreContent();
@@ -73,14 +77,11 @@ private:
void CloseStartElement();
private:
- static cmXMLSafe SafeAttribute(const char* value)
- {
- return cmXMLSafe(value);
- }
+ static cmXMLSafe SafeAttribute(const char* value) { return { value }; }
static cmXMLSafe SafeAttribute(std::string const& value)
{
- return cmXMLSafe(value);
+ return { value };
}
template <typename T>
@@ -99,6 +100,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)
{
@@ -107,12 +124,77 @@ private:
private:
std::ostream& Output;
- std::stack<std::string, std::vector<std::string> > Elements;
+ std::stack<std::string, std::vector<std::string>> Elements;
std::string IndentationElement;
std::size_t Level;
+ std::size_t Indent;
bool ElementOpen;
bool BreakAttrib;
bool IsContent;
};
+class cmXMLElement; // IWYU pragma: keep
+
+class cmXMLDocument
+{
+public:
+ cmXMLDocument(cmXMLWriter& xml)
+ : xmlwr(xml)
+ {
+ xmlwr.StartDocument();
+ }
+ ~cmXMLDocument() { xmlwr.EndDocument(); }
+ cmXMLDocument(const cmXMLDocument&) = delete;
+ cmXMLDocument& operator=(const cmXMLDocument&) = delete;
+
+private:
+ friend class cmXMLElement;
+ cmXMLWriter& xmlwr;
+};
+
+class cmXMLElement
+{
+public:
+ cmXMLElement(cmXMLWriter& xml, const char* tag)
+ : xmlwr(xml)
+ {
+ xmlwr.StartElement(tag);
+ }
+ cmXMLElement(cmXMLElement& par, const char* tag)
+ : xmlwr(par.xmlwr)
+ {
+ xmlwr.StartElement(tag);
+ }
+ cmXMLElement(cmXMLDocument& doc, const char* tag)
+ : xmlwr(doc.xmlwr)
+ {
+ xmlwr.StartElement(tag);
+ }
+ ~cmXMLElement() { xmlwr.EndElement(); }
+
+ cmXMLElement(const cmXMLElement&) = delete;
+ cmXMLElement& operator=(const cmXMLElement&) = delete;
+
+ template <typename T>
+ cmXMLElement& Attribute(const char* name, T const& value)
+ {
+ xmlwr.Attribute(name, value);
+ return *this;
+ }
+ template <typename T>
+ void Content(T const& content)
+ {
+ xmlwr.Content(content);
+ }
+ template <typename T>
+ void Element(std::string const& name, T const& value)
+ {
+ xmlwr.Element(name, value);
+ }
+ void Comment(const char* comment) { xmlwr.Comment(comment); }
+
+private:
+ cmXMLWriter& xmlwr;
+};
+
#endif
diff --git a/Source/cm_auto_ptr.hxx b/Source/cm_auto_ptr.hxx
deleted file mode 100644
index 773602af9..000000000
--- a/Source/cm_auto_ptr.hxx
+++ /dev/null
@@ -1,220 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef CM_AUTO_PTR_HXX
-#define CM_AUTO_PTR_HXX
-
-#include "cmConfigure.h"
-
-#ifdef CMake_HAVE_CXX_AUTO_PTR
-
-#include <memory>
-#define CM_AUTO_PTR std::auto_ptr
-
-#else
-
-#define CM_AUTO_PTR cm::auto_ptr
-
-// The HP compiler cannot handle the conversions necessary to use
-// auto_ptr_ref to pass an auto_ptr returned from one function
-// directly to another function as in use_auto_ptr(get_auto_ptr()).
-// We instead use const_cast to achieve the syntax on those platforms.
-// We do not use const_cast on other platforms to maintain the C++
-// standard design and guarantee that if an auto_ptr is bound
-// to a reference-to-const then ownership will be maintained.
-#if defined(__HP_aCC)
-#define cm_AUTO_PTR_REF 0
-#define cm_AUTO_PTR_CONST const
-#define cm_AUTO_PTR_CAST(a) cast(a)
-#else
-#define cm_AUTO_PTR_REF 1
-#define cm_AUTO_PTR_CONST
-#define cm_AUTO_PTR_CAST(a) a
-#endif
-
-// In C++11, clang will warn about using dynamic exception specifications
-// as they are deprecated. But as this class is trying to faithfully
-// mimic std::auto_ptr, we want to keep the 'throw()' decorations below.
-// So we suppress the warning.
-#if defined(__clang__) && defined(__has_warning)
-#if __has_warning("-Wdeprecated")
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated"
-#endif
-#endif
-
-namespace cm {
-
-template <class X>
-class auto_ptr;
-
-#if cm_AUTO_PTR_REF
-namespace detail {
-// The auto_ptr_ref template is supposed to be a private member of
-// auto_ptr but Borland 5.8 cannot handle it. Instead put it in
-// a private namespace.
-template <class Y>
-struct auto_ptr_ref
-{
- Y* p_;
-
- // The extra constructor argument prevents implicit conversion to
- // auto_ptr_ref from auto_ptr through the constructor. Normally
- // this should be done with the explicit keyword but Borland 5.x
- // generates code in the conversion operator to call itself
- // infinately.
- auto_ptr_ref(Y* p, int)
- : p_(p)
- {
- }
-};
-}
-#endif
-
-/** C++98 Standard Section 20.4.5 - Template class auto_ptr. */
-template <class X>
-class auto_ptr
-{
-#if !cm_AUTO_PTR_REF
- template <typename Y>
- static inline auto_ptr<Y>& cast(auto_ptr<Y> const& a)
- {
- return const_cast<auto_ptr<Y>&>(a);
- }
-#endif
-
- /** The pointer to the object held. */
- X* x_;
-
-public:
- /** The type of object held by the auto_ptr. */
- typedef X element_type;
-
- /** Construct from an auto_ptr holding a compatible object. This
- transfers ownership to the newly constructed auto_ptr. */
- template <class Y>
- auto_ptr(auto_ptr<Y> cm_AUTO_PTR_CONST& a) throw()
- : x_(cm_AUTO_PTR_CAST(a).release())
- {
- }
-
- /** Assign from an auto_ptr holding a compatible object. This
- transfers ownership to the left-hand-side of the assignment. */
- template <class Y>
- auto_ptr& operator=(auto_ptr<Y> cm_AUTO_PTR_CONST& a) throw() // NOLINT
- {
- this->reset(cm_AUTO_PTR_CAST(a).release());
- return *this; // NOLINT
- }
-
- /**
- * Explicitly construct from a raw pointer. This is typically
- * called with the result of operator new. For example:
- *
- * auto_ptr<X> ptr(new X());
- */
- explicit auto_ptr(X* p = CM_NULLPTR) throw()
- : x_(p)
- {
- }
-
- /** Construct from another auto_ptr holding an object of the same
- type. This transfers ownership to the newly constructed
- auto_ptr. */
- auto_ptr(auto_ptr cm_AUTO_PTR_CONST& a) throw()
- : x_(cm_AUTO_PTR_CAST(a).release())
- {
- }
-
- /** Assign from another auto_ptr holding an object of the same type.
- This transfers ownership to the newly constructed auto_ptr. */
- auto_ptr& operator=(auto_ptr cm_AUTO_PTR_CONST& a) throw() // NOLINT
- {
- this->reset(cm_AUTO_PTR_CAST(a).release());
- return *this; // NOLINT
- }
-
- /** Destruct and delete the object held. */
- ~auto_ptr() throw()
- {
- // Assume object destructor is nothrow.
- delete this->x_;
- }
-
- /** Dereference and return a reference to the object held. */
- X& operator*() const throw() { return *this->x_; }
-
- /** Return a pointer to the object held. */
- X* operator->() const throw() { return this->x_; }
-
- /** Return a pointer to the object held. */
- X* get() const throw() { return this->x_; }
-
- /** Return a pointer to the object held and reset to hold no object.
- This transfers ownership to the caller. */
- X* release() throw()
- {
- X* x = this->x_;
- this->x_ = CM_NULLPTR;
- return x;
- }
-
- /** Assume ownership of the given object. The object previously
- held is deleted. */
- void reset(X* p = 0) throw()
- {
- if (this->x_ != p) {
- // Assume object destructor is nothrow.
- delete this->x_;
- this->x_ = p;
- }
- }
-
- /** Convert to an auto_ptr holding an object of a compatible type.
- This transfers ownership to the returned auto_ptr. */
- template <class Y>
- operator auto_ptr<Y>() throw()
- {
- return auto_ptr<Y>(this->release());
- }
-
-#if cm_AUTO_PTR_REF
- /** Construct from an auto_ptr_ref. This is used when the
- constructor argument is a call to a function returning an
- auto_ptr. */
- auto_ptr(detail::auto_ptr_ref<X> r) throw()
- : x_(r.p_)
- {
- }
-
- /** Assign from an auto_ptr_ref. This is used when a function
- returning an auto_ptr is passed on the right-hand-side of an
- assignment. */
- auto_ptr& operator=(detail::auto_ptr_ref<X> r) throw()
- {
- this->reset(r.p_);
- return *this; // NOLINT
- }
-
- /** Convert to an auto_ptr_ref. This is used when a function
- returning an auto_ptr is the argument to the constructor of
- another auto_ptr. */
- template <class Y>
- operator detail::auto_ptr_ref<Y>() throw()
- {
- return detail::auto_ptr_ref<Y>(this->release(), 1);
- }
-#endif
-};
-
-} // namespace cm
-
-// Undo warning suppression.
-#if defined(__clang__) && defined(__has_warning)
-#if __has_warning("-Wdeprecated")
-#pragma clang diagnostic pop
-#endif
-#endif
-
-#endif
-
-#endif
diff --git a/Source/cm_codecvt.cxx b/Source/cm_codecvt.cxx
index cf55741a7..122e02283 100644
--- a/Source/cm_codecvt.cxx
+++ b/Source/cm_codecvt.cxx
@@ -3,11 +3,12 @@
#include "cm_codecvt.hxx"
#if defined(_WIN32)
-#include <assert.h>
-#include <string.h>
-#include <windows.h>
-#undef max
-#include "cmsys/Encoding.hxx"
+# include <windows.h>
+
+# include <assert.h>
+# include <string.h>
+# undef max
+# include "cmsys/Encoding.hxx"
#endif
#if defined(_WIN32)
@@ -38,12 +39,12 @@ codecvt::codecvt(Encoding e)
}
}
-codecvt::~codecvt(){};
+codecvt::~codecvt() = default;
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 +123,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 +144,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 +236,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_codecvt.hxx b/Source/cm_codecvt.hxx
index 30c6d5407..b2cb9e6a3 100644
--- a/Source/cm_codecvt.hxx
+++ b/Source/cm_codecvt.hxx
@@ -3,10 +3,10 @@
#ifndef cm_codecvt_hxx
#define cm_codecvt_hxx
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+#include <cwchar>
#include <locale>
-#include <wchar.h>
class codecvt : public std::codecvt<char, char, mbstate_t>
{
@@ -18,20 +18,20 @@ public:
ANSI
};
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
codecvt(Encoding e);
protected:
- ~codecvt() CM_OVERRIDE;
- bool do_always_noconv() const throw() CM_OVERRIDE;
+ ~codecvt() override;
+ bool do_always_noconv() const throw() override;
result do_out(mbstate_t& state, const char* from, const char* from_end,
const char*& from_next, char* to, char* to_end,
- char*& to_next) const CM_OVERRIDE;
+ char*& to_next) const override;
result do_unshift(mbstate_t& state, char* to, char*,
- char*& to_next) const CM_OVERRIDE;
- int do_max_length() const throw() CM_OVERRIDE;
- int do_encoding() const throw() CM_OVERRIDE;
+ char*& to_next) const override;
+ int do_max_length() const throw() override;
+ int do_encoding() const throw() override;
private:
// The mbstate_t argument to do_out and do_unshift is responsible
@@ -52,13 +52,13 @@ private:
};
bool m_noconv;
-#if defined(_WIN32)
+# if defined(_WIN32)
unsigned int m_codepage;
result Decode(mbstate_t& state, int need, const char*& from_next,
char*& to_next, char* to_end) const;
result DecodePartial(mbstate_t& state, char*& to_next, char* to_end) const;
void BufferPartial(mbstate_t& state, int need, const char*& from_next) const;
-#endif
+# endif
#endif
};
diff --git a/Source/cm_get_date.h b/Source/cm_get_date.h
index 6acf8dea3..38a690ee0 100644
--- a/Source/cm_get_date.h
+++ b/Source/cm_get_date.h
@@ -3,7 +3,7 @@
#ifndef cm_get_date_h
#define cm_get_date_h
-#include <time.h>
+#include <time.h> /* NOLINT(modernize-deprecated-headers) */
#ifdef __cplusplus
extern "C" {
diff --git a/Source/cm_static_string_view.hxx b/Source/cm_static_string_view.hxx
new file mode 100644
index 000000000..708ac9579
--- /dev/null
+++ b/Source/cm_static_string_view.hxx
@@ -0,0 +1,41 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cm_static_string_view_hxx
+#define cm_static_string_view_hxx
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cstddef>
+
+#include <cm/string_view>
+
+namespace cm {
+
+/** A string_view that only binds to static storage.
+ *
+ * This is used together with the `""_s` user-defined literal operator
+ * to construct a type-safe abstraction of a string_view that only views
+ * statically allocated strings. These strings are const and available
+ * for the entire lifetime of the program.
+ */
+class static_string_view : public string_view
+{
+ static_string_view(string_view v)
+ : string_view(v)
+ {
+ }
+
+ friend static_string_view operator"" _s(const char* data, size_t size);
+};
+
+/** Create a static_string_view using `""_s` literal syntax. */
+inline static_string_view operator"" _s(const char* data, size_t size)
+{
+ return string_view(data, size);
+}
+
+} // namespace cm
+
+using cm::operator"" _s;
+
+#endif
diff --git a/Source/cm_sys_stat.h b/Source/cm_sys_stat.h
index 26e4baa03..919428634 100644
--- a/Source/cm_sys_stat.h
+++ b/Source/cm_sys_stat.h
@@ -4,11 +4,11 @@
#define cm_sys_stat_h
#if defined(_MSC_VER)
-typedef unsigned short mode_t;
+using mode_t = unsigned short;
#endif
#include <sys/types.h>
// include sys/stat.h after sys/types.h
-#include <sys/stat.h>
+#include <sys/stat.h> // IWYU pragma: export
#endif
diff --git a/Source/cm_unordered_map.hxx b/Source/cm_unordered_map.hxx
deleted file mode 100644
index bf3890314..000000000
--- a/Source/cm_unordered_map.hxx
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef CM_UNORDERED_MAP_HXX
-#define CM_UNORDERED_MAP_HXX
-
-#include "cmConfigure.h"
-
-#if defined(CMake_HAVE_CXX_UNORDERED_MAP)
-
-#include <unordered_map>
-#define CM_UNORDERED_MAP std::unordered_map
-
-#elif defined(CMAKE_BUILD_WITH_CMAKE)
-
-#include "cmsys/hash_map.hxx"
-#define CM_UNORDERED_MAP cmsys::hash_map
-
-#else
-
-#include <map>
-#define CM_UNORDERED_MAP std::map
-
-#endif
-
-#endif
diff --git a/Source/cm_unordered_set.hxx b/Source/cm_unordered_set.hxx
deleted file mode 100644
index dd1a9a115..000000000
--- a/Source/cm_unordered_set.hxx
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef CM_UNORDERED_SET_HXX
-#define CM_UNORDERED_SET_HXX
-
-#include "cmConfigure.h"
-
-#if defined(CMake_HAVE_CXX_UNORDERED_SET)
-
-#include <unordered_set>
-#define CM_UNORDERED_SET std::unordered_set
-
-#elif defined(CMAKE_BUILD_WITH_CMAKE)
-
-#include "cmsys/hash_set.hxx"
-#define CM_UNORDERED_SET cmsys::hash_set
-
-#else
-
-#include <set>
-#define CM_UNORDERED_SET std::set
-
-#endif
-
-#endif
diff --git a/Source/cm_utf8.c b/Source/cm_utf8.c
index 52af4a6f4..62e7e8c8c 100644
--- a/Source/cm_utf8.c
+++ b/Source/cm_utf8.c
@@ -2,6 +2,8 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cm_utf8.h"
+#include <string.h>
+
/*
RFC 3629
07-bit: 0xxxxxxx
@@ -71,7 +73,34 @@ const char* cm_utf8_decode_character(const char* first, const char* last,
return 0;
}
+ /* UTF-16 surrogate halves. */
+ if (0xD800 <= uc && uc <= 0xDFFF) {
+ return 0;
+ }
+
+ /* Invalid codepoints. */
+ if (0x10FFFF < uc) {
+ return 0;
+ }
+
*pc = uc;
return first;
}
}
+
+int cm_utf8_is_valid(const char* s)
+{
+ if (!s) {
+ return 0;
+ }
+
+ const char* last = s + strlen(s);
+ const char* pos = s;
+ unsigned int pc;
+
+ while (pos != last && (pos = cm_utf8_decode_character(pos, last, &pc))) {
+ /* Nothing to do. */
+ }
+
+ return pos == last;
+}
diff --git a/Source/cm_utf8.h b/Source/cm_utf8.h
index fcb43e0e4..27dc5591f 100644
--- a/Source/cm_utf8.h
+++ b/Source/cm_utf8.h
@@ -13,6 +13,10 @@ extern "C" {
const char* cm_utf8_decode_character(const char* first, const char* last,
unsigned int* pc);
+/** Returns whether a C string is a sequence of valid UTF-8 encoded Unicode
+ codepoints. Returns non-zero on success. */
+int cm_utf8_is_valid(const char* s);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 689439378..f63a26400 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -2,13 +2,22 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmake.h"
+#include <cm/memory>
+#include <cm/string_view>
+#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
+# include <cm/iterator>
+#endif
+
+#include "cm_sys_stat.h"
+
#include "cmAlgorithms.h"
#include "cmCommands.h"
#include "cmDocumentation.h"
#include "cmDocumentationEntry.h"
#include "cmDocumentationFormatter.h"
+#include "cmDuration.h"
#include "cmExternalMakefileProjectGenerator.h"
-#include "cmFileTimeComparison.h"
+#include "cmFileTimeCache.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalGeneratorFactory.h"
@@ -18,140 +27,128 @@
#include "cmMessenger.h"
#include "cmState.h"
#include "cmStateDirectory.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetLinkLibraryType.h"
#include "cmUtils.hxx"
#include "cmVersionConfig.h"
#include "cmWorkingDirectory.h"
-#include "cm_auto_ptr.hxx"
-#include "cm_sys_stat.h"
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cm_jsoncpp_writer.h"
+#if !defined(CMAKE_BOOTSTRAP)
+# include <unordered_map>
-#include "cmGraphVizWriter.h"
-#include "cmVariableWatch.h"
-#include "cm_unordered_map.hxx"
-#endif
+# include "cm_jsoncpp_writer.h"
-// 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
+# include "cmFileAPI.h"
+# include "cmGraphVizWriter.h"
+# include "cmVariableWatch.h"
#endif
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#define CMAKE_USE_ECLIPSE
+#if !defined(CMAKE_BOOTSTRAP)
+# define CMAKE_USE_ECLIPSE
#endif
-#if defined(__MINGW32__) && !defined(CMAKE_BUILD_WITH_CMAKE)
-#define CMAKE_BOOT_MINGW
+#if defined(__MINGW32__) && defined(CMAKE_BOOTSTRAP)
+# define CMAKE_BOOT_MINGW
#endif
// include the generator
#if defined(_WIN32) && !defined(__CYGWIN__)
-#if !defined(CMAKE_BOOT_MINGW)
-#include "cmGlobalBorlandMakefileGenerator.h"
-#include "cmGlobalGhsMultiGenerator.h"
-#include "cmGlobalJOMMakefileGenerator.h"
-#include "cmGlobalNMakeMakefileGenerator.h"
-#include "cmGlobalVisualStudio10Generator.h"
-#include "cmGlobalVisualStudio11Generator.h"
-#include "cmGlobalVisualStudio12Generator.h"
-#include "cmGlobalVisualStudio14Generator.h"
-#include "cmGlobalVisualStudio15Generator.h"
-#include "cmGlobalVisualStudio8Generator.h"
-#include "cmGlobalVisualStudio9Generator.h"
-#include "cmVSSetupHelper.h"
-
-#define CMAKE_HAVE_VS_GENERATORS
-#endif
-#include "cmGlobalMSYSMakefileGenerator.h"
-#include "cmGlobalMinGWMakefileGenerator.h"
+# if !defined(CMAKE_BOOT_MINGW)
+# include "cmGlobalBorlandMakefileGenerator.h"
+# include "cmGlobalJOMMakefileGenerator.h"
+# include "cmGlobalNMakeMakefileGenerator.h"
+# include "cmGlobalVisualStudio10Generator.h"
+# include "cmGlobalVisualStudio11Generator.h"
+# include "cmGlobalVisualStudio12Generator.h"
+# include "cmGlobalVisualStudio14Generator.h"
+# include "cmGlobalVisualStudio9Generator.h"
+# include "cmGlobalVisualStudioVersionedGenerator.h"
+# include "cmVSSetupHelper.h"
+
+# define CMAKE_HAVE_VS_GENERATORS
+# endif
+# include "cmGlobalMSYSMakefileGenerator.h"
+# include "cmGlobalMinGWMakefileGenerator.h"
#else
#endif
#if defined(CMAKE_USE_WMAKE)
-#include "cmGlobalWatcomWMakeGenerator.h"
+# include "cmGlobalWatcomWMakeGenerator.h"
#endif
#include "cmGlobalUnixMakefileGenerator3.h"
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmGlobalNinjaGenerator.h"
+#if !defined(CMAKE_BOOTSTRAP)
+# include "cmGlobalNinjaGenerator.h"
#endif
#include "cmExtraCodeLiteGenerator.h"
#if !defined(CMAKE_BOOT_MINGW)
-#include "cmExtraCodeBlocksGenerator.h"
+# include "cmExtraCodeBlocksGenerator.h"
#endif
#include "cmExtraKateGenerator.h"
#include "cmExtraSublimeTextGenerator.h"
-#ifdef CMAKE_USE_KDEVELOP
-#include "cmGlobalKdevelopGenerator.h"
+#ifdef CMAKE_USE_ECLIPSE
+# include "cmExtraEclipseCDT4Generator.h"
#endif
-#ifdef CMAKE_USE_ECLIPSE
-#include "cmExtraEclipseCDT4Generator.h"
+#if defined(__linux__) || defined(_WIN32)
+# include "cmGlobalGhsMultiGenerator.h"
#endif
#if defined(__APPLE__)
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmGlobalXCodeGenerator.h"
+# if !defined(CMAKE_BOOTSTRAP)
+# include "cmGlobalXCodeGenerator.h"
-#define CMAKE_USE_XCODE 1
-#endif
-#include <sys/resource.h>
-#include <sys/time.h>
+# define CMAKE_USE_XCODE 1
+# endif
+# include <sys/resource.h>
+# include <sys/time.h>
#endif
-#include "cmsys/FStream.hxx"
-#include "cmsys/Glob.hxx"
-#include "cmsys/RegularExpression.hxx"
#include <algorithm>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <initializer_list>
#include <iostream>
#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <utility>
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/RegularExpression.hxx"
+
namespace {
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-typedef CM_UNORDERED_MAP<std::string, Json::Value> JsonValueMapType;
+#if !defined(CMAKE_BOOTSTRAP)
+using JsonValueMapType = std::unordered_map<std::string, Json::Value>;
#endif
} // namespace
-static bool cmakeCheckStampFile(const char* stampName, bool verbose = true);
-static bool cmakeCheckStampList(const char* stampList, bool verbose = true);
+static bool cmakeCheckStampFile(const std::string& stampName);
+static bool cmakeCheckStampList(const std::string& stampList);
-void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/,
- void* ctx, const char* /*unused*/,
- const cmMakefile* /*unused*/)
+static void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/,
+ void* ctx, const char* /*unused*/,
+ const cmMakefile* /*unused*/)
{
cmake* cm = reinterpret_cast<cmake*>(ctx);
cm->MarkCliAsUsed(variable);
}
-cmake::cmake(Role role)
+cmake::cmake(Role role, cmState::Mode mode)
+ : FileTimeCache(cm::make_unique<cmFileTimeCache>())
+#ifndef CMAKE_BOOTSTRAP
+ , VariableWatch(cm::make_unique<cmVariableWatch>())
+#endif
+ , State(cm::make_unique<cmState>())
+ , Messenger(cm::make_unique<cmMessenger>())
{
- this->Trace = false;
- this->TraceExpand = false;
- this->WarnUninitialized = false;
- this->WarnUnused = false;
- this->WarnUnusedCli = true;
- this->CheckSystemVars = false;
- this->DebugOutput = false;
- this->DebugTryCompile = false;
- this->ClearBuildSystem = false;
- this->FileComparison = new cmFileTimeComparison;
-
- this->State = new cmState;
+ this->TraceFile.close();
+ this->State->SetMode(mode);
this->CurrentSnapshot = this->State->CreateBaseSnapshot();
- this->Messenger = new cmMessenger(this->State);
#ifdef __APPLE__
struct rlimit rlp;
@@ -163,15 +160,6 @@ cmake::cmake(Role role)
}
#endif
- this->GlobalGenerator = CM_NULLPTR;
- this->ProgressCallback = CM_NULLPTR;
- this->ProgressCallbackClientData = CM_NULLPTR;
- this->CurrentWorkingMode = NORMAL_MODE;
-
-#ifdef CMAKE_BUILD_WITH_CMAKE
- this->VariableWatch = new cmVariableWatch;
-#endif
-
this->AddDefaultGenerators();
this->AddDefaultExtraGenerators();
if (role == RoleScript || role == RoleProject) {
@@ -181,54 +169,50 @@ cmake::cmake(Role role)
this->AddProjectCommands();
}
+ if (mode == cmState::Project) {
+ this->LoadEnvironmentPresets();
+ }
+
// Make sure we can capture the build tool output.
cmSystemTools::EnableVSConsoleOutput();
- // Set up a list of source and header extensions
- // these are used to find files when the extension
- // is not given
- // The "c" extension MUST precede the "C" extension.
- this->SourceFileExtensions.push_back("c");
- this->SourceFileExtensions.push_back("C");
-
- this->SourceFileExtensions.push_back("c++");
- this->SourceFileExtensions.push_back("cc");
- this->SourceFileExtensions.push_back("cpp");
- this->SourceFileExtensions.push_back("cxx");
- this->SourceFileExtensions.push_back("m");
- this->SourceFileExtensions.push_back("M");
- this->SourceFileExtensions.push_back("mm");
-
- this->HeaderFileExtensions.push_back("h");
- this->HeaderFileExtensions.push_back("hh");
- this->HeaderFileExtensions.push_back("h++");
- this->HeaderFileExtensions.push_back("hm");
- this->HeaderFileExtensions.push_back("hpp");
- this->HeaderFileExtensions.push_back("hxx");
- this->HeaderFileExtensions.push_back("in");
- this->HeaderFileExtensions.push_back("txx");
+ // Set up a list of source and header extensions.
+ // These are used to find files when the extension is not given.
+ {
+ auto setupExts = [](FileExtensions& exts,
+ std::initializer_list<cm::string_view> extList) {
+ // Fill ordered vector
+ exts.ordered.reserve(extList.size());
+ for (cm::string_view ext : extList) {
+ exts.ordered.emplace_back(ext);
+ };
+ // Fill unordered set
+ exts.unordered.insert(exts.ordered.begin(), exts.ordered.end());
+ };
+
+ // The "c" extension MUST precede the "C" extension.
+ setupExts(this->SourceFileExtensions,
+ { "c", "C", "c++", "cc", "cpp", "cxx", "cu", "m", "M", "mm" });
+ setupExts(this->HeaderFileExtensions,
+ { "h", "hh", "h++", "hm", "hpp", "hxx", "in", "txx" });
+ setupExts(this->CudaFileExtensions, { "cu" });
+ setupExts(this->FortranFileExtensions,
+ { "f", "F", "for", "f77", "f90", "f95", "f03" });
+ }
}
cmake::~cmake()
{
- delete this->State;
- delete this->Messenger;
if (this->GlobalGenerator) {
delete this->GlobalGenerator;
- this->GlobalGenerator = CM_NULLPTR;
+ this->GlobalGenerator = nullptr;
}
cmDeleteAll(this->Generators);
-#ifdef CMAKE_BUILD_WITH_CMAKE
- delete this->VariableWatch;
-#endif
- delete this->FileComparison;
}
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-Json::Value cmake::ReportCapabilitiesJson(bool haveServerMode) const
+#if !defined(CMAKE_BOOTSTRAP)
+Json::Value cmake::ReportVersionJson() const
{
- Json::Value obj = Json::objectValue;
- // Version information:
Json::Value version = Json::objectValue;
version["string"] = CMake_VERSION;
version["major"] = CMake_VERSION_MAJOR;
@@ -236,53 +220,58 @@ Json::Value cmake::ReportCapabilitiesJson(bool haveServerMode) const
version["suffix"] = CMake_VERSION_SUFFIX;
version["isDirty"] = (CMake_VERSION_IS_DIRTY == 1);
version["patch"] = CMake_VERSION_PATCH;
+ return version;
+}
- obj["version"] = version;
+Json::Value cmake::ReportCapabilitiesJson() const
+{
+ Json::Value obj = Json::objectValue;
+
+ // Version information:
+ obj["version"] = this->ReportVersionJson();
// Generators:
std::vector<cmake::GeneratorInfo> generatorInfoList;
this->GetRegisteredGenerators(generatorInfoList);
JsonValueMapType generatorMap;
- for (std::vector<cmake::GeneratorInfo>::const_iterator i =
- generatorInfoList.begin();
- i != generatorInfoList.end(); ++i) {
- if (i->isAlias) { // skip aliases, they are there for compatibility reasons
+ for (cmake::GeneratorInfo const& gi : generatorInfoList) {
+ if (gi.isAlias) { // skip aliases, they are there for compatibility reasons
// only
continue;
}
- if (i->extraName.empty()) {
+ if (gi.extraName.empty()) {
Json::Value gen = Json::objectValue;
- gen["name"] = i->name;
- gen["toolsetSupport"] = i->supportsToolset;
- gen["platformSupport"] = i->supportsPlatform;
+ gen["name"] = gi.name;
+ gen["toolsetSupport"] = gi.supportsToolset;
+ gen["platformSupport"] = gi.supportsPlatform;
gen["extraGenerators"] = Json::arrayValue;
- generatorMap[i->name] = gen;
+ generatorMap[gi.name] = gen;
} else {
- Json::Value& gen = generatorMap[i->baseName];
- gen["extraGenerators"].append(i->extraName);
+ Json::Value& gen = generatorMap[gi.baseName];
+ gen["extraGenerators"].append(gi.extraName);
}
}
Json::Value generators = Json::arrayValue;
- for (JsonValueMapType::const_iterator i = generatorMap.begin();
- i != generatorMap.end(); ++i) {
- generators.append(i->second);
+ for (auto const& i : generatorMap) {
+ generators.append(i.second);
}
obj["generators"] = generators;
- obj["serverMode"] = haveServerMode;
+ obj["fileApi"] = cmFileAPI::ReportCapabilities();
+ obj["serverMode"] = true;
return obj;
}
#endif
-std::string cmake::ReportCapabilities(bool haveServerMode) const
+std::string cmake::ReportCapabilities() const
{
std::string result;
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
Json::FastWriter writer;
- result = writer.write(this->ReportCapabilitiesJson(haveServerMode));
+ result = writer.write(this->ReportCapabilitiesJson());
#else
result = "Not supported";
#endif
@@ -313,7 +302,8 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
return false;
}
}
- std::string var, value;
+ std::string var;
+ std::string value;
cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED;
if (cmState::ParseCacheEntry(entry, var, value, type)) {
// The value is transformed if it is a filepath for example, so
@@ -322,9 +312,10 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
bool haveValue = false;
std::string cachedValue;
if (this->WarnUnusedCli) {
- if (const char* v = this->State->GetInitializedCacheValue(var)) {
+ if (const std::string* v =
+ this->State->GetInitializedCacheValue(var)) {
haveValue = true;
- cachedValue = v;
+ cachedValue = *v;
}
}
@@ -334,7 +325,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
if (this->WarnUnusedCli) {
if (!haveValue ||
- cachedValue != this->State->GetInitializedCacheValue(var)) {
+ cachedValue != *this->State->GetInitializedCacheValue(var)) {
this->WatchUnusedCli(var);
}
}
@@ -407,21 +398,18 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
// removed
std::vector<std::string> entriesToDelete;
std::vector<std::string> cacheKeys = this->State->GetCacheEntryKeys();
- for (std::vector<std::string>::const_iterator it = cacheKeys.begin();
- it != cacheKeys.end(); ++it) {
- cmStateEnums::CacheEntryType t = this->State->GetCacheEntryType(*it);
+ for (std::string const& ck : cacheKeys) {
+ cmStateEnums::CacheEntryType t = this->State->GetCacheEntryType(ck);
if (t != cmStateEnums::STATIC) {
- if (regex.find(it->c_str())) {
- entriesToDelete.push_back(*it);
+ if (regex.find(ck)) {
+ entriesToDelete.push_back(ck);
}
}
}
// now remove them from the cache
- for (std::vector<std::string>::const_iterator currentEntry =
- entriesToDelete.begin();
- currentEntry != entriesToDelete.end(); ++currentEntry) {
- this->State->RemoveCacheEntry(*currentEntry);
+ for (std::string const& currentEntry : entriesToDelete) {
+ this->State->RemoveCacheEntry(currentEntry);
}
} else if (arg.find("-C", 0) == 0) {
std::string path = arg.substr(2);
@@ -435,7 +423,9 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
}
}
std::cout << "loading initial cache file " << path << "\n";
- this->ReadListFile(args, path.c_str());
+ // Resolve script path specified on command line relative to $PWD.
+ path = cmSystemTools::CollapseFullPath(path);
+ this->ReadListFile(args, path);
} else if (arg.find("-P", 0) == 0) {
i++;
if (i >= args.size()) {
@@ -448,8 +438,13 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
return false;
}
// Register fake project commands that hint misuse in script mode.
- GetProjectCommandsInScriptMode(this->State);
- this->ReadListFile(args, path.c_str());
+ GetProjectCommandsInScriptMode(this->GetState());
+ // Documented behaviour of CMAKE{,_CURRENT}_{SOURCE,BINARY}_DIR is to be
+ // set to $PWD for -P mode.
+ this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+ this->SetHomeOutputDirectory(
+ cmSystemTools::GetCurrentWorkingDirectory());
+ this->ReadListFile(args, path);
} else if (arg.find("--find-package", 0) == 0) {
findPackageMode = true;
}
@@ -463,7 +458,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
}
void cmake::ReadListFile(const std::vector<std::string>& args,
- const char* path)
+ const std::string& path)
{
// if a generator was not yet created, temporarily create one
cmGlobalGenerator* gg = this->GetGlobalGenerator();
@@ -476,31 +471,23 @@ void cmake::ReadListFile(const std::vector<std::string>& args,
}
// read in the list file to fill the cache
- if (path) {
+ if (!path.empty()) {
this->CurrentSnapshot = this->State->Reset();
- std::string homeDir = this->GetHomeDirectory();
- std::string homeOutputDir = this->GetHomeOutputDirectory();
- this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
- this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
cmStateSnapshot snapshot = this->GetCurrentSnapshot();
- snapshot.GetDirectory().SetCurrentBinary(
- cmSystemTools::GetCurrentWorkingDirectory());
- snapshot.GetDirectory().SetCurrentSource(
- cmSystemTools::GetCurrentWorkingDirectory());
+ snapshot.GetDirectory().SetCurrentBinary(this->GetHomeOutputDirectory());
+ snapshot.GetDirectory().SetCurrentSource(this->GetHomeDirectory());
snapshot.SetDefaultDefinitions();
- CM_AUTO_PTR<cmMakefile> mf(new cmMakefile(gg, snapshot));
+ cmMakefile mf(gg, snapshot);
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);
+ mf.SetArgcArgv(args);
}
- if (!mf->ReadListFile(path)) {
- cmSystemTools::Error("Error processing file: ", path);
+ if (!mf.ReadListFile(path)) {
+ cmSystemTools::Error("Error processing file: " + path);
}
- this->SetHomeDirectory(homeDir);
- this->SetHomeOutputDirectory(homeOutputDir);
}
// free generic one if generated
@@ -531,7 +518,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args)
mf->SetArgcArgv(args);
std::string systemFile = mf->GetModulesFile("CMakeFindPackageMode.cmake");
- mf->ReadListFile(systemFile.c_str());
+ mf->ReadListFile(systemFile);
std::string language = mf->GetSafeDefinition("LANGUAGE");
std::string mode = mf->GetSafeDefinition("MODE");
@@ -549,13 +536,12 @@ bool cmake::FindPackage(const std::vector<std::string>& args)
}
} else if (mode == "COMPILE") {
std::string includes = mf->GetSafeDefinition("PACKAGE_INCLUDE_DIRS");
- std::vector<std::string> includeDirs;
- cmSystemTools::ExpandListArgument(includes, includeDirs);
+ std::vector<std::string> includeDirs = cmExpandedList(includes);
gg->CreateGenerationObjects();
cmLocalGenerator* lg = gg->LocalGenerators[0];
std::string includeFlags =
- lg->GetIncludeFlags(includeDirs, CM_NULLPTR, language);
+ lg->GetIncludeFlags(includeDirs, nullptr, language);
std::string definitions = mf->GetSafeDefinition("PACKAGE_DEFINITIONS");
printf("%s %s\n", includeFlags.c_str(), definitions.c_str());
@@ -566,11 +552,9 @@ bool cmake::FindPackage(const std::vector<std::string>& args)
tgt->SetProperty("LINKER_LANGUAGE", language.c_str());
std::string libs = mf->GetSafeDefinition("PACKAGE_LIBRARIES");
- std::vector<std::string> libList;
- cmSystemTools::ExpandListArgument(libs, libList);
- for (std::vector<std::string>::const_iterator libIt = libList.begin();
- libIt != libList.end(); ++libIt) {
- tgt->AddLinkLibrary(*mf, *libIt, GENERAL_LibraryType);
+ std::vector<std::string> libList = cmExpandedList(libs);
+ for (std::string const& lib : libList) {
+ tgt->AddLinkLibrary(*mf, lib, GENERAL_LibraryType);
}
std::string buildType = mf->GetSafeDefinition("CMAKE_BUILD_TYPE");
@@ -609,28 +593,76 @@ bool cmake::FindPackage(const std::vector<std::string>& args)
return packageFound;
}
+void cmake::LoadEnvironmentPresets()
+{
+ std::string envGenVar;
+ bool hasEnvironmentGenerator = false;
+ if (cmSystemTools::GetEnv("CMAKE_GENERATOR", envGenVar)) {
+ hasEnvironmentGenerator = true;
+ this->EnvironmentGenerator = envGenVar;
+ }
+
+ auto readGeneratorVar = [&](std::string const& name, std::string& key) {
+ std::string varValue;
+ if (cmSystemTools::GetEnv(name, varValue)) {
+ if (hasEnvironmentGenerator) {
+ key = varValue;
+ } else if (!this->GetIsInTryCompile()) {
+ std::string message =
+ cmStrCat("Warning: Environment variable ", name,
+ " will be ignored, because CMAKE_GENERATOR is not set.");
+ cmSystemTools::Message(message, "Warning");
+ }
+ }
+ };
+
+ readGeneratorVar("CMAKE_GENERATOR_INSTANCE", this->GeneratorInstance);
+ readGeneratorVar("CMAKE_GENERATOR_PLATFORM", this->GeneratorPlatform);
+ readGeneratorVar("CMAKE_GENERATOR_TOOLSET", this->GeneratorToolset);
+}
+
// Parse the args
-void cmake::SetArgs(const std::vector<std::string>& args,
- bool directoriesSetBefore)
+void cmake::SetArgs(const std::vector<std::string>& args)
{
- bool directoriesSet = directoriesSetBefore;
bool haveToolset = false;
bool havePlatform = false;
for (unsigned int i = 1; i < args.size(); ++i) {
std::string const& arg = args[i];
- if (arg.find("-H", 0) == 0) {
- directoriesSet = true;
+ if (arg.find("-H", 0) == 0 || arg.find("-S", 0) == 0) {
std::string path = arg.substr(2);
+ if (path.empty()) {
+ ++i;
+ if (i >= args.size()) {
+ cmSystemTools::Error("No source directory specified for -S");
+ return;
+ }
+ path = args[i];
+ if (path[0] == '-') {
+ cmSystemTools::Error("No source directory specified for -S");
+ return;
+ }
+ }
+
path = cmSystemTools::CollapseFullPath(path);
cmSystemTools::ConvertToUnixSlashes(path);
this->SetHomeDirectory(path);
- } else if (arg.find("-S", 0) == 0) {
- // There is no local generate anymore. Ignore -S option.
} else if (arg.find("-O", 0) == 0) {
// There is no local generate anymore. Ignore -O option.
} else if (arg.find("-B", 0) == 0) {
- directoriesSet = true;
std::string path = arg.substr(2);
+ if (path.empty()) {
+ ++i;
+ if (i >= args.size()) {
+ cmSystemTools::Error("No build directory specified for -B");
+ return;
+ }
+ path = args[i];
+ if (path[0] == '-') {
+ cmSystemTools::Error("No build directory specified for -B");
+ return;
+ }
+ }
+
path = cmSystemTools::CollapseFullPath(path);
cmSystemTools::ConvertToUnixSlashes(path);
this->SetHomeOutputDirectory(path);
@@ -653,10 +685,25 @@ void cmake::SetArgs(const std::vector<std::string>& args,
#endif
else if (arg.find("-D", 0) == 0) {
// skip for now
+ // in case '-D var=val' is given, also skip the next
+ // in case '-Dvar=val' is given, don't skip the next
+ if (arg.size() == 2) {
+ ++i;
+ }
} else if (arg.find("-U", 0) == 0) {
// skip for now
+ // in case '-U var' is given, also skip the next
+ // in case '-Uvar' is given, don't skip the next
+ if (arg.size() == 2) {
+ ++i;
+ }
} else if (arg.find("-C", 0) == 0) {
// skip for now
+ // in case '-C path' is given, also skip the next
+ // in case '-Cpath' is given, don't skip the next
+ if (arg.size() == 2) {
+ ++i;
+ }
} else if (arg.find("-P", 0) == 0) {
// skip for now
i++;
@@ -672,6 +719,7 @@ void cmake::SetArgs(const std::vector<std::string>& args,
this->GraphVizFile = path;
if (this->GraphVizFile.empty()) {
cmSystemTools::Error("No file specified for --graphviz");
+ return;
}
} else if (arg.find("--debug-trycompile", 0) == 0) {
std::cout << "debug trycompile on\n";
@@ -679,6 +727,25 @@ void cmake::SetArgs(const std::vector<std::string>& args,
} else if (arg.find("--debug-output", 0) == 0) {
std::cout << "Running with debug output on.\n";
this->SetDebugOutputOn(true);
+ } else if (arg.find("--log-level=", 0) == 0) {
+ const auto logLevel =
+ StringToLogLevel(arg.substr(sizeof("--log-level=") - 1));
+ if (logLevel == LogLevel::LOG_UNDEFINED) {
+ cmSystemTools::Error("Invalid level specified for --log-level");
+ return;
+ }
+ this->SetLogLevel(logLevel);
+ } else if (arg.find("--loglevel=", 0) == 0) {
+ // This is supported for backward compatibility. This option only
+ // appeared in the 3.15.x release series and was renamed to
+ // --log-level in 3.16.0
+ const auto logLevel =
+ StringToLogLevel(arg.substr(sizeof("--loglevel=") - 1));
+ if (logLevel == LogLevel::LOG_UNDEFINED) {
+ cmSystemTools::Error("Invalid level specified for --loglevel");
+ return;
+ }
+ this->SetLogLevel(logLevel);
} else if (arg.find("--trace-expand", 0) == 0) {
std::cout << "Running with expanded trace output on.\n";
this->SetTrace(true);
@@ -688,6 +755,11 @@ void cmake::SetArgs(const std::vector<std::string>& args,
cmSystemTools::ConvertToUnixSlashes(file);
this->AddTraceSource(file);
this->SetTrace(true);
+ } else if (arg.find("--trace-redirect=", 0) == 0) {
+ std::string file = arg.substr(strlen("--trace-redirect="));
+ cmSystemTools::ConvertToUnixSlashes(file);
+ this->SetTraceFile(file);
+ this->SetTrace(true);
} else if (arg.find("--trace", 0) == 0) {
std::cout << "Running with trace output on.\n";
this->SetTrace(true);
@@ -720,7 +792,7 @@ void cmake::SetArgs(const std::vector<std::string>& args,
cmSystemTools::Error("Multiple -A options not allowed");
return;
}
- this->GeneratorPlatform = value;
+ this->SetGeneratorPlatform(value);
havePlatform = true;
} else if (arg.find("-T", 0) == 0) {
std::string value = arg.substr(2);
@@ -736,7 +808,7 @@ void cmake::SetArgs(const std::vector<std::string>& args,
cmSystemTools::Error("Multiple -T options not allowed");
return;
}
- this->GeneratorToolset = value;
+ this->SetGeneratorToolset(value);
haveToolset = true;
} else if (arg.find("-G", 0) == 0) {
std::string value = arg.substr(2);
@@ -751,26 +823,88 @@ void cmake::SetArgs(const std::vector<std::string>& args,
}
cmGlobalGenerator* gen = this->CreateGlobalGenerator(value);
if (!gen) {
- cmSystemTools::Error("Could not create named generator ",
- value.c_str());
+ std::string kdevError;
+ if (value.find("KDevelop3", 0) != std::string::npos) {
+ kdevError = "\nThe KDevelop3 generator is not supported anymore.";
+ }
+
+ cmSystemTools::Error(
+ cmStrCat("Could not create named generator ", value, kdevError));
this->PrintGeneratorList();
- } else {
- this->SetGlobalGenerator(gen);
+ return;
}
+ this->SetGlobalGenerator(gen);
}
- // no option assume it is the path to the source
+ // no option assume it is the path to the source or an existing build
else {
- directoriesSet = true;
- this->SetDirectoriesFromFile(arg.c_str());
+ this->SetDirectoriesFromFile(arg);
+ }
+ // Empty instance, platform and toolset if only a generator is specified
+ if (this->GlobalGenerator) {
+ this->GeneratorInstance = "";
+ if (!this->GeneratorPlatformSet) {
+ this->GeneratorPlatform = "";
+ }
+ if (!this->GeneratorToolsetSet) {
+ this->GeneratorToolset = "";
+ }
}
}
- if (!directoriesSet) {
- this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+
+ const bool haveSourceDir = !this->GetHomeDirectory().empty();
+ const bool haveBinaryDir = !this->GetHomeOutputDirectory().empty();
+
+ if (this->CurrentWorkingMode == cmake::NORMAL_MODE && !haveSourceDir &&
+ !haveBinaryDir) {
+ this->IssueMessage(
+ MessageType::WARNING,
+ "No source or binary directory provided. Both will be assumed to be "
+ "the same as the current working directory, but note that this "
+ "warning will become a fatal error in future CMake releases.");
+ }
+
+ if (!haveSourceDir) {
this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
}
+ if (!haveBinaryDir) {
+ this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+ }
+}
+
+cmake::LogLevel cmake::StringToLogLevel(const std::string& levelStr)
+{
+ using LevelsPair = std::pair<std::string, LogLevel>;
+ static const std::vector<LevelsPair> levels = {
+ { "error", LogLevel::LOG_ERROR }, { "warning", LogLevel::LOG_WARNING },
+ { "notice", LogLevel::LOG_NOTICE }, { "status", LogLevel::LOG_STATUS },
+ { "verbose", LogLevel::LOG_VERBOSE }, { "debug", LogLevel::LOG_DEBUG },
+ { "trace", LogLevel::LOG_TRACE }
+ };
+
+ const auto levelStrLowCase = cmSystemTools::LowerCase(levelStr);
+
+ const auto it = std::find_if(levels.cbegin(), levels.cend(),
+ [&levelStrLowCase](const LevelsPair& p) {
+ return p.first == levelStrLowCase;
+ });
+ return (it != levels.cend()) ? it->second : LogLevel::LOG_UNDEFINED;
+}
+
+void cmake::SetTraceFile(const std::string& file)
+{
+ this->TraceFile.close();
+ this->TraceFile.open(file.c_str());
+ if (!this->TraceFile) {
+ std::stringstream ss;
+ ss << "Error opening trace file " << file << ": "
+ << cmSystemTools::GetLastSystemError();
+ cmSystemTools::Error(ss.str());
+ return;
+ }
+ std::cout << "Trace will be written to " << file << "\n";
}
-void cmake::SetDirectoriesFromFile(const char* arg)
+void cmake::SetDirectoriesFromFile(const std::string& arg)
{
// Check if the argument refers to a CMakeCache.txt or
// CMakeLists.txt file.
@@ -780,14 +914,12 @@ void cmake::SetDirectoriesFromFile(const char* arg)
if (cmSystemTools::FileIsDirectory(arg)) {
std::string path = cmSystemTools::CollapseFullPath(arg);
cmSystemTools::ConvertToUnixSlashes(path);
- std::string cacheFile = path;
- cacheFile += "/CMakeCache.txt";
- std::string listFile = path;
- listFile += "/CMakeLists.txt";
- if (cmSystemTools::FileExists(cacheFile.c_str())) {
+ std::string cacheFile = cmStrCat(path, "/CMakeCache.txt");
+ std::string listFile = cmStrCat(path, "/CMakeLists.txt");
+ if (cmSystemTools::FileExists(cacheFile)) {
cachePath = path;
}
- if (cmSystemTools::FileExists(listFile.c_str())) {
+ if (cmSystemTools::FileExists(listFile)) {
listPath = path;
}
} else if (cmSystemTools::FileExists(arg)) {
@@ -837,20 +969,27 @@ void cmake::SetDirectoriesFromFile(const char* arg)
this->SetHomeOutputDirectory(listPath);
} else {
// Source directory given on command line. Use current working
- // directory as build tree.
- std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
- this->SetHomeOutputDirectory(cwd);
+ // directory as build tree if -B hasn't been given already
+ if (this->GetHomeOutputDirectory().empty()) {
+ std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+ this->SetHomeOutputDirectory(cwd);
+ }
}
return;
}
- // We didn't find a CMakeLists.txt or CMakeCache.txt file from the
- // argument. Assume it is the path to the source tree, and use the
- // current working directory as the build tree.
- std::string full = cmSystemTools::CollapseFullPath(arg);
- std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
- this->SetHomeDirectory(full);
- this->SetHomeOutputDirectory(cwd);
+ if (this->GetHomeDirectory().empty()) {
+ // We didn't find a CMakeLists.txt and it wasn't specified
+ // with -S. Assume it is the path to the source tree
+ std::string full = cmSystemTools::CollapseFullPath(arg);
+ this->SetHomeDirectory(full);
+ }
+ if (this->GetHomeOutputDirectory().empty()) {
+ // We didn't find a CMakeCache.txt and it wasn't specified
+ // with -B. Assume the current working directory as the build tree.
+ std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+ this->SetHomeOutputDirectory(cwd);
+ }
}
// at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the
@@ -861,7 +1000,7 @@ int cmake::AddCMakePaths()
this->AddCacheEntry("CMAKE_COMMAND",
cmSystemTools::GetCMakeCommand().c_str(),
"Path to CMake executable.", cmStateEnums::INTERNAL);
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
this->AddCacheEntry(
"CMAKE_CTEST_COMMAND", cmSystemTools::GetCTestCommand().c_str(),
"Path to ctest program executable.", cmStateEnums::INTERNAL);
@@ -870,13 +1009,13 @@ 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"
"CMake has most likely not been installed correctly.\n"
- "Modules directory not found in\n",
- cmSystemTools::GetCMakeRoot().c_str());
+ "Modules directory not found in\n" +
+ cmSystemTools::GetCMakeRoot());
return 0;
}
this->AddCacheEntry("CMAKE_ROOT", cmSystemTools::GetCMakeRoot().c_str(),
@@ -887,72 +1026,67 @@ int cmake::AddCMakePaths()
void cmake::AddDefaultExtraGenerators()
{
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
this->ExtraGenerators.push_back(cmExtraCodeBlocksGenerator::GetFactory());
this->ExtraGenerators.push_back(cmExtraCodeLiteGenerator::GetFactory());
this->ExtraGenerators.push_back(cmExtraSublimeTextGenerator::GetFactory());
this->ExtraGenerators.push_back(cmExtraKateGenerator::GetFactory());
-#ifdef CMAKE_USE_ECLIPSE
+# ifdef CMAKE_USE_ECLIPSE
this->ExtraGenerators.push_back(cmExtraEclipseCDT4Generator::GetFactory());
-#endif
+# endif
-#ifdef CMAKE_USE_KDEVELOP
- this->ExtraGenerators.push_back(cmGlobalKdevelopGenerator::GetFactory());
-#endif
#endif
}
-void cmake::GetRegisteredGenerators(
- std::vector<GeneratorInfo>& generators) const
+void cmake::GetRegisteredGenerators(std::vector<GeneratorInfo>& generators,
+ bool includeNamesWithPlatform) const
{
- for (RegisteredGeneratorsVector::const_iterator i = this->Generators.begin(),
- e = this->Generators.end();
- i != e; ++i) {
- std::vector<std::string> names;
- (*i)->GetGenerators(names);
+ for (cmGlobalGeneratorFactory* gen : this->Generators) {
+ std::vector<std::string> names = gen->GetGeneratorNames();
+
+ if (includeNamesWithPlatform) {
+ cmAppend(names, gen->GetGeneratorNamesWithPlatform());
+ }
- for (size_t j = 0; j < names.size(); ++j) {
+ for (std::string const& name : names) {
GeneratorInfo info;
- info.supportsToolset = (*i)->SupportsToolset();
- info.supportsPlatform = (*i)->SupportsPlatform();
- info.name = names[j];
- info.baseName = names[j];
+ info.supportsToolset = gen->SupportsToolset();
+ info.supportsPlatform = gen->SupportsPlatform();
+ info.supportedPlatforms = gen->GetKnownPlatforms();
+ info.defaultPlatform = gen->GetDefaultPlatformName();
+ info.name = name;
+ info.baseName = name;
info.isAlias = false;
- generators.push_back(info);
+ generators.push_back(std::move(info));
}
}
- for (RegisteredExtraGeneratorsVector::const_iterator
- i = this->ExtraGenerators.begin(),
- e = this->ExtraGenerators.end();
- i != e; ++i) {
+ for (cmExternalMakefileProjectGeneratorFactory* eg : this->ExtraGenerators) {
const std::vector<std::string> genList =
- (*i)->GetSupportedGlobalGenerators();
- for (std::vector<std::string>::const_iterator gen = genList.begin();
- gen != genList.end(); ++gen) {
+ eg->GetSupportedGlobalGenerators();
+ for (std::string const& gen : genList) {
GeneratorInfo info;
info.name = cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
- *gen, (*i)->GetName());
- info.baseName = *gen;
- info.extraName = (*i)->GetName();
+ gen, eg->GetName());
+ info.baseName = gen;
+ info.extraName = eg->GetName();
info.supportsPlatform = false;
info.supportsToolset = false;
info.isAlias = false;
- generators.push_back(info);
+ generators.push_back(std::move(info));
}
- for (std::vector<std::string>::const_iterator a = (*i)->Aliases.begin();
- a != (*i)->Aliases.end(); ++a) {
+ for (std::string const& a : eg->Aliases) {
GeneratorInfo info;
- info.name = *a;
+ info.name = a;
if (!genList.empty()) {
info.baseName = genList.at(0);
}
- info.extraName = (*i)->GetName();
+ info.extraName = eg->GetName();
info.supportsPlatform = false;
info.supportsToolset = false;
info.isAlias = true;
- generators.push_back(info);
+ generators.push_back(std::move(info));
}
}
}
@@ -962,28 +1096,22 @@ createExtraGenerator(
const std::vector<cmExternalMakefileProjectGeneratorFactory*>& in,
const std::string& name)
{
- for (std::vector<cmExternalMakefileProjectGeneratorFactory*>::const_iterator
- i = in.begin();
- i != in.end(); ++i) {
+ for (cmExternalMakefileProjectGeneratorFactory* i : in) {
const std::vector<std::string> generators =
- (*i)->GetSupportedGlobalGenerators();
- if ((*i)->GetName() == name) { // Match aliases
- return std::make_pair((*i)->CreateExternalMakefileProjectGenerator(),
- generators.at(0));
+ i->GetSupportedGlobalGenerators();
+ if (i->GetName() == name) { // Match aliases
+ return { i->CreateExternalMakefileProjectGenerator(), generators.at(0) };
}
- for (std::vector<std::string>::const_iterator g = generators.begin();
- g != generators.end(); ++g) {
+ for (std::string const& g : generators) {
const std::string fullName =
cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
- *g, (*i)->GetName());
+ g, i->GetName());
if (fullName == name) {
- return std::make_pair((*i)->CreateExternalMakefileProjectGenerator(),
- *g);
+ return { i->CreateExternalMakefileProjectGenerator(), g };
}
}
}
- return std::make_pair(
- static_cast<cmExternalMakefileProjectGenerator*>(CM_NULLPTR), name);
+ return { nullptr, name };
}
cmGlobalGenerator* cmake::CreateGlobalGenerator(const std::string& gname)
@@ -993,10 +1121,9 @@ cmGlobalGenerator* cmake::CreateGlobalGenerator(const std::string& gname)
cmExternalMakefileProjectGenerator* extraGenerator = extra.first;
const std::string name = extra.second;
- cmGlobalGenerator* generator = CM_NULLPTR;
- for (RegisteredGeneratorsVector::const_iterator i = this->Generators.begin();
- i != this->Generators.end(); ++i) {
- generator = (*i)->CreateGlobalGenerator(name, this);
+ cmGlobalGenerator* generator = nullptr;
+ for (cmGlobalGeneratorFactory* g : this->Generators) {
+ generator = g->CreateGlobalGenerator(name, this);
if (generator) {
break;
}
@@ -1019,7 +1146,7 @@ void cmake::SetHomeDirectory(const std::string& dir)
}
}
-const char* cmake::GetHomeDirectory() const
+std::string const& cmake::GetHomeDirectory() const
{
return this->State->GetSourceDirectory();
}
@@ -1032,7 +1159,7 @@ void cmake::SetHomeOutputDirectory(const std::string& dir)
}
}
-const char* cmake::GetHomeOutputDirectory() const
+std::string const& cmake::GetHomeOutputDirectory() const
{
return this->State->GetBinaryDirectory();
}
@@ -1041,16 +1168,14 @@ std::string cmake::FindCacheFile(const std::string& binaryDir)
{
std::string cachePath = binaryDir;
cmSystemTools::ConvertToUnixSlashes(cachePath);
- std::string cacheFile = cachePath;
- cacheFile += "/CMakeCache.txt";
- if (!cmSystemTools::FileExists(cacheFile.c_str())) {
+ std::string cacheFile = cmStrCat(cachePath, "/CMakeCache.txt");
+ if (!cmSystemTools::FileExists(cacheFile)) {
// search in parent directories for cache
- std::string cmakeFiles = cachePath;
- cmakeFiles += "/CMakeFiles";
- if (cmSystemTools::FileExists(cmakeFiles.c_str())) {
+ std::string cmakeFiles = cmStrCat(cachePath, "/CMakeFiles");
+ if (cmSystemTools::FileExists(cmakeFiles)) {
std::string cachePathFound =
cmSystemTools::FileExistsInParentDirectories("CMakeCache.txt",
- cachePath.c_str(), "/");
+ cachePath, "/");
if (!cachePathFound.empty()) {
cachePath = cmSystemTools::GetFilenamePath(cachePathFound);
}
@@ -1091,19 +1216,18 @@ void cmake::SetGlobalGenerator(cmGlobalGenerator* gg)
// Save the environment variables CXX and CC
if (!cmSystemTools::GetEnv("CXX", this->CXXEnvironment)) {
- this->CXXEnvironment = "";
+ this->CXXEnvironment.clear();
}
if (!cmSystemTools::GetEnv("CC", this->CCEnvironment)) {
- this->CCEnvironment = "";
+ this->CCEnvironment.clear();
}
}
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())) {
+ std::string srcList = cmStrCat(this->GetHomeDirectory(), "/CMakeLists.txt");
+ if (!cmSystemTools::FileExists(srcList)) {
std::ostringstream err;
if (cmSystemTools::FileIsDirectory(this->GetHomeDirectory())) {
err << "The source directory \"" << this->GetHomeDirectory()
@@ -1117,25 +1241,24 @@ int cmake::DoPreConfigureChecks()
}
err << "Specify --help for usage, or press the help button on the CMake "
"GUI.";
- cmSystemTools::Error(err.str().c_str());
+ cmSystemTools::Error(err.str());
return -2;
}
// do a sanity check on some values
if (this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY")) {
std::string cacheStart =
- this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY");
- cacheStart += "/CMakeLists.txt";
- std::string currentStart = this->GetHomeDirectory();
- currentStart += "/CMakeLists.txt";
+ cmStrCat(*this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY"),
+ "/CMakeLists.txt");
+ std::string currentStart =
+ cmStrCat(this->GetHomeDirectory(), "/CMakeLists.txt");
if (!cmSystemTools::SameFile(cacheStart, currentStart)) {
- std::string message = "The source \"";
- message += currentStart;
- message += "\" does not match the source \"";
- message += cacheStart;
- message += "\" used to generate cache. ";
- message += "Re-run cmake with a different source directory.";
- cmSystemTools::Error(message.c_str());
+ std::string message =
+ cmStrCat("The source \"", currentStart,
+ "\" does not match the source \"", cacheStart,
+ "\" used to generate cache. Re-run cmake with a different "
+ "source directory.");
+ cmSystemTools::Error(message);
return -2;
}
} else {
@@ -1153,8 +1276,7 @@ struct SaveCacheEntry
int cmake::HandleDeleteCacheVariables(const std::string& var)
{
- std::vector<std::string> argsSplit;
- cmSystemTools::ExpandListArgument(std::string(var), argsSplit, true);
+ std::vector<std::string> argsSplit = cmExpandedList(std::string(var), true);
// erase the property to avoid infinite recursion
this->State->SetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", "");
if (this->State->GetIsInTryCompile()) {
@@ -1168,8 +1290,7 @@ int cmake::HandleDeleteCacheVariables(const std::string& var)
<< "Configure will be re-run and you may have to reset some variables.\n"
<< "The following variables have changed:\n";
/* clang-format on */
- for (std::vector<std::string>::iterator i = argsSplit.begin();
- i != argsSplit.end(); ++i) {
+ for (auto i = argsSplit.begin(); i != argsSplit.end(); ++i) {
SaveCacheEntry save;
save.key = *i;
warning << *i << "= ";
@@ -1184,7 +1305,7 @@ int cmake::HandleDeleteCacheVariables(const std::string& var)
save.help = help;
}
}
- saved.push_back(save);
+ saved.push_back(std::move(save));
}
// remove the cache
@@ -1192,11 +1313,10 @@ int cmake::HandleDeleteCacheVariables(const std::string& var)
// load the empty cache
this->LoadCache();
// restore the changed compilers
- for (std::vector<SaveCacheEntry>::iterator i = saved.begin();
- i != saved.end(); ++i) {
- this->AddCacheEntry(i->key, i->value.c_str(), i->help.c_str(), i->type);
+ for (SaveCacheEntry const& i : saved) {
+ this->AddCacheEntry(i.key, i.value.c_str(), i.help.c_str(), i.type);
}
- cmSystemTools::Message(warning.str().c_str());
+ cmSystemTools::Message(warning.str());
// avoid reconfigure if there were errors
if (!cmSystemTools::GetErrorOccuredFlag()) {
// re-run configure
@@ -1265,6 +1385,21 @@ int cmake::Configure()
}
}
+ // Cache variables may have already been set by a previous invocation,
+ // so we cannot rely on command line options alone. Always ensure our
+ // messenger is in sync with the cache.
+ const char* value = this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED");
+ this->Messenger->SetSuppressDeprecatedWarnings(value && cmIsOff(value));
+
+ value = this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED");
+ this->Messenger->SetDeprecatedWarningsAsErrors(cmIsOn(value));
+
+ value = this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_WARNINGS");
+ this->Messenger->SetSuppressDevWarnings(cmIsOn(value));
+
+ value = this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_ERRORS");
+ this->Messenger->SetDevWarningsAsErrors(value && cmIsOff(value));
+
int ret = this->ActualConfigure();
const char* delCacheVars =
this->State->GetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_");
@@ -1280,16 +1415,13 @@ int cmake::ActualConfigure()
this->UpdateConversionPathTable();
this->CleanupCommandsAndMacros();
- int res = 0;
- if (this->GetWorkingMode() == NORMAL_MODE) {
- res = this->DoPreConfigureChecks();
- }
+ int res = this->DoPreConfigureChecks();
if (res < 0) {
return -2;
}
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);
@@ -1297,14 +1429,14 @@ int cmake::ActualConfigure()
// no generator specified on the command line
if (!this->GlobalGenerator) {
- const char* genName =
+ const std::string* genName =
this->State->GetInitializedCacheValue("CMAKE_GENERATOR");
- const char* extraGenName =
+ const std::string* extraGenName =
this->State->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR");
if (genName) {
std::string fullName =
cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
- genName, extraGenName ? extraGenName : "");
+ *genName, extraGenName ? *extraGenName : "");
this->GlobalGenerator = this->CreateGlobalGenerator(fullName);
}
if (this->GlobalGenerator) {
@@ -1322,17 +1454,16 @@ int cmake::ActualConfigure()
}
}
- const char* genName =
+ const std::string* genName =
this->State->GetInitializedCacheValue("CMAKE_GENERATOR");
if (genName) {
- if (!this->GlobalGenerator->MatchesGeneratorName(genName)) {
- std::string message = "Error: generator : ";
- message += this->GlobalGenerator->GetName();
- message += "\nDoes not match the generator used previously: ";
- message += genName;
- message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
- "directory or choose a different binary directory.";
- cmSystemTools::Error(message.c_str());
+ if (!this->GlobalGenerator->MatchesGeneratorName(*genName)) {
+ std::string message =
+ cmStrCat("Error: generator : ", this->GlobalGenerator->GetName(),
+ "\nDoes not match the generator used previously: ", *genName,
+ "\nEither remove the CMakeCache.txt file and CMakeFiles "
+ "directory or choose a different binary directory.");
+ cmSystemTools::Error(message);
return -2;
}
}
@@ -1346,18 +1477,33 @@ int cmake::ActualConfigure()
cmStateEnums::INTERNAL);
}
- if (const char* platformName =
+ if (const std::string* instance =
+ this->State->GetInitializedCacheValue("CMAKE_GENERATOR_INSTANCE")) {
+ if (this->GeneratorInstanceSet && this->GeneratorInstance != *instance) {
+ std::string message =
+ cmStrCat("Error: generator instance: ", this->GeneratorInstance,
+ "\nDoes not match the instance used previously: ", *instance,
+ "\nEither remove the CMakeCache.txt file and CMakeFiles "
+ "directory or choose a different binary directory.");
+ cmSystemTools::Error(message);
+ return -2;
+ }
+ } else {
+ this->AddCacheEntry(
+ "CMAKE_GENERATOR_INSTANCE", this->GeneratorInstance.c_str(),
+ "Generator instance identifier.", cmStateEnums::INTERNAL);
+ }
+
+ if (const std::string* platformName =
this->State->GetInitializedCacheValue("CMAKE_GENERATOR_PLATFORM")) {
- if (this->GeneratorPlatform.empty()) {
- this->GeneratorPlatform = platformName;
- } else if (this->GeneratorPlatform != platformName) {
- std::string message = "Error: generator platform: ";
- message += this->GeneratorPlatform;
- message += "\nDoes not match the platform used previously: ";
- message += platformName;
- message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
- "directory or choose a different binary directory.";
- cmSystemTools::Error(message.c_str());
+ if (this->GeneratorPlatformSet &&
+ this->GeneratorPlatform != *platformName) {
+ std::string message = cmStrCat(
+ "Error: generator platform: ", this->GeneratorPlatform,
+ "\nDoes not match the platform used previously: ", *platformName,
+ "\nEither remove the CMakeCache.txt file and CMakeFiles "
+ "directory or choose a different binary directory.");
+ cmSystemTools::Error(message);
return -2;
}
} else {
@@ -1366,18 +1512,15 @@ int cmake::ActualConfigure()
"Name of generator platform.", cmStateEnums::INTERNAL);
}
- if (const char* tsName =
+ if (const std::string* tsName =
this->State->GetInitializedCacheValue("CMAKE_GENERATOR_TOOLSET")) {
- if (this->GeneratorToolset.empty()) {
- this->GeneratorToolset = tsName;
- } else if (this->GeneratorToolset != tsName) {
- std::string message = "Error: generator toolset: ";
- message += this->GeneratorToolset;
- message += "\nDoes not match the toolset used previously: ";
- message += tsName;
- message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
- "directory or choose a different binary directory.";
- cmSystemTools::Error(message.c_str());
+ if (this->GeneratorToolsetSet && this->GeneratorToolset != *tsName) {
+ std::string message =
+ cmStrCat("Error: generator toolset: ", this->GeneratorToolset,
+ "\nDoes not match the toolset used previously: ", *tsName,
+ "\nEither remove the CMakeCache.txt file and CMakeFiles "
+ "directory or choose a different binary directory.");
+ cmSystemTools::Error(message);
return -2;
}
} else {
@@ -1396,6 +1539,11 @@ int cmake::ActualConfigure()
this->TruncateOutputLog("CMakeError.log");
}
+#if !defined(CMAKE_BOOTSTRAP)
+ this->FileAPI = cm::make_unique<cmFileAPI>(this);
+ this->FileAPI->ReadQueries();
+#endif
+
// actually do the configure
this->GlobalGenerator->Configure();
// Before saving the cache
@@ -1433,18 +1581,26 @@ int cmake::ActualConfigure()
"CMakeLists.txt ?");
}
- // only save the cache if there were no fatal errors
- if (this->GetWorkingMode() == NORMAL_MODE) {
- this->SaveCache(this->GetHomeOutputDirectory());
- }
+ this->State->SaveVerificationScript(this->GetHomeOutputDirectory());
+ this->SaveCache(this->GetHomeOutputDirectory());
if (cmSystemTools::GetErrorOccuredFlag()) {
return -1;
}
return 0;
}
-void cmake::CreateDefaultGlobalGenerator()
+std::unique_ptr<cmGlobalGenerator> cmake::EvaluateDefaultGlobalGenerator()
{
+ if (!this->EnvironmentGenerator.empty()) {
+ cmGlobalGenerator* gen =
+ this->CreateGlobalGenerator(this->EnvironmentGenerator);
+ if (!gen) {
+ cmSystemTools::Error("CMAKE_GENERATOR was set but the specified "
+ "generator doesn't exist. Using CMake default.");
+ } else {
+ return std::unique_ptr<cmGlobalGenerator>(gen);
+ }
+ }
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
std::string found;
// Try to find the newest VS installed on the computer and
@@ -1460,28 +1616,27 @@ void cmake::CreateDefaultGlobalGenerator()
const char* GeneratorName;
};
static VSVersionedGenerator const vsGenerators[] = {
- { "15.0", "Visual Studio 15 2017" }, //
{ "14.0", "Visual Studio 14 2015" }, //
{ "12.0", "Visual Studio 12 2013" }, //
{ "11.0", "Visual Studio 11 2012" }, //
{ "10.0", "Visual Studio 10 2010" }, //
- { "9.0", "Visual Studio 9 2008" }, //
- { "8.0", "Visual Studio 8 2005" }
+ { "9.0", "Visual Studio 9 2008" }
};
static const char* const vsEntries[] = {
"\\Setup\\VC;ProductDir", //
";InstallDir" //
};
- cmVSSetupAPIHelper vsSetupAPIHelper;
- if (vsSetupAPIHelper.IsVS2017Installed()) {
+ if (cmVSSetupAPIHelper(16).IsVSInstalled()) {
+ found = "Visual Studio 16 2019";
+ } else if (cmVSSetupAPIHelper(15).IsVSInstalled()) {
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,
@@ -1497,11 +1652,20 @@ void cmake::CreateDefaultGlobalGenerator()
if (!gen) {
gen = new cmGlobalNMakeMakefileGenerator(this);
}
- this->SetGlobalGenerator(gen);
- std::cout << "-- Building for: " << gen->GetName() << "\n";
+ return std::unique_ptr<cmGlobalGenerator>(gen);
#else
- this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator3(this));
+ return cm::make_unique<cmGlobalUnixMakefileGenerator3>(this);
+#endif
+}
+
+void cmake::CreateDefaultGlobalGenerator()
+{
+ auto gen = this->EvaluateDefaultGlobalGenerator();
+#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
+ // This print could be unified for all platforms
+ std::cout << "-- Building for: " << gen->GetName() << "\n";
#endif
+ this->SetGlobalGenerator(gen.release());
}
void cmake::PreLoadCMakeFiles()
@@ -1510,15 +1674,15 @@ void cmake::PreLoadCMakeFiles()
std::string pre_load = this->GetHomeDirectory();
if (!pre_load.empty()) {
pre_load += "/PreLoad.cmake";
- if (cmSystemTools::FileExists(pre_load.c_str())) {
- this->ReadListFile(args, pre_load.c_str());
+ if (cmSystemTools::FileExists(pre_load)) {
+ this->ReadListFile(args, pre_load);
}
}
pre_load = this->GetHomeOutputDirectory();
if (!pre_load.empty()) {
pre_load += "/PreLoad.cmake";
- if (cmSystemTools::FileExists(pre_load.c_str())) {
- this->ReadListFile(args, pre_load.c_str());
+ if (cmSystemTools::FileExists(pre_load)) {
+ this->ReadListFile(args, pre_load);
}
}
}
@@ -1534,13 +1698,13 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
// If we are given a stamp list file check if it is really out of date.
if (!this->CheckStampList.empty() &&
- cmakeCheckStampList(this->CheckStampList.c_str())) {
+ cmakeCheckStampList(this->CheckStampList)) {
return 0;
}
// If we are given a stamp file check if it is really out of date.
if (!this->CheckStampFile.empty() &&
- cmakeCheckStampFile(this->CheckStampFile.c_str())) {
+ cmakeCheckStampFile(this->CheckStampFile)) {
return 0;
}
@@ -1590,7 +1754,7 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
}
int ret = this->Configure();
- if (ret || this->GetWorkingMode() != NORMAL_MODE) {
+ if (ret) {
#if defined(CMAKE_HAVE_VS_GENERATORS)
if (!this->VSSolutionFile.empty() && this->GlobalGenerator) {
// CMake is running to regenerate a Visual Studio build tree
@@ -1602,15 +1766,20 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
cmGlobalVisualStudioGenerator* gg =
static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator);
gg->CallVisualStudioMacro(cmGlobalVisualStudioGenerator::MacroStop,
- this->VSSolutionFile.c_str());
+ this->VSSolutionFile);
}
#endif
return ret;
}
ret = this->Generate();
- std::string message = "Build files have been written to: ";
- message += this->GetHomeOutputDirectory();
- this->UpdateProgress(message.c_str(), -1);
+ if (ret) {
+ cmSystemTools::Message("CMake Generate step failed. "
+ "Build files cannot be regenerated correctly.");
+ return ret;
+ }
+ std::string message = cmStrCat("Build files have been written to: ",
+ this->GetHomeOutputDirectory());
+ this->UpdateProgress(message, -1);
return ret;
}
@@ -1625,7 +1794,7 @@ int cmake::Generate()
this->GlobalGenerator->Generate();
if (!this->GraphVizFile.empty()) {
std::cout << "Generate graphviz: " << this->GraphVizFile << std::endl;
- this->GenerateGraphViz(this->GraphVizFile.c_str());
+ this->GenerateGraphViz(this->GraphVizFile);
}
if (this->WarnUnusedCli) {
this->RunCheckForUnusedVariables();
@@ -1636,9 +1805,12 @@ int cmake::Generate()
// Save the cache again after a successful Generate so that any internal
// variables created during Generate are saved. (Specifically target GUIDs
// for the Visual Studio and Xcode generators.)
- if (this->GetWorkingMode() == NORMAL_MODE) {
- this->SaveCache(this->GetHomeOutputDirectory());
- }
+ this->SaveCache(this->GetHomeOutputDirectory());
+
+#if !defined(CMAKE_BOOTSTRAP)
+ this->FileAPI->WriteReplies();
+#endif
+
return 0;
}
@@ -1648,44 +1820,101 @@ void cmake::AddCacheEntry(const std::string& key, const char* value,
this->State->AddCacheEntry(key, value, helpString,
cmStateEnums::CacheEntryType(type));
this->UnwatchUnusedCli(key);
+
+ if (key == "CMAKE_WARN_DEPRECATED") {
+ this->Messenger->SetSuppressDeprecatedWarnings(value && cmIsOff(value));
+ } else if (key == "CMAKE_ERROR_DEPRECATED") {
+ this->Messenger->SetDeprecatedWarningsAsErrors(cmIsOn(value));
+ } else if (key == "CMAKE_SUPPRESS_DEVELOPER_WARNINGS") {
+ this->Messenger->SetSuppressDevWarnings(cmIsOn(value));
+ } else if (key == "CMAKE_SUPPRESS_DEVELOPER_ERRORS") {
+ this->Messenger->SetDevWarningsAsErrors(value && cmIsOff(value));
+ }
+}
+
+bool cmake::DoWriteGlobVerifyTarget() const
+{
+ return this->State->DoWriteGlobVerifyTarget();
+}
+
+std::string const& cmake::GetGlobVerifyScript() const
+{
+ return this->State->GetGlobVerifyScript();
+}
+
+std::string const& cmake::GetGlobVerifyStamp() const
+{
+ return this->State->GetGlobVerifyStamp();
+}
+
+void cmake::AddGlobCacheEntry(bool recurse, bool listDirectories,
+ bool followSymlinks, const std::string& relative,
+ const std::string& expression,
+ const std::vector<std::string>& files,
+ const std::string& variable,
+ cmListFileBacktrace const& backtrace)
+{
+ this->State->AddGlobCacheEntry(recurse, listDirectories, followSymlinks,
+ relative, expression, files, variable,
+ backtrace);
+}
+
+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);
+ const std::string* p = this->State->GetInitializedCacheValue(name);
+ return p ? p->c_str() : nullptr;
}
void cmake::AddScriptingCommands()
{
- GetScriptingCommands(this->State);
+ GetScriptingCommands(this->GetState());
}
void cmake::AddProjectCommands()
{
- GetProjectCommands(this->State);
+ GetProjectCommands(this->GetState());
}
void cmake::AddDefaultGenerators()
{
#if defined(_WIN32) && !defined(__CYGWIN__)
-#if !defined(CMAKE_BOOT_MINGW)
- this->Generators.push_back(cmGlobalVisualStudio15Generator::NewFactory());
+# if !defined(CMAKE_BOOT_MINGW)
+ this->Generators.push_back(
+ cmGlobalVisualStudioVersionedGenerator::NewFactory16());
+ this->Generators.push_back(
+ cmGlobalVisualStudioVersionedGenerator::NewFactory15());
this->Generators.push_back(cmGlobalVisualStudio14Generator::NewFactory());
this->Generators.push_back(cmGlobalVisualStudio12Generator::NewFactory());
this->Generators.push_back(cmGlobalVisualStudio11Generator::NewFactory());
this->Generators.push_back(cmGlobalVisualStudio10Generator::NewFactory());
this->Generators.push_back(cmGlobalVisualStudio9Generator::NewFactory());
- this->Generators.push_back(cmGlobalVisualStudio8Generator::NewFactory());
this->Generators.push_back(cmGlobalBorlandMakefileGenerator::NewFactory());
this->Generators.push_back(cmGlobalNMakeMakefileGenerator::NewFactory());
this->Generators.push_back(cmGlobalJOMMakefileGenerator::NewFactory());
- this->Generators.push_back(cmGlobalGhsMultiGenerator::NewFactory());
-#endif
+# endif
this->Generators.push_back(cmGlobalMSYSMakefileGenerator::NewFactory());
this->Generators.push_back(cmGlobalMinGWMakefileGenerator::NewFactory());
#endif
this->Generators.push_back(cmGlobalUnixMakefileGenerator3::NewFactory());
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
+# if defined(__linux__) || defined(_WIN32)
+ this->Generators.push_back(cmGlobalGhsMultiGenerator::NewFactory());
+# endif
this->Generators.push_back(cmGlobalNinjaGenerator::NewFactory());
#endif
#if defined(CMAKE_USE_WMAKE)
@@ -1708,9 +1937,9 @@ int cmake::LoadCache()
// could we not read the cache
if (!this->LoadCache(this->GetHomeOutputDirectory())) {
// 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())) {
+ std::string cacheFile =
+ cmStrCat(this->GetHomeOutputDirectory(), "/CMakeCache.txt");
+ 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 "
@@ -1737,25 +1966,23 @@ bool cmake::LoadCache(const std::string& path, bool internal,
std::set<std::string>& includes)
{
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) {
- this->UnwatchUnusedCli(*nameIt);
+ static const auto entries = { "CMAKE_CACHE_MAJOR_VERSION",
+ "CMAKE_CACHE_MINOR_VERSION" };
+ for (auto const& entry : entries) {
+ this->UnwatchUnusedCli(entry);
}
return result;
}
bool cmake::SaveCache(const std::string& path)
{
- bool result = this->State->SaveCache(path);
- 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) {
- this->UnwatchUnusedCli(*nameIt);
+ bool result = this->State->SaveCache(path, this->GetMessenger());
+ static const auto entries = { "CMAKE_CACHE_MAJOR_VERSION",
+ "CMAKE_CACHE_MINOR_VERSION",
+ "CMAKE_CACHE_PATCH_VERSION",
+ "CMAKE_CACHEFILE_DIR" };
+ for (auto const& entry : entries) {
+ this->UnwatchUnusedCli(entry);
}
return result;
}
@@ -1765,17 +1992,15 @@ bool cmake::DeleteCache(const std::string& path)
return this->State->DeleteCache(path);
}
-void cmake::SetProgressCallback(ProgressCallbackType f, void* cd)
+void cmake::SetProgressCallback(ProgressCallbackType f)
{
- this->ProgressCallback = f;
- this->ProgressCallbackClientData = cd;
+ this->ProgressCallback = std::move(f);
}
-void cmake::UpdateProgress(const char* msg, float prog)
+void cmake::UpdateProgress(const std::string& msg, float prog)
{
if (this->ProgressCallback && !this->State->GetIsInTryCompile()) {
- (*this->ProgressCallback)(msg, prog, this->ProgressCallbackClientData);
- return;
+ this->ProgressCallback(msg, prog);
}
}
@@ -1789,49 +2014,65 @@ void cmake::SetIsInTryCompile(bool b)
this->State->SetIsInTryCompile(b);
}
-void cmake::GetGeneratorDocumentation(std::vector<cmDocumentationEntry>& v)
+void cmake::AppendGlobalGeneratorsDocumentation(
+ std::vector<cmDocumentationEntry>& v)
{
- for (RegisteredGeneratorsVector::const_iterator i = this->Generators.begin();
- i != this->Generators.end(); ++i) {
+ const auto defaultGenerator = this->EvaluateDefaultGlobalGenerator();
+ const std::string defaultName = defaultGenerator->GetName();
+ bool foundDefaultOne = false;
+
+ for (cmGlobalGeneratorFactory* g : this->Generators) {
cmDocumentationEntry e;
- (*i)->GetDocumentation(e);
- v.push_back(e);
+ g->GetDocumentation(e);
+ if (!foundDefaultOne && cmHasPrefix(e.Name, defaultName)) {
+ e.CustomNamePrefix = '*';
+ foundDefaultOne = true;
+ }
+ v.push_back(std::move(e));
}
- for (RegisteredExtraGeneratorsVector::const_iterator i =
- this->ExtraGenerators.begin();
- i != this->ExtraGenerators.end(); ++i) {
- const std::string doc = (*i)->GetDocumentation();
- const std::string name = (*i)->GetName();
+}
+
+void cmake::AppendExtraGeneratorsDocumentation(
+ std::vector<cmDocumentationEntry>& v)
+{
+ for (cmExternalMakefileProjectGeneratorFactory* eg : this->ExtraGenerators) {
+ const std::string doc = eg->GetDocumentation();
+ const std::string name = eg->GetName();
// Aliases:
- for (std::vector<std::string>::const_iterator a = (*i)->Aliases.begin();
- a != (*i)->Aliases.end(); ++a) {
+ for (std::string const& a : eg->Aliases) {
cmDocumentationEntry e;
- e.Name = *a;
+ e.Name = a;
e.Brief = doc;
- v.push_back(e);
+ v.push_back(std::move(e));
}
// Full names:
const std::vector<std::string> generators =
- (*i)->GetSupportedGlobalGenerators();
- for (std::vector<std::string>::const_iterator g = generators.begin();
- g != generators.end(); ++g) {
+ eg->GetSupportedGlobalGenerators();
+ for (std::string const& g : generators) {
cmDocumentationEntry e;
e.Name =
- cmExternalMakefileProjectGenerator::CreateFullGeneratorName(*g, name);
+ cmExternalMakefileProjectGenerator::CreateFullGeneratorName(g, name);
e.Brief = doc;
- v.push_back(e);
+ v.push_back(std::move(e));
}
}
}
+std::vector<cmDocumentationEntry> cmake::GetGeneratorsDocumentation()
+{
+ std::vector<cmDocumentationEntry> v;
+ this->AppendGlobalGeneratorsDocumentation(v);
+ this->AppendExtraGeneratorsDocumentation(v);
+ return v;
+}
+
void cmake::PrintGeneratorList()
{
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
cmDocumentation doc;
- std::vector<cmDocumentationEntry> generators;
- this->GetGeneratorDocumentation(generators);
+ auto generators = this->GetGeneratorsDocumentation();
doc.AppendSection("Generators", generators);
std::cerr << "\n";
doc.PrintDocumentation(cmDocumentation::ListGenerators, std::cerr);
@@ -1841,17 +2082,18 @@ void cmake::PrintGeneratorList()
void cmake::UpdateConversionPathTable()
{
// Update the path conversion table with any specified file:
- const char* tablepath =
+ const std::string* tablepath =
this->State->GetInitializedCacheValue("CMAKE_PATH_TRANSLATION_FILE");
if (tablepath) {
- cmsys::ifstream table(tablepath);
+ cmsys::ifstream table(tablepath->c_str());
if (!table) {
- cmSystemTools::Error("CMAKE_PATH_TRANSLATION_FILE set to ", tablepath,
+ cmSystemTools::Error("CMAKE_PATH_TRANSLATION_FILE set to " + *tablepath +
". CMake can not open file.");
cmSystemTools::ReportLastSystemError("CMake can not open file.");
} else {
- std::string a, b;
+ std::string a;
+ std::string b;
while (!table.eof()) {
// two entries per line
table >> a;
@@ -1874,39 +2116,38 @@ int cmake::CheckBuildSystem()
// If no file is provided for the check, we have to rerun.
if (this->CheckBuildSystemArgument.empty()) {
if (verbose) {
- std::ostringstream msg;
- msg << "Re-run cmake no build system arguments\n";
- cmSystemTools::Stdout(msg.str().c_str());
+ cmSystemTools::Stdout("Re-run cmake no build system arguments\n");
}
return 1;
}
// 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
<< "\n";
- cmSystemTools::Stdout(msg.str().c_str());
+ cmSystemTools::Stdout(msg.str());
}
return 1;
}
// Read the rerun check file and use it to decide whether to do the
// global generate.
- cmake cm(RoleScript); // Actually, all we need is the `set` command.
+ // Actually, all we need is the `set` command.
+ cmake cm(RoleScript, cmState::Unknown);
cm.SetHomeDirectory("");
cm.SetHomeOutputDirectory("");
cm.GetCurrentSnapshot().SetDefaultDefinitions();
cmGlobalGenerator gg(&cm);
- CM_AUTO_PTR<cmMakefile> mf(new cmMakefile(&gg, cm.GetCurrentSnapshot()));
- if (!mf->ReadListFile(this->CheckBuildSystemArgument.c_str()) ||
+ cmMakefile mf(&gg, cm.GetCurrentSnapshot());
+ if (!mf.ReadListFile(this->CheckBuildSystemArgument) ||
cmSystemTools::GetErrorOccuredFlag()) {
if (verbose) {
std::ostringstream msg;
msg << "Re-run cmake error reading : " << this->CheckBuildSystemArgument
<< "\n";
- cmSystemTools::Stdout(msg.str().c_str());
+ cmSystemTools::Stdout(msg.str());
}
// There was an error reading the file. Just rerun.
return 1;
@@ -1914,35 +2155,33 @@ int cmake::CheckBuildSystem()
if (this->ClearBuildSystem) {
// Get the generator used for this build system.
- const char* genName = mf->GetDefinition("CMAKE_DEPENDS_GENERATOR");
+ const char* genName = mf.GetDefinition("CMAKE_DEPENDS_GENERATOR");
if (!genName || genName[0] == '\0') {
genName = "Unix Makefiles";
}
// Create the generator and use it to clear the dependencies.
- CM_AUTO_PTR<cmGlobalGenerator> ggd(this->CreateGlobalGenerator(genName));
- if (ggd.get()) {
+ std::unique_ptr<cmGlobalGenerator> ggd(
+ this->CreateGlobalGenerator(genName));
+ if (ggd) {
cm.GetCurrentSnapshot().SetDefaultDefinitions();
- CM_AUTO_PTR<cmMakefile> mfd(
- new cmMakefile(ggd.get(), cm.GetCurrentSnapshot()));
- CM_AUTO_PTR<cmLocalGenerator> lgd(ggd->CreateLocalGenerator(mfd.get()));
- lgd->ClearDependencies(mfd.get(), verbose);
+ cmMakefile mfd(ggd.get(), cm.GetCurrentSnapshot());
+ std::unique_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator(&mfd));
+ lgd->ClearDependencies(&mfd, verbose);
}
}
// If any byproduct of makefile generation is missing we must re-run.
std::vector<std::string> products;
- if (const char* productStr = mf->GetDefinition("CMAKE_MAKEFILE_PRODUCTS")) {
- cmSystemTools::ExpandListArgument(productStr, products);
+ if (const char* productStr = mf.GetDefinition("CMAKE_MAKEFILE_PRODUCTS")) {
+ cmExpandList(productStr, products);
}
- for (std::vector<std::string>::const_iterator pi = products.begin();
- pi != products.end(); ++pi) {
- if (!(cmSystemTools::FileExists(pi->c_str()) ||
- cmSystemTools::FileIsSymlink(*pi))) {
+ for (std::string const& p : products) {
+ if (!(cmSystemTools::FileExists(p) || cmSystemTools::FileIsSymlink(p))) {
if (verbose) {
std::ostringstream msg;
- msg << "Re-run cmake, missing byproduct: " << *pi << "\n";
- cmSystemTools::Stdout(msg.str().c_str());
+ msg << "Re-run cmake, missing byproduct: " << p << "\n";
+ cmSystemTools::Stdout(msg.str());
}
return 1;
}
@@ -1951,58 +2190,52 @@ int cmake::CheckBuildSystem()
// Get the set of dependencies and outputs.
std::vector<std::string> depends;
std::vector<std::string> outputs;
- const char* dependsStr = mf->GetDefinition("CMAKE_MAKEFILE_DEPENDS");
- const char* outputsStr = mf->GetDefinition("CMAKE_MAKEFILE_OUTPUTS");
+ const char* dependsStr = mf.GetDefinition("CMAKE_MAKEFILE_DEPENDS");
+ const char* outputsStr = mf.GetDefinition("CMAKE_MAKEFILE_OUTPUTS");
if (dependsStr && outputsStr) {
- cmSystemTools::ExpandListArgument(dependsStr, depends);
- cmSystemTools::ExpandListArgument(outputsStr, outputs);
+ cmExpandList(dependsStr, depends);
+ cmExpandList(outputsStr, outputs);
}
if (depends.empty() || outputs.empty()) {
// Not enough information was provided to do the test. Just rerun.
if (verbose) {
- std::ostringstream msg;
- msg << "Re-run cmake no CMAKE_MAKEFILE_DEPENDS "
- "or CMAKE_MAKEFILE_OUTPUTS :\n";
- cmSystemTools::Stdout(msg.str().c_str());
+ cmSystemTools::Stdout("Re-run cmake no CMAKE_MAKEFILE_DEPENDS "
+ "or CMAKE_MAKEFILE_OUTPUTS :\n");
}
return 1;
}
// Find the newest dependency.
- std::vector<std::string>::iterator dep = depends.begin();
+ auto dep = depends.begin();
std::string dep_newest = *dep++;
for (; dep != depends.end(); ++dep) {
int result = 0;
- if (this->FileComparison->FileTimeCompare(dep_newest.c_str(), dep->c_str(),
- &result)) {
+ if (this->FileTimeCache->Compare(dep_newest, *dep, &result)) {
if (result < 0) {
dep_newest = *dep;
}
} else {
if (verbose) {
- std::ostringstream msg;
- msg << "Re-run cmake: build system dependency is missing\n";
- cmSystemTools::Stdout(msg.str().c_str());
+ cmSystemTools::Stdout(
+ "Re-run cmake: build system dependency is missing\n");
}
return 1;
}
}
// Find the oldest output.
- std::vector<std::string>::iterator out = outputs.begin();
+ auto out = outputs.begin();
std::string out_oldest = *out++;
for (; out != outputs.end(); ++out) {
int result = 0;
- if (this->FileComparison->FileTimeCompare(out_oldest.c_str(), out->c_str(),
- &result)) {
+ if (this->FileTimeCache->Compare(out_oldest, *out, &result)) {
if (result > 0) {
out_oldest = *out;
}
} else {
if (verbose) {
- std::ostringstream msg;
- msg << "Re-run cmake: build system output is missing\n";
- cmSystemTools::Stdout(msg.str().c_str());
+ cmSystemTools::Stdout(
+ "Re-run cmake: build system output is missing\n");
}
return 1;
}
@@ -2011,14 +2244,13 @@ int cmake::CheckBuildSystem()
// If any output is older than any dependency then rerun.
{
int result = 0;
- if (!this->FileComparison->FileTimeCompare(out_oldest.c_str(),
- dep_newest.c_str(), &result) ||
+ if (!this->FileTimeCache->Compare(out_oldest, dep_newest, &result) ||
result < 0) {
if (verbose) {
std::ostringstream msg;
msg << "Re-run cmake file: " << out_oldest
<< " older than: " << dep_newest << "\n";
- cmSystemTools::Stdout(msg.str().c_str());
+ cmSystemTools::Stdout(msg.str());
}
return 1;
}
@@ -2030,9 +2262,7 @@ int cmake::CheckBuildSystem()
void cmake::TruncateOutputLog(const char* fname)
{
- std::string fullPath = this->GetHomeOutputDirectory();
- fullPath += "/";
- fullPath += fname;
+ std::string fullPath = cmStrCat(this->GetHomeOutputDirectory(), '/', fname);
struct stat st;
if (::stat(fullPath.c_str(), &st)) {
return;
@@ -2049,35 +2279,25 @@ void cmake::TruncateOutputLog(const char* fname)
}
}
-inline std::string removeQuotes(const std::string& s)
-{
- if (s[0] == '\"' && s[s.size() - 1] == '\"') {
- return s.substr(1, s.size() - 2);
- }
- return s;
-}
-
void cmake::MarkCliAsUsed(const std::string& variable)
{
this->UsedCliVariables[variable] = true;
}
-void cmake::GenerateGraphViz(const char* fileName) const
+void cmake::GenerateGraphViz(const std::string& fileName) const
{
-#ifdef CMAKE_BUILD_WITH_CMAKE
- CM_AUTO_PTR<cmGraphVizWriter> gvWriter(
- new cmGraphVizWriter(this->GetGlobalGenerator()->GetLocalGenerators()));
+#ifndef CMAKE_BOOTSTRAP
+ cmGraphVizWriter gvWriter(this->GetGlobalGenerator());
- std::string settingsFile = this->GetHomeOutputDirectory();
- settingsFile += "/CMakeGraphVizOptions.cmake";
- std::string fallbackSettingsFile = this->GetHomeDirectory();
- fallbackSettingsFile += "/CMakeGraphVizOptions.cmake";
+ std::string settingsFile =
+ cmStrCat(this->GetHomeOutputDirectory(), "/CMakeGraphVizOptions.cmake");
+ std::string fallbackSettingsFile =
+ cmStrCat(this->GetHomeDirectory(), "/CMakeGraphVizOptions.cmake");
- gvWriter->ReadSettings(settingsFile.c_str(), fallbackSettingsFile.c_str());
-
- gvWriter->WritePerTargetFiles(fileName);
- gvWriter->WriteTargetDependersFiles(fileName);
- gvWriter->WriteGlobalFile(fileName);
+ gvWriter.ReadSettings(settingsFile, fallbackSettingsFile);
+ gvWriter.WritePerTargetFiles(fileName);
+ gvWriter.WriteTargetDependersFiles(fileName);
+ gvWriter.WriteGlobalFile(fileName);
#endif
}
@@ -2106,8 +2326,7 @@ bool cmake::GetPropertyAsBool(const std::string& prop)
cmInstalledFile* cmake::GetOrCreateInstalledFile(cmMakefile* mf,
const std::string& name)
{
- std::map<std::string, cmInstalledFile>::iterator i =
- this->InstalledFiles.find(name);
+ auto i = this->InstalledFiles.find(name);
if (i != this->InstalledFiles.end()) {
cmInstalledFile& file = i->second;
@@ -2120,14 +2339,13 @@ cmInstalledFile* cmake::GetOrCreateInstalledFile(cmMakefile* mf,
cmInstalledFile const* cmake::GetInstalledFile(const std::string& name) const
{
- std::map<std::string, cmInstalledFile>::const_iterator i =
- this->InstalledFiles.find(name);
+ auto i = this->InstalledFiles.find(name);
if (i != this->InstalledFiles.end()) {
cmInstalledFile const& file = i->second;
return &file;
}
- return CM_NULLPTR;
+ return nullptr;
}
int cmake::GetSystemInformation(std::vector<std::string>& args)
@@ -2137,7 +2355,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;
@@ -2160,8 +2378,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
}
cmGlobalGenerator* gen = this->CreateGlobalGenerator(value);
if (!gen) {
- cmSystemTools::Error("Could not create named generator ",
- value.c_str());
+ cmSystemTools::Error("Could not create named generator " + value);
this->PrintGeneratorList();
} else {
this->SetGlobalGenerator(gen);
@@ -2169,9 +2386,8 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
}
// no option assume it is the output file
else {
- if (!cmSystemTools::FileIsFullPath(arg.c_str())) {
- resultFile = cwd;
- resultFile += "/";
+ if (!cmSystemTools::FileIsFullPath(arg)) {
+ resultFile = cmStrCat(cwd, '/');
}
resultFile += arg;
writeToStdout = false;
@@ -2180,15 +2396,13 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
// we have to find the module directory, so we can copy the files
this->AddCMakePaths();
- std::string modulesPath = cmSystemTools::GetCMakeRoot();
- modulesPath += "/Modules";
- std::string inFile = modulesPath;
- inFile += "/SystemInformation.cmake";
- std::string outFile = destPath;
- outFile += "/CMakeLists.txt";
+ std::string modulesPath =
+ cmStrCat(cmSystemTools::GetCMakeRoot(), "/Modules");
+ std::string inFile = cmStrCat(modulesPath, "/SystemInformation.cmake");
+ std::string outFile = cmStrCat(destPath, "/CMakeLists.txt");
// Copy file
- if (!cmSystemTools::cmCopyFile(inFile.c_str(), outFile.c_str())) {
+ if (!cmsys::SystemTools::CopyFileAlways(inFile, outFile)) {
std::cerr << "Error copying file \"" << inFile << "\" to \"" << outFile
<< "\".\n";
return 1;
@@ -2196,19 +2410,25 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
// do we write to a file or to stdout?
if (resultFile.empty()) {
- resultFile = cwd;
- resultFile += "/__cmake_systeminformation/results.txt";
+ resultFile = cmStrCat(cwd, "/__cmake_systeminformation/results.txt");
}
{
// now run cmake on the CMakeLists file
cmWorkingDirectory workdir(destPath);
+ if (workdir.Failed()) {
+ // We created the directory and we were able to copy the CMakeLists.txt
+ // file to it, so we wouldn't expect to get here unless the default
+ // permissions are questionable or some other process has deleted the
+ // directory
+ std::cerr << "Failed to change to directory " << destPath << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl;
+ return 1;
+ }
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) {
@@ -2239,15 +2459,14 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
return 0;
}
-static bool cmakeCheckStampFile(const char* stampName, bool verbose)
+static bool cmakeCheckStampFile(const std::string& stampName)
{
// The stamp file does not exist. Use the stamp dependencies to
// determine whether it is really out of date. This works in
// conjunction with cmLocalVisualStudio7Generator to avoid
// repeatedly re-running CMake when the user rebuilds the entire
// solution.
- std::string stampDepends = stampName;
- stampDepends += ".depend";
+ std::string stampDepends = cmStrCat(stampName, ".depend");
#if defined(_WIN32) || defined(__CYGWIN__)
cmsys::ifstream fin(stampDepends.c_str(), std::ios::in | std::ios::binary);
#else
@@ -2262,21 +2481,22 @@ static bool cmakeCheckStampFile(const char* stampName, bool verbose)
}
// Compare the stamp dependencies against the dependency file itself.
- cmFileTimeComparison ftc;
- std::string dep;
- while (cmSystemTools::GetLineFromStream(fin, dep)) {
- int result;
- if (!dep.empty() && dep[0] != '#' &&
- (!ftc.FileTimeCompare(stampDepends.c_str(), dep.c_str(), &result) ||
- result < 0)) {
- // The stamp depends file is older than this dependency. The
- // build system is really out of date.
- std::cout << "CMake is re-running because " << stampName
- << " is out-of-date.\n";
- std::cout << " the file '" << dep << "'\n";
- std::cout << " is newer than '" << stampDepends << "'\n";
- std::cout << " result='" << result << "'\n";
- return false;
+ {
+ cmFileTimeCache ftc;
+ std::string dep;
+ while (cmSystemTools::GetLineFromStream(fin, dep)) {
+ int result;
+ if (!dep.empty() && dep[0] != '#' &&
+ (!ftc.Compare(stampDepends, dep, &result) || result < 0)) {
+ // The stamp depends file is older than this dependency. The
+ // build system is really out of date.
+ std::cout << "CMake is re-running because " << stampName
+ << " is out-of-date.\n";
+ std::cout << " the file '" << dep << "'\n";
+ std::cout << " is newer than '" << stampDepends << "'\n";
+ std::cout << " result='" << result << "'\n";
+ return false;
+ }
}
}
@@ -2284,30 +2504,23 @@ static bool cmakeCheckStampFile(const char* stampName, bool verbose)
// by the VS IDE due to a "rebuild" request. Restore it atomically.
std::ostringstream stampTempStream;
stampTempStream << stampName << ".tmp" << cmSystemTools::RandomSeed();
- std::string stampTempString = stampTempStream.str();
- const char* stampTemp = stampTempString.c_str();
+ std::string stampTemp = stampTempStream.str();
{
// TODO: Teach cmGeneratedFileStream to use a random temp file (with
// multiple tries in unlikely case of conflict) and use that here.
- cmsys::ofstream stamp(stampTemp);
+ cmsys::ofstream stamp(stampTemp.c_str());
stamp << "# CMake generation timestamp file for this directory.\n";
}
if (cmSystemTools::RenameFile(stampTemp, stampName)) {
- if (verbose) {
- // Notify the user why CMake is not re-running. It is safe to
- // just print to stdout here because this code is only reachable
- // through an undocumented flag used by the VS generator.
- std::cout << "CMake does not need to re-run because " << stampName
- << " is up-to-date.\n";
- }
+ // CMake does not need to re-run because the stamp file is up-to-date.
return true;
}
cmSystemTools::RemoveFile(stampTemp);
- cmSystemTools::Error("Cannot restore timestamp ", stampName);
+ cmSystemTools::Error("Cannot restore timestamp " + stampName);
return false;
}
-static bool cmakeCheckStampList(const char* stampList, bool verbose)
+static bool cmakeCheckStampList(const std::string& stampList)
{
// If the stamp list does not exist CMake must rerun to generate it.
if (!cmSystemTools::FileExists(stampList)) {
@@ -2315,7 +2528,7 @@ static bool cmakeCheckStampList(const char* stampList, bool verbose)
<< "is missing.\n";
return false;
}
- cmsys::ifstream fin(stampList);
+ cmsys::ifstream fin(stampList.c_str());
if (!fin) {
std::cout << "CMake is re-running because generate.stamp.list "
<< "could not be read.\n";
@@ -2325,14 +2538,14 @@ static bool cmakeCheckStampList(const char* stampList, bool verbose)
// Check each stamp.
std::string stampName;
while (cmSystemTools::GetLineFromStream(fin, stampName)) {
- if (!cmakeCheckStampFile(stampName.c_str(), verbose)) {
+ if (!cmakeCheckStampFile(stampName)) {
return false;
}
}
return true;
}
-void cmake::IssueMessage(cmake::MessageType t, std::string const& text,
+void cmake::IssueMessage(MessageType t, std::string const& text,
cmListFileBacktrace const& backtrace) const
{
this->Messenger->IssueMessage(t, text, backtrace);
@@ -2344,25 +2557,22 @@ std::vector<std::string> cmake::GetDebugConfigs()
if (const char* config_list =
this->State->GetGlobalProperty("DEBUG_CONFIGURATIONS")) {
// Expand the specified list and convert to upper-case.
- cmSystemTools::ExpandListArgument(config_list, configs);
+ cmExpandList(config_list, configs);
std::transform(configs.begin(), configs.end(), configs.begin(),
cmSystemTools::UpperCase);
}
// If no configurations were specified, use a default list.
if (configs.empty()) {
- configs.push_back("DEBUG");
+ configs.emplace_back("DEBUG");
}
return configs;
}
-cmMessenger* cmake::GetMessenger() const
-{
- return this->Messenger;
-}
-
-int cmake::Build(const std::string& dir, const std::string& target,
+int cmake::Build(int jobs, const std::string& dir,
+ const std::vector<std::string>& targets,
const std::string& config,
- const std::vector<std::string>& nativeOptions, bool clean)
+ const std::vector<std::string>& nativeOptions, bool clean,
+ bool verbose)
{
this->SetHomeDirectory("");
@@ -2383,13 +2593,29 @@ int cmake::Build(const std::string& dir, const std::string& target,
std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n";
return 1;
}
- CM_AUTO_PTR<cmGlobalGenerator> gen(
- this->CreateGlobalGenerator(cachedGenerator));
- if (!gen.get()) {
+ cmGlobalGenerator* gen = this->CreateGlobalGenerator(cachedGenerator);
+ if (!gen) {
std::cerr << "Error: could create CMAKE_GENERATOR \"" << cachedGenerator
<< "\"\n";
return 1;
}
+ this->SetGlobalGenerator(gen);
+ const char* cachedGeneratorInstance =
+ this->State->GetCacheEntryValue("CMAKE_GENERATOR_INSTANCE");
+ if (cachedGeneratorInstance) {
+ cmMakefile mf(gen, this->GetCurrentSnapshot());
+ if (!gen->SetGeneratorInstance(cachedGeneratorInstance, &mf)) {
+ return 1;
+ }
+ }
+ const char* cachedGeneratorPlatform =
+ this->State->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM");
+ if (cachedGeneratorPlatform) {
+ cmMakefile mf(gen, this->GetCurrentSnapshot());
+ if (!gen->SetGeneratorPlatform(cachedGeneratorPlatform, &mf)) {
+ return 1;
+ }
+ }
std::string output;
std::string projName;
const char* cachedProjectName =
@@ -2399,11 +2625,11 @@ int cmake::Build(const std::string& dir, const std::string& target,
return 1;
}
projName = cachedProjectName;
- bool verbose = false;
+
const char* cachedVerbose =
this->State->GetCacheEntryValue("CMAKE_VERBOSE_MAKEFILE");
- if (cachedVerbose) {
- verbose = cmSystemTools::IsOn(cachedVerbose);
+ if (cmIsOn(cachedVerbose)) {
+ verbose = true;
}
#ifdef CMAKE_HAVE_VS_GENERATORS
@@ -2411,55 +2637,110 @@ int cmake::Build(const std::string& dir, const std::string& target,
// actually starting the build. If not done separately from the build
// itself, there is the risk of building an out-of-date solution file due
// to limitations of the underlying build system.
- std::string const stampList = cachePath + "/" +
- GetCMakeFilesDirectoryPostSlash() +
- cmGlobalVisualStudio8Generator::GetGenerateStampList();
+ std::string const stampList = cachePath + "/" + "CMakeFiles/" +
+ cmGlobalVisualStudio9Generator::GetGenerateStampList();
// Note that the stampList file only exists for VS generators.
- if (cmSystemTools::FileExists(stampList.c_str()) &&
- !cmakeCheckStampList(stampList.c_str(), false)) {
-
- // Correctly initialize the home (=source) and home output (=binary)
- // directories, which is required for running the generation step.
- std::string homeOrig = this->GetHomeDirectory();
- std::string homeOutputOrig = this->GetHomeOutputDirectory();
- this->SetDirectoriesFromFile(cachePath.c_str());
+ if (cmSystemTools::FileExists(stampList)) {
+ // Check if running for Visual Studio 9 - we need to explicitly run
+ // the glob verification script before starting the build
this->AddScriptingCommands();
- this->AddProjectCommands();
-
- int ret = this->Configure();
- if (ret) {
- cmSystemTools::Message("CMake Configure step failed. "
- "Build files cannot be regenerated correctly.");
- return ret;
- }
- ret = this->Generate();
- if (ret) {
- cmSystemTools::Message("CMake Generate step failed. "
- "Build files cannot be regenerated correctly.");
- return ret;
+ if (this->GlobalGenerator->MatchesGeneratorName("Visual Studio 9 2008")) {
+ std::string const globVerifyScript =
+ cachePath + "/" + "CMakeFiles/" + "VerifyGlobs.cmake";
+ if (cmSystemTools::FileExists(globVerifyScript)) {
+ std::vector<std::string> args;
+ this->ReadListFile(args, globVerifyScript);
+ }
}
- std::string message = "Build files have been written to: ";
- message += this->GetHomeOutputDirectory();
- this->UpdateProgress(message.c_str(), -1);
- // Restore the previously set directories to their original value.
- this->SetHomeDirectory(homeOrig);
- this->SetHomeOutputDirectory(homeOutputOrig);
+ if (!cmakeCheckStampList(stampList)) {
+ // Correctly initialize the home (=source) and home output (=binary)
+ // directories, which is required for running the generation step.
+ std::string homeOrig = this->GetHomeDirectory();
+ std::string homeOutputOrig = this->GetHomeOutputDirectory();
+ this->SetDirectoriesFromFile(cachePath);
+
+ this->AddProjectCommands();
+
+ int ret = this->Configure();
+ if (ret) {
+ cmSystemTools::Message("CMake Configure step failed. "
+ "Build files cannot be regenerated correctly.");
+ return ret;
+ }
+ ret = this->Generate();
+ if (ret) {
+ cmSystemTools::Message("CMake Generate step failed. "
+ "Build files cannot be regenerated correctly.");
+ return ret;
+ }
+ std::string message = cmStrCat("Build files have been written to: ",
+ this->GetHomeOutputDirectory());
+ this->UpdateProgress(message, -1);
+
+ // Restore the previously set directories to their original value.
+ this->SetHomeDirectory(homeOrig);
+ this->SetHomeOutputDirectory(homeOutputOrig);
+ }
}
#endif
- return gen->Build("", dir, projName, target, output, "", config, clean,
- false, verbose, 0, cmSystemTools::OUTPUT_PASSTHROUGH,
- nativeOptions);
+ gen->PrintBuildCommandAdvice(std::cerr, jobs);
+ return gen->Build(jobs, "", dir, projName, targets, output, "", config,
+ clean, 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 std::string* 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) {
+ 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)
{
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
this->VariableWatch->AddWatch(var, cmWarnUnusedCliWarning, this);
- if (this->UsedCliVariables.find(var) == this->UsedCliVariables.end()) {
+ if (!cmContains(this->UsedCliVariables, var)) {
this->UsedCliVariables[var] = false;
}
#endif
@@ -2467,7 +2748,7 @@ void cmake::WatchUnusedCli(const std::string& var)
void cmake::UnwatchUnusedCli(const std::string& var)
{
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
this->VariableWatch->RemoveWatch(var, cmWarnUnusedCliWarning);
this->UsedCliVariables.erase(var);
#endif
@@ -2475,20 +2756,18 @@ void cmake::UnwatchUnusedCli(const std::string& var)
void cmake::RunCheckForUnusedVariables()
{
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
bool haveUnused = false;
std::ostringstream msg;
msg << "Manually-specified variables were not used by the project:";
- for (std::map<std::string, bool>::const_iterator it =
- this->UsedCliVariables.begin();
- it != this->UsedCliVariables.end(); ++it) {
- if (!it->second) {
+ for (auto const& it : this->UsedCliVariables) {
+ if (!it.second) {
haveUnused = true;
- msg << "\n " << it->first;
+ msg << "\n " << it.first;
}
}
if (haveUnused) {
- this->IssueMessage(cmake::WARNING, msg.str());
+ this->IssueMessage(MessageType::WARNING, msg.str());
}
#endif
}
diff --git a/Source/cmake.h b/Source/cmake.h
index 4ddacf701..687c1056b 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -3,29 +3,35 @@
#ifndef cmake_h
#define cmake_h
-#include "cmConfigure.h"
+#include "cmConfigure.h" // IWYU pragma: keep
+#include <functional>
#include <map>
+#include <memory>
#include <set>
#include <string>
+#include <unordered_set>
#include <vector>
+#include "cmGeneratedFileStream.h"
#include "cmInstalledFile.h"
#include "cmListFileCache.h"
+#include "cmMessageType.h"
+#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cm_jsoncpp_value.h"
+#if !defined(CMAKE_BOOTSTRAP)
+# include "cm_jsoncpp_value.h"
#endif
class cmExternalMakefileProjectGeneratorFactory;
-class cmFileTimeComparison;
+class cmFileAPI;
+class cmFileTimeCache;
class cmGlobalGenerator;
class cmGlobalGeneratorFactory;
class cmMakefile;
class cmMessenger;
-class cmState;
class cmVariableWatch;
struct cmDocumentationEntry;
@@ -55,8 +61,6 @@ struct cmDocumentationEntry;
class cmake
{
- CM_DISABLE_COPY(cmake)
-
public:
enum Role
{
@@ -65,19 +69,6 @@ public:
RoleProject // all commands
};
- enum MessageType
- {
- AUTHOR_WARNING,
- AUTHOR_ERROR,
- FATAL_ERROR,
- INTERNAL_ERROR,
- MESSAGE,
- WARNING,
- LOG,
- DEPRECATION_ERROR,
- DEPRECATION_WARNING
- };
-
enum DiagLevel
{
DIAG_IGNORE,
@@ -106,6 +97,19 @@ public:
FIND_PACKAGE_MODE
};
+ /** \brief Define log level constants. */
+ enum LogLevel
+ {
+ LOG_UNDEFINED,
+ LOG_ERROR,
+ LOG_WARNING,
+ LOG_NOTICE,
+ LOG_STATUS,
+ LOG_VERBOSE,
+ LOG_DEBUG,
+ LOG_TRACE
+ };
+
struct GeneratorInfo
{
std::string name;
@@ -113,26 +117,40 @@ public:
std::string extraName;
bool supportsToolset;
bool supportsPlatform;
+ std::vector<std::string> supportedPlatforms;
+ std::string defaultPlatform;
bool isAlias;
};
- typedef std::map<std::string, cmInstalledFile> InstalledFilesMap;
+ struct FileExtensions
+ {
+ bool Test(std::string const& ext) const
+ {
+ return (this->unordered.find(ext) != this->unordered.end());
+ }
+
+ std::vector<std::string> ordered;
+ std::unordered_set<std::string> unordered;
+ };
+
+ using InstalledFilesMap = std::map<std::string, cmInstalledFile>;
+
+ static const int NO_BUILD_PARALLEL_LEVEL = -1;
+ static const int DEFAULT_BUILD_PARALLEL_LEVEL = 0;
/// Default constructor
- cmake(Role role);
+ cmake(Role role, cmState::Mode mode);
/// Destructor
~cmake();
-#if defined(CMAKE_BUILD_WITH_CMAKE)
- Json::Value ReportCapabilitiesJson(bool haveServerMode) const;
-#endif
- std::string ReportCapabilities(bool haveServerMode) const;
+ cmake(cmake const&) = delete;
+ cmake& operator=(cmake const&) = delete;
- static const char* GetCMakeFilesDirectory() { return "/CMakeFiles"; }
- static const char* GetCMakeFilesDirectoryPostSlash()
- {
- return "CMakeFiles/";
- }
+#if !defined(CMAKE_BOOTSTRAP)
+ Json::Value ReportVersionJson() const;
+ Json::Value ReportCapabilitiesJson() const;
+#endif
+ std::string ReportCapabilities() const;
//@{
/**
@@ -141,9 +159,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;
//@}
/**
@@ -169,7 +187,7 @@ public:
int Configure();
int ActualConfigure();
- ///! Break up a line like VAR:type="value" into var, type and value
+ //! Break up a line like VAR:type="value" into var, type and value
static bool ParseCacheEntry(const std::string& entry, std::string& var,
std::string& value,
cmStateEnums::CacheEntryType& type);
@@ -183,84 +201,128 @@ public:
bool DeleteCache(const std::string& path);
void PreLoadCMakeFiles();
- ///! Create a GlobalGenerator
+ //! Create a GlobalGenerator
cmGlobalGenerator* CreateGlobalGenerator(const std::string& name);
- ///! Return the global generator assigned to this instance of cmake
+ //! Return the global generator assigned to this instance of cmake
cmGlobalGenerator* GetGlobalGenerator() { return this->GlobalGenerator; }
- ///! Return the global generator assigned to this instance of cmake, const
+ //! Return the global generator assigned to this instance of cmake, const
const cmGlobalGenerator* GetGlobalGenerator() const
{
return this->GlobalGenerator;
}
- ///! Return the full path to where the CMakeCache.txt file should be.
+ //! Return the full path to where the CMakeCache.txt file should be.
static std::string FindCacheFile(const std::string& binaryDir);
- ///! Return the global generator assigned to this instance of cmake
+ //! Return the global generator assigned to this instance of cmake
void SetGlobalGenerator(cmGlobalGenerator*);
- ///! Get the names of the current registered generators
- void GetRegisteredGenerators(std::vector<GeneratorInfo>& generators) const;
+ //! Get the names of the current registered generators
+ void GetRegisteredGenerators(std::vector<GeneratorInfo>& generators,
+ bool includeNamesWithPlatform = true) const;
- ///! Set the name of the selected generator-specific platform.
- void SetGeneratorPlatform(std::string const& ts)
+ //! Set the name of the selected generator-specific instance.
+ void SetGeneratorInstance(std::string const& instance)
{
- this->GeneratorPlatform = ts;
+ this->GeneratorInstance = instance;
+ this->GeneratorInstanceSet = true;
}
- ///! Get the name of the selected generator-specific platform.
- std::string const& GetGeneratorPlatform() const
+ //! Set the name of the selected generator-specific platform.
+ void SetGeneratorPlatform(std::string const& ts)
{
- return this->GeneratorPlatform;
+ this->GeneratorPlatform = ts;
+ this->GeneratorPlatformSet = true;
}
- ///! Set the name of the selected generator-specific toolset.
+ //! Set the name of the selected generator-specific toolset.
void SetGeneratorToolset(std::string const& ts)
{
this->GeneratorToolset = ts;
+ this->GeneratorToolsetSet = true;
}
- ///! Get the name of the selected generator-specific toolset.
- std::string const& GetGeneratorToolset() const
+ const std::vector<std::string>& GetSourceExtensions() const
{
- return this->GeneratorToolset;
+ return this->SourceFileExtensions.ordered;
}
- const std::vector<std::string>& GetSourceExtensions() const
+ bool IsSourceExtension(const std::string& ext) const
{
- return this->SourceFileExtensions;
+ return this->SourceFileExtensions.Test(ext);
}
+
const std::vector<std::string>& GetHeaderExtensions() const
{
- return this->HeaderFileExtensions;
+ return this->HeaderFileExtensions.ordered;
+ }
+
+ bool IsHeaderExtension(const std::string& ext) const
+ {
+ return this->HeaderFileExtensions.Test(ext);
+ }
+
+ const std::vector<std::string>& GetCudaExtensions() const
+ {
+ return this->CudaFileExtensions.ordered;
+ }
+
+ bool IsCudaExtension(const std::string& ext) const
+ {
+ return this->CudaFileExtensions.Test(ext);
+ }
+
+ const std::vector<std::string>& GetFortranExtensions() const
+ {
+ return this->FortranFileExtensions.ordered;
+ }
+
+ bool IsFortranExtension(const std::string& ext) const
+ {
+ return this->FortranFileExtensions.Test(ext);
}
+ // 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).
*/
const char* GetCacheDefinition(const std::string&) const;
- ///! Add an entry into the cache
+ //! Add an entry into the cache
void AddCacheEntry(const std::string& key, const char* value,
const char* helpString, int type);
+ bool DoWriteGlobVerifyTarget() const;
+ std::string const& GetGlobVerifyScript() const;
+ std::string const& GetGlobVerifyStamp() const;
+ void AddGlobCacheEntry(bool recurse, bool listDirectories,
+ bool followSymlinks, const std::string& relative,
+ const std::string& expression,
+ const std::vector<std::string>& files,
+ const std::string& variable,
+ cmListFileBacktrace const& bt);
+
/**
* Get the system information and write it to the file specified
*/
int GetSystemInformation(std::vector<std::string>&);
- ///! Parse command line arguments
- void SetArgs(const std::vector<std::string>&,
- bool directoriesSetBefore = false);
+ //! Parse environment variables
+ void LoadEnvironmentPresets();
+
+ //! Parse command line arguments
+ void SetArgs(const std::vector<std::string>& args);
- ///! Is this cmake running as a result of a TRY_COMPILE command
+ //! Is this cmake running as a result of a TRY_COMPILE command
bool GetIsInTryCompile() const;
void SetIsInTryCompile(bool b);
- ///! Parse command line arguments that might set cache values
+ //! Parse command line arguments that might set cache values
bool SetCacheArgs(const std::vector<std::string>&);
- typedef void (*ProgressCallbackType)(const char* msg, float progress, void*);
+ using ProgressCallbackType = std::function<void(const std::string&, float)>;
/**
* Set the function used by GUIs to receive progress updates
* Function gets passed: message as a const char*, a progress
@@ -268,25 +330,26 @@ public:
* number provided may be negative in cases where a message is
* to be displayed without any progress percentage.
*/
- void SetProgressCallback(ProgressCallbackType f,
- void* clientData = CM_NULLPTR);
+ void SetProgressCallback(ProgressCallbackType f);
- ///! this is called by generators to update the progress
- void UpdateProgress(const char* msg, float prog);
+ //! this is called by generators to update the progress
+ void UpdateProgress(const std::string& msg, float prog);
- ///! Get the variable watch object
- cmVariableWatch* GetVariableWatch() { return this->VariableWatch; }
+#if !defined(CMAKE_BOOTSTRAP)
+ //! Get the variable watch object
+ cmVariableWatch* GetVariableWatch() { return this->VariableWatch.get(); }
+#endif
- void GetGeneratorDocumentation(std::vector<cmDocumentationEntry>&);
+ std::vector<cmDocumentationEntry> GetGeneratorsDocumentation();
- ///! Set/Get a property of this target file
+ //! Set/Get a property of this target file
void SetProperty(const std::string& prop, const char* value);
void AppendProperty(const std::string& prop, const char* value,
bool asString = false);
const char* GetProperty(const std::string& prop);
bool GetPropertyAsBool(const std::string& prop);
- ///! Get or create an cmInstalledFile instance and return a pointer to it
+ //! Get or create an cmInstalledFile instance and return a pointer to it
cmInstalledFile* GetOrCreateInstalledFile(cmMakefile* mf,
const std::string& name);
@@ -297,13 +360,13 @@ public:
return this->InstalledFiles;
}
- ///! Do all the checks before running configure
+ //! Do all the checks before running configure
int DoPreConfigureChecks();
void SetWorkingMode(WorkingMode mode) { this->CurrentWorkingMode = mode; }
WorkingMode GetWorkingMode() { return this->CurrentWorkingMode; }
- ///! Debug the try compile stuff by not deleting the files
+ //! Debug the try compile stuff by not deleting the files
bool GetDebugTryCompile() { return this->DebugTryCompile; }
void DebugTryCompileOn() { this->DebugTryCompile = true; }
@@ -315,13 +378,18 @@ public:
/**
* Get the file comparison class
*/
- cmFileTimeComparison* GetFileComparison() { return this->FileComparison; }
+ cmFileTimeCache* GetFileTimeCache() { return this->FileTimeCache.get(); }
+
+ //! Get the selected log level for `message()` commands during the cmake run.
+ LogLevel GetLogLevel() const { return this->MessageLogLevel; }
+ void SetLogLevel(LogLevel level) { this->MessageLogLevel = level; }
+ static LogLevel StringToLogLevel(const std::string& levelStr);
- // Do we want debug output during the cmake run.
+ //! Do we want debug output during the cmake run.
bool GetDebugOutput() { return this->DebugOutput; }
void SetDebugOutputOn(bool b) { this->DebugOutput = b; }
- // Do we want trace output during the cmake run.
+ //! Do we want trace output during the cmake run.
bool GetTrace() { return this->Trace; }
void SetTrace(bool b) { this->Trace = b; }
bool GetTraceExpand() { return this->TraceExpand; }
@@ -334,6 +402,9 @@ public:
{
return this->TraceOnlyThisSources;
}
+ cmGeneratedFileStream& GetTraceFile() { return this->TraceFile; }
+ void SetTraceFile(std::string const& file);
+
bool GetWarnUninitialized() { return this->WarnUninitialized; }
void SetWarnUninitialized(bool b) { this->WarnUninitialized = b; }
bool GetWarnUnused() { return this->WarnUnused; }
@@ -358,31 +429,31 @@ public:
return this->CMakeEditCommand;
}
- cmMessenger* GetMessenger() const;
+ cmMessenger* GetMessenger() const { return this->Messenger.get(); }
- /*
+ /**
* Get the state of the suppression of developer (author) warnings.
* Returns false, by default, if developer warnings should be shown, true
* otherwise.
*/
bool GetSuppressDevWarnings() const;
- /*
+ /**
* Set the state of the suppression of developer (author) warnings.
*/
void SetSuppressDevWarnings(bool v);
- /*
+ /**
* Get the state of the suppression of deprecated warnings.
* Returns false, by default, if deprecated warnings should be shown, true
* otherwise.
*/
bool GetSuppressDeprecatedWarnings() const;
- /*
+ /**
* Set the state of the suppression of deprecated warnings.
*/
void SetSuppressDeprecatedWarnings(bool v);
- /*
+ /**
* Get the state of treating developer (author) warnings as errors.
* Returns false, by default, if warnings should not be treated as errors,
* true otherwise.
@@ -393,7 +464,7 @@ public:
*/
void SetDevWarningsAsErrors(bool v);
- /*
+ /**
* Get the state of treating deprecated warnings as errors.
* Returns false, by default, if warnings should not be treated as errors,
* true otherwise.
@@ -406,18 +477,22 @@ public:
/** Display a message to the user. */
void IssueMessage(
- cmake::MessageType t, std::string const& text,
+ MessageType t, std::string const& text,
cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const;
- ///! run the --build option
- int Build(const std::string& dir, const std::string& target,
- const std::string& config,
- const std::vector<std::string>& nativeOptions, bool clean);
+ //! run the --build option
+ int Build(int jobs, const std::string& dir,
+ const std::vector<std::string>& targets, const std::string& config,
+ const std::vector<std::string>& nativeOptions, bool clean,
+ bool verbose);
+
+ //! run the --open option
+ bool Open(const std::string& dir, bool dryRun);
void UnwatchUnusedCli(const std::string& var);
void WatchUnusedCli(const std::string& var);
- cmState* GetState() const { return this->State; }
+ cmState* GetState() const { return this->State.get(); }
void SetCurrentSnapshot(cmStateSnapshot const& snapshot)
{
this->CurrentSnapshot = snapshot;
@@ -426,29 +501,33 @@ public:
protected:
void RunCheckForUnusedVariables();
- void InitializeProperties();
int HandleDeleteCacheVariables(const std::string& var);
- typedef std::vector<cmGlobalGeneratorFactory*> RegisteredGeneratorsVector;
+ using RegisteredGeneratorsVector = std::vector<cmGlobalGeneratorFactory*>;
RegisteredGeneratorsVector Generators;
- typedef std::vector<cmExternalMakefileProjectGeneratorFactory*>
- RegisteredExtraGeneratorsVector;
+ using RegisteredExtraGeneratorsVector =
+ std::vector<cmExternalMakefileProjectGeneratorFactory*>;
RegisteredExtraGeneratorsVector ExtraGenerators;
void AddScriptingCommands();
void AddProjectCommands();
void AddDefaultGenerators();
void AddDefaultExtraGenerators();
- cmGlobalGenerator* GlobalGenerator;
+ cmGlobalGenerator* GlobalGenerator = nullptr;
std::map<std::string, DiagLevel> DiagLevels;
+ std::string GeneratorInstance;
std::string GeneratorPlatform;
std::string GeneratorToolset;
+ bool GeneratorInstanceSet = false;
+ bool GeneratorPlatformSet = false;
+ bool GeneratorToolsetSet = false;
- ///! read in a cmake list file to initialize the cache
- void ReadListFile(const std::vector<std::string>& args, const char* path);
+ //! read in a cmake list file to initialize the cache
+ void ReadListFile(const std::vector<std::string>& args,
+ const std::string& path);
bool FindPackage(const std::vector<std::string>& args);
- ///! Check if CMAKE_CACHEFILE_DIR is set. If it is not, delete the log file.
+ //! Check if CMAKE_CACHEFILE_DIR is set. If it is not, delete the log file.
/// If it is set, truncate it to 50kb
void TruncateOutputLog(const char* fname);
@@ -458,28 +537,25 @@ protected:
*/
int CheckBuildSystem();
- void SetDirectoriesFromFile(const char* arg);
+ void SetDirectoriesFromFile(const std::string& arg);
//! Make sure all commands are what they say they are and there is no
/// macros.
void CleanupCommandsAndMacros();
- void GenerateGraphViz(const char* fileName) const;
-
- cmVariableWatch* VariableWatch;
+ void GenerateGraphViz(const std::string& fileName) const;
private:
ProgressCallbackType ProgressCallback;
- void* ProgressCallbackClientData;
- bool InTryCompile;
- WorkingMode CurrentWorkingMode;
- bool DebugOutput;
- bool Trace;
- bool TraceExpand;
- bool WarnUninitialized;
- bool WarnUnused;
- bool WarnUnusedCli;
- bool CheckSystemVars;
+ WorkingMode CurrentWorkingMode = NORMAL_MODE;
+ bool DebugOutput = false;
+ bool Trace = false;
+ bool TraceExpand = false;
+ cmGeneratedFileStream TraceFile;
+ bool WarnUninitialized = false;
+ bool WarnUnused = false;
+ bool WarnUnusedCli = true;
+ bool CheckSystemVars = false;
std::map<std::string, bool> UsedCliVariables;
std::string CMakeEditCommand;
std::string CXXEnvironment;
@@ -488,43 +564,47 @@ private:
std::string CheckStampFile;
std::string CheckStampList;
std::string VSSolutionFile;
- std::vector<std::string> SourceFileExtensions;
- std::vector<std::string> HeaderFileExtensions;
- bool ClearBuildSystem;
- bool DebugTryCompile;
- cmFileTimeComparison* FileComparison;
+ std::string EnvironmentGenerator;
+ FileExtensions SourceFileExtensions;
+ FileExtensions HeaderFileExtensions;
+ FileExtensions CudaFileExtensions;
+ FileExtensions FortranFileExtensions;
+ bool ClearBuildSystem = false;
+ bool DebugTryCompile = false;
+ std::unique_ptr<cmFileTimeCache> FileTimeCache;
std::string GraphVizFile;
InstalledFilesMap InstalledFiles;
- cmState* State;
+#if !defined(CMAKE_BOOTSTRAP)
+ std::unique_ptr<cmVariableWatch> VariableWatch;
+ std::unique_ptr<cmFileAPI> FileAPI;
+#endif
+
+ std::unique_ptr<cmState> State;
cmStateSnapshot CurrentSnapshot;
- cmMessenger* Messenger;
+ std::unique_ptr<cmMessenger> Messenger;
std::vector<std::string> TraceOnlyThisSources;
+ LogLevel MessageLogLevel = LogLevel::LOG_STATUS;
+
void UpdateConversionPathTable();
- // Print a list of valid generators to stderr.
+ //! Print a list of valid generators to stderr.
void PrintGeneratorList();
+ std::unique_ptr<cmGlobalGenerator> EvaluateDefaultGlobalGenerator();
void CreateDefaultGlobalGenerator();
- /**
- * Convert a message type between a warning and an error, based on the state
- * of the error output CMake variables, in the cache.
- */
- cmake::MessageType ConvertMessageType(cmake::MessageType t) const;
-
- /*
- * Check if messages of this type should be output, based on the state of the
- * warning and error output CMake variables, in the cache.
- */
- bool IsMessageTypeVisible(cmake::MessageType t) const;
+ void AppendGlobalGeneratorsDocumentation(std::vector<cmDocumentationEntry>&);
+ void AppendExtraGeneratorsDocumentation(std::vector<cmDocumentationEntry>&);
};
#define CMAKE_STANDARD_OPTIONS_TABLE \
- { "-C <initial-cache>", "Pre-load a script to populate the cache." }, \
- { "-D <var>[:<type>]=<value>", "Create a cmake cache entry." }, \
+ { "-S <path-to-source>", "Explicitly specify a source directory." }, \
+ { "-B <path-to-build>", "Explicitly specify a build directory." }, \
+ { "-C <initial-cache>", "Pre-load a script to populate the cache." }, \
+ { "-D <var>[:<type>]=<value>", "Create or update a cmake cache entry." }, \
{ "-U <globbing_expr>", "Remove matching entries from CMake cache." }, \
{ "-G <generator-name>", "Specify a build system generator." }, \
{ "-T <toolset-name>", \
@@ -537,46 +617,47 @@ private:
{ "-Wno-error=dev", "Make developer warnings not errors." }, \
{ "-Wdeprecated", "Enable deprecation warnings." }, \
{ "-Wno-deprecated", "Suppress deprecation warnings." }, \
- { "-Werror=deprecated", "Make deprecated macro and function warnings " \
- "errors." }, \
+ { "-Werror=deprecated", \
+ "Make deprecated macro and function warnings " \
+ "errors." }, \
{ \
- "-Wno-error=deprecated", "Make deprecated macro and function warnings " \
- "not errors." \
+ "-Wno-error=deprecated", \
+ "Make deprecated macro and function warnings " \
+ "not errors." \
}
+#define FOR_EACH_C90_FEATURE(F) F(c_function_prototypes)
+
+#define FOR_EACH_C99_FEATURE(F) \
+ F(c_restrict) \
+ F(c_variadic_macros)
+
+#define FOR_EACH_C11_FEATURE(F) F(c_static_assert)
+
#define FOR_EACH_C_FEATURE(F) \
F(c_std_90) \
F(c_std_99) \
F(c_std_11) \
- F(c_function_prototypes) \
- F(c_restrict) \
- F(c_static_assert) \
- F(c_variadic_macros)
+ FOR_EACH_C90_FEATURE(F) \
+ FOR_EACH_C99_FEATURE(F) \
+ FOR_EACH_C11_FEATURE(F)
-#define FOR_EACH_CXX_FEATURE(F) \
- F(cxx_std_98) \
- F(cxx_std_11) \
- F(cxx_std_14) \
- F(cxx_std_17) \
- F(cxx_aggregate_default_initializers) \
+#define FOR_EACH_CXX98_FEATURE(F) F(cxx_template_template_parameters)
+
+#define FOR_EACH_CXX11_FEATURE(F) \
F(cxx_alias_templates) \
F(cxx_alignas) \
F(cxx_alignof) \
F(cxx_attributes) \
- F(cxx_attribute_deprecated) \
F(cxx_auto_type) \
- F(cxx_binary_literals) \
F(cxx_constexpr) \
- F(cxx_contextual_conversions) \
F(cxx_decltype) \
- F(cxx_decltype_auto) \
F(cxx_decltype_incomplete_return_types) \
F(cxx_default_function_template_args) \
F(cxx_defaulted_functions) \
F(cxx_defaulted_move_initializers) \
F(cxx_delegating_constructors) \
F(cxx_deleted_functions) \
- F(cxx_digit_separators) \
F(cxx_enum_forward_declarations) \
F(cxx_explicit_conversions) \
F(cxx_extended_friend_declarations) \
@@ -584,11 +665,9 @@ private:
F(cxx_final) \
F(cxx_func_identifier) \
F(cxx_generalized_initializers) \
- F(cxx_generic_lambdas) \
F(cxx_inheriting_constructors) \
F(cxx_inline_namespaces) \
F(cxx_lambdas) \
- F(cxx_lambda_init_captures) \
F(cxx_local_type_template_args) \
F(cxx_long_long_type) \
F(cxx_noexcept) \
@@ -598,22 +677,41 @@ private:
F(cxx_range_for) \
F(cxx_raw_string_literals) \
F(cxx_reference_qualified_functions) \
- F(cxx_relaxed_constexpr) \
- F(cxx_return_type_deduction) \
F(cxx_right_angle_brackets) \
F(cxx_rvalue_references) \
F(cxx_sizeof_member) \
F(cxx_static_assert) \
F(cxx_strong_enums) \
- F(cxx_template_template_parameters) \
F(cxx_thread_local) \
F(cxx_trailing_return_types) \
F(cxx_unicode_literals) \
F(cxx_uniform_initialization) \
F(cxx_unrestricted_unions) \
F(cxx_user_literals) \
- F(cxx_variable_templates) \
F(cxx_variadic_macros) \
F(cxx_variadic_templates)
+#define FOR_EACH_CXX14_FEATURE(F) \
+ F(cxx_aggregate_default_initializers) \
+ F(cxx_attribute_deprecated) \
+ F(cxx_binary_literals) \
+ F(cxx_contextual_conversions) \
+ F(cxx_decltype_auto) \
+ F(cxx_digit_separators) \
+ F(cxx_generic_lambdas) \
+ F(cxx_lambda_init_captures) \
+ F(cxx_relaxed_constexpr) \
+ F(cxx_return_type_deduction) \
+ F(cxx_variable_templates)
+
+#define FOR_EACH_CXX_FEATURE(F) \
+ F(cxx_std_98) \
+ F(cxx_std_11) \
+ F(cxx_std_14) \
+ F(cxx_std_17) \
+ F(cxx_std_20) \
+ FOR_EACH_CXX98_FEATURE(F) \
+ FOR_EACH_CXX11_FEATURE(F) \
+ FOR_EACH_CXX14_FEATURE(F)
+
#endif
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index da1fe6d64..6d3e6ee30 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -1,126 +1,123 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmConfigure.h"
#include "cmAlgorithms.h"
-#include "cmDocumentationEntry.h"
+#include "cmDocumentationEntry.h" // IWYU pragma: keep
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
#include "cmcmd.h"
-#ifdef CMAKE_BUILD_WITH_CMAKE
-#include "cmDocumentation.h"
-#include "cmDynamicLoader.h"
+#ifndef CMAKE_BOOTSTRAP
+# include "cmDocumentation.h"
+# include "cmDynamicLoader.h"
#endif
#include "cmsys/Encoding.hxx"
-#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmsys/ConsoleBuf.hxx"
+
+#include "cm_uv.h"
+#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
+# include "cmsys/ConsoleBuf.hxx"
#endif
+
+#include <cassert>
+#include <cctype>
+#include <climits>
+#include <cstring>
#include <iostream>
-#include <string.h>
#include <string>
#include <vector>
-#ifdef CMAKE_USE_LIBUV
-#ifdef _WIN32
-#include <fcntl.h> /* _O_TEXT */
-#include <stdlib.h> /* _set_fmode, _fmode */
-#endif
-#include "cm_uv.h"
-#endif
-
-#ifdef CMAKE_BUILD_WITH_CMAKE
-static const char* cmDocumentationName[][2] = {
- { CM_NULLPTR, " cmake - Cross-Platform Makefile Generator." },
- { CM_NULLPTR, CM_NULLPTR }
+namespace {
+#ifndef CMAKE_BOOTSTRAP
+const char* cmDocumentationName[][2] = {
+ { nullptr, " cmake - Cross-Platform Makefile Generator." },
+ { nullptr, nullptr }
};
-static const char* cmDocumentationUsage[][2] = {
- { CM_NULLPTR, " cmake [options] <path-to-source>\n"
- " cmake [options] <path-to-existing-build>" },
- { CM_NULLPTR,
+const char* cmDocumentationUsage[][2] = {
+ { nullptr,
+ " cmake [options] <path-to-source>\n"
+ " cmake [options] <path-to-existing-build>\n"
+ " cmake [options] -S <path-to-source> -B <path-to-build>" },
+ { nullptr,
"Specify a source directory to (re-)generate a build system for "
"it in the current working directory. Specify an existing build "
"directory to re-generate its build system." },
- { CM_NULLPTR, CM_NULLPTR }
+ { nullptr, nullptr }
};
-static const char* cmDocumentationUsageNote[][2] = {
- { CM_NULLPTR, "Run 'cmake --help' for more information." },
- { CM_NULLPTR, CM_NULLPTR }
+const char* cmDocumentationUsageNote[][2] = {
+ { nullptr, "Run 'cmake --help' for more information." },
+ { nullptr, nullptr }
};
-#define CMAKE_BUILD_OPTIONS \
- " <dir> = Project binary directory to be built.\n" \
- " --target <tgt> = Build <tgt> instead of default targets.\n" \
- " May only be specified once.\n" \
- " --config <cfg> = For multi-configuration tools, choose <cfg>.\n" \
- " --clean-first = Build target 'clean' first, then build.\n" \
- " (To clean only, use --target 'clean'.)\n" \
- " --use-stderr = Ignored. Behavior is default in CMake >= 3.0.\n" \
- " -- = Pass remaining options to the native tool.\n"
-
-static const char* cmDocumentationOptions[][2] = {
+const char* cmDocumentationOptions[][2] = {
CMAKE_STANDARD_OPTIONS_TABLE,
{ "-E", "CMake command mode." },
{ "-L[A][H]", "List non-advanced cached variables." },
{ "--build <dir>", "Build a CMake-generated project binary tree." },
+ { "--install <dir>", "Install 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." },
- { "--graphviz=[file]", "Generate graphviz of dependencies, see "
- "CMakeGraphVizOptions.cmake for more." },
+ { "--graphviz=[file]",
+ "Generate graphviz of dependencies, see "
+ "CMakeGraphVizOptions.cmake for more." },
{ "--system-information [file]", "Dump information about this system." },
- { "--debug-trycompile", "Do not delete the try_compile build tree. Only "
- "useful on one try_compile at a time." },
+ { "--log-level=<ERROR|WARNING|NOTICE|STATUS|VERBOSE|DEBUG|TRACE>",
+ "Set the verbosity of messages from CMake files. "
+ "--loglevel is also accepted for backward compatibility reasons." },
+ { "--debug-trycompile",
+ "Do not delete the try_compile build tree. Only "
+ "useful on one try_compile at a time." },
{ "--debug-output", "Put cmake in a debug mode." },
{ "--trace", "Put cmake in trace mode." },
{ "--trace-expand", "Put cmake in trace mode with variable expansion." },
{ "--trace-source=<file>",
"Trace only this CMake file/module. Multiple options allowed." },
+ { "--trace-redirect=<file>",
+ "Redirect trace output to a file instead of stderr." },
{ "--warn-uninitialized", "Warn about uninitialized values." },
{ "--warn-unused-vars", "Warn about unused variables." },
{ "--no-warn-unused-cli", "Don't warn about command line options." },
- { "--check-system-vars", "Find problems with variable usage in system "
- "files." },
- { CM_NULLPTR, CM_NULLPTR }
+ { "--check-system-vars",
+ "Find problems with variable usage in system "
+ "files." },
+ { nullptr, nullptr }
};
#endif
-static int do_command(int ac, char const* const* av)
+int do_command(int ac, char const* const* av)
{
std::vector<std::string> args;
args.reserve(ac - 1);
- args.push_back(av[0]);
- args.insert(args.end(), av + 2, av + ac);
+ args.emplace_back(av[0]);
+ cmAppend(args, av + 2, av + ac);
return cmcmd::ExecuteCMakeCommand(args);
}
-int do_cmake(int ac, char const* const* av);
-static int do_build(int ac, char const* const* av);
-
-static cmMakefile* cmakemainGetMakefile(void* clientdata)
+cmMakefile* cmakemainGetMakefile(cmake* cm)
{
- cmake* cm = (cmake*)clientdata;
if (cm && cm->GetDebugOutput()) {
cmGlobalGenerator* gg = cm->GetGlobalGenerator();
if (gg) {
return gg->GetCurrentMakefile();
}
}
- return CM_NULLPTR;
+ return nullptr;
}
-static std::string cmakemainGetStack(void* clientdata)
+std::string cmakemainGetStack(cmake* cm)
{
std::string msg;
- cmMakefile* mf = cmakemainGetMakefile(clientdata);
+ cmMakefile* mf = cmakemainGetMakefile(cm);
if (mf) {
msg = mf->FormatListFileStack();
if (!msg.empty()) {
@@ -131,77 +128,25 @@ static std::string cmakemainGetStack(void* clientdata)
return msg;
}
-static void cmakemainMessageCallback(const char* m, const char* /*unused*/,
- bool& /*unused*/, void* clientdata)
+void cmakemainMessageCallback(const std::string& m, const char* /*unused*/,
+ cmake* cm)
{
- std::cerr << m << cmakemainGetStack(clientdata) << std::endl << std::flush;
+ std::cerr << m << cmakemainGetStack(cm) << std::endl;
}
-static void cmakemainProgressCallback(const char* m, float prog,
- void* clientdata)
+void cmakemainProgressCallback(const std::string& m, float prog, cmake* cm)
{
- cmMakefile* mf = cmakemainGetMakefile(clientdata);
+ cmMakefile* mf = cmakemainGetMakefile(cm);
std::string dir;
- if ((mf) && (strstr(m, "Configuring") == m) && (prog < 0)) {
- dir = " ";
- dir += mf->GetCurrentSourceDirectory();
- } else if ((mf) && (strstr(m, "Generating") == m)) {
- dir = " ";
- dir += mf->GetCurrentBinaryDirectory();
+ if (mf && cmHasLiteralPrefix(m, "Configuring") && (prog < 0)) {
+ dir = cmStrCat(' ', mf->GetCurrentSourceDirectory());
+ } else if (mf && cmHasLiteralPrefix(m, "Generating")) {
+ dir = cmStrCat(' ', mf->GetCurrentBinaryDirectory());
}
if ((prog < 0) || (!dir.empty())) {
- std::cout << "-- " << m << dir << cmakemainGetStack(clientdata)
- << std::endl;
+ std::cout << "-- " << m << dir << cmakemainGetStack(cm) << std::endl;
}
-
- std::cout.flush();
-}
-
-int main(int ac, char const* const* av)
-{
-#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
- // Replace streambuf so we can output Unicode to console
- cmsys::ConsoleBuf::Manager consoleOut(std::cout);
- consoleOut.SetUTF8Pipes();
- cmsys::ConsoleBuf::Manager consoleErr(std::cerr, true);
- consoleErr.SetUTF8Pipes();
-#endif
- cmsys::Encoding::CommandLineArguments args =
- cmsys::Encoding::CommandLineArguments::Main(ac, av);
- ac = args.argc();
- av = args.argv();
-
-#if defined(CMAKE_USE_LIBUV) && 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::FindCMakeResources(av[0]);
- if (ac > 1) {
- if (strcmp(av[1], "--build") == 0) {
- return do_build(ac, av);
- }
- if (strcmp(av[1], "-E") == 0) {
- return do_command(ac, av);
- }
- }
- int ret = do_cmake(ac, av);
-#ifdef CMAKE_BUILD_WITH_CMAKE
- cmDynamicLoader::FlushCache();
-#endif
-#ifdef CMAKE_USE_LIBUV
- uv_loop_close(uv_default_loop());
-#endif
- return ret;
}
int do_cmake(int ac, char const* const* av)
@@ -212,12 +157,12 @@ int do_cmake(int ac, char const* const* av)
return 1;
}
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
cmDocumentation doc;
doc.addCMakeStandardDocSections();
if (doc.CheckOptions(ac, av)) {
// Construct and print requested documentation.
- cmake hcm(cmake::RoleInternal);
+ cmake hcm(cmake::RoleInternal, cmState::Unknown);
hcm.SetHomeDirectory("");
hcm.SetHomeOutputDirectory("");
hcm.AddCMakePaths();
@@ -227,9 +172,7 @@ int do_cmake(int ac, char const* const* av)
std::vector<std::string> args(av, av + ac);
hcm.SetCacheArgs(args);
- std::vector<cmDocumentationEntry> generators;
-
- hcm.GetGeneratorDocumentation(generators);
+ auto generators = hcm.GetGeneratorsDocumentation();
doc.SetName("cmake");
doc.SetSection("Name", cmDocumentationName);
@@ -285,21 +228,21 @@ int do_cmake(int ac, char const* const* av)
} else if (cmHasLiteralPrefix(av[i], "-P")) {
if (i == ac - 1) {
cmSystemTools::Error("No script specified for argument -P");
- } else {
- workingMode = cmake::SCRIPT_MODE;
- args.push_back(av[i]);
- i++;
- args.push_back(av[i]);
+ return 1;
}
+ workingMode = cmake::SCRIPT_MODE;
+ args.emplace_back(av[i]);
+ i++;
+ args.emplace_back(av[i]);
} else if (cmHasLiteralPrefix(av[i], "--find-package")) {
workingMode = cmake::FIND_PACKAGE_MODE;
- args.push_back(av[i]);
+ args.emplace_back(av[i]);
} else {
- args.push_back(av[i]);
+ args.emplace_back(av[i]);
}
}
if (sysinfo) {
- cmake cm(cmake::RoleProject);
+ cmake cm(cmake::RoleProject, cmState::Project);
cm.SetHomeDirectory("");
cm.SetHomeOutputDirectory("");
int ret = cm.GetSystemInformation(args);
@@ -307,33 +250,48 @@ int do_cmake(int ac, char const* const* av)
}
cmake::Role const role =
workingMode == cmake::SCRIPT_MODE ? cmake::RoleScript : cmake::RoleProject;
- cmake cm(role);
+ cmState::Mode mode = cmState::Unknown;
+ switch (workingMode) {
+ case cmake::NORMAL_MODE:
+ mode = cmState::Project;
+ break;
+ case cmake::SCRIPT_MODE:
+ mode = cmState::Script;
+ break;
+ case cmake::FIND_PACKAGE_MODE:
+ mode = cmState::FindPackage;
+ break;
+ }
+ cmake cm(role, mode);
cm.SetHomeDirectory("");
cm.SetHomeOutputDirectory("");
- cmSystemTools::SetMessageCallback(cmakemainMessageCallback, (void*)&cm);
- cm.SetProgressCallback(cmakemainProgressCallback, (void*)&cm);
+ cmSystemTools::SetMessageCallback(
+ [&cm](const std::string& msg, const char* title) {
+ cmakemainMessageCallback(msg, title, &cm);
+ });
+ cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
+ cmakemainProgressCallback(msg, prog, &cm);
+ });
cm.SetWorkingMode(workingMode);
int res = cm.Run(args, view_only);
if (list_cached || list_all_cached) {
std::cout << "-- Cache values" << std::endl;
std::vector<std::string> keys = cm.GetState()->GetCacheEntryKeys();
- for (std::vector<std::string>::const_iterator it = keys.begin();
- it != keys.end(); ++it) {
- cmStateEnums::CacheEntryType t = cm.GetState()->GetCacheEntryType(*it);
+ for (std::string const& k : keys) {
+ cmStateEnums::CacheEntryType t = cm.GetState()->GetCacheEntryType(k);
if (t != cmStateEnums::INTERNAL && t != cmStateEnums::STATIC &&
t != cmStateEnums::UNINITIALIZED) {
const char* advancedProp =
- cm.GetState()->GetCacheEntryProperty(*it, "ADVANCED");
+ cm.GetState()->GetCacheEntryProperty(k, "ADVANCED");
if (list_all_cached || !advancedProp) {
if (list_help) {
std::cout << "// "
- << cm.GetState()->GetCacheEntryProperty(*it,
- "HELPSTRING")
+ << cm.GetState()->GetCacheEntryProperty(k, "HELPSTRING")
<< std::endl;
}
- std::cout << *it << ":" << cmState::CacheEntryTypeToString(t) << "="
- << cm.GetState()->GetCacheEntryValue(*it) << std::endl;
+ std::cout << k << ":" << cmState::CacheEntryTypeToString(t) << "="
+ << cm.GetState()->GetCacheEntryValue(k) << std::endl;
if (list_help) {
std::cout << std::endl;
}
@@ -350,18 +308,51 @@ int do_cmake(int ac, char const* const* av)
return 0;
}
-static int do_build(int ac, char const* const* av)
+int extract_job_number(int& index, char const* current, char const* next,
+ int len_of_flag)
{
-#ifndef CMAKE_BUILD_WITH_CMAKE
+ std::string command(current);
+ std::string jobString = command.substr(len_of_flag);
+ if (jobString.empty() && next && isdigit(next[0])) {
+ ++index; // skip parsing the job number
+ jobString = std::string(next);
+ }
+
+ int jobs = -1;
+ unsigned long numJobs = 0;
+ if (jobString.empty()) {
+ jobs = cmake::DEFAULT_BUILD_PARALLEL_LEVEL;
+ } else if (cmStrToULong(jobString, &numJobs)) {
+ if (numJobs == 0) {
+ std::cerr
+ << "The <jobs> value requires a positive integer argument.\n\n";
+ } else if (numJobs > INT_MAX) {
+ std::cerr << "The <jobs> value is too large.\n\n";
+ } else {
+ jobs = int(numJobs);
+ }
+ } else {
+ std::cerr << "'" << command.substr(0, len_of_flag) << "' invalid number '"
+ << jobString << "' given.\n\n";
+ }
+ return jobs;
+}
+
+int do_build(int ac, char const* const* av)
+{
+#ifdef CMAKE_BOOTSTRAP
std::cerr << "This cmake does not support --build\n";
return -1;
#else
- std::string target;
+ int jobs = cmake::NO_BUILD_PARALLEL_LEVEL;
+ std::vector<std::string> targets;
std::string config = "Debug";
std::string dir;
std::vector<std::string> nativeOptions;
- bool clean = false;
- bool hasTarget = false;
+ bool cleanFirst = false;
+ bool foundClean = false;
+ bool foundNonClean = false;
+ bool verbose = cmSystemTools::HasEnv("VERBOSE");
enum Doing
{
@@ -374,20 +365,32 @@ static int do_build(int ac, char const* const* av)
Doing doing = DoingDir;
for (int i = 2; i < ac; ++i) {
if (doing == DoingNative) {
- nativeOptions.push_back(av[i]);
- } else if (strcmp(av[i], "--target") == 0) {
- if (!hasTarget) {
- doing = DoingTarget;
- hasTarget = true;
- } else {
- std::cerr << "'--target' may not be specified more than once.\n\n";
- dir = "";
- break;
+ nativeOptions.emplace_back(av[i]);
+ } else if (cmHasLiteralPrefix(av[i], "-j")) {
+ const char* nextArg = ((i + 1 < ac) ? av[i + 1] : nullptr);
+ jobs = extract_job_number(i, av[i], nextArg, sizeof("-j") - 1);
+ if (jobs < 0) {
+ dir.clear();
}
+ doing = DoingNone;
+ } else if (cmHasLiteralPrefix(av[i], "--parallel")) {
+ const char* nextArg = ((i + 1 < ac) ? av[i + 1] : nullptr);
+ jobs = extract_job_number(i, av[i], nextArg, sizeof("--parallel") - 1);
+ if (jobs < 0) {
+ dir.clear();
+ }
+ doing = DoingNone;
+ } else if ((strcmp(av[i], "--target") == 0) ||
+ (strcmp(av[i], "-t") == 0)) {
+ doing = DoingTarget;
} else if (strcmp(av[i], "--config") == 0) {
doing = DoingConfig;
} else if (strcmp(av[i], "--clean-first") == 0) {
- clean = true;
+ cleanFirst = true;
+ doing = DoingNone;
+ } else if ((strcmp(av[i], "--verbose") == 0) ||
+ (strcmp(av[i], "-v") == 0)) {
+ verbose = true;
doing = DoingNone;
} else if (strcmp(av[i], "--use-stderr") == 0) {
/* tolerate legacy option */
@@ -400,8 +403,23 @@ static int do_build(int ac, char const* const* av)
doing = DoingNone;
break;
case DoingTarget:
- target = av[i];
- doing = DoingNone;
+ if (strlen(av[i]) == 0) {
+ std::cerr << "Warning: Argument number " << i
+ << " after --target option is empty." << std::endl;
+ } else {
+ targets.emplace_back(av[i]);
+ if (strcmp(av[i], "clean") == 0) {
+ foundClean = true;
+ } else {
+ foundNonClean = true;
+ }
+ }
+ if (foundClean && foundNonClean) {
+ std::cerr << "Error: Building 'clean' and other targets together "
+ "is not supported."
+ << std::endl;
+ dir.clear();
+ }
break;
case DoingConfig:
config = av[i];
@@ -409,25 +427,282 @@ static int do_build(int ac, char const* const* av)
break;
default:
std::cerr << "Unknown argument " << av[i] << std::endl;
- dir = "";
+ dir.clear();
break;
}
}
}
+
+ if (jobs == cmake::NO_BUILD_PARALLEL_LEVEL) {
+ std::string parallel;
+ if (cmSystemTools::GetEnv("CMAKE_BUILD_PARALLEL_LEVEL", parallel)) {
+ if (parallel.empty()) {
+ jobs = cmake::DEFAULT_BUILD_PARALLEL_LEVEL;
+ } else {
+ unsigned long numJobs = 0;
+ if (cmStrToULong(parallel, &numJobs)) {
+ if (numJobs == 0) {
+ std::cerr << "The CMAKE_BUILD_PARALLEL_LEVEL environment variable "
+ "requires a positive integer argument.\n\n";
+ dir.clear();
+ } else if (numJobs > INT_MAX) {
+ std::cerr << "The CMAKE_BUILD_PARALLEL_LEVEL environment variable "
+ "is too large.\n\n";
+ dir.clear();
+ } else {
+ jobs = int(numJobs);
+ }
+ } else {
+ std::cerr << "'CMAKE_BUILD_PARALLEL_LEVEL' environment variable\n"
+ << "invalid number '" << parallel << "' given.\n\n";
+ dir.clear();
+ }
+ }
+ }
+ }
+
if (dir.empty()) {
/* clang-format off */
std::cerr <<
"Usage: cmake --build <dir> [options] [-- [native-options]]\n"
"Options:\n"
- CMAKE_BUILD_OPTIONS
+ " <dir> = Project binary directory to be built.\n"
+ " --parallel [<jobs>], -j [<jobs>]\n"
+ " = Build in parallel using the given number of jobs. \n"
+ " If <jobs> is omitted the native build tool's \n"
+ " default number is used.\n"
+ " The CMAKE_BUILD_PARALLEL_LEVEL environment "
+ "variable\n"
+ " specifies a default parallel level when this "
+ "option\n"
+ " is not given.\n"
+ " --target <tgt>..., -t <tgt>... \n"
+ " = Build <tgt> instead of default targets.\n"
+ " --config <cfg> = For multi-configuration tools, choose <cfg>.\n"
+ " --clean-first = Build target 'clean' first, then build.\n"
+ " (To clean only, use --target 'clean'.)\n"
+ " --verbose, -v = Enable verbose output - if supported - including\n"
+ " the build commands to be executed. \n"
+ " -- = Pass remaining options to the native tool.\n"
+ ;
+ /* clang-format on */
+ return 1;
+ }
+
+ cmake cm(cmake::RoleInternal, cmState::Project);
+ cmSystemTools::SetMessageCallback(
+ [&cm](const std::string& msg, const char* title) {
+ cmakemainMessageCallback(msg, title, &cm);
+ });
+ cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
+ cmakemainProgressCallback(msg, prog, &cm);
+ });
+ return cm.Build(jobs, dir, targets, config, nativeOptions, cleanFirst,
+ verbose);
+#endif
+}
+
+int do_install(int ac, char const* const* av)
+{
+#ifdef CMAKE_BOOTSTRAP
+ std::cerr << "This cmake does not support --install\n";
+ return -1;
+#else
+ assert(1 < ac);
+
+ std::string config;
+ std::string component;
+ std::string prefix;
+ std::string dir;
+ bool strip = false;
+ bool verbose = cmSystemTools::HasEnv("VERBOSE");
+
+ enum Doing
+ {
+ DoingNone,
+ DoingDir,
+ DoingConfig,
+ DoingComponent,
+ DoingPrefix,
+ };
+
+ Doing doing = DoingDir;
+
+ for (int i = 2; i < ac; ++i) {
+ if (strcmp(av[i], "--config") == 0) {
+ doing = DoingConfig;
+ } else if (strcmp(av[i], "--component") == 0) {
+ doing = DoingComponent;
+ } else if (strcmp(av[i], "--prefix") == 0) {
+ doing = DoingPrefix;
+ } else if (strcmp(av[i], "--strip") == 0) {
+ strip = true;
+ doing = DoingNone;
+ } else if ((strcmp(av[i], "--verbose") == 0) ||
+ (strcmp(av[i], "-v") == 0)) {
+ verbose = true;
+ doing = DoingNone;
+ } else {
+ switch (doing) {
+ case DoingDir:
+ dir = cmSystemTools::CollapseFullPath(av[i]);
+ doing = DoingNone;
+ break;
+ case DoingConfig:
+ config = av[i];
+ doing = DoingNone;
+ break;
+ case DoingComponent:
+ component = av[i];
+ doing = DoingNone;
+ break;
+ case DoingPrefix:
+ prefix = av[i];
+ doing = DoingNone;
+ break;
+ default:
+ std::cerr << "Unknown argument " << av[i] << std::endl;
+ dir.clear();
+ break;
+ }
+ }
+ }
+
+ if (dir.empty()) {
+ /* clang-format off */
+ std::cerr <<
+ "Usage: cmake --install <dir> [options]\n"
+ "Options:\n"
+ " <dir> = Project binary directory to install.\n"
+ " --config <cfg> = For multi-configuration tools, choose <cfg>.\n"
+ " --component <comp> = Component-based install. Only install <comp>.\n"
+ " --prefix <prefix> = The installation prefix CMAKE_INSTALL_PREFIX.\n"
+ " --strip = Performing install/strip.\n"
+ " -v --verbose = Enable verbose output.\n"
;
/* clang-format on */
return 1;
}
- cmake cm(cmake::RoleInternal);
- cmSystemTools::SetMessageCallback(cmakemainMessageCallback, (void*)&cm);
- cm.SetProgressCallback(cmakemainProgressCallback, (void*)&cm);
- return cm.Build(dir, target, config, nativeOptions, clean);
+ cmake cm(cmake::RoleScript, cmState::Script);
+
+ cmSystemTools::SetMessageCallback(
+ [&cm](const std::string& msg, const char* title) {
+ cmakemainMessageCallback(msg, title, &cm);
+ });
+ cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
+ cmakemainProgressCallback(msg, prog, &cm);
+ });
+ cm.SetHomeDirectory("");
+ cm.SetHomeOutputDirectory("");
+ cm.SetDebugOutputOn(verbose);
+ cm.SetWorkingMode(cmake::SCRIPT_MODE);
+
+ std::vector<std::string> args{ av[0] };
+
+ if (!prefix.empty()) {
+ args.emplace_back("-DCMAKE_INSTALL_PREFIX=" + prefix);
+ }
+
+ if (!component.empty()) {
+ args.emplace_back("-DCMAKE_INSTALL_COMPONENT=" + component);
+ }
+
+ if (strip) {
+ args.emplace_back("-DCMAKE_INSTALL_DO_STRIP=1");
+ }
+
+ if (!config.empty()) {
+ args.emplace_back("-DCMAKE_INSTALL_CONFIG_NAME=" + config);
+ }
+
+ args.emplace_back("-P");
+ args.emplace_back(dir + "/cmake_install.cmake");
+
+ return cm.Run(args) ? 1 : 0;
+#endif
+}
+
+int do_open(int ac, char const* const* av)
+{
+#ifdef CMAKE_BOOTSTRAP
+ 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, cmState::Unknown);
+ cmSystemTools::SetMessageCallback(
+ [&cm](const std::string& msg, const char* title) {
+ cmakemainMessageCallback(msg, title, &cm);
+ });
+ cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
+ cmakemainProgressCallback(msg, prog, &cm);
+ });
+ return cm.Open(dir, false) ? 0 : 1;
#endif
}
+} // namespace
+
+int main(int ac, char const* const* av)
+{
+ cmSystemTools::EnsureStdPipes();
+#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
+ // Replace streambuf so we can output Unicode to console
+ cmsys::ConsoleBuf::Manager consoleOut(std::cout);
+ consoleOut.SetUTF8Pipes();
+ cmsys::ConsoleBuf::Manager consoleErr(std::cerr, true);
+ consoleErr.SetUTF8Pipes();
+#endif
+ cmsys::Encoding::CommandLineArguments args =
+ cmsys::Encoding::CommandLineArguments::Main(ac, av);
+ ac = args.argc();
+ av = args.argv();
+
+ 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], "--install") == 0) {
+ return do_install(ac, av);
+ }
+ if (strcmp(av[1], "--open") == 0) {
+ return do_open(ac, av);
+ }
+ if (strcmp(av[1], "-E") == 0) {
+ return do_command(ac, av);
+ }
+ }
+ int ret = do_cmake(ac, av);
+#ifndef CMAKE_BOOTSTRAP
+ cmDynamicLoader::FlushCache();
+#endif
+ uv_loop_close(uv_default_loop());
+ return ret;
+}
diff --git a/Source/cmakexbuild.cxx b/Source/cmakexbuild.cxx
deleted file mode 100644
index 72da456d4..000000000
--- a/Source/cmakexbuild.cxx
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include "cmsys/Process.h"
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "cmSystemTools.h"
-
-// This is a wrapper program for xcodebuild
-// it calls xcodebuild, and does two things
-// it removes much of the output, all the setenv
-// stuff. Also, it checks for the text file busy
-// error, and re-runs xcodebuild until that error does
-// not show up.
-
-int RunXCode(std::vector<const char*>& argv, bool& hitbug)
-{
- hitbug = false;
- cmsysProcess* cp = cmsysProcess_New();
- cmsysProcess_SetCommand(cp, &*argv.begin());
- cmsysProcess_SetTimeout(cp, 0);
- cmsysProcess_Execute(cp);
- std::vector<char> out;
- std::vector<char> err;
- std::string line;
- int pipe = cmSystemTools::WaitForLine(cp, line, 100.0, out, err);
- while (pipe != cmsysProcess_Pipe_None) {
- if (line.find("/bin/sh: bad interpreter: Text file busy") !=
- std::string::npos) {
- hitbug = true;
- std::cerr << "Hit xcodebuild bug : " << line << "\n";
- }
- // if the bug is hit, no more output should be generated
- // because it may contain bogus errors
- // also remove all output with setenv in it to tone down
- // the verbosity of xcodebuild
- if (!hitbug && (line.find("setenv") == std::string::npos)) {
- if (pipe == cmsysProcess_Pipe_STDERR) {
- std::cerr << line << "\n";
- } else if (pipe == cmsysProcess_Pipe_STDOUT) {
- std::cout << line << "\n";
- }
- }
- pipe = cmSystemTools::WaitForLine(cp, line, 100, out, err);
- }
- cmsysProcess_WaitForExit(cp, 0);
- if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) {
- return cmsysProcess_GetExitValue(cp);
- }
- if (cmsysProcess_GetState(cp) == cmsysProcess_State_Error) {
- return -1;
- }
- return -1;
-}
-
-int main(int ac, char* av[])
-{
- std::vector<const char*> argv;
- argv.push_back("xcodebuild");
- for (int i = 1; i < ac; i++) {
- argv.push_back(av[i]);
- }
- argv.push_back(0);
- bool hitbug = true;
- int ret = 0;
- while (hitbug) {
- ret = RunXCode(argv, hitbug);
- }
- if (ret < 0) {
- return 255;
- }
- return ret;
-}
diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx
index 0c5bbe2df..caf645301 100644
--- a/Source/cmcldeps.cxx
+++ b/Source/cmcldeps.cxx
@@ -18,13 +18,15 @@
// /showIncludes is equivalent to -MD, not -MMD, that is, system headers are
// included.
-#include "cmSystemTools.h"
-#include "cmsys/Encoding.hxx"
-
#include <algorithm>
#include <sstream>
+
#include <windows.h>
+#include "cmsys/Encoding.hxx"
+
+#include "cmSystemTools.h"
+
// We don't want any wildcard expansion.
// See http://msdn.microsoft.com/en-us/library/zay8tzh6(v=vs.85).aspx
void _setargv()
@@ -221,7 +223,7 @@ static int process(const std::string& srcfilename, const std::string& dfile,
while (std::getline(ss, line)) {
if (startsWith(line, prefix)) {
std::string inc = trimLeadingSpace(line.substr(prefix.size()).c_str());
- if (inc[inc.size() - 1] == '\r') // blech, stupid \r\n
+ if (inc.back() == '\r') // blech, stupid \r\n
inc = inc.substr(0, inc.size() - 1);
includes.push_back(inc);
} else {
@@ -276,7 +278,7 @@ int main()
std::string clrest = rest;
// rc: /fo x.dir\x.rc.res -> cl: /out:x.dir\x.rc.res.dep.obj
- clrest = replace(clrest, "/fo", "/out:");
+ clrest = replace(clrest, "/fo ", "/out:");
clrest = replace(clrest, objfile, objfile + ".dep.obj ");
cl = "\"" + cl + "\" /P /DRC_INVOKED /TC ";
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index d5b086174..d05e3c81b 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -3,46 +3,58 @@
#include "cmcmd.h"
#include "cmAlgorithms.h"
+#include "cmDuration.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmQtAutoGenerators.h"
+#include "cmQtAutoMocUic.h"
+#include "cmQtAutoRcc.h"
+#include "cmRange.h"
+#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmUtils.hxx"
#include "cmVersion.h"
-#include "cm_auto_ptr.hxx"
#include "cmake.h"
-#if defined(HAVE_SERVER_MODE) && HAVE_SERVER_MODE
-#include "cmServer.h"
-#include "cmServerConnection.h"
+#if !defined(CMAKE_BOOTSTRAP)
+# include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
+# include "cmServer.h"
+# include "cmServerConnection.h"
#endif
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
-#endif
+#if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32)
+# include "cmsys/ConsoleBuf.hxx"
+
+# include "cmFileTime.h"
-#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32)
-#include "bindexplib.h"
+# include "bindexplib.h"
#endif
-#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32) && !defined(__CYGWIN__)
-#include "cmVisualStudioWCEPlatformParser.h"
+#if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32) && !defined(__CYGWIN__)
+# include "cmVisualStudioWCEPlatformParser.h"
#endif
-#include "cmConfigure.h"
+#include <array>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <utility>
+
+#include <cm/string_view>
+
#include "cmsys/Directory.hxx"
#include "cmsys/FStream.hxx"
#include "cmsys/Process.h"
#include "cmsys/Terminal.h"
-#include <algorithm>
-#include <iostream>
-#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
+
+class cmConnection;
int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
std::vector<std::string>::const_iterator argEnd);
@@ -53,7 +65,7 @@ void CMakeCommandUsage(const char* program)
{
std::ostringstream errorStream;
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
/* clang-format off */
errorStream
<< "cmake version " << cmVersion::GetCMakeVersion() << "\n";
@@ -73,7 +85,8 @@ void CMakeCommandUsage(const char* program)
<< " capabilities - Report capabilities built into cmake "
"in JSON format\n"
<< " chdir dir cmd [args...] - run command in a given directory\n"
- << " compare_files file1 file2 - check if file1 is same as file2\n"
+ << " compare_files [--ignore-eol] file1 file2\n"
+ << " - check if file1 is same as file2\n"
<< " copy <file>... destination - copy files to destination "
"(either file or directory)\n"
<< " copy_directory <dir>... destination - copy content of <dir>... "
@@ -88,18 +101,26 @@ void CMakeCommandUsage(const char* program)
<< " environment - display the current environment\n"
<< " make_directory <dir>... - create parent and <dir> directories\n"
<< " md5sum <file>... - create MD5 checksum of files\n"
+ << " sha1sum <file>... - create SHA1 checksum of files\n"
+ << " sha224sum <file>... - create SHA224 checksum of files\n"
+ << " sha256sum <file>... - create SHA256 checksum of files\n"
+ << " sha384sum <file>... - create SHA384 checksum of files\n"
+ << " sha512sum <file>... - create SHA512 checksum of files\n"
<< " remove [-f] <file>... - remove the file(s), use -f to force "
"it\n"
- << " remove_directory dir - remove a directory and its contents\n"
+ << " remove_directory <dir>... - remove directories and their contents\n"
<< " rename oldname newname - rename a file or directory "
"(on one volume)\n"
<< " server - start cmake in server mode\n"
<< " 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"
- << " touch file - touch a file.\n"
- << " touch_nocreate file - touch a file but do not create it.\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"
+ << " create_symlink old new - create a symbolic link new -> old\n"
+ << " true - do nothing with an exit code of 0\n"
+ << " false - do nothing with an exit code of 1\n"
#if defined(_WIN32) && !defined(__CYGWIN__)
<< "Available on Windows only:\n"
<< " delete_regv key - delete registry value\n"
@@ -108,14 +129,11 @@ void CMakeCommandUsage(const char* program)
<< " env_vs9_wince sdkname - displays a batch file which sets the "
"environment for the provided Windows CE SDK installed in VS2008\n"
<< " write_regv key value - write registry value\n"
-#else
- << "Available on UNIX only:\n"
- << " create_symlink old new - create a symbolic link new -> old\n"
#endif
;
/* clang-format on */
- cmSystemTools::Error(errorStream.str().c_str());
+ cmSystemTools::Error(errorStream.str());
}
static bool cmTarFilesFrom(std::string const& file,
@@ -124,14 +142,14 @@ static bool cmTarFilesFrom(std::string const& file,
if (cmSystemTools::FileIsDirectory(file)) {
std::ostringstream e;
e << "-E tar --files-from= file '" << file << "' is a directory";
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
return false;
}
cmsys::ifstream fin(file.c_str());
if (!fin) {
std::ostringstream e;
e << "-E tar --files-from= file '" << file << "' not found";
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
return false;
}
std::string line;
@@ -145,7 +163,7 @@ static bool cmTarFilesFrom(std::string const& file,
std::ostringstream e;
e << "-E tar --files-from='" << file << "' file invalid line:\n"
<< line << "\n";
- cmSystemTools::Error(e.str().c_str());
+ cmSystemTools::Error(e.str());
return false;
} else {
files.push_back(line);
@@ -154,7 +172,303 @@ static bool cmTarFilesFrom(std::string const& file,
return true;
}
-int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
+static int HandleIWYU(const std::string& runCmd,
+ const std::string& /* sourceFile */,
+ const std::vector<std::string>& orig_cmd)
+{
+ // Construct the iwyu command line by taking what was given
+ // and adding all the arguments we give to the compiler.
+ std::vector<std::string> iwyu_cmd = cmExpandedList(runCmd, true);
+ cmAppend(iwyu_cmd, orig_cmd.begin() + 1, orig_cmd.end());
+ // Run the iwyu command line. Capture its stderr and hide its stdout.
+ // Ignore its return code because the tool always returns non-zero.
+ std::string stdErr;
+ int ret;
+ if (!cmSystemTools::RunSingleCommand(iwyu_cmd, nullptr, &stdErr, &ret,
+ nullptr, cmSystemTools::OUTPUT_NONE)) {
+ std::cerr << "Error running '" << iwyu_cmd[0] << "': " << stdErr << "\n";
+ return 1;
+ }
+ // Warn if iwyu reported anything.
+ if (stdErr.find("should remove these lines:") != std::string::npos ||
+ stdErr.find("should add these lines:") != std::string::npos) {
+ std::cerr << "Warning: include-what-you-use reported diagnostics:\n"
+ << stdErr << "\n";
+ }
+ // always return 0 we don't want to break the compile
+ return 0;
+}
+
+static int HandleTidy(const std::string& runCmd, const std::string& sourceFile,
+ const std::vector<std::string>& orig_cmd)
+{
+ // Construct the clang-tidy command line by taking what was given
+ // and adding our compiler command line. The clang-tidy tool will
+ // automatically skip over the compiler itself and extract the
+ // options.
+ int ret;
+ std::vector<std::string> tidy_cmd = cmExpandedList(runCmd, true);
+ tidy_cmd.push_back(sourceFile);
+ tidy_cmd.emplace_back("--");
+ cmAppend(tidy_cmd, orig_cmd);
+
+ // Run the tidy command line. Capture its stdout and hide its stderr.
+ std::string stdOut;
+ std::string stdErr;
+ if (!cmSystemTools::RunSingleCommand(tidy_cmd, &stdOut, &stdErr, &ret,
+ nullptr, cmSystemTools::OUTPUT_NONE)) {
+ std::cerr << "Error running '" << tidy_cmd[0] << "': " << stdErr << "\n";
+ return 1;
+ }
+ // Output the stdout from clang-tidy to stderr
+ std::cerr << stdOut;
+ // If clang-tidy exited with an error do the same.
+ if (ret != 0) {
+ std::cerr << stdErr;
+ }
+ return ret;
+}
+
+static int HandleLWYU(const std::string& runCmd,
+ const std::string& /* sourceFile */,
+ const std::vector<std::string>&)
+{
+ // Construct the ldd -r -u (link what you use lwyu) command line
+ // ldd -u -r lwuy target
+ std::vector<std::string> lwyu_cmd;
+ lwyu_cmd.emplace_back("ldd");
+ lwyu_cmd.emplace_back("-u");
+ lwyu_cmd.emplace_back("-r");
+ lwyu_cmd.push_back(runCmd);
+
+ // Run the ldd -u -r command line.
+ // Capture its stdout and hide its stderr.
+ // Ignore its return code because the tool always returns non-zero
+ // if there are any warnings, but we just want to warn.
+ std::string stdOut;
+ std::string stdErr;
+ int ret;
+ if (!cmSystemTools::RunSingleCommand(lwyu_cmd, &stdOut, &stdErr, &ret,
+ nullptr, cmSystemTools::OUTPUT_NONE)) {
+ std::cerr << "Error running '" << lwyu_cmd[0] << "': " << stdErr << "\n";
+ return 1;
+ }
+
+ // Output the stdout from ldd -r -u to stderr
+ // Warn if lwyu reported anything.
+ if (stdOut.find("Unused direct dependencies:") != std::string::npos) {
+ std::cerr << "Warning: " << stdOut;
+ }
+ return 0;
+}
+
+static int HandleCppLint(const std::string& runCmd,
+ const std::string& sourceFile,
+ const std::vector<std::string>&)
+{
+ // Construct the cpplint command line.
+ std::vector<std::string> cpplint_cmd = cmExpandedList(runCmd, true);
+ cpplint_cmd.push_back(sourceFile);
+
+ // Run the cpplint command line. Capture its output.
+ std::string stdOut;
+ int ret;
+ if (!cmSystemTools::RunSingleCommand(cpplint_cmd, &stdOut, &stdOut, &ret,
+ nullptr, cmSystemTools::OUTPUT_NONE)) {
+ std::cerr << "Error running '" << cpplint_cmd[0] << "': " << stdOut
+ << "\n";
+ return 1;
+ }
+ if (!stdOut.empty()) {
+ std::cerr << "Warning: cpplint diagnostics:\n";
+ // Output the output from cpplint to stderr
+ std::cerr << stdOut;
+ }
+
+ // 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,
+ const std::string& sourceFile,
+ const std::vector<std::string>& orig_cmd)
+{
+ // Construct the cpplint command line.
+ std::vector<std::string> cppcheck_cmd = cmExpandedList(runCmd, true);
+ // extract all the -D, -U, and -I options from the compile line
+ for (auto const& opt : orig_cmd) {
+ if (opt.size() > 2) {
+ if ((opt[0] == '-') &&
+ ((opt[1] == 'D') || (opt[1] == 'I') || (opt[1] == 'U'))) {
+ cppcheck_cmd.push_back(opt);
+// convert cl / options to - options if needed
+#if defined(_WIN32)
+ } else if ((opt[0] == '/') &&
+ ((opt[1] == 'D') || (opt[1] == 'I') || (opt[1] == 'U'))) {
+ std::string optcopy = opt;
+ optcopy[0] = '-';
+ cppcheck_cmd.push_back(optcopy);
+#endif
+ }
+ }
+ }
+ // add the source file
+ cppcheck_cmd.push_back(sourceFile);
+
+ // Run the cpplint command line. Capture its output.
+ std::string stdOut;
+ std::string stdErr;
+ int ret;
+ if (!cmSystemTools::RunSingleCommand(cppcheck_cmd, &stdOut, &stdErr, &ret,
+ nullptr, cmSystemTools::OUTPUT_NONE)) {
+ std::cerr << "Error running '" << cppcheck_cmd[0] << "': " << stdOut
+ << "\n";
+ return 1;
+ }
+ std::cerr << stdOut;
+ // Output the output from cpplint to stderr
+ if (stdErr.find("(error)") != std::string::npos ||
+ stdErr.find("(warning)") != std::string::npos ||
+ stdErr.find("(style)") != std::string::npos ||
+ stdErr.find("(performance)") != std::string::npos ||
+ stdErr.find("(portability)") != std::string::npos ||
+ stdErr.find("(information)") != std::string::npos) {
+ if (ret == 0) {
+ std::cerr << "Warning: cppcheck reported diagnostics:\n";
+ } else {
+ std::cerr << "Error: cppcheck reported failure:\n";
+ }
+ }
+ std::cerr << stdErr;
+
+ return ret;
+}
+
+using CoCompileHandler = int (*)(const std::string&, const std::string&,
+ const std::vector<std::string>&);
+
+struct CoCompiler
+{
+ const char* Option;
+ CoCompileHandler Handler;
+ bool NoOriginalCommand;
+};
+
+static const std::array<CoCompiler, 5> CoCompilers = {
+ { // Table of options and handlers.
+ { "--cppcheck=", HandleCppCheck, false },
+ { "--cpplint=", HandleCppLint, false },
+ { "--iwyu=", HandleIWYU, false },
+ { "--lwyu=", HandleLWYU, true },
+ { "--tidy=", HandleTidy, false } }
+};
+
+struct CoCompileJob
+{
+ std::string Command;
+ CoCompileHandler Handler;
+};
+
+// called when args[0] == "__run_co_compile"
+int cmcmd::HandleCoCompileCommands(std::vector<std::string> const& args)
+{
+ std::vector<CoCompileJob> jobs;
+ std::string sourceFile; // store --source=
+ std::vector<std::string> launchers; // store --launcher=
+
+ // Default is to run the original command found after -- if the option
+ // does not need to do that, it should be specified here, currently only
+ // lwyu does that.
+ bool runOriginalCmd = true;
+
+ std::vector<std::string> orig_cmd;
+ bool doing_options = true;
+ for (std::string const& arg : cmMakeRange(args).advance(2)) {
+ // if the arg is -- then the rest of the args after
+ // go into orig_cmd
+ if (arg == "--") {
+ doing_options = false;
+ } else if (doing_options) {
+ bool optionFound = false;
+ for (CoCompiler const& cc : CoCompilers) {
+ size_t optionLen = strlen(cc.Option);
+ if (arg.compare(0, optionLen, cc.Option) == 0) {
+ optionFound = true;
+ CoCompileJob job;
+ job.Command = arg.substr(optionLen);
+ job.Handler = cc.Handler;
+ jobs.push_back(std::move(job));
+ if (cc.NoOriginalCommand) {
+ runOriginalCmd = false;
+ }
+ }
+ }
+ if (!optionFound) {
+ if (cmHasLiteralPrefix(arg, "--source=")) {
+ sourceFile = arg.substr(9);
+ } else if (cmHasLiteralPrefix(arg, "--launcher=")) {
+ cmExpandList(arg.substr(11), launchers, true);
+ } else {
+ // if it was not a co-compiler or --source/--launcher then error
+ std::cerr << "__run_co_compile given unknown argument: " << arg
+ << "\n";
+ return 1;
+ }
+ }
+ } else { // if not doing_options then push to orig_cmd
+ orig_cmd.push_back(arg);
+ }
+ }
+ 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 : CoCompilers) {
+ std::cerr << cc.Option << "\n";
+ }
+ return 1;
+ }
+
+ if (runOriginalCmd && orig_cmd.empty()) {
+ std::cerr << "__run_co_compile missing compile command after --\n";
+ return 1;
+ }
+
+ for (CoCompileJob const& job : jobs) {
+ // call the command handler here
+ int ret = job.Handler(job.Command, sourceFile, orig_cmd);
+
+ // if the command returns non-zero then return and fail.
+ // for commands that do not want to break the build, they should return
+ // 0 no matter what.
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
+ // if there is no original command to run return now
+ if (!runOriginalCmd) {
+ return 0;
+ }
+
+ // Prepend launcher argument(s), if any
+ if (!launchers.empty()) {
+ orig_cmd.insert(orig_cmd.begin(), launchers.begin(), launchers.end());
+ }
+
+ // Now run the real compiler command and return its result value
+ int ret;
+ if (!cmSystemTools::RunSingleCommand(orig_cmd, nullptr, nullptr, &ret,
+ nullptr,
+ cmSystemTools::OUTPUT_PASSTHROUGH)) {
+ std::cerr << "Error running '" << orig_cmd[0] << "'\n";
+ return 1;
+ }
+ // return the return value from the original compiler command
+ return ret;
+}
+
+int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
{
// IF YOU ADD A NEW COMMAND, DOCUMENT IT ABOVE and in cmakemain.cxx
if (args.size() > 1) {
@@ -163,18 +477,17 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// If multiple source files specified,
// then destination must be directory
if ((args.size() > 4) &&
- (!cmSystemTools::FileIsDirectory(args[args.size() - 1]))) {
- std::cerr << "Error: Target (for copy command) \""
- << args[args.size() - 1] << "\" is not a directory.\n";
+ (!cmSystemTools::FileIsDirectory(args.back()))) {
+ std::cerr << "Error: Target (for copy command) \"" << args.back()
+ << "\" is not a directory.\n";
return 1;
}
// If error occurs we want to continue copying next files.
bool return_value = false;
- for (std::string::size_type cc = 2; cc < args.size() - 1; cc++) {
- if (!cmSystemTools::cmCopyFile(args[cc].c_str(),
- args[args.size() - 1].c_str())) {
- std::cerr << "Error copying file \"" << args[cc] << "\" to \""
- << args[args.size() - 1] << "\".\n";
+ for (auto const& arg : cmMakeRange(args).advance(2).retreat(1)) {
+ if (!cmsys::SystemTools::CopyFileAlways(arg, args.back())) {
+ std::cerr << "Error copying file \"" << arg << "\" to \""
+ << args.back() << "\".\n";
return_value = true;
}
}
@@ -186,18 +499,17 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// If multiple source files specified,
// then destination must be directory
if ((args.size() > 4) &&
- (!cmSystemTools::FileIsDirectory(args[args.size() - 1]))) {
+ (!cmSystemTools::FileIsDirectory(args.back()))) {
std::cerr << "Error: Target (for copy_if_different command) \""
- << args[args.size() - 1] << "\" is not a directory.\n";
+ << args.back() << "\" is not a directory.\n";
return 1;
}
// If error occurs we want to continue copying next files.
bool return_value = false;
- for (std::string::size_type cc = 2; cc < args.size() - 1; cc++) {
- if (!cmSystemTools::CopyFileIfDifferent(
- args[cc].c_str(), args[args.size() - 1].c_str())) {
- std::cerr << "Error copying file (if different) from \"" << args[cc]
- << "\" to \"" << args[args.size() - 1] << "\".\n";
+ for (auto const& arg : cmMakeRange(args).advance(2).retreat(1)) {
+ if (!cmSystemTools::CopyFileIfDifferent(arg, args.back())) {
+ std::cerr << "Error copying file (if different) from \"" << arg
+ << "\" to \"" << args.back() << "\".\n";
return_value = true;
}
}
@@ -208,10 +520,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
if (args[1] == "copy_directory" && args.size() > 3) {
// If error occurs we want to continue copying next files.
bool return_value = false;
- for (std::string::size_type cc = 2; cc < args.size() - 1; cc++) {
- if (!cmSystemTools::CopyADirectory(args[cc], args[args.size() - 1])) {
- std::cerr << "Error copying directory from \"" << args[cc]
- << "\" to \"" << args[args.size() - 1] << "\".\n";
+ for (auto const& arg : cmMakeRange(args).advance(2).retreat(1)) {
+ if (!cmSystemTools::CopyADirectory(arg, args.back())) {
+ std::cerr << "Error copying directory from \"" << arg << "\" to \""
+ << args.back() << "\".\n";
return_value = true;
}
}
@@ -220,7 +532,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// Rename a file or directory
if (args[1] == "rename" && args.size() == 4) {
- if (!cmSystemTools::RenameFile(args[2].c_str(), args[3].c_str())) {
+ if (!cmSystemTools::RenameFile(args[2], args[3])) {
std::string e = cmSystemTools::GetLastSystemError();
std::cerr << "Error renaming from \"" << args[2] << "\" to \""
<< args[3] << "\": " << e << "\n";
@@ -230,26 +542,30 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
}
// Compare files
- if (args[1] == "compare_files" && args.size() == 4) {
- if (cmSystemTools::FilesDiffer(args[2], args[3])) {
- std::cerr << "Files \"" << args[2] << "\" to \"" << args[3]
- << "\" are different.\n";
+ if (args[1] == "compare_files" && (args.size() == 4 || args.size() == 5)) {
+ bool filesDiffer;
+ if (args.size() == 4) {
+ filesDiffer = cmSystemTools::FilesDiffer(args[2], args[3]);
+ } else if (args[2] == "--ignore-eol") {
+ filesDiffer = cmsys::SystemTools::TextFilesDiffer(args[3], args[4]);
+ } else {
+ ::CMakeCommandUsage(args[0].c_str());
+ return 1;
+ }
+
+ if (filesDiffer) {
+ std::cerr << "Files \"" << args[args.size() - 2] << "\" to \""
+ << args[args.size() - 1] << "\" are different.\n";
return 1;
}
return 0;
}
-#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
+#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
else if (args[1] == "__create_def") {
if (args.size() < 4) {
- std::cerr
- << "__create_def Usage: -E __create_def outfile.def objlistfile\n";
- return 1;
- }
- FILE* fout = cmsys::SystemTools::Fopen(args[2].c_str(), "w+");
- if (!fout) {
- std::cerr << "could not open output .def file: " << args[2].c_str()
- << "\n";
+ std::cerr << "__create_def Usage: -E __create_def outfile.def "
+ "objlistfile [-nm=nm-path]\n";
return 1;
}
cmsys::ifstream fin(args[3].c_str(), std::ios::in | std::ios::binary);
@@ -258,9 +574,41 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
<< "\n";
return 1;
}
- std::string file;
+ std::vector<std::string> files;
+ {
+ std::string file;
+ cmFileTime outTime;
+ bool outValid = outTime.Load(args[2]);
+ while (cmSystemTools::GetLineFromStream(fin, file)) {
+ files.push_back(file);
+ if (outValid) {
+ cmFileTime inTime;
+ outValid = inTime.Load(file) && inTime.Older(outTime);
+ }
+ }
+ if (outValid) {
+ // The def file already exists and all input files are older than the
+ // existing def file.
+ return 0;
+ }
+ }
+ FILE* fout = cmsys::SystemTools::Fopen(args[2].c_str(), "w+");
+ if (!fout) {
+ std::cerr << "could not open output .def file: " << args[2].c_str()
+ << "\n";
+ return 1;
+ }
bindexplib deffile;
- while (cmSystemTools::GetLineFromStream(fin, file)) {
+ if (args.size() >= 5) {
+ auto a = args[4];
+ if (cmHasLiteralPrefix(a, "--nm=")) {
+ deffile.SetNmPath(a.substr(5));
+ std::cerr << a.substr(5) << "\n";
+ } else {
+ std::cerr << "unknown argument: " << a << "\n";
+ }
+ }
+ for (auto const& file : files) {
std::string const& ext = cmSystemTools::GetFilenameLastExtension(file);
if (cmSystemTools::LowerCase(ext) == ".def") {
if (!deffile.AddDefinitionFile(file.c_str())) {
@@ -277,181 +625,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
return 0;
}
#endif
- // run include what you use command and then run the compile
- // command. This is an internal undocumented option and should
- // only be used by CMake itself when running iwyu.
- if (args[1] == "__run_iwyu") {
- if (args.size() < 3) {
- std::cerr << "__run_iwyu Usage: -E __run_iwyu [--iwyu=/path/iwyu]"
- " [--cpplint=/path/cpplint] [--tidy=/path/tidy]"
- " -- compile command\n";
- return 1;
- }
- bool doing_options = true;
- std::vector<std::string> orig_cmd;
- std::string iwyu;
- std::string tidy;
- std::string sourceFile;
- std::string lwyu;
- std::string cpplint;
- for (std::string::size_type cc = 2; cc < args.size(); cc++) {
- std::string const& arg = args[cc];
- if (arg == "--") {
- doing_options = false;
- } else if (doing_options && cmHasLiteralPrefix(arg, "--iwyu=")) {
- iwyu = arg.substr(7);
- } else if (doing_options && cmHasLiteralPrefix(arg, "--tidy=")) {
- tidy = arg.substr(7);
- } else if (doing_options && cmHasLiteralPrefix(arg, "--source=")) {
- sourceFile = arg.substr(9);
- } else if (doing_options && cmHasLiteralPrefix(arg, "--lwyu=")) {
- lwyu = arg.substr(7);
- } else if (doing_options && cmHasLiteralPrefix(arg, "--cpplint=")) {
- cpplint = arg.substr(10);
- } else if (doing_options) {
- std::cerr << "__run_iwyu given unknown argument: " << arg << "\n";
- return 1;
- } else {
- orig_cmd.push_back(arg);
- }
- }
- if (tidy.empty() && iwyu.empty() && lwyu.empty() && cpplint.empty()) {
- std::cerr << "__run_iwyu missing --cpplint=, --iwyu=, --lwyu=, and/or"
- " --tidy=\n";
- return 1;
- }
- if ((!cpplint.empty() || !tidy.empty()) && sourceFile.empty()) {
- std::cerr << "__run_iwyu --cpplint= and/or __run_iwyu --tidy="
- " require --source=\n";
- return 1;
- }
- if (orig_cmd.empty() && lwyu.empty()) {
- std::cerr << "__run_iwyu missing compile command after --\n";
- return 1;
- }
-
- int ret = 0;
-
- if (!iwyu.empty()) {
- // Construct the iwyu command line by taking what was given
- // and adding all the arguments we give to the compiler.
- std::vector<std::string> iwyu_cmd;
- cmSystemTools::ExpandListArgument(iwyu, iwyu_cmd, true);
- iwyu_cmd.insert(iwyu_cmd.end(), orig_cmd.begin() + 1, orig_cmd.end());
-
- // Run the iwyu command line. Capture its stderr and hide its stdout.
- // Ignore its return code because the tool always returns non-zero.
- std::string stdErr;
- if (!cmSystemTools::RunSingleCommand(iwyu_cmd, CM_NULLPTR, &stdErr,
- &ret, CM_NULLPTR,
- cmSystemTools::OUTPUT_NONE)) {
- std::cerr << "Error running '" << iwyu_cmd[0] << "': " << stdErr
- << "\n";
- return 1;
- }
-
- // Warn if iwyu reported anything.
- if (stdErr.find("should remove these lines:") != std::string::npos ||
- stdErr.find("should add these lines:") != std::string::npos) {
- std::cerr << "Warning: include-what-you-use reported diagnostics:\n"
- << stdErr << "\n";
- }
- }
-
- if (!tidy.empty()) {
- // Construct the clang-tidy command line by taking what was given
- // and adding our compiler command line. The clang-tidy tool will
- // automatically skip over the compiler itself and extract the
- // options.
- std::vector<std::string> tidy_cmd;
- cmSystemTools::ExpandListArgument(tidy, tidy_cmd, true);
- tidy_cmd.push_back(sourceFile);
- tidy_cmd.push_back("--");
- tidy_cmd.insert(tidy_cmd.end(), orig_cmd.begin(), orig_cmd.end());
-
- // Run the tidy command line. Capture its stdout and hide its stderr.
- std::string stdOut;
- std::string stdErr;
- if (!cmSystemTools::RunSingleCommand(tidy_cmd, &stdOut, &stdErr, &ret,
- CM_NULLPTR,
- cmSystemTools::OUTPUT_NONE)) {
- std::cerr << "Error running '" << tidy_cmd[0] << "': " << stdErr
- << "\n";
- return 1;
- }
- // Output the stdout from clang-tidy to stderr
- std::cerr << stdOut;
- // If clang-tidy exited with an error do the same.
- if (ret != 0) {
- std::cerr << stdErr;
- return ret;
- }
- }
- if (!lwyu.empty()) {
- // Construct the ldd -r -u (link what you use lwyu) command line
- // ldd -u -r lwuy target
- std::vector<std::string> lwyu_cmd;
- lwyu_cmd.push_back("ldd");
- lwyu_cmd.push_back("-u");
- lwyu_cmd.push_back("-r");
- lwyu_cmd.push_back(lwyu);
-
- // Run the ldd -u -r command line.
- // Capture its stdout and hide its stderr.
- // Ignore its return code because the tool always returns non-zero
- // if there are any warnings, but we just want to warn.
- std::string stdOut;
- std::string stdErr;
- if (!cmSystemTools::RunSingleCommand(lwyu_cmd, &stdOut, &stdErr, &ret,
- CM_NULLPTR,
- cmSystemTools::OUTPUT_NONE)) {
- std::cerr << "Error running '" << lwyu_cmd[0] << "': " << stdErr
- << "\n";
- return 1;
- }
-
- // Output the stdout from ldd -r -u to stderr
- // Warn if lwyu reported anything.
- if (stdOut.find("Unused direct dependencies:") != std::string::npos) {
- std::cerr << "Warning: " << stdOut;
- }
- }
-
- if (!cpplint.empty()) {
- // Construct the cpplint command line.
- std::vector<std::string> cpplint_cmd;
- cmSystemTools::ExpandListArgument(cpplint, cpplint_cmd, true);
- cpplint_cmd.push_back(sourceFile);
-
- // Run the cpplint command line. Capture its output.
- std::string stdOut;
- if (!cmSystemTools::RunSingleCommand(cpplint_cmd, &stdOut, &stdOut,
- &ret, CM_NULLPTR,
- cmSystemTools::OUTPUT_NONE)) {
- std::cerr << "Error running '" << cpplint_cmd[0] << "': " << stdOut
- << "\n";
- return 1;
- }
-
- // Output the output from cpplint to stderr
- std::cerr << stdOut;
-
- // If cpplint exited with an error do the same.
- if (ret != 0) {
- return ret;
- }
- }
-
- ret = 0;
- // Now run the real compiler command and return its result value.
- if (lwyu.empty() &&
- !cmSystemTools::RunSingleCommand(
- orig_cmd, CM_NULLPTR, CM_NULLPTR, &ret, CM_NULLPTR,
- cmSystemTools::OUTPUT_PASSTHROUGH)) {
- std::cerr << "Error running '" << orig_cmd[0] << "'\n";
- return 1;
- }
- return ret;
+ if (args[1] == "__run_co_compile") {
+ return cmcmd::HandleCoCompileCommands(args);
}
// Echo string
@@ -467,13 +642,13 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
}
if (args[1] == "env") {
- std::vector<std::string>::const_iterator ai = args.begin() + 2;
- std::vector<std::string>::const_iterator ae = args.end();
+ auto ai = args.cbegin() + 2;
+ auto ae = args.cend();
for (; ai != ae; ++ai) {
std::string const& a = *ai;
if (cmHasLiteralPrefix(a, "--unset=")) {
// Unset environment variable.
- cmSystemTools::UnPutEnv(a.c_str() + 8);
+ cmSystemTools::UnPutEnv(a.substr(8));
} else if (!a.empty() && a[0] == '-') {
// Environment variable and command names cannot start in '-',
// so this must be an unknown option.
@@ -497,57 +672,66 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// Execute command from remaining arguments.
std::vector<std::string> cmd(ai, ae);
int retval;
- if (cmSystemTools::RunSingleCommand(cmd, CM_NULLPTR, CM_NULLPTR, &retval,
- CM_NULLPTR,
+ if (cmSystemTools::RunSingleCommand(cmd, nullptr, nullptr, &retval,
+ nullptr,
cmSystemTools::OUTPUT_PASSTHROUGH)) {
return retval;
}
return 1;
}
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
if (args[1] == "environment") {
- std::vector<std::string> env = cmSystemTools::GetEnvironmentVariables();
- std::vector<std::string>::iterator it;
- for (it = env.begin(); it != env.end(); ++it) {
- std::cout << *it << std::endl;
+ for (auto const& env : cmSystemTools::GetEnvironmentVariables()) {
+ std::cout << env << std::endl;
}
return 0;
}
#endif
if (args[1] == "make_directory" && args.size() > 2) {
- // If error occurs we want to continue copying next files.
+ // If an error occurs, we want to continue making directories.
bool return_value = false;
- for (std::string::size_type cc = 2; cc < args.size(); cc++) {
- if (!cmSystemTools::MakeDirectory(args[cc].c_str())) {
- std::cerr << "Error creating directory \"" << args[cc] << "\".\n";
+ for (auto const& arg : cmMakeRange(args).advance(2)) {
+ if (!cmSystemTools::MakeDirectory(arg)) {
+ std::cerr << "Error creating directory \"" << arg << "\".\n";
return_value = true;
}
}
return return_value;
}
- if (args[1] == "remove_directory" && args.size() == 3) {
- if (cmSystemTools::FileIsDirectory(args[2]) &&
- !cmSystemTools::RemoveADirectory(args[2])) {
- std::cerr << "Error removing directory \"" << args[2] << "\".\n";
- return 1;
+ if (args[1] == "remove_directory" && args.size() > 2) {
+ // If an error occurs, we want to continue removing directories.
+ bool return_value = false;
+ for (auto const& arg : cmMakeRange(args).advance(2)) {
+ if (cmSystemTools::FileIsDirectory(arg)) {
+ if (cmSystemTools::FileIsSymlink(arg)) {
+ if (!cmSystemTools::RemoveFile(arg)) {
+ std::cerr << "Error removing directory symlink \"" << arg
+ << "\".\n";
+ return_value = true;
+ }
+ } else if (!cmSystemTools::RemoveADirectory(arg)) {
+ std::cerr << "Error removing directory \"" << arg << "\".\n";
+ return_value = true;
+ }
+ }
}
- return 0;
+ return return_value;
}
// Remove file
if (args[1] == "remove" && args.size() > 2) {
bool force = false;
- for (std::string::size_type cc = 2; cc < args.size(); cc++) {
- if (args[cc] == "\\-f" || args[cc] == "-f") {
+ for (auto const& arg : cmMakeRange(args).advance(2)) {
+ if (arg == "\\-f" || arg == "-f") {
force = true;
} else {
// 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())) {
+ if (!cmSystemTools::RemoveFile(arg) && !force &&
+ cmSystemTools::FileExists(arg)) {
return 1;
}
}
@@ -557,8 +741,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// Touch file
if (args[1] == "touch" && args.size() > 2) {
- for (std::string::size_type cc = 2; cc < args.size(); cc++) {
- if (!cmSystemTools::Touch(args[cc], true)) {
+ for (auto const& arg : cmMakeRange(args).advance(2)) {
+ if (!cmSystemTools::Touch(arg, true)) {
+ std::cerr << "cmake -E touch: failed to update \"";
+ std::cerr << arg << "\".\n";
return 1;
}
}
@@ -567,10 +753,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// Touch file
if (args[1] == "touch_nocreate" && args.size() > 2) {
- for (std::string::size_type cc = 2; cc < args.size(); cc++) {
- // Complain if the file could not be removed, still exists,
- // and the -f option was not given.
- if (!cmSystemTools::Touch(args[cc], false)) {
+ for (auto const& arg : cmMakeRange(args).advance(2)) {
+ if (!cmSystemTools::Touch(arg, false)) {
+ std::cerr << "cmake -E touch_nocreate: failed to update \"";
+ std::cerr << arg << "\".\n";
return 1;
}
}
@@ -583,27 +769,23 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
std::cerr << "-E capabilities accepts no additional arguments\n";
return 1;
}
- cmake cm(cmake::RoleInternal);
-#if defined(HAVE_SERVER_MODE) && HAVE_SERVER_MODE
- std::cout << cm.ReportCapabilities(true);
-#else
- std::cout << cm.ReportCapabilities(false);
-#endif
+ cmake cm(cmake::RoleInternal, cmState::Unknown);
+ std::cout << cm.ReportCapabilities();
return 0;
}
// Sleep command
if (args[1] == "sleep" && args.size() > 2) {
double total = 0;
- for (size_t i = 2; i < args.size(); ++i) {
+ for (auto const& arg : cmMakeRange(args).advance(2)) {
double num = 0.0;
char unit;
char extra;
- int n = sscanf(args[i].c_str(), "%lg%c%c", &num, &unit, &extra);
+ int n = sscanf(arg.c_str(), "%lg%c%c", &num, &unit, &extra);
if ((n == 1 || (n == 2 && unit == 's')) && num >= 0) {
total += num;
} else {
- std::cerr << "Unknown sleep time format \"" << args[i] << "\".\n";
+ std::cerr << "Unknown sleep time format \"" << arg << "\".\n";
return 1;
}
}
@@ -617,13 +799,15 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
if (args[1] == "time" && args.size() > 2) {
std::vector<std::string> command(args.begin() + 2, args.end());
- clock_t clock_start, clock_finish;
- time_t time_start, time_finish;
+ clock_t clock_start;
+ clock_t clock_finish;
+ time_t time_start;
+ time_t time_finish;
time(&time_start);
clock_start = clock();
int ret = 0;
- cmSystemTools::RunSingleCommand(command, CM_NULLPTR, CM_NULLPTR, &ret);
+ cmSystemTools::RunSingleCommand(command, nullptr, nullptr, &ret);
clock_finish = clock();
time(&time_finish);
@@ -641,42 +825,45 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// Command to calculate the md5sum of a file
if (args[1] == "md5sum" && args.size() >= 3) {
- char md5out[32];
- int retval = 0;
- for (std::string::size_type cc = 2; cc < args.size(); cc++) {
- const char* filename = args[cc].c_str();
- // Cannot compute md5sum of a directory
- if (cmSystemTools::FileIsDirectory(filename)) {
- std::cerr << "Error: " << filename << " is a directory" << std::endl;
- retval++;
- } else if (!cmSystemTools::ComputeFileMD5(filename, md5out)) {
- // To mimic md5sum behavior in a shell:
- std::cerr << filename << ": No such file or directory" << std::endl;
- retval++;
- } else {
- std::cout << std::string(md5out, 32) << " " << filename
- << std::endl;
- }
- }
- return retval;
+ return HashSumFile(args, cmCryptoHash::AlgoMD5);
+ }
+
+ // Command to calculate the sha1sum of a file
+ if (args[1] == "sha1sum" && args.size() >= 3) {
+ return HashSumFile(args, cmCryptoHash::AlgoSHA1);
+ }
+
+ if (args[1] == "sha224sum" && args.size() >= 3) {
+ return HashSumFile(args, cmCryptoHash::AlgoSHA224);
+ }
+
+ if (args[1] == "sha256sum" && args.size() >= 3) {
+ return HashSumFile(args, cmCryptoHash::AlgoSHA256);
+ }
+
+ if (args[1] == "sha384sum" && args.size() >= 3) {
+ return HashSumFile(args, cmCryptoHash::AlgoSHA384);
+ }
+
+ if (args[1] == "sha512sum" && args.size() >= 3) {
+ return HashSumFile(args, cmCryptoHash::AlgoSHA512);
}
// 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())) {
- cmSystemTools::Error("Directory does not exist for chdir command: ",
- args[2].c_str());
+ if (!cmSystemTools::FileExists(directory)) {
+ cmSystemTools::Error("Directory does not exist for chdir command: " +
+ args[2]);
return 1;
}
std::string command =
cmWrap('"', cmMakeRange(args).advance(3), '"', " ");
int retval = 0;
- int timeout = 0;
if (cmSystemTools::RunSingleCommand(
- command.c_str(), CM_NULLPTR, CM_NULLPTR, &retval,
- directory.c_str(), cmSystemTools::OUTPUT_PASSTHROUGH, timeout)) {
+ command, nullptr, nullptr, &retval, directory.c_str(),
+ cmSystemTools::OUTPUT_PASSTHROUGH, cmDuration::zero())) {
return retval;
}
@@ -686,8 +873,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// Command to start progress for a build
if (args[1] == "cmake_progress_start" && args.size() == 4) {
// basically remove the directory
- std::string dirName = args[2];
- dirName += "/Progress";
+ std::string dirName = cmStrCat(args[2], "/Progress");
cmSystemTools::RemoveADirectory(dirName);
// is the last argument a filename that exists?
@@ -702,10 +888,9 @@ 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";
+ std::string fName = cmStrCat(dirName, "/count.txt");
FILE* progFile = cmsys::SystemTools::Fopen(fName, "w");
if (progFile) {
fprintf(progFile, "%i\n", count);
@@ -737,14 +922,21 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
return 1;
}
if (!cmSystemTools::CreateSymlink(args[2], args[3])) {
- std::string emsg = cmSystemTools::GetLastSystemError();
- std::cerr << "failed to create symbolic link '" << destinationFileName
- << "': " << emsg << "\n";
return 1;
}
return 0;
}
+ // Command to do nothing with an exit code of 0.
+ if (args[1] == "true") {
+ return 0;
+ }
+
+ // Command to do nothing with an exit code of 1.
+ if (args[1] == "false") {
+ return 1;
+ }
+
// Internal CMake shared library support.
if (args[1] == "cmake_symlink_library" && args.size() == 5) {
return cmcmd::SymlinkLibrary(args);
@@ -760,7 +952,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
const bool verbose = isCMakeVerbose();
// Create a cmake object instance to process dependencies.
- cmake cm(cmake::RoleScript); // All we need is the `set` command.
+ // All we need is the `set` command.
+ cmake cm(cmake::RoleScript, cmState::Unknown);
std::string gen;
std::string homeDir;
std::string startDir;
@@ -786,8 +979,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
if (args.size() >= 9 && args[8].length() >= 8 &&
args[8].substr(0, 8) == "--color=") {
// Enable or disable color based on the switch value.
- color = (args[8].size() == 8 ||
- cmSystemTools::IsOn(args[8].substr(8).c_str()));
+ color = (args[8].size() == 8 || cmIsOn(args[8].substr(8)));
}
} else {
// Support older signature for existing makefiles:
@@ -820,12 +1012,11 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
snapshot.GetDirectory().SetCurrentBinary(startOutDir);
snapshot.GetDirectory().SetCurrentSource(startDir);
- CM_AUTO_PTR<cmMakefile> mf(new cmMakefile(ggd, snapshot));
- CM_AUTO_PTR<cmLocalGenerator> lgd(ggd->CreateLocalGenerator(mf.get()));
+ cmMakefile mf(ggd, snapshot);
+ std::unique_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator(&mf));
// Actually scan dependencies.
- return lgd->UpdateDependencies(depInfo.c_str(), verbose, color) ? 0
- : 2;
+ return lgd->UpdateDependencies(depInfo, verbose, color) ? 0 : 2;
}
return 1;
}
@@ -835,7 +1026,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
return cmcmd::ExecuteLinkScript(args);
}
-#ifdef CMAKE_BUILD_WITH_CMAKE
+#ifndef CMAKE_BOOTSTRAP
// Internal CMake ninja dependency scanning support.
if (args[1] == "cmake_ninja_depends") {
return cmcmd_cmake_ninja_depends(args.begin() + 2, args.end());
@@ -870,12 +1061,17 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
return cmcmd::ExecuteEchoColor(args);
}
-#ifdef CMAKE_BUILD_WITH_CMAKE
- if (args[1] == "cmake_autogen" && args.size() >= 4) {
- cmQtAutoGenerators autogen;
- std::string const& config = args[3];
- bool autogenSuccess = autogen.Run(args[2], config);
- return autogenSuccess ? 0 : 1;
+#ifndef CMAKE_BOOTSTRAP
+ if ((args[1] == "cmake_autogen") && (args.size() >= 4)) {
+ cm::string_view const infoFile = args[2];
+ cm::string_view const config = args[3];
+ return cmQtAutoMocUic(infoFile, config) ? 0 : 1;
+ }
+ if ((args[1] == "cmake_autorcc") && (args.size() >= 3)) {
+ cm::string_view const infoFile = args[2];
+ cm::string_view const config =
+ (args.size() > 3) ? cm::string_view(args[3]) : cm::string_view();
+ return cmQtAutoRcc(infoFile, config) ? 0 : 1;
}
#endif
@@ -888,12 +1084,17 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
std::vector<std::string> files;
std::string mtime;
std::string format;
+ cmSystemTools::cmTarCompression compress =
+ cmSystemTools::TarCompressNone;
+ int nCompress = 0;
bool doing_options = true;
- for (std::string::size_type cc = 4; cc < args.size(); cc++) {
- std::string const& arg = args[cc];
+ for (auto const& arg : cmMakeRange(args).advance(4)) {
if (doing_options && cmHasLiteralPrefix(arg, "--")) {
if (arg == "--") {
doing_options = false;
+ } else if (arg == "--zstd") {
+ compress = cmSystemTools::TarCompressZstd;
+ ++nCompress;
} else if (cmHasLiteralPrefix(arg, "--mtime=")) {
mtime = arg.substr(8);
} else if (cmHasLiteralPrefix(arg, "--files-from=")) {
@@ -903,42 +1104,61 @@ 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);
-
- if (!isKnown) {
- cmSystemTools::Error("Unknown -E tar --format= argument: ",
- format.c_str());
+ if (!cmContains(knownFormats, format)) {
+ cmSystemTools::Error("Unknown -E tar --format= argument: " +
+ format);
return 1;
}
} else {
- cmSystemTools::Error("Unknown option to -E tar: ", arg.c_str());
+ cmSystemTools::Error("Unknown option to -E tar: " + arg);
return 1;
}
} else {
files.push_back(arg);
}
}
- cmSystemTools::cmTarCompression compress =
- cmSystemTools::TarCompressNone;
+ cmSystemTools::cmTarAction action = cmSystemTools::TarActionNone;
bool verbose = false;
- int nCompress = 0;
- if (flags.find_first_of('j') != std::string::npos) {
- compress = cmSystemTools::TarCompressBZip2;
- ++nCompress;
- }
- if (flags.find_first_of('J') != std::string::npos) {
- compress = cmSystemTools::TarCompressXZ;
- ++nCompress;
- }
- if (flags.find_first_of('z') != std::string::npos) {
- compress = cmSystemTools::TarCompressGZip;
- ++nCompress;
+
+ for (auto flag : flags) {
+ switch (flag) {
+ case '-':
+ case 'f': {
+ // Keep for backward compatibility. Ignored
+ } break;
+ case 'j': {
+ compress = cmSystemTools::TarCompressBZip2;
+ ++nCompress;
+ } break;
+ case 'J': {
+ compress = cmSystemTools::TarCompressXZ;
+ ++nCompress;
+ } break;
+ case 'z': {
+ compress = cmSystemTools::TarCompressGZip;
+ ++nCompress;
+ } break;
+ case 'v': {
+ verbose = true;
+ } break;
+ case 't': {
+ action = cmSystemTools::TarActionList;
+ } break;
+ case 'c': {
+ action = cmSystemTools::TarActionCreate;
+ } break;
+ case 'x': {
+ action = cmSystemTools::TarActionExtract;
+ } break;
+ default: {
+ cmSystemTools::Message(
+ std::string("tar: Unknown argument: ") + flag, "Warning");
+ }
+ }
}
if ((format == "7zip" || format == "zip") && nCompress > 0) {
- cmSystemTools::Error("Can not use compression flags with format: ",
- format.c_str());
+ cmSystemTools::Error("Can not use compression flags with format: " +
+ format);
return 1;
}
if (nCompress > 1) {
@@ -946,24 +1166,24 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
"at most one flag of z, j, or J may be used");
return 1;
}
- if (flags.find_first_of('v') != std::string::npos) {
- verbose = true;
- }
-
- if (flags.find_first_of('t') != std::string::npos) {
- if (!cmSystemTools::ListTar(outFile.c_str(), verbose)) {
- cmSystemTools::Error("Problem listing tar: ", outFile.c_str());
+ if (action == cmSystemTools::TarActionList) {
+ if (!cmSystemTools::ListTar(outFile, files, verbose)) {
+ cmSystemTools::Error("Problem listing tar: " + outFile);
return 1;
}
- } else if (flags.find_first_of('c') != std::string::npos) {
- if (!cmSystemTools::CreateTar(outFile.c_str(), files, compress,
- verbose, mtime, format)) {
- cmSystemTools::Error("Problem creating tar: ", outFile.c_str());
+ } else if (action == cmSystemTools::TarActionCreate) {
+ if (files.empty()) {
+ cmSystemTools::Message("tar: No files or directories specified",
+ "Warning");
+ }
+ if (!cmSystemTools::CreateTar(outFile, files, compress, verbose, mtime,
+ format)) {
+ cmSystemTools::Error("Problem creating tar: " + outFile);
return 1;
}
- } else if (flags.find_first_of('x') != std::string::npos) {
- if (!cmSystemTools::ExtractTar(outFile.c_str(), verbose)) {
- cmSystemTools::Error("Problem extracting tar: ", outFile.c_str());
+ } else if (action == cmSystemTools::TarActionExtract) {
+ if (!cmSystemTools::ExtractTar(outFile, files, verbose)) {
+ cmSystemTools::Error("Problem extracting tar: " + outFile);
return 1;
}
#ifdef WIN32
@@ -982,6 +1202,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
cmSystemTools::Delay(delay);
}
#endif
+ } else {
+ cmSystemTools::Error("tar: No action specified. Please choose: 't' "
+ "(list), 'c' (create) or 'x' (extract)");
+ return 1;
}
return 0;
}
@@ -992,17 +1216,15 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
bool isDebug = false;
std::string pipe;
- for (size_t i = 2; i < args.size(); ++i) {
- const std::string& a = args[i];
-
- if (a == "--experimental") {
+ for (auto const& arg : cmMakeRange(args).advance(2)) {
+ if (arg == "--experimental") {
supportExperimental = true;
- } else if (a == "--debug") {
+ } else if (arg == "--debug") {
pipe.clear();
isDebug = true;
- } else if (a.substr(0, pipePrefix.size()) == pipePrefix) {
+ } else if (arg.substr(0, pipePrefix.size()) == pipePrefix) {
isDebug = false;
- pipe = a.substr(pipePrefix.size());
+ pipe = arg.substr(pipePrefix.size());
if (pipe.empty()) {
cmSystemTools::Error("No pipe given after --pipe=");
return 2;
@@ -1012,8 +1234,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
return 1;
}
}
-#if defined(HAVE_SERVER_MODE) && HAVE_SERVER_MODE
- cmServerConnection* conn;
+#if !defined(CMAKE_BOOTSTRAP)
+ cmConnection* conn;
if (isDebug) {
conn = new cmServerStdIoConnection;
} else {
@@ -1024,7 +1246,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
if (server.Serve(&errorMessage)) {
return 0;
}
- cmSystemTools::Error(errorMessage.c_str());
+ cmSystemTools::Error(errorMessage);
#else
static_cast<void>(supportExperimental);
static_cast<void>(isDebug);
@@ -1033,7 +1255,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
return 1;
}
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+#if !defined(CMAKE_BOOTSTRAP)
// Internal CMake Fortran module support.
if (args[1] == "cmake_copy_f90_mod" && args.size() >= 4) {
return cmDependsFortran::CopyModule(args) ? 0 : 1;
@@ -1074,12 +1296,42 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
return 1;
}
-int cmcmd::SymlinkLibrary(std::vector<std::string>& args)
+int cmcmd::HashSumFile(std::vector<std::string> const& args,
+ cmCryptoHash::Algo algo)
+{
+ if (args.size() < 3) {
+ return -1;
+ }
+ int retval = 0;
+
+ for (auto const& filename : cmMakeRange(args).advance(2)) {
+ // Cannot compute sum of a directory
+ if (cmSystemTools::FileIsDirectory(filename)) {
+ std::cerr << "Error: " << filename << " is a directory" << std::endl;
+ retval++;
+ } else {
+ std::string value = cmSystemTools::ComputeFileHash(filename, algo);
+ if (value.empty()) {
+ // To mimic "md5sum/shasum" behavior in a shell:
+ std::cerr << filename << ": No such file or directory" << std::endl;
+ retval++;
+ } else {
+ std::cout << value << " " << filename << std::endl;
+ }
+ }
+ }
+ return retval;
+}
+
+int cmcmd::SymlinkLibrary(std::vector<std::string> const& 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");
@@ -1095,7 +1347,7 @@ int cmcmd::SymlinkLibrary(std::vector<std::string>& args)
return result;
}
-int cmcmd::SymlinkExecutable(std::vector<std::string>& args)
+int cmcmd::SymlinkExecutable(std::vector<std::string> const& args)
{
int result = 0;
std::string const& realName = args[2];
@@ -1111,12 +1363,11 @@ 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__)
- return cmSystemTools::CopyFileAlways(file.c_str(), link.c_str());
+ return cmSystemTools::CopyFileAlways(file, link);
#else
std::string linktext = cmSystemTools::GetFilenameName(file);
return cmSystemTools::CreateSymlink(linktext, link);
@@ -1125,14 +1376,12 @@ bool cmcmd::SymlinkInternal(std::string const& file, std::string const& link)
static void cmcmdProgressReport(std::string const& dir, std::string const& num)
{
- std::string dirName = dir;
- dirName += "/Progress";
+ std::string dirName = cmStrCat(dir, "/Progress");
std::string fName;
FILE* progFile;
// read the count
- fName = dirName;
- fName += "/count.txt";
+ fName = cmStrCat(dirName, "/count.txt");
progFile = cmsys::SystemTools::Fopen(fName, "r");
int count = 0;
if (!progFile) {
@@ -1147,8 +1396,7 @@ static void cmcmdProgressReport(std::string const& dir, std::string const& num)
for (const char* c = last;; ++c) {
if (*c == ',' || *c == '\0') {
if (c != last) {
- fName = dirName;
- fName += "/";
+ fName = cmStrCat(dirName, '/');
fName.append(last, c - last);
progFile = cmsys::SystemTools::Fopen(fName, "w");
if (progFile) {
@@ -1170,75 +1418,74 @@ static void cmcmdProgressReport(std::string const& dir, std::string const& num)
}
}
-int cmcmd::ExecuteEchoColor(std::vector<std::string>& args)
+int cmcmd::ExecuteEchoColor(std::vector<std::string> const& args)
{
// The arguments are
- // argv[0] == <cmake-executable>
- // argv[1] == cmake_echo_color
+ // args[0] == <cmake-executable>
+ // args[1] == cmake_echo_color
bool enabled = true;
int color = cmsysTerminal_Color_Normal;
bool newline = true;
std::string progressDir;
- for (unsigned int i = 2; i < args.size(); ++i) {
- if (args[i].find("--switch=") == 0) {
+ for (auto const& arg : cmMakeRange(args).advance(2)) {
+ if (arg.find("--switch=") == 0) {
// Enable or disable color based on the switch value.
- std::string value = args[i].substr(9);
+ std::string value = arg.substr(9);
if (!value.empty()) {
- enabled = cmSystemTools::IsOn(value.c_str());
+ enabled = cmIsOn(value);
}
- } else if (cmHasLiteralPrefix(args[i], "--progress-dir=")) {
- progressDir = args[i].substr(15);
- } else if (cmHasLiteralPrefix(args[i], "--progress-num=")) {
+ } else if (cmHasLiteralPrefix(arg, "--progress-dir=")) {
+ progressDir = arg.substr(15);
+ } else if (cmHasLiteralPrefix(arg, "--progress-num=")) {
if (!progressDir.empty()) {
- std::string const& progressNum = args[i].substr(15);
+ std::string const& progressNum = arg.substr(15);
cmcmdProgressReport(progressDir, progressNum);
}
- } else if (args[i] == "--normal") {
+ } else if (arg == "--normal") {
color = cmsysTerminal_Color_Normal;
- } else if (args[i] == "--black") {
+ } else if (arg == "--black") {
color = cmsysTerminal_Color_ForegroundBlack;
- } else if (args[i] == "--red") {
+ } else if (arg == "--red") {
color = cmsysTerminal_Color_ForegroundRed;
- } else if (args[i] == "--green") {
+ } else if (arg == "--green") {
color = cmsysTerminal_Color_ForegroundGreen;
- } else if (args[i] == "--yellow") {
+ } else if (arg == "--yellow") {
color = cmsysTerminal_Color_ForegroundYellow;
- } else if (args[i] == "--blue") {
+ } else if (arg == "--blue") {
color = cmsysTerminal_Color_ForegroundBlue;
- } else if (args[i] == "--magenta") {
+ } else if (arg == "--magenta") {
color = cmsysTerminal_Color_ForegroundMagenta;
- } else if (args[i] == "--cyan") {
+ } else if (arg == "--cyan") {
color = cmsysTerminal_Color_ForegroundCyan;
- } else if (args[i] == "--white") {
+ } else if (arg == "--white") {
color = cmsysTerminal_Color_ForegroundWhite;
- } else if (args[i] == "--bold") {
+ } else if (arg == "--bold") {
color |= cmsysTerminal_Color_ForegroundBold;
- } else if (args[i] == "--no-newline") {
+ } else if (arg == "--no-newline") {
newline = false;
- } else if (args[i] == "--newline") {
+ } else if (arg == "--newline") {
newline = true;
} else {
// Color is enabled. Print with the current color.
- cmSystemTools::MakefileColorEcho(color, args[i].c_str(), newline,
- enabled);
+ cmSystemTools::MakefileColorEcho(color, arg.c_str(), newline, enabled);
}
}
return 0;
}
-int cmcmd::ExecuteLinkScript(std::vector<std::string>& args)
+int cmcmd::ExecuteLinkScript(std::vector<std::string> const& args)
{
// The arguments are
- // argv[0] == <cmake-executable>
- // argv[1] == cmake_link_script
- // argv[2] == <link-script-name>
- // argv[3] == --verbose=?
+ // args[0] == <cmake-executable>
+ // args[1] == cmake_link_script
+ // args[2] == <link-script-name>
+ // args[3] == --verbose=?
bool verbose = false;
if (args.size() >= 4) {
if (args[3].find("--verbose=") == 0) {
- if (!cmSystemTools::IsOff(args[3].substr(10).c_str())) {
+ if (!cmIsOff(args[3].substr(10))) {
verbose = true;
}
}
@@ -1277,7 +1524,7 @@ int cmcmd::ExecuteLinkScript(std::vector<std::string>& args)
}
// Setup this command line.
- const char* cmd[2] = { command.c_str(), CM_NULLPTR };
+ const char* cmd[2] = { command.c_str(), nullptr };
cmsysProcess_SetCommand(cp, cmd);
// Report the command if verbose output is enabled.
@@ -1287,7 +1534,7 @@ int cmcmd::ExecuteLinkScript(std::vector<std::string>& args)
// Run the command and wait for it to exit.
cmsysProcess_Execute(cp);
- cmsysProcess_WaitForExit(cp, CM_NULLPTR);
+ cmsysProcess_WaitForExit(cp, nullptr);
// Report failure if any.
switch (cmsysProcess_GetState(cp)) {
@@ -1309,7 +1556,7 @@ int cmcmd::ExecuteLinkScript(std::vector<std::string>& args)
break;
default:
break;
- };
+ }
}
// Free the process instance.
@@ -1321,7 +1568,7 @@ int cmcmd::ExecuteLinkScript(std::vector<std::string>& args)
int cmcmd::WindowsCEEnvironment(const char* version, const std::string& name)
{
-#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32) && !defined(__CYGWIN__)
+#if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32) && !defined(__CYGWIN__)
cmVisualStudioWCEPlatformParser parser(name.c_str());
parser.ParseVersion(version);
if (parser.Found()) {
@@ -1353,6 +1600,8 @@ class cmVSLink
std::string ManifestFileRC;
std::string ManifestFileRes;
std::string TargetFile;
+ std::string MtPath;
+ std::string RcPath;
public:
cmVSLink(int type, bool verbose)
@@ -1375,24 +1624,32 @@ private:
// For visual studio 2005 and newer manifest files need to be embedded into
// exe and dll's. This code does that in such a way that incremental linking
// still works.
-int cmcmd::VisualStudioLink(std::vector<std::string>& args, int type)
+int cmcmd::VisualStudioLink(std::vector<std::string> const& args, int type)
{
+#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
+ // Replace streambuf so we output in the system codepage. CMake is set up
+ // to output in Unicode (see SetUTF8Pipes) but the Visual Studio linker
+ // outputs using the system codepage so we need to change behavior when
+ // we run the link command.
+ cmsys::ConsoleBuf::Manager consoleOut(std::cout);
+ cmsys::ConsoleBuf::Manager consoleErr(std::cerr, true);
+#endif
+
if (args.size() < 2) {
return -1;
}
const bool verbose = cmSystemTools::HasEnv("VERBOSE");
std::vector<std::string> expandedArgs;
- for (std::vector<std::string>::iterator i = args.begin(); i != args.end();
- ++i) {
+ for (std::string const& i : args) {
// check for nmake temporary files
- if ((*i)[0] == '@' && i->find("@CMakeFiles") != 0) {
- cmsys::ifstream fin(i->substr(1).c_str());
+ if (i[0] == '@' && i.find("@CMakeFiles") != 0) {
+ cmsys::ifstream fin(i.substr(1).c_str());
std::string line;
while (cmSystemTools::GetLineFromStream(fin, line)) {
cmSystemTools::ParseWindowsCommandLine(line.c_str(), expandedArgs);
}
} else {
- expandedArgs.push_back(*i);
+ expandedArgs.push_back(i);
}
}
@@ -1403,8 +1660,38 @@ int cmcmd::VisualStudioLink(std::vector<std::string>& args, int type)
return vsLink.Link();
}
-static bool RunCommand(const char* comment, std::vector<std::string>& command,
- bool verbose, int* retCodeOut = CM_NULLPTR)
+enum NumberFormat
+{
+ FORMAT_DECIMAL,
+ FORMAT_HEX
+};
+struct NumberFormatter
+{
+ NumberFormat Format;
+ int Value;
+ NumberFormatter(NumberFormat format, int value)
+ : Format(format)
+ , Value(value)
+ {
+ }
+};
+std::ostream& operator<<(std::ostream& stream,
+ NumberFormatter const& formatter)
+{
+ auto const& flags = stream.flags();
+ if (formatter.Format == FORMAT_DECIMAL) {
+ stream << std::dec << formatter.Value;
+ } else {
+ stream << "0x" << std::hex << formatter.Value;
+ }
+ stream.flags(flags);
+ return stream;
+}
+
+static bool RunCommand(const char* comment,
+ std::vector<std::string> const& command, bool verbose,
+ NumberFormat exitFormat, int* retCodeOut = nullptr,
+ bool (*retCodeOkay)(int) = nullptr)
{
if (verbose) {
std::cout << comment << ":\n";
@@ -1412,32 +1699,32 @@ static bool RunCommand(const char* comment, std::vector<std::string>& command,
}
std::string output;
int retCode = 0;
- // use rc command to create .res file
- bool res =
- cmSystemTools::RunSingleCommand(command, &output, &output, &retCode,
- CM_NULLPTR, cmSystemTools::OUTPUT_NONE);
- // always print the output of the command, unless
- // it is the dumb rc command banner, but if the command
- // returned an error code then print the output anyway as
- // the banner may be mixed with some other important information.
- if (output.find("Resource Compiler Version") == std::string::npos || !res ||
- retCode) {
- std::cout << output;
- }
- if (!res) {
- std::cout << comment << " failed to run." << std::endl;
- return false;
- }
- // if retCodeOut is requested then always return true
- // and set the retCodeOut to retCode
+ bool commandResult = cmSystemTools::RunSingleCommand(
+ command, &output, &output, &retCode, nullptr, cmSystemTools::OUTPUT_NONE);
+ bool const retCodeSuccess =
+ retCode == 0 || (retCodeOkay && retCodeOkay(retCode));
+ bool const success = commandResult && retCodeSuccess;
if (retCodeOut) {
- *retCodeOut = retCode;
- return true;
+ if (commandResult || !retCodeSuccess) {
+ *retCodeOut = retCode;
+ } else {
+ *retCodeOut = -1;
+ }
}
- if (retCode != 0) {
- std::cout << comment << " failed. with " << retCode << "\n";
+ if (!success) {
+ std::cout << comment << ": command \"" << cmJoin(command, " ")
+ << "\" failed (exit code "
+ << NumberFormatter(exitFormat, retCode)
+ << ") with the following output:\n"
+ << output;
+ } else {
+ // always print the output of the command, unless
+ // it is the dumb rc command banner
+ if (output.find("Resource Compiler Version") == std::string::npos) {
+ std::cout << output;
+ }
}
- return retCode == 0;
+ return success;
}
bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg,
@@ -1445,7 +1732,7 @@ bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg,
{
// Parse our own arguments.
std::string intDir;
- std::vector<std::string>::const_iterator arg = argBeg;
+ auto arg = argBeg;
while (arg != argEnd && cmHasLiteralPrefix(*arg, "-")) {
if (*arg == "--") {
++arg;
@@ -1458,6 +1745,12 @@ bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg,
} else if (cmHasLiteralPrefix(*arg, "--intdir=")) {
intDir = arg->substr(9);
++arg;
+ } else if (cmHasLiteralPrefix(*arg, "--rc=")) {
+ this->RcPath = arg->substr(5);
+ ++arg;
+ } else if (cmHasLiteralPrefix(*arg, "--mt=")) {
+ this->MtPath = arg->substr(5);
+ ++arg;
} else {
std::cerr << "unknown argument '" << *arg << "'\n";
return false;
@@ -1509,7 +1802,7 @@ bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg,
}
if (this->LinkGeneratesManifest) {
- this->LinkCommand.push_back("/MANIFEST");
+ this->LinkCommand.emplace_back("/MANIFEST");
this->LinkCommand.push_back("/MANIFESTFILE:" + this->LinkerManifestFile);
}
@@ -1535,6 +1828,13 @@ int cmVSLink::Link()
return LinkNonIncremental();
}
+static bool mtRetIsUpdate(int mtRet)
+{
+ // 'mt /notify_update' returns a special value (differing between
+ // Windows and POSIX hosts) when it updated the manifest file.
+ return mtRet == 0x41020001 || mtRet == 0xbb;
+}
+
int cmVSLink::LinkIncremental()
{
// This follows the steps listed here:
@@ -1571,8 +1871,11 @@ int cmVSLink::LinkIncremental()
if (!fout) {
return -1;
}
- fout << this->Type << " /* CREATEPROCESS_MANIFEST_RESOURCE_ID */ "
- "24 /* RT_MANIFEST */ \""
+ // Insert a pragma statement to specify utf-8 encoding.
+ fout << "#pragma code_page(65001)\n";
+ fout << this->Type
+ << " /* CREATEPROCESS_MANIFEST_RESOURCE_ID */ "
+ "24 /* RT_MANIFEST */ \""
<< absManifestFile << "\"";
}
@@ -1587,10 +1890,11 @@ int cmVSLink::LinkIncremental()
// Compile the resource file.
std::vector<std::string> rcCommand;
- rcCommand.push_back(cmSystemTools::FindProgram("rc.exe"));
- rcCommand.push_back("/fo" + this->ManifestFileRes);
+ rcCommand.push_back(this->RcPath.empty() ? "rc" : this->RcPath);
+ rcCommand.emplace_back("/fo");
+ rcCommand.push_back(this->ManifestFileRes);
rcCommand.push_back(this->ManifestFileRC);
- if (!RunCommand("RC Pass 1", rcCommand, this->Verbose)) {
+ if (!RunCommand("RC Pass 1", rcCommand, this->Verbose, FORMAT_DECIMAL)) {
return -1;
}
@@ -1598,26 +1902,28 @@ int cmVSLink::LinkIncremental()
this->LinkCommand.push_back(this->ManifestFileRes);
// Run the link command (possibly generates intermediate manifest).
- if (!RunCommand("LINK Pass 1", this->LinkCommand, this->Verbose)) {
+ if (!RunCommand("LINK Pass 1", this->LinkCommand, this->Verbose,
+ FORMAT_DECIMAL)) {
return -1;
}
// Run the manifest tool to create the final manifest.
int mtRet = this->RunMT("/out:" + this->ManifestFile, true);
- // If mt returns 1090650113 (or 187 on a posix host) then it updated the
- // manifest file so we need to embed it again. Otherwise we are done.
- if (mtRet != 1090650113 && mtRet != 187) {
+ // If mt returns a special value then it updated the manifest file so
+ // we need to embed it again. Otherwise we are done.
+ if (!mtRetIsUpdate(mtRet)) {
return mtRet;
}
// Compile the resource file again.
- if (!RunCommand("RC Pass 2", rcCommand, this->Verbose)) {
+ if (!RunCommand("RC Pass 2", rcCommand, this->Verbose, FORMAT_DECIMAL)) {
return -1;
}
// Link incrementally again to use the updated resource.
- if (!RunCommand("FINAL LINK", this->LinkCommand, this->Verbose)) {
+ if (!RunCommand("FINAL LINK", this->LinkCommand, this->Verbose,
+ FORMAT_DECIMAL)) {
return -1;
}
return 0;
@@ -1626,7 +1932,7 @@ int cmVSLink::LinkIncremental()
int cmVSLink::LinkNonIncremental()
{
// Run the link command (possibly generates intermediate manifest).
- if (!RunCommand("LINK", this->LinkCommand, this->Verbose)) {
+ if (!RunCommand("LINK", this->LinkCommand, this->Verbose, FORMAT_DECIMAL)) {
return -1;
}
@@ -1644,22 +1950,22 @@ int cmVSLink::LinkNonIncremental()
int cmVSLink::RunMT(std::string const& out, bool notify)
{
std::vector<std::string> mtCommand;
- mtCommand.push_back(cmSystemTools::FindProgram("mt.exe"));
- mtCommand.push_back("/nologo");
- mtCommand.push_back("/manifest");
+ mtCommand.push_back(this->MtPath.empty() ? "mt" : this->MtPath);
+ mtCommand.emplace_back("/nologo");
+ mtCommand.emplace_back("/manifest");
if (this->LinkGeneratesManifest) {
mtCommand.push_back(this->LinkerManifestFile);
}
- mtCommand.insert(mtCommand.end(), this->UserManifests.begin(),
- this->UserManifests.end());
+ cmAppend(mtCommand, this->UserManifests);
mtCommand.push_back(out);
if (notify) {
// Add an undocumented option that enables a special return
// code to notify us when the manifest is modified.
- mtCommand.push_back("/notify_update");
+ mtCommand.emplace_back("/notify_update");
}
int mtRet = 0;
- if (!RunCommand("MT", mtCommand, this->Verbose, &mtRet)) {
+ if (!RunCommand("MT", mtCommand, this->Verbose, FORMAT_HEX, &mtRet,
+ mtRetIsUpdate)) {
return -1;
}
return mtRet;
diff --git a/Source/cmcmd.h b/Source/cmcmd.h
index 929f1ae47..17f2f9a52 100644
--- a/Source/cmcmd.h
+++ b/Source/cmcmd.h
@@ -8,6 +8,8 @@
#include <string>
#include <vector>
+#include "cmCryptoHash.h"
+
class cmcmd
{
public:
@@ -15,18 +17,21 @@ public:
* Execute commands during the build process. Supports options such
* as echo, remove file etc.
*/
- static int ExecuteCMakeCommand(std::vector<std::string>&);
+ static int ExecuteCMakeCommand(std::vector<std::string> const&);
protected:
- static int SymlinkLibrary(std::vector<std::string>& args);
- static int SymlinkExecutable(std::vector<std::string>& args);
+ static int HandleCoCompileCommands(std::vector<std::string> const& args);
+ static int HashSumFile(std::vector<std::string> const& args,
+ cmCryptoHash::Algo algo);
+ static int SymlinkLibrary(std::vector<std::string> const& args);
+ static int SymlinkExecutable(std::vector<std::string> const& args);
static bool SymlinkInternal(std::string const& file,
std::string const& link);
- static int ExecuteEchoColor(std::vector<std::string>& args);
- static int ExecuteLinkScript(std::vector<std::string>& args);
+ static int ExecuteEchoColor(std::vector<std::string> const& args);
+ static int ExecuteLinkScript(std::vector<std::string> const& args);
static int WindowsCEEnvironment(const char* version,
const std::string& name);
- static int VisualStudioLink(std::vector<std::string>& args, int type);
+ static int VisualStudioLink(std::vector<std::string> const& args, int type);
};
#endif
diff --git a/Source/cmparseMSBuildXML.py b/Source/cmparseMSBuildXML.py
deleted file mode 100755
index 1b38d1547..000000000
--- a/Source/cmparseMSBuildXML.py
+++ /dev/null
@@ -1,341 +0,0 @@
-# This python script parses the spec files from MSBuild to create
-# mappings from compiler options to IDE XML specifications. For
-# more information see here:
-
-# http://blogs.msdn.com/vcblog/archive/2008/12/16/msbuild-task.aspx
-# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/1033/cl.xml"
-# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/1033/lib.xml"
-# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/1033/link.xml"
-# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V110/1033/cl.xml"
-# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V110/1033/lib.xml"
-# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V110/1033/link.xml"
-# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/v120/1033/cl.xml"
-# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/v120/1033/lib.xml"
-# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/v120/1033/link.xml"
-# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V140/1033/cl.xml"
-# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V140/1033/lib.xml"
-# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V140/1033/link.xml"
-# "${PROGRAMFILES}/Microsoft Visual Studio/VS15Preview/Common7/IDE/VC/VCTargets/1033/cl.xml"
-# "${PROGRAMFILES}/Microsoft Visual Studio/VS15Preview/Common7/IDE/VC/VCTargets/1033/lib.xml"
-# "${PROGRAMFILES}/Microsoft Visual Studio/VS15Preview/Common7/IDE/VC/VCTargets/1033/link.xml"
-#
-# BoolProperty <Name>true|false</Name>
-# simple example:
-# <BoolProperty ReverseSwitch="Oy-" Name="OmitFramePointers"
-# Category="Optimization" Switch="Oy">
-# <BoolProperty.DisplayName> <BoolProperty.Description>
-# <CLCompile>
-# <OmitFramePointers>true</OmitFramePointers>
-# </ClCompile>
-#
-# argument means it might be this: /MP3
-# example with argument:
-# <BoolProperty Name="MultiProcessorCompilation" Category="General" Switch="MP">
-# <BoolProperty.DisplayName>
-# <sys:String>Multi-processor Compilation</sys:String>
-# </BoolProperty.DisplayName>
-# <BoolProperty.Description>
-# <sys:String>Multi-processor Compilation</sys:String>
-# </BoolProperty.Description>
-# <Argument Property="ProcessorNumber" IsRequired="false" />
-# </BoolProperty>
-# <CLCompile>
-# <MultiProcessorCompilation>true</MultiProcessorCompilation>
-# <ProcessorNumber>4</ProcessorNumber>
-# </ClCompile>
-# IntProperty
-# not used AFIT
-# <IntProperty Name="ProcessorNumber" Category="General" Visible="false">
-
-
-# per config options example
-# <EnableFiberSafeOptimizations Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</EnableFiberSafeOptimizations>
-#
-# EnumProperty
-# <EnumProperty Name="Optimization" Category="Optimization">
-# <EnumProperty.DisplayName>
-# <sys:String>Optimization</sys:String>
-# </EnumProperty.DisplayName>
-# <EnumProperty.Description>
-# <sys:String>Select option for code optimization; choose Custom to use specific optimization options. (/Od, /O1, /O2, /Ox)</sys:String>
-# </EnumProperty.Description>
-# <EnumValue Name="MaxSpeed" Switch="O2">
-# <EnumValue.DisplayName>
-# <sys:String>Maximize Speed</sys:String>
-# </EnumValue.DisplayName>
-# <EnumValue.Description>
-# <sys:String>Equivalent to /Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy</sys:String>
-# </EnumValue.Description>
-# </EnumValue>
-# <EnumValue Name="MinSpace" Switch="O1">
-# <EnumValue.DisplayName>
-# <sys:String>Minimize Size</sys:String>
-# </EnumValue.DisplayName>
-# <EnumValue.Description>
-# <sys:String>Equivalent to /Og /Os /Oy /Ob2 /Gs /GF /Gy</sys:String>
-# </EnumValue.Description>
-# </EnumValue>
-# example for O2 would be this:
-# <Optimization>MaxSpeed</Optimization>
-# example for O1 would be this:
-# <Optimization>MinSpace</Optimization>
-#
-# StringListProperty
-# <StringListProperty Name="PreprocessorDefinitions" Category="Preprocessor" Switch="D ">
-# <StringListProperty.DisplayName>
-# <sys:String>Preprocessor Definitions</sys:String>
-# </StringListProperty.DisplayName>
-# <StringListProperty.Description>
-# <sys:String>Defines a preprocessing symbols for your source file.</sys:String>
-# </StringListProperty.Description>
-# </StringListProperty>
-
-# <StringListProperty Subtype="folder" Name="AdditionalIncludeDirectories" Category="General" Switch="I">
-# <StringListProperty.DisplayName>
-# <sys:String>Additional Include Directories</sys:String>
-# </StringListProperty.DisplayName>
-# <StringListProperty.Description>
-# <sys:String>Specifies one or more directories to add to the include path; separate with semi-colons if more than one. (/I[path])</sys:String>
-# </StringListProperty.Description>
-# </StringListProperty>
-# StringProperty
-
-# Example add bill include:
-
-# <AdditionalIncludeDirectories>..\..\..\..\..\..\bill;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-
-
-import sys
-from xml.dom.minidom import parse, parseString
-
-def getText(node):
- nodelist = node.childNodes
- rc = ""
- for child in nodelist:
- if child.nodeType == child.TEXT_NODE:
- rc = rc + child.data
- return rc
-
-def print_tree(document, spaces=""):
- for i in range(len(document.childNodes)):
- if document.childNodes[i].nodeType == document.childNodes[i].ELEMENT_NODE:
- print spaces+str(document.childNodes[i].nodeName )
- print_tree(document.childNodes[i],spaces+"----")
- pass
-
-###########################################################################################
-#Data structure that stores a property of MSBuild
-class Property:
- #type = type of MSBuild property (ex. if the property is EnumProperty type should be "Enum")
- #attributeNames = a list of any attributes that this property could have (ex. if this was a EnumProperty it should be ["Name","Category"])
- #document = the dom file that's root node is the Property node (ex. if you were parsing a BoolProperty the root node should be something like <BoolProperty Name="RegisterOutput" Category="General" IncludeInCommandLine="false">
- def __init__(self,type,attributeNames,document=None):
- self.suffix_type = "Property"
- self.prefix_type = type
- self.attributeNames = attributeNames
- self.attributes = {}
- self.DisplayName = ""
- self.Description = ""
- self.argumentProperty = ""
- self.argumentIsRequired = ""
- self.values = []
- if document is not None:
- self.populate(document)
- pass
-
- #document = the dom file that's root node is the Property node (ex. if you were parsing a BoolProperty the root node should be something like <BoolProperty Name="RegisterOutput" Category="General" IncludeInCommandLine="false">
- #spaces = do not use
- def populate(self,document, spaces = ""):
- if document.nodeName == self.prefix_type+self.suffix_type:
- for i in self.attributeNames:
- self.attributes[i] = document.getAttribute(i)
- for i in range(len(document.childNodes)):
- child = document.childNodes[i]
- if child.nodeType == child.ELEMENT_NODE:
- if child.nodeName == self.prefix_type+self.suffix_type+".DisplayName":
- self.DisplayName = getText(child.childNodes[1])
- if child.nodeName == self.prefix_type+self.suffix_type+".Description":
- self.Description = getText(child.childNodes[1])
- if child.nodeName == "Argument":
- self.argumentProperty = child.getAttribute("Property")
- self.argumentIsRequired = child.getAttribute("IsRequired")
- if child.nodeName == self.prefix_type+"Value":
- va = Property(self.prefix_type,["Name","DisplayName","Switch"])
- va.suffix_type = "Value"
- va.populate(child)
- self.values.append(va)
- self.populate(child,spaces+"----")
- pass
-
- #toString function
- def __str__(self):
- toReturn = self.prefix_type+self.suffix_type+":"
- for i in self.attributeNames:
- toReturn += "\n "+i+": "+self.attributes[i]
- if self.argumentProperty != "":
- toReturn += "\n Argument:\n Property: "+self.argumentProperty+"\n IsRequired: "+self.argumentIsRequired
- for i in self.values:
- toReturn+="\n "+str(i).replace("\n","\n ")
- return toReturn
-###########################################################################################
-
-###########################################################################################
-#Class that populates itself from an MSBuild file and outputs it in CMake
-#format
-
-class MSBuildToCMake:
- #document = the entire MSBuild xml file
- def __init__(self,document=None):
- self.enumProperties = []
- self.stringProperties = []
- self.stringListProperties = []
- self.boolProperties = []
- self.intProperties = []
- if document!=None :
- self.populate(document)
- pass
-
- #document = the entire MSBuild xml file
- #spaces = don't use
- #To add a new property (if they exist) copy and paste this code and fill in appropriate places
- #
- #if child.nodeName == "<Name>Property":
- # self.<Name>Properties.append(Property("<Name>",[<List of attributes>],child))
- #
- #Replace <Name> with the name of the new property (ex. if property is StringProperty replace <Name> with String)
- #Replace <List of attributes> with a list of attributes in your property's root node
- #in the __init__ function add the line self.<Name>Properties = []
- #
- #That is all that is required to add new properties
- #
- def populate(self,document, spaces=""):
- for i in range(len(document.childNodes)):
- child = document.childNodes[i]
- if child.nodeType == child.ELEMENT_NODE:
- if child.nodeName == "EnumProperty":
- self.enumProperties.append(Property("Enum",["Name","Category"],child))
- if child.nodeName == "StringProperty":
- self.stringProperties.append(Property("String",["Name","Subtype","Separator","Category","Visible","IncludeInCommandLine","Switch","DisplayName","ReadOnly"],child))
- if child.nodeName == "StringListProperty":
- self.stringListProperties.append(Property("StringList",["Name","Category","Switch","DisplayName","Subtype"],child))
- if child.nodeName == "BoolProperty":
- self.boolProperties.append(Property("Bool",["ReverseSwitch","Name","Category","Switch","DisplayName","SwitchPrefix","IncludeInCommandLine"],child))
- if child.nodeName == "IntProperty":
- self.intProperties.append(Property("Int",["Name","Category","Visible"],child))
- self.populate(child,spaces+"----")
- pass
-
- #outputs information that CMake needs to know about MSBuild xml files
- def toCMake(self):
- toReturn = "static cmVS7FlagTable cmVS10CxxTable[] =\n{\n"
- toReturn += "\n //Enum Properties\n"
- lastProp = {}
- for i in self.enumProperties:
- if i.attributes["Name"] == "CompileAsManaged":
- #write these out after the rest of the enumProperties
- lastProp = i
- continue
- for j in i.values:
- #hardcore Brad King's manual fixes for cmVS10CLFlagTable.h
- if i.attributes["Name"] == "PrecompiledHeader" and j.attributes["Switch"] != "":
- toReturn+=" {\""+i.attributes["Name"]+"\", \""+j.attributes["Switch"]+"\",\n \""+j.attributes["DisplayName"]+"\", \""+j.attributes["Name"]+"\",\n cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},\n"
- else:
- #default (normal, non-hardcoded) case
- toReturn+=" {\""+i.attributes["Name"]+"\", \""+j.attributes["Switch"]+"\",\n \""+j.attributes["DisplayName"]+"\", \""+j.attributes["Name"]+"\", 0},\n"
- toReturn += "\n"
-
- if lastProp != {}:
- for j in lastProp.values:
- toReturn+=" {\""+lastProp.attributes["Name"]+"\", \""+j.attributes["Switch"]+"\",\n \""+j.attributes["DisplayName"]+"\", \""+j.attributes["Name"]+"\", 0},\n"
- toReturn += "\n"
-
- toReturn += "\n //Bool Properties\n"
- for i in self.boolProperties:
- if i.argumentProperty == "":
- if i.attributes["ReverseSwitch"] != "":
- toReturn += " {\""+i.attributes["Name"]+"\", \""+i.attributes["ReverseSwitch"]+"\", \"\", \"false\", 0},\n"
- if i.attributes["Switch"] != "":
- toReturn += " {\""+i.attributes["Name"]+"\", \""+i.attributes["Switch"]+"\", \"\", \"true\", 0},\n"
-
- toReturn += "\n //Bool Properties With Argument\n"
- for i in self.boolProperties:
- if i.argumentProperty != "":
- if i.attributes["ReverseSwitch"] != "":
- toReturn += " {\""+i.attributes["Name"]+"\", \""+i.attributes["ReverseSwitch"]+"\", \"\", \"false\",\n cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},\n"
- toReturn += " {\""+i.attributes["Name"]+"\", \""+i.attributes["ReverseSwitch"]+"\", \""+i.attributes["DisplayName"]+"\", \"\",\n cmVS7FlagTable::UserValueRequired},\n"
- if i.attributes["Switch"] != "":
- toReturn += " {\""+i.attributes["Name"]+"\", \""+i.attributes["Switch"]+"\", \"\", \"true\",\n cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},\n"
- toReturn += " {\""+i.argumentProperty+"\", \""+i.attributes["Switch"]+"\", \""+i.attributes["DisplayName"]+"\", \"\",\n cmVS7FlagTable::UserValueRequired},\n"
-
- toReturn += "\n //String List Properties\n"
- for i in self.stringListProperties:
- if i.attributes["Switch"] == "":
- toReturn += " // Skip [" + i.attributes["Name"] + "] - no command line Switch.\n";
- else:
- toReturn +=" {\""+i.attributes["Name"]+"\", \""+i.attributes["Switch"]+"\",\n \""+i.attributes["DisplayName"]+"\",\n \"\", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},\n"
-
- toReturn += "\n //String Properties\n"
- for i in self.stringProperties:
- if i.attributes["Switch"] == "":
- if i.attributes["Name"] == "PrecompiledHeaderFile":
- #more hardcoding
- toReturn += " {\"PrecompiledHeaderFile\", \"Yc\",\n"
- toReturn += " \"Precompiled Header Name\",\n"
- toReturn += " \"\", cmVS7FlagTable::UserValueRequired},\n"
- toReturn += " {\"PrecompiledHeaderFile\", \"Yu\",\n"
- toReturn += " \"Precompiled Header Name\",\n"
- toReturn += " \"\", cmVS7FlagTable::UserValueRequired},\n"
- else:
- toReturn += " // Skip [" + i.attributes["Name"] + "] - no command line Switch.\n";
- else:
- toReturn +=" {\""+i.attributes["Name"]+"\", \""+i.attributes["Switch"]+i.attributes["Separator"]+"\",\n \""+i.attributes["DisplayName"]+"\",\n \"\", cmVS7FlagTable::UserValue},\n"
-
- toReturn += " {0,0,0,0,0}\n};"
- return toReturn
- pass
-
- #toString function
- def __str__(self):
- toReturn = ""
- allList = [self.enumProperties,self.stringProperties,self.stringListProperties,self.boolProperties,self.intProperties]
- for p in allList:
- for i in p:
- toReturn += "==================================================\n"+str(i).replace("\n","\n ")+"\n==================================================\n"
-
- return toReturn
-###########################################################################################
-
-###########################################################################################
-# main function
-def main(argv):
- xml_file = None
- help = """
- Please specify an input xml file with -x
-
- Exiting...
- Have a nice day :)"""
- for i in range(0,len(argv)):
- if argv[i] == "-x":
- xml_file = argv[i+1]
- if argv[i] == "-h":
- print help
- sys.exit(0)
- pass
- if xml_file == None:
- print help
- sys.exit(1)
-
- f = open(xml_file,"r")
- xml_str = f.read()
- xml_dom = parseString(xml_str)
-
- convertor = MSBuildToCMake(xml_dom)
- print convertor.toCMake()
-
- xml_dom.unlink()
-###########################################################################################
-# main entry point
-if __name__ == "__main__":
- main(sys.argv)
-
-sys.exit(0)
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index 84e815d1d..0d65902ef 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -1,88 +1,113 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmConfigure.h"
-#include "CTest/cmCTestLaunch.h"
-#include "CTest/cmCTestScriptHandler.h"
+#include "cmsys/Encoding.hxx"
+
#include "cmCTest.h"
#include "cmDocumentation.h"
#include "cmSystemTools.h"
-#include "cmsys/Encoding.hxx"
-#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmsys/ConsoleBuf.hxx"
+#include "CTest/cmCTestLaunch.h"
+#include "CTest/cmCTestScriptHandler.h"
+#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
+# include "cmsys/ConsoleBuf.hxx"
#endif
+#include <cstring>
#include <iostream>
-#include <string.h>
#include <string>
#include <vector>
static const char* cmDocumentationName[][2] = {
- { CM_NULLPTR, " ctest - Testing driver provided by CMake." },
- { CM_NULLPTR, CM_NULLPTR }
+ { nullptr, " ctest - Testing driver provided by CMake." },
+ { nullptr, nullptr }
};
-static const char* cmDocumentationUsage[][2] = { { CM_NULLPTR,
+static const char* cmDocumentationUsage[][2] = { { nullptr,
" ctest [options]" },
- { CM_NULLPTR, CM_NULLPTR } };
+ { nullptr, nullptr } };
static const char* cmDocumentationOptions[][2] = {
{ "-C <cfg>, --build-config <cfg>", "Choose configuration to test." },
+ { "--progress", "Enable short progress output from tests." },
{ "-V,--verbose", "Enable verbose output from tests." },
{ "-VV,--extra-verbose", "Enable more verbose output from tests." },
{ "--debug", "Displaying more verbose internals of CTest." },
- { "--output-on-failure", "Output anything outputted by the test program "
- "if the test should fail." },
- { "--test-output-size-passed <size>", "Limit the output for passed tests "
- "to <size> bytes" },
- { "--test-output-size-failed <size>", "Limit the output for failed tests "
- "to <size> bytes" },
+ { "--output-on-failure",
+ "Output anything outputted by the test program "
+ "if the test should fail." },
+ { "--test-output-size-passed <size>",
+ "Limit the output for passed tests "
+ "to <size> bytes" },
+ { "--test-output-size-failed <size>",
+ "Limit the output for failed tests "
+ "to <size> bytes" },
{ "-F", "Enable failover." },
- { "-j <jobs>, --parallel <jobs>", "Run the tests in parallel using the "
- "given number of jobs." },
+ { "-j <jobs>, --parallel <jobs>",
+ "Run the tests in parallel using the "
+ "given number of jobs." },
{ "-Q,--quiet", "Make ctest quiet." },
{ "-O <file>, --output-log <file>", "Output to log file" },
- { "-N,--show-only", "Disable actual execution of tests." },
- { "-L <regex>, --label-regex <regex>", "Run tests with labels matching "
- "regular expression." },
- { "-R <regex>, --tests-regex <regex>", "Run tests matching regular "
- "expression." },
- { "-E <regex>, --exclude-regex <regex>", "Exclude tests matching regular "
- "expression." },
- { "-LE <regex>, --label-exclude <regex>", "Exclude tests with labels "
- "matching regular expression." },
- { "-FA <regex>, --fixture-exclude-any <regex>", "Do not automatically "
- "add any tests for "
- "fixtures matching "
- "regular expression." },
- { "-FS <regex>, --fixture-exclude-setup <regex>", "Do not automatically "
- "add setup tests for "
- "fixtures matching "
- "regular expression." },
- { "-FC <regex>, --fixture-exclude-cleanup <regex>", "Do not automatically "
- "add cleanup tests for "
- "fixtures matching "
- "regular expression." },
+ { "-N,--show-only[=format]",
+ "Disable actual execution of tests. The optional 'format' defines the "
+ "format of the test information and can be 'human' for the current text "
+ "format or 'json-v1' for json format. Defaults to 'human'." },
+ { "-L <regex>, --label-regex <regex>",
+ "Run tests with labels matching "
+ "regular expression." },
+ { "-R <regex>, --tests-regex <regex>",
+ "Run tests matching regular "
+ "expression." },
+ { "-E <regex>, --exclude-regex <regex>",
+ "Exclude tests matching regular "
+ "expression." },
+ { "-LE <regex>, --label-exclude <regex>",
+ "Exclude tests with labels "
+ "matching regular expression." },
+ { "-FA <regex>, --fixture-exclude-any <regex>",
+ "Do not automatically "
+ "add any tests for "
+ "fixtures matching "
+ "regular expression." },
+ { "-FS <regex>, --fixture-exclude-setup <regex>",
+ "Do not automatically "
+ "add setup tests for "
+ "fixtures matching "
+ "regular expression." },
+ { "-FC <regex>, --fixture-exclude-cleanup <regex>",
+ "Do not automatically "
+ "add cleanup tests for "
+ "fixtures matching "
+ "regular expression." },
{ "-D <dashboard>, --dashboard <dashboard>", "Execute dashboard test" },
{ "-D <var>:<type>=<value>", "Define a variable for script mode" },
{ "-M <model>, --test-model <model>", "Sets the model for a dashboard" },
- { "-T <action>, --test-action <action>", "Sets the dashboard action to "
- "perform" },
- { "--track <track>", "Specify the track to submit dashboard to" },
- { "-S <script>, --script <script>", "Execute a dashboard for a "
- "configuration" },
- { "-SP <script>, --script-new-process <script>", "Execute a dashboard for a "
- "configuration" },
+ { "-T <action>, --test-action <action>",
+ "Sets the dashboard action to "
+ "perform" },
+ { "--group <group>",
+ "Specify what build group on the dashboard you'd like to "
+ "submit results to." },
+ { "-S <script>, --script <script>",
+ "Execute a dashboard for a "
+ "configuration" },
+ { "-SP <script>, --script-new-process <script>",
+ "Execute a dashboard for a "
+ "configuration" },
{ "-A <file>, --add-notes <file>", "Add a notes file with submission" },
{ "-I [Start,End,Stride,test#,test#|Test file], --tests-information",
"Run a specific number of tests by number." },
{ "-U, --union", "Take the Union of -I and -R" },
{ "--rerun-failed", "Run only the tests that failed previously" },
- { "--repeat-until-fail <n>", "Require each test to run <n> "
- "times without failing in order to pass" },
+ { "--repeat-until-fail <n>",
+ "Require each test to run <n> "
+ "times without failing in order to pass" },
{ "--max-width <width>", "Set the max width for a test name to output" },
{ "--interactive-debug-mode [0|1]", "Set the interactive mode to 0 or 1." },
+ { "--resource-spec-file <file>", "Set the resource spec file to use." },
{ "--no-label-summary", "Disable timing summary information for labels." },
+ { "--no-subproject-summary",
+ "Disable timing summary information for "
+ "subprojects." },
{ "--build-and-test", "Configure, build and run a test." },
{ "--build-target", "Specify a specific target to build." },
{ "--build-nocmake", "Run the build without running cmake first." },
@@ -103,8 +128,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",
@@ -112,19 +135,20 @@ static const char* cmDocumentationOptions[][2] = {
{ "--schedule-random", "Use a random order for scheduling tests" },
{ "--submit-index",
"Submit individual dashboard tests with specific index" },
- { "--timeout <seconds>", "Set a global timeout on all tests." },
+ { "--timeout <seconds>", "Set the default test timeout." },
{ "--stop-time <time>",
"Set a time at which all tests should stop running." },
{ "--http1.0", "Submit using HTTP 1.0." },
{ "--no-compress-output", "Do not compress test output when submitting." },
{ "--print-labels", "Print all available test labels." },
- { CM_NULLPTR, CM_NULLPTR }
+ { nullptr, nullptr }
};
// this is a test driver program for cmCTest.
int main(int argc, char const* const* argv)
{
-#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
+ cmSystemTools::EnsureStdPipes();
+#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
// Replace streambuf so we can output Unicode to console
cmsys::ConsoleBuf::Manager consoleOut(std::cout);
consoleOut.SetUTF8Pipes();
@@ -138,6 +162,7 @@ int main(int argc, char const* const* argv)
cmSystemTools::DoNotInheritStdPipes();
cmSystemTools::EnableMSVCDebugHook();
+ cmSystemTools::InitializeLibUV();
cmSystemTools::FindCMakeResources(argv[0]);
// Dispatch 'ctest --launch' mode directly.
@@ -161,7 +186,8 @@ int main(int argc, char const* const* argv)
!(cmSystemTools::FileExists("CTestTestfile.cmake") ||
cmSystemTools::FileExists("DartTestfile.txt"))) {
if (argc == 1) {
- cmCTestLog(&inst, ERROR_MESSAGE, "*********************************"
+ cmCTestLog(&inst, ERROR_MESSAGE,
+ "*********************************"
<< std::endl
<< "No test configuration file found!" << std::endl
<< "*********************************" << std::endl);
@@ -170,8 +196,7 @@ int main(int argc, char const* const* argv)
doc.addCTestStandardDocSections();
if (doc.CheckOptions(argc, argv)) {
// Construct and print requested documentation.
- cmCTestScriptHandler* ch =
- static_cast<cmCTestScriptHandler*>(inst.GetHandler("script"));
+ cmCTestScriptHandler* ch = inst.GetScriptHandler();
ch->CreateCMake();
doc.SetShowGenerators(false);
@@ -185,8 +210,9 @@ int main(int argc, char const* const* argv)
// copy the args to a vector
std::vector<std::string> args;
+ args.reserve(argc);
for (int i = 0; i < argc; ++i) {
- args.push_back(argv[i]);
+ args.emplace_back(argv[i]);
}
// run ctest
std::string output;
diff --git a/Source/kwsys/Base64.c b/Source/kwsys/Base64.c
index 99f008e59..bf876f2d5 100644
--- a/Source/kwsys/Base64.c
+++ b/Source/kwsys/Base64.c
@@ -6,7 +6,7 @@
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "Base64.h.in"
+# include "Base64.h.in"
#endif
static const unsigned char kwsysBase64EncodeTable[65] =
diff --git a/Source/kwsys/Base64.h.in b/Source/kwsys/Base64.h.in
index 35367574a..729f97297 100644
--- a/Source/kwsys/Base64.h.in
+++ b/Source/kwsys/Base64.h.in
@@ -12,17 +12,17 @@
not visible to user code. Use kwsysHeaderDump.pl to reproduce
these macros after making changes to the interface. */
#if !defined(KWSYS_NAMESPACE)
-#define kwsys_ns(x) @KWSYS_NAMESPACE@##x
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsysBase64 kwsys_ns(Base64)
-#define kwsysBase64_Decode kwsys_ns(Base64_Decode)
-#define kwsysBase64_Decode3 kwsys_ns(Base64_Decode3)
-#define kwsysBase64_Encode kwsys_ns(Base64_Encode)
-#define kwsysBase64_Encode1 kwsys_ns(Base64_Encode1)
-#define kwsysBase64_Encode2 kwsys_ns(Base64_Encode2)
-#define kwsysBase64_Encode3 kwsys_ns(Base64_Encode3)
+# define kwsysBase64 kwsys_ns(Base64)
+# define kwsysBase64_Decode kwsys_ns(Base64_Decode)
+# define kwsysBase64_Decode3 kwsys_ns(Base64_Decode3)
+# define kwsysBase64_Encode kwsys_ns(Base64_Encode)
+# define kwsysBase64_Encode1 kwsys_ns(Base64_Encode1)
+# define kwsysBase64_Encode2 kwsys_ns(Base64_Encode2)
+# define kwsysBase64_Encode3 kwsys_ns(Base64_Encode3)
#endif
#if defined(__cplusplus)
@@ -94,17 +94,17 @@ kwsysEXPORT size_t kwsysBase64_Decode(const unsigned char* input,
/* If we are building a kwsys .c or .cxx file, let it use these macros.
Otherwise, undefine them to keep the namespace clean. */
#if !defined(KWSYS_NAMESPACE)
-#undef kwsys_ns
-#undef kwsysEXPORT
-#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#undef kwsysBase64
-#undef kwsysBase64_Decode
-#undef kwsysBase64_Decode3
-#undef kwsysBase64_Encode
-#undef kwsysBase64_Encode1
-#undef kwsysBase64_Encode2
-#undef kwsysBase64_Encode3
-#endif
+# undef kwsys_ns
+# undef kwsysEXPORT
+# if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# undef kwsysBase64
+# undef kwsysBase64_Decode
+# undef kwsysBase64_Decode3
+# undef kwsysBase64_Encode
+# undef kwsysBase64_Encode1
+# undef kwsysBase64_Encode2
+# undef kwsysBase64_Encode3
+# endif
#endif
#endif
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index e915b1a80..09bcdb943 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -20,12 +20,32 @@
# KWSYS_HEADER_ROOT = The directory into which to generate the kwsys headers.
# A directory called "${KWSYS_NAMESPACE}" will be
# created under this root directory to hold the files.
+# KWSYS_SPLIT_OBJECTS_FROM_INTERFACE
+# = Instead of creating a single ${KWSYS_NAMESPACE} library
+# target, create three separate targets:
+# ${KWSYS_NAMESPACE}
+# - An INTERFACE library only containing usage
+# requirements.
+# ${KWSYS_NAMESPACE}_objects
+# - An OBJECT library for the built kwsys objects.
+# Note: This is omitted from the install rules
+# ${KWSYS_NAMESPACE}_private
+# - An INTERFACE library combining both that is
+# appropriate for use with PRIVATE linking in
+# target_link_libraries. Because of how interface
+# properties propagate, this target is not suitable
+# for use with PUBLIC or INTERFACE linking.
+# KWSYS_ALIAS_TARGET = The name of an alias target to create to the actual target.
#
# Example:
#
# SET(KWSYS_HEADER_ROOT ${PROJECT_BINARY_DIR})
# INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR})
#
+# KWSYS_CXX_STANDARD = A value for CMAKE_CXX_STANDARD within KWSys.
+# Set to empty string to use no default value.
+# KWSYS_CXX_COMPILE_FEATURES = target_compile_features arguments for KWSys.
+#
# Optional settings to setup install rules are as follows:
#
# KWSYS_INSTALL_BIN_DIR = The installation target directories into
@@ -66,18 +86,17 @@
# any outside mailing list and no documentation of the change will be
# written.
-CMAKE_MINIMUM_REQUIRED(VERSION 2.6.3 FATAL_ERROR)
+CMAKE_MINIMUM_REQUIRED(VERSION 3.1 FATAL_ERROR)
FOREACH(p
- CMP0025 # CMake 3.0, Compiler id for Apple Clang is now AppleClang.
- 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.
+ CMP0067 # CMake 3.8, Honor language standard in try_compile source-file signature.
+ CMP0069 # CMake 3.9, INTERPROCEDURAL_OPTIMIZATION is enforced when enabled.
)
IF(POLICY ${p})
CMAKE_POLICY(SET ${p} NEW)
ENDIF()
ENDFOREACH()
-SET(CMAKE_LEGACY_CYGWIN_WIN32 0)
#-----------------------------------------------------------------------------
# If a namespace is not specified, use "kwsys" and enable testing.
@@ -98,6 +117,19 @@ SET_PROPERTY(DIRECTORY
"KWSYS_HEADER(%)=<${KWSYS_NAMESPACE}/%>"
)
+if(KWSYS_CXX_STANDARD)
+ set(CMAKE_CXX_STANDARD "${KWSYS_CXX_STANDARD}")
+elseif(NOT DEFINED CMAKE_CXX_STANDARD AND NOT DEFINED KWSYS_CXX_STANDARD)
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
+ AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC"
+ AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU"
+ )
+ set(CMAKE_CXX_STANDARD 14)
+ else()
+ set(CMAKE_CXX_STANDARD 11)
+ endif()
+endif()
+
# Select library components.
IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
SET(KWSYS_ENABLE_C 1)
@@ -147,6 +179,9 @@ ENDIF()
IF(KWSYS_USE_Directory)
SET(KWSYS_USE_Encoding 1)
ENDIF()
+IF(KWSYS_USE_DynamicLoader)
+ SET(KWSYS_USE_Encoding 1)
+ENDIF()
IF(KWSYS_USE_FStream)
SET(KWSYS_USE_Encoding 1)
ENDIF()
@@ -154,13 +189,6 @@ IF(KWSYS_USE_ConsoleBuf)
SET(KWSYS_USE_Encoding 1)
ENDIF()
-# Setup the large file support default.
-IF(KWSYS_LFS_DISABLE)
- SET(KWSYS_LFS_REQUESTED 0)
-ELSE()
- SET(KWSYS_LFS_REQUESTED 1)
-ENDIF()
-
# Specify default 8 bit encoding for Windows
IF(NOT KWSYS_ENCODING_DEFAULT_CODEPAGE)
SET(KWSYS_ENCODING_DEFAULT_CODEPAGE CP_ACP)
@@ -175,6 +203,11 @@ IF(KWSYS_STANDALONE)
ENDIF()
ENDIF()
+# Choose default shared/static build if not specified.
+IF(NOT DEFINED KWSYS_BUILD_SHARED)
+ SET(KWSYS_BUILD_SHARED ${BUILD_SHARED_LIBS})
+ENDIF()
+
# Include helper macros.
INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/kwsysPlatformTests.cmake)
INCLUDE(CheckTypeSize)
@@ -209,13 +242,14 @@ ENDIF()
# Setup library install rules.
SET(KWSYS_INSTALL_LIBRARY_RULE)
+SET(KWSYS_INSTALL_NAMELINK_RULE)
IF(KWSYS_INSTALL_LIB_DIR)
IF(KWSYS_INSTALL_EXPORT_NAME)
LIST(APPEND KWSYS_INSTALL_LIBRARY_RULE EXPORT ${KWSYS_INSTALL_EXPORT_NAME})
ENDIF()
# Install the shared library to the lib directory.
SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE}
- LIBRARY DESTINATION ${KWSYS_INSTALL_LIB_DIR}
+ LIBRARY DESTINATION ${KWSYS_INSTALL_LIB_DIR} NAMELINK_SKIP
)
# Assign the shared library to the runtime component.
IF(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME)
@@ -223,6 +257,17 @@ IF(KWSYS_INSTALL_LIB_DIR)
COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_RUNTIME}
)
ENDIF()
+ IF(KWSYS_BUILD_SHARED)
+ SET(KWSYS_INSTALL_NAMELINK_RULE ${KWSYS_INSTALL_NAMELINK_RULE}
+ LIBRARY DESTINATION ${KWSYS_INSTALL_LIB_DIR} NAMELINK_ONLY
+ )
+ # Assign the namelink to the development component.
+ IF(KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT)
+ SET(KWSYS_INSTALL_NAMELINK_RULE ${KWSYS_INSTALL_NAMELINK_RULE}
+ COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT}
+ )
+ ENDIF()
+ ENDIF()
# Install the archive to the lib directory.
SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE}
@@ -311,30 +356,6 @@ IF(KWSYS_STANDALONE)
ENDIF()
#-----------------------------------------------------------------------------
-# Configure Large File Support.
-KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_CSTDIO
- "Checking whether header cstdio is available" DIRECT)
-SET(KWSYS_LFS_AVAILABLE 0)
-IF(KWSYS_LFS_REQUESTED)
- # Large File Support is requested.
- SET(KWSYS_LFS_REQUESTED 1)
-
- # Check for large file support.
- SET(KWSYS_PLATFORM_CXX_TEST_DEFINES
- -DKWSYS_CXX_HAS_CSTDIO=${KWSYS_CXX_HAS_CSTDIO})
- KWSYS_PLATFORM_CXX_TEST_RUN(KWSYS_LFS_WORKS
- "Checking for Large File Support" DIRECT)
- SET(KWSYS_PLATFORM_CXX_TEST_DEFINES)
-
- IF(KWSYS_LFS_WORKS)
- SET(KWSYS_LFS_AVAILABLE 1)
- ENDIF()
-ELSE()
- # Large File Support is not requested.
- SET(KWSYS_LFS_REQUESTED 0)
-ENDIF()
-
-#-----------------------------------------------------------------------------
# Configure the standard library header wrappers based on compiler's
# capabilities and parent project's request. Enforce 0/1 as only
# possible values for configuration into Configure.hxx.
@@ -406,11 +427,6 @@ ELSE()
SET(KWSYS_NAME_IS_KWSYS 0)
ENDIF()
-# Choose default shared/static build if not specified.
-IF(KWSYS_BUILD_SHARED MATCHES "^KWSYS_BUILD_SHARED$")
- SET(KWSYS_BUILD_SHARED ${BUILD_SHARED_LIBS})
-ENDIF()
-
IF(KWSYS_BUILD_SHARED)
SET(KWSYS_BUILD_SHARED 1)
SET(KWSYS_LIBRARY_TYPE SHARED)
@@ -419,6 +435,10 @@ ELSE()
SET(KWSYS_LIBRARY_TYPE STATIC)
ENDIF()
+if(NOT DEFINED KWSYS_BUILD_PIC)
+ set(KWSYS_BUILD_PIC 0)
+endif()
+
#-----------------------------------------------------------------------------
# Configure some implementation details.
@@ -426,10 +446,20 @@ 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)
+ GET_PROPERTY(ProcessUNIX_FLAGS SOURCE ProcessUNIX.c PROPERTY COMPILE_FLAGS)
+ SET_PROPERTY(SOURCE ProcessUNIX.c PROPERTY COMPILE_FLAGS "${ProcessUNIX_FLAGS} -DKWSYSPE_USE_SELECT=${KWSYSPE_USE_SELECT}")
+ENDIF()
+
IF(KWSYS_USE_DynamicLoader)
GET_PROPERTY(KWSYS_SUPPORTS_SHARED_LIBS GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS)
IF(KWSYS_SUPPORTS_SHARED_LIBS)
@@ -442,6 +472,14 @@ IF(KWSYS_USE_DynamicLoader)
ENDIF()
IF(KWSYS_USE_SystemTools)
+ if (NOT DEFINED KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP)
+ set(KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP 1)
+ endif ()
+ if (KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP)
+ set(KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP 1)
+ else ()
+ set(KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP 0)
+ endif ()
KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_SETENV
"Checking whether CXX compiler has setenv" DIRECT)
KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_UNSETENV
@@ -465,6 +503,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)
@@ -506,9 +562,6 @@ IF(KWSYS_USE_SystemInformation)
COMPILE_DEFINITIONS KWSYS_SYS_HAS_MACHINE_CPU_H=1)
ENDIF()
ENDIF()
- IF(KWSYS_LFS_AVAILABLE AND NOT KWSYS_LFS_DISABLE)
- SET(KWSYS_PLATFORM_CXX_TEST_DEFINES -DKWSYS_HAS_LFS=1)
- ENDIF()
KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_RLIMIT64
"Checking whether CXX compiler has rlimit64" DIRECT)
SET(KWSYS_PLATFORM_CXX_TEST_DEFINES)
@@ -547,7 +600,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)
@@ -676,9 +729,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
@@ -795,68 +852,158 @@ ENDFOREACH()
#-----------------------------------------------------------------------------
# Add the library with the configured name and list of sources.
IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS)
- ADD_LIBRARY(${KWSYS_NAMESPACE} ${KWSYS_LIBRARY_TYPE}
- ${KWSYS_C_SRCS} ${KWSYS_CXX_SRCS})
- SET_PROPERTY(TARGET ${KWSYS_NAMESPACE} PROPERTY C_CLANG_TIDY "")
- SET_PROPERTY(TARGET ${KWSYS_NAMESPACE} PROPERTY CXX_CLANG_TIDY "")
- SET_PROPERTY(TARGET ${KWSYS_NAMESPACE} PROPERTY C_INCLUDE_WHAT_YOU_USE "")
- SET_PROPERTY(TARGET ${KWSYS_NAMESPACE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE "")
- SET_PROPERTY(TARGET ${KWSYS_NAMESPACE} PROPERTY LABELS ${KWSYS_LABELS_LIB})
+ IF(KWSYS_SPLIT_OBJECTS_FROM_INTERFACE)
+ SET(KWSYS_TARGET_INTERFACE ${KWSYS_NAMESPACE})
+ SET(KWSYS_TARGET_OBJECT ${KWSYS_NAMESPACE}_objects)
+ SET(KWSYS_TARGET_LINK ${KWSYS_NAMESPACE}_private)
+ SET(KWSYS_TARGET_INSTALL ${KWSYS_TARGET_INTERFACE} ${KWSYS_TARGET_LINK})
+ SET(KWSYS_LINK_DEPENDENCY INTERFACE)
+ ADD_LIBRARY(${KWSYS_TARGET_OBJECT} OBJECT
+ ${KWSYS_C_SRCS} ${KWSYS_CXX_SRCS})
+ IF(KWSYS_BUILD_SHARED OR KWSYS_BUILD_PIC)
+ SET_PROPERTY(TARGET ${KWSYS_TARGET_OBJECT} PROPERTY
+ POSITION_INDEPENDENT_CODE TRUE)
+ ENDIF()
+ ADD_LIBRARY(${KWSYS_TARGET_INTERFACE} INTERFACE)
+ ADD_LIBRARY(${KWSYS_TARGET_LINK} INTERFACE)
+ TARGET_LINK_LIBRARIES(${KWSYS_TARGET_LINK} INTERFACE
+ ${KWSYS_TARGET_INTERFACE})
+ TARGET_SOURCES(${KWSYS_TARGET_LINK} INTERFACE
+ $<TARGET_OBJECTS:${KWSYS_TARGET_OBJECT}>)
+ target_compile_features(${KWSYS_TARGET_OBJECT} PRIVATE ${KWSYS_CXX_COMPILE_FEATURES})
+ target_compile_features(${KWSYS_TARGET_INTERFACE} INTERFACE ${KWSYS_CXX_COMPILE_FEATURES})
+ ELSE()
+ SET(KWSYS_TARGET_INTERFACE ${KWSYS_NAMESPACE})
+ SET(KWSYS_TARGET_OBJECT ${KWSYS_NAMESPACE})
+ SET(KWSYS_TARGET_LINK ${KWSYS_NAMESPACE})
+ set(KWSYS_TARGET_INSTALL ${KWSYS_TARGET_LINK})
+ SET(KWSYS_LINK_DEPENDENCY PUBLIC)
+ ADD_LIBRARY(${KWSYS_TARGET_INTERFACE} ${KWSYS_LIBRARY_TYPE}
+ ${KWSYS_C_SRCS} ${KWSYS_CXX_SRCS})
+ target_compile_features(${KWSYS_TARGET_INTERFACE} PUBLIC ${KWSYS_CXX_COMPILE_FEATURES})
+ ENDIF()
+ if (KWSYS_ALIAS_TARGET)
+ add_library(${KWSYS_ALIAS_TARGET} ALIAS ${KWSYS_TARGET_INTERFACE})
+ endif ()
+ SET_TARGET_PROPERTIES(${KWSYS_TARGET_OBJECT} PROPERTIES
+ C_CLANG_TIDY ""
+ CXX_CLANG_TIDY ""
+ C_INCLUDE_WHAT_YOU_USE ""
+ CXX_INCLUDE_WHAT_YOU_USE ""
+ LABELS "${KWSYS_LABELS_LIB}")
IF(KWSYS_USE_DynamicLoader)
IF(UNIX)
- TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ${CMAKE_DL_LIBS})
+ TARGET_LINK_LIBRARIES(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY}
+ ${CMAKE_DL_LIBS})
ENDIF()
ENDIF()
IF(KWSYS_USE_SystemInformation)
IF(WIN32)
- TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ws2_32)
+ TARGET_LINK_LIBRARIES(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} ws2_32)
+ # link in dbghelp.dll for symbol lookup if MSVC 1800 or later
+ # Note that the dbghelp runtime is part of MS Windows OS
+ IF(MSVC_VERSION AND NOT MSVC_VERSION VERSION_LESS 1800)
+ TARGET_LINK_LIBRARIES(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} dbghelp)
+ ENDIF()
IF(KWSYS_SYS_HAS_PSAPI)
- TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} Psapi)
+ TARGET_LINK_LIBRARIES(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY}
+ Psapi)
ENDIF()
ELSEIF(UNIX)
IF (EXECINFO_LIB AND KWSYS_CXX_HAS_BACKTRACE)
# backtrace on FreeBSD is not in libc
- TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ${EXECINFO_LIB})
+ TARGET_LINK_LIBRARIES(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY}
+ ${EXECINFO_LIB})
ENDIF()
IF (KWSYS_CXX_HAS_DLADDR)
# for symbol lookup using dladdr
- TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ${CMAKE_DL_LIBS})
+ TARGET_LINK_LIBRARIES(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY}
+ ${CMAKE_DL_LIBS})
ENDIF()
IF (CMAKE_SYSTEM_NAME STREQUAL "SunOS")
- TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} socket)
+ TARGET_LINK_LIBRARIES(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY}
+ socket)
ENDIF()
ENDIF()
ENDIF()
# Apply user-defined target properties to the library.
IF(KWSYS_PROPERTIES_CXX)
- SET_TARGET_PROPERTIES(${KWSYS_NAMESPACE} PROPERTIES
- ${KWSYS_PROPERTIES_CXX}
- )
+ SET_TARGET_PROPERTIES(${KWSYS_TARGET_INTERFACE} PROPERTIES
+ ${KWSYS_PROPERTIES_CXX})
+ ENDIF()
+
+ # Set up include usage requirement
+ IF(COMMAND TARGET_INCLUDE_DIRECTORIES)
+ TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_INTERFACE} INTERFACE
+ $<BUILD_INTERFACE:${KWSYS_HEADER_ROOT}>)
+ IF(KWSYS_INSTALL_INCLUDE_DIR)
+ TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_INTERFACE} INTERFACE
+ $<INSTALL_INTERFACE:${KWSYS_INSTALL_INCLUDE_DIR}>)
+ ENDIF()
ENDIF()
# Create an install target for the library.
IF(KWSYS_INSTALL_LIBRARY_RULE)
- INSTALL(TARGETS ${KWSYS_NAMESPACE} ${KWSYS_INSTALL_LIBRARY_RULE})
+ INSTALL(TARGETS ${KWSYS_TARGET_INSTALL} ${KWSYS_INSTALL_LIBRARY_RULE})
+ ENDIF()
+ IF(KWSYS_INSTALL_NAMELINK_RULE)
+ INSTALL(TARGETS ${KWSYS_TARGET_INSTALL} ${KWSYS_INSTALL_NAMELINK_RULE})
ENDIF()
ENDIF()
# Add a C-only library if requested.
IF(KWSYS_ENABLE_C AND KWSYS_C_SRCS)
- ADD_LIBRARY(${KWSYS_NAMESPACE}_c ${KWSYS_LIBRARY_TYPE} ${KWSYS_C_SRCS})
- SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}_c PROPERTY LABELS ${KWSYS_LABELS_LIB})
+ IF(KWSYS_SPLIT_OBJECTS_FROM_INTERFACE)
+ SET(KWSYS_TARGET_C_INTERFACE ${KWSYS_NAMESPACE}_c)
+ SET(KWSYS_TARGET_C_OBJECT ${KWSYS_NAMESPACE}_c_objects)
+ SET(KWSYS_TARGET_C_LINK ${KWSYS_NAMESPACE}_c_private)
+ SET(KWSYS_TARGET_C_INSTALL
+ ${KWSYS_TARGET_C_INTERFACE} ${KWSYS_TARGET_C_LINK})
+ SET(KWSYS_LINK_DEPENDENCY INTERFACE)
+ ADD_LIBRARY(${KWSYS_TARGET_C_OBJECT} OBJECT ${KWSYS_C_SRCS})
+ IF(KWSYS_BUILD_SHARED OR KWSYS_BUILD_PIC)
+ SET_PROPERTY(TARGET ${KWSYS_TARGET_C_OBJECT} PROPERTY
+ POSITION_INDEPENDENT_CODE TRUE)
+ ENDIF()
+ ADD_LIBRARY(${KWSYS_TARGET_C_INTERFACE} INTERFACE)
+ ADD_LIBRARY(${KWSYS_TARGET_C_LINK} INTERFACE)
+ TARGET_LINK_LIBRARIES(${KWSYS_TARGET_C_LINK} INTERFACE
+ ${KWSYS_TARGET_C_INTERFACE})
+ TARGET_SOURCES(${KWSYS_TARGET_C_LINK} INTERFACE
+ $<TARGET_OBJECTS:${KWSYS_TARGET_C_OBJECT}>)
+ ELSE()
+ SET(KWSYS_TARGET_C_INTERFACE ${KWSYS_NAMESPACE}_c)
+ SET(KWSYS_TARGET_C_OBJECT ${KWSYS_NAMESPACE}_c)
+ SET(KWSYS_TARGET_C_LINK ${KWSYS_NAMESPACE}_c)
+ SET(KWSYS_TARGET_C_INSTALL ${KWSYS_TARGET_C_LINK})
+ SET(KWSYS_LINK_DEPENDENCY PUBLIC)
+ ADD_LIBRARY(${KWSYS_TARGET_C_INTERFACE} ${KWSYS_LIBRARY_TYPE}
+ ${KWSYS_C_SRCS})
+ ENDIF()
+ SET_TARGET_PROPERTIES(${KWSYS_TARGET_C_OBJECT} PROPERTIES
+ LABELS "${KWSYS_LABELS_LIB}")
# Apply user-defined target properties to the library.
IF(KWSYS_PROPERTIES_C)
- SET_TARGET_PROPERTIES(${KWSYS_NAMESPACE}_c PROPERTIES
- ${KWSYS_PROPERTIES_C}
- )
+ SET_TARGET_PROPERTIES(${KWSYS_TARGET_C_INTERFACE} PROPERTIES
+ ${KWSYS_PROPERTIES_C})
+ ENDIF()
+
+ # Set up include usage requirement
+ IF(COMMAND TARGET_INCLUDE_DIRECTORIES)
+ TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_C_INTERFACE} INTERFACE
+ $<BUILD_INTERFACE:${KWSYS_HEADER_ROOT}>)
+ IF(KWSYS_INSTALL_INCLUDE_DIR)
+ TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_C_INTERFACE} INTERFACE
+ $<INSTALL_INTERFACE:${KWSYS_INSTALL_INCLUDE_DIR}>)
+ ENDIF()
ENDIF()
# Create an install target for the library.
IF(KWSYS_INSTALL_LIBRARY_RULE)
- INSTALL(TARGETS ${KWSYS_NAMESPACE}_c ${KWSYS_INSTALL_LIBRARY_RULE})
+ INSTALL(TARGETS ${KWSYS_TARGET_C_INSTALL})
ENDIF()
ENDIF()
@@ -865,7 +1012,8 @@ ENDIF()
ADD_DEFINITIONS("-DKWSYS_NAMESPACE=${KWSYS_NAMESPACE}")
# Disable deprecation warnings for standard C functions.
-IF(MSVC OR (WIN32 AND CMAKE_C_COMPILER_ID STREQUAL "Intel"))
+IF(MSVC OR (WIN32 AND (CMAKE_C_COMPILER_ID STREQUAL "Intel" OR
+ (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC"))))
ADD_DEFINITIONS(
-D_CRT_NONSTDC_NO_DEPRECATE
-D_CRT_SECURE_NO_DEPRECATE
@@ -903,11 +1051,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
@@ -915,32 +1063,34 @@ 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_NAMESPACE}_c)
- FOREACH(test ${KWSYS_C_TESTS})
+ TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE}TestsC ${KWSYS_TARGET_C_LINK})
+ 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}
- testIOS
- testSystemTools
- testCommandLineArguments
- testCommandLineArguments1
+ 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)
@@ -950,11 +1100,11 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
SET_PROPERTY(TARGET testConsoleBufChild PROPERTY C_INCLUDE_WHAT_YOU_USE "")
SET_PROPERTY(TARGET testConsoleBufChild PROPERTY CXX_INCLUDE_WHAT_YOU_USE "")
SET_PROPERTY(TARGET testConsoleBufChild PROPERTY LABELS ${KWSYS_LABELS_EXE})
- TARGET_LINK_LIBRARIES(testConsoleBufChild ${KWSYS_NAMESPACE})
+ 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
+ IF(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND
CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "19.0.23506")
set_property(SOURCE testConsoleBuf.cxx testConsoleBufChild.cxx PROPERTY COMPILE_FLAGS /utf-8)
ENDIF()
@@ -962,14 +1112,28 @@ 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})
- ADD_DEPENDENCIES(${KWSYS_NAMESPACE}TestDynload ${KWSYS_NAMESPACE})
+ ADD_DEPENDENCIES(${KWSYS_NAMESPACE}TestDynload ${KWSYS_TARGET_INTERFACE})
+
+ if (WIN32)
+ # Windows tests supported flags.
+ add_library(${KWSYS_NAMESPACE}TestDynloadImpl SHARED testDynloadImpl.c)
+ set_property(TARGET ${KWSYS_NAMESPACE}TestDynloadImpl PROPERTY LABELS ${KWSYS_LABELS_LIB})
+ set_property(TARGET ${KWSYS_NAMESPACE}TestDynloadImpl PROPERTY DEFINE_SYMBOL BUILDING_TestDynloadImpl)
+ set_property(TARGET ${KWSYS_NAMESPACE}TestDynloadImpl PROPERTY RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/dynloaddir")
+ add_dependencies(${KWSYS_NAMESPACE}TestDynloadImpl ${KWSYS_TARGET_INTERFACE})
+ add_library(${KWSYS_NAMESPACE}TestDynloadUse MODULE testDynloadUse.c)
+ set_property(TARGET ${KWSYS_NAMESPACE}TestDynloadUse PROPERTY LABELS ${KWSYS_LABELS_LIB})
+ set_property(TARGET ${KWSYS_NAMESPACE}TestDynloadUse PROPERTY LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/dynloaddir")
+ add_dependencies(${KWSYS_NAMESPACE}TestDynloadUse ${KWSYS_TARGET_INTERFACE})
+ target_link_libraries(${KWSYS_NAMESPACE}TestDynloadUse PRIVATE ${KWSYS_NAMESPACE}TestDynloadImpl)
+ endif ()
ENDIF()
CREATE_TEST_SOURCELIST(
KWSYS_CXX_TEST_SRCS ${KWSYS_NAMESPACE}TestsCxx.cxx
@@ -981,7 +1145,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY C_INCLUDE_WHAT_YOU_USE "")
SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY CXX_INCLUDE_WHAT_YOU_USE "")
SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY LABELS ${KWSYS_LABELS_EXE})
- TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE}TestsCxx ${KWSYS_NAMESPACE})
+ TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE}TestsCxx ${KWSYS_TARGET_LINK})
SET(TEST_SYSTEMTOOLS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
SET(TEST_SYSTEMTOOLS_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
@@ -1024,7 +1188,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()
@@ -1032,7 +1197,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
# Process tests.
ADD_EXECUTABLE(${KWSYS_NAMESPACE}TestProcess testProcess.c)
SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestProcess PROPERTY LABELS ${KWSYS_LABELS_EXE})
- TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE}TestProcess ${KWSYS_NAMESPACE}_c)
+ TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE}TestProcess ${KWSYS_TARGET_C_LINK})
IF(NOT CYGWIN)
SET(KWSYS_TEST_PROCESS_7 7)
ENDIF()
@@ -1042,17 +1207,26 @@ 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)
- 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"))
+ SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -O0")
+ ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "XL")
# 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)
+ IF(CMAKE_SYSTEM MATCHES "Linux.*ppc64le"
+ AND CMAKE_C_COMPILER_VERSION VERSION_LESS "16.1.0"
+ AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS "13.1.1")
+ # v13.1.[1-6] on Linux ppc64le is clang based and does not accept
+ # the -qsuppress option, so just suppress all warnings.
+ SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -w")
+ ELSE()
+ SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -qsuppress=1500-010")
+ ENDIF()
+ 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
@@ -1060,7 +1234,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
ADD_EXECUTABLE(${KWSYS_NAMESPACE}TestSharedForward
${PROJECT_BINARY_DIR}/testSharedForward.c)
SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestSharedForward PROPERTY LABELS ${KWSYS_LABELS_EXE})
- ADD_DEPENDENCIES(${KWSYS_NAMESPACE}TestSharedForward ${KWSYS_NAMESPACE}_c)
+ ADD_DEPENDENCIES(${KWSYS_NAMESPACE}TestSharedForward ${KWSYS_TARGET_C_LINK})
ADD_TEST(kwsys.testSharedForward ${EXEC_DIR}/${KWSYS_NAMESPACE}TestSharedForward 1)
SET_PROPERTY(TEST kwsys.testSharedForward PROPERTY LABELS ${KWSYS_LABELS_TEST})
diff --git a/Source/kwsys/CONTRIBUTING.rst b/Source/kwsys/CONTRIBUTING.rst
index 70a313e05..32e7b83c5 100644
--- a/Source/kwsys/CONTRIBUTING.rst
+++ b/Source/kwsys/CONTRIBUTING.rst
@@ -27,7 +27,7 @@ copies of KWSys within dependent projects can be updated to get the changes.
Code Style
==========
-We use `clang-format`_ version **3.8** to define our style for C++ code in
+We use `clang-format`_ version **6.0** to define our style for C++ code in
the KWSys source tree. See the `.clang-format`_ configuration file for
our style settings. Use the `clang-format.bash`_ script to format source
code. It automatically runs ``clang-format`` on the set of source files
diff --git a/Source/kwsys/CommandLineArguments.cxx b/Source/kwsys/CommandLineArguments.cxx
index 5613bd7ab..3fd195561 100644
--- a/Source/kwsys/CommandLineArguments.cxx
+++ b/Source/kwsys/CommandLineArguments.cxx
@@ -9,9 +9,9 @@
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "CommandLineArguments.hxx.in"
-#include "Configure.hxx.in"
-#include "String.hxx.in"
+# include "CommandLineArguments.hxx.in"
+# include "Configure.hxx.in"
+# include "String.hxx.in"
#endif
#include <iostream>
@@ -25,18 +25,18 @@
#include <string.h>
#ifdef _MSC_VER
-#pragma warning(disable : 4786)
+# pragma warning(disable : 4786)
#endif
#if defined(__sgi) && !defined(__GNUC__)
-#pragma set woff 1375 /* base class destructor not virtual */
+# pragma set woff 1375 /* base class destructor not virtual */
#endif
#if 0
-#define CommandLineArguments_DEBUG(x) \
- std::cout << __LINE__ << " CLA: " << x << std::endl
+# define CommandLineArguments_DEBUG(x) \
+ std::cout << __LINE__ << " CLA: " << x << std::endl
#else
-#define CommandLineArguments_DEBUG(x)
+# define CommandLineArguments_DEBUG(x)
#endif
namespace KWSYS_NAMESPACE {
@@ -67,10 +67,10 @@ class CommandLineArgumentsInternal
{
public:
CommandLineArgumentsInternal()
+ : UnknownArgumentCallback{ nullptr }
+ , ClientData{ nullptr }
+ , LastArgument{ 0 }
{
- this->UnknownArgumentCallback = 0;
- this->ClientData = 0;
- this->LastArgument = 0;
}
typedef CommandLineArgumentsVectorOfStrings VectorOfStrings;
@@ -187,7 +187,7 @@ int CommandLineArguments::Parse()
switch (cs->ArgumentType) {
case NO_ARGUMENT:
// No value
- if (!this->PopulateVariable(cs, 0)) {
+ if (!this->PopulateVariable(cs, 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 = 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 = nullptr;
+ s.CallData = 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 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 = 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 = 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 = 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 = nullptr;
variable->push_back(strtod(value.c_str(), &res));
// if ( res && *res )
// {
diff --git a/Source/kwsys/CommandLineArguments.hxx.in b/Source/kwsys/CommandLineArguments.hxx.in
index 31115e51f..7db901556 100644
--- a/Source/kwsys/CommandLineArguments.hxx.in
+++ b/Source/kwsys/CommandLineArguments.hxx.in
@@ -62,6 +62,9 @@ public:
CommandLineArguments();
~CommandLineArguments();
+ CommandLineArguments(const CommandLineArguments&) = delete;
+ CommandLineArguments& operator=(const CommandLineArguments&) = delete;
+
/**
* Various argument types.
*/
diff --git a/Source/kwsys/Configure.h.in b/Source/kwsys/Configure.h.in
index 0afcae781..5323c57be 100644
--- a/Source/kwsys/Configure.h.in
+++ b/Source/kwsys/Configure.h.in
@@ -7,110 +7,72 @@
namespace. When not building a kwsys source file these macros are
temporarily defined inside the headers that use them. */
#if defined(KWSYS_NAMESPACE)
-#define kwsys_ns(x) @KWSYS_NAMESPACE@##x
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
/* Disable some warnings inside kwsys source files. */
#if defined(KWSYS_NAMESPACE)
-#if defined(__BORLANDC__)
-#pragma warn - 8027 /* function not inlined. */
-#endif
-#if defined(__INTEL_COMPILER)
-#pragma warning(disable : 1572) /* floating-point equality test */
-#endif
-#if defined(__sgi) && !defined(__GNUC__)
-#pragma set woff 3970 /* pointer to int conversion */
-#pragma set woff 3968 /* 64 bit conversion */
-#endif
+# if defined(__BORLANDC__)
+# pragma warn - 8027 /* function not inlined. */
+# endif
+# if defined(__INTEL_COMPILER)
+# pragma warning(disable : 1572) /* floating-point equality test */
+# endif
+# if defined(__sgi) && !defined(__GNUC__)
+# pragma set woff 3970 /* pointer to int conversion */
+# pragma set woff 3968 /* 64 bit conversion */
+# endif
#endif
/* Whether kwsys namespace is "kwsys". */
#define @KWSYS_NAMESPACE@_NAME_IS_KWSYS @KWSYS_NAME_IS_KWSYS@
-/* Whether Large File Support is requested. */
-#define @KWSYS_NAMESPACE@_LFS_REQUESTED @KWSYS_LFS_REQUESTED@
-
-/* Whether Large File Support is available. */
-#if @KWSYS_NAMESPACE@_LFS_REQUESTED
-#define @KWSYS_NAMESPACE@_LFS_AVAILABLE @KWSYS_LFS_AVAILABLE@
-#endif
-
-/* Setup Large File Support if requested. */
-#if @KWSYS_NAMESPACE@_LFS_REQUESTED
-/* Since LFS is requested this header must be included before system
- headers whether or not LFS is available. */
-#if 0 && (defined(_SYS_TYPES_H) || defined(_SYS_TYPES_INCLUDED))
-#error "@KWSYS_NAMESPACE@/Configure.h must be included before sys/types.h"
-#endif
-/* Enable the large file API if it is available. */
-#if @KWSYS_NAMESPACE@_LFS_AVAILABLE && \
- !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINES)
-#if !defined(_LARGEFILE_SOURCE) && \
- !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINE_LARGEFILE_SOURCE)
-#define _LARGEFILE_SOURCE
-#endif
-#if !defined(_LARGEFILE64_SOURCE) && \
- !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINE_LARGEFILE64_SOURCE)
-#define _LARGEFILE64_SOURCE
-#endif
-#if !defined(_LARGE_FILES) && \
- !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINE_LARGE_FILES)
-#define _LARGE_FILES
-#endif
-#if !defined(_FILE_OFFSET_BITS) && \
- !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
-
/* Setup the export macro. */
#if @KWSYS_BUILD_SHARED@
-#if defined(_WIN32) || defined(__CYGWIN__)
-#if defined(@KWSYS_NAMESPACE@_EXPORTS)
-#define @KWSYS_NAMESPACE@_EXPORT __declspec(dllexport)
+# if defined(_WIN32) || defined(__CYGWIN__)
+# if defined(@KWSYS_NAMESPACE@_EXPORTS)
+# define @KWSYS_NAMESPACE@_EXPORT __declspec(dllexport)
+# else
+# define @KWSYS_NAMESPACE@_EXPORT __declspec(dllimport)
+# endif
+# elif __GNUC__ >= 4
+# define @KWSYS_NAMESPACE@_EXPORT __attribute__((visibility("default")))
+# else
+# define @KWSYS_NAMESPACE@_EXPORT
+# endif
#else
-#define @KWSYS_NAMESPACE@_EXPORT __declspec(dllimport)
-#endif
-#elif __GNUC__ >= 4
-#define @KWSYS_NAMESPACE@_EXPORT __attribute__((visibility("default")))
-#else
-#define @KWSYS_NAMESPACE@_EXPORT
-#endif
-#else
-#define @KWSYS_NAMESPACE@_EXPORT
+# define @KWSYS_NAMESPACE@_EXPORT
#endif
/* Enable warnings that are off by default but are useful. */
#if !defined(@KWSYS_NAMESPACE@_NO_WARNING_ENABLE)
-#if defined(_MSC_VER)
-#pragma warning(default : 4263) /* no override, call convention differs */
-#endif
+# if defined(_MSC_VER)
+# pragma warning(default : 4263) /* no override, call convention differs \
+ */
+# endif
#endif
/* Disable warnings that are on by default but occur in valid code. */
#if !defined(@KWSYS_NAMESPACE@_NO_WARNING_DISABLE)
-#if defined(_MSC_VER)
-#pragma warning(disable : 4097) /* typedef is synonym for class */
-#pragma warning(disable : 4127) /* conditional expression is constant */
-#pragma warning(disable : 4244) /* possible loss in conversion */
-#pragma warning(disable : 4251) /* missing DLL-interface */
-#pragma warning(disable : 4305) /* truncation from type1 to type2 */
-#pragma warning(disable : 4309) /* truncation of constant value */
-#pragma warning(disable : 4514) /* unreferenced inline function */
-#pragma warning(disable : 4706) /* assignment in conditional expression */
-#pragma warning(disable : 4710) /* function not inlined */
-#pragma warning(disable : 4786) /* identifier truncated in debug info */
-#endif
-#if defined(__BORLANDC__) && !defined(__cplusplus)
+# if defined(_MSC_VER)
+# pragma warning(disable : 4097) /* typedef is synonym for class */
+# pragma warning(disable : 4127) /* conditional expression is constant */
+# pragma warning(disable : 4244) /* possible loss in conversion */
+# pragma warning(disable : 4251) /* missing DLL-interface */
+# pragma warning(disable : 4305) /* truncation from type1 to type2 */
+# pragma warning(disable : 4309) /* truncation of constant value */
+# pragma warning(disable : 4514) /* unreferenced inline function */
+# pragma warning(disable : 4706) /* assignment in conditional expression \
+ */
+# pragma warning(disable : 4710) /* function not inlined */
+# pragma warning(disable : 4786) /* identifier truncated in debug info */
+# endif
+# if defined(__BORLANDC__) && !defined(__cplusplus)
/* Code has no effect; raised by winnt.h in C (not C++) when ignoring an
unused parameter using "(param)" syntax (i.e. no cast to void). */
-#pragma warn - 8019
-#endif
+# pragma warn - 8019
+# endif
#endif
/* MSVC 6.0 in release mode will warn about code it produces with its
@@ -118,10 +80,10 @@
configuration. Real warnings will be revealed by a debug build or
by other compilers. */
#if !defined(@KWSYS_NAMESPACE@_NO_WARNING_DISABLE_BOGUS)
-#if defined(_MSC_VER) && (_MSC_VER < 1300) && defined(NDEBUG)
-#pragma warning(disable : 4701) /* Variable may be used uninitialized. */
-#pragma warning(disable : 4702) /* Unreachable code. */
-#endif
+# if defined(_MSC_VER) && (_MSC_VER < 1300) && defined(NDEBUG)
+# pragma warning(disable : 4701) /* Variable may be used uninitialized. */
+# pragma warning(disable : 4702) /* Unreachable code. */
+# endif
#endif
#endif
diff --git a/Source/kwsys/Configure.hxx.in b/Source/kwsys/Configure.hxx.in
index 1c07a4ef7..29a2dd11e 100644
--- a/Source/kwsys/Configure.hxx.in
+++ b/Source/kwsys/Configure.hxx.in
@@ -11,17 +11,55 @@
/* Whether <ext/stdio_filebuf.h> is available. */
#define @KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H \
@KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H@
+/* Whether the translation map is available or not. */
+#define @KWSYS_NAMESPACE@_SYSTEMTOOLS_USE_TRANSLATION_MAP \
+ @KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP@
+
+#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)
-#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsys @KWSYS_NAMESPACE@
-#endif
-#define KWSYS_NAME_IS_KWSYS @KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#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
+# if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# define kwsys @KWSYS_NAMESPACE@
+# endif
+# define KWSYS_NAME_IS_KWSYS @KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# 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_SYSTEMTOOLS_USE_TRANSLATION_MAP \
+ @KWSYS_NAMESPACE@_SYSTEMTOOLS_USE_TRANSLATION_MAP
#endif
#endif
diff --git a/Source/kwsys/ConsoleBuf.hxx.in b/Source/kwsys/ConsoleBuf.hxx.in
index 46d65a865..49dbdf7ea 100644
--- a/Source/kwsys/ConsoleBuf.hxx.in
+++ b/Source/kwsys/ConsoleBuf.hxx.in
@@ -15,10 +15,10 @@
#include <string>
#if defined(_WIN32)
-#include <windows.h>
-#if __cplusplus >= 201103L
-#include <system_error>
-#endif
+# include <windows.h>
+# if __cplusplus >= 201103L
+# include <system_error>
+# endif
#endif
namespace @KWSYS_NAMESPACE@ {
@@ -116,7 +116,7 @@ protected:
DWORD charsWritten;
success =
::WriteConsoleW(m_hOutput, wbuffer.c_str(), (DWORD)wbuffer.size(),
- &charsWritten, NULL) == 0
+ &charsWritten, nullptr) == 0
? false
: true;
} else {
@@ -124,8 +124,9 @@ protected:
std::string buffer;
success = encodeOutputBuffer(wbuffer, buffer);
if (success) {
- success = ::WriteFile(m_hOutput, buffer.c_str(),
- (DWORD)buffer.size(), &bytesWritten, NULL) == 0
+ success =
+ ::WriteFile(m_hOutput, buffer.c_str(), (DWORD)buffer.size(),
+ &bytesWritten, nullptr) == 0
? false
: true;
}
@@ -152,7 +153,7 @@ protected:
DWORD charsRead;
if (ReadConsoleW(m_hInput, wbuffer,
(sizeof(wbuffer) / sizeof(wbuffer[0])), &charsRead,
- NULL) == 0 ||
+ nullptr) == 0 ||
charsRead == 0) {
_setg(true);
return Traits::eof();
@@ -168,7 +169,7 @@ protected:
return Traits::eof();
}
char* buffer = new char[size.LowPart];
- while (ReadFile(m_hInput, buffer, size.LowPart, &bytesRead, NULL) ==
+ while (ReadFile(m_hInput, buffer, size.LowPart, &bytesRead, nullptr) ==
0) {
if (GetLastError() == ERROR_MORE_DATA) {
strbuffer += std::string(buffer, bytesRead);
@@ -231,12 +232,12 @@ private:
(!input && m_hOutput == INVALID_HANDLE_VALUE)) {
std::string errmsg =
"GetStdHandle(" + handleName + ") returned INVALID_HANDLE_VALUE";
-#if __cplusplus >= 201103L
+# if __cplusplus >= 201103L
throw std::system_error(::GetLastError(), std::system_category(),
errmsg);
-#else
+# else
throw std::runtime_error(errmsg);
-#endif
+# endif
}
}
UINT getConsolesCodepage()
@@ -264,6 +265,7 @@ private:
if (m_isConsoleInput) {
break;
}
+ @KWSYS_NAMESPACE@_FALLTHROUGH;
case FILE_TYPE_PIPE:
m_activeInputCodepage = input_pipe_codepage;
break;
@@ -290,6 +292,7 @@ private:
if (m_isConsoleOutput) {
break;
}
+ @KWSYS_NAMESPACE@_FALLTHROUGH;
case FILE_TYPE_PIPE:
m_activeOutputCodepage = output_pipe_codepage;
break;
@@ -325,11 +328,12 @@ private:
}
const int length =
WideCharToMultiByte(m_activeOutputCodepage, 0, wbuffer.c_str(),
- (int)wbuffer.size(), NULL, 0, NULL, NULL);
+ (int)wbuffer.size(), nullptr, 0, nullptr, nullptr);
char* buf = new char[length];
const bool success =
WideCharToMultiByte(m_activeOutputCodepage, 0, wbuffer.c_str(),
- (int)wbuffer.size(), buf, length, NULL, NULL) > 0
+ (int)wbuffer.size(), buf, length, nullptr,
+ nullptr) > 0
? true
: false;
buffer = std::string(buf, length);
@@ -354,7 +358,7 @@ private:
length -= BOMsize;
}
const size_t wlength = static_cast<size_t>(MultiByteToWideChar(
- actualCodepage, 0, data, static_cast<int>(length), NULL, 0));
+ actualCodepage, 0, data, static_cast<int>(length), nullptr, 0));
wchar_t* wbuf = new wchar_t[wlength];
const bool success =
MultiByteToWideChar(actualCodepage, 0, data, static_cast<int>(length),
diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx
index 5141d4519..e3791826b 100644
--- a/Source/kwsys/Directory.cxx
+++ b/Source/kwsys/Directory.cxx
@@ -10,9 +10,9 @@
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Configure.hxx.in"
-#include "Directory.hxx.in"
-#include "Encoding.hxx.in"
+# include "Configure.hxx.in"
+# include "Directory.hxx.in"
+# include "Encoding.hxx.in"
#endif
#include <string>
@@ -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 nullptr;
}
return this->Internal->Files[dindex].c_str();
}
@@ -69,40 +69,40 @@ void Directory::Clear()
// First Windows platforms
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <windows.h>
+# include <windows.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <io.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
+# include <ctype.h>
+# include <fcntl.h>
+# include <io.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <sys/stat.h>
+# include <sys/types.h>
// Wide function names can vary depending on compiler:
-#ifdef __BORLANDC__
-#define _wfindfirst_func __wfindfirst
-#define _wfindnext_func __wfindnext
-#else
-#define _wfindfirst_func _wfindfirst
-#define _wfindnext_func _wfindnext
-#endif
+# ifdef __BORLANDC__
+# define _wfindfirst_func __wfindfirst
+# define _wfindnext_func __wfindnext
+# else
+# define _wfindfirst_func _wfindfirst
+# define _wfindnext_func _wfindnext
+# endif
namespace KWSYS_NAMESPACE {
bool Directory::Load(const std::string& name)
{
this->Clear();
-#if (defined(_MSC_VER) && _MSC_VER < 1300) || defined(__BORLANDC__)
+# if (defined(_MSC_VER) && _MSC_VER < 1300) || defined(__BORLANDC__)
// Older Visual C++ and Embarcadero compilers.
long srchHandle;
-#else // Newer Visual C++
+# else // Newer Visual C++
intptr_t srchHandle;
-#endif
+# endif
char* buf;
size_t n = name.size();
- if (*name.rbegin() == '/' || *name.rbegin() == '\\') {
+ if (name.back() == '/' || name.back() == '\\') {
buf = new char[n + 1 + 1];
sprintf(buf, "%s*", name.c_str());
} else {
@@ -118,8 +118,8 @@ bool Directory::Load(const std::string& name)
struct _wfinddata_t data; // data of current file
// Now put them into the file array
- srchHandle =
- _wfindfirst_func((wchar_t*)Encoding::ToWide(buf).c_str(), &data);
+ srchHandle = _wfindfirst_func(
+ (wchar_t*)Encoding::ToWindowsExtendedPath(buf).c_str(), &data);
delete[] buf;
if (srchHandle == -1) {
@@ -136,15 +136,15 @@ bool Directory::Load(const std::string& name)
unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name)
{
-#if (defined(_MSC_VER) && _MSC_VER < 1300) || defined(__BORLANDC__)
+# if (defined(_MSC_VER) && _MSC_VER < 1300) || defined(__BORLANDC__)
// Older Visual C++ and Embarcadero compilers.
long srchHandle;
-#else // Newer Visual C++
+# else // Newer Visual C++
intptr_t srchHandle;
-#endif
+# endif
char* buf;
size_t n = name.size();
- if (*name.rbegin() == '/') {
+ if (name.back() == '/') {
buf = new char[n + 1 + 1];
sprintf(buf, "%s*", name.c_str());
} else {
@@ -177,23 +177,23 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name)
// Now the POSIX style directory access
-#include <sys/types.h>
+# include <sys/types.h>
-#include <dirent.h>
+# include <dirent.h>
// PGI with glibc has trouble with dirent and large file support:
// http://www.pgroup.com/userforum/viewtopic.php?
// p=1992&sid=f16167f51964f1a68fe5041b8eb213b6
// Work around the problem by mapping dirent the same way as readdir.
-#if defined(__PGI) && defined(__GLIBC__)
-#define kwsys_dirent_readdir dirent
-#define kwsys_dirent_readdir64 dirent64
-#define kwsys_dirent kwsys_dirent_lookup(readdir)
-#define kwsys_dirent_lookup(x) kwsys_dirent_lookup_delay(x)
-#define kwsys_dirent_lookup_delay(x) kwsys_dirent_##x
-#else
-#define kwsys_dirent dirent
-#endif
+# if defined(__PGI) && defined(__GLIBC__)
+# define kwsys_dirent_readdir dirent
+# define kwsys_dirent_readdir64 dirent64
+# define kwsys_dirent kwsys_dirent_lookup(readdir)
+# define kwsys_dirent_lookup(x) kwsys_dirent_lookup_delay(x)
+# define kwsys_dirent_lookup_delay(x) kwsys_dirent_##x
+# else
+# define kwsys_dirent dirent
+# endif
namespace KWSYS_NAMESPACE {
diff --git a/Source/kwsys/DynamicLoader.cxx b/Source/kwsys/DynamicLoader.cxx
index 1b4596a4e..a4b864118 100644
--- a/Source/kwsys/DynamicLoader.cxx
+++ b/Source/kwsys/DynamicLoader.cxx
@@ -1,15 +1,20 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+#if defined(_WIN32)
+# define NOMINMAX // hide min,max to not conflict with <limits>
+#endif
+
#include "kwsysPrivate.h"
#include KWSYS_HEADER(DynamicLoader.hxx)
#include KWSYS_HEADER(Configure.hxx)
+#include KWSYS_HEADER(Encoding.hxx)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Configure.hxx.in"
-#include "DynamicLoader.hxx.in"
+# include "Configure.hxx.in"
+# include "DynamicLoader.hxx.in"
#endif
// This file actually contains several different implementations:
@@ -25,14 +30,36 @@
// Each part of the ifdef contains a complete implementation for
// the static methods of DynamicLoader.
+#define CHECK_OPEN_FLAGS(var, supported, ret) \
+ do { \
+ /* Check for unknown flags. */ \
+ if ((var & AllOpenFlags) != var) { \
+ return ret; \
+ } \
+ \
+ /* Check for unsupported flags. */ \
+ if ((var & (supported)) != var) { \
+ return ret; \
+ } \
+ } while (0)
+
+namespace KWSYS_NAMESPACE {
+
+DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
+ const std::string& libname)
+{
+ return DynamicLoader::OpenLibrary(libname, 0);
+}
+}
+
#if !KWSYS_SUPPORTS_SHARED_LIBS
// Implementation for environments without dynamic libs
-#include <string.h> // for strerror()
+# include <string.h> // for strerror()
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
- const std::string& libname)
+ const std::string& libname, int flags)
{
return 0;
}
@@ -60,15 +87,17 @@ const char* DynamicLoader::LastError()
} // namespace KWSYS_NAMESPACE
#elif defined(__hpux)
-// Implementation for HPUX machines
-#include <dl.h>
-#include <errno.h>
+// Implementation for HPUX machines
+# include <dl.h>
+# include <errno.h>
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
- const std::string& libname)
+ const std::string& libname, int flags)
{
+ CHECK_OPEN_FLAGS(flags, 0, 0);
+
return shl_load(libname.c_str(), BIND_DEFERRED | DYNAMIC_PATH, 0L);
}
@@ -124,14 +153,16 @@ const char* DynamicLoader::LastError()
#elif defined(__APPLE__) && (MAC_OS_X_VERSION_MAX_ALLOWED < 1030)
// Implementation for Mac OS X 10.2.x and earlier
-#include <mach-o/dyld.h>
-#include <string.h> // for strlen
+# include <mach-o/dyld.h>
+# include <string.h> // for strlen
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
- const std::string& libname)
+ const std::string& libname, int flags)
{
+ CHECK_OPEN_FLAGS(flags, 0, 0);
+
NSObjectFileImageReturnCode rc;
NSObjectFileImage image = 0;
@@ -140,9 +171,9 @@ DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
if (rc != NSObjectFileImageSuccess) {
return 0;
}
- NSModule handle =
- NSLinkModule(image, libname.c_str(), NSLINKMODULE_OPTION_BINDNOW |
- NSLINKMODULE_OPTION_RETURN_ON_ERROR);
+ NSModule handle = NSLinkModule(image, libname.c_str(),
+ NSLINKMODULE_OPTION_BINDNOW |
+ NSLINKMODULE_OPTION_RETURN_ON_ERROR);
NSDestroyObjectFileImage(image);
return handle;
}
@@ -163,17 +194,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);
}
@@ -187,21 +214,24 @@ const char* DynamicLoader::LastError()
#elif defined(_WIN32) && !defined(__CYGWIN__)
// Implementation for Windows win32 code but not cygwin
-#include <windows.h>
+# include <windows.h>
+
+# include <stdio.h>
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
- const std::string& libname)
+ const std::string& libname, int flags)
{
- DynamicLoader::LibraryHandle lh;
- int length = MultiByteToWideChar(CP_UTF8, 0, libname.c_str(), -1, NULL, 0);
- wchar_t* wchars = new wchar_t[length + 1];
- wchars[0] = '\0';
- MultiByteToWideChar(CP_UTF8, 0, libname.c_str(), -1, wchars, length);
- lh = LoadLibraryW(wchars);
- delete[] wchars;
- return lh;
+ CHECK_OPEN_FLAGS(flags, SearchBesideLibrary, nullptr);
+
+ DWORD llFlags = 0;
+ if (flags & SearchBesideLibrary) {
+ llFlags |= LOAD_WITH_ALTERED_SEARCH_PATH;
+ }
+
+ return LoadLibraryExW(Encoding::ToWindowsExtendedPath(libname).c_str(),
+ nullptr, llFlags);
}
int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
@@ -235,45 +265,54 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
// Note that the "@X" part of the name above is the total size (in
// bytes) of the arguments on the stack.
void* result;
-#if defined(__BORLANDC__) || defined(__WATCOMC__)
+# 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());
-#else
+ std::string ssym = '_' + sym;
+ const char* rsym = ssym.c_str();
+# else
const char* rsym = sym.c_str();
-#endif
+# 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__
+# ifdef __WATCOMC__
return *(DynamicLoader::SymbolPointer*)(&result);
-#else
+# else
return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
-#endif
+# endif
}
+# define DYNLOAD_ERROR_BUFFER_SIZE 1024
+
const char* DynamicLoader::LastError()
{
- LPVOID lpMsgBuf = NULL;
-
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
- (LPTSTR)&lpMsgBuf, 0, NULL);
+ wchar_t lpMsgBuf[DYNLOAD_ERROR_BUFFER_SIZE + 1];
+
+ DWORD error = GetLastError();
+ DWORD length = FormatMessageW(
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, error,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ lpMsgBuf, DYNLOAD_ERROR_BUFFER_SIZE, nullptr);
+
+ static char str[DYNLOAD_ERROR_BUFFER_SIZE + 1];
+
+ if (length < 1) {
+ /* FormatMessage failed. Use a default message. */
+ _snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE,
+ "DynamicLoader encountered error 0x%X. "
+ "FormatMessage failed with error 0x%X",
+ error, GetLastError());
+ return str;
+ }
- if (!lpMsgBuf) {
- return NULL;
+ if (!WideCharToMultiByte(CP_UTF8, 0, lpMsgBuf, -1, str,
+ DYNLOAD_ERROR_BUFFER_SIZE, nullptr, nullptr)) {
+ /* WideCharToMultiByte failed. Use a default message. */
+ _snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE,
+ "DynamicLoader encountered error 0x%X. "
+ "WideCharToMultiByte failed with error 0x%X",
+ error, GetLastError());
}
- static char* str = 0;
- delete[] str;
- str = strcpy(new char[strlen((char*)lpMsgBuf) + 1], (char*)lpMsgBuf);
- // Free the buffer.
- LocalFree(lpMsgBuf);
return str;
}
@@ -281,18 +320,20 @@ const char* DynamicLoader::LastError()
#elif defined(__BEOS__)
// Implementation for BeOS / Haiku
-#include <string.h> // for strerror()
+# include <string.h> // for strerror()
-#include <be/kernel/image.h>
-#include <be/support/Errors.h>
+# include <be/kernel/image.h>
+# include <be/support/Errors.h>
namespace KWSYS_NAMESPACE {
static image_id last_dynamic_err = B_OK;
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
- const std::string& libname)
+ const std::string& libname, int flags)
{
+ CHECK_OPEN_FLAGS(flags, 0, 0);
+
// image_id's are integers, errors are negative. Add one just in case we
// get a valid image_id of zero (is that even possible?).
image_id rc = load_add_on(libname.c_str());
@@ -331,7 +372,7 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
DynamicLoader::SymbolPointer psym;
} result;
- result.psym = NULL;
+ result.psym = nullptr;
if (!lib) {
last_dynamic_err = B_BAD_VALUE;
@@ -343,7 +384,7 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
get_image_symbol(lib - 1, sym.c_str(), B_SYMBOL_TYPE_ANY, &result.pvoid);
if (rc != B_OK) {
last_dynamic_err = rc;
- result.psym = NULL;
+ result.psym = nullptr;
}
}
return result.psym;
@@ -360,17 +401,19 @@ const char* DynamicLoader::LastError()
#elif defined(__MINT__)
// Implementation for FreeMiNT on Atari
-#define _GNU_SOURCE /* for program_invocation_name */
-#include <dld.h>
-#include <errno.h>
-#include <malloc.h>
-#include <string.h>
+# define _GNU_SOURCE /* for program_invocation_name */
+# include <dld.h>
+# include <errno.h>
+# include <malloc.h>
+# include <string.h>
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
- const std::string& libname)
+ const std::string& libname, int flags)
{
+ CHECK_OPEN_FLAGS(flags, 0, nullptr);
+
char* name = (char*)calloc(1, libname.size() + 1);
dld_init(program_invocation_name);
strncpy(name, libname.c_str(), libname.size());
@@ -408,13 +451,15 @@ const char* DynamicLoader::LastError()
#else
// Default implementation for *NIX systems (including Mac OS X 10.3 and
// later) which use dlopen
-#include <dlfcn.h>
+# include <dlfcn.h>
namespace KWSYS_NAMESPACE {
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
- const std::string& libname)
+ const std::string& libname, int flags)
{
+ CHECK_OPEN_FLAGS(flags, 0, nullptr);
+
return dlopen(libname.c_str(), RTLD_LAZY);
}
diff --git a/Source/kwsys/DynamicLoader.hxx.in b/Source/kwsys/DynamicLoader.hxx.in
index 7e71a4593..539c74259 100644
--- a/Source/kwsys/DynamicLoader.hxx.in
+++ b/Source/kwsys/DynamicLoader.hxx.in
@@ -8,16 +8,16 @@
#include <string>
#if defined(__hpux)
-#include <dl.h>
+# include <dl.h>
#elif defined(_WIN32) && !defined(__CYGWIN__)
-#include <windows.h>
+# include <windows.h>
#elif defined(__APPLE__)
-#include <AvailabilityMacros.h>
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
-#include <mach-o/dyld.h>
-#endif
+# include <AvailabilityMacros.h>
+# if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
+# include <mach-o/dyld.h>
+# endif
#elif defined(__BEOS__)
-#include <be/kernel/image.h>
+# include <be/kernel/image.h>
#endif
namespace @KWSYS_NAMESPACE@ {
@@ -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
@@ -52,11 +52,11 @@ public:
#elif defined(_WIN32) && !defined(__CYGWIN__)
typedef HMODULE LibraryHandle;
#elif defined(__APPLE__)
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
+# if MAC_OS_X_VERSION_MAX_ALLOWED < 1030
typedef NSModule LibraryHandle;
-#else
+# else
typedef void* LibraryHandle;
-#endif
+# endif
#elif defined(__BEOS__)
typedef image_id LibraryHandle;
#else // POSIX
@@ -66,13 +66,26 @@ public:
// Return type from DynamicLoader::GetSymbolAddress.
typedef void (*SymbolPointer)();
+ enum OpenFlags
+ {
+ // Search for dependent libraries beside the library being loaded.
+ //
+ // This is currently only supported on Windows.
+ SearchBesideLibrary = 0x00000001,
+
+ AllOpenFlags = SearchBesideLibrary
+ };
+
/** Load a dynamic library into the current process.
* The returned LibraryHandle can be used to access the symbols in the
- * library. */
+ * library. The optional second argument is a set of flags to use when
+ * opening the library. If unrecognized or unsupported flags are specified,
+ * the library is not opened. */
static LibraryHandle OpenLibrary(const std::string&);
+ static LibraryHandle OpenLibrary(const std::string&, int);
/** 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/Encoding.h.in b/Source/kwsys/Encoding.h.in
index 7b6ed10f8..86a26692a 100644
--- a/Source/kwsys/Encoding.h.in
+++ b/Source/kwsys/Encoding.h.in
@@ -12,15 +12,15 @@
not visible to user code. Use kwsysHeaderDump.pl to reproduce
these macros after making changes to the interface. */
#if !defined(KWSYS_NAMESPACE)
-#define kwsys_ns(x) @KWSYS_NAMESPACE@##x
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsysEncoding kwsys_ns(Encoding)
-#define kwsysEncoding_mbstowcs kwsys_ns(Encoding_mbstowcs)
-#define kwsysEncoding_DupToWide kwsys_ns(Encoding_DupToWide)
-#define kwsysEncoding_wcstombs kwsys_ns(Encoding_wcstombs)
-#define kwsysEncoding_DupToNarrow kwsys_ns(Encoding_DupToNarrow)
+# define kwsysEncoding kwsys_ns(Encoding)
+# define kwsysEncoding_mbstowcs kwsys_ns(Encoding_mbstowcs)
+# define kwsysEncoding_DupToWide kwsys_ns(Encoding_DupToWide)
+# define kwsysEncoding_wcstombs kwsys_ns(Encoding_wcstombs)
+# define kwsysEncoding_DupToNarrow kwsys_ns(Encoding_DupToNarrow)
#endif
#if defined(__cplusplus)
@@ -55,15 +55,15 @@ kwsysEXPORT char* kwsysEncoding_DupToNarrow(const wchar_t* str);
/* If we are building a kwsys .c or .cxx file, let it use these macros.
Otherwise, undefine them to keep the namespace clean. */
#if !defined(KWSYS_NAMESPACE)
-#undef kwsys_ns
-#undef kwsysEXPORT
-#if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#undef kwsysEncoding
-#undef kwsysEncoding_mbstowcs
-#undef kwsysEncoding_DupToWide
-#undef kwsysEncoding_wcstombs
-#undef kwsysEncoding_DupToNarrow
-#endif
+# undef kwsys_ns
+# undef kwsysEXPORT
+# if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# undef kwsysEncoding
+# undef kwsysEncoding_mbstowcs
+# undef kwsysEncoding_DupToWide
+# undef kwsysEncoding_wcstombs
+# undef kwsysEncoding_DupToNarrow
+# endif
#endif
#endif
diff --git a/Source/kwsys/Encoding.hxx.in b/Source/kwsys/Encoding.hxx.in
index 09691fd3f..b06752115 100644
--- a/Source/kwsys/Encoding.hxx.in
+++ b/Source/kwsys/Encoding.hxx.in
@@ -41,9 +41,9 @@ public:
std::vector<char*> argv_;
};
-/**
- * Convert between char and wchar_t
- */
+ /**
+ * Convert between char and wchar_t
+ */
#if @KWSYS_NAMESPACE@_STL_HAS_WSTRING
@@ -59,7 +59,7 @@ public:
static std::string ToNarrow(const std::wstring& str);
static std::string ToNarrow(const wchar_t* str);
-#if defined(_WIN32)
+# if defined(_WIN32)
/**
* Convert the path to an extended length path to avoid MAX_PATH length
* limitations on Windows. If the input is a local path the result will be
@@ -68,7 +68,7 @@ public:
* absolute paths with Windows-style backslashes.
**/
static std::wstring ToWindowsExtendedPath(std::string const&);
-#endif
+# endif
#endif // @KWSYS_NAMESPACE@_STL_HAS_WSTRING
diff --git a/Source/kwsys/EncodingC.c b/Source/kwsys/EncodingC.c
index c1315b2d5..e12236afe 100644
--- a/Source/kwsys/EncodingC.c
+++ b/Source/kwsys/EncodingC.c
@@ -6,13 +6,13 @@
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "Encoding.h.in"
+# include "Encoding.h.in"
#endif
#include <stdlib.h>
#ifdef _WIN32
-#include <windows.h>
+# include <windows.h>
#endif
size_t kwsysEncoding_mbstowcs(wchar_t* dest, const char* str, size_t n)
diff --git a/Source/kwsys/EncodingCXX.cxx b/Source/kwsys/EncodingCXX.cxx
index b1e54c958..4593c9251 100644
--- a/Source/kwsys/EncodingCXX.cxx
+++ b/Source/kwsys/EncodingCXX.cxx
@@ -1,9 +1,9 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#ifdef __osf__
-#define _OSF_SOURCE
-#define _POSIX_C_SOURCE 199506L
-#define _XOPEN_SOURCE_EXTENDED
+# define _OSF_SOURCE
+# define _POSIX_C_SOURCE 199506L
+# define _XOPEN_SOURCE_EXTENDED
#endif
#include "kwsysPrivate.h"
@@ -13,8 +13,8 @@
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Encoding.h.in"
-#include "Encoding.hxx.in"
+# include "Encoding.h.in"
+# include "Encoding.hxx.in"
#endif
#include <stdlib.h>
@@ -22,15 +22,15 @@
#include <vector>
#ifdef _MSC_VER
-#pragma warning(disable : 4786)
+# pragma warning(disable : 4786)
#endif
// Windows API.
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
-#include <ctype.h>
-#include <shellapi.h>
+# include <ctype.h>
+# include <shellapi.h>
#endif
namespace KWSYS_NAMESPACE {
@@ -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] = 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] = 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]) : 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]) : nullptr;
}
}
@@ -127,9 +127,10 @@ char const* const* Encoding::CommandLineArguments::argv() const
std::wstring Encoding::ToWide(const std::string& str)
{
std::wstring wstr;
-#if defined(_WIN32)
- const int wlength = MultiByteToWideChar(
- KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.data(), int(str.size()), NULL, 0);
+# if defined(_WIN32)
+ const int wlength =
+ MultiByteToWideChar(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.data(),
+ int(str.size()), nullptr, 0);
if (wlength > 0) {
wchar_t* wdata = new wchar_t[wlength];
int r = MultiByteToWideChar(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.data(),
@@ -139,7 +140,7 @@ std::wstring Encoding::ToWide(const std::string& str)
}
delete[] wdata;
}
-#else
+# else
size_t pos = 0;
size_t nullPos = 0;
do {
@@ -152,28 +153,28 @@ std::wstring Encoding::ToWide(const std::string& str)
wstr += wchar_t('\0');
}
} while (nullPos != std::string::npos);
-#endif
+# endif
return wstr;
}
std::string Encoding::ToNarrow(const std::wstring& str)
{
std::string nstr;
-#if defined(_WIN32)
+# if defined(_WIN32)
int length =
WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.c_str(),
- int(str.size()), NULL, 0, NULL, NULL);
+ int(str.size()), nullptr, 0, nullptr, nullptr);
if (length > 0) {
char* data = new char[length];
int r =
WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.c_str(),
- int(str.size()), data, length, NULL, NULL);
+ int(str.size()), data, length, nullptr, nullptr);
if (r > 0) {
nstr = std::string(data, length);
}
delete[] data;
}
-#else
+# else
size_t pos = 0;
size_t nullPos = 0;
do {
@@ -186,14 +187,14 @@ std::string Encoding::ToNarrow(const std::wstring& str)
nstr += '\0';
}
} while (nullPos != std::string::npos);
-#endif
+# endif
return nstr;
}
std::wstring Encoding::ToWide(const char* cstr)
{
std::wstring wstr;
- size_t length = kwsysEncoding_mbstowcs(0, cstr, 0) + 1;
+ size_t length = kwsysEncoding_mbstowcs(nullptr, cstr, 0) + 1;
if (length > 0) {
std::vector<wchar_t> wchars(length);
if (kwsysEncoding_mbstowcs(&wchars[0], cstr, length) > 0) {
@@ -206,7 +207,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(nullptr, wcstr, 0) + 1;
if (length > 0) {
std::vector<char> chars(length);
if (kwsysEncoding_wcstombs(&chars[0], wcstr, length) > 0) {
@@ -216,7 +217,7 @@ std::string Encoding::ToNarrow(const wchar_t* wcstr)
return str;
}
-#if defined(_WIN32)
+# if defined(_WIN32)
// Convert local paths to UNC style paths
std::wstring Encoding::ToWindowsExtendedPath(std::string const& source)
{
@@ -227,9 +228,9 @@ std::wstring Encoding::ToWindowsExtendedPath(std::string const& source)
/* The +3 is a workaround for a bug in some versions of GetFullPathNameW that
* won't return a large enough buffer size if the input is too small */
- wfull_len = GetFullPathNameW(wsource.c_str(), 0, NULL, NULL) + 3;
+ wfull_len = GetFullPathNameW(wsource.c_str(), 0, nullptr, nullptr) + 3;
std::vector<wchar_t> wfull(wfull_len);
- GetFullPathNameW(wsource.c_str(), wfull_len, &wfull[0], NULL);
+ GetFullPathNameW(wsource.c_str(), wfull_len, &wfull[0], nullptr);
/* This should get the correct size without any extra padding from the
* previous size workaround. */
@@ -270,7 +271,7 @@ std::wstring Encoding::ToWindowsExtendedPath(std::string const& source)
// unchanged
return Encoding::ToWide(source);
}
-#endif
+# endif
#endif // KWSYS_STL_HAS_WSTRING
diff --git a/Source/kwsys/FStream.cxx b/Source/kwsys/FStream.cxx
index 3c44a6fa0..5e4133ac5 100644
--- a/Source/kwsys/FStream.cxx
+++ b/Source/kwsys/FStream.cxx
@@ -6,7 +6,7 @@
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "FStream.hxx.in"
+# include "FStream.hxx.in"
#endif
namespace KWSYS_NAMESPACE {
diff --git a/Source/kwsys/FStream.hxx.in b/Source/kwsys/FStream.hxx.in
index a4c65fe30..d79bbdf16 100644
--- a/Source/kwsys/FStream.hxx.in
+++ b/Source/kwsys/FStream.hxx.in
@@ -9,26 +9,26 @@
#include <fstream>
#if defined(_WIN32)
-#if !defined(_MSC_VER) && @KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H
-#include <ext/stdio_filebuf.h>
-#endif
+# if !defined(_MSC_VER) && @KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H
+# include <ext/stdio_filebuf.h>
+# endif
#endif
namespace @KWSYS_NAMESPACE@ {
#if defined(_WIN32) && \
(defined(_MSC_VER) || @KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H)
-#if defined(_NOEXCEPT)
-#define @KWSYS_NAMESPACE@_FStream_NOEXCEPT _NOEXCEPT
-#else
-#define @KWSYS_NAMESPACE@_FStream_NOEXCEPT
-#endif
+# if defined(_NOEXCEPT)
+# define @KWSYS_NAMESPACE@_FStream_NOEXCEPT _NOEXCEPT
+# else
+# define @KWSYS_NAMESPACE@_FStream_NOEXCEPT
+# endif
-#if defined(_MSC_VER)
+# if defined(_MSC_VER)
template <typename CharType, typename Traits>
class basic_filebuf : public std::basic_filebuf<CharType, Traits>
{
-#if _MSC_VER >= 1400
+# if _MSC_VER >= 1400
public:
typedef std::basic_filebuf<CharType, Traits> my_base_type;
basic_filebuf* open(char const* s, std::ios_base::openmode mode)
@@ -36,10 +36,10 @@ public:
const std::wstring wstr = Encoding::ToWindowsExtendedPath(s);
return static_cast<basic_filebuf*>(my_base_type::open(wstr.c_str(), mode));
}
-#endif
+# endif
};
-#else
+# else
inline std::wstring getcmode(const std::ios_base::openmode mode)
{
@@ -67,17 +67,17 @@ inline std::wstring getcmode(const std::ios_base::openmode mode)
return cmode;
};
-#endif
+# endif
template <typename CharType, typename Traits = std::char_traits<CharType> >
class basic_efilebuf
{
public:
-#if defined(_MSC_VER)
+# if defined(_MSC_VER)
typedef basic_filebuf<CharType, Traits> internal_buffer_type;
-#else
+# else
typedef __gnu_cxx::stdio_filebuf<CharType, Traits> internal_buffer_type;
-#endif
+# endif
basic_efilebuf()
: file_(0)
@@ -90,9 +90,9 @@ public:
if (is_open() || file_) {
return false;
}
-#if defined(_MSC_VER)
+# if defined(_MSC_VER)
const bool success = buf_->open(file_name, mode) != 0;
-#else
+# else
const std::wstring wstr = Encoding::ToWindowsExtendedPath(file_name);
bool success = false;
std::wstring cmode = getcmode(mode);
@@ -104,7 +104,7 @@ public:
buf_ = new internal_buffer_type(file_, mode);
success = true;
}
-#endif
+# endif
return success;
}
@@ -129,12 +129,12 @@ public:
bool success = false;
if (buf_) {
success = buf_->close() != 0;
-#if !defined(_MSC_VER)
+# if !defined(_MSC_VER)
if (file_) {
success = fclose(file_) == 0 ? success : false;
file_ = 0;
}
-#endif
+# endif
}
return success;
}
@@ -142,11 +142,11 @@ public:
static void _set_state(bool success, std::basic_ios<CharType, Traits>* ios,
basic_efilebuf* efilebuf)
{
-#if !defined(_MSC_VER)
+# if !defined(_MSC_VER)
ios->rdbuf(efilebuf->buf_);
-#else
+# else
static_cast<void>(efilebuf);
-#endif
+# endif
if (!success) {
ios->setstate(std::ios_base::failbit);
} else {
@@ -167,8 +167,9 @@ protected:
};
template <typename CharType, typename Traits = std::char_traits<CharType> >
-class basic_ifstream : public std::basic_istream<CharType, Traits>,
- public basic_efilebuf<CharType, Traits>
+class basic_ifstream
+ : public std::basic_istream<CharType, Traits>
+ , public basic_efilebuf<CharType, Traits>
{
public:
typedef typename basic_efilebuf<CharType, Traits>::internal_buffer_type
@@ -207,8 +208,9 @@ public:
};
template <typename CharType, typename Traits = std::char_traits<CharType> >
-class basic_ofstream : public std::basic_ostream<CharType, Traits>,
- public basic_efilebuf<CharType, Traits>
+class basic_ofstream
+ : public std::basic_ostream<CharType, Traits>
+ , public basic_efilebuf<CharType, Traits>
{
using basic_efilebuf<CharType, Traits>::is_open;
@@ -248,7 +250,7 @@ public:
typedef basic_ifstream<char> ifstream;
typedef basic_ofstream<char> ofstream;
-#undef @KWSYS_NAMESPACE@_FStream_NOEXCEPT
+# undef @KWSYS_NAMESPACE@_FStream_NOEXCEPT
#else
using std::ofstream;
using std::ifstream;
diff --git a/Source/kwsys/Glob.cxx b/Source/kwsys/Glob.cxx
index d2f0b8516..34bb0d0fe 100644
--- a/Source/kwsys/Glob.cxx
+++ b/Source/kwsys/Glob.cxx
@@ -12,11 +12,11 @@
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Configure.hxx.in"
-#include "Directory.hxx.in"
-#include "Glob.hxx.in"
-#include "RegularExpression.hxx.in"
-#include "SystemTools.hxx.in"
+# include "Configure.hxx.in"
+# include "Directory.hxx.in"
+# include "Glob.hxx.in"
+# include "RegularExpression.hxx.in"
+# include "SystemTools.hxx.in"
#endif
#include <algorithm>
@@ -28,13 +28,13 @@
#include <string.h>
namespace KWSYS_NAMESPACE {
#if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
-// On Windows and apple, no difference between lower and upper case
-#define KWSYS_GLOB_CASE_INDEPENDENT
+// On Windows and Apple, no difference between lower and upper case
+# define KWSYS_GLOB_CASE_INDEPENDENT
#endif
#if defined(_WIN32) || defined(__CYGWIN__)
// Handle network paths
-#define KWSYS_GLOB_SUPPORT_NETWORK_PATHS
+# define KWSYS_GLOB_SUPPORT_NETWORK_PATHS
#endif
class GlobInternals
@@ -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
@@ -217,9 +217,10 @@ bool Glob::RecurseDirectory(std::string::size_type start,
if (!realPathErrorMessage.empty()) {
if (messages) {
- messages->push_back(Message(
- Glob::error, "Canonical path generation from path '" + dir +
- "' failed! Reason: '" + realPathErrorMessage + "'"));
+ messages->push_back(
+ Message(Glob::error,
+ "Canonical path generation from path '" + dir +
+ "' failed! Reason: '" + realPathErrorMessage + "'"));
}
return false;
}
@@ -262,7 +263,7 @@ bool Glob::RecurseDirectory(std::string::size_type start,
}
} else {
if (!this->Internals->Expressions.empty() &&
- this->Internals->Expressions.rbegin()->find(fname)) {
+ this->Internals->Expressions.back().find(fname)) {
this->AddFile(this->Internals->Files, realname);
}
}
@@ -430,7 +431,7 @@ void Glob::SetRelative(const char* dir)
const char* Glob::GetRelative()
{
if (this->Relative.empty()) {
- return 0;
+ return nullptr;
}
return this->Relative.c_str();
}
diff --git a/Source/kwsys/Glob.hxx.in b/Source/kwsys/Glob.hxx.in
index bd4a17616..170766f4b 100644
--- a/Source/kwsys/Glob.hxx.in
+++ b/Source/kwsys/Glob.hxx.in
@@ -41,17 +41,9 @@ public:
, content(c)
{
}
- Message(const Message& msg)
- : type(msg.type)
- , content(msg.content)
- {
- }
- Message& operator=(Message const& msg)
- {
- this->type = msg.type;
- this->content = msg.content;
- return *this;
- }
+ ~Message() = default;
+ Message(const Message& msg) = default;
+ Message& operator=(Message const& msg) = default;
};
typedef std::vector<Message> GlobMessages;
@@ -62,7 +54,7 @@ public:
~Glob();
//! Find all files that match the pattern.
- bool FindFiles(const std::string& inexpr, GlobMessages* messages = 0);
+ bool FindFiles(const std::string& inexpr, GlobMessages* messages = nullptr);
//! Return the list of files that matched.
std::vector<std::string>& GetFiles();
diff --git a/Source/kwsys/IOStream.cxx b/Source/kwsys/IOStream.cxx
index 01ada1f2f..e21f87d45 100644
--- a/Source/kwsys/IOStream.cxx
+++ b/Source/kwsys/IOStream.cxx
@@ -10,21 +10,21 @@
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Configure.hxx.in"
-#include "IOStream.hxx.in"
+# include "Configure.hxx.in"
+# include "IOStream.hxx.in"
#endif
// Implement the rest of this file only if it is needed.
#if KWSYS_IOS_NEED_OPERATORS_LL
-#include <stdio.h> // sscanf, sprintf
-#include <string.h> // memchr
+# include <stdio.h> // sscanf, sprintf
+# include <string.h> // memchr
-#if defined(_MAX_INT_DIG)
-#define KWSYS_IOS_INT64_MAX_DIG _MAX_INT_DIG
-#else
-#define KWSYS_IOS_INT64_MAX_DIG 32
-#endif
+# if defined(_MAX_INT_DIG)
+# define KWSYS_IOS_INT64_MAX_DIG _MAX_INT_DIG
+# else
+# define KWSYS_IOS_INT64_MAX_DIG 32
+# endif
namespace KWSYS_NAMESPACE {
@@ -118,13 +118,13 @@ std::istream& IOStreamScanTemplate(std::istream& is, T& value, char type)
try {
// Copy the string to a buffer and construct the format string.
char buffer[KWSYS_IOS_INT64_MAX_DIG];
-#if defined(_MSC_VER)
+# if defined(_MSC_VER)
char format[] = "%I64_";
const int typeIndex = 4;
-#else
+# else
char format[] = "%ll_";
const int typeIndex = 3;
-#endif
+# endif
switch (IOStreamScanStream(is, buffer)) {
case 8:
format[typeIndex] = 'o';
@@ -177,14 +177,14 @@ std::ostream& IOStreamPrintTemplate(std::ostream& os, T value, char type)
if (os.flags() & std::ios_base::showbase) {
*f++ = '#';
}
-#if defined(_MSC_VER)
+# if defined(_MSC_VER)
*f++ = 'I';
*f++ = '6';
*f++ = '4';
-#else
+# else
*f++ = 'l';
*f++ = 'l';
-#endif
+# endif
long bflags = os.flags() & std::ios_base::basefield;
if (bflags == std::ios_base::oct) {
*f++ = 'o';
@@ -209,7 +209,7 @@ std::ostream& IOStreamPrintTemplate(std::ostream& os, T value, char type)
return os;
}
-#if !KWSYS_IOS_HAS_ISTREAM_LONG_LONG
+# if !KWSYS_IOS_HAS_ISTREAM_LONG_LONG
// Implement input stream operator for IOStreamSLL.
std::istream& IOStreamScan(std::istream& is, IOStreamSLL& value)
{
@@ -221,9 +221,9 @@ std::istream& IOStreamScan(std::istream& is, IOStreamULL& value)
{
return IOStreamScanTemplate(is, value, 'u');
}
-#endif
+# endif
-#if !KWSYS_IOS_HAS_OSTREAM_LONG_LONG
+# if !KWSYS_IOS_HAS_OSTREAM_LONG_LONG
// Implement output stream operator for IOStreamSLL.
std::ostream& IOStreamPrint(std::ostream& os, IOStreamSLL value)
{
@@ -235,7 +235,7 @@ std::ostream& IOStreamPrint(std::ostream& os, IOStreamULL value)
{
return IOStreamPrintTemplate(os, value, 'u');
}
-#endif
+# endif
} // namespace KWSYS_NAMESPACE
diff --git a/Source/kwsys/IOStream.hxx.in b/Source/kwsys/IOStream.hxx.in
index de3a2e634..db8a23ef5 100644
--- a/Source/kwsys/IOStream.hxx.in
+++ b/Source/kwsys/IOStream.hxx.in
@@ -7,7 +7,7 @@
/* Define these macros temporarily to keep the code readable. */
#if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
/* Whether istream supports long long. */
@@ -21,27 +21,27 @@
/* Determine whether we need to define the streaming operators for
long long or __int64. */
#if @KWSYS_USE_LONG_LONG@
-#if !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG || \
- !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG
-#define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 1
+# if !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG || \
+ !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG
+# define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 1
namespace @KWSYS_NAMESPACE@ {
typedef long long IOStreamSLL;
typedef unsigned long long IOStreamULL;
}
-#endif
+# endif
#elif defined(_MSC_VER) && _MSC_VER < 1300
-#define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 1
+# define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 1
namespace @KWSYS_NAMESPACE@ {
typedef __int64 IOStreamSLL;
typedef unsigned __int64 IOStreamULL;
}
#endif
#if !defined(@KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL)
-#define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 0
+# define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 0
#endif
#if @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL
-#if !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG
+# if !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG
/* Input stream operator implementation functions. */
namespace @KWSYS_NAMESPACE@ {
@@ -50,31 +50,31 @@ kwsysEXPORT std::istream& IOStreamScan(std::istream&, IOStreamULL&);
}
/* Provide input stream operator for long long. */
-#if !defined(@KWSYS_NAMESPACE@_IOS_NO_ISTREAM_LONG_LONG) && \
- !defined(KWSYS_IOS_ISTREAM_LONG_LONG_DEFINED)
-#define KWSYS_IOS_ISTREAM_LONG_LONG_DEFINED
-#define @KWSYS_NAMESPACE@_IOS_ISTREAM_LONG_LONG_DEFINED
+# if !defined(@KWSYS_NAMESPACE@_IOS_NO_ISTREAM_LONG_LONG) && \
+ !defined(KWSYS_IOS_ISTREAM_LONG_LONG_DEFINED)
+# define KWSYS_IOS_ISTREAM_LONG_LONG_DEFINED
+# define @KWSYS_NAMESPACE@_IOS_ISTREAM_LONG_LONG_DEFINED
inline std::istream& operator>>(std::istream& is,
@KWSYS_NAMESPACE@::IOStreamSLL& value)
{
return @KWSYS_NAMESPACE@::IOStreamScan(is, value);
}
-#endif
+# endif
/* Provide input stream operator for unsigned long long. */
-#if !defined(@KWSYS_NAMESPACE@_IOS_NO_ISTREAM_UNSIGNED_LONG_LONG) && \
- !defined(KWSYS_IOS_ISTREAM_UNSIGNED_LONG_LONG_DEFINED)
-#define KWSYS_IOS_ISTREAM_UNSIGNED_LONG_LONG_DEFINED
-#define @KWSYS_NAMESPACE@_IOS_ISTREAM_UNSIGNED_LONG_LONG_DEFINED
+# if !defined(@KWSYS_NAMESPACE@_IOS_NO_ISTREAM_UNSIGNED_LONG_LONG) && \
+ !defined(KWSYS_IOS_ISTREAM_UNSIGNED_LONG_LONG_DEFINED)
+# define KWSYS_IOS_ISTREAM_UNSIGNED_LONG_LONG_DEFINED
+# define @KWSYS_NAMESPACE@_IOS_ISTREAM_UNSIGNED_LONG_LONG_DEFINED
inline std::istream& operator>>(std::istream& is,
@KWSYS_NAMESPACE@::IOStreamULL& value)
{
return @KWSYS_NAMESPACE@::IOStreamScan(is, value);
}
-#endif
-#endif /* !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG */
+# endif
+# endif /* !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG */
-#if !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG
+# if !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG
/* Output stream operator implementation functions. */
namespace @KWSYS_NAMESPACE@ {
@@ -83,44 +83,44 @@ kwsysEXPORT std::ostream& IOStreamPrint(std::ostream&, IOStreamULL);
}
/* Provide output stream operator for long long. */
-#if !defined(@KWSYS_NAMESPACE@_IOS_NO_OSTREAM_LONG_LONG) && \
- !defined(KWSYS_IOS_OSTREAM_LONG_LONG_DEFINED)
-#define KWSYS_IOS_OSTREAM_LONG_LONG_DEFINED
-#define @KWSYS_NAMESPACE@_IOS_OSTREAM_LONG_LONG_DEFINED
+# if !defined(@KWSYS_NAMESPACE@_IOS_NO_OSTREAM_LONG_LONG) && \
+ !defined(KWSYS_IOS_OSTREAM_LONG_LONG_DEFINED)
+# define KWSYS_IOS_OSTREAM_LONG_LONG_DEFINED
+# define @KWSYS_NAMESPACE@_IOS_OSTREAM_LONG_LONG_DEFINED
inline std::ostream& operator<<(std::ostream& os,
@KWSYS_NAMESPACE@::IOStreamSLL value)
{
return @KWSYS_NAMESPACE@::IOStreamPrint(os, value);
}
-#endif
+# endif
/* Provide output stream operator for unsigned long long. */
-#if !defined(@KWSYS_NAMESPACE@_IOS_NO_OSTREAM_UNSIGNED_LONG_LONG) && \
- !defined(KWSYS_IOS_OSTREAM_UNSIGNED_LONG_LONG_DEFINED)
-#define KWSYS_IOS_OSTREAM_UNSIGNED_LONG_LONG_DEFINED
-#define @KWSYS_NAMESPACE@_IOS_OSTREAM_UNSIGNED_LONG_LONG_DEFINED
+# if !defined(@KWSYS_NAMESPACE@_IOS_NO_OSTREAM_UNSIGNED_LONG_LONG) && \
+ !defined(KWSYS_IOS_OSTREAM_UNSIGNED_LONG_LONG_DEFINED)
+# define KWSYS_IOS_OSTREAM_UNSIGNED_LONG_LONG_DEFINED
+# define @KWSYS_NAMESPACE@_IOS_OSTREAM_UNSIGNED_LONG_LONG_DEFINED
inline std::ostream& operator<<(std::ostream& os,
@KWSYS_NAMESPACE@::IOStreamULL value)
{
return @KWSYS_NAMESPACE@::IOStreamPrint(os, value);
}
-#endif
-#endif /* !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG */
-#endif /* @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL */
+# endif
+# endif /* !@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG */
+#endif /* @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL */
/* Undefine temporary macros. */
#if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#undef kwsysEXPORT
+# undef kwsysEXPORT
#endif
/* If building a C++ file in kwsys itself, give the source file
access to the macros without a configured namespace. */
#if defined(KWSYS_NAMESPACE)
-#define KWSYS_IOS_HAS_ISTREAM_LONG_LONG \
- @KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG
-#define KWSYS_IOS_HAS_OSTREAM_LONG_LONG \
- @KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG
-#define KWSYS_IOS_NEED_OPERATORS_LL @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL
+# define KWSYS_IOS_HAS_ISTREAM_LONG_LONG \
+ @KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG
+# define KWSYS_IOS_HAS_OSTREAM_LONG_LONG \
+ @KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG
+# define KWSYS_IOS_NEED_OPERATORS_LL @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL
#endif
#endif
diff --git a/Source/kwsys/MD5.c b/Source/kwsys/MD5.c
index 3188fb67a..97cf9ba68 100644
--- a/Source/kwsys/MD5.c
+++ b/Source/kwsys/MD5.c
@@ -6,7 +6,7 @@
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "MD5.h.in"
+# include "MD5.h.in"
#endif
#include <stddef.h> /* size_t */
@@ -19,8 +19,8 @@
implementation file. */
#if defined(__clang__) && !defined(__INTEL_COMPILER)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wcast-align"
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wcast-align"
#endif
/*
@@ -98,9 +98,9 @@ typedef struct md5_state_s
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
#ifdef ARCH_IS_BIG_ENDIAN
-#define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
#else
-#define BYTE_ORDER 0
+# define BYTE_ORDER 0
#endif
#define T_MASK ((md5_word_t)~0)
@@ -222,11 +222,11 @@ static void md5_process(md5_state_t* pms, const md5_byte_t* data /*[64]*/)
const md5_byte_t* xp = data;
int i;
-#if BYTE_ORDER == 0
+# if BYTE_ORDER == 0
X = xbuf; /* (dynamic only) */
-#else
-#define xbuf X /* (static only) */
-#endif
+# else
+# define xbuf X /* (static only) */
+# endif
for (i = 0; i < 16; ++i, xp += 4)
xbuf[i] =
(md5_word_t)(xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24));
@@ -420,7 +420,7 @@ static void md5_finish(md5_state_t* pms, md5_byte_t digest[16])
}
#if defined(__clang__) && !defined(__INTEL_COMPILER)
-#pragma clang diagnostic pop
+# pragma clang diagnostic pop
#endif
/* Wrap up the MD5 state in our opaque structure. */
diff --git a/Source/kwsys/MD5.h.in b/Source/kwsys/MD5.h.in
index c257f7f9a..7646f1297 100644
--- a/Source/kwsys/MD5.h.in
+++ b/Source/kwsys/MD5.h.in
@@ -10,19 +10,19 @@
not visible to user code. Use kwsysHeaderDump.pl to reproduce
these macros after making changes to the interface. */
#if !defined(KWSYS_NAMESPACE)
-#define kwsys_ns(x) @KWSYS_NAMESPACE@##x
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsysMD5 kwsys_ns(MD5)
-#define kwsysMD5_s kwsys_ns(MD5_s)
-#define kwsysMD5_New kwsys_ns(MD5_New)
-#define kwsysMD5_Delete kwsys_ns(MD5_Delete)
-#define kwsysMD5_Initialize kwsys_ns(MD5_Initialize)
-#define kwsysMD5_Append kwsys_ns(MD5_Append)
-#define kwsysMD5_Finalize kwsys_ns(MD5_Finalize)
-#define kwsysMD5_FinalizeHex kwsys_ns(MD5_FinalizeHex)
-#define kwsysMD5_DigestToHex kwsys_ns(MD5_DigestToHex)
+# define kwsysMD5 kwsys_ns(MD5)
+# define kwsysMD5_s kwsys_ns(MD5_s)
+# define kwsysMD5_New kwsys_ns(MD5_New)
+# define kwsysMD5_Delete kwsys_ns(MD5_Delete)
+# define kwsysMD5_Initialize kwsys_ns(MD5_Initialize)
+# define kwsysMD5_Append kwsys_ns(MD5_Append)
+# define kwsysMD5_Finalize kwsys_ns(MD5_Finalize)
+# define kwsysMD5_FinalizeHex kwsys_ns(MD5_FinalizeHex)
+# define kwsysMD5_DigestToHex kwsys_ns(MD5_DigestToHex)
#endif
#if defined(__cplusplus)
@@ -79,19 +79,19 @@ kwsysEXPORT void kwsysMD5_DigestToHex(unsigned char const digest[16],
/* If we are building a kwsys .c or .cxx file, let it use these macros.
Otherwise, undefine them to keep the namespace clean. */
#if !defined(KWSYS_NAMESPACE)
-#undef kwsys_ns
-#undef kwsysEXPORT
-#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#undef kwsysMD5
-#undef kwsysMD5_s
-#undef kwsysMD5_New
-#undef kwsysMD5_Delete
-#undef kwsysMD5_Initialize
-#undef kwsysMD5_Append
-#undef kwsysMD5_Finalize
-#undef kwsysMD5_FinalizeHex
-#undef kwsysMD5_DigestToHex
-#endif
+# undef kwsys_ns
+# undef kwsysEXPORT
+# if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# undef kwsysMD5
+# undef kwsysMD5_s
+# undef kwsysMD5_New
+# undef kwsysMD5_Delete
+# undef kwsysMD5_Initialize
+# undef kwsysMD5_Append
+# undef kwsysMD5_Finalize
+# undef kwsysMD5_FinalizeHex
+# undef kwsysMD5_DigestToHex
+# endif
#endif
#endif
diff --git a/Source/kwsys/Process.h.in b/Source/kwsys/Process.h.in
index 237001c60..73ea9dbfc 100644
--- a/Source/kwsys/Process.h.in
+++ b/Source/kwsys/Process.h.in
@@ -10,74 +10,79 @@
not visible to user code. Use kwsysHeaderDump.pl to reproduce
these macros after making changes to the interface. */
#if !defined(KWSYS_NAMESPACE)
-#define kwsys_ns(x) @KWSYS_NAMESPACE@##x
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsysProcess kwsys_ns(Process)
-#define kwsysProcess_s kwsys_ns(Process_s)
-#define kwsysProcess_New kwsys_ns(Process_New)
-#define kwsysProcess_Delete kwsys_ns(Process_Delete)
-#define kwsysProcess_SetCommand kwsys_ns(Process_SetCommand)
-#define kwsysProcess_AddCommand kwsys_ns(Process_AddCommand)
-#define kwsysProcess_SetTimeout kwsys_ns(Process_SetTimeout)
-#define kwsysProcess_SetWorkingDirectory kwsys_ns(Process_SetWorkingDirectory)
-#define kwsysProcess_SetPipeFile kwsys_ns(Process_SetPipeFile)
-#define kwsysProcess_SetPipeNative kwsys_ns(Process_SetPipeNative)
-#define kwsysProcess_SetPipeShared kwsys_ns(Process_SetPipeShared)
-#define kwsysProcess_Option_Detach kwsys_ns(Process_Option_Detach)
-#define kwsysProcess_Option_HideWindow kwsys_ns(Process_Option_HideWindow)
-#define kwsysProcess_Option_MergeOutput kwsys_ns(Process_Option_MergeOutput)
-#define kwsysProcess_Option_Verbatim kwsys_ns(Process_Option_Verbatim)
-#define kwsysProcess_Option_CreateProcessGroup \
- kwsys_ns(Process_Option_CreateProcessGroup)
-#define kwsysProcess_GetOption kwsys_ns(Process_GetOption)
-#define kwsysProcess_SetOption kwsys_ns(Process_SetOption)
-#define kwsysProcess_Option_e kwsys_ns(Process_Option_e)
-#define kwsysProcess_State_Starting kwsys_ns(Process_State_Starting)
-#define kwsysProcess_State_Error kwsys_ns(Process_State_Error)
-#define kwsysProcess_State_Exception kwsys_ns(Process_State_Exception)
-#define kwsysProcess_State_Executing kwsys_ns(Process_State_Executing)
-#define kwsysProcess_State_Exited kwsys_ns(Process_State_Exited)
-#define kwsysProcess_State_Expired kwsys_ns(Process_State_Expired)
-#define kwsysProcess_State_Killed kwsys_ns(Process_State_Killed)
-#define kwsysProcess_State_Disowned kwsys_ns(Process_State_Disowned)
-#define kwsysProcess_State_e kwsys_ns(Process_State_e)
-#define kwsysProcess_Exception_None kwsys_ns(Process_Exception_None)
-#define kwsysProcess_Exception_Fault kwsys_ns(Process_Exception_Fault)
-#define kwsysProcess_Exception_Illegal kwsys_ns(Process_Exception_Illegal)
-#define kwsysProcess_Exception_Interrupt kwsys_ns(Process_Exception_Interrupt)
-#define kwsysProcess_Exception_Numerical kwsys_ns(Process_Exception_Numerical)
-#define kwsysProcess_Exception_Other kwsys_ns(Process_Exception_Other)
-#define kwsysProcess_Exception_e kwsys_ns(Process_Exception_e)
-#define kwsysProcess_GetState kwsys_ns(Process_GetState)
-#define kwsysProcess_GetExitException kwsys_ns(Process_GetExitException)
-#define kwsysProcess_GetExitCode kwsys_ns(Process_GetExitCode)
-#define kwsysProcess_GetExitValue kwsys_ns(Process_GetExitValue)
-#define kwsysProcess_GetErrorString kwsys_ns(Process_GetErrorString)
-#define kwsysProcess_GetExceptionString kwsys_ns(Process_GetExceptionString)
-#define kwsysProcess_GetStateByIndex kwsys_ns(Process_GetStateByIndex)
-#define kwsysProcess_GetExitExceptionByIndex \
- kwsys_ns(Process_GetExitExceptionByIndex)
-#define kwsysProcess_GetExitCodeByIndex kwsys_ns(Process_GetExitCodeByIndex)
-#define kwsysProcess_GetExitValueByIndex kwsys_ns(Process_GetExitValueByIndex)
-#define kwsysProcess_GetExceptionStringByIndex \
- kwsys_ns(Process_GetExceptionStringByIndex)
-#define kwsysProcess_GetExitCodeByIndex kwsys_ns(Process_GetExitCodeByIndex)
-#define kwsysProcess_Execute kwsys_ns(Process_Execute)
-#define kwsysProcess_Disown kwsys_ns(Process_Disown)
-#define kwsysProcess_WaitForData kwsys_ns(Process_WaitForData)
-#define kwsysProcess_Pipes_e kwsys_ns(Process_Pipes_e)
-#define kwsysProcess_Pipe_None kwsys_ns(Process_Pipe_None)
-#define kwsysProcess_Pipe_STDIN kwsys_ns(Process_Pipe_STDIN)
-#define kwsysProcess_Pipe_STDOUT kwsys_ns(Process_Pipe_STDOUT)
-#define kwsysProcess_Pipe_STDERR kwsys_ns(Process_Pipe_STDERR)
-#define kwsysProcess_Pipe_Timeout kwsys_ns(Process_Pipe_Timeout)
-#define kwsysProcess_Pipe_Handle kwsys_ns(Process_Pipe_Handle)
-#define kwsysProcess_WaitForExit kwsys_ns(Process_WaitForExit)
-#define kwsysProcess_Interrupt kwsys_ns(Process_Interrupt)
-#define kwsysProcess_Kill kwsys_ns(Process_Kill)
-#define kwsysProcess_ResetStartTime kwsys_ns(Process_ResetStartTime)
+# define kwsysProcess kwsys_ns(Process)
+# define kwsysProcess_s kwsys_ns(Process_s)
+# define kwsysProcess_New kwsys_ns(Process_New)
+# define kwsysProcess_Delete kwsys_ns(Process_Delete)
+# define kwsysProcess_SetCommand kwsys_ns(Process_SetCommand)
+# define kwsysProcess_AddCommand kwsys_ns(Process_AddCommand)
+# define kwsysProcess_SetTimeout kwsys_ns(Process_SetTimeout)
+# define kwsysProcess_SetWorkingDirectory \
+ kwsys_ns(Process_SetWorkingDirectory)
+# define kwsysProcess_SetPipeFile kwsys_ns(Process_SetPipeFile)
+# define kwsysProcess_SetPipeNative kwsys_ns(Process_SetPipeNative)
+# define kwsysProcess_SetPipeShared kwsys_ns(Process_SetPipeShared)
+# define kwsysProcess_Option_Detach kwsys_ns(Process_Option_Detach)
+# define kwsysProcess_Option_HideWindow kwsys_ns(Process_Option_HideWindow)
+# define kwsysProcess_Option_MergeOutput kwsys_ns(Process_Option_MergeOutput)
+# define kwsysProcess_Option_Verbatim kwsys_ns(Process_Option_Verbatim)
+# define kwsysProcess_Option_CreateProcessGroup \
+ kwsys_ns(Process_Option_CreateProcessGroup)
+# define kwsysProcess_GetOption kwsys_ns(Process_GetOption)
+# define kwsysProcess_SetOption kwsys_ns(Process_SetOption)
+# define kwsysProcess_Option_e kwsys_ns(Process_Option_e)
+# define kwsysProcess_State_Starting kwsys_ns(Process_State_Starting)
+# define kwsysProcess_State_Error kwsys_ns(Process_State_Error)
+# define kwsysProcess_State_Exception kwsys_ns(Process_State_Exception)
+# define kwsysProcess_State_Executing kwsys_ns(Process_State_Executing)
+# define kwsysProcess_State_Exited kwsys_ns(Process_State_Exited)
+# define kwsysProcess_State_Expired kwsys_ns(Process_State_Expired)
+# define kwsysProcess_State_Killed kwsys_ns(Process_State_Killed)
+# define kwsysProcess_State_Disowned kwsys_ns(Process_State_Disowned)
+# define kwsysProcess_State_e kwsys_ns(Process_State_e)
+# define kwsysProcess_Exception_None kwsys_ns(Process_Exception_None)
+# define kwsysProcess_Exception_Fault kwsys_ns(Process_Exception_Fault)
+# define kwsysProcess_Exception_Illegal kwsys_ns(Process_Exception_Illegal)
+# define kwsysProcess_Exception_Interrupt \
+ kwsys_ns(Process_Exception_Interrupt)
+# define kwsysProcess_Exception_Numerical \
+ kwsys_ns(Process_Exception_Numerical)
+# define kwsysProcess_Exception_Other kwsys_ns(Process_Exception_Other)
+# define kwsysProcess_Exception_e kwsys_ns(Process_Exception_e)
+# define kwsysProcess_GetState kwsys_ns(Process_GetState)
+# define kwsysProcess_GetExitException kwsys_ns(Process_GetExitException)
+# define kwsysProcess_GetExitCode kwsys_ns(Process_GetExitCode)
+# define kwsysProcess_GetExitValue kwsys_ns(Process_GetExitValue)
+# define kwsysProcess_GetErrorString kwsys_ns(Process_GetErrorString)
+# define kwsysProcess_GetExceptionString kwsys_ns(Process_GetExceptionString)
+# define kwsysProcess_GetStateByIndex kwsys_ns(Process_GetStateByIndex)
+# define kwsysProcess_GetExitExceptionByIndex \
+ kwsys_ns(Process_GetExitExceptionByIndex)
+# define kwsysProcess_GetExitCodeByIndex kwsys_ns(Process_GetExitCodeByIndex)
+# define kwsysProcess_GetExitValueByIndex \
+ kwsys_ns(Process_GetExitValueByIndex)
+# define kwsysProcess_GetExceptionStringByIndex \
+ kwsys_ns(Process_GetExceptionStringByIndex)
+# define kwsysProcess_GetExitCodeByIndex kwsys_ns(Process_GetExitCodeByIndex)
+# define kwsysProcess_Execute kwsys_ns(Process_Execute)
+# define kwsysProcess_Disown kwsys_ns(Process_Disown)
+# define kwsysProcess_WaitForData kwsys_ns(Process_WaitForData)
+# define kwsysProcess_Pipes_e kwsys_ns(Process_Pipes_e)
+# define kwsysProcess_Pipe_None kwsys_ns(Process_Pipe_None)
+# define kwsysProcess_Pipe_STDIN kwsys_ns(Process_Pipe_STDIN)
+# define kwsysProcess_Pipe_STDOUT kwsys_ns(Process_Pipe_STDOUT)
+# define kwsysProcess_Pipe_STDERR kwsys_ns(Process_Pipe_STDERR)
+# define kwsysProcess_Pipe_Timeout kwsys_ns(Process_Pipe_Timeout)
+# define kwsysProcess_Pipe_Handle kwsys_ns(Process_Pipe_Handle)
+# 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
#if defined(__cplusplus)
@@ -306,13 +311,13 @@ kwsysEXPORT const char* kwsysProcess_GetErrorString(kwsysProcess* cp);
kwsysEXPORT const char* kwsysProcess_GetExceptionString(kwsysProcess* cp);
/**
-* Get the current state of the Process instance. Possible states are:
-*
-* kwsysProcess_StateByIndex_Starting = Execute has not yet been called.
-* kwsysProcess_StateByIndex_Exception = Child process exited abnormally.
-* kwsysProcess_StateByIndex_Exited = Child process exited normally.
-* kwsysProcess_StateByIndex_Error = Error getting the child return code.
-*/
+ * Get the current state of the Process instance. Possible states are:
+ *
+ * kwsysProcess_StateByIndex_Starting = Execute has not yet been called.
+ * kwsysProcess_StateByIndex_Exception = Child process exited abnormally.
+ * kwsysProcess_StateByIndex_Exited = Child process exited normally.
+ * kwsysProcess_StateByIndex_Error = Error getting the child return code.
+ */
kwsysEXPORT int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx);
enum kwsysProcess_StateByIndex_e
{
@@ -323,46 +328,46 @@ enum kwsysProcess_StateByIndex_e
};
/**
-* When GetState returns "Exception", this method returns a
-* platform-independent description of the exceptional behavior that
-* caused the child to terminate abnormally. Possible exceptions are:
-*
-* kwsysProcess_Exception_None = No exceptional behavior occurred.
-* kwsysProcess_Exception_Fault = Child crashed with a memory fault.
-* kwsysProcess_Exception_Illegal = Child crashed with an illegal
-* instruction.
-* kwsysProcess_Exception_Interrupt = Child was interrupted by user
-* (Cntl-C/Break).
-* kwsysProcess_Exception_Numerical = Child crashed with a numerical
-* exception.
-* kwsysProcess_Exception_Other = Child terminated for another reason.
-*/
+ * When GetState returns "Exception", this method returns a
+ * platform-independent description of the exceptional behavior that
+ * caused the child to terminate abnormally. Possible exceptions are:
+ *
+ * kwsysProcess_Exception_None = No exceptional behavior occurred.
+ * kwsysProcess_Exception_Fault = Child crashed with a memory fault.
+ * kwsysProcess_Exception_Illegal = Child crashed with an illegal
+ * instruction.
+ * kwsysProcess_Exception_Interrupt = Child was interrupted by user
+ * (Cntl-C/Break).
+ * kwsysProcess_Exception_Numerical = Child crashed with a numerical
+ * exception.
+ * kwsysProcess_Exception_Other = Child terminated for another reason.
+ */
kwsysEXPORT int kwsysProcess_GetExitExceptionByIndex(kwsysProcess* cp,
int idx);
/**
-* When GetState returns "Exited" or "Exception", this method returns
-* the platform-specific raw exit code of the process. UNIX platforms
-* should use WIFEXITED/WEXITSTATUS and WIFSIGNALED/WTERMSIG to access
-* this value. Windows users should compare the value to the various
-* EXCEPTION_* values.
-*
-* If GetState returns "Exited", use GetExitValue to get the
-* platform-independent child return value.
-*/
+ * When GetState returns "Exited" or "Exception", this method returns
+ * the platform-specific raw exit code of the process. UNIX platforms
+ * should use WIFEXITED/WEXITSTATUS and WIFSIGNALED/WTERMSIG to access
+ * this value. Windows users should compare the value to the various
+ * EXCEPTION_* values.
+ *
+ * If GetState returns "Exited", use GetExitValue to get the
+ * platform-independent child return value.
+ */
kwsysEXPORT int kwsysProcess_GetExitCodeByIndex(kwsysProcess* cp, int idx);
/**
-* When GetState returns "Exited", this method returns the child's
-* platform-independent exit code (such as the value returned by the
-* child's main).
-*/
+ * When GetState returns "Exited", this method returns the child's
+ * platform-independent exit code (such as the value returned by the
+ * child's main).
+ */
kwsysEXPORT int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx);
/**
-* When GetState returns "Exception", this method returns a string
-* describing the problem. Otherwise, it returns NULL.
-*/
+ * When GetState returns "Exception", this method returns a string
+ * describing the problem. Otherwise, it returns NULL.
+ */
kwsysEXPORT const char* kwsysProcess_GetExceptionStringByIndex(
kwsysProcess* cp, int idx);
@@ -420,7 +425,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 +462,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);
@@ -468,65 +480,65 @@ kwsysEXPORT void kwsysProcess_ResetStartTime(kwsysProcess* cp);
/* If we are building a kwsys .c or .cxx file, let it use these macros.
Otherwise, undefine them to keep the namespace clean. */
#if !defined(KWSYS_NAMESPACE)
-#undef kwsys_ns
-#undef kwsysEXPORT
-#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#undef kwsysProcess
-#undef kwsysProcess_s
-#undef kwsysProcess_New
-#undef kwsysProcess_Delete
-#undef kwsysProcess_SetCommand
-#undef kwsysProcess_AddCommand
-#undef kwsysProcess_SetTimeout
-#undef kwsysProcess_SetWorkingDirectory
-#undef kwsysProcess_SetPipeFile
-#undef kwsysProcess_SetPipeNative
-#undef kwsysProcess_SetPipeShared
-#undef kwsysProcess_Option_Detach
-#undef kwsysProcess_Option_HideWindow
-#undef kwsysProcess_Option_MergeOutput
-#undef kwsysProcess_Option_Verbatim
-#undef kwsysProcess_Option_CreateProcessGroup
-#undef kwsysProcess_GetOption
-#undef kwsysProcess_SetOption
-#undef kwsysProcess_Option_e
-#undef kwsysProcess_State_Starting
-#undef kwsysProcess_State_Error
-#undef kwsysProcess_State_Exception
-#undef kwsysProcess_State_Executing
-#undef kwsysProcess_State_Exited
-#undef kwsysProcess_State_Expired
-#undef kwsysProcess_State_Killed
-#undef kwsysProcess_State_Disowned
-#undef kwsysProcess_GetState
-#undef kwsysProcess_State_e
-#undef kwsysProcess_Exception_None
-#undef kwsysProcess_Exception_Fault
-#undef kwsysProcess_Exception_Illegal
-#undef kwsysProcess_Exception_Interrupt
-#undef kwsysProcess_Exception_Numerical
-#undef kwsysProcess_Exception_Other
-#undef kwsysProcess_GetExitException
-#undef kwsysProcess_Exception_e
-#undef kwsysProcess_GetExitCode
-#undef kwsysProcess_GetExitValue
-#undef kwsysProcess_GetErrorString
-#undef kwsysProcess_GetExceptionString
-#undef kwsysProcess_Execute
-#undef kwsysProcess_Disown
-#undef kwsysProcess_WaitForData
-#undef kwsysProcess_Pipes_e
-#undef kwsysProcess_Pipe_None
-#undef kwsysProcess_Pipe_STDIN
-#undef kwsysProcess_Pipe_STDOUT
-#undef kwsysProcess_Pipe_STDERR
-#undef kwsysProcess_Pipe_Timeout
-#undef kwsysProcess_Pipe_Handle
-#undef kwsysProcess_WaitForExit
-#undef kwsysProcess_Interrupt
-#undef kwsysProcess_Kill
-#undef kwsysProcess_ResetStartTime
-#endif
+# undef kwsys_ns
+# undef kwsysEXPORT
+# if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# undef kwsysProcess
+# undef kwsysProcess_s
+# undef kwsysProcess_New
+# undef kwsysProcess_Delete
+# undef kwsysProcess_SetCommand
+# undef kwsysProcess_AddCommand
+# undef kwsysProcess_SetTimeout
+# undef kwsysProcess_SetWorkingDirectory
+# undef kwsysProcess_SetPipeFile
+# undef kwsysProcess_SetPipeNative
+# undef kwsysProcess_SetPipeShared
+# undef kwsysProcess_Option_Detach
+# undef kwsysProcess_Option_HideWindow
+# undef kwsysProcess_Option_MergeOutput
+# undef kwsysProcess_Option_Verbatim
+# undef kwsysProcess_Option_CreateProcessGroup
+# undef kwsysProcess_GetOption
+# undef kwsysProcess_SetOption
+# undef kwsysProcess_Option_e
+# undef kwsysProcess_State_Starting
+# undef kwsysProcess_State_Error
+# undef kwsysProcess_State_Exception
+# undef kwsysProcess_State_Executing
+# undef kwsysProcess_State_Exited
+# undef kwsysProcess_State_Expired
+# undef kwsysProcess_State_Killed
+# undef kwsysProcess_State_Disowned
+# undef kwsysProcess_GetState
+# undef kwsysProcess_State_e
+# undef kwsysProcess_Exception_None
+# undef kwsysProcess_Exception_Fault
+# undef kwsysProcess_Exception_Illegal
+# undef kwsysProcess_Exception_Interrupt
+# undef kwsysProcess_Exception_Numerical
+# undef kwsysProcess_Exception_Other
+# undef kwsysProcess_GetExitException
+# undef kwsysProcess_Exception_e
+# undef kwsysProcess_GetExitCode
+# undef kwsysProcess_GetExitValue
+# undef kwsysProcess_GetErrorString
+# undef kwsysProcess_GetExceptionString
+# undef kwsysProcess_Execute
+# undef kwsysProcess_Disown
+# undef kwsysProcess_WaitForData
+# undef kwsysProcess_Pipes_e
+# undef kwsysProcess_Pipe_None
+# undef kwsysProcess_Pipe_STDIN
+# undef kwsysProcess_Pipe_STDOUT
+# undef kwsysProcess_Pipe_STDERR
+# undef kwsysProcess_Pipe_Timeout
+# undef kwsysProcess_Pipe_Handle
+# undef kwsysProcess_WaitForExit
+# undef kwsysProcess_Interrupt
+# undef kwsysProcess_Kill
+# undef kwsysProcess_ResetStartTime
+# endif
#endif
#endif
diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c
index 9ebcfce59..f65690b31 100644
--- a/Source/kwsys/ProcessUNIX.c
+++ b/Source/kwsys/ProcessUNIX.c
@@ -7,8 +7,8 @@
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "Process.h.in"
-#include "System.h.in"
+# include "Process.h.in"
+# include "System.h.in"
#endif
/*
@@ -40,7 +40,7 @@ do.
#if defined(__CYGWIN__)
/* Increase the file descriptor limit for select() before including
related system headers. (Default: 64) */
-#define FD_SETSIZE 16384
+# define FD_SETSIZE 16384
#endif
#include <assert.h> /* assert */
@@ -61,9 +61,9 @@ do.
#include <unistd.h> /* pipe, close, fork, execvp, select, _exit */
#if defined(__VMS)
-#define KWSYSPE_VMS_NONBLOCK , O_NONBLOCK
+# define KWSYSPE_VMS_NONBLOCK , O_NONBLOCK
#else
-#define KWSYSPE_VMS_NONBLOCK
+# define KWSYSPE_VMS_NONBLOCK
#endif
#if defined(KWSYS_C_HAS_PTRDIFF_T) && KWSYS_C_HAS_PTRDIFF_T
@@ -80,13 +80,13 @@ typedef int kwsysProcess_ssize_t;
#if defined(__BEOS__) && !defined(__ZETA__)
/* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */
-#include <be/kernel/OS.h>
+# include <be/kernel/OS.h>
static inline void kwsysProcess_usleep(unsigned int msec)
{
snooze(msec);
}
#else
-#define kwsysProcess_usleep usleep
+# define kwsysProcess_usleep usleep
#endif
/*
@@ -99,13 +99,14 @@ static inline void kwsysProcess_usleep(unsigned int msec)
* pipes' file handles to be non-blocking and just poll them directly
* without select().
*/
-#if !defined(__BEOS__) && !defined(__VMS) && !defined(__MINT__)
-#define KWSYSPE_USE_SELECT 1
+#if !defined(__BEOS__) && !defined(__VMS) && !defined(__MINT__) && \
+ !defined(KWSYSPE_USE_SELECT)
+# define KWSYSPE_USE_SELECT 1
#endif
/* Some platforms do not have siginfo on their signal handlers. */
#if defined(SA_SIGINFO) && !defined(__BEOS__)
-#define KWSYSPE_USE_SIGINFO 1
+# define KWSYSPE_USE_SIGINFO 1
#endif
/* The number of pipes for the child's output. The standard stdout
@@ -230,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. */
@@ -358,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);
}
@@ -497,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;
}
@@ -530,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
@@ -1165,7 +1162,7 @@ static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length,
case KWSYSPE_PIPE_STDERR:
wd->PipeId = kwsysProcess_Pipe_STDERR;
break;
- };
+ }
return 1;
}
} else if (n < 0 && errno == EAGAIN) {
@@ -1269,21 +1266,21 @@ static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length,
} else if (n == 0) /* EOF */
{
/* We are done reading from this pipe. */
-#if defined(__VMS)
+# if defined(__VMS)
if (!cp->CommandsLeft)
-#endif
+# endif
{
kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]);
--cp->PipesLeft;
}
} else if (n < 0) /* error */
{
-#if defined(__VMS)
+# if defined(__VMS)
if (!cp->CommandsLeft) {
kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]);
--cp->PipesLeft;
} else
-#endif
+# endif
if ((errno != EINTR) && (errno != EAGAIN)) {
strncpy(cp->ErrorMessage, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE);
/* Kill the children now. */
@@ -1474,12 +1471,12 @@ static void kwsysProcessVolatileFree(volatile void* p)
/* clang has made it impossible to free memory that points to volatile
without first using special pragmas to disable a warning... */
#if defined(__clang__) && !defined(__INTEL_COMPILER)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wcast-qual"
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wcast-qual"
#endif
free((void*)p); /* The cast will silence most compilers, but not clang. */
#if defined(__clang__) && !defined(__INTEL_COMPILER)
-#pragma clang diagnostic pop
+# pragma clang diagnostic pop
#endif
}
@@ -1513,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;
}
@@ -1523,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) {
@@ -1937,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;
}
@@ -2032,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;
@@ -2096,11 +2098,11 @@ static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig,
break;
#endif
#ifdef SIGBUS
-#if !defined(SIGSEGV) || SIGBUS != SIGSEGV
+# if !defined(SIGSEGV) || SIGBUS != SIGSEGV
case SIGBUS:
KWSYSPE_CASE(Fault, "Bus error");
break;
-#endif
+# endif
#endif
#ifdef SIGFPE
case SIGFPE:
@@ -2148,11 +2150,11 @@ static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig,
break;
#endif
#ifdef SIGIOT
-#if !defined(SIGABRT) || SIGIOT != SIGABRT
+# if !defined(SIGABRT) || SIGIOT != SIGABRT
case SIGIOT:
KWSYSPE_CASE(Other, "SIGIOT");
break;
-#endif
+# endif
#endif
#ifdef SIGUSR1
case SIGUSR1:
@@ -2249,11 +2251,11 @@ static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig,
break;
#endif
#ifdef SIGIO
-#if !defined(SIGPOLL) || SIGIO != SIGPOLL
+# if !defined(SIGPOLL) || SIGIO != SIGPOLL
case SIGIO:
KWSYSPE_CASE(Other, "SIGIO");
break;
-#endif
+# endif
#endif
#ifdef SIGPWR
case SIGPWR:
@@ -2266,11 +2268,11 @@ static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig,
break;
#endif
#ifdef SIGUNUSED
-#if !defined(SIGSYS) || SIGUNUSED != SIGSYS
+# if !defined(SIGSYS) || SIGUNUSED != SIGSYS
case SIGUNUSED:
KWSYSPE_CASE(Other, "SIGUNUSED");
break;
-#endif
+# endif
#endif
default:
cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_Other;
@@ -2289,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));
@@ -2465,23 +2468,28 @@ static pid_t kwsysProcessFork(kwsysProcess* cp,
have two integers to store: the pid and then the ppid. */
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
defined(__OpenBSD__) || defined(__GLIBC__) || defined(__GNU__)
-#define KWSYSPE_PS_COMMAND "ps axo pid,ppid"
-#define KWSYSPE_PS_FORMAT "%d %d\n"
+# define KWSYSPE_PS_COMMAND "ps axo pid,ppid"
+# define KWSYSPE_PS_FORMAT "%d %d\n"
#elif defined(__sun) && (defined(__SVR4) || defined(__svr4__)) /* Solaris */
-#define KWSYSPE_PS_COMMAND "ps -e -o pid,ppid"
-#define KWSYSPE_PS_FORMAT "%d %d\n"
+# define KWSYSPE_PS_COMMAND "ps -e -o pid,ppid"
+# define KWSYSPE_PS_FORMAT "%d %d\n"
#elif defined(__hpux) || defined(__sun__) || defined(__sgi) || \
defined(_AIX) || defined(__sparc)
-#define KWSYSPE_PS_COMMAND "ps -ef"
-#define KWSYSPE_PS_FORMAT "%*s %d %d %*[^\n]\n"
+# define KWSYSPE_PS_COMMAND "ps -ef"
+# define KWSYSPE_PS_FORMAT "%*s %d %d %*[^\n]\n"
#elif defined(__QNX__)
-#define KWSYSPE_PS_COMMAND "ps -Af"
-#define KWSYSPE_PS_FORMAT "%*d %d %d %*[^\n]\n"
+# define KWSYSPE_PS_COMMAND "ps -Af"
+# define KWSYSPE_PS_FORMAT "%*d %d %d %*[^\n]\n"
#elif defined(__CYGWIN__)
-#define KWSYSPE_PS_COMMAND "ps aux"
-#define KWSYSPE_PS_FORMAT "%d %d %*[^\n]\n"
+# define KWSYSPE_PS_COMMAND "ps aux"
+# 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__)
@@ -2501,13 +2509,13 @@ static void kwsysProcessKill(pid_t process_id)
#if defined(__linux__) || defined(__CYGWIN__)
/* First try using the /proc filesystem. */
if ((procdir = opendir("/proc")) != NULL) {
-#if defined(MAXPATHLEN)
+# if defined(MAXPATHLEN)
char fname[MAXPATHLEN];
-#elif defined(PATH_MAX)
+# elif defined(PATH_MAX)
char fname[PATH_MAX];
-#else
+# else
char fname[4096];
-#endif
+# endif
char buffer[KWSYSPE_PIPE_BUFFER_SIZE + 1];
struct dirent* d;
@@ -2707,9 +2715,9 @@ static int kwsysProcessesAdd(kwsysProcess* cp)
#if KWSYSPE_USE_SIGINFO
newSigAction.sa_sigaction = kwsysProcessesSignalHandler;
newSigAction.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
-#ifdef SA_RESTART
+# ifdef SA_RESTART
newSigAction.sa_flags |= SA_RESTART;
-#endif
+# endif
#else
newSigAction.sa_handler = kwsysProcessesSignalHandler;
newSigAction.sa_flags = SA_NOCLDSTOP;
@@ -2796,7 +2804,7 @@ static void kwsysProcessesSignalHandler(int signum
,
siginfo_t* info, void* ucontext
#endif
- )
+)
{
int i, j, procStatus, old_errno = errno;
#if KWSYSPE_USE_SIGINFO
diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c
index 5183e3d2c..68c52185e 100644
--- a/Source/kwsys/ProcessWin32.c
+++ b/Source/kwsys/ProcessWin32.c
@@ -7,8 +7,8 @@
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "Encoding.h.in"
-#include "Process.h.in"
+# include "Encoding.h.in"
+# include "Process.h.in"
#endif
/*
@@ -22,35 +22,35 @@ a UNIX-style select system call.
*/
#ifdef _MSC_VER
-#pragma warning(push, 1)
+# pragma warning(push, 1)
#endif
#include <windows.h> /* Windows API */
#if defined(_MSC_VER) && _MSC_VER >= 1800
-#define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
#endif
#include <io.h> /* _unlink */
#include <stdio.h> /* sprintf */
#include <string.h> /* strlen, strdup */
#ifdef __WATCOMC__
-#define _unlink unlink
+# define _unlink unlink
#endif
#ifndef _MAX_FNAME
-#define _MAX_FNAME 4096
+# define _MAX_FNAME 4096
#endif
#ifndef _MAX_PATH
-#define _MAX_PATH 4096
+# define _MAX_PATH 4096
#endif
#ifdef _MSC_VER
-#pragma warning(pop)
-#pragma warning(disable : 4514)
-#pragma warning(disable : 4706)
+# pragma warning(pop)
+# pragma warning(disable : 4514)
+# pragma warning(disable : 4706)
#endif
#if defined(__BORLANDC__)
-#pragma warn - 8004 /* assigned a value that is never used */
-#pragma warn - 8060 /* Assignment inside if() condition. */
+# pragma warn - 8004 /* assigned a value that is never used */
+# pragma warn - 8060 /* Assignment inside if() condition. */
#endif
/* There are pipes for the process pipeline's stdout and stderr. */
@@ -63,14 +63,14 @@ a UNIX-style select system call.
/* Debug output macro. */
#if 0
-#define KWSYSPE_DEBUG(x) \
- ((void*)cp == (void*)0x00226DE0 \
- ? (fprintf(stderr, "%d/%p/%d ", (int)GetCurrentProcessId(), cp, \
- __LINE__), \
- fprintf x, fflush(stderr), 1) \
- : (1))
+# define KWSYSPE_DEBUG(x) \
+ ((void*)cp == (void*)0x00226DE0 \
+ ? (fprintf(stderr, "%d/%p/%d ", (int)GetCurrentProcessId(), cp, \
+ __LINE__), \
+ fprintf x, fflush(stderr), 1) \
+ : (1))
#else
-#define KWSYSPE_DEBUG(x) (void)1
+# define KWSYSPE_DEBUG(x) (void)1
#endif
typedef LARGE_INTEGER kwsysProcessTime;
@@ -117,7 +117,6 @@ static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1,
kwsysProcessTime in2);
static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1,
kwsysProcessTime in2);
-static void kwsysProcessSetExitException(kwsysProcess* cp, int code);
static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int code,
int idx);
static void kwsysProcessKillTree(int pid);
@@ -355,16 +354,23 @@ kwsysProcess* kwsysProcess_New(void)
ZeroMemory(&osv, sizeof(osv));
osv.dwOSVersionInfoSize = sizeof(osv);
#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(push)
-#ifdef __INTEL_COMPILER
-#pragma warning(disable : 1478)
-#else
-#pragma warning(disable : 4996)
-#endif
+# pragma warning(push)
+# ifdef __INTEL_COMPILER
+# pragma warning(disable : 1478)
+# elif defined __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated-declarations"
+# else
+# pragma warning(disable : 4996)
+# endif
#endif
GetVersionEx(&osv);
#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(pop)
+# ifdef __clang__
+# pragma clang diagnostic pop
+# else
+# pragma warning(pop)
+# endif
#endif
if (osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
/* Win9x no longer supported. */
@@ -523,9 +529,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 +717,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
@@ -976,8 +979,8 @@ void kwsysProcess_Execute(kwsysProcess* cp)
wchar_t* wstdin = kwsysEncoding_DupToWide(cp->PipeFileSTDIN);
DWORD error;
cp->PipeChildStd[0] =
- CreateFileW(wstdin, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
+ CreateFileW(wstdin, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
+ OPEN_EXISTING, 0, 0);
error = GetLastError(); /* Check now in case free changes this. */
free(wstdin);
if (cp->PipeChildStd[0] == INVALID_HANDLE_VALUE) {
@@ -1469,6 +1472,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 +1615,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;
@@ -2266,16 +2272,23 @@ static kwsysProcess_List* kwsysProcess_List_New(void)
ZeroMemory(&osv, sizeof(osv));
osv.dwOSVersionInfoSize = sizeof(osv);
#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(push)
-#ifdef __INTEL_COMPILER
-#pragma warning(disable : 1478)
-#else
-#pragma warning(disable : 4996)
-#endif
+# pragma warning(push)
+# ifdef __INTEL_COMPILER
+# pragma warning(disable : 1478)
+# elif defined __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated-declarations"
+# else
+# pragma warning(disable : 4996)
+# endif
#endif
GetVersionEx(&osv);
#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(pop)
+# ifdef __clang__
+# pragma clang diagnostic pop
+# else
+# pragma warning(pop)
+# endif
#endif
self->NT4 =
(osv.dwPlatformId == VER_PLATFORM_WIN32_NT && osv.dwMajorVersion < 5) ? 1
@@ -2362,9 +2375,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)
@@ -2661,8 +2672,8 @@ static int kwsysProcessesAdd(HANDLE hProcess, DWORD dwProcessid,
newSize = kwsysProcesses.Size ? kwsysProcesses.Size * 2 : 4;
/* Try allocating the new block of memory. */
- if (newArray = (kwsysProcessInstance*)malloc(
- newSize * sizeof(kwsysProcessInstance))) {
+ if ((newArray = (kwsysProcessInstance*)malloc(
+ newSize * sizeof(kwsysProcessInstance)))) {
/* Copy the old process handles to the new memory. */
if (kwsysProcesses.Count > 0) {
memcpy(newArray, kwsysProcesses.Processes,
diff --git a/Source/kwsys/RegularExpression.cxx b/Source/kwsys/RegularExpression.cxx
index 6d7f83295..5e6f8da50 100644
--- a/Source/kwsys/RegularExpression.cxx
+++ b/Source/kwsys/RegularExpression.cxx
@@ -25,7 +25,7 @@
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "RegularExpression.hxx.in"
+# include "RegularExpression.hxx.in"
#endif
#include <stdio.h>
@@ -37,18 +37,18 @@ namespace KWSYS_NAMESPACE {
RegularExpression::RegularExpression(const RegularExpression& rxp)
{
if (!rxp.program) {
- this->program = 0;
+ this->program = 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 != 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 = 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 != 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.
/*
@@ -163,8 +164,8 @@ bool RegularExpression::deep_equal(const RegularExpression& rxp) const
*
* regstart char that must begin a match; '\0' if none obvious
* reganch is the match anchored (at beginning-of-line only)?
- * regmust string (pointer into program) that match must include, or NULL
- * regmlen length of regmust string
+ * regmust string (pointer into program) that match must include, or
+ * nullptr regmlen length of regmust string
*
* Regstart and reganch permit very fast decisions on suitable starting points
* for a match, cutting down the work a lot. Regmust permits fast rejection
@@ -193,24 +194,29 @@ bool RegularExpression::deep_equal(const RegularExpression& rxp) const
*/
// definition number opnd? meaning
-#define END 0 // no End of program.
-#define BOL 1 // no Match "" at beginning of line.
-#define EOL 2 // no Match "" at end of line.
-#define ANY 3 // no Match any one character.
-#define ANYOF 4 // str Match any character in this string.
-#define ANYBUT 5 // str Match any character not in this
- // string.
-#define BRANCH 6 // node Match this alternative, or the
+#define END 0 // no End of program.
+#define BOL 1 // no Match "" at beginning of line.
+#define EOL 2 // no Match "" at end of line.
+#define ANY 3 // no Match any one character.
+#define ANYOF 4 // str Match any character in this string.
+#define ANYBUT \
+ 5 // str Match any character not in this
+ // string.
+#define BRANCH \
+ 6 // node Match this alternative, or the
// next...
#define BACK 7 // no Match "", "next" ptr points backward.
#define EXACTLY 8 // str Match this string.
#define NOTHING 9 // no Match empty string.
-#define STAR 10 // node Match this (simple) thing 0 or more
- // times.
-#define PLUS 11 // node Match this (simple) thing 1 or more
- // times.
-#define OPEN 20 // no Mark this point in input as start of
- // #n.
+#define STAR \
+ 10 // node Match this (simple) thing 0 or more
+ // times.
+#define PLUS \
+ 11 // node Match this (simple) thing 1 or more
+ // times.
+#define OPEN \
+ 20 // no Mark this point in input as start of
+ // #n.
// OPEN+1 is number 1, etc.
#define CLOSE 30 // no Analogous to OPEN.
@@ -258,11 +264,6 @@ const unsigned char MAGIC = 0234;
#define UCHARAT(p) (reinterpret_cast<const unsigned char*>(p))[0]
-#define FAIL(m) \
- { \
- regerror(m); \
- return (0); \
- }
#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?')
#define META "^$.[()|?+*\\"
@@ -281,31 +282,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();
@@ -332,29 +337,29 @@ bool RegularExpression::compile(const char* exp)
{
const char* scan;
const char* longest;
- size_t len;
int flags;
- if (exp == 0) {
+ if (exp == 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;
@@ -362,29 +367,29 @@ bool RegularExpression::compile(const char* exp)
// Allocate space.
//#ifndef _WIN32
- if (this->program != 0)
+ if (this->program != 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 == 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 = nullptr;
this->regmlen = 0;
scan = this->program + 1; // First BRANCH.
if (OP(regnext(scan)) == END) { // Only one top-level choice.
@@ -405,9 +410,9 @@ bool RegularExpression::compile(const char* exp)
// absence of others.
//
if (flags & SPSTART) {
- longest = 0;
- len = 0;
- for (; scan != 0; scan = regnext(scan))
+ longest = nullptr;
+ size_t len = 0;
+ for (; scan != nullptr; scan = regnext(scan))
if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
longest = OPERAND(scan);
len = strlen(OPERAND(scan));
@@ -428,7 +433,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;
@@ -440,22 +445,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 nullptr;
}
parno = regnpar;
regnpar++;
ret = regnode(static_cast<char>(OPEN + parno));
} else
- ret = 0;
+ ret = nullptr;
// Pick up the branches, linking them together.
br = regbranch(&flags);
- if (br == 0)
- return (0);
- if (ret != 0)
+ if (br == nullptr)
+ return (nullptr);
+ if (ret != nullptr)
regtail(ret, br); // OPEN -> first.
else
ret = br;
@@ -465,8 +470,8 @@ static char* reg(int paren, int* flagp)
while (*regparse == '|') {
regparse++;
br = regbranch(&flags);
- if (br == 0)
- return (0);
+ if (br == nullptr)
+ return (nullptr);
regtail(ret, br); // BRANCH -> BRANCH.
if (!(flags & HASWIDTH))
*flagp &= ~HASWIDTH;
@@ -478,23 +483,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 != 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 nullptr;
} else if (!paren && *regparse != '\0') {
if (*regparse == ')') {
// RAISE Error, SYM(RegularExpression), SYM(Unmatched_Parens),
printf("RegularExpression::compile(): Unmatched parentheses.\n");
- return 0;
+ return nullptr;
} else {
// RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
printf("RegularExpression::compile(): Internal error.\n");
- return 0;
+ return nullptr;
}
// NOTREACHED
}
@@ -506,7 +511,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;
@@ -516,19 +521,19 @@ static char* regbranch(int* flagp)
*flagp = WORST; // Tentatively.
ret = regnode(BRANCH);
- chain = 0;
+ chain = nullptr;
while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
latest = regpiece(&flags);
- if (latest == 0)
- return (0);
+ if (latest == nullptr)
+ return (nullptr);
*flagp |= flags & HASWIDTH;
- if (chain == 0) // First piece.
+ if (chain == nullptr) // First piece.
*flagp |= flags & SPSTART;
else
regtail(chain, latest);
chain = latest;
}
- if (chain == 0) // Loop ran zero times.
+ if (chain == nullptr) // Loop ran zero times.
regnode(NOTHING);
return (ret);
@@ -543,7 +548,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;
@@ -551,8 +556,8 @@ static char* regpiece(int* flagp)
int flags;
ret = regatom(&flags);
- if (ret == 0)
- return (0);
+ if (ret == nullptr)
+ return (nullptr);
op = *regparse;
if (!ISMULT(op)) {
@@ -563,7 +568,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 nullptr;
}
*flagp = (op != '+') ? (WORST | SPSTART) : (WORST | HASWIDTH);
@@ -597,7 +602,7 @@ static char* regpiece(int* flagp)
if (ISMULT(*regparse)) {
// RAISE Error, SYM(RegularExpression), SYM(Nested_Operand),
printf("RegularExpression::compile(): Nested *?+.\n");
- return 0;
+ return nullptr;
}
return (ret);
}
@@ -610,7 +615,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;
@@ -650,7 +655,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 nullptr;
}
for (; rxpclass <= rxpclassend; rxpclass++)
regc(static_cast<char>(rxpclass));
@@ -663,15 +668,15 @@ static char* regatom(int* flagp)
if (*regparse != ']') {
// RAISE Error, SYM(RegularExpression), SYM(Unmatched_Bracket),
printf("RegularExpression::compile(): Unmatched [].\n");
- return 0;
+ return nullptr;
}
regparse++;
*flagp |= HASWIDTH | SIMPLE;
} break;
case '(':
ret = reg(1, &flags);
- if (ret == 0)
- return (0);
+ if (ret == nullptr)
+ return (nullptr);
*flagp |= flags & (HASWIDTH | SPSTART);
break;
case '\0':
@@ -679,18 +684,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 nullptr;
case '?':
case '+':
case '*':
// RAISE Error, SYM(RegularExpression), SYM(No_Operand),
printf("RegularExpression::compile(): ?+* follows nothing.\n");
- return 0;
+ return nullptr;
case '\\':
if (*regparse == '\0') {
// RAISE Error, SYM(RegularExpression), SYM(Trailing_Backslash),
printf("RegularExpression::compile(): Trailing backslash.\n");
- return 0;
+ return nullptr;
}
ret = regnode(EXACTLY);
regc(*regparse++);
@@ -706,7 +711,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 nullptr;
}
ender = *(regparse + len);
if (len > 1 && ISMULT(ender))
@@ -729,13 +734,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);
}
@@ -752,9 +757,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++;
@@ -765,13 +770,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;
}
@@ -791,20 +796,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 == nullptr)
break;
scan = temp;
}
@@ -820,10 +825,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 == nullptr || p == regdummyptr || OP(p) != BRANCH)
return;
regtail(OPERAND(p), val);
}
@@ -835,34 +840,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;
@@ -873,54 +874,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 != nullptr) {
s = string;
- while ((s = strchr(s, this->regmust[0])) != 0) {
+ while ((s = strchr(s, this->regmust[0])) != nullptr) {
if (strncmp(s, this->regmust, this->regmlen) == 0)
break; // Found it.
s++;
}
- if (s == 0) // Not present.
- return (0);
+ if (s == 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)) != 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;
@@ -932,9 +936,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++ = nullptr;
+ *ep++ = nullptr;
}
if (regmatch(prog + 1)) {
start[0] = string;
@@ -955,14 +959,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 != nullptr) {
next = regnext(scan);
@@ -994,12 +998,12 @@ 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) == nullptr)
return (0);
reginput++;
break;
case ANYBUT:
- if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != 0)
+ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != nullptr)
return (0);
reginput++;
break;
@@ -1028,7 +1032,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] == nullptr)
regstartp[no] = save;
return (1);
} else
@@ -1056,7 +1060,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] == nullptr)
regendp[no] = save;
return (1);
} else
@@ -1076,7 +1080,7 @@ static int regmatch(const char* prog)
return (1);
reginput = save;
scan = regnext(scan);
- } while (scan != 0 && OP(scan) == BRANCH);
+ } while (scan != nullptr && OP(scan) == BRANCH);
return (0);
// NOTREACHED
}
@@ -1134,7 +1138,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;
@@ -1154,13 +1158,13 @@ static int regrepeat(const char* p)
}
break;
case ANYOF:
- while (*scan != '\0' && strchr(opnd, *scan) != 0) {
+ while (*scan != '\0' && strchr(opnd, *scan) != nullptr) {
count++;
scan++;
}
break;
case ANYBUT:
- while (*scan != '\0' && strchr(opnd, *scan) == 0) {
+ while (*scan != '\0' && strchr(opnd, *scan) == nullptr) {
count++;
scan++;
}
@@ -1181,12 +1185,12 @@ static const char* regnext(const char* p)
{
int offset;
- if (p == &regdummy)
- return (0);
+ if (p == regdummyptr)
+ return (nullptr);
offset = NEXT(p);
if (offset == 0)
- return (0);
+ return (nullptr);
if (OP(p) == BACK)
return (p - offset);
@@ -1198,12 +1202,12 @@ static char* regnext(char* p)
{
int offset;
- if (p == &regdummy)
- return (0);
+ if (p == regdummyptr)
+ return (nullptr);
offset = NEXT(p);
if (offset == 0)
- return (0);
+ return (nullptr);
if (OP(p) == BACK)
return (p - offset);
diff --git a/Source/kwsys/RegularExpression.hxx.in b/Source/kwsys/RegularExpression.hxx.in
index 606e3da6e..df7eb4558 100644
--- a/Source/kwsys/RegularExpression.hxx.in
+++ b/Source/kwsys/RegularExpression.hxx.in
@@ -29,11 +29,121 @@
/* Disable useless Borland warnings. KWSys tries not to force things
on its includers, but there is no choice here. */
#if defined(__BORLANDC__)
-#pragma warn - 8027 /* function not inlined. */
+# pragma warn - 8027 /* function not inlined. */
#endif
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] = nullptr;
+ endp[0] = nullptr;
+ searchstring = nullptr;
+}
+
+/**
+ * \brief Returns true if the match pointers are valid
+ */
+inline bool RegularExpressionMatch::isValid() const
+{
+ return (this->startp[0] != nullptr);
+}
+
+/**
+ * \brief Resets to the (invalid) construction state.
+ */
+inline void RegularExpressionMatch::clear()
+{
+ startp[0] = nullptr;
+ endp[0] = nullptr;
+ searchstring = nullptr;
+}
+
+/**
+ * \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] == nullptr) {
+ 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 +203,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,21 +219,22 @@ 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
* the to see if the compiled regular expression is the same, and the
* deep_equal functions also checks to see if the start and end pointers are
- * the same. The is_valid function returns false if program is set to NULL,
- * (i.e. there is no valid compiled exression). The set_invalid function sets
- * the program to NULL (Warning: this deletes the compiled expression). The
- * following examples may help clarify regular expression usage:
+ * the same. The is_valid function returns false if program is set to
+ * nullptr, (i.e. there is no valid compiled expression). The set_invalid
+ * function sets the program to nullptr (Warning: this deletes the compiled
+ * expression). The following examples may help clarify regular expression
+ * usage:
*
* * The regular expression "^hello" matches a "hello" only at the
* beginning of a line. It would match "hello there" but not "hi,
@@ -161,21 +272,24 @@ namespace @KWSYS_NAMESPACE@ {
*
* * The regular expression "(..p)b" matches something ending with pb
* and beginning with whatever the two characters before the first p
- * encounterd in the line were. It would find "repb" in "rep drepa
+ * encountered in the line were. It would find "repb" in "rep drepa
* qrepb". The regular expression "(..p)a" would find "repa qrepb"
* in "rep drepa qrepb"
*
* * The regular expression "d(..p)" matches something ending with p,
* beginning with d, and having two characters in between that are
- * the same as the two characters before the first p encounterd in
+ * the same as the two characters before the first p encountered 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
{
public:
/**
- * Instantiate RegularExpression with program=NULL.
+ * Instantiate RegularExpression with program=nullptr.
*/
inline RegularExpression();
@@ -213,9 +327,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 +348,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,37 +394,26 @@ 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;
};
/**
* Create an empty regular expression.
*/
inline RegularExpression::RegularExpression()
+ : regstart{}
+ , reganch{}
+ , regmust{}
+ , program{ nullptr }
+ , progsize{}
{
- this->program = 0;
}
/**
@@ -304,8 +421,12 @@ inline RegularExpression::RegularExpression()
* compiles s.
*/
inline RegularExpression::RegularExpression(const char* s)
+ : regstart{}
+ , reganch{}
+ , regmust{}
+ , program{ nullptr }
+ , progsize{}
{
- this->program = 0;
if (s) {
this->compile(s);
}
@@ -316,8 +437,12 @@ inline RegularExpression::RegularExpression(const char* s)
* compiles s.
*/
inline RegularExpression::RegularExpression(const std::string& s)
+ : regstart{}
+ , reganch{}
+ , regmust{}
+ , program{ nullptr }
+ , progsize{}
{
- this->program = 0;
this->compile(s);
}
@@ -344,51 +469,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
+inline std::string::size_type RegularExpression::end() const
{
- return (this->program != 0);
-}
-
-inline void RegularExpression::set_invalid()
-{
- //#ifndef _WIN32
- delete[] this->program;
- //#endif
- this->program = 0;
+ return regmatch.end();
}
/**
@@ -396,7 +512,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 +520,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 +528,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 != nullptr);
+}
+
+inline void RegularExpression::set_invalid()
+{
+ //#ifndef _WIN32
+ delete[] this->program;
+ //#endif
+ this->program = nullptr;
}
} // namespace @KWSYS_NAMESPACE@
diff --git a/Source/kwsys/SharedForward.h.in b/Source/kwsys/SharedForward.h.in
index f638267ec..5716cd4f1 100644
--- a/Source/kwsys/SharedForward.h.in
+++ b/Source/kwsys/SharedForward.h.in
@@ -1,7 +1,7 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#ifndef @KWSYS_NAMESPACE@_SharedForward_h
-#define @KWSYS_NAMESPACE@_SharedForward_h
+# define @KWSYS_NAMESPACE@_SharedForward_h
/*
This header is used to create a forwarding executable sets up the
@@ -59,134 +59,134 @@
/* Disable -Wcast-qual warnings since they are too hard to fix in a
cross-platform way. */
-#if defined(__clang__) && defined(__has_warning)
-#if __has_warning("-Wcast-qual")
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wcast-qual"
-#endif
-#endif
-
-#if defined(__BORLANDC__) && !defined(__cplusplus)
+# if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wcast-qual")
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wcast-qual"
+# endif
+# endif
+
+# if defined(__BORLANDC__) && !defined(__cplusplus)
/* Code has no effect; raised by winnt.h in C (not C++) when ignoring an
unused parameter using "(param)" syntax (i.e. no cast to void). */
-#pragma warn - 8019
-#endif
+# pragma warn - 8019
+# endif
/* Full path to the directory in which this executable is built. Do
not include a trailing slash. */
-#if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD)
-#error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD"
-#endif
-#if !defined(KWSYS_SHARED_FORWARD_DIR_BUILD)
-#define KWSYS_SHARED_FORWARD_DIR_BUILD \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD
-#endif
+# if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD)
+# error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD"
+# endif
+# if !defined(KWSYS_SHARED_FORWARD_DIR_BUILD)
+# define KWSYS_SHARED_FORWARD_DIR_BUILD \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD
+# endif
/* Library search path for build tree. */
-#if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD)
-#error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD"
-#endif
-#if !defined(KWSYS_SHARED_FORWARD_PATH_BUILD)
-#define KWSYS_SHARED_FORWARD_PATH_BUILD \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD
-#endif
+# if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD)
+# error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD"
+# endif
+# if !defined(KWSYS_SHARED_FORWARD_PATH_BUILD)
+# define KWSYS_SHARED_FORWARD_PATH_BUILD \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD
+# endif
/* Library search path for install tree. */
-#if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL)
-#error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL"
-#endif
-#if !defined(KWSYS_SHARED_FORWARD_PATH_INSTALL)
-#define KWSYS_SHARED_FORWARD_PATH_INSTALL \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL
-#endif
+# if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL)
+# error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL"
+# endif
+# if !defined(KWSYS_SHARED_FORWARD_PATH_INSTALL)
+# define KWSYS_SHARED_FORWARD_PATH_INSTALL \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL
+# endif
/* The real executable to which to forward in the build tree. */
-#if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD)
-#error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD"
-#endif
-#if !defined(KWSYS_SHARED_FORWARD_EXE_BUILD)
-#define KWSYS_SHARED_FORWARD_EXE_BUILD \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD
-#endif
+# if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD)
+# error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD"
+# endif
+# if !defined(KWSYS_SHARED_FORWARD_EXE_BUILD)
+# define KWSYS_SHARED_FORWARD_EXE_BUILD \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD
+# endif
/* The real executable to which to forward in the install tree. */
-#if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL)
-#error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL"
-#endif
-#if !defined(KWSYS_SHARED_FORWARD_EXE_INSTALL)
-#define KWSYS_SHARED_FORWARD_EXE_INSTALL \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL
-#endif
+# if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL)
+# error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL"
+# endif
+# if !defined(KWSYS_SHARED_FORWARD_EXE_INSTALL)
+# define KWSYS_SHARED_FORWARD_EXE_INSTALL \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL
+# endif
/* The configuration name with which this executable was built (Debug/Release).
*/
-#if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME)
-#define KWSYS_SHARED_FORWARD_CONFIG_NAME \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME
-#else
-#undef KWSYS_SHARED_FORWARD_CONFIG_NAME
-#endif
+# if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME)
+# define KWSYS_SHARED_FORWARD_CONFIG_NAME \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME
+# else
+# undef KWSYS_SHARED_FORWARD_CONFIG_NAME
+# endif
/* Create command line option to replace executable. */
-#if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_COMMAND)
-#if !defined(KWSYS_SHARED_FORWARD_OPTION_COMMAND)
-#define KWSYS_SHARED_FORWARD_OPTION_COMMAND \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_COMMAND
-#endif
-#else
-#undef KWSYS_SHARED_FORWARD_OPTION_COMMAND
-#endif
+# if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_COMMAND)
+# if !defined(KWSYS_SHARED_FORWARD_OPTION_COMMAND)
+# define KWSYS_SHARED_FORWARD_OPTION_COMMAND \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_COMMAND
+# endif
+# else
+# undef KWSYS_SHARED_FORWARD_OPTION_COMMAND
+# endif
/* Create command line option to print environment setting and exit. */
-#if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_PRINT)
-#if !defined(KWSYS_SHARED_FORWARD_OPTION_PRINT)
-#define KWSYS_SHARED_FORWARD_OPTION_PRINT \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_PRINT
-#endif
-#else
-#undef KWSYS_SHARED_FORWARD_OPTION_PRINT
-#endif
+# if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_PRINT)
+# if !defined(KWSYS_SHARED_FORWARD_OPTION_PRINT)
+# define KWSYS_SHARED_FORWARD_OPTION_PRINT \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_PRINT
+# endif
+# else
+# undef KWSYS_SHARED_FORWARD_OPTION_PRINT
+# endif
/* Create command line option to run ldd or equivalent. */
-#if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_LDD)
-#if !defined(KWSYS_SHARED_FORWARD_OPTION_LDD)
-#define KWSYS_SHARED_FORWARD_OPTION_LDD \
- @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_LDD
-#endif
-#else
-#undef KWSYS_SHARED_FORWARD_OPTION_LDD
-#endif
+# if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_LDD)
+# if !defined(KWSYS_SHARED_FORWARD_OPTION_LDD)
+# define KWSYS_SHARED_FORWARD_OPTION_LDD \
+ @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_LDD
+# endif
+# else
+# undef KWSYS_SHARED_FORWARD_OPTION_LDD
+# endif
/* Include needed system headers. */
-#include <errno.h>
-#include <limits.h>
-#include <stddef.h> /* size_t */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+# include <errno.h>
+# include <limits.h>
+# include <stddef.h> /* size_t */
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <windows.h>
+# if defined(_WIN32) && !defined(__CYGWIN__)
+# include <windows.h>
-#include <io.h>
-#include <process.h>
-#define KWSYS_SHARED_FORWARD_ESCAPE_ARGV /* re-escape argv for execvp */
-#else
-#include <sys/stat.h>
-#include <unistd.h>
-#endif
+# include <io.h>
+# include <process.h>
+# define KWSYS_SHARED_FORWARD_ESCAPE_ARGV /* re-escape argv for execvp */
+# else
+# include <sys/stat.h>
+# include <unistd.h>
+# endif
/* Configuration for this platform. */
/* The path separator for this platform. */
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#define KWSYS_SHARED_FORWARD_PATH_SEP ';'
-#define KWSYS_SHARED_FORWARD_PATH_SLASH '\\'
-#else
-#define KWSYS_SHARED_FORWARD_PATH_SEP ':'
-#define KWSYS_SHARED_FORWARD_PATH_SLASH '/'
-#endif
+# if defined(_WIN32) && !defined(__CYGWIN__)
+# define KWSYS_SHARED_FORWARD_PATH_SEP ';'
+# define KWSYS_SHARED_FORWARD_PATH_SLASH '\\'
+# else
+# define KWSYS_SHARED_FORWARD_PATH_SEP ':'
+# define KWSYS_SHARED_FORWARD_PATH_SLASH '/'
+# endif
static const char kwsys_shared_forward_path_sep[2] = {
KWSYS_SHARED_FORWARD_PATH_SEP, 0
};
@@ -195,99 +195,101 @@ static const char kwsys_shared_forward_path_slash[2] = {
};
/* The maximum length of a file name. */
-#if defined(PATH_MAX)
-#define KWSYS_SHARED_FORWARD_MAXPATH PATH_MAX
-#elif defined(MAXPATHLEN)
-#define KWSYS_SHARED_FORWARD_MAXPATH MAXPATHLEN
-#else
-#define KWSYS_SHARED_FORWARD_MAXPATH 16384
-#endif
+# if defined(PATH_MAX)
+# define KWSYS_SHARED_FORWARD_MAXPATH PATH_MAX
+# elif defined(MAXPATHLEN)
+# define KWSYS_SHARED_FORWARD_MAXPATH MAXPATHLEN
+# else
+# define KWSYS_SHARED_FORWARD_MAXPATH 16384
+# endif
/* Select the environment variable holding the shared library runtime
search path for this platform and build configuration. Also select
ldd command equivalent. */
/* Linux */
-#if defined(__linux)
-#define KWSYS_SHARED_FORWARD_LDD "ldd"
-#define KWSYS_SHARED_FORWARD_LDD_N 1
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
+# if defined(__linux)
+# define KWSYS_SHARED_FORWARD_LDD "ldd"
+# define KWSYS_SHARED_FORWARD_LDD_N 1
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
/* FreeBSD */
-#elif defined(__FreeBSD__)
-#define KWSYS_SHARED_FORWARD_LDD "ldd"
-#define KWSYS_SHARED_FORWARD_LDD_N 1
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
+# elif defined(__FreeBSD__)
+# define KWSYS_SHARED_FORWARD_LDD "ldd"
+# define KWSYS_SHARED_FORWARD_LDD_N 1
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
/* OpenBSD */
-#elif defined(__OpenBSD__)
-#define KWSYS_SHARED_FORWARD_LDD "ldd"
-#define KWSYS_SHARED_FORWARD_LDD_N 1
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
+# elif defined(__OpenBSD__)
+# define KWSYS_SHARED_FORWARD_LDD "ldd"
+# define KWSYS_SHARED_FORWARD_LDD_N 1
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
-/* OSX */
-#elif defined(__APPLE__)
-#define KWSYS_SHARED_FORWARD_LDD "otool", "-L"
-#define KWSYS_SHARED_FORWARD_LDD_N 2
-#define KWSYS_SHARED_FORWARD_LDPATH "DYLD_LIBRARY_PATH"
+/* OS X */
+# elif defined(__APPLE__)
+# define KWSYS_SHARED_FORWARD_LDD "otool", "-L"
+# define KWSYS_SHARED_FORWARD_LDD_N 2
+# define KWSYS_SHARED_FORWARD_LDPATH "DYLD_LIBRARY_PATH"
/* AIX */
-#elif defined(_AIX)
-#define KWSYS_SHARED_FORWARD_LDD "dump", "-H"
-#define KWSYS_SHARED_FORWARD_LDD_N 2
-#define KWSYS_SHARED_FORWARD_LDPATH "LIBPATH"
+# elif defined(_AIX)
+# define KWSYS_SHARED_FORWARD_LDD "dump", "-H"
+# define KWSYS_SHARED_FORWARD_LDD_N 2
+# define KWSYS_SHARED_FORWARD_LDPATH "LIBPATH"
/* SUN */
-#elif defined(__sun)
-#define KWSYS_SHARED_FORWARD_LDD "ldd"
-#define KWSYS_SHARED_FORWARD_LDD_N 1
-#include <sys/isa_defs.h>
-#if defined(_ILP32)
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
-#elif defined(_LP64)
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH_64"
-#endif
+# elif defined(__sun)
+# define KWSYS_SHARED_FORWARD_LDD "ldd"
+# define KWSYS_SHARED_FORWARD_LDD_N 1
+# include <sys/isa_defs.h>
+# if defined(_ILP32)
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
+# elif defined(_LP64)
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH_64"
+# endif
/* HP-UX */
-#elif defined(__hpux)
-#define KWSYS_SHARED_FORWARD_LDD "chatr"
-#define KWSYS_SHARED_FORWARD_LDD_N 1
-#if defined(__LP64__)
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
-#else
-#define KWSYS_SHARED_FORWARD_LDPATH "SHLIB_PATH"
-#endif
+# elif defined(__hpux)
+# define KWSYS_SHARED_FORWARD_LDD "chatr"
+# define KWSYS_SHARED_FORWARD_LDD_N 1
+# if defined(__LP64__)
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
+# else
+# define KWSYS_SHARED_FORWARD_LDPATH "SHLIB_PATH"
+# endif
/* SGI MIPS */
-#elif defined(__sgi) && defined(_MIPS_SIM)
-#define KWSYS_SHARED_FORWARD_LDD "ldd"
-#define KWSYS_SHARED_FORWARD_LDD_N 1
-#if _MIPS_SIM == _ABIO32
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
-#elif _MIPS_SIM == _ABIN32
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARYN32_PATH"
-#elif _MIPS_SIM == _ABI64
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY64_PATH"
-#endif
+# elif defined(__sgi) && defined(_MIPS_SIM)
+# define KWSYS_SHARED_FORWARD_LDD "ldd"
+# define KWSYS_SHARED_FORWARD_LDD_N 1
+# if _MIPS_SIM == _ABIO32
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
+# elif _MIPS_SIM == _ABIN32
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARYN32_PATH"
+# elif _MIPS_SIM == _ABI64
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY64_PATH"
+# endif
/* Cygwin */
-#elif defined(__CYGWIN__)
-#define KWSYS_SHARED_FORWARD_LDD "cygcheck" /* TODO: cygwin 1.7 has ldd */
-#define KWSYS_SHARED_FORWARD_LDD_N 1
-#define KWSYS_SHARED_FORWARD_LDPATH "PATH"
+# elif defined(__CYGWIN__)
+# define KWSYS_SHARED_FORWARD_LDD \
+ "cygcheck" /* TODO: cygwin 1.7 has ldd \
+ */
+# define KWSYS_SHARED_FORWARD_LDD_N 1
+# define KWSYS_SHARED_FORWARD_LDPATH "PATH"
/* Windows */
-#elif defined(_WIN32)
-#define KWSYS_SHARED_FORWARD_LDPATH "PATH"
+# elif defined(_WIN32)
+# define KWSYS_SHARED_FORWARD_LDPATH "PATH"
/* Guess on this unknown system. */
-#else
-#define KWSYS_SHARED_FORWARD_LDD "ldd"
-#define KWSYS_SHARED_FORWARD_LDD_N 1
-#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
-#endif
+# else
+# define KWSYS_SHARED_FORWARD_LDD "ldd"
+# define KWSYS_SHARED_FORWARD_LDD_N 1
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
+# endif
-#ifdef KWSYS_SHARED_FORWARD_ESCAPE_ARGV
+# ifdef KWSYS_SHARED_FORWARD_ESCAPE_ARGV
typedef struct kwsys_sf_arg_info_s
{
const char* arg;
@@ -404,25 +406,25 @@ static char* kwsys_sf_get_arg(kwsys_sf_arg_info info, char* out)
return out;
}
-#endif
+# endif
/* Function to convert a logical or relative path to a physical full path. */
static int kwsys_shared_forward_realpath(const char* in_path, char* out_path)
{
-#if defined(_WIN32) && !defined(__CYGWIN__)
+# if defined(_WIN32) && !defined(__CYGWIN__)
/* Implementation for Windows. */
DWORD n =
GetFullPathNameA(in_path, KWSYS_SHARED_FORWARD_MAXPATH, out_path, 0);
return n > 0 && n <= KWSYS_SHARED_FORWARD_MAXPATH;
-#else
+# else
/* Implementation for UNIX. */
return realpath(in_path, out_path) != 0;
-#endif
+# endif
}
static int kwsys_shared_forward_samepath(const char* file1, const char* file2)
{
-#if defined(_WIN32)
+# if defined(_WIN32)
int result = 0;
HANDLE h1 = CreateFileA(file1, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
@@ -440,19 +442,19 @@ static int kwsys_shared_forward_samepath(const char* file1, const char* file2)
CloseHandle(h1);
CloseHandle(h2);
return result;
-#else
+# else
struct stat fs1, fs2;
return (stat(file1, &fs1) == 0 && stat(file2, &fs2) == 0 &&
memcmp(&fs2.st_dev, &fs1.st_dev, sizeof(fs1.st_dev)) == 0 &&
memcmp(&fs2.st_ino, &fs1.st_ino, sizeof(fs1.st_ino)) == 0 &&
fs2.st_size == fs1.st_size);
-#endif
+# endif
}
/* Function to report a system error message. */
static void kwsys_shared_forward_strerror(char* message)
{
-#if defined(_WIN32) && !defined(__CYGWIN__)
+# if defined(_WIN32) && !defined(__CYGWIN__)
/* Implementation for Windows. */
DWORD original = GetLastError();
DWORD length =
@@ -465,17 +467,17 @@ static void kwsys_shared_forward_strerror(char* message)
"Error 0x%X (FormatMessage failed with error 0x%X)", original,
GetLastError());
}
-#else
+# else
/* Implementation for UNIX. */
strcpy(message, strerror(errno));
-#endif
+# endif
}
/* Functions to execute a child process. */
static void kwsys_shared_forward_execvp(const char* cmd,
char const* const* argv)
{
-#ifdef KWSYS_SHARED_FORWARD_ESCAPE_ARGV
+# ifdef KWSYS_SHARED_FORWARD_ESCAPE_ARGV
/* Count the number of arguments. */
int argc = 0;
{
@@ -498,16 +500,16 @@ static void kwsys_shared_forward_execvp(const char* cmd,
/* Replace the command line to be used. */
argv = (char const* const*)nargv;
}
-#endif
+# endif
/* Invoke the child process. */
-#if defined(_MSC_VER)
+# if defined(_MSC_VER)
_execvp(cmd, argv);
-#elif defined(__MINGW32__) && !defined(__MINGW64__)
+# elif defined(__MINGW32__) && !defined(__MINGW64__)
execvp(cmd, argv);
-#else
+# else
execvp(cmd, (char* const*)argv);
-#endif
+# endif
}
/* Function to get the directory containing the given file or directory. */
@@ -530,14 +532,14 @@ static void kwsys_shared_forward_dirname(const char* begin, char* result)
/* Only one leading slash. */
strcpy(result, kwsys_shared_forward_path_slash);
}
-#if defined(_WIN32)
+# if defined(_WIN32)
else if (last_slash_index == 2 && begin[1] == ':') {
/* Only one leading drive letter and slash. */
strncpy(result, begin, (size_t)last_slash_index);
result[last_slash_index] = KWSYS_SHARED_FORWARD_PATH_SLASH;
result[last_slash_index + 1] = 0;
}
-#endif
+# endif
else {
/* A non-leading slash. */
strncpy(result, begin, (size_t)last_slash_index);
@@ -548,16 +550,16 @@ static void kwsys_shared_forward_dirname(const char* begin, char* result)
/* Function to check if a file exists and is executable. */
static int kwsys_shared_forward_is_executable(const char* f)
{
-#if defined(_MSC_VER)
-#define KWSYS_SHARED_FORWARD_ACCESS _access
-#else
-#define KWSYS_SHARED_FORWARD_ACCESS access
-#endif
-#if defined(X_OK)
-#define KWSYS_SHARED_FORWARD_ACCESS_OK X_OK
-#else
-#define KWSYS_SHARED_FORWARD_ACCESS_OK 04
-#endif
+# if defined(_MSC_VER)
+# define KWSYS_SHARED_FORWARD_ACCESS _access
+# else
+# define KWSYS_SHARED_FORWARD_ACCESS access
+# endif
+# if defined(X_OK)
+# define KWSYS_SHARED_FORWARD_ACCESS_OK X_OK
+# else
+# define KWSYS_SHARED_FORWARD_ACCESS_OK 04
+# endif
if (KWSYS_SHARED_FORWARD_ACCESS(f, KWSYS_SHARED_FORWARD_ACCESS_OK) == 0) {
return 1;
} else {
@@ -641,12 +643,12 @@ static int kwsys_shared_forward_fullpath(const char* self_path,
/* Already a full path. */
strcpy(result, in_path);
}
-#if defined(_WIN32)
+# if defined(_WIN32)
else if (in_path[0] && in_path[1] == ':') {
/* Already a full path. */
strcpy(result, in_path);
}
-#endif
+# endif
else {
/* Relative to self path. */
char temp_path[KWSYS_SHARED_FORWARD_MAXPATH];
@@ -683,14 +685,14 @@ static int kwsys_shared_forward_get_settings(const char* self_path,
const char* exe_path;
/* Get the real name of the build and self paths. */
-#if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME)
+# if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME)
char build_path[] =
KWSYS_SHARED_FORWARD_DIR_BUILD "/" KWSYS_SHARED_FORWARD_CONFIG_NAME;
char self_path_logical[KWSYS_SHARED_FORWARD_MAXPATH];
-#else
+# else
char build_path[] = KWSYS_SHARED_FORWARD_DIR_BUILD;
const char* self_path_logical = self_path;
-#endif
+# endif
char build_path_real[KWSYS_SHARED_FORWARD_MAXPATH];
char self_path_real[KWSYS_SHARED_FORWARD_MAXPATH];
if (!kwsys_shared_forward_realpath(self_path, self_path_real)) {
@@ -706,29 +708,29 @@ static int kwsys_shared_forward_get_settings(const char* self_path,
kwsys_shared_forward_samepath(self_path_real, build_path_real)) {
/* Running in build tree. Use the build path and exe. */
search_path = search_path_build;
-#if defined(_WIN32)
+# if defined(_WIN32)
exe_path = KWSYS_SHARED_FORWARD_EXE_BUILD ".exe";
-#else
+# else
exe_path = KWSYS_SHARED_FORWARD_EXE_BUILD;
-#endif
+# endif
-#if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME)
+# if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME)
/* Remove the configuration directory from self_path. */
kwsys_shared_forward_dirname(self_path, self_path_logical);
-#endif
+# endif
} else {
/* Running in install tree. Use the install path and exe. */
search_path = search_path_install;
-#if defined(_WIN32)
+# if defined(_WIN32)
exe_path = KWSYS_SHARED_FORWARD_EXE_INSTALL ".exe";
-#else
+# else
exe_path = KWSYS_SHARED_FORWARD_EXE_INSTALL;
-#endif
+# endif
-#if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME)
+# if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME)
/* Use the original self path directory. */
strcpy(self_path_logical, self_path);
-#endif
+# endif
}
/* Construct the runtime search path. */
@@ -795,7 +797,7 @@ static int @KWSYS_NAMESPACE@_shared_forward_to_real(int argc, char** argv_in)
/* Store the environment variable. */
putenv(kwsys_shared_forward_ldpath);
-#if defined(KWSYS_SHARED_FORWARD_OPTION_COMMAND)
+# if defined(KWSYS_SHARED_FORWARD_OPTION_COMMAND)
/* Look for the command line replacement option. */
if (argc > 1 &&
strcmp(argv[1], KWSYS_SHARED_FORWARD_OPTION_COMMAND) == 0) {
@@ -806,14 +808,15 @@ static int @KWSYS_NAMESPACE@_shared_forward_to_real(int argc, char** argv_in)
argc -= 2;
} else {
/* The option was not given an executable. */
- fprintf(stderr, "Option " KWSYS_SHARED_FORWARD_OPTION_COMMAND
- " must be followed by a command line.\n");
+ fprintf(stderr,
+ "Option " KWSYS_SHARED_FORWARD_OPTION_COMMAND
+ " must be followed by a command line.\n");
return 1;
}
}
-#endif
+# endif
-#if defined(KWSYS_SHARED_FORWARD_OPTION_PRINT)
+# if defined(KWSYS_SHARED_FORWARD_OPTION_PRINT)
/* Look for the print command line option. */
if (argc > 1 &&
strcmp(argv[1], KWSYS_SHARED_FORWARD_OPTION_PRINT) == 0) {
@@ -821,12 +824,12 @@ static int @KWSYS_NAMESPACE@_shared_forward_to_real(int argc, char** argv_in)
fprintf(stdout, "%s\n", exe);
return 0;
}
-#endif
+# endif
-#if defined(KWSYS_SHARED_FORWARD_OPTION_LDD)
+# if defined(KWSYS_SHARED_FORWARD_OPTION_LDD)
/* Look for the ldd command line option. */
if (argc > 1 && strcmp(argv[1], KWSYS_SHARED_FORWARD_OPTION_LDD) == 0) {
-#if defined(KWSYS_SHARED_FORWARD_LDD)
+# if defined(KWSYS_SHARED_FORWARD_LDD)
/* Use the named ldd-like executable and arguments. */
char const* ldd_argv[] = { KWSYS_SHARED_FORWARD_LDD, 0, 0 };
ldd_argv[KWSYS_SHARED_FORWARD_LDD_N] = exe;
@@ -835,13 +838,13 @@ static int @KWSYS_NAMESPACE@_shared_forward_to_real(int argc, char** argv_in)
/* Report why execution failed. */
kwsys_shared_forward_print_failure(ldd_argv);
return 1;
-#else
+# else
/* We have no ldd-like executable available on this platform. */
fprintf(stderr, "No ldd-like tool is known to this executable.\n");
return 1;
-#endif
+# endif
}
-#endif
+# endif
/* Replace this process with the real executable. */
argv[0] = exe;
@@ -865,12 +868,12 @@ static int @KWSYS_NAMESPACE@_shared_forward_to_real(int argc, char** argv_in)
}
/* Restore warning stack. */
-#if defined(__clang__) && defined(__has_warning)
-#if __has_warning("-Wcast-qual")
-#pragma clang diagnostic pop
-#endif
-#endif
+# if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wcast-qual")
+# pragma clang diagnostic pop
+# endif
+# endif
#else
-#error "@KWSYS_NAMESPACE@/SharedForward.h should be included only once."
+# error "@KWSYS_NAMESPACE@/SharedForward.h should be included only once."
#endif
diff --git a/Source/kwsys/String.c b/Source/kwsys/String.c
index 048222968..daf7ad1a0 100644
--- a/Source/kwsys/String.c
+++ b/Source/kwsys/String.c
@@ -8,23 +8,23 @@ directory that use the stl string cause the compiler to load this
source to try to get the definition of the string template. This
condition blocks the compiler from seeing the symbols defined here.
*/
-#include "kwsysPrivate.h"
-#include KWSYS_HEADER(String.h)
+# include "kwsysPrivate.h"
+# include KWSYS_HEADER(String.h)
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
-#if 0
-#include "String.h.in"
-#endif
+# if 0
+# include "String.h.in"
+# endif
/* Select an implementation for strcasecmp. */
-#if defined(_MSC_VER)
-#define KWSYS_STRING_USE_STRICMP
-#include <string.h>
-#elif defined(__GNUC__)
-#define KWSYS_STRING_USE_STRCASECMP
-#include <strings.h>
-#else
+# if defined(_MSC_VER)
+# define KWSYS_STRING_USE_STRICMP
+# include <string.h>
+# elif defined(__GNUC__)
+# define KWSYS_STRING_USE_STRCASECMP
+# include <strings.h>
+# else
/* Table to convert upper case letters to lower case and leave all
other characters alone. */
static char kwsysString_strcasecmp_tolower[] = {
@@ -58,16 +58,16 @@ static char kwsysString_strcasecmp_tolower[] = {
'\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373',
'\374', '\375', '\376', '\377'
};
-#endif
+# endif
/*--------------------------------------------------------------------------*/
int kwsysString_strcasecmp(const char* lhs, const char* rhs)
{
-#if defined(KWSYS_STRING_USE_STRICMP)
+# if defined(KWSYS_STRING_USE_STRICMP)
return _stricmp(lhs, rhs);
-#elif defined(KWSYS_STRING_USE_STRCASECMP)
+# elif defined(KWSYS_STRING_USE_STRCASECMP)
return strcasecmp(lhs, rhs);
-#else
+# else
const char* const lower = kwsysString_strcasecmp_tolower;
unsigned char const* us1 = (unsigned char const*)lhs;
unsigned char const* us2 = (unsigned char const*)rhs;
@@ -75,17 +75,17 @@ int kwsysString_strcasecmp(const char* lhs, const char* rhs)
while ((result = lower[*us1] - lower[*us2++], result == 0) && *us1++) {
}
return result;
-#endif
+# endif
}
/*--------------------------------------------------------------------------*/
int kwsysString_strncasecmp(const char* lhs, const char* rhs, size_t n)
{
-#if defined(KWSYS_STRING_USE_STRICMP)
+# if defined(KWSYS_STRING_USE_STRICMP)
return _strnicmp(lhs, rhs, n);
-#elif defined(KWSYS_STRING_USE_STRCASECMP)
+# elif defined(KWSYS_STRING_USE_STRCASECMP)
return strncasecmp(lhs, rhs, n);
-#else
+# else
const char* const lower = kwsysString_strcasecmp_tolower;
unsigned char const* us1 = (unsigned char const*)lhs;
unsigned char const* us2 = (unsigned char const*)rhs;
@@ -94,7 +94,7 @@ int kwsysString_strncasecmp(const char* lhs, const char* rhs, size_t n)
--n;
}
return result;
-#endif
+# endif
}
#endif /* KWSYS_STRING_C */
diff --git a/Source/kwsys/String.h.in b/Source/kwsys/String.h.in
index 3c1d571c0..7c9348af1 100644
--- a/Source/kwsys/String.h.in
+++ b/Source/kwsys/String.h.in
@@ -12,12 +12,12 @@
not visible to user code. Use kwsysHeaderDump.pl to reproduce
these macros after making changes to the interface. */
#if !defined(KWSYS_NAMESPACE)
-#define kwsys_ns(x) @KWSYS_NAMESPACE@##x
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsysString_strcasecmp kwsys_ns(String_strcasecmp)
-#define kwsysString_strncasecmp kwsys_ns(String_strncasecmp)
+# define kwsysString_strcasecmp kwsys_ns(String_strcasecmp)
+# define kwsysString_strncasecmp kwsys_ns(String_strncasecmp)
#endif
#if defined(__cplusplus)
@@ -46,12 +46,12 @@ kwsysEXPORT int kwsysString_strncasecmp(const char* lhs, const char* rhs,
/* If we are building a kwsys .c or .cxx file, let it use these macros.
Otherwise, undefine them to keep the namespace clean. */
#if !defined(KWSYS_NAMESPACE)
-#undef kwsys_ns
-#undef kwsysEXPORT
-#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#undef kwsysString_strcasecmp
-#undef kwsysString_strncasecmp
-#endif
+# undef kwsys_ns
+# undef kwsysEXPORT
+# if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# undef kwsysString_strcasecmp
+# undef kwsysString_strncasecmp
+# endif
#endif
#endif
diff --git a/Source/kwsys/System.c b/Source/kwsys/System.c
index b9af8e9d9..d43cc6fbb 100644
--- a/Source/kwsys/System.c
+++ b/Source/kwsys/System.c
@@ -6,7 +6,7 @@
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "System.h.in"
+# include "System.h.in"
#endif
#include <ctype.h> /* isspace */
diff --git a/Source/kwsys/System.h.in b/Source/kwsys/System.h.in
index 102974db7..a9d4f5e69 100644
--- a/Source/kwsys/System.h.in
+++ b/Source/kwsys/System.h.in
@@ -10,11 +10,12 @@
not visible to user code. Use kwsysHeaderDump.pl to reproduce
these macros after making changes to the interface. */
#if !defined(KWSYS_NAMESPACE)
-#define kwsys_ns(x) @KWSYS_NAMESPACE@##x
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsysSystem_Parse_CommandForUnix kwsys_ns(System_Parse_CommandForUnix)
+# define kwsysSystem_Parse_CommandForUnix \
+ kwsys_ns(System_Parse_CommandForUnix)
#endif
#if defined(__cplusplus)
@@ -49,11 +50,11 @@ kwsysEXPORT char** kwsysSystem_Parse_CommandForUnix(const char* command,
/* If we are building a kwsys .c or .cxx file, let it use these macros.
Otherwise, undefine them to keep the namespace clean. */
#if !defined(KWSYS_NAMESPACE)
-#undef kwsys_ns
-#undef kwsysEXPORT
-#if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#undef kwsysSystem_Parse_CommandForUnix
-#endif
+# undef kwsys_ns
+# undef kwsysEXPORT
+# if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# undef kwsysSystem_Parse_CommandForUnix
+# endif
#endif
#endif
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index 86fdccdc7..6ec6e48ff 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -1,15 +1,18 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#if defined(_WIN32)
-#define NOMINMAX // use our min,max
-#if !defined(_WIN32_WINNT) && !(defined(_MSC_VER) && _MSC_VER < 1300)
-#define _WIN32_WINNT 0x0501
-#endif
-#include <winsock.h> // WSADATA, include before sys/types.h
+# define NOMINMAX // use our min,max
+# if !defined(_WIN32_WINNT) && defined(_MSC_VER) && _MSC_VER >= 1800
+# define _WIN32_WINNT 0x0600 // vista
+# endif
+# if !defined(_WIN32_WINNT) && !(defined(_MSC_VER) && _MSC_VER < 1300)
+# define _WIN32_WINNT 0x0501
+# endif
+# include <winsock.h> // WSADATA, include before sys/types.h
#endif
#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
-#define _GNU_SOURCE
+# define _GNU_SOURCE
#endif
// TODO:
@@ -31,8 +34,8 @@
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Process.h.in"
-#include "SystemInformation.hxx.in"
+# include "Process.h.in"
+# include "SystemInformation.hxx.in"
#endif
#include <algorithm>
@@ -47,114 +50,117 @@
#include <vector>
#if defined(_WIN32)
-#include <windows.h>
-#if defined(_MSC_VER) && _MSC_VER >= 1800
-#define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#endif
-#include <errno.h>
-#if defined(KWSYS_SYS_HAS_PSAPI)
-#include <psapi.h>
-#endif
-#if !defined(siginfo_t)
+# include <windows.h>
+# if defined(_MSC_VER) && _MSC_VER >= 1800
+# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# endif
+# include <errno.h>
+# if defined(KWSYS_SYS_HAS_PSAPI)
+# include <psapi.h>
+# endif
+# if !defined(siginfo_t)
typedef int siginfo_t;
-#endif
+# endif
#else
-#include <sys/types.h>
-
-#include <errno.h> // extern int errno;
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/resource.h> // getrlimit
-#include <sys/time.h>
-#include <sys/utsname.h> // int uname(struct utsname *buf);
-#include <unistd.h>
+# include <sys/types.h>
+
+# include <errno.h> // extern int errno;
+# include <fcntl.h>
+# include <signal.h>
+# include <sys/resource.h> // getrlimit
+# include <sys/time.h>
+# include <sys/utsname.h> // int uname(struct utsname *buf);
+# include <unistd.h>
#endif
#if defined(__CYGWIN__) && !defined(_WIN32)
-#include <windows.h>
-#undef _WIN32
+# include <windows.h>
+# undef _WIN32
#endif
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
defined(__DragonFly__)
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#if defined(KWSYS_SYS_HAS_IFADDRS_H)
-#include <ifaddrs.h>
-#include <net/if.h>
-#define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
-#endif
+# include <netdb.h>
+# include <netinet/in.h>
+# include <sys/param.h>
+# include <sys/socket.h>
+# include <sys/sysctl.h>
+# if defined(KWSYS_SYS_HAS_IFADDRS_H)
+# include <ifaddrs.h>
+# include <net/if.h>
+# define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
+# endif
#endif
#if defined(KWSYS_SYS_HAS_MACHINE_CPU_H)
-#include <machine/cpu.h>
+# include <machine/cpu.h>
#endif
#ifdef __APPLE__
-#include <fenv.h>
-#include <mach/host_info.h>
-#include <mach/mach.h>
-#include <mach/mach_types.h>
-#include <mach/vm_statistics.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#if defined(KWSYS_SYS_HAS_IFADDRS_H)
-#include <ifaddrs.h>
-#include <net/if.h>
-#define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
-#endif
-#if !(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ - 0 >= 1050)
-#undef KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE
-#endif
-#endif
-
-#if defined(__linux) || defined(__sun) || defined(_SCO_DS)
-#include <fenv.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#if defined(KWSYS_SYS_HAS_IFADDRS_H)
-#include <ifaddrs.h>
-#include <net/if.h>
-#if !defined(__LSB_VERSION__) /* LSB has no getifaddrs */
-#define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
-#endif
-#endif
-#if defined(KWSYS_CXX_HAS_RLIMIT64)
+# include <mach/host_info.h>
+# include <mach/mach.h>
+# include <mach/mach_types.h>
+# include <mach/vm_statistics.h>
+# include <netdb.h>
+# include <netinet/in.h>
+# include <sys/socket.h>
+# include <sys/sysctl.h>
+# if defined(KWSYS_SYS_HAS_IFADDRS_H)
+# include <ifaddrs.h>
+# include <net/if.h>
+# define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
+# endif
+# if !(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ - 0 >= 1050)
+# undef KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE
+# endif
+#endif
+
+#if defined(__linux) || defined(__sun) || defined(_SCO_DS) || \
+ defined(__GLIBC__) || defined(__GNU__)
+# include <netdb.h>
+# include <netinet/in.h>
+# include <sys/socket.h>
+# if defined(KWSYS_SYS_HAS_IFADDRS_H)
+# include <ifaddrs.h>
+# include <net/if.h>
+# 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
+# if defined(KWSYS_CXX_HAS_RLIMIT64)
typedef struct rlimit64 ResourceLimitType;
-#define GetResourceLimit getrlimit64
-#else
+# define GetResourceLimit getrlimit64
+# else
typedef struct rlimit ResourceLimitType;
-#define GetResourceLimit getrlimit
-#endif
+# define GetResourceLimit getrlimit
+# endif
#elif defined(__hpux)
-#include <sys/param.h>
-#include <sys/pstat.h>
-#if defined(KWSYS_SYS_HAS_MPCTL_H)
-#include <sys/mpctl.h>
-#endif
+# include <sys/param.h>
+# include <sys/pstat.h>
+# if defined(KWSYS_SYS_HAS_MPCTL_H)
+# include <sys/mpctl.h>
+# endif
#endif
#ifdef __HAIKU__
-#include <OS.h>
+# include <OS.h>
#endif
#if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
-#include <execinfo.h>
-#if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
-#include <cxxabi.h>
-#endif
-#if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
-#include <dlfcn.h>
-#endif
+# include <execinfo.h>
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
+# include <cxxabi.h>
+# endif
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+# include <dlfcn.h>
+# endif
#else
-#undef KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE
-#undef KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP
+# undef KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE
+# undef KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP
#endif
#include <ctype.h> // int isdigit(int c);
@@ -164,57 +170,57 @@ typedef struct rlimit ResourceLimitType;
#include <string.h>
#if defined(KWSYS_USE_LONG_LONG)
-#if defined(KWSYS_IOS_HAS_OSTREAM_LONG_LONG)
-#define iostreamLongLong(x) (x)
-#else
-#define iostreamLongLong(x) ((long)(x))
-#endif
+# if defined(KWSYS_IOS_HAS_OSTREAM_LONG_LONG)
+# define iostreamLongLong(x) (x)
+# else
+# define iostreamLongLong(x) ((long)(x))
+# endif
#elif defined(KWSYS_USE___INT64)
-#if defined(KWSYS_IOS_HAS_OSTREAM___INT64)
-#define iostreamLongLong(x) (x)
+# if defined(KWSYS_IOS_HAS_OSTREAM___INT64)
+# define iostreamLongLong(x) (x)
+# else
+# define iostreamLongLong(x) ((long)(x))
+# endif
#else
-#define iostreamLongLong(x) ((long)(x))
-#endif
-#else
-#error "No Long Long"
+# error "No Long Long"
#endif
#if defined(KWSYS_CXX_HAS_ATOLL)
-#define atoLongLong atoll
-#else
-#if defined(KWSYS_CXX_HAS__ATOI64)
-#define atoLongLong _atoi64
-#elif defined(KWSYS_CXX_HAS_ATOL)
-#define atoLongLong atol
+# define atoLongLong atoll
#else
-#define atoLongLong atoi
-#endif
+# if defined(KWSYS_CXX_HAS__ATOI64)
+# define atoLongLong _atoi64
+# elif defined(KWSYS_CXX_HAS_ATOL)
+# define atoLongLong atol
+# else
+# define atoLongLong atoi
+# endif
#endif
#if defined(_MSC_VER) && (_MSC_VER >= 1300) && !defined(_WIN64) && \
!defined(__clang__)
-#define USE_ASM_INSTRUCTIONS 1
+# define USE_ASM_INSTRUCTIONS 1
#else
-#define USE_ASM_INSTRUCTIONS 0
+# define USE_ASM_INSTRUCTIONS 0
#endif
#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__clang__)
-#include <intrin.h>
-#define USE_CPUID_INTRINSICS 1
+# include <intrin.h>
+# define USE_CPUID_INTRINSICS 1
#else
-#define USE_CPUID_INTRINSICS 0
+# define USE_CPUID_INTRINSICS 0
#endif
#if USE_ASM_INSTRUCTIONS || USE_CPUID_INTRINSICS || \
defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
-#define USE_CPUID 1
+# define USE_CPUID 1
#else
-#define USE_CPUID 0
+# define USE_CPUID 0
#endif
#if USE_CPUID
-#define CPUID_AWARE_COMPILER
+# define CPUID_AWARE_COMPILER
/**
* call CPUID instruction
@@ -223,16 +229,16 @@ typedef struct rlimit ResourceLimitType;
*/
static bool call_cpuid(int select, int result[4])
{
-#if USE_CPUID_INTRINSICS
+# if USE_CPUID_INTRINSICS
__cpuid(result, select);
return true;
-#else
+# else
int tmp[4];
-#if defined(_MSC_VER)
+# if defined(_MSC_VER)
// Use SEH to determine CPUID presence
__try {
_asm {
-#ifdef CPUID_AWARE_COMPILER
+# ifdef CPUID_AWARE_COMPILER
; we must push/pop the registers <<CPUID>> writes to, as the
; optimiser does not know about <<CPUID>>, and so does not expect
; these registers to change.
@@ -240,33 +246,33 @@ static bool call_cpuid(int select, int result[4])
push ebx
push ecx
push edx
-#endif
+# endif
; <<CPUID>>
mov eax, select
-#ifdef CPUID_AWARE_COMPILER
+# ifdef CPUID_AWARE_COMPILER
cpuid
-#else
+# else
_asm _emit 0x0f
_asm _emit 0xa2
-#endif
+# endif
mov tmp[0 * TYPE int], eax
mov tmp[1 * TYPE int], ebx
mov tmp[2 * TYPE int], ecx
mov tmp[3 * TYPE int], edx
-#ifdef CPUID_AWARE_COMPILER
+# ifdef CPUID_AWARE_COMPILER
pop edx
pop ecx
pop ebx
pop eax
-#endif
+# endif
}
} __except (1) {
return false;
}
memcpy(result, tmp, sizeof(tmp));
-#elif defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
+# elif defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
unsigned int a, b, c, d;
__asm {
mov EAX, select;
@@ -281,11 +287,11 @@ static bool call_cpuid(int select, int result[4])
result[1] = b;
result[2] = c;
result[3] = d;
-#endif
+# endif
// The cpuid instruction succeeded.
return true;
-#endif
+# endif
}
#endif
@@ -340,7 +346,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 +354,7 @@ public:
LongLong GetProcessId();
- // Retrieve memory information in kib
+ // Retrieve memory information in KiB.
LongLong GetHostMemoryTotal();
LongLong GetHostMemoryAvailable(const char* envVarName);
LongLong GetHostMemoryUsed();
@@ -441,6 +447,7 @@ public:
IBM,
Motorola,
HP,
+ Hygon,
UnknownManufacturer
};
@@ -736,7 +743,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();
@@ -840,31 +847,16 @@ void SystemInformation::RunMemoryCheck()
// SystemInformationImplementation starts here
-#define STORE_TLBCACHE_INFO(x, y) x = (x < (y)) ? (y) : x
-#define TLBCACHE_INFO_UNITS (15)
-#define CLASSICAL_CPU_FREQ_LOOP 10000000
-#define RDTSC_INSTRUCTION _asm _emit 0x0f _asm _emit 0x31
-
-// Status Flag
-#define HT_NOT_CAPABLE 0
-#define HT_ENABLED 1
-#define HT_DISABLED 2
-#define HT_SUPPORTED_NOT_ENABLED 3
-#define HT_CANNOT_DETECT 4
-
-// EDX[28] Bit 28 is set if HT is supported
-#define HT_BIT 0x10000000
-
-// EAX[11:8] Bit 8-11 contains family processor ID.
-#define FAMILY_ID 0x0F00
-#define PENTIUM4_ID 0x0F00
-// EAX[23:20] Bit 20-23 contains extended family processor ID
-#define EXT_FAMILY_ID 0x0F00000
-// EBX[23:16] Bit 16-23 in ebx contains the number of logical
-#define NUM_LOGICAL_BITS 0x00FF0000
-// processors per physical processor when execute cpuid with
-// eax set to 1
-// EBX[31:24] Bits 24-31 (8 bits) return the 8-bit unique
+#if USE_CPUID
+# define STORE_TLBCACHE_INFO(x, y) x = (x < (y)) ? (y) : x
+# define TLBCACHE_INFO_UNITS (15)
+#endif
+
+#if USE_ASM_INSTRUCTIONS
+# define CLASSICAL_CPU_FREQ_LOOP 10000000
+# define RDTSC_INSTRUCTION _asm _emit 0x0f _asm _emit 0x31
+#endif
+
#define INITIAL_APIC_ID_BITS 0xFF000000
// initial APIC ID for the processor this code is running on.
// Default value = 0xff if HT is not supported
@@ -881,7 +873,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) == nullptr) {
if (ferror(file) && (errno == EINTR)) {
clearerr(file);
}
@@ -902,7 +894,7 @@ int LoadLines(FILE* file, std::vector<std::string>& lines)
return nRead;
}
-#if defined(__linux)
+# if defined(__linux)
// *****************************************************************************
int LoadLines(const char* fileName, std::vector<std::string>& lines)
{
@@ -914,7 +906,7 @@ int LoadLines(const char* fileName, std::vector<std::string>& lines)
fclose(file);
return nRead;
}
-#endif
+# endif
// ****************************************************************************
template <typename T>
@@ -945,7 +937,7 @@ int GetFieldsFromFile(const char* fileName, const char** fieldNames, T* values)
return -1;
}
int i = 0;
- while (fieldNames[i] != NULL) {
+ while (fieldNames[i] != nullptr) {
int ierr = NameValue(fields, fieldNames[i], values[i]);
if (ierr) {
return -(i + 2);
@@ -959,7 +951,7 @@ int GetFieldsFromFile(const char* fileName, const char** fieldNames, T* values)
template <typename T>
int GetFieldFromFile(const char* fileName, const char* fieldName, T& value)
{
- const char* fieldNames[2] = { fieldName, NULL };
+ const char* fieldNames[2] = { fieldName, nullptr };
T values[1] = { T(0) };
int ierr = GetFieldsFromFile(fileName, fieldNames, values);
if (ierr) {
@@ -977,7 +969,7 @@ int GetFieldsFromCommand(const char* command, const char** fieldNames,
T* values)
{
FILE* file = popen(command, "r");
- if (file == 0) {
+ if (file == nullptr) {
return -1;
}
std::vector<std::string> fields;
@@ -987,7 +979,7 @@ int GetFieldsFromCommand(const char* command, const char** fieldNames,
return -1;
}
int i = 0;
- while (fieldNames[i] != NULL) {
+ while (fieldNames[i] != nullptr) {
int ierr = NameValue(fields, fieldNames[i], values[i]);
if (ierr) {
return -(i + 2);
@@ -1003,7 +995,7 @@ int GetFieldsFromCommand(const char* command, const char** fieldNames,
void StacktraceSignalHandler(int sigNo, siginfo_t* sigInfo,
void* /*sigContext*/)
{
-#if defined(__linux) || defined(__APPLE__)
+# if defined(__linux) || defined(__APPLE__)
std::ostringstream oss;
oss << std::endl
<< "========================================================="
@@ -1023,20 +1015,20 @@ 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 == nullptr ? "0x" : "")
<< sigInfo->si_addr << " ";
switch (sigInfo->si_code) {
-#if defined(FPE_INTDIV)
+# if defined(FPE_INTDIV)
case FPE_INTDIV:
oss << "integer division by zero";
break;
-#endif
+# endif
-#if defined(FPE_INTOVF)
+# if defined(FPE_INTOVF)
case FPE_INTOVF:
oss << "integer overflow";
break;
-#endif
+# endif
case FPE_FLTDIV:
oss << "floating point divide by zero";
@@ -1058,11 +1050,11 @@ void StacktraceSignalHandler(int sigNo, siginfo_t* sigInfo,
oss << "floating point invalid operation";
break;
-#if defined(FPE_FLTSUB)
+# if defined(FPE_FLTSUB)
case FPE_FLTSUB:
oss << "floating point subscript out of range";
break;
-#endif
+# endif
default:
oss << "code " << sigInfo->si_code;
@@ -1071,7 +1063,7 @@ 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 == nullptr ? "0x" : "")
<< sigInfo->si_addr << " ";
switch (sigInfo->si_code) {
case SEGV_MAPERR:
@@ -1089,38 +1081,38 @@ 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 == nullptr ? "0x" : "")
<< sigInfo->si_addr << " ";
switch (sigInfo->si_code) {
case BUS_ADRALN:
oss << "invalid address alignment";
break;
-#if defined(BUS_ADRERR)
+# if defined(BUS_ADRERR)
case BUS_ADRERR:
oss << "nonexistent physical address";
break;
-#endif
+# endif
-#if defined(BUS_OBJERR)
+# if defined(BUS_OBJERR)
case BUS_OBJERR:
oss << "object-specific hardware error";
break;
-#endif
+# endif
-#if defined(BUS_MCEERR_AR)
+# if defined(BUS_MCEERR_AR)
case BUS_MCEERR_AR:
oss << "Hardware memory error consumed on a machine check; action "
"required.";
break;
-#endif
+# endif
-#if defined(BUS_MCEERR_AO)
+# if defined(BUS_MCEERR_AO)
case BUS_MCEERR_AO:
oss << "Hardware memory error detected in process but not consumed; "
"action optional.";
break;
-#endif
+# endif
default:
oss << "code " << sigInfo->si_code;
@@ -1129,24 +1121,24 @@ 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 == nullptr ? "0x" : "")
<< sigInfo->si_addr << " ";
switch (sigInfo->si_code) {
case ILL_ILLOPC:
oss << "illegal opcode";
break;
-#if defined(ILL_ILLOPN)
+# if defined(ILL_ILLOPN)
case ILL_ILLOPN:
oss << "illegal operand";
break;
-#endif
+# endif
-#if defined(ILL_ILLADR)
+# if defined(ILL_ILLADR)
case ILL_ILLADR:
oss << "illegal addressing mode.";
break;
-#endif
+# endif
case ILL_ILLTRP:
oss << "illegal trap";
@@ -1156,23 +1148,23 @@ void StacktraceSignalHandler(int sigNo, siginfo_t* sigInfo,
oss << "privileged opcode";
break;
-#if defined(ILL_PRVREG)
+# if defined(ILL_PRVREG)
case ILL_PRVREG:
oss << "privileged register";
break;
-#endif
+# endif
-#if defined(ILL_COPROC)
+# if defined(ILL_COPROC)
case ILL_COPROC:
oss << "co-processor error";
break;
-#endif
+# endif
-#if defined(ILL_BADSTK)
+# if defined(ILL_BADSTK)
case ILL_BADSTK:
oss << "internal stack error";
break;
-#endif
+# endif
default:
oss << "code " << sigInfo->si_code;
@@ -1195,16 +1187,16 @@ void StacktraceSignalHandler(int sigNo, siginfo_t* sigInfo,
// and abort
SystemInformationImplementation::SetStackTraceOnError(0);
abort();
-#else
+# else
// avoid warning C4100
(void)sigNo;
(void)sigInfo;
-#endif
+# endif
}
#endif
#if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
-#define safes(_arg) ((_arg) ? (_arg) : "???")
+# define safes(_arg) ((_arg) ? (_arg) : "???")
// Description:
// A container for symbol properties. Each instance
@@ -1264,7 +1256,7 @@ public:
long GetLineNumber() const { return this->LineNumber; }
// Description:
- // Set the address where the biinary image is mapped
+ // Set the address where the binary image is mapped
// into memory.
void SetBinaryBaseAddress(void* address)
{
@@ -1292,19 +1284,19 @@ private:
std::ostream& operator<<(std::ostream& os, const SymbolProperties& sp)
{
-#if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
os << std::hex << sp.GetAddress() << " : " << sp.GetFunction() << " [("
<< sp.GetBinary() << ") " << sp.GetSourceFile() << ":" << std::dec
<< sp.GetLineNumber() << "]";
-#elif defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
+# elif defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
void* addr = sp.GetAddress();
char** syminfo = backtrace_symbols(&addr, 1);
os << safes(syminfo[0]);
free(syminfo);
-#else
+# else
(void)os;
(void)sp;
-#endif
+# endif
return os;
}
@@ -1313,8 +1305,8 @@ SymbolProperties::SymbolProperties()
// not using an initializer list
// to avoid some PGI compiler warnings
this->SetBinary("???");
- this->SetBinaryBaseAddress(NULL);
- this->Address = NULL;
+ this->SetBinaryBaseAddress(nullptr);
+ this->Address = nullptr;
this->SetSourceFile("???");
this->SetFunction("???");
this->SetLineNumber(-1);
@@ -1341,12 +1333,12 @@ std::string SymbolProperties::GetFileName(const std::string& path) const
std::string SymbolProperties::GetBinary() const
{
// only linux has proc fs
-#if defined(__linux__)
+# if defined(__linux__)
if (this->Binary == "/proc/self/exe") {
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 {
@@ -1354,14 +1346,14 @@ std::string SymbolProperties::GetBinary() const
}
return this->GetFileName(binary);
}
-#endif
+# endif
return this->GetFileName(this->Binary);
}
std::string SymbolProperties::Demangle(const char* symbol) const
{
std::string result = safes(symbol);
-#if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
int status = 0;
size_t bufferLen = 1024;
char* buffer = (char*)malloc(1024);
@@ -1371,16 +1363,16 @@ std::string SymbolProperties::Demangle(const char* symbol) const
result = demangledSymbol;
}
free(buffer);
-#else
+# else
(void)symbol;
-#endif
+# endif
return result;
}
void SymbolProperties::Initialize(void* address)
{
this->Address = address;
-#if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
// first fallback option can demangle c++ functions
Dl_info info;
int ierr = dladdr(this->Address, &info);
@@ -1388,18 +1380,18 @@ void SymbolProperties::Initialize(void* address)
this->SetBinary(info.dli_fname);
this->SetFunction(info.dli_sname);
}
-#else
+# else
// second fallback use builtin backtrace_symbols
// to decode the bactrace.
-#endif
+# endif
}
#endif // don't define this class if we're not using it
#if defined(_WIN32) || defined(__CYGWIN__)
-#define KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes
+# define KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes
#endif
#if defined(_MSC_VER) && _MSC_VER < 1310
-#undef KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes
+# undef KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes
#endif
#if defined(KWSYS_SYSTEMINFORMATION_USE_GetSystemTimes)
double calculateCPULoad(unsigned __int64 idleTicks,
@@ -1649,7 +1641,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 +1663,7 @@ int SystemInformationImplementation::GetFullyQualifiedDomainName(
return -2;
}
- for (ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) {
+ for (ifa = ifas; ifa != 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 +1674,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, 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.
@@ -1759,6 +1751,8 @@ const char* SystemInformationImplementation::GetVendorID()
return "Motorola";
case HP:
return "Hewlett-Packard";
+ case Hygon:
+ return "Chengdu Haiguang IC Design Co., Ltd.";
case UnknownManufacturer:
default:
return "Unknown Manufacturer";
@@ -2004,12 +1998,12 @@ bool SystemInformationImplementation::DoesCPUSupportCPUID()
#if USE_CPUID
int dummy[4] = { 0, 0, 0, 0 };
-#if USE_ASM_INSTRUCTIONS
+# if USE_ASM_INSTRUCTIONS
return call_cpuid(0, dummy);
-#else
+# else
call_cpuid(0, dummy);
return dummy[0] || dummy[1] || dummy[2] || dummy[3];
-#endif
+# endif
#else
// Assume no cpuid instruction.
return false;
@@ -2051,7 +2045,7 @@ bool SystemInformationImplementation::RetrieveCPUFeatures()
this->Features.HasIA64 =
((cpuinfo[3] & 0x40000000) != 0); // IA64 Present --> Bit 30
-#if USE_ASM_INSTRUCTIONS
+# if USE_ASM_INSTRUCTIONS
// Retrieve extended SSE capabilities if SSE is available.
if (this->Features.HasSSE) {
@@ -2075,9 +2069,9 @@ bool SystemInformationImplementation::RetrieveCPUFeatures()
// Set the advanced SSE capabilities to not available.
this->Features.HasSSEFP = false;
}
-#else
+# else
this->Features.HasSSEFP = false;
-#endif
+# endif
// Retrieve Intel specific extended features.
if (this->ChipManufacturer == Intel) {
@@ -2110,6 +2104,8 @@ void SystemInformationImplementation::FindManufacturer(
this->ChipManufacturer = AMD; // Advanced Micro Devices
else if (this->ChipID.Vendor == "AMD ISBETTER")
this->ChipManufacturer = AMD; // Advanced Micro Devices (1994)
+ else if (this->ChipID.Vendor == "HygonGenuine")
+ this->ChipManufacturer = Hygon; // Chengdu Haiguang IC Design Co., Ltd.
else if (this->ChipID.Vendor == "CyrixInstead")
this->ChipManufacturer = Cyrix; // Cyrix Corp., VIA Inc.
else if (this->ChipID.Vendor == "NexGenDriven")
@@ -2562,7 +2558,7 @@ bool SystemInformationImplementation::RetrieveCPUClockSpeed()
// If RDTSC is not supported, we fallback to trying to read this value
// from the registry:
if (!retrieved) {
- HKEY hKey = NULL;
+ HKEY hKey = nullptr;
LONG err =
RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0,
@@ -2582,7 +2578,7 @@ bool SystemInformationImplementation::RetrieveCPUClockSpeed()
}
RegCloseKey(hKey);
- hKey = NULL;
+ hKey = nullptr;
}
}
#endif
@@ -2744,7 +2740,7 @@ bool SystemInformationImplementation::RetrieveExtendedCPUFeatures()
0); // MP Capable -- > Bit 19.
// Retrieve AMD specific extended features.
- if (this->ChipManufacturer == AMD) {
+ if (this->ChipManufacturer == AMD || this->ChipManufacturer == Hygon) {
this->Features.ExtendedFeatures.HasMMXPlus =
((localCPUExtendedFeatures[3] & 0x00400000) !=
0); // AMD specific: MMX-SSE --> Bit 22
@@ -3151,6 +3147,10 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
}
break;
+ case Hygon:
+ this->ChipID.ProcessorName = "Unknown Hygon family";
+ return false;
+
case Transmeta:
switch (this->ChipID.Family) {
case 5:
@@ -3489,7 +3489,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
// Chip Model Name
this->ChipID.ModelName =
- this->ExtractValueFromCpuInfoFile(buffer, "model name").c_str();
+ this->ExtractValueFromCpuInfoFile(buffer, "model name");
// L1 Cache size
// Different architectures may show different names for the caches.
@@ -3558,7 +3558,7 @@ bool SystemInformationImplementation::QueryProcessorBySysconf()
{
#if defined(_SC_NPROC_ONLN) && !defined(_SC_NPROCESSORS_ONLN)
// IRIX names this slightly different
-#define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN
+# define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN
#endif
#ifdef _SC_NPROCESSORS_ONLN
@@ -3588,17 +3588,17 @@ SystemInformation::LongLong
SystemInformationImplementation::GetHostMemoryTotal()
{
#if defined(_WIN32)
-#if defined(_MSC_VER) && _MSC_VER < 1300
+# if defined(_MSC_VER) && _MSC_VER < 1300
MEMORYSTATUS stat;
stat.dwLength = sizeof(stat);
GlobalMemoryStatus(&stat);
return stat.dwTotalPhys / 1024;
-#else
+# else
MEMORYSTATUSEX statex;
statex.dwLength = sizeof(statex);
GlobalMemoryStatusEx(&statex);
return statex.ullTotalPhys / 1024;
-#endif
+# endif
#elif defined(__linux)
SystemInformation::LongLong memTotal = 0;
int ierr = GetFieldFromFile("/proc/meminfo", "MemTotal:", memTotal);
@@ -3609,7 +3609,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, nullptr, 0);
if (ierr) {
return -1;
}
@@ -3633,7 +3633,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);
@@ -3713,25 +3713,25 @@ SystemInformation::LongLong
SystemInformationImplementation::GetHostMemoryUsed()
{
#if defined(_WIN32)
-#if defined(_MSC_VER) && _MSC_VER < 1300
+# if defined(_MSC_VER) && _MSC_VER < 1300
MEMORYSTATUS stat;
stat.dwLength = sizeof(stat);
GlobalMemoryStatus(&stat);
return (stat.dwTotalPhys - stat.dwAvailPhys) / 1024;
-#else
+# else
MEMORYSTATUSEX statex;
statex.dwLength = sizeof(statex);
GlobalMemoryStatusEx(&statex);
return (statex.ullTotalPhys - statex.ullAvailPhys) / 1024;
-#endif
+# endif
#elif defined(__linux)
// First try to use MemAvailable, but it only works on newer kernels
- const char* names2[3] = { "MemTotal:", "MemAvailable:", NULL };
+ const char* names2[3] = { "MemTotal:", "MemAvailable:", nullptr };
SystemInformation::LongLong values2[2] = { SystemInformation::LongLong(0) };
int ierr = GetFieldsFromFile("/proc/meminfo", names2, values2);
if (ierr) {
const char* names4[5] = { "MemTotal:", "MemFree:", "Buffers:", "Cached:",
- NULL };
+ nullptr };
SystemInformation::LongLong values4[4] = { SystemInformation::LongLong(
0) };
ierr = GetFieldsFromFile("/proc/meminfo", names4, values4);
@@ -3752,7 +3752,7 @@ 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:", nullptr };
SystemInformation::LongLong values[2] = { SystemInformation::LongLong(0) };
int ierr = GetFieldsFromCommand("vm_stat", names, values);
if (ierr) {
@@ -3800,7 +3800,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 == nullptr) {
return -1;
}
oss.str("");
@@ -3863,7 +3863,8 @@ SystemInformation::LongLong SystemInformationImplementation::GetProcessId()
{
#if defined(_WIN32)
return GetCurrentProcessId();
-#elif defined(__linux) || defined(__APPLE__)
+#elif defined(__linux) || defined(__APPLE__) || defined(__OpenBSD__) || \
+ defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
return getpid();
#else
return -1;
@@ -3871,34 +3872,78 @@ SystemInformation::LongLong SystemInformationImplementation::GetProcessId()
}
/**
+ * Used in GetProgramStack(...) below
+ */
+#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 && defined(_MSC_VER) && \
+ _MSC_VER >= 1800
+# define KWSYS_SYSTEMINFORMATION_HAS_DBGHELP
+# define TRACE_MAX_STACK_FRAMES 1024
+# define TRACE_MAX_FUNCTION_NAME_LENGTH 1024
+# pragma warning(push)
+# pragma warning(disable : 4091) /* 'typedef ': ignored on left of '' */
+# include "dbghelp.h"
+# pragma warning(pop)
+#endif
+
+/**
return current program stack in a string
demangle cxx symbols if possible.
*/
std::string SystemInformationImplementation::GetProgramStack(int firstFrame,
int wholePath)
{
- std::string programStack = ""
-#if !defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
- "WARNING: The stack could not be examined "
- "because backtrace is not supported.\n"
-#elif !defined(KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD)
- "WARNING: The stack trace will not use advanced "
- "capabilities because this is a release build.\n"
+ std::ostringstream oss;
+ std::string programStack = "";
+
+#ifdef KWSYS_SYSTEMINFORMATION_HAS_DBGHELP
+ (void)wholePath;
+
+ void* stack[TRACE_MAX_STACK_FRAMES];
+ HANDLE process = GetCurrentProcess();
+ SymInitialize(process, nullptr, TRUE);
+ WORD numberOfFrames =
+ CaptureStackBackTrace(firstFrame, TRACE_MAX_STACK_FRAMES, stack, nullptr);
+ SYMBOL_INFO* symbol = static_cast<SYMBOL_INFO*>(
+ malloc(sizeof(SYMBOL_INFO) +
+ (TRACE_MAX_FUNCTION_NAME_LENGTH - 1) * sizeof(TCHAR)));
+ symbol->MaxNameLen = TRACE_MAX_FUNCTION_NAME_LENGTH;
+ symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+ DWORD displacement;
+ IMAGEHLP_LINE64 line;
+ line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+ for (int i = 0; i < numberOfFrames; i++) {
+ DWORD64 address = reinterpret_cast<DWORD64>(stack[i]);
+ SymFromAddr(process, address, nullptr, symbol);
+ if (SymGetLineFromAddr64(process, address, &displacement, &line)) {
+ oss << " at " << symbol->Name << " in " << line.FileName << " line "
+ << line.LineNumber << std::endl;
+ } else {
+ oss << " at " << symbol->Name << std::endl;
+ }
+ }
+ free(symbol);
+
#else
-#if !defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
- "WARNING: Function names will not be demangled "
- "because "
- "dladdr is not available.\n"
-#endif
-#if !defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
- "WARNING: Function names will not be demangled "
- "because cxxabi is not available.\n"
-#endif
-#endif
+ programStack += ""
+# if !defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
+ "WARNING: The stack could not be examined "
+ "because backtrace is not supported.\n"
+# elif !defined(KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD)
+ "WARNING: The stack trace will not use advanced "
+ "capabilities because this is a release build.\n"
+# else
+# if !defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+ "WARNING: Function names will not be demangled "
+ "because dladdr is not available.\n"
+# endif
+# if !defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
+ "WARNING: Function names will not be demangled "
+ "because cxxabi is not available.\n"
+# endif
+# endif
;
- std::ostringstream oss;
-#if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
void* stackSymbols[256];
int nFrames = backtrace(stackSymbols, 256);
for (int i = firstFrame; i < nFrames; ++i) {
@@ -3907,10 +3952,12 @@ std::string SystemInformationImplementation::GetProgramStack(int firstFrame,
symProps.Initialize(stackSymbols[i]);
oss << symProps << std::endl;
}
-#else
+# else
(void)firstFrame;
(void)wholePath;
+# endif
#endif
+
programStack += oss.str();
return programStack;
@@ -3933,13 +3980,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, nullptr, &saABRTOrig);
+ sigaction(SIGSEGV, nullptr, &saSEGVOrig);
+ sigaction(SIGTERM, nullptr, &saTERMOrig);
+ sigaction(SIGINT, nullptr, &saINTOrig);
+ sigaction(SIGILL, nullptr, &saILLOrig);
+ sigaction(SIGBUS, nullptr, &saBUSOrig);
+ sigaction(SIGFPE, nullptr, &saFPEOrig);
// enable read, disable write
saOrigValid = 1;
@@ -3948,27 +3995,27 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable)
struct sigaction sa;
sa.sa_sigaction = (SigAction)StacktraceSignalHandler;
sa.sa_flags = SA_SIGINFO | SA_RESETHAND;
-#ifdef SA_RESTART
+# ifdef SA_RESTART
sa.sa_flags |= SA_RESTART;
-#endif
+# 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, nullptr);
+ sigaction(SIGSEGV, &sa, nullptr);
+ sigaction(SIGTERM, &sa, nullptr);
+ sigaction(SIGINT, &sa, nullptr);
+ sigaction(SIGILL, &sa, nullptr);
+ sigaction(SIGBUS, &sa, nullptr);
+ sigaction(SIGFPE, &sa, 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, nullptr);
+ sigaction(SIGSEGV, &saSEGVOrig, nullptr);
+ sigaction(SIGTERM, &saTERMOrig, nullptr);
+ sigaction(SIGINT, &saINTOrig, nullptr);
+ sigaction(SIGILL, &saILLOrig, nullptr);
+ sigaction(SIGBUS, &saBUSOrig, nullptr);
+ sigaction(SIGFPE, &saFPEOrig, nullptr);
// enable write, disable read
saOrigValid = 0;
@@ -3982,21 +4029,21 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable)
bool SystemInformationImplementation::QueryWindowsMemory()
{
#if defined(_WIN32)
-#if defined(_MSC_VER) && _MSC_VER < 1300
+# if defined(_MSC_VER) && _MSC_VER < 1300
MEMORYSTATUS ms;
unsigned long tv, tp, av, ap;
ms.dwLength = sizeof(ms);
GlobalMemoryStatus(&ms);
-#define MEM_VAL(value) dw##value
-#else
+# define MEM_VAL(value) dw##value
+# else
MEMORYSTATUSEX ms;
DWORDLONG tv, tp, av, ap;
ms.dwLength = sizeof(ms);
if (0 == GlobalMemoryStatusEx(&ms)) {
return 0;
}
-#define MEM_VAL(value) ull##value
-#endif
+# define MEM_VAL(value) ull##value
+# endif
tv = ms.MEM_VAL(TotalPageFile);
tp = ms.MEM_VAL(TotalPhys);
av = ms.MEM_VAL(AvailPageFile);
@@ -4054,7 +4101,7 @@ bool SystemInformationImplementation::QueryLinuxMemory()
if (linuxMajor >= 3 || ((linuxMajor >= 2) && (linuxMinor >= 6))) {
// new /proc/meminfo format since kernel 2.6.x
- // Rigorously, this test should check from the developping version 2.5.x
+ // Rigorously, this test should check from the developing version 2.5.x
// that introduced the new format...
enum
@@ -4179,7 +4226,7 @@ bool SystemInformationImplementation::QueryMemoryBySysconf()
this->TotalPhysicalMemory = p;
this->TotalPhysicalMemory /= pagediv;
-#if defined(_SC_AVPHYS_PAGES)
+# if defined(_SC_AVPHYS_PAGES)
p = sysconf(_SC_AVPHYS_PAGES);
if (p < 0) {
return false;
@@ -4187,7 +4234,7 @@ bool SystemInformationImplementation::QueryMemoryBySysconf()
this->AvailablePhysicalMemory = p;
this->AvailablePhysicalMemory /= pagediv;
-#endif
+# endif
return true;
#else
@@ -4350,7 +4397,7 @@ void SystemInformationImplementation::CPUCountWindows()
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> ProcInfo;
{
DWORD Length = 0;
- DWORD rc = pGetLogicalProcessorInformation(NULL, &Length);
+ DWORD rc = pGetLogicalProcessorInformation(nullptr, &Length);
assert(FALSE == rc);
(void)rc; // Silence unused variable warning in Borland C++ 5.81
assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
@@ -4404,7 +4451,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, nullptr, 0);
this->TotalPhysicalMemory = static_cast<size_t>(value / 1048576);
// Parse values for Mac
@@ -4414,45 +4461,47 @@ 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);
- int64_t available_memory = vmstat.free_count * value;
+ err = sysctlbyname("hw.pagesize", &value, &len, nullptr, 0);
+ int64_t available_memory =
+ (vmstat.free_count + vmstat.inactive_count) * value;
this->AvailablePhysicalMemory =
static_cast<size_t>(available_memory / 1048576);
}
-#ifdef VM_SWAPUSAGE
+# ifdef VM_SWAPUSAGE
// Virtual memory.
int mib[2] = { CTL_VM, VM_SWAPUSAGE };
- size_t miblen = sizeof(mib) / sizeof(mib[0]);
+ unsigned int miblen =
+ static_cast<unsigned int>(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, nullptr, 0);
if (err == 0) {
this->AvailableVirtualMemory =
static_cast<size_t>(swap.xsu_avail / 1048576);
this->TotalVirtualMemory = static_cast<size_t>(swap.xsu_total / 1048576);
}
-#else
+# else
this->AvailableVirtualMemory = 0;
this->TotalVirtualMemory = 0;
-#endif
+# endif
// CPU Info
len = sizeof(this->NumberOfPhysicalCPU);
- sysctlbyname("hw.physicalcpu", &this->NumberOfPhysicalCPU, &len, NULL, 0);
+ sysctlbyname("hw.physicalcpu", &this->NumberOfPhysicalCPU, &len, nullptr, 0);
len = sizeof(this->NumberOfLogicalCPU);
- sysctlbyname("hw.logicalcpu", &this->NumberOfLogicalCPU, &len, NULL, 0);
+ sysctlbyname("hw.logicalcpu", &this->NumberOfLogicalCPU, &len, 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);
+ 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, nullptr, 0);
this->CPUSpeedInMHz = static_cast<float>(value) / 1000000;
// Chip family
@@ -4460,50 +4509,51 @@ bool SystemInformationImplementation::ParseSysCtl()
// 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);
+ sysctlbyname("machdep.cpu.family", &this->ChipID.Family, &len, 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, 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, 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, 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,
+ nullptr, 0);
::memset(retBuf, 0, 128);
len = 128;
- err = sysctlbyname("machdep.cpu.vendor", retBuf, &len, NULL, 0);
+ err = sysctlbyname("machdep.cpu.vendor", retBuf, &len, 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, 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, nullptr, 0);
if (!err) {
this->ChipID.Revision = static_cast<int>(value);
}
// feature string
- char* buf = 0;
+ char* buf = nullptr;
size_t allocSize = 128;
err = 0;
@@ -4520,7 +4570,7 @@ 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, nullptr, 0);
}
if (!err && buf && len) {
// now we can match every flags as space + flag + space
@@ -4561,7 +4611,7 @@ 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, nullptr, 0);
if (!err) {
this->ChipID.ProcessorName = retBuf;
this->ChipID.ModelName = retBuf;
@@ -4569,10 +4619,10 @@ bool SystemInformationImplementation::ParseSysCtl()
// Cache size
len = sizeof(value);
- err = sysctlbyname("hw.l1icachesize", &value, &len, NULL, 0);
+ err = sysctlbyname("hw.l1icachesize", &value, &len, 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, nullptr, 0);
this->Features.L2CacheSize = static_cast<int>(value);
return true;
@@ -4600,16 +4650,16 @@ std::string SystemInformationImplementation::ExtractValueFromSysCtl(
std::string SystemInformationImplementation::RunProcess(
std::vector<const char*> args)
{
- std::string buffer = "";
+ std::string buffer;
// Run the application
kwsysProcess* gp = kwsysProcess_New();
- kwsysProcess_SetCommand(gp, &*args.begin());
+ kwsysProcess_SetCommand(gp, args.data());
kwsysProcess_SetOption(gp, kwsysProcess_Option_HideWindow, 1);
kwsysProcess_Execute(gp);
- char* data = NULL;
+ char* data = nullptr;
int length;
double timeout = 255;
int pipe; // pipe id as returned by kwsysProcess_WaitForData()
@@ -4621,7 +4671,7 @@ std::string SystemInformationImplementation::RunProcess(
{
buffer.append(data, length);
}
- kwsysProcess_WaitForExit(gp, 0);
+ kwsysProcess_WaitForExit(gp, nullptr);
int result = 0;
switch (kwsysProcess_GetState(gp)) {
@@ -4655,11 +4705,7 @@ std::string SystemInformationImplementation::RunProcess(
std::string SystemInformationImplementation::ParseValueFromKStat(
const char* arguments)
{
- std::vector<const char*> args;
- args.clear();
- args.push_back("kstat");
- args.push_back("-p");
-
+ std::vector<std::string> args_string;
std::string command = arguments;
size_t start = std::string::npos;
size_t pos = command.find(' ', 0);
@@ -4678,35 +4724,35 @@ std::string SystemInformationImplementation::ParseValueFromKStat(
}
if (!inQuotes) {
- std::string arg = command.substr(start + 1, pos - start - 1);
+ args_string.push_back(command.substr(start + 1, pos - start - 1));
+ std::string& arg = args_string.back();
// Remove the quotes if any
- size_t quotes = arg.find('"');
- while (quotes != std::string::npos) {
- arg.erase(quotes, 1);
- quotes = arg.find('"');
- }
- args.push_back(arg.c_str());
+ arg.erase(std::remove(arg.begin(), arg.end(), '"'), arg.end());
start = pos;
}
pos = command.find(' ', pos + 1);
}
- std::string lastArg = command.substr(start + 1, command.size() - start - 1);
- args.push_back(lastArg.c_str());
+ args_string.push_back(command.substr(start + 1, command.size() - start - 1));
- args.push_back(0);
+ std::vector<const char*> args;
+ args.reserve(3 + args_string.size());
+ args.push_back("kstat");
+ args.push_back("-p");
+ for (size_t i = 0; i < args_string.size(); ++i) {
+ args.push_back(args_string[i].c_str());
+ }
+ args.push_back(nullptr);
std::string buffer = this->RunProcess(args);
- std::string value = "";
+ std::string value;
for (size_t i = buffer.size() - 1; i > 0; i--) {
if (buffer[i] == ' ' || buffer[i] == '\t') {
break;
}
if (buffer[i] != '\n' && buffer[i] != '\r') {
- std::string val = value;
- value = buffer[i];
- value += val;
+ value.insert(0u, 1, buffer[i]);
}
}
return value;
@@ -4720,11 +4766,11 @@ bool SystemInformationImplementation::QuerySolarisMemory()
// a 32 bit process on a 64 bit host the returned memory will be
// limited to 4GiB. So if this is a 32 bit process or if the sysconf
// method fails use the kstat interface.
-#if SIZEOF_VOID_P == 8
+# if SIZEOF_VOID_P == 8
if (this->QueryMemoryBySysconf()) {
return true;
}
-#endif
+# endif
char* tail;
unsigned long totalMemory =
@@ -4887,15 +4933,15 @@ bool SystemInformationImplementation::QueryBSDMemory()
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
defined(__DragonFly__)
int ctrl[2] = { CTL_HW, HW_PHYSMEM };
-#if defined(HW_PHYSMEM64)
+# if defined(HW_PHYSMEM64)
int64_t k;
ctrl[1] = HW_PHYSMEM64;
-#else
+# else
int k;
-#endif
+# endif
size_t sz = sizeof(k);
- if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) {
+ if (sysctl(ctrl, 2, &k, &sz, nullptr, 0) != 0) {
return false;
}
@@ -4966,58 +5012,58 @@ bool SystemInformationImplementation::QueryBSDProcessor()
size_t sz = sizeof(k);
int ctrl[2] = { CTL_HW, HW_NCPU };
- if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) {
+ if (sysctl(ctrl, 2, &k, &sz, nullptr, 0) != 0) {
return false;
}
this->NumberOfPhysicalCPU = k;
this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU;
-#if defined(HW_CPUSPEED)
+# if defined(HW_CPUSPEED)
ctrl[1] = HW_CPUSPEED;
- if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) {
+ if (sysctl(ctrl, 2, &k, &sz, nullptr, 0) != 0) {
return false;
}
this->CPUSpeedInMHz = (float)k;
-#endif
+# endif
-#if defined(CPU_SSE)
+# if defined(CPU_SSE)
ctrl[0] = CTL_MACHDEP;
ctrl[1] = CPU_SSE;
- if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) {
+ if (sysctl(ctrl, 2, &k, &sz, nullptr, 0) != 0) {
return false;
}
this->Features.HasSSE = (k > 0);
-#endif
+# endif
-#if defined(CPU_SSE2)
+# if defined(CPU_SSE2)
ctrl[0] = CTL_MACHDEP;
ctrl[1] = CPU_SSE2;
- if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0) {
+ if (sysctl(ctrl, 2, &k, &sz, nullptr, 0) != 0) {
return false;
}
this->Features.HasSSE2 = (k > 0);
-#endif
+# endif
-#if defined(CPU_CPUVENDOR)
+# if defined(CPU_CPUVENDOR)
ctrl[0] = CTL_MACHDEP;
ctrl[1] = CPU_CPUVENDOR;
char vbuf[25];
::memset(vbuf, 0, sizeof(vbuf));
sz = sizeof(vbuf) - 1;
- if (sysctl(ctrl, 2, vbuf, &sz, NULL, 0) != 0) {
+ if (sysctl(ctrl, 2, vbuf, &sz, nullptr, 0) != 0) {
return false;
}
this->ChipID.Vendor = vbuf;
this->FindManufacturer();
-#endif
+# endif
return true;
#else
@@ -5062,7 +5108,7 @@ bool SystemInformationImplementation::QueryHPUXMemory()
bool SystemInformationImplementation::QueryHPUXProcessor()
{
#if defined(__hpux)
-#if defined(KWSYS_SYS_HAS_MPCTL_H)
+# if defined(KWSYS_SYS_HAS_MPCTL_H)
int c = mpctl(MPC_GETNUMSPUS_SYS, 0, 0);
if (c <= 0) {
return false;
@@ -5090,17 +5136,17 @@ bool SystemInformationImplementation::QueryHPUXProcessor()
this->ChipID.Vendor = "Hewlett-Packard";
this->ChipID.Family = 0x200;
break;
-#if defined(CPU_HP_INTEL_EM_1_0) || defined(CPU_IA64_ARCHREV_0)
-#ifdef CPU_HP_INTEL_EM_1_0
+# if defined(CPU_HP_INTEL_EM_1_0) || defined(CPU_IA64_ARCHREV_0)
+# ifdef CPU_HP_INTEL_EM_1_0
case CPU_HP_INTEL_EM_1_0:
-#endif
-#ifdef CPU_IA64_ARCHREV_0
+# endif
+# ifdef CPU_IA64_ARCHREV_0
case CPU_IA64_ARCHREV_0:
-#endif
+# endif
this->ChipID.Vendor = "GenuineIntel";
this->Features.HasIA64 = true;
break;
-#endif
+# endif
default:
return false;
}
@@ -5108,9 +5154,9 @@ bool SystemInformationImplementation::QueryHPUXProcessor()
this->FindManufacturer();
return true;
-#else
+# else
return false;
-#endif
+# endif
#else
return false;
#endif
@@ -5131,14 +5177,17 @@ bool SystemInformationImplementation::QueryOSInformation()
// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXW));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
-#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(push)
-#ifdef __INTEL_COMPILER
-#pragma warning(disable : 1478)
-#else
-#pragma warning(disable : 4996)
-#endif
-#endif
+# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# pragma warning(push)
+# ifdef __INTEL_COMPILER
+# pragma warning(disable : 1478)
+# elif defined __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated-declarations"
+# else
+# pragma warning(disable : 4996)
+# endif
+# endif
bOsVersionInfoEx = GetVersionExW((OSVERSIONINFOW*)&osvi);
if (!bOsVersionInfoEx) {
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
@@ -5146,9 +5195,13 @@ bool SystemInformationImplementation::QueryOSInformation()
return false;
}
}
-#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(pop)
-#endif
+# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# ifdef __clang__
+# pragma clang diagnostic pop
+# else
+# pragma warning(pop)
+# endif
+# endif
switch (osvi.dwPlatformId) {
case VER_PLATFORM_WIN32_NT:
@@ -5166,7 +5219,7 @@ bool SystemInformationImplementation::QueryOSInformation()
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) {
this->OSRelease = "XP";
}
-#ifdef VER_NT_WORKSTATION
+# ifdef VER_NT_WORKSTATION
// Test for product type.
if (bOsVersionInfoEx) {
if (osvi.wProductType == VER_NT_WORKSTATION) {
@@ -5177,7 +5230,7 @@ bool SystemInformationImplementation::QueryOSInformation()
this->OSRelease = "7";
}
// VER_SUITE_PERSONAL may not be defined
-#ifdef VER_SUITE_PERSONAL
+# ifdef VER_SUITE_PERSONAL
else {
if (osvi.wSuiteMask & VER_SUITE_PERSONAL) {
this->OSRelease += " Personal";
@@ -5185,7 +5238,7 @@ bool SystemInformationImplementation::QueryOSInformation()
this->OSRelease += " Professional";
}
}
-#endif
+# endif
} else if (osvi.wProductType == VER_NT_SERVER) {
// Check for .NET Server instead of Windows XP.
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
@@ -5206,7 +5259,7 @@ bool SystemInformationImplementation::QueryOSInformation()
osvi.dwBuildNumber & 0xFFFF);
this->OSVersion = operatingSystem;
} else
-#endif // VER_NT_WORKSTATION
+# endif // VER_NT_WORKSTATION
{
HKEY hKey;
wchar_t szProductType[80];
@@ -5216,7 +5269,7 @@ bool SystemInformationImplementation::QueryOSInformation()
RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0,
KEY_QUERY_VALUE, &hKey);
- RegQueryValueExW(hKey, L"ProductType", NULL, NULL,
+ RegQueryValueExW(hKey, L"ProductType", nullptr, nullptr,
(LPBYTE)szProductType, &dwBufLen);
RegCloseKey(hKey);
@@ -5258,13 +5311,13 @@ bool SystemInformationImplementation::QueryOSInformation()
// Load the Kernel32 DLL.
hKernelDLL = LoadLibraryW(L"kernel32");
- if (hKernelDLL != NULL) {
+ if (hKernelDLL != nullptr) {
// Only XP and .NET Server support IsWOW64Process so... Load
// dynamically!
DLLProc = (LPFNPROC)GetProcAddress(hKernelDLL, "IsWow64Process");
// If the function address is valid, call the function.
- if (DLLProc != NULL)
+ if (DLLProc != nullptr)
(DLLProc)(GetCurrentProcess(), &bIsWindows64Bit);
else
bIsWindows64Bit = false;
@@ -5357,7 +5410,7 @@ bool SystemInformationImplementation::QueryOSInformation()
}
}
-#ifdef __APPLE__
+# ifdef __APPLE__
this->OSName = "Unknown Apple OS";
this->OSRelease = "Unknown product version";
this->OSVersion = "Unknown build version";
@@ -5365,7 +5418,7 @@ bool SystemInformationImplementation::QueryOSInformation()
this->CallSwVers("-productName", this->OSName);
this->CallSwVers("-productVersion", this->OSRelease);
this->CallSwVers("-buildVersion", this->OSVersion);
-#endif
+# endif
#endif
@@ -5379,7 +5432,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(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..fc42e9dc7 100644
--- a/Source/kwsys/SystemInformation.hxx.in
+++ b/Source/kwsys/SystemInformation.hxx.in
@@ -20,7 +20,7 @@ class @KWSYS_NAMESPACE@_EXPORT SystemInformation
#elif @KWSYS_USE___INT64@
typedef __int64 LongLong;
#else
-#error "No Long Long"
+# error "No Long Long"
#endif
friend class SystemInformationImplementation;
SystemInformationImplementation* Implementation;
@@ -56,6 +56,9 @@ public:
SystemInformation();
~SystemInformation();
+ SystemInformation(const SystemInformation&) = delete;
+ SystemInformation& operator=(const SystemInformation&) = delete;
+
const char* GetVendorString();
const char* GetVendorID();
std::string GetTypeID();
@@ -103,17 +106,17 @@ 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);
+ std::string GetMemoryDescription(const char* hostLimitEnvVarName = nullptr,
+ const char* procLimitEnvVarName = nullptr);
// Retrieve amount of physical memory installed on the system in KiB
// units.
@@ -124,8 +127,8 @@ 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.
- LongLong GetHostMemoryAvailable(const char* hostLimitEnvVarName = NULL);
+ // are reported to us via an application specified environment variable.
+ LongLong GetHostMemoryAvailable(const char* hostLimitEnvVarName = nullptr);
// Get total system RAM in units of KiB available to this process.
// This may differ from the host available if a per-process resource
@@ -133,8 +136,8 @@ public:
// system via rlimit API. Resource limits that are not imposed via
// rlimit API may be reported to us via an application specified
// environment variable.
- LongLong GetProcMemoryAvailable(const char* hostLimitEnvVarName = NULL,
- const char* procLimitEnvVarName = NULL);
+ LongLong GetProcMemoryAvailable(const char* hostLimitEnvVarName = nullptr,
+ const char* procLimitEnvVarName = nullptr);
// Get the system RAM used by all processes on the host, in units of KiB.
LongLong GetHostMemoryUsed();
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 1c4fe3389..ce4d6ef95 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -1,18 +1,19 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#ifdef __osf__
-#define _OSF_SOURCE
-#define _POSIX_C_SOURCE 199506L
-#define _XOPEN_SOURCE_EXTENDED
+# define _OSF_SOURCE
+# define _POSIX_C_SOURCE 199506L
+# define _XOPEN_SOURCE_EXTENDED
#endif
-#if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || \
- defined(__BORLANDC__) || defined(__MINGW32__))
-#define KWSYS_WINDOWS_DIRS
+#if defined(_WIN32) && \
+ (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || \
+ defined(__MINGW32__))
+# define KWSYS_WINDOWS_DIRS
#else
-#if defined(__SUNPRO_CC)
-#include <fcntl.h>
-#endif
+# if defined(__SUNPRO_CC)
+# include <fcntl.h>
+# endif
#endif
#include "kwsysPrivate.h"
@@ -20,37 +21,38 @@
#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 <algorithm>
#include <fstream>
#include <iostream>
#include <set>
#include <sstream>
+#include <utility>
#include <vector>
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Directory.hxx.in"
-#include "Encoding.hxx.in"
-#include "FStream.hxx.in"
-#include "RegularExpression.hxx.in"
-#include "SystemTools.hxx.in"
+# include "Directory.hxx.in"
+# include "Encoding.hxx.in"
+# include "FStream.hxx.in"
+# include "RegularExpression.hxx.in"
+# include "SystemTools.hxx.in"
#endif
#ifdef _MSC_VER
-#pragma warning(disable : 4786)
+# pragma warning(disable : 4786)
#endif
#if defined(__sgi) && !defined(__GNUC__)
-#pragma set woff 1375 /* base class destructor not virtual */
+# pragma set woff 1375 /* base class destructor not virtual */
#endif
#include <ctype.h>
#include <errno.h>
#ifdef __QNX__
-#include <malloc.h> /* for malloc/free on QNX */
+# include <malloc.h> /* for malloc/free on QNX */
#endif
#include <stdio.h>
#include <stdlib.h>
@@ -58,42 +60,46 @@
#include <time.h>
#if defined(_WIN32) && !defined(_MSC_VER) && defined(__GNUC__)
-#include <strings.h> /* for strcasecmp */
+# include <strings.h> /* for strcasecmp */
#endif
#ifdef _MSC_VER
-#define umask _umask // Note this is still umask on Borland
+# define umask _umask // Note this is still umask on Borland
#endif
// support for realpath call
#ifndef _WIN32
-#include <limits.h>
-#include <pwd.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <utime.h>
-#ifndef __VMS
-#include <sys/param.h>
-#include <termios.h>
+# include <limits.h>
+# include <pwd.h>
+# include <sys/ioctl.h>
+# include <sys/time.h>
+# include <sys/wait.h>
+# include <unistd.h>
+# include <utime.h>
+# ifndef __VMS
+# include <sys/param.h>
+# include <termios.h>
+# endif
+# include <signal.h> /* sigprocmask */
#endif
-#include <signal.h> /* sigprocmask */
+
+#ifdef __linux
+# include <linux/fs.h>
#endif
// Windows API.
#if defined(_WIN32)
-#include <windows.h>
-#include <winioctl.h>
-#ifndef INVALID_FILE_ATTRIBUTES
-#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
-#endif
-#if defined(_MSC_VER) && _MSC_VER >= 1800
-#define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#endif
+# include <windows.h>
+# include <winioctl.h>
+# ifndef INVALID_FILE_ATTRIBUTES
+# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+# endif
+# if defined(_MSC_VER) && _MSC_VER >= 1800
+# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# endif
#elif defined(__CYGWIN__)
-#include <windows.h>
-#undef _WIN32
+# include <windows.h>
+# undef _WIN32
#endif
#if !KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H
@@ -101,17 +107,18 @@ extern char** environ;
#endif
#ifdef __CYGWIN__
-#include <sys/cygwin.h>
+# include <sys/cygwin.h>
#endif
// getpwnam doesn't exist on Windows and Cray Xt3/Catamount
// same for TIOCGWINSZ
-#if defined(_WIN32) || defined(__LIBCATAMOUNT__)
-#undef HAVE_GETPWNAM
-#undef HAVE_TTY_INFO
+#if defined(_WIN32) || defined(__LIBCATAMOUNT__) || \
+ (defined(HAVE_GETPWNAM) && HAVE_GETPWNAM == 0)
+# undef HAVE_GETPWNAM
+# undef HAVE_TTY_INFO
#else
-#define HAVE_GETPWNAM 1
-#define HAVE_TTY_INFO 1
+# define HAVE_GETPWNAM 1
+# define HAVE_TTY_INFO 1
#endif
#define VTK_URL_PROTOCOL_REGEX "([a-zA-Z0-9]*)://(.*)"
@@ -120,15 +127,15 @@ extern char** environ;
"(.+)?"
#ifdef _MSC_VER
-#include <sys/utime.h>
+# include <sys/utime.h>
#else
-#include <utime.h>
+# include <utime.h>
#endif
// This is a hack to prevent warnings about these functions being
// declared but not referenced.
#if defined(__sgi) && !defined(__GNUC__)
-#include <sys/termios.h>
+# include <sys/termios.h>
namespace KWSYS_NAMESPACE {
class SystemToolsHack
{
@@ -146,32 +153,33 @@ public:
}
#endif
-#if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || \
- defined(__BORLANDC__) || defined(__MINGW32__))
-#include <direct.h>
-#include <io.h>
-#define _unlink unlink
+#if defined(_WIN32) && \
+ (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || \
+ defined(__MINGW32__))
+# include <direct.h>
+# include <io.h>
+# define _unlink unlink
#endif
/* The maximum length of a file name. */
#if defined(PATH_MAX)
-#define KWSYS_SYSTEMTOOLS_MAXPATH PATH_MAX
+# define KWSYS_SYSTEMTOOLS_MAXPATH PATH_MAX
#elif defined(MAXPATHLEN)
-#define KWSYS_SYSTEMTOOLS_MAXPATH MAXPATHLEN
+# define KWSYS_SYSTEMTOOLS_MAXPATH MAXPATHLEN
#else
-#define KWSYS_SYSTEMTOOLS_MAXPATH 16384
+# define KWSYS_SYSTEMTOOLS_MAXPATH 16384
#endif
#if defined(__WATCOMC__)
-#include <direct.h>
-#define _mkdir mkdir
-#define _rmdir rmdir
-#define _getcwd getcwd
-#define _chdir chdir
+# include <direct.h>
+# define _mkdir mkdir
+# define _rmdir rmdir
+# define _getcwd getcwd
+# define _chdir chdir
#endif
#if defined(__BEOS__) && !defined(__ZETA__)
-#include <be/kernel/OS.h>
-#include <be/storage/Path.h>
+# include <be/kernel/OS.h>
+# include <be/storage/Path.h>
// BeOS 5 doesn't have usleep(), but it has snooze(), which is identical.
static inline void usleep(unsigned int msec)
@@ -184,15 +192,15 @@ static inline char* realpath(const char* path, char* resolved_path)
{
const size_t maxlen = KWSYS_SYSTEMTOOLS_MAXPATH;
snprintf(resolved_path, maxlen, "%s", path);
- BPath normalized(resolved_path, NULL, true);
+ BPath normalized(resolved_path, nullptr, true);
const char* resolved = normalized.Path();
- if (resolved != NULL) // NULL == No such file.
+ if (resolved != nullptr) // nullptr == No such file.
{
if (snprintf(resolved_path, maxlen, "%s", resolved) < maxlen) {
return resolved_path;
}
}
- return NULL; // something went wrong.
+ return nullptr; // something went wrong.
}
#endif
@@ -212,7 +220,7 @@ static time_t windows_filetime_to_posix_time(const FILETIME& ft)
#endif
#ifdef KWSYS_WINDOWS_DIRS
-#include <wctype.h>
+# include <wctype.h>
inline int Mkdir(const std::string& dir)
{
@@ -228,23 +236,27 @@ 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;
}
inline int Chdir(const std::string& dir)
{
-#if defined(__BORLANDC__)
+# if defined(__BORLANDC__)
return chdir(dir.c_str());
-#else
+# else
return _wchdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str());
-#endif
+# endif
}
inline void Realpath(const std::string& path, std::string& resolved_path,
std::string* errorMessage = 0)
@@ -261,12 +273,12 @@ inline void Realpath(const std::string& path, std::string& resolved_path,
if (bufferLen) {
*errorMessage = "Destination path buffer size too small.";
} else if (unsigned int errorId = GetLastError()) {
- LPSTR message = NULL;
+ LPSTR message = nullptr;
DWORD size = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, errorId, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPSTR)&message, 0, NULL);
+ nullptr, errorId, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&message, 0, nullptr);
*errorMessage = std::string(message, size);
LocalFree(message);
} else {
@@ -279,10 +291,10 @@ inline void Realpath(const std::string& path, std::string& resolved_path,
}
}
#else
-#include <sys/types.h>
+# include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
+# include <fcntl.h>
+# include <unistd.h>
inline int Mkdir(const std::string& dir)
{
return mkdir(dir.c_str(), 00777);
@@ -301,7 +313,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 = nullptr)
{
char resolved_name[KWSYS_SYSTEMTOOLS_MAXPATH];
@@ -347,15 +359,11 @@ double SystemTools::GetTime(void)
11644473600.0);
#else
struct timeval t;
- gettimeofday(&t, 0);
+ gettimeofday(&t, nullptr);
return 1.0 * double(t.tv_sec) + 0.000001 * double(t.tv_usec);
#endif
}
-class SystemToolsTranslationMap : public std::map<std::string, std::string>
-{
-};
-
/* Type of character storing the environment. */
#if defined(_WIN32)
typedef wchar_t envchar;
@@ -381,8 +389,8 @@ struct kwsysEnvCompare
#else
const char* leq = strchr(l, '=');
const char* req = strchr(r, '=');
- size_t llen = leq ? (leq - l) : strlen(l);
- size_t rlen = req ? (req - r) : strlen(r);
+ size_t llen = leq ? static_cast<size_t>(leq - l) : strlen(l);
+ size_t rlen = req ? static_cast<size_t>(req - r) : strlen(r);
if (llen == rlen) {
return strncmp(l, r, llen) < 0;
} else {
@@ -405,11 +413,14 @@ public:
{
}
~Free() { free(const_cast<envchar*>(this->Env)); }
+
+ Free(const Free&) = delete;
+ Free& operator=(const Free&) = delete;
};
const envchar* Release(const envchar* env)
{
- const envchar* old = 0;
+ const envchar* old = nullptr;
iterator i = this->find(env);
if (i != this->end()) {
old = *i;
@@ -424,24 +435,150 @@ struct SystemToolsPathCaseCmp
{
bool operator()(std::string const& l, std::string const& r) const
{
-#ifdef _MSC_VER
+# ifdef _MSC_VER
return _stricmp(l.c_str(), r.c_str()) < 0;
-#elif defined(__GNUC__)
+# elif defined(__GNUC__)
return strcasecmp(l.c_str(), r.c_str()) < 0;
-#else
+# else
return SystemTools::Strucmp(l.c_str(), r.c_str()) < 0;
-#endif
+# endif
}
};
+#endif
-class SystemToolsPathCaseMap
- : public std::map<std::string, std::string, SystemToolsPathCaseCmp>
+/**
+ * SystemTools static variables singleton class.
+ */
+class SystemToolsStatic
{
+public:
+ typedef std::map<std::string, std::string> StringMap;
+#if KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP
+ /**
+ * Path translation table from dir to refdir
+ * Each time 'dir' will be found it will be replace by 'refdir'
+ */
+ StringMap TranslationMap;
+#endif
+#ifdef _WIN32
+ static std::string GetCasePathName(std::string const& pathIn);
+ static std::string GetActualCaseForPathCached(std::string const& path);
+ static const char* GetEnvBuffered(const char* key);
+ std::map<std::string, std::string, SystemToolsPathCaseCmp> PathCaseMap;
+ std::map<std::string, std::string> EnvMap;
+#endif
+#ifdef __CYGWIN__
+ StringMap Cyg2Win32Map;
+#endif
+
+ /**
+ * Actual implementation of ReplaceString.
+ */
+ static void ReplaceString(std::string& source, const char* replace,
+ size_t replaceSize, const std::string& with);
+
+ /**
+ * Actual implementation of FileIsFullPath.
+ */
+ static bool FileIsFullPath(const char*, size_t);
+
+ /**
+ * Find a filename (file or directory) in the system PATH, with
+ * optional extra paths.
+ */
+ static std::string FindName(
+ const std::string& name,
+ const std::vector<std::string>& path = std::vector<std::string>(),
+ bool no_system_path = false);
};
-class SystemToolsEnvMap : public std::map<std::string, std::string>
+#ifdef _WIN32
+std::string SystemToolsStatic::GetCasePathName(std::string const& pathIn)
{
-};
+ std::string casePath;
+
+ // First check if the file is relative. We don't fix relative paths since the
+ // real case depends on the root directory and the given path fragment may
+ // have meaning elsewhere in the project.
+ if (!SystemTools::FileIsFullPath(pathIn)) {
+ // This looks unnecessary, but it allows for the return value optimization
+ // since all return paths return the same local variable.
+ casePath = pathIn;
+ return casePath;
+ }
+
+ std::vector<std::string> path_components;
+ SystemTools::SplitPath(pathIn, path_components);
+
+ // Start with root component.
+ std::vector<std::string>::size_type idx = 0;
+ casePath = path_components[idx++];
+ // make sure drive letter is always upper case
+ if (casePath.size() > 1 && casePath[1] == ':') {
+ casePath[0] = toupper(casePath[0]);
+ }
+ const char* sep = "";
+
+ // If network path, fill casePath with server/share so FindFirstFile
+ // will work after that. Maybe someday call other APIs to get
+ // actual case of servers and shares.
+ if (path_components.size() > 2 && path_components[0] == "//") {
+ casePath += path_components[idx++];
+ casePath += "/";
+ casePath += path_components[idx++];
+ sep = "/";
+ }
+
+ // Convert case of all components that exist.
+ bool converting = true;
+ for (; idx < path_components.size(); idx++) {
+ casePath += sep;
+ sep = "/";
+
+ if (converting) {
+ // If path component contains wildcards, we skip matching
+ // because these filenames are not allowed on windows,
+ // and we do not want to match a different file.
+ if (path_components[idx].find('*') != std::string::npos ||
+ path_components[idx].find('?') != std::string::npos) {
+ converting = false;
+ } else {
+ std::string test_str = casePath;
+ test_str += path_components[idx];
+ WIN32_FIND_DATAW findData;
+ HANDLE hFind =
+ ::FindFirstFileW(Encoding::ToWide(test_str).c_str(), &findData);
+ if (INVALID_HANDLE_VALUE != hFind) {
+ path_components[idx] = Encoding::ToNarrow(findData.cFileName);
+ ::FindClose(hFind);
+ } else {
+ converting = false;
+ }
+ }
+ }
+
+ casePath += path_components[idx];
+ }
+ return casePath;
+}
+
+std::string SystemToolsStatic::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
+ auto& pcm = SystemTools::Statics->PathCaseMap;
+ {
+ auto itr = pcm.find(p);
+ if (itr != pcm.end()) {
+ return itr->second;
+ }
+ }
+ std::string casePath = SystemToolsStatic::GetCasePathName(p);
+ if (casePath.size() <= MAX_PATH) {
+ pcm[p] = casePath;
+ }
+ return casePath;
+}
#endif
// adds the elements of the env variable path to the arg passed in
@@ -462,7 +599,7 @@ void SystemTools::GetPath(std::vector<std::string>& path, const char* env)
}
// A hack to make the below algorithm work.
- if (!pathEnv.empty() && *pathEnv.rbegin() != pathSep) {
+ if (!pathEnv.empty() && pathEnv.back() != pathSep) {
pathEnv += pathSep;
}
std::string::size_type start = 0;
@@ -482,30 +619,37 @@ void SystemTools::GetPath(std::vector<std::string>& path, const char* env)
}
}
-const char* SystemTools::GetEnvImpl(const char* key)
-{
- const char* v = 0;
#if defined(_WIN32)
+const char* SystemToolsStatic::GetEnvBuffered(const char* key)
+{
std::string env;
if (SystemTools::GetEnv(key, env)) {
- std::string& menv = (*SystemTools::EnvMap)[key];
- menv = env;
- v = menv.c_str();
+ std::string& menv = SystemTools::Statics->EnvMap[key];
+ if (menv != env) {
+ menv = std::move(env);
+ }
+ return menv.c_str();
}
-#else
- v = getenv(key);
-#endif
- return v;
+ return nullptr;
}
+#endif
const char* SystemTools::GetEnv(const char* key)
{
- return SystemTools::GetEnvImpl(key);
+#if defined(_WIN32)
+ return SystemToolsStatic::GetEnvBuffered(key);
+#else
+ return getenv(key);
+#endif
}
const char* SystemTools::GetEnv(const std::string& key)
{
- return SystemTools::GetEnvImpl(key.c_str());
+#if defined(_WIN32)
+ return SystemToolsStatic::GetEnvBuffered(key.c_str());
+#else
+ return getenv(key.c_str());
+#endif
}
bool SystemTools::GetEnv(const char* key, std::string& result)
@@ -540,7 +684,7 @@ bool SystemTools::HasEnv(const char* key)
#else
const char* v = getenv(key);
#endif
- return v != 0;
+ return v != nullptr;
}
bool SystemTools::HasEnv(const std::string& key)
@@ -667,9 +811,9 @@ bool SystemTools::UnPutEnv(const std::string& env)
environment values that may still reference memory we allocated. Then free
the memory. This will not affect any environment values we never set. */
-#ifdef __INTEL_COMPILER
-#pragma warning disable 444 /* base has non-virtual destructor */
-#endif
+# ifdef __INTEL_COMPILER
+# pragma warning disable 444 /* base has non-virtual destructor */
+# endif
class kwsysEnv : public kwsysEnvSet
{
@@ -677,39 +821,39 @@ public:
~kwsysEnv()
{
for (iterator i = this->begin(); i != this->end(); ++i) {
-#if defined(_WIN32)
+# if defined(_WIN32)
const std::string s = Encoding::ToNarrow(*i);
- kwsysUnPutEnv(s.c_str());
-#else
+ kwsysUnPutEnv(s);
+# else
kwsysUnPutEnv(*i);
-#endif
+# endif
free(const_cast<envchar*>(*i));
}
}
bool Put(const char* env)
{
-#if defined(_WIN32)
+# if defined(_WIN32)
const std::wstring wEnv = Encoding::ToWide(env);
wchar_t* newEnv = _wcsdup(wEnv.c_str());
-#else
+# else
char* newEnv = strdup(env);
-#endif
+# endif
Free oldEnv(this->Release(newEnv));
this->insert(newEnv);
-#if defined(_WIN32)
+# if defined(_WIN32)
return _wputenv(newEnv) == 0;
-#else
+# else
return putenv(newEnv) == 0;
-#endif
+# endif
}
bool UnPut(const char* env)
{
-#if defined(_WIN32)
+# if defined(_WIN32)
const std::wstring wEnv = Encoding::ToWide(env);
Free oldEnv(this->Release(wEnv.c_str()));
-#else
+# else
Free oldEnv(this->Release(env));
-#endif
+# endif
return kwsysUnPutEnv(env) == 0;
}
};
@@ -747,15 +891,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);
@@ -770,8 +914,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 != nullptr) {
+ SystemTools::SetPermissions(topdir, *mode);
+ }
+
+ ++pos;
}
topdir = dir;
if (Mkdir(topdir) != 0) {
@@ -783,10 +931,13 @@ bool SystemTools::MakeDirectory(const std::string& path)
#ifdef __BORLANDC__
&& (errno != EACCES)
#endif
- ) {
+ ) {
return false;
}
+ } else if (mode != nullptr) {
+ SystemTools::SetPermissions(topdir, *mode);
}
+
return true;
}
@@ -801,7 +952,8 @@ void SystemTools::ReplaceString(std::string& source,
return;
}
- SystemTools::ReplaceString(source, replace.c_str(), replace.size(), with);
+ SystemToolsStatic::ReplaceString(source, replace.c_str(), replace.size(),
+ with);
}
void SystemTools::ReplaceString(std::string& source, const char* replace,
@@ -812,12 +964,13 @@ void SystemTools::ReplaceString(std::string& source, const char* replace,
return;
}
- SystemTools::ReplaceString(source, replace, strlen(replace),
- with ? with : "");
+ SystemToolsStatic::ReplaceString(source, replace, strlen(replace),
+ with ? with : "");
}
-void SystemTools::ReplaceString(std::string& source, const char* replace,
- size_t replaceSize, const std::string& with)
+void SystemToolsStatic::ReplaceString(std::string& source, const char* replace,
+ size_t replaceSize,
+ const std::string& with)
{
const char* src = source.c_str();
char* searchPos = const_cast<char*>(strstr(src, replace));
@@ -848,15 +1001,16 @@ void SystemTools::ReplaceString(std::string& source, const char* replace,
free(orig);
}
-#if defined(KEY_WOW64_32KEY) && defined(KEY_WOW64_64KEY)
-#define KWSYS_ST_KEY_WOW64_32KEY KEY_WOW64_32KEY
-#define KWSYS_ST_KEY_WOW64_64KEY KEY_WOW64_64KEY
-#else
-#define KWSYS_ST_KEY_WOW64_32KEY 0x0200
-#define KWSYS_ST_KEY_WOW64_64KEY 0x0100
-#endif
-
#if defined(_WIN32) && !defined(__CYGWIN__)
+
+# if defined(KEY_WOW64_32KEY) && defined(KEY_WOW64_64KEY)
+# define KWSYS_ST_KEY_WOW64_32KEY KEY_WOW64_32KEY
+# define KWSYS_ST_KEY_WOW64_64KEY KEY_WOW64_64KEY
+# else
+# define KWSYS_ST_KEY_WOW64_32KEY 0x0200
+# define KWSYS_ST_KEY_WOW64_64KEY 0x0100
+# endif
+
static bool SystemToolsParseRegistryKey(const std::string& key,
HKEY& primaryKey, std::string& second,
std::string& valuename)
@@ -901,7 +1055,7 @@ static DWORD SystemToolsMakeRegistryMode(DWORD mode,
// only add the modes when on a system that supports Wow64.
static FARPROC wow64p =
GetProcAddress(GetModuleHandleW(L"kernel32"), "IsWow64Process");
- if (wow64p == NULL) {
+ if (wow64p == nullptr) {
return mode;
}
@@ -982,7 +1136,7 @@ bool SystemTools::ReadRegistryValue(const std::string& key, std::string& value,
DWORD dwType, dwSize;
dwSize = 1023;
wchar_t data[1024];
- if (RegQueryValueExW(hKey, Encoding::ToWide(valuename).c_str(), NULL,
+ if (RegQueryValueExW(hKey, Encoding::ToWide(valuename).c_str(), nullptr,
&dwType, (BYTE*)data, &dwSize) == ERROR_SUCCESS) {
if (dwType == REG_SZ) {
value = Encoding::ToNarrow(data);
@@ -1032,7 +1186,7 @@ bool SystemTools::WriteRegistryValue(const std::string& key,
wchar_t lpClass[] = L"";
if (RegCreateKeyExW(primaryKey, Encoding::ToWide(second).c_str(), 0, lpClass,
REG_OPTION_NON_VOLATILE,
- SystemToolsMakeRegistryMode(KEY_WRITE, view), NULL,
+ SystemToolsMakeRegistryMode(KEY_WRITE, view), nullptr,
&hKey, &dwDummy) != ERROR_SUCCESS) {
return false;
}
@@ -1059,7 +1213,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)
@@ -1098,10 +1252,10 @@ bool SystemTools::SameFile(const std::string& file1, const std::string& file2)
hFile1 =
CreateFileW(Encoding::ToWide(file1).c_str(), GENERIC_READ, FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
hFile2 =
CreateFileW(Encoding::ToWide(file2).c_str(), GENERIC_READ, FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
if (hFile1 == INVALID_HANDLE_VALUE || hFile2 == INVALID_HANDLE_VALUE) {
if (hFile1 != INVALID_HANDLE_VALUE) {
CloseHandle(hFile1);
@@ -1182,16 +1336,34 @@ bool SystemTools::FileExists(const std::string& filename)
}
return access(filename.c_str(), R_OK) == 0;
#elif defined(_WIN32)
- return (
- GetFileAttributesW(Encoding::ToWindowsExtendedPath(filename).c_str()) !=
- INVALID_FILE_ATTRIBUTES);
+ DWORD attr =
+ GetFileAttributesW(Encoding::ToWindowsExtendedPath(filename).c_str());
+ if (attr == INVALID_FILE_ATTRIBUTES) {
+ return false;
+ }
+
+ if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
+ // Using 0 instead of GENERIC_READ as it allows reading of file attributes
+ // even if we do not have permission to read the file itself
+ HANDLE handle =
+ CreateFileW(Encoding::ToWindowsExtendedPath(filename).c_str(), 0, 0,
+ nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ CloseHandle(handle);
+ }
+
+ return true;
#else
// SCO OpenServer 5.0.7/3.2's command has 711 permission.
-#if defined(_SCO_DS)
+# if defined(_SCO_DS)
return access(filename.c_str(), F_OK) == 0;
-#else
+# else
return access(filename.c_str(), R_OK) == 0;
-#endif
+# endif
#endif
}
@@ -1263,11 +1435,11 @@ int SystemTools::Stat(const std::string& path, SystemTools::Stat_t* buf)
// long paths, but _wstat64 rejects paths with '?' in them, thinking
// they are wildcards.
std::wstring const& wpath = Encoding::ToWide(path);
-#if defined(__BORLANDC__)
+# if defined(__BORLANDC__)
return _wstati64(wpath.c_str(), buf);
-#else
+# else
return _wstat64(wpath.c_str(), buf);
-#endif
+# endif
#else
return stat(path.c_str(), buf);
#endif
@@ -1276,18 +1448,16 @@ int SystemTools::Stat(const std::string& path, SystemTools::Stat_t* buf)
#ifdef __CYGWIN__
bool SystemTools::PathCygwinToWin32(const char* path, char* win32_path)
{
- SystemToolsTranslationMap::iterator i =
- SystemTools::Cyg2Win32Map->find(path);
-
- if (i != SystemTools::Cyg2Win32Map->end()) {
- strncpy(win32_path, i->second.c_str(), MAX_PATH);
+ auto itr = SystemTools::Statics->Cyg2Win32Map.find(path);
+ if (itr != SystemTools::Statics->Cyg2Win32Map.end()) {
+ strncpy(win32_path, itr->second.c_str(), MAX_PATH);
} else {
if (cygwin_conv_path(CCP_POSIX_TO_WIN_A, path, win32_path, MAX_PATH) !=
0) {
win32_path[0] = 0;
}
- SystemToolsTranslationMap::value_type entry(path, win32_path);
- SystemTools::Cyg2Win32Map->insert(entry);
+ SystemTools::Statics->Cyg2Win32Map.insert(
+ SystemToolsStatic::StringMap::value_type(path, win32_path));
}
return win32_path[0] != 0;
}
@@ -1322,39 +1492,15 @@ bool SystemTools::Touch(const std::string& filename, bool create)
}
CloseHandle(h);
#elif KWSYS_CXX_HAS_UTIMENSAT
- struct timespec times[2] = { { 0, UTIME_OMIT }, { 0, UTIME_NOW } };
- if (utimensat(AT_FDCWD, filename.c_str(), times, 0) < 0) {
- return false;
- }
-#else
- struct stat st;
- if (stat(filename.c_str(), &st) < 0) {
+ // utimensat is only available on newer Unixes and macOS 10.13+
+ if (utimensat(AT_FDCWD, filename.c_str(), nullptr, 0) < 0) {
return false;
}
- struct timeval mtime;
- gettimeofday(&mtime, 0);
-#if KWSYS_CXX_HAS_UTIMES
- struct timeval atime;
-#if KWSYS_CXX_STAT_HAS_ST_MTIM
- atime.tv_sec = st.st_atim.tv_sec;
- atime.tv_usec = st.st_atim.tv_nsec / 1000;
-#elif KWSYS_CXX_STAT_HAS_ST_MTIMESPEC
- atime.tv_sec = st.st_atimespec.tv_sec;
- atime.tv_usec = st.st_atimespec.tv_nsec / 1000;
#else
- atime.tv_sec = st.st_atime;
- atime.tv_usec = 0;
-#endif
- struct timeval times[2] = { atime, mtime };
- if (utimes(filename.c_str(), times) < 0) {
+ // fall back to utimes
+ if (utimes(filename.c_str(), nullptr) < 0) {
return false;
}
-#else
- struct utimbuf times = { st.st_atime, mtime.tv_sec };
- if (utime(filename.c_str(), &times) < 0) {
- return false;
- }
-#endif
#endif
return true;
}
@@ -1374,7 +1520,7 @@ bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2,
if (stat(f2.c_str(), &s2) != 0) {
return false;
}
-#if KWSYS_CXX_STAT_HAS_ST_MTIM
+# if KWSYS_CXX_STAT_HAS_ST_MTIM
// Compare using nanosecond resolution.
if (s1.st_mtim.tv_sec < s2.st_mtim.tv_sec) {
*result = -1;
@@ -1385,7 +1531,7 @@ bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2,
} else if (s1.st_mtim.tv_nsec > s2.st_mtim.tv_nsec) {
*result = 1;
}
-#elif KWSYS_CXX_STAT_HAS_ST_MTIMESPEC
+# elif KWSYS_CXX_STAT_HAS_ST_MTIMESPEC
// Compare using nanosecond resolution.
if (s1.st_mtimespec.tv_sec < s2.st_mtimespec.tv_sec) {
*result = -1;
@@ -1396,14 +1542,14 @@ bool SystemTools::FileTimeCompare(const std::string& f1, const std::string& f2,
} else if (s1.st_mtimespec.tv_nsec > s2.st_mtimespec.tv_nsec) {
*result = 1;
}
-#else
+# else
// Compare using 1 second resolution.
if (s1.st_mtime < s2.st_mtime) {
*result = -1;
} else if (s1.st_mtime > s2.st_mtime) {
*result = 1;
}
-#endif
+# endif
#else
// Windows version. Get the modification time from extended file attributes.
WIN32_FILE_ATTRIBUTE_DATA f1d;
@@ -1507,7 +1653,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 nullptr;
}
strcpy(newstr, str1);
strcat(newstr + len1, str2);
@@ -1530,7 +1676,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 nullptr;
}
strcpy(newstr, str1);
strcat(newstr + len1, str2);
@@ -1580,7 +1726,7 @@ size_t SystemTools::CountChar(const char* str, char c)
char* SystemTools::RemoveChars(const char* str, const char* toremove)
{
if (!str) {
- return NULL;
+ return nullptr;
}
char* clean_str = new char[strlen(str) + 1];
char* ptr = clean_str;
@@ -1602,7 +1748,7 @@ char* SystemTools::RemoveChars(const char* str, const char* toremove)
char* SystemTools::RemoveCharsButUpperHex(const char* str)
{
if (!str) {
- return 0;
+ return nullptr;
}
char* clean_str = new char[strlen(str) + 1];
char* ptr = clean_str;
@@ -1679,11 +1825,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 nullptr;
}
size_t len1 = strlen(str1), len2 = strlen(str2);
@@ -1696,7 +1842,7 @@ const char* SystemTools::FindLastString(const char* str1, const char* str2)
} while (ptr-- != str1);
}
- return NULL;
+ return nullptr;
}
// Duplicate string
@@ -1706,7 +1852,7 @@ char* SystemTools::DuplicateString(const char* str)
char* newstr = new char[strlen(str) + 1];
return strcpy(newstr, str);
}
- return NULL;
+ return nullptr;
}
// Return a cropped string
@@ -1737,11 +1883,11 @@ std::string SystemTools::CropString(const std::string& s, size_t max_len)
return n;
}
-std::vector<kwsys::String> SystemTools::SplitString(const std::string& p,
- char sep, bool isPath)
+std::vector<std::string> SystemTools::SplitString(const std::string& p,
+ char sep, bool isPath)
{
std::string path = p;
- std::vector<kwsys::String> paths;
+ std::vector<std::string> paths;
if (path.empty()) {
return paths;
}
@@ -1870,70 +2016,70 @@ 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) {
-#ifdef _WIN32
+ 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.
if (pos > 0) {
hasDoubleSlash = true;
}
-#else
+# else
hasDoubleSlash = true;
-#endif
+# endif
}
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.back() == '/') {
+ // if it is c:/ then do not remove the trailing slash
+ if (!((size == 3 && pathCString[1] == ':'))) {
+ path.resize(size - 1);
}
}
}
@@ -1958,7 +2104,7 @@ std::string SystemTools::ConvertToUnixOutputPath(const std::string& path)
}
// escape spaces and () in the path
if (ret.find_first_of(" ") != std::string::npos) {
- std::string result = "";
+ std::string result;
char lastch = 1;
for (const char* ch = ret.c_str(); *ch != '\0'; ++ch) {
// if it is already escaped then don't try to escape it again
@@ -2023,24 +2169,24 @@ std::string SystemTools::ConvertToWindowsOutputPath(const std::string& path)
return ret;
}
+/**
+ * Append the filename from the path source to the directory name dir.
+ */
+static std::string FileInDir(const std::string& source, const std::string& dir)
+{
+ std::string new_destination = dir;
+ SystemTools::ConvertToUnixSlashes(new_destination);
+ return new_destination + '/' + SystemTools::GetFilenameName(source);
+}
+
bool SystemTools::CopyFileIfDifferent(const std::string& source,
const std::string& destination)
{
// special check for a destination that is a directory
// FilesDiffer does not handle file to directory compare
if (SystemTools::FileIsDirectory(destination)) {
- std::string new_destination = destination;
- SystemTools::ConvertToUnixSlashes(new_destination);
- new_destination += '/';
- std::string source_name = source;
- new_destination += SystemTools::GetFilenameName(source_name);
- if (SystemTools::FilesDiffer(source, new_destination)) {
- return SystemTools::CopyFileAlways(source, destination);
- } else {
- // the files are the same so the copy is done return
- // true
- return true;
- }
+ const std::string new_destination = FileInDir(source, destination);
+ return SystemTools::CopyFileIfDifferent(source, new_destination);
}
// source and destination are files so do a copy if they
// are different
@@ -2148,16 +2294,152 @@ bool SystemTools::FilesDiffer(const std::string& source,
return false;
}
+bool SystemTools::TextFilesDiffer(const std::string& path1,
+ const std::string& path2)
+{
+ kwsys::ifstream if1(path1.c_str());
+ kwsys::ifstream if2(path2.c_str());
+ if (!if1 || !if2) {
+ return true;
+ }
+
+ for (;;) {
+ std::string line1, line2;
+ bool hasData1 = GetLineFromStream(if1, line1);
+ bool hasData2 = GetLineFromStream(if2, line2);
+ if (hasData1 != hasData2) {
+ return true;
+ }
+ if (!hasData1) {
+ break;
+ }
+ if (line1 != line2) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Blockwise copy source to destination file
+ */
+static bool CopyFileContentBlockwise(const std::string& source,
+ const std::string& destination)
+{
+// Open files
+#if defined(_WIN32)
+ kwsys::ifstream fin(
+ Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)).c_str(),
+ std::ios::in | std::ios::binary);
+#else
+ kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary);
+#endif
+ if (!fin) {
+ return false;
+ }
+
+ // try and remove the destination file so that read only destination files
+ // can be written to.
+ // If the remove fails continue so that files in read only directories
+ // that do not allow file removal can be modified.
+ SystemTools::RemoveFile(destination);
+
+#if defined(_WIN32)
+ kwsys::ofstream fout(
+ Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(destination)).c_str(),
+ std::ios::out | std::ios::trunc | std::ios::binary);
+#else
+ kwsys::ofstream fout(destination.c_str(),
+ std::ios::out | std::ios::trunc | std::ios::binary);
+#endif
+ if (!fout) {
+ return false;
+ }
+
+ // This copy loop is very sensitive on certain platforms with
+ // slightly broken stream libraries (like HPUX). Normally, it is
+ // incorrect to not check the error condition on the fin.read()
+ // before using the data, but the fin.gcount() will be zero if an
+ // error occurred. Therefore, the loop should be safe everywhere.
+ while (fin) {
+ const int bufferSize = 4096;
+ char buffer[bufferSize];
+
+ fin.read(buffer, bufferSize);
+ if (fin.gcount()) {
+ fout.write(buffer, fin.gcount());
+ } else {
+ break;
+ }
+ }
+
+ // Make sure the operating system has finished writing the file
+ // before closing it. This will ensure the file is finished before
+ // the check below.
+ fout.flush();
+
+ fin.close();
+ fout.close();
+
+ if (!fout) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Clone the source file to the destination file
+ *
+ * If available, the Linux FICLONE ioctl is used to create a check
+ * copy-on-write clone of the source file.
+ *
+ * The method returns false for the following cases:
+ * - The code has not been compiled on Linux or the ioctl was unknown
+ * - The source and destination is on different file systems
+ * - The underlying filesystem does not support file cloning
+ * - An unspecified error occurred
+ */
+static bool CloneFileContent(const std::string& source,
+ const std::string& destination)
+{
+#if defined(__linux) && defined(FICLONE)
+ int in = open(source.c_str(), O_RDONLY);
+ if (in < 0) {
+ return false;
+ }
+
+ SystemTools::RemoveFile(destination);
+
+ int out =
+ open(destination.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
+ if (out < 0) {
+ close(in);
+ return false;
+ }
+
+ int result = ioctl(out, FICLONE, in);
+ close(in);
+ close(out);
+
+ if (result < 0) {
+ return false;
+ }
+
+ return true;
+#else
+ (void)source;
+ (void)destination;
+ return false;
+#endif
+}
+
/**
* Copy a file named by "source" to the file named by "destination".
*/
bool SystemTools::CopyFileAlways(const std::string& source,
const std::string& destination)
{
- // If files are the same do not copy
- if (SystemTools::SameFile(source, destination)) {
- return true;
- }
mode_t perm = 0;
bool perms = SystemTools::GetPermissions(source, perm);
std::string real_destination = destination;
@@ -2165,9 +2447,6 @@ bool SystemTools::CopyFileAlways(const std::string& source,
if (SystemTools::FileIsDirectory(source)) {
SystemTools::MakeDirectory(destination);
} else {
- const int bufferSize = 4096;
- char buffer[bufferSize];
-
// If destination is a directory, try to create a file with the same
// name as the source in that directory.
@@ -2181,67 +2460,21 @@ bool SystemTools::CopyFileAlways(const std::string& source,
} else {
destination_dir = SystemTools::GetFilenamePath(destination);
}
+ // If files are the same do not copy
+ if (SystemTools::SameFile(source, real_destination)) {
+ return true;
+ }
// Create destination directory
SystemTools::MakeDirectory(destination_dir);
-// Open files
-#if defined(_WIN32)
- kwsys::ifstream fin(
- Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)).c_str(),
- std::ios::in | std::ios::binary);
-#else
- kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary);
-#endif
- if (!fin) {
- return false;
- }
-
- // try and remove the destination file so that read only destination files
- // can be written to.
- // If the remove fails continue so that files in read only directories
- // that do not allow file removal can be modified.
- SystemTools::RemoveFile(real_destination);
-
-#if defined(_WIN32)
- kwsys::ofstream fout(
- Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(real_destination))
- .c_str(),
- std::ios::out | std::ios::trunc | std::ios::binary);
-#else
- kwsys::ofstream fout(real_destination.c_str(),
- std::ios::out | std::ios::trunc | std::ios::binary);
-#endif
- if (!fout) {
- return false;
- }
-
- // This copy loop is very sensitive on certain platforms with
- // slightly broken stream libraries (like HPUX). Normally, it is
- // incorrect to not check the error condition on the fin.read()
- // before using the data, but the fin.gcount() will be zero if an
- // error occurred. Therefore, the loop should be safe everywhere.
- while (fin) {
- fin.read(buffer, bufferSize);
- if (fin.gcount()) {
- fout.write(buffer, fin.gcount());
- } else {
- break;
+ if (!CloneFileContent(source, real_destination)) {
+ // if cloning did not succeed, fall back to blockwise copy
+ if (!CopyFileContentBlockwise(source, real_destination)) {
+ return false;
}
}
-
- // Make sure the operating system has finished writing the file
- // before closing it. This will ensure the file is finished before
- // the check below.
- fout.flush();
-
- fin.close();
- fout.close();
-
- if (!fout) {
- return false;
- }
}
if (perms) {
if (!SystemTools::SetPermissions(real_destination, perm)) {
@@ -2269,11 +2502,9 @@ bool SystemTools::CopyADirectory(const std::string& source,
const std::string& destination, bool always)
{
Directory dir;
-#ifdef _WIN32
- dir.Load(Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)));
-#else
- dir.Load(source);
-#endif
+ if (dir.Load(source) == 0) {
+ return false;
+ }
size_t fileNum;
if (!SystemTools::MakeDirectory(destination)) {
return false;
@@ -2375,205 +2606,12 @@ long int SystemTools::CreationTime(const std::string& filename)
return ct;
}
-bool SystemTools::ConvertDateMacroString(const char* str, time_t* tmt)
-{
- if (!str || !tmt || strlen(str) > 11) {
- return false;
- }
-
- struct tm tmt2;
-
- // __DATE__
- // The compilation date of the current source file. The date is a string
- // literal of the form Mmm dd yyyy. The month name Mmm is the same as for
- // dates generated by the library function asctime declared in TIME.H.
-
- // index: 012345678901
- // format: Mmm dd yyyy
- // example: Dec 19 2003
-
- static char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
-
- char buffer[12];
- strcpy(buffer, str);
-
- buffer[3] = 0;
- char* ptr = strstr(month_names, buffer);
- if (!ptr) {
- return false;
- }
-
- int month = static_cast<int>((ptr - month_names) / 3);
- int day = atoi(buffer + 4);
- int year = atoi(buffer + 7);
-
- tmt2.tm_isdst = -1;
- tmt2.tm_hour = 0;
- tmt2.tm_min = 0;
- tmt2.tm_sec = 0;
- tmt2.tm_wday = 0;
- tmt2.tm_yday = 0;
- tmt2.tm_mday = day;
- tmt2.tm_mon = month;
- tmt2.tm_year = year - 1900;
-
- *tmt = mktime(&tmt2);
- return true;
-}
-
-bool SystemTools::ConvertTimeStampMacroString(const char* str, time_t* tmt)
-{
- if (!str || !tmt || strlen(str) > 26) {
- return false;
- }
-
- struct tm tmt2;
-
- // __TIMESTAMP__
- // The date and time of the last modification of the current source file,
- // expressed as a string literal in the form Ddd Mmm Date hh:mm:ss yyyy,
- /// where Ddd is the abbreviated day of the week and Date is an integer
- // from 1 to 31.
-
- // index: 0123456789
- // 0123456789
- // 0123456789
- // format: Ddd Mmm Date hh:mm:ss yyyy
- // example: Fri Dec 19 14:34:58 2003
-
- static char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
-
- char buffer[27];
- strcpy(buffer, str);
-
- buffer[7] = 0;
- char* ptr = strstr(month_names, buffer + 4);
- if (!ptr) {
- return false;
- }
-
- int month = static_cast<int>((ptr - month_names) / 3);
- int day = atoi(buffer + 8);
- int hour = atoi(buffer + 11);
- int min = atoi(buffer + 14);
- int sec = atoi(buffer + 17);
- int year = atoi(buffer + 20);
-
- tmt2.tm_isdst = -1;
- tmt2.tm_hour = hour;
- tmt2.tm_min = min;
- tmt2.tm_sec = sec;
- tmt2.tm_wday = 0;
- tmt2.tm_yday = 0;
- tmt2.tm_mday = day;
- tmt2.tm_mon = month;
- tmt2.tm_year = year - 1900;
-
- *tmt = mktime(&tmt2);
- return true;
-}
-
std::string SystemTools::GetLastSystemError()
{
int e = errno;
return strerror(e);
}
-#ifdef _WIN32
-
-static bool IsJunction(const std::wstring& source)
-{
-#ifdef FSCTL_GET_REPARSE_POINT
- const DWORD JUNCTION_ATTRS =
- FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT;
- DWORD attrs = GetFileAttributesW(source.c_str());
- if (attrs == INVALID_FILE_ATTRIBUTES) {
- return false;
- }
- if ((attrs & JUNCTION_ATTRS) != JUNCTION_ATTRS) {
- return false;
- }
-
- // Adjust privileges so that we can succefully open junction points.
- HANDLE token;
- TOKEN_PRIVILEGES privs;
- OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token);
- LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &privs.Privileges[0].Luid);
- privs.PrivilegeCount = 1;
- privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- AdjustTokenPrivileges(token, FALSE, &privs, sizeof(TOKEN_PRIVILEGES), NULL,
- NULL);
- CloseHandle(token);
-
- HANDLE dir = CreateFileW(
- source.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING,
- FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (dir == INVALID_HANDLE_VALUE) {
- return false;
- }
-
- // Query whether this is a reparse point or not.
- BYTE buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
- REPARSE_GUID_DATA_BUFFER* reparse_buffer = (REPARSE_GUID_DATA_BUFFER*)buffer;
- DWORD sentinel;
-
- BOOL success =
- DeviceIoControl(dir, FSCTL_GET_REPARSE_POINT, NULL, 0, reparse_buffer,
- MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &sentinel, NULL);
-
- CloseHandle(dir);
-
- return (success &&
- (reparse_buffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT));
-#else
- return false;
-#endif
-}
-
-static bool DeleteJunction(const std::wstring& source)
-{
-#ifdef FSCTL_DELETE_REPARSE_POINT
- // Adjust privileges so that we can succefully open junction points as
- // read/write.
- HANDLE token;
- TOKEN_PRIVILEGES privs;
- OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token);
- LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &privs.Privileges[0].Luid);
- privs.PrivilegeCount = 1;
- privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- AdjustTokenPrivileges(token, FALSE, &privs, sizeof(TOKEN_PRIVILEGES), NULL,
- NULL);
- CloseHandle(token);
-
- HANDLE dir = CreateFileW(
- source.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
- FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (dir == INVALID_HANDLE_VALUE) {
- return false;
- }
-
- // Set up the structure so that we can delete the junction.
- std::vector<BYTE> buffer(REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, 0);
- REPARSE_GUID_DATA_BUFFER* reparse_buffer =
- (REPARSE_GUID_DATA_BUFFER*)&buffer[0];
- DWORD sentinel;
-
- reparse_buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
-
- BOOL success = DeviceIoControl(
- dir, FSCTL_DELETE_REPARSE_POINT, reparse_buffer,
- REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, NULL, 0, &sentinel, NULL);
-
- CloseHandle(dir);
-
- return !!success;
-#else
- return false;
-#endif
-}
-
-#endif
-
bool SystemTools::RemoveFile(const std::string& source)
{
#ifdef _WIN32
@@ -2595,7 +2633,13 @@ bool SystemTools::RemoveFile(const std::string& source)
SetLastError(err);
return false;
}
- if (IsJunction(ws) && DeleteJunction(ws)) {
+
+ 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 ||
@@ -2626,11 +2670,7 @@ bool SystemTools::RemoveADirectory(const std::string& source)
}
Directory dir;
-#ifdef _WIN32
- dir.Load(Encoding::ToNarrow(Encoding::ToWindowsExtendedPath(source)));
-#else
dir.Load(source);
-#endif
size_t fileNum;
for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) {
if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") &&
@@ -2666,9 +2706,9 @@ size_t SystemTools::GetMaximumFilePathLength()
* the system search path. Returns the full path to the file if it is
* found. Otherwise, the empty string is returned.
*/
-std::string SystemTools::FindName(const std::string& name,
- const std::vector<std::string>& userPaths,
- bool no_system_path)
+std::string SystemToolsStatic::FindName(
+ const std::string& name, const std::vector<std::string>& userPaths,
+ bool no_system_path)
{
// Add the system search path to our path first
std::vector<std::string> path;
@@ -2677,27 +2717,15 @@ std::string SystemTools::FindName(const std::string& name,
SystemTools::GetPath(path);
}
// now add the additional paths
- {
- for (std::vector<std::string>::const_iterator i = userPaths.begin();
- i != userPaths.end(); ++i) {
- path.push_back(*i);
- }
- }
- // Add a trailing slash to all paths to aid the search process.
- {
- for (std::vector<std::string>::iterator i = path.begin(); i != path.end();
- ++i) {
- std::string& p = *i;
- if (p.empty() || *p.rbegin() != '/') {
- p += "/";
- }
- }
- }
+ path.reserve(path.size() + userPaths.size());
+ path.insert(path.end(), userPaths.begin(), userPaths.end());
// now look for the file
std::string tryPath;
- for (std::vector<std::string>::const_iterator p = path.begin();
- p != path.end(); ++p) {
- tryPath = *p;
+ for (std::string const& p : path) {
+ tryPath = p;
+ if (tryPath.empty() || tryPath.back() != '/') {
+ tryPath += '/';
+ }
tryPath += name;
if (SystemTools::FileExists(tryPath)) {
return tryPath;
@@ -2716,7 +2744,8 @@ std::string SystemTools::FindFile(const std::string& name,
const std::vector<std::string>& userPaths,
bool no_system_path)
{
- std::string tryPath = SystemTools::FindName(name, userPaths, no_system_path);
+ std::string tryPath =
+ SystemToolsStatic::FindName(name, userPaths, no_system_path);
if (!tryPath.empty() && !SystemTools::FileIsDirectory(tryPath)) {
return SystemTools::CollapseFullPath(tryPath);
}
@@ -2733,7 +2762,8 @@ std::string SystemTools::FindDirectory(
const std::string& name, const std::vector<std::string>& userPaths,
bool no_system_path)
{
- std::string tryPath = SystemTools::FindName(name, userPaths, no_system_path);
+ std::string tryPath =
+ SystemToolsStatic::FindName(name, userPaths, no_system_path);
if (!tryPath.empty() && SystemTools::FileIsDirectory(tryPath)) {
return SystemTools::CollapseFullPath(tryPath);
}
@@ -2769,14 +2799,13 @@ std::string SystemTools::FindProgram(const std::string& name,
// the end of it
// on windows try .com then .exe
if (name.size() <= 3 || name[name.size() - 4] != '.') {
- extensions.push_back(".com");
- extensions.push_back(".exe");
+ extensions.emplace_back(".com");
+ extensions.emplace_back(".exe");
// first try with extensions if the os supports them
- for (std::vector<std::string>::iterator i = extensions.begin();
- i != extensions.end(); ++i) {
+ for (std::string const& ext : extensions) {
tryPath = name;
- tryPath += *i;
+ tryPath += ext;
if (SystemTools::FileExists(tryPath, true)) {
return SystemTools::CollapseFullPath(tryPath);
}
@@ -2795,43 +2824,33 @@ std::string SystemTools::FindProgram(const std::string& name,
SystemTools::GetPath(path);
}
// now add the additional paths
- {
- for (std::vector<std::string>::const_iterator i = userPaths.begin();
- i != userPaths.end(); ++i) {
- path.push_back(*i);
- }
- }
+ path.reserve(path.size() + userPaths.size());
+ path.insert(path.end(), userPaths.begin(), userPaths.end());
// Add a trailing slash to all paths to aid the search process.
- {
- for (std::vector<std::string>::iterator i = path.begin(); i != path.end();
- ++i) {
- std::string& p = *i;
- if (p.empty() || *p.rbegin() != '/') {
- p += "/";
- }
+ for (std::string& p : path) {
+ if (p.empty() || p.back() != '/') {
+ p += '/';
}
}
// Try each path
- for (std::vector<std::string>::iterator p = path.begin(); p != path.end();
- ++p) {
+ for (std::string& p : path) {
#ifdef _WIN32
// Remove double quotes from the path on windows
- SystemTools::ReplaceString(*p, "\"", "");
+ SystemTools::ReplaceString(p, "\"", "");
#endif
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
// first try with extensions
- for (std::vector<std::string>::iterator ext = extensions.begin();
- ext != extensions.end(); ++ext) {
- tryPath = *p;
+ for (std::string const& ext : extensions) {
+ tryPath = p;
tryPath += name;
- tryPath += *ext;
+ tryPath += ext;
if (SystemTools::FileExists(tryPath, true)) {
return SystemTools::CollapseFullPath(tryPath);
}
}
#endif
// now try it without them
- tryPath = *p;
+ tryPath = p;
tryPath += name;
if (SystemTools::FileExists(tryPath, true)) {
return SystemTools::CollapseFullPath(tryPath);
@@ -2845,10 +2864,9 @@ std::string SystemTools::FindProgram(const std::vector<std::string>& names,
const std::vector<std::string>& path,
bool noSystemPath)
{
- for (std::vector<std::string>::const_iterator it = names.begin();
- it != names.end(); ++it) {
+ for (std::string const& name : names) {
// Try to find the program.
- std::string result = SystemTools::FindProgram(*it, path, noSystemPath);
+ std::string result = SystemTools::FindProgram(name, path, noSystemPath);
if (!result.empty()) {
return result;
}
@@ -2873,27 +2891,18 @@ std::string SystemTools::FindLibrary(const std::string& name,
std::vector<std::string> path;
SystemTools::GetPath(path);
// now add the additional paths
- {
- for (std::vector<std::string>::const_iterator i = userPaths.begin();
- i != userPaths.end(); ++i) {
- path.push_back(*i);
- }
- }
+ path.reserve(path.size() + userPaths.size());
+ path.insert(path.end(), userPaths.begin(), userPaths.end());
// Add a trailing slash to all paths to aid the search process.
- {
- for (std::vector<std::string>::iterator i = path.begin(); i != path.end();
- ++i) {
- std::string& p = *i;
- if (p.empty() || *p.rbegin() != '/') {
- p += "/";
- }
+ for (std::string& p : path) {
+ if (p.empty() || p.back() != '/') {
+ p += '/';
}
}
std::string tryPath;
- for (std::vector<std::string>::const_iterator p = path.begin();
- p != path.end(); ++p) {
+ for (std::string const& p : path) {
#if defined(__APPLE__)
- tryPath = *p;
+ tryPath = p;
tryPath += name;
tryPath += ".framework";
if (SystemTools::FileIsDirectory(tryPath)) {
@@ -2901,42 +2910,42 @@ std::string SystemTools::FindLibrary(const std::string& name,
}
#endif
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
- tryPath = *p;
+ tryPath = p;
tryPath += name;
tryPath += ".lib";
if (SystemTools::FileExists(tryPath, true)) {
return SystemTools::CollapseFullPath(tryPath);
}
#else
- tryPath = *p;
+ tryPath = p;
tryPath += "lib";
tryPath += name;
tryPath += ".so";
if (SystemTools::FileExists(tryPath, true)) {
return SystemTools::CollapseFullPath(tryPath);
}
- tryPath = *p;
+ tryPath = p;
tryPath += "lib";
tryPath += name;
tryPath += ".a";
if (SystemTools::FileExists(tryPath, true)) {
return SystemTools::CollapseFullPath(tryPath);
}
- tryPath = *p;
+ tryPath = p;
tryPath += "lib";
tryPath += name;
tryPath += ".sl";
if (SystemTools::FileExists(tryPath, true)) {
return SystemTools::CollapseFullPath(tryPath);
}
- tryPath = *p;
+ tryPath = p;
tryPath += "lib";
tryPath += name;
tryPath += ".dylib";
if (SystemTools::FileExists(tryPath, true)) {
return SystemTools::CollapseFullPath(tryPath);
}
- tryPath = *p;
+ tryPath = p;
tryPath += "lib";
tryPath += name;
tryPath += ".dll";
@@ -3001,10 +3010,36 @@ bool SystemTools::FileIsDirectory(const std::string& inName)
bool SystemTools::FileIsSymlink(const std::string& name)
{
#if defined(_WIN32)
- DWORD attr =
- GetFileAttributesW(Encoding::ToWindowsExtendedPath(name).c_str());
+ std::wstring path = Encoding::ToWindowsExtendedPath(name);
+ DWORD attr = GetFileAttributesW(path.c_str());
if (attr != INVALID_FILE_ATTRIBUTES) {
- return (attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
+ if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
+ // FILE_ATTRIBUTE_REPARSE_POINT means:
+ // * a file or directory that has an associated reparse point, or
+ // * a file that is a symbolic link.
+ HANDLE hFile = CreateFileW(
+ path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, nullptr);
+ if (hFile == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+ byte buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+ DWORD bytesReturned = 0;
+ if (!DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, nullptr, 0, buffer,
+ MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bytesReturned,
+ nullptr)) {
+ CloseHandle(hFile);
+ // Since FILE_ATTRIBUTE_REPARSE_POINT is set this file must be
+ // a symbolic link if it is not a reparse point.
+ return GetLastError() == ERROR_NOT_A_REPARSE_POINT;
+ }
+ CloseHandle(hFile);
+ ULONG reparseTag =
+ reinterpret_cast<PREPARSE_GUID_DATA_BUFFER>(&buffer[0])->ReparseTag;
+ return (reparseTag == IO_REPARSE_TAG_SYMLINK) ||
+ (reparseTag == IO_REPARSE_TAG_MOUNT_POINT);
+ }
+ return false;
} else {
return false;
}
@@ -3023,7 +3058,7 @@ bool SystemTools::FileIsFIFO(const std::string& name)
#if defined(_WIN32)
HANDLE hFile =
CreateFileW(Encoding::ToWide(name).c_str(), GENERIC_READ, FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
if (hFile == INVALID_HANDLE_VALUE) {
return false;
}
@@ -3172,9 +3207,8 @@ bool SystemTools::FindProgramPath(const char* argv0, std::string& pathOut,
msg << " argv[0] = \"" << argv0 << "\"\n";
}
msg << " Attempted paths:\n";
- std::vector<std::string>::iterator i;
- for (i = failures.begin(); i != failures.end(); ++i) {
- msg << " \"" << *i << "\"\n";
+ for (std::string const& ff : failures) {
+ msg << " \"" << ff << "\"\n";
}
errorMsg = msg.str();
return false;
@@ -3185,9 +3219,10 @@ 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, nullptr);
}
+#if KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP
void SystemTools::AddTranslationPath(const std::string& a,
const std::string& b)
{
@@ -3204,15 +3239,16 @@ void SystemTools::AddTranslationPath(const std::string& a,
if (SystemTools::FileIsFullPath(path_b) &&
path_b.find("..") == std::string::npos) {
// Before inserting make sure path ends with '/'
- if (!path_a.empty() && *path_a.rbegin() != '/') {
+ if (!path_a.empty() && path_a.back() != '/') {
path_a += '/';
}
- if (!path_b.empty() && *path_b.rbegin() != '/') {
+ if (!path_b.empty() && path_b.back() != '/') {
path_b += '/';
}
if (!(path_a == path_b)) {
- SystemTools::TranslationMap->insert(
- SystemToolsTranslationMap::value_type(path_a, path_b));
+ SystemTools::Statics->TranslationMap.insert(
+ SystemToolsStatic::StringMap::value_type(std::move(path_a),
+ std::move(path_b)));
}
}
}
@@ -3221,7 +3257,7 @@ void SystemTools::AddTranslationPath(const std::string& a,
void SystemTools::AddKeepPath(const std::string& dir)
{
std::string cdir;
- Realpath(SystemTools::CollapseFullPath(dir).c_str(), cdir);
+ Realpath(SystemTools::CollapseFullPath(dir), cdir);
SystemTools::AddTranslationPath(cdir, dir);
}
@@ -3236,37 +3272,41 @@ void SystemTools::CheckTranslationPath(std::string& path)
// Always add a trailing slash before translation. It does not
// matter if this adds an extra slash, but we do not want to
// translate part of a directory (like the foo part of foo-dir).
- path += "/";
+ path += '/';
// In case a file was specified we still have to go through this:
// Now convert any path found in the table back to the one desired:
- std::map<std::string, std::string>::const_iterator it;
- for (it = SystemTools::TranslationMap->begin();
- it != SystemTools::TranslationMap->end(); ++it) {
+ for (auto const& pair : SystemTools::Statics->TranslationMap) {
// We need to check of the path is a substring of the other path
- if (path.find(it->first) == 0) {
- path = path.replace(0, it->first.size(), it->second);
+ if (path.find(pair.first) == 0) {
+ path = path.replace(0, pair.first.size(), pair.second);
}
}
// Remove the trailing slash we added before.
- path.erase(path.end() - 1, path.end());
+ path.pop_back();
}
+#endif
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 = ".";
for (std::vector<std::string>::const_iterator i = first; i != last; ++i) {
if (*i == up) {
- if (out_components.size() > 1) {
+ // Remove the previous component if possible. Ignore ../ components
+ // that try to go above the root. Keep ../ components if they are
+ // at the beginning of a relative path (base path is relative).
+ if (out_components.size() > 1 && out_components.back() != up) {
out_components.resize(out_components.size() - 1);
+ } else if (!out_components.empty() && out_components[0].empty()) {
+ out_components.emplace_back(std::move(*i));
}
} else if (!i->empty() && *i != cur) {
- out_components.push_back(*i);
+ out_components.emplace_back(std::move(*i));
}
}
}
@@ -3274,63 +3314,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,
@@ -3342,9 +3337,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);
@@ -3362,6 +3358,7 @@ std::string SystemTools::CollapseFullPath(const std::string& in_path,
// Transform the path back to a string.
std::string newPath = SystemTools::JoinPath(out_components);
+#if KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP
// 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
@@ -3377,8 +3374,9 @@ std::string SystemTools::CollapseFullPath(const std::string& in_path,
// SystemTools::AddTranslationPath(newPath, in_path);
SystemTools::CheckTranslationPath(newPath);
+#endif
#ifdef _WIN32
- newPath = SystemTools::GetActualCaseForPath(newPath);
+ newPath = SystemTools::Statics->GetActualCaseForPathCached(newPath);
SystemTools::ConvertToUnixSlashes(newPath);
#endif
// Return the reconstructed path.
@@ -3400,25 +3398,24 @@ std::string SystemTools::RelativePath(const std::string& local,
std::string r = SystemTools::CollapseFullPath(remote);
// split up both paths into arrays of strings using / as a separator
- std::vector<kwsys::String> localSplit =
- SystemTools::SplitString(l, '/', true);
- std::vector<kwsys::String> remoteSplit =
+ std::vector<std::string> localSplit = SystemTools::SplitString(l, '/', true);
+ std::vector<std::string> remoteSplit =
SystemTools::SplitString(r, '/', true);
- std::vector<kwsys::String>
+ std::vector<std::string>
commonPath; // store shared parts of path in this array
- std::vector<kwsys::String> finalPath; // store the final relative path here
+ std::vector<std::string> finalPath; // store the final relative path here
// count up how many matching directory names there are from the start
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
#else
localSplit[sameCount] == remoteSplit[sameCount]
#endif
- ) {
+ ) {
// put the common parts of the path into the commonPath array
commonPath.push_back(localSplit[sameCount]);
// erase the common parts of the path from the original path arrays
@@ -3439,115 +3436,36 @@ std::string SystemTools::RelativePath(const std::string& local,
// for each entry that is not common in the local path
// add a ../ to the finalpath array, this gets us out of the local
// path into the remote dir
- for (unsigned int i = 0; i < localSplit.size(); ++i) {
- if (!localSplit[i].empty()) {
- finalPath.push_back("../");
+ for (std::string const& lp : localSplit) {
+ if (!lp.empty()) {
+ finalPath.emplace_back("../");
}
}
// for each entry that is not common in the remote path add it
// to the final path.
- for (std::vector<String>::iterator vit = remoteSplit.begin();
- vit != remoteSplit.end(); ++vit) {
- if (!vit->empty()) {
- finalPath.push_back(*vit);
+ for (std::string const& rp : remoteSplit) {
+ if (!rp.empty()) {
+ finalPath.push_back(rp);
}
}
std::string relativePath; // result string
// now turn the array of directories into a unix path by puttint /
// between each entry that does not already have one
- for (std::vector<String>::iterator vit1 = finalPath.begin();
- vit1 != finalPath.end(); ++vit1) {
- if (!relativePath.empty() && *relativePath.rbegin() != '/') {
- relativePath += "/";
+ for (std::string const& fp : finalPath) {
+ if (!relativePath.empty() && relativePath.back() != '/') {
+ relativePath += '/';
}
- relativePath += *vit1;
+ relativePath += fp;
}
return relativePath;
}
-#ifdef _WIN32
-static std::string GetCasePathName(std::string const& pathIn)
-{
- std::string casePath;
- std::vector<std::string> path_components;
- SystemTools::SplitPath(pathIn, path_components);
- if (path_components[0].empty()) // First component always exists.
- {
- // Relative paths cannot be converted.
- casePath = pathIn;
- return casePath;
- }
-
- // Start with root component.
- std::vector<std::string>::size_type idx = 0;
- casePath = path_components[idx++];
- // make sure drive letter is always upper case
- if (casePath.size() > 1 && casePath[1] == ':') {
- casePath[0] = toupper(casePath[0]);
- }
- const char* sep = "";
-
- // If network path, fill casePath with server/share so FindFirstFile
- // will work after that. Maybe someday call other APIs to get
- // actual case of servers and shares.
- if (path_components.size() > 2 && path_components[0] == "//") {
- casePath += path_components[idx++];
- casePath += "/";
- casePath += path_components[idx++];
- sep = "/";
- }
-
- // Convert case of all components that exist.
- bool converting = true;
- for (; idx < path_components.size(); idx++) {
- casePath += sep;
- sep = "/";
-
- if (converting) {
- // If path component contains wildcards, we skip matching
- // because these filenames are not allowed on windows,
- // and we do not want to match a different file.
- if (path_components[idx].find('*') != std::string::npos ||
- path_components[idx].find('?') != std::string::npos) {
- converting = false;
- } else {
- std::string test_str = casePath;
- test_str += path_components[idx];
- WIN32_FIND_DATAW findData;
- HANDLE hFind =
- ::FindFirstFileW(Encoding::ToWide(test_str).c_str(), &findData);
- if (INVALID_HANDLE_VALUE != hFind) {
- path_components[idx] = Encoding::ToNarrow(findData.cFileName);
- ::FindClose(hFind);
- } else {
- converting = false;
- }
- }
- }
-
- casePath += path_components[idx];
- }
- return casePath;
-}
-#endif
-
std::string SystemTools::GetActualCaseForPath(const std::string& p)
{
-#ifndef _WIN32
- return p;
+#ifdef _WIN32
+ return SystemToolsStatic::GetCasePathName(p);
#else
- // 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);
- if (i != SystemTools::PathCaseMap->end()) {
- return i->second;
- }
- std::string casePath = GetCasePathName(p);
- if (casePath.size() > MAX_PATH) {
- return casePath;
- }
- (*SystemTools::PathCaseMap)[p] = casePath;
- return casePath;
+ return p;
#endif
}
@@ -3647,7 +3565,7 @@ void SystemTools::SplitPath(const std::string& p,
}
#endif
if (!homedir.empty() &&
- (*homedir.rbegin() == '/' || *homedir.rbegin() == '\\')) {
+ (homedir.back() == '/' || homedir.back() == '\\')) {
homedir.resize(homedir.size() - 1);
}
SystemTools::SplitPath(homedir, components);
@@ -3685,8 +3603,7 @@ std::string SystemTools::JoinPath(
// Construct result in a single string.
std::string result;
size_t len = 0;
- std::vector<std::string>::const_iterator i;
- for (i = first; i != last; ++i) {
+ for (std::vector<std::string>::const_iterator i = first; i != last; ++i) {
len += 1 + i->size();
}
result.reserve(len);
@@ -3701,7 +3618,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++));
}
@@ -3709,26 +3626,16 @@ std::string SystemTools::JoinPath(
return result;
}
-void SystemTools::RemoveEmptyPathElements(std::vector<std::string>& path)
-{
- if (path.empty()) {
- return;
- }
-
- path.erase(std::remove(path.begin() + 1, path.end(), std::string("")),
- path.end());
-}
-
bool SystemTools::ComparePath(const std::string& c1, const std::string& c2)
{
#if defined(_WIN32) || defined(__APPLE__)
-#ifdef _MSC_VER
+# ifdef _MSC_VER
return _stricmp(c1.c_str(), c2.c_str()) == 0;
-#elif defined(__APPLE__) || defined(__GNUC__)
+# elif defined(__APPLE__) || defined(__GNUC__)
return strcasecmp(c1.c_str(), c2.c_str()) == 0;
-#else
+# else
return SystemTools::Strucmp(c1.c_str(), c2.c_str()) == 0;
-#endif
+# endif
#else
return c1 == c2;
#endif
@@ -3742,11 +3649,11 @@ bool SystemTools::Split(const std::string& str,
while (lpos < data.length()) {
std::string::size_type rpos = data.find_first_of(separator, lpos);
if (rpos == std::string::npos) {
- // Line ends at end of string without a newline.
+ // String ends at end of string without a separator.
lines.push_back(data.substr(lpos));
return false;
} else {
- // Line ends in a "\n", remove the character.
+ // String ends in a separator, remove the character.
lines.push_back(data.substr(lpos, rpos - lpos));
}
lpos = rpos + 1;
@@ -3760,7 +3667,7 @@ bool SystemTools::Split(const std::string& str,
std::string data(str);
std::string::size_type lpos = 0;
while (lpos < data.length()) {
- std::string::size_type rpos = data.find_first_of("\n", lpos);
+ std::string::size_type rpos = data.find_first_of('\n', lpos);
if (rpos == std::string::npos) {
// Line ends at end of string without a newline.
lines.push_back(data.substr(lpos));
@@ -3807,11 +3714,12 @@ std::string SystemTools::GetFilenamePath(const std::string& filename)
*/
std::string SystemTools::GetFilenameName(const std::string& filename)
{
-#if defined(_WIN32)
- std::string::size_type slash_pos = filename.find_last_of("/\\");
+#if defined(_WIN32) || defined(KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES)
+ const char* separators = "/\\";
#else
- std::string::size_type slash_pos = filename.rfind('/');
+ 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 {
@@ -4024,7 +3932,7 @@ bool SystemTools::LocateFileInDir(const char* filename, const char* dir,
filename_dir = SystemTools::GetFilenamePath(filename_dir);
filename_dir_base = SystemTools::GetFilenameName(filename_dir);
#if defined(_WIN32)
- if (filename_dir_base.empty() || *filename_dir_base.rbegin() == ':')
+ if (filename_dir_base.empty() || filename_dir_base.back() == ':')
#else
if (filename_dir_base.empty())
#endif
@@ -4052,16 +3960,16 @@ bool SystemTools::LocateFileInDir(const char* filename, const char* dir,
bool SystemTools::FileIsFullPath(const std::string& in_name)
{
- return SystemTools::FileIsFullPath(in_name.c_str(), in_name.size());
+ return SystemToolsStatic::FileIsFullPath(in_name.c_str(), in_name.size());
}
bool SystemTools::FileIsFullPath(const char* in_name)
{
- return SystemTools::FileIsFullPath(in_name,
- in_name[0] ? (in_name[1] ? 2 : 1) : 0);
+ return SystemToolsStatic::FileIsFullPath(
+ in_name, in_name[0] ? (in_name[1] ? 2 : 1) : 0);
}
-bool SystemTools::FileIsFullPath(const char* in_name, size_t len)
+bool SystemToolsStatic::FileIsFullPath(const char* in_name, size_t len)
{
#if defined(_WIN32) || defined(__CYGWIN__)
// On Windows, the name must be at least two characters long.
@@ -4100,12 +4008,12 @@ bool SystemTools::GetShortPath(const std::string& path, std::string& shortPath)
std::string tempPath = path; // create a buffer
// if the path passed in has quotes around it, first remove the quotes
- if (!path.empty() && path[0] == '"' && *path.rbegin() == '"') {
+ if (!path.empty() && path[0] == '"' && path.back() == '"') {
tempPath = path.substr(1, path.length() - 2);
}
std::wstring wtempPath = Encoding::ToWide(tempPath);
- DWORD ret = GetShortPathNameW(wtempPath.c_str(), NULL, 0);
+ DWORD ret = GetShortPathNameW(wtempPath.c_str(), nullptr, 0);
std::vector<wchar_t> buffer(ret);
if (ret != 0) {
ret = GetShortPathNameW(wtempPath.c_str(), &buffer[0],
@@ -4124,66 +4032,6 @@ bool SystemTools::GetShortPath(const std::string& path, std::string& shortPath)
#endif
}
-void SystemTools::SplitProgramFromArgs(const std::string& path,
- std::string& program, std::string& args)
-{
- // see if this is a full path to a program
- // if so then set program to path and args to nothing
- if (SystemTools::FileExists(path)) {
- program = path;
- args = "";
- return;
- }
- // Try to find the program in the path, note the program
- // may have spaces in its name so we have to look for it
- std::vector<std::string> e;
- std::string findProg = SystemTools::FindProgram(path, e);
- if (!findProg.empty()) {
- program = findProg;
- args = "";
- return;
- }
-
- // Now try and peel off space separated chunks from the end of the string
- // so the largest path possible is found allowing for spaces in the path
- std::string dir = path;
- std::string::size_type spacePos = dir.rfind(' ');
- while (spacePos != std::string::npos) {
- std::string tryProg = dir.substr(0, spacePos);
- // See if the file exists
- if (SystemTools::FileExists(tryProg)) {
- program = tryProg;
- // remove trailing spaces from program
- std::string::size_type pos = program.size() - 1;
- while (program[pos] == ' ') {
- program.erase(pos);
- pos--;
- }
- args = dir.substr(spacePos, dir.size() - spacePos);
- return;
- }
- // Now try and find the program in the path
- findProg = SystemTools::FindProgram(tryProg, e);
- if (!findProg.empty()) {
- program = findProg;
- // remove trailing spaces from program
- std::string::size_type pos = program.size() - 1;
- while (program[pos] == ' ') {
- program.erase(pos);
- pos--;
- }
- args = dir.substr(spacePos, dir.size() - spacePos);
- return;
- }
- // move past the space for the next search
- spacePos--;
- spacePos = dir.rfind(' ', spacePos);
- }
-
- program = "";
- args = "";
-}
-
std::string SystemTools::GetCurrentDateTime(const char* format)
{
char buf[1024];
@@ -4212,23 +4060,16 @@ std::string SystemTools::MakeCidentifier(const std::string& s)
return str;
}
-// Due to a buggy stream library on the HP and another on Mac OS X, we
-// need this very carefully written version of getline. Returns true
+// Convenience function around std::getline which removes a trailing carriage
+// return and can truncate the buffer as needed. Returns true
// if any data were read before the end-of-file was reached.
bool SystemTools::GetLineFromStream(std::istream& is, std::string& line,
bool* has_newline /* = 0 */,
long sizeLimit /* = -1 */)
{
- const int bufferSize = 1024;
- char buffer[bufferSize];
- bool haveData = false;
- bool haveNewline = false;
-
// Start with an empty line.
line = "";
- long leftToRead = sizeLimit;
-
// Early short circuit return if stream is no good. Just return
// false and the empty line. (Probably means caller tried to
// create a file stream with a non-existent file name...)
@@ -4240,44 +4081,23 @@ bool SystemTools::GetLineFromStream(std::istream& is, std::string& line,
return false;
}
- // If no characters are read from the stream, the end of file has
- // been reached. Clear the fail bit just before reading.
- while (!haveNewline && leftToRead != 0 &&
- (static_cast<void>(is.clear(is.rdstate() & ~std::ios::failbit)),
- static_cast<void>(is.getline(buffer, bufferSize)),
- is.gcount() > 0)) {
- // We have read at least one byte.
- haveData = true;
-
- // If newline character was read the gcount includes the character
- // but the buffer does not: the end of line has been reached.
- size_t length = strlen(buffer);
- if (length < static_cast<size_t>(is.gcount())) {
- haveNewline = true;
- }
-
+ std::getline(is, line);
+ bool haveData = !line.empty() || !is.eof();
+ if (!line.empty()) {
// Avoid storing a carriage return character.
- if (length > 0 && buffer[length - 1] == '\r') {
- buffer[length - 1] = 0;
+ if (line.back() == '\r') {
+ line.resize(line.size() - 1);
}
// if we read too much then truncate the buffer
- if (leftToRead > 0) {
- if (static_cast<long>(length) > leftToRead) {
- buffer[leftToRead] = 0;
- leftToRead = 0;
- } else {
- leftToRead -= static_cast<long>(length);
- }
+ if (sizeLimit >= 0 && line.size() >= static_cast<size_t>(sizeLimit)) {
+ line.resize(sizeLimit);
}
-
- // Append the data read to the line.
- line.append(buffer);
}
// Return the results.
if (has_newline) {
- *has_newline = haveNewline;
+ *has_newline = !is.eof();
}
return haveData;
}
@@ -4338,8 +4158,9 @@ bool SystemTools::GetPermissions(const std::string& file, mode_t& mode)
}
size_t dotPos = file.rfind('.');
const char* ext = dotPos == std::string::npos ? 0 : (file.c_str() + dotPos);
- if (ext && (Strucmp(ext, ".exe") == 0 || Strucmp(ext, ".com") == 0 ||
- Strucmp(ext, ".cmd") == 0 || Strucmp(ext, ".bat") == 0)) {
+ if (ext &&
+ (Strucmp(ext, ".exe") == 0 || Strucmp(ext, ".com") == 0 ||
+ Strucmp(ext, ".cmd") == 0 || Strucmp(ext, ".bat") == 0)) {
mode |= (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6));
}
#else
@@ -4399,11 +4220,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.back() == '/'; // 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)
@@ -4440,24 +4266,31 @@ std::string SystemTools::GetOperatingSystemNameAndVersion()
ZeroMemory(&osvi, sizeof(osvi));
osvi.dwOSVersionInfoSize = sizeof(osvi);
-#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(push)
-#ifdef __INTEL_COMPILER
-#pragma warning(disable : 1478)
-#else
-#pragma warning(disable : 4996)
-#endif
-#endif
+# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# pragma warning(push)
+# ifdef __INTEL_COMPILER
+# pragma warning(disable : 1478)
+# elif defined __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated-declarations"
+# else
+# pragma warning(disable : 4996)
+# endif
+# endif
bOsVersionInfoEx = GetVersionExA((OSVERSIONINFOA*)&osvi);
if (!bOsVersionInfoEx) {
return 0;
}
-#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
-#pragma warning(pop)
-#endif
+# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
+# ifdef __clang__
+# pragma clang diagnostic pop
+# else
+# pragma warning(pop)
+# endif
+# endif
switch (osvi.dwPlatformId) {
- // Test for the Windows NT product family.
+ // Test for the Windows NT product family.
case VER_PLATFORM_WIN32_NT:
@@ -4575,7 +4408,7 @@ std::string SystemTools::GetOperatingSystemNameAndVersion()
else {
HKEY hKey;
-#define BUFSIZE 80
+# define BUFSIZE 80
wchar_t szProductType[BUFSIZE];
DWORD dwBufLen = BUFSIZE;
LONG lRet;
@@ -4588,7 +4421,7 @@ std::string SystemTools::GetOperatingSystemNameAndVersion()
return 0;
}
- lRet = RegQueryValueExW(hKey, L"ProductType", NULL, NULL,
+ lRet = RegQueryValueExW(hKey, L"ProductType", nullptr, nullptr,
(LPBYTE)szProductType, &dwBufLen);
if ((lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE)) {
@@ -4657,7 +4490,7 @@ std::string SystemTools::GetOperatingSystemNameAndVersion()
break;
- // Test for the Windows 95 product family.
+ // Test for the Windows 95 product family.
case VER_PLATFORM_WIN32_WINDOWS:
@@ -4741,14 +4574,7 @@ bool SystemTools::ParseURL(const std::string& URL, std::string& protocol,
// These must NOT be initialized. Default initialization to zero is
// necessary.
static unsigned int SystemToolsManagerCount;
-SystemToolsTranslationMap* SystemTools::TranslationMap;
-#ifdef _WIN32
-SystemToolsPathCaseMap* SystemTools::PathCaseMap;
-SystemToolsEnvMap* SystemTools::EnvMap;
-#endif
-#ifdef __CYGWIN__
-SystemToolsTranslationMap* SystemTools::Cyg2Win32Map;
-#endif
+SystemToolsStatic* SystemTools::Statics;
// SystemToolsManager manages the SystemTools singleton.
// SystemToolsManager should be included in any translation unit
@@ -4789,20 +4615,15 @@ void SystemTools::ClassInitialize()
#ifdef __VMS
SetVMSFeature("DECC$FILENAME_UNIX_ONLY", 1);
#endif
- // Allocate the translation map first.
- SystemTools::TranslationMap = new SystemToolsTranslationMap;
-#ifdef _WIN32
- SystemTools::PathCaseMap = new SystemToolsPathCaseMap;
- SystemTools::EnvMap = new SystemToolsEnvMap;
-#endif
-#ifdef __CYGWIN__
- SystemTools::Cyg2Win32Map = new SystemToolsTranslationMap;
-#endif
+ // Create statics singleton instance
+ SystemTools::Statics = new SystemToolsStatic;
+
+#if KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP
// Add some special translation paths for unix. These are not added
// for windows because drive letters need to be maintained. Also,
// there are not sym-links and mount points on windows anyway.
-#if !defined(_WIN32) || defined(__CYGWIN__)
+# if !defined(_WIN32) || defined(__CYGWIN__)
// The tmp path is frequently a logical path so always keep it:
SystemTools::AddKeepPath("/tmp/");
@@ -4821,7 +4642,7 @@ void SystemTools::ClassInitialize()
// Test progressively shorter logical-to-physical mappings.
std::string cwd_str = cwd;
std::string pwd_path;
- Realpath(pwd_str.c_str(), pwd_path);
+ Realpath(pwd_str, pwd_path);
while (cwd_str == pwd_path && cwd_str != pwd_str) {
// The current pair of paths is a working logical mapping.
cwd_changed = cwd_str;
@@ -4831,7 +4652,7 @@ void SystemTools::ClassInitialize()
// mapping still works.
pwd_str = SystemTools::GetFilenamePath(pwd_str);
cwd_str = SystemTools::GetFilenamePath(cwd_str);
- Realpath(pwd_str.c_str(), pwd_path);
+ Realpath(pwd_str, pwd_path);
}
// Add the translation to keep the logical path name.
@@ -4840,27 +4661,21 @@ void SystemTools::ClassInitialize()
}
}
}
+# endif
#endif
}
void SystemTools::ClassFinalize()
{
- delete SystemTools::TranslationMap;
-#ifdef _WIN32
- delete SystemTools::PathCaseMap;
- delete SystemTools::EnvMap;
-#endif
-#ifdef __CYGWIN__
- delete SystemTools::Cyg2Win32Map;
-#endif
+ delete SystemTools::Statics;
}
} // namespace KWSYS_NAMESPACE
#if defined(_MSC_VER) && defined(_DEBUG)
-#include <crtdbg.h>
-#include <stdio.h>
-#include <stdlib.h>
+# include <crtdbg.h>
+# include <stdio.h>
+# include <stdlib.h>
namespace KWSYS_NAMESPACE {
static int SystemToolsDebugReport(int, char* message, int*)
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index 5e091c2af..c4ab9d4f3 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -10,14 +10,12 @@
#include <string>
#include <vector>
-#include <@KWSYS_NAMESPACE@/String.hxx>
-
#include <sys/types.h>
// include sys/stat.h after sys/types.h
#include <sys/stat.h>
#if !defined(_WIN32) || defined(__CYGWIN__)
-#include <unistd.h> // For access permissions for use with access()
+# include <unistd.h> // For access permissions for use with access()
#endif
// Required for va_list
@@ -43,9 +41,7 @@ typedef @KWSYS_NAMESPACE@_VA_LIST::hack_va_list va_list;
namespace @KWSYS_NAMESPACE@ {
-class SystemToolsTranslationMap;
-class SystemToolsPathCaseMap;
-class SystemToolsEnvMap;
+class SystemToolsStatic;
/** \class SystemToolsManager
* \brief Use to make sure SystemTools is initialized before it is used
@@ -56,6 +52,9 @@ class @KWSYS_NAMESPACE@_EXPORT SystemToolsManager
public:
SystemToolsManager();
~SystemToolsManager();
+
+ SystemToolsManager(const SystemToolsManager&) = delete;
+ SystemToolsManager& operator=(const SystemToolsManager&) = delete;
};
// This instance will show up in any translation unit that uses
@@ -107,7 +106,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 +174,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);
@@ -197,22 +196,15 @@ public:
s starts with a / then the first element of the returned array will
be /, so /foo/bar will be [/, foo, bar]
*/
- static std::vector<String> SplitString(const std::string& s,
- char separator = '/',
- bool isPath = false);
+ static std::vector<std::string> SplitString(const std::string& s,
+ char separator = '/',
+ bool isPath = false);
/**
* Perform a case-independent string comparison
*/
static int Strucmp(const char* s1, const char* s2);
/**
- * Convert a string in __DATE__ or __TIMESTAMP__ format into a time_t.
- * Return false on error, true on success
- */
- static bool ConvertDateMacroString(const char* str, time_t* tmt);
- static bool ConvertTimeStampMacroString(const char* str, time_t* tmt);
-
- /**
* Split a string on its newlines into multiple lines
* Return false only if the last line stored had no newline
*/
@@ -325,11 +317,11 @@ public:
* Cross platform wrapper for stat struct
*/
#if defined(_WIN32) && !defined(__CYGWIN__)
-#if defined(__BORLANDC__)
+# if defined(__BORLANDC__)
typedef struct stati64 Stat_t;
-#else
+# else
typedef struct _stat64 Stat_t;
-#endif
+# endif
#else
typedef struct stat Stat_t;
#endif
@@ -408,9 +400,10 @@ public:
* installPrefix is a possibly null pointer to the install directory.
*/
static bool FindProgramPath(const char* argv0, std::string& pathOut,
- std::string& errorMsg, const char* exeName = 0,
- const char* buildDir = 0,
- const char* installPrefix = 0);
+ std::string& errorMsg,
+ const char* exeName = nullptr,
+ const char* buildDir = nullptr,
+ const char* installPrefix = nullptr);
/**
* Given a path to a file or directory, convert it to a full path.
@@ -428,11 +421,11 @@ public:
* Get the real path for a given path, removing all symlinks. In
* the event of an error (non-existent path, permissions issue,
* etc.) the original path is returned if errorMessage pointer is
- * NULL. Otherwise empty string is returned and errorMessage
+ * nullptr. Otherwise empty string is returned and errorMessage
* contains error description.
*/
static std::string GetRealPath(const std::string& path,
- std::string* errorMessage = 0);
+ std::string* errorMessage = nullptr);
/**
* Split a path name into its root component and the rest of the
@@ -450,7 +443,7 @@ public:
* given.
*/
static const char* SplitPathRootComponent(const std::string& p,
- std::string* root = 0);
+ std::string* root = nullptr);
/**
* Split a path name into its basic components. The first component
@@ -461,6 +454,10 @@ public:
* produce the original path. Home directory references are
* automatically expanded if expand_home_dir is true and this
* platform supports them.
+ *
+ * This does *not* normalize the input path. All components are
+ * preserved, including empty ones. Typically callers should use
+ * this only on paths that have already been normalized.
*/
static void SplitPath(const std::string& p,
std::vector<std::string>& components,
@@ -469,15 +466,15 @@ public:
/**
* Join components of a path name into a single string. See
* SplitPath for the format of the components.
+ *
+ * This does *not* normalize the input path. All components are
+ * preserved, including empty ones. Typically callers should use
+ * this only on paths that have already been normalized.
*/
static std::string JoinPath(const std::vector<std::string>& components);
static std::string JoinPath(std::vector<std::string>::const_iterator first,
std::vector<std::string>::const_iterator last);
- /** Removes empty components from path.
- */
- static void RemoveEmptyPathElements(std::vector<std::string>& path);
-
/**
* Compare a path or components of a path.
*/
@@ -494,12 +491,6 @@ public:
static std::string GetFilenameName(const std::string&);
/**
- * Split a program from its arguments and handle spaces in the paths
- */
- static void SplitProgramFromArgs(const std::string& path,
- std::string& program, std::string& args);
-
- /**
* Return longest file extension of a full filename (dot included)
*/
static std::string GetFilenameExtension(const std::string&);
@@ -532,14 +523,14 @@ public:
static bool GetShortPath(const std::string& path, std::string& result);
/**
- * Read line from file. Make sure to get everything. Due to a buggy stream
- * library on the HP and another on Mac OS X, we need this very carefully
- * written version of getline. Returns true if any data were read before the
+ * Read line from file. Make sure to read a full line and truncates it if
+ * requested via sizeLimit. Returns true if any data were read before the
* end-of-file was reached. If the has_newline argument is specified, it will
* be true when the line read had a newline character.
*/
static bool GetLineFromStream(std::istream& istr, std::string& line,
- bool* has_newline = 0, long sizeLimit = -1);
+ bool* has_newline = nullptr,
+ long sizeLimit = -1);
/**
* Get the parent directory of the directory or file
@@ -562,13 +553,21 @@ 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 = nullptr);
+ static bool MakeDirectory(const std::string& path,
+ const mode_t* mode = nullptr);
/**
* Copy the source file to the destination file only
@@ -584,6 +583,13 @@ public:
const std::string& destination);
/**
+ * Compare the contents of two files, ignoring line ending differences.
+ * Return true if different
+ */
+ static bool TextFilesDiffer(const std::string& path1,
+ const std::string& path2);
+
+ /**
* Return true if the two files are the same file
*/
static bool SameFile(const std::string& file1, const std::string& file2);
@@ -758,13 +764,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
@@ -846,7 +845,8 @@ public:
* string vector passed in. If env is set then the value
* of env will be used instead of PATH.
*/
- static void GetPath(std::vector<std::string>& path, const char* env = 0);
+ static void GetPath(std::vector<std::string>& path,
+ const char* env = nullptr);
/**
* Read an environment variable
@@ -890,11 +890,12 @@ 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();
+#if @KWSYS_NAMESPACE@_SYSTEMTOOLS_USE_TRANSLATION_MAP
/**
* Add an entry in the path translation table.
*/
@@ -911,10 +912,11 @@ public:
* Update path by going through the Path Translation table;
*/
static void CheckTranslationPath(std::string& path);
+#endif
/**
* Delay the execution for a specified amount of time specified
- * in miliseconds
+ * in milliseconds
*/
static void Delay(unsigned int msec);
@@ -969,40 +971,8 @@ private:
return &SystemToolsManagerInstance;
}
- /**
- * Actual implementation of ReplaceString.
- */
- static void ReplaceString(std::string& source, const char* replace,
- size_t replaceSize, const std::string& with);
-
- /**
- * Actual implementation of FileIsFullPath.
- */
- static bool FileIsFullPath(const char*, size_t);
-
- /**
- * Find a filename (file or directory) in the system PATH, with
- * optional extra paths.
- */
- static std::string FindName(
- const std::string& name,
- const std::vector<std::string>& path = std::vector<std::string>(),
- bool no_system_path = false);
-
- static const char* GetEnvImpl(const char* key);
-
- /**
- * Path translation table from dir to refdir
- * Each time 'dir' will be found it will be replace by 'refdir'
- */
- static SystemToolsTranslationMap* TranslationMap;
-#ifdef _WIN32
- static SystemToolsPathCaseMap* PathCaseMap;
- static SystemToolsEnvMap* EnvMap;
-#endif
-#ifdef __CYGWIN__
- static SystemToolsTranslationMap* Cyg2Win32Map;
-#endif
+ static SystemToolsStatic* Statics;
+ friend class SystemToolsStatic;
friend class SystemToolsManager;
};
diff --git a/Source/kwsys/Terminal.c b/Source/kwsys/Terminal.c
index eaa5c7d43..4dd246148 100644
--- a/Source/kwsys/Terminal.c
+++ b/Source/kwsys/Terminal.c
@@ -6,15 +6,15 @@
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "Terminal.h.in"
+# include "Terminal.h.in"
#endif
/* Configure support for this platform. */
#if defined(_WIN32) || defined(__CYGWIN__)
-#define KWSYS_TERMINAL_SUPPORT_CONSOLE
+# define KWSYS_TERMINAL_SUPPORT_CONSOLE
#endif
#if !defined(_WIN32)
-#define KWSYS_TERMINAL_ISATTY_WORKS
+# define KWSYS_TERMINAL_ISATTY_WORKS
#endif
/* Include needed system APIs. */
@@ -24,14 +24,14 @@
#include <string.h> /* strcmp */
#if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
-#include <io.h> /* _get_osfhandle */
-#include <windows.h> /* SetConsoleTextAttribute */
+# include <io.h> /* _get_osfhandle */
+# include <windows.h> /* SetConsoleTextAttribute */
#endif
#if defined(KWSYS_TERMINAL_ISATTY_WORKS)
-#include <unistd.h> /* isatty */
+# include <unistd.h> /* isatty */
#else
-#include <sys/stat.h> /* fstat */
+# include <sys/stat.h> /* fstat */
#endif
static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100,
@@ -103,6 +103,8 @@ static int kwsysTerminalStreamIsNotInteractive(FILE* stream)
/* List of terminal names known to support VT100 color escape sequences. */
static const char* kwsysTerminalVT100Names[] = { "Eterm",
+ "alacritty",
+ "alacritty-direct",
"ansi",
"color-xterm",
"con132x25",
@@ -153,6 +155,7 @@ static const char* kwsysTerminalVT100Names[] = { "Eterm",
"xterm-88color",
"xterm-color",
"xterm-debian",
+ "xterm-kitty",
"xterm-termite",
0 };
@@ -208,27 +211,34 @@ static int kwsysTerminalStreamIsVT100(FILE* stream, int default_vt100,
}
/* VT100 escape sequence strings. */
-#define KWSYS_TERMINAL_VT100_NORMAL "\33[0m"
-#define KWSYS_TERMINAL_VT100_BOLD "\33[1m"
-#define KWSYS_TERMINAL_VT100_UNDERLINE "\33[4m"
-#define KWSYS_TERMINAL_VT100_BLINK "\33[5m"
-#define KWSYS_TERMINAL_VT100_INVERSE "\33[7m"
-#define KWSYS_TERMINAL_VT100_FOREGROUND_BLACK "\33[30m"
-#define KWSYS_TERMINAL_VT100_FOREGROUND_RED "\33[31m"
-#define KWSYS_TERMINAL_VT100_FOREGROUND_GREEN "\33[32m"
-#define KWSYS_TERMINAL_VT100_FOREGROUND_YELLOW "\33[33m"
-#define KWSYS_TERMINAL_VT100_FOREGROUND_BLUE "\33[34m"
-#define KWSYS_TERMINAL_VT100_FOREGROUND_MAGENTA "\33[35m"
-#define KWSYS_TERMINAL_VT100_FOREGROUND_CYAN "\33[36m"
-#define KWSYS_TERMINAL_VT100_FOREGROUND_WHITE "\33[37m"
-#define KWSYS_TERMINAL_VT100_BACKGROUND_BLACK "\33[40m"
-#define KWSYS_TERMINAL_VT100_BACKGROUND_RED "\33[41m"
-#define KWSYS_TERMINAL_VT100_BACKGROUND_GREEN "\33[42m"
-#define KWSYS_TERMINAL_VT100_BACKGROUND_YELLOW "\33[43m"
-#define KWSYS_TERMINAL_VT100_BACKGROUND_BLUE "\33[44m"
-#define KWSYS_TERMINAL_VT100_BACKGROUND_MAGENTA "\33[45m"
-#define KWSYS_TERMINAL_VT100_BACKGROUND_CYAN "\33[46m"
-#define KWSYS_TERMINAL_VT100_BACKGROUND_WHITE "\33[47m"
+#if defined(__MVS__)
+/* if building on z/OS (aka MVS), assume we are using EBCDIC */
+# define ESCAPE_CHAR "\47"
+#else
+# define ESCAPE_CHAR "\33"
+#endif
+
+#define KWSYS_TERMINAL_VT100_NORMAL ESCAPE_CHAR "[0m"
+#define KWSYS_TERMINAL_VT100_BOLD ESCAPE_CHAR "[1m"
+#define KWSYS_TERMINAL_VT100_UNDERLINE ESCAPE_CHAR "[4m"
+#define KWSYS_TERMINAL_VT100_BLINK ESCAPE_CHAR "[5m"
+#define KWSYS_TERMINAL_VT100_INVERSE ESCAPE_CHAR "[7m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_BLACK ESCAPE_CHAR "[30m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_RED ESCAPE_CHAR "[31m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_GREEN ESCAPE_CHAR "[32m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_YELLOW ESCAPE_CHAR "[33m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_BLUE ESCAPE_CHAR "[34m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_MAGENTA ESCAPE_CHAR "[35m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_CYAN ESCAPE_CHAR "[36m"
+#define KWSYS_TERMINAL_VT100_FOREGROUND_WHITE ESCAPE_CHAR "[37m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_BLACK ESCAPE_CHAR "[40m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_RED ESCAPE_CHAR "[41m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_GREEN ESCAPE_CHAR "[42m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_YELLOW ESCAPE_CHAR "[43m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_BLUE ESCAPE_CHAR "[44m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_MAGENTA ESCAPE_CHAR "[45m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_CYAN ESCAPE_CHAR "[46m"
+#define KWSYS_TERMINAL_VT100_BACKGROUND_WHITE ESCAPE_CHAR "[47m"
/* Write VT100 escape sequences to the stream for the given color. */
static void kwsysTerminalSetVT100Color(FILE* stream, int color)
@@ -300,10 +310,12 @@ static void kwsysTerminalSetVT100Color(FILE* stream, int color)
#if defined(KWSYS_TERMINAL_SUPPORT_CONSOLE)
-#define KWSYS_TERMINAL_MASK_FOREGROUND \
- (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)
-#define KWSYS_TERMINAL_MASK_BACKGROUND \
- (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY)
+# define KWSYS_TERMINAL_MASK_FOREGROUND \
+ (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | \
+ FOREGROUND_INTENSITY)
+# define KWSYS_TERMINAL_MASK_BACKGROUND \
+ (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | \
+ BACKGROUND_INTENSITY)
/* Get the Windows handle for a FILE stream. */
static HANDLE kwsysTerminalGetStreamHandle(FILE* stream)
@@ -311,7 +323,7 @@ static HANDLE kwsysTerminalGetStreamHandle(FILE* stream)
/* Get the C-library file descriptor from the stream. */
int fd = fileno(stream);
-#if defined(__CYGWIN__)
+# if defined(__CYGWIN__)
/* Cygwin seems to have an extra pipe level. If the file descriptor
corresponds to stdout or stderr then obtain the matching windows
handle directly. */
@@ -320,7 +332,7 @@ static HANDLE kwsysTerminalGetStreamHandle(FILE* stream)
} else if (fd == fileno(stderr)) {
return GetStdHandle(STD_ERROR_HANDLE);
}
-#endif
+# endif
/* Get the underlying Windows handle for the descriptor. */
return (HANDLE)_get_osfhandle(fd);
diff --git a/Source/kwsys/Terminal.h.in b/Source/kwsys/Terminal.h.in
index 5d2983004..1a2c7452f 100644
--- a/Source/kwsys/Terminal.h.in
+++ b/Source/kwsys/Terminal.h.in
@@ -12,57 +12,57 @@
not visible to user code. Use kwsysHeaderDump.pl to reproduce
these macros after making changes to the interface. */
#if !defined(KWSYS_NAMESPACE)
-#define kwsys_ns(x) @KWSYS_NAMESPACE@##x
-#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
+# define kwsys_ns(x) @KWSYS_NAMESPACE@##x
+# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#define kwsysTerminal_cfprintf kwsys_ns(Terminal_cfprintf)
-#define kwsysTerminal_Color_e kwsys_ns(Terminal_Color_e)
-#define kwsysTerminal_Color_Normal kwsys_ns(Terminal_Color_Normal)
-#define kwsysTerminal_Color_ForegroundBlack \
- kwsys_ns(Terminal_Color_ForegroundBlack)
-#define kwsysTerminal_Color_ForegroundRed \
- kwsys_ns(Terminal_Color_ForegroundRed)
-#define kwsysTerminal_Color_ForegroundGreen \
- kwsys_ns(Terminal_Color_ForegroundGreen)
-#define kwsysTerminal_Color_ForegroundYellow \
- kwsys_ns(Terminal_Color_ForegroundYellow)
-#define kwsysTerminal_Color_ForegroundBlue \
- kwsys_ns(Terminal_Color_ForegroundBlue)
-#define kwsysTerminal_Color_ForegroundMagenta \
- kwsys_ns(Terminal_Color_ForegroundMagenta)
-#define kwsysTerminal_Color_ForegroundCyan \
- kwsys_ns(Terminal_Color_ForegroundCyan)
-#define kwsysTerminal_Color_ForegroundWhite \
- kwsys_ns(Terminal_Color_ForegroundWhite)
-#define kwsysTerminal_Color_ForegroundMask \
- kwsys_ns(Terminal_Color_ForegroundMask)
-#define kwsysTerminal_Color_BackgroundBlack \
- kwsys_ns(Terminal_Color_BackgroundBlack)
-#define kwsysTerminal_Color_BackgroundRed \
- kwsys_ns(Terminal_Color_BackgroundRed)
-#define kwsysTerminal_Color_BackgroundGreen \
- kwsys_ns(Terminal_Color_BackgroundGreen)
-#define kwsysTerminal_Color_BackgroundYellow \
- kwsys_ns(Terminal_Color_BackgroundYellow)
-#define kwsysTerminal_Color_BackgroundBlue \
- kwsys_ns(Terminal_Color_BackgroundBlue)
-#define kwsysTerminal_Color_BackgroundMagenta \
- kwsys_ns(Terminal_Color_BackgroundMagenta)
-#define kwsysTerminal_Color_BackgroundCyan \
- kwsys_ns(Terminal_Color_BackgroundCyan)
-#define kwsysTerminal_Color_BackgroundWhite \
- kwsys_ns(Terminal_Color_BackgroundWhite)
-#define kwsysTerminal_Color_BackgroundMask \
- kwsys_ns(Terminal_Color_BackgroundMask)
-#define kwsysTerminal_Color_ForegroundBold \
- kwsys_ns(Terminal_Color_ForegroundBold)
-#define kwsysTerminal_Color_BackgroundBold \
- kwsys_ns(Terminal_Color_BackgroundBold)
-#define kwsysTerminal_Color_AssumeTTY kwsys_ns(Terminal_Color_AssumeTTY)
-#define kwsysTerminal_Color_AssumeVT100 kwsys_ns(Terminal_Color_AssumeVT100)
-#define kwsysTerminal_Color_AttributeMask \
- kwsys_ns(Terminal_Color_AttributeMask)
+# define kwsysTerminal_cfprintf kwsys_ns(Terminal_cfprintf)
+# define kwsysTerminal_Color_e kwsys_ns(Terminal_Color_e)
+# define kwsysTerminal_Color_Normal kwsys_ns(Terminal_Color_Normal)
+# define kwsysTerminal_Color_ForegroundBlack \
+ kwsys_ns(Terminal_Color_ForegroundBlack)
+# define kwsysTerminal_Color_ForegroundRed \
+ kwsys_ns(Terminal_Color_ForegroundRed)
+# define kwsysTerminal_Color_ForegroundGreen \
+ kwsys_ns(Terminal_Color_ForegroundGreen)
+# define kwsysTerminal_Color_ForegroundYellow \
+ kwsys_ns(Terminal_Color_ForegroundYellow)
+# define kwsysTerminal_Color_ForegroundBlue \
+ kwsys_ns(Terminal_Color_ForegroundBlue)
+# define kwsysTerminal_Color_ForegroundMagenta \
+ kwsys_ns(Terminal_Color_ForegroundMagenta)
+# define kwsysTerminal_Color_ForegroundCyan \
+ kwsys_ns(Terminal_Color_ForegroundCyan)
+# define kwsysTerminal_Color_ForegroundWhite \
+ kwsys_ns(Terminal_Color_ForegroundWhite)
+# define kwsysTerminal_Color_ForegroundMask \
+ kwsys_ns(Terminal_Color_ForegroundMask)
+# define kwsysTerminal_Color_BackgroundBlack \
+ kwsys_ns(Terminal_Color_BackgroundBlack)
+# define kwsysTerminal_Color_BackgroundRed \
+ kwsys_ns(Terminal_Color_BackgroundRed)
+# define kwsysTerminal_Color_BackgroundGreen \
+ kwsys_ns(Terminal_Color_BackgroundGreen)
+# define kwsysTerminal_Color_BackgroundYellow \
+ kwsys_ns(Terminal_Color_BackgroundYellow)
+# define kwsysTerminal_Color_BackgroundBlue \
+ kwsys_ns(Terminal_Color_BackgroundBlue)
+# define kwsysTerminal_Color_BackgroundMagenta \
+ kwsys_ns(Terminal_Color_BackgroundMagenta)
+# define kwsysTerminal_Color_BackgroundCyan \
+ kwsys_ns(Terminal_Color_BackgroundCyan)
+# define kwsysTerminal_Color_BackgroundWhite \
+ kwsys_ns(Terminal_Color_BackgroundWhite)
+# define kwsysTerminal_Color_BackgroundMask \
+ kwsys_ns(Terminal_Color_BackgroundMask)
+# define kwsysTerminal_Color_ForegroundBold \
+ kwsys_ns(Terminal_Color_ForegroundBold)
+# define kwsysTerminal_Color_BackgroundBold \
+ kwsys_ns(Terminal_Color_BackgroundBold)
+# define kwsysTerminal_Color_AssumeTTY kwsys_ns(Terminal_Color_AssumeTTY)
+# define kwsysTerminal_Color_AssumeVT100 kwsys_ns(Terminal_Color_AssumeVT100)
+# define kwsysTerminal_Color_AttributeMask \
+ kwsys_ns(Terminal_Color_AttributeMask)
#endif
#if defined(__cplusplus)
@@ -135,36 +135,36 @@ enum kwsysTerminal_Color_e
/* If we are building a kwsys .c or .cxx file, let it use these macros.
Otherwise, undefine them to keep the namespace clean. */
#if !defined(KWSYS_NAMESPACE)
-#undef kwsys_ns
-#undef kwsysEXPORT
-#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-#undef kwsysTerminal_cfprintf
-#undef kwsysTerminal_Color_e
-#undef kwsysTerminal_Color_Normal
-#undef kwsysTerminal_Color_ForegroundBlack
-#undef kwsysTerminal_Color_ForegroundRed
-#undef kwsysTerminal_Color_ForegroundGreen
-#undef kwsysTerminal_Color_ForegroundYellow
-#undef kwsysTerminal_Color_ForegroundBlue
-#undef kwsysTerminal_Color_ForegroundMagenta
-#undef kwsysTerminal_Color_ForegroundCyan
-#undef kwsysTerminal_Color_ForegroundWhite
-#undef kwsysTerminal_Color_ForegroundMask
-#undef kwsysTerminal_Color_BackgroundBlack
-#undef kwsysTerminal_Color_BackgroundRed
-#undef kwsysTerminal_Color_BackgroundGreen
-#undef kwsysTerminal_Color_BackgroundYellow
-#undef kwsysTerminal_Color_BackgroundBlue
-#undef kwsysTerminal_Color_BackgroundMagenta
-#undef kwsysTerminal_Color_BackgroundCyan
-#undef kwsysTerminal_Color_BackgroundWhite
-#undef kwsysTerminal_Color_BackgroundMask
-#undef kwsysTerminal_Color_ForegroundBold
-#undef kwsysTerminal_Color_BackgroundBold
-#undef kwsysTerminal_Color_AssumeTTY
-#undef kwsysTerminal_Color_AssumeVT100
-#undef kwsysTerminal_Color_AttributeMask
-#endif
+# undef kwsys_ns
+# undef kwsysEXPORT
+# if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
+# undef kwsysTerminal_cfprintf
+# undef kwsysTerminal_Color_e
+# undef kwsysTerminal_Color_Normal
+# undef kwsysTerminal_Color_ForegroundBlack
+# undef kwsysTerminal_Color_ForegroundRed
+# undef kwsysTerminal_Color_ForegroundGreen
+# undef kwsysTerminal_Color_ForegroundYellow
+# undef kwsysTerminal_Color_ForegroundBlue
+# undef kwsysTerminal_Color_ForegroundMagenta
+# undef kwsysTerminal_Color_ForegroundCyan
+# undef kwsysTerminal_Color_ForegroundWhite
+# undef kwsysTerminal_Color_ForegroundMask
+# undef kwsysTerminal_Color_BackgroundBlack
+# undef kwsysTerminal_Color_BackgroundRed
+# undef kwsysTerminal_Color_BackgroundGreen
+# undef kwsysTerminal_Color_BackgroundYellow
+# undef kwsysTerminal_Color_BackgroundBlue
+# undef kwsysTerminal_Color_BackgroundMagenta
+# undef kwsysTerminal_Color_BackgroundCyan
+# undef kwsysTerminal_Color_BackgroundWhite
+# undef kwsysTerminal_Color_BackgroundMask
+# undef kwsysTerminal_Color_ForegroundBold
+# undef kwsysTerminal_Color_BackgroundBold
+# undef kwsysTerminal_Color_AssumeTTY
+# undef kwsysTerminal_Color_AssumeVT100
+# undef kwsysTerminal_Color_AttributeMask
+# endif
#endif
#endif
diff --git a/Source/kwsys/hash_map.hxx.in b/Source/kwsys/hash_map.hxx.in
index 3f9174f3b..5f04e9c16 100644
--- a/Source/kwsys/hash_map.hxx.in
+++ b/Source/kwsys/hash_map.hxx.in
@@ -35,21 +35,21 @@
#include <functional> // equal_to
#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4284)
-#pragma warning(disable : 4786)
+# pragma warning(push)
+# pragma warning(disable : 4284)
+# pragma warning(disable : 4786)
#endif
#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
-#pragma set woff 1174
-#pragma set woff 1375
+# pragma set woff 1174
+# pragma set woff 1375
#endif
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
{
@@ -412,12 +412,12 @@ inline void swap(hash_multimap<_Key, _Tp, _HashFcn, _EqlKey, _Alloc>& __hm1,
} // namespace @KWSYS_NAMESPACE@
#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
-#pragma reset woff 1174
-#pragma reset woff 1375
+# pragma reset woff 1174
+# pragma reset woff 1375
#endif
#if defined(_MSC_VER)
-#pragma warning(pop)
+# pragma warning(pop)
#endif
#endif
diff --git a/Source/kwsys/hash_set.hxx.in b/Source/kwsys/hash_set.hxx.in
index e3a0c6c44..f4a37eebd 100644
--- a/Source/kwsys/hash_set.hxx.in
+++ b/Source/kwsys/hash_set.hxx.in
@@ -35,21 +35,21 @@
#include <functional> // equal_to
#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4284)
-#pragma warning(disable : 4786)
+# pragma warning(push)
+# pragma warning(disable : 4284)
+# pragma warning(disable : 4786)
#endif
#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
-#pragma set woff 1174
-#pragma set woff 1375
+# pragma set woff 1174
+# pragma set woff 1375
#endif
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; }
};
@@ -381,12 +381,12 @@ inline void swap(hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1,
} // namespace @KWSYS_NAMESPACE@
#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
-#pragma reset woff 1174
-#pragma reset woff 1375
+# pragma reset woff 1174
+# pragma reset woff 1375
#endif
#if defined(_MSC_VER)
-#pragma warning(pop)
+# pragma warning(pop)
#endif
#endif
diff --git a/Source/kwsys/hashtable.hxx.in b/Source/kwsys/hashtable.hxx.in
index dd92cb9d4..8c4b0025f 100644
--- a/Source/kwsys/hashtable.hxx.in
+++ b/Source/kwsys/hashtable.hxx.in
@@ -26,43 +26,42 @@
*
*/
#ifdef __BORLANDC__
-#pragma warn - 8027 /* 'for' not inlined. */
-#pragma warn - 8026 /* 'exception' not inlined. */
+# pragma warn - 8027 /* 'for' not inlined. */
+# pragma warn - 8026 /* 'exception' not inlined. */
#endif
#ifndef @KWSYS_NAMESPACE@_hashtable_hxx
-#define @KWSYS_NAMESPACE@_hashtable_hxx
-
-#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
-
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4284)
-#pragma warning(disable : 4786)
-#pragma warning(disable : 4512) /* no assignment operator for class */
-#endif
-#if defined(__sgi) && !defined(__GNUC__)
-#pragma set woff 3970 /* pointer to int conversion */ 3321 3968
-#endif
+# define @KWSYS_NAMESPACE@_hashtable_hxx
+
+# include <@KWSYS_NAMESPACE@/Configure.hxx>
+
+# 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)
+# pragma warning(disable : 4284)
+# pragma warning(disable : 4786)
+# pragma warning(disable : 4512) /* no assignment operator for class */
+# endif
+# if defined(__sgi) && !defined(__GNUC__)
+# pragma set woff 3970 /* pointer to int conversion */ 3321 3968
+# endif
// In C++11, clang will warn about using dynamic exception specifications
// as they are deprecated. But as this class is trying to faithfully
// mimic unordered_set and unordered_map, we want to keep the 'throw()'
// decorations below. So we suppress the warning.
-#if defined(__clang__) && defined(__has_warning)
-#if __has_warning("-Wdeprecated")
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated"
-#endif
-#endif
+# if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wdeprecated")
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated"
+# endif
+# endif
namespace @KWSYS_NAMESPACE@ {
@@ -74,7 +73,7 @@ struct _Hashtable_node
void public_method_to_quiet_warning_about_all_methods_private();
private:
- void operator=(_Hashtable_node<_Val> const&); // poison node assignment
+ void operator=(_Hashtable_node<_Val> const&) = delete;
};
template <class _Val, class _Key, class _HashFcn, class _ExtractKey,
@@ -251,6 +250,7 @@ private:
public:
typedef typename _Alloc::template rebind<_Val>::other allocator_type;
allocator_type get_allocator() const { return _M_node_allocator; }
+
private:
typedef
typename _Alloc::template rebind<_Node>::other _M_node_allocator_type;
@@ -354,7 +354,7 @@ public:
return end();
}
- iterator end() { return iterator(0, this); }
+ iterator end() { return iterator(nullptr, this); }
const_iterator begin() const
{
@@ -364,7 +364,7 @@ public:
return end();
}
- const_iterator end() const { return const_iterator(0, this); }
+ const_iterator end() const { return const_iterator(nullptr, this); }
friend bool operator==<>(const hashtable&, const hashtable&);
@@ -510,7 +510,7 @@ private:
{
const size_type __n_buckets = _M_next_size(__n);
_M_buckets.reserve(__n_buckets);
- _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*)0);
+ _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*)nullptr);
_M_num_elements = 0;
}
@@ -544,7 +544,7 @@ private:
_Node* _M_new_node(const value_type& __obj)
{
_Node* __n = _M_get_node();
- __n->_M_next = 0;
+ __n->_M_next = nullptr;
try {
construct(&__n->_M_val, __obj);
return __n;
@@ -569,7 +569,7 @@ private:
template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
class _All>
_Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>&
- _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++()
+_Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++()
{
const _Node* __old = _M_cur;
_M_cur = _M_cur->_M_next;
@@ -584,7 +584,7 @@ _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>&
template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
class _All>
inline _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>
- _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++(int)
+_Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++(int)
{
iterator __tmp = *this;
++*this;
@@ -594,7 +594,7 @@ inline _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>
template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
class _All>
_Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>&
- _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++()
+_Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++()
{
const _Node* __old = _M_cur;
_M_cur = _M_cur->_M_next;
@@ -609,7 +609,7 @@ _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>&
template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
class _All>
inline _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>
- _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++(int)
+_Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::operator++(int)
{
const_iterator __tmp = *this;
++*this;
@@ -694,8 +694,9 @@ hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::insert_equal_noresize(
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
-typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::reference hashtable<
- _Val, _Key, _HF, _Ex, _Eq, _All>::find_or_insert(const value_type& __obj)
+typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::reference
+hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::find_or_insert(
+ const value_type& __obj)
{
resize(_M_num_elements + 1);
@@ -838,9 +839,9 @@ void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::erase(iterator __first,
else if (__f_bucket == __l_bucket)
_M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur);
else {
- _M_erase_bucket(__f_bucket, __first._M_cur, 0);
+ _M_erase_bucket(__f_bucket, __first._M_cur, nullptr);
for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n)
- _M_erase_bucket(__n, 0);
+ _M_erase_bucket(__n, nullptr);
if (__l_bucket != _M_buckets.size())
_M_erase_bucket(__l_bucket, __last._M_cur);
}
@@ -872,7 +873,8 @@ void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::resize(
if (__num_elements_hint > __old_n) {
const size_type __n = _M_next_size(__num_elements_hint);
if (__n > __old_n) {
- _M_buckets_type __tmp(__n, (_Node*)(0), _M_buckets.get_allocator());
+ _M_buckets_type __tmp(__n, (_Node*)(nullptr),
+ _M_buckets.get_allocator());
try {
for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) {
_Node* __first = _M_buckets[__bucket];
@@ -939,12 +941,12 @@ void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::clear()
{
for (size_type __i = 0; __i < _M_buckets.size(); ++__i) {
_Node* __cur = _M_buckets[__i];
- while (__cur != 0) {
+ while (__cur != nullptr) {
_Node* __next = __cur->_M_next;
_M_delete_node(__cur);
__cur = __next;
}
- _M_buckets[__i] = 0;
+ _M_buckets[__i] = nullptr;
}
_M_num_elements = 0;
}
@@ -955,7 +957,7 @@ void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::_M_copy_from(
{
_M_buckets.clear();
_M_buckets.reserve(__ht._M_buckets.size());
- _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*)0);
+ _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*)nullptr);
try {
for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) {
const _Node* __cur = __ht._M_buckets[__i];
@@ -963,7 +965,7 @@ void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::_M_copy_from(
_Node* __copy = _M_new_node(__cur->_M_val);
_M_buckets[__i] = __copy;
- for (_Node *__next = __cur->_M_next; __next;
+ for (_Node* __next = __cur->_M_next; __next;
__cur = __next, __next = __cur->_M_next) {
__copy->_M_next = _M_new_node(__next->_M_val);
__copy = __copy->_M_next;
@@ -980,14 +982,14 @@ void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::_M_copy_from(
} // namespace @KWSYS_NAMESPACE@
// Undo warning suppression.
-#if defined(__clang__) && defined(__has_warning)
-#if __has_warning("-Wdeprecated")
-#pragma clang diagnostic pop
-#endif
-#endif
-
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif
+# if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wdeprecated")
+# pragma clang diagnostic pop
+# endif
+# endif
+
+# if defined(_MSC_VER)
+# pragma warning(pop)
+# endif
#endif
diff --git a/Source/kwsys/kwsysPlatformTests.cmake b/Source/kwsys/kwsysPlatformTests.cmake
index 5386a49a3..28d3f68e2 100644
--- a/Source/kwsys/kwsysPlatformTests.cmake
+++ b/Source/kwsys/kwsysPlatformTests.cmake
@@ -7,11 +7,16 @@ SET(KWSYS_PLATFORM_TEST_FILE_CXX kwsysPlatformTestsCXX.cxx)
MACRO(KWSYS_PLATFORM_TEST lang var description invert)
IF(NOT DEFINED ${var}_COMPILED)
MESSAGE(STATUS "${description}")
+ set(maybe_cxx_standard "")
+ if(CMAKE_VERSION VERSION_LESS 3.8 AND CMAKE_CXX_STANDARD)
+ set(maybe_cxx_standard "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}")
+ endif()
TRY_COMPILE(${var}_COMPILED
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/${KWSYS_PLATFORM_TEST_FILE_${lang}}
COMPILE_DEFINITIONS -DTEST_${var} ${KWSYS_PLATFORM_TEST_DEFINES} ${KWSYS_PLATFORM_TEST_EXTRA_FLAGS}
CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=${KWSYS_PLATFORM_TEST_LINK_LIBRARIES}"
+ ${maybe_cxx_standard}
OUTPUT_VARIABLE OUTPUT)
IF(${var}_COMPILED)
FILE(APPEND
diff --git a/Source/kwsys/kwsysPlatformTestsC.c b/Source/kwsys/kwsysPlatformTestsC.c
index 64a361bbe..b0cf7ad3b 100644
--- a/Source/kwsys/kwsysPlatformTestsC.c
+++ b/Source/kwsys/kwsysPlatformTestsC.c
@@ -17,18 +17,18 @@
}
*/
#if defined(__CLASSIC_C__)
-#define KWSYS_PLATFORM_TEST_C_MAIN() main()
-#define KWSYS_PLATFORM_TEST_C_MAIN_ARGS(argc, argv) \
- main(argc, argv) int argc; \
- char* argv[];
+# define KWSYS_PLATFORM_TEST_C_MAIN() main()
+# define KWSYS_PLATFORM_TEST_C_MAIN_ARGS(argc, argv) \
+ main(argc, argv) int argc; \
+ char* argv[];
#else
-#define KWSYS_PLATFORM_TEST_C_MAIN() main(void)
-#define KWSYS_PLATFORM_TEST_C_MAIN_ARGS(argc, argv) \
- main(int argc, char* argv[])
+# define KWSYS_PLATFORM_TEST_C_MAIN() main(void)
+# define KWSYS_PLATFORM_TEST_C_MAIN_ARGS(argc, argv) \
+ main(int argc, char* argv[])
#endif
#ifdef TEST_KWSYS_C_HAS_PTRDIFF_T
-#include <stddef.h>
+# include <stddef.h>
int f(ptrdiff_t n)
{
return n > 0;
@@ -43,7 +43,7 @@ int KWSYS_PLATFORM_TEST_C_MAIN()
#endif
#ifdef TEST_KWSYS_C_HAS_SSIZE_T
-#include <unistd.h>
+# include <unistd.h>
int f(ssize_t n)
{
return (int)n;
@@ -55,32 +55,47 @@ 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__)
+# if defined(__SIZEOF_SHORT__)
"INFO:macro[__SIZEOF_SHORT__]\n"
-#endif
-#if defined(__SIZEOF_INT__)
+# endif
+# if defined(__SIZEOF_INT__)
"INFO:macro[__SIZEOF_INT__]\n"
-#endif
-#if defined(__SIZEOF_LONG__)
+# endif
+# if defined(__SIZEOF_LONG__)
"INFO:macro[__SIZEOF_LONG__]\n"
-#endif
-#if defined(__SIZEOF_LONG_LONG__)
+# endif
+# if defined(__SIZEOF_LONG_LONG__)
"INFO:macro[__SIZEOF_LONG_LONG__]\n"
-#endif
-#if defined(__SHORT_MAX__)
+# endif
+# if defined(__SHORT_MAX__)
"INFO:macro[__SHORT_MAX__]\n"
-#endif
-#if defined(__INT_MAX__)
+# endif
+# if defined(__INT_MAX__)
"INFO:macro[__INT_MAX__]\n"
-#endif
-#if defined(__LONG_MAX__)
+# endif
+# if defined(__LONG_MAX__)
"INFO:macro[__LONG_MAX__]\n"
-#endif
-#if defined(__LONG_LONG_MAX__)
+# endif
+# if defined(__LONG_LONG_MAX__)
"INFO:macro[__LONG_LONG_MAX__]\n"
-#endif
+# endif
"";
int KWSYS_PLATFORM_TEST_C_MAIN_ARGS(argc, argv)
diff --git a/Source/kwsys/kwsysPlatformTestsCXX.cxx b/Source/kwsys/kwsysPlatformTestsCXX.cxx
index 01c69514c..cfd5666f3 100644
--- a/Source/kwsys/kwsysPlatformTestsCXX.cxx
+++ b/Source/kwsys/kwsysPlatformTestsCXX.cxx
@@ -1,7 +1,7 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#ifdef TEST_KWSYS_CXX_HAS_CSTDIO
-#include <cstdio>
+# include <cstdio>
int main()
{
return 0;
@@ -33,10 +33,10 @@ int main()
#endif
#ifdef TEST_KWSYS_CXX_STAT_HAS_ST_MTIM
-#include <sys/types.h>
+# include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
+# include <sys/stat.h>
+# include <unistd.h>
int main()
{
struct stat stat1;
@@ -47,10 +47,10 @@ int main()
#endif
#ifdef TEST_KWSYS_CXX_STAT_HAS_ST_MTIMESPEC
-#include <sys/types.h>
+# include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
+# include <sys/stat.h>
+# include <unistd.h>
int main()
{
struct stat stat1;
@@ -85,7 +85,7 @@ int main()
#endif
#ifdef TEST_KWSYS_IOS_HAS_ISTREAM_LONG_LONG
-#include <iostream>
+# include <iostream>
int test_istream(std::istream& is, long long& x)
{
return (is >> x) ? 1 : 0;
@@ -98,7 +98,7 @@ int main()
#endif
#ifdef TEST_KWSYS_IOS_HAS_OSTREAM_LONG_LONG
-#include <iostream>
+# include <iostream>
int test_ostream(std::ostream& os, long long x)
{
return (os << x) ? 1 : 0;
@@ -111,7 +111,7 @@ int main()
#endif
#ifdef TEST_KWSYS_IOS_HAS_ISTREAM___INT64
-#include <iostream>
+# include <iostream>
int test_istream(std::istream& is, __int64& x)
{
return (is >> x) ? 1 : 0;
@@ -124,7 +124,7 @@ int main()
#endif
#ifdef TEST_KWSYS_IOS_HAS_OSTREAM___INT64
-#include <iostream>
+# include <iostream>
int test_ostream(std::ostream& os, __int64 x)
{
return (os << x) ? 1 : 0;
@@ -136,44 +136,8 @@ int main()
}
#endif
-#ifdef TEST_KWSYS_LFS_WORKS
-/* Return 0 when LFS is available and 1 otherwise. */
-#define _LARGEFILE_SOURCE
-#define _LARGEFILE64_SOURCE
-#define _LARGE_FILES
-#define _FILE_OFFSET_BITS 64
-#include <sys/types.h>
-
-#include <assert.h>
-#include <sys/stat.h>
-#if KWSYS_CXX_HAS_CSTDIO
-#include <cstdio>
-#endif
-#include <stdio.h>
-
-int main(int, char** argv)
-{
-/* check that off_t can hold 2^63 - 1 and perform basic operations... */
-#define OFF_T_64 (((off_t)1 << 62) - 1 + ((off_t)1 << 62))
- if (OFF_T_64 % 2147483647 != 1)
- return 1;
-
- // stat breaks on SCO OpenServer
- struct stat buf;
- stat(argv[0], &buf);
- if (!S_ISREG(buf.st_mode))
- return 2;
-
- FILE* file = fopen(argv[0], "r");
- off_t offset = ftello(file);
- fseek(file, offset, SEEK_CUR);
- fclose(file);
- return 0;
-}
-#endif
-
#ifdef TEST_KWSYS_CXX_HAS_SETENV
-#include <stdlib.h>
+# include <stdlib.h>
int main()
{
return setenv("A", "B", 1);
@@ -181,7 +145,7 @@ int main()
#endif
#ifdef TEST_KWSYS_CXX_HAS_UNSETENV
-#include <stdlib.h>
+# include <stdlib.h>
int main()
{
unsetenv("A");
@@ -190,7 +154,7 @@ int main()
#endif
#ifdef TEST_KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H
-#include <stdlib.h>
+# include <stdlib.h>
int main()
{
char* e = environ[0];
@@ -200,10 +164,10 @@ int main()
#ifdef TEST_KWSYS_CXX_HAS_GETLOADAVG
// Match feature definitions from SystemInformation.cxx
-#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
-#define _GNU_SOURCE
-#endif
-#include <stdlib.h>
+# if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
+# endif
+# include <stdlib.h>
int main()
{
double loadavg[3] = { 0.0, 0.0, 0.0 };
@@ -212,13 +176,7 @@ int main()
#endif
#ifdef TEST_KWSYS_CXX_HAS_RLIMIT64
-#if defined(KWSYS_HAS_LFS)
-#define _LARGEFILE_SOURCE
-#define _LARGEFILE64_SOURCE
-#define _LARGE_FILES
-#define _FILE_OFFSET_BITS 64
-#endif
-#include <sys/resource.h>
+# include <sys/resource.h>
int main()
{
struct rlimit64 rlim;
@@ -227,7 +185,7 @@ int main()
#endif
#ifdef TEST_KWSYS_CXX_HAS_ATOLL
-#include <stdlib.h>
+# include <stdlib.h>
int main()
{
const char* str = "1024";
@@ -236,7 +194,7 @@ int main()
#endif
#ifdef TEST_KWSYS_CXX_HAS_ATOL
-#include <stdlib.h>
+# include <stdlib.h>
int main()
{
const char* str = "1024";
@@ -245,7 +203,7 @@ int main()
#endif
#ifdef TEST_KWSYS_CXX_HAS__ATOI64
-#include <stdlib.h>
+# include <stdlib.h>
int main()
{
const char* str = "1024";
@@ -254,7 +212,7 @@ int main()
#endif
#ifdef TEST_KWSYS_CXX_HAS_UTIMES
-#include <sys/time.h>
+# include <sys/time.h>
int main()
{
struct timeval* current_time = 0;
@@ -263,8 +221,14 @@ int main()
#endif
#ifdef TEST_KWSYS_CXX_HAS_UTIMENSAT
-#include <fcntl.h>
-#include <sys/stat.h>
+# include <fcntl.h>
+# include <sys/stat.h>
+# if defined(__APPLE__)
+# include <AvailabilityMacros.h>
+# if MAC_OS_X_VERSION_MIN_REQUIRED < 101300
+# error "utimensat not available on macOS < 10.13"
+# endif
+# endif
int main()
{
struct timespec times[2] = { { 0, UTIME_OMIT }, { 0, UTIME_NOW } };
@@ -273,14 +237,14 @@ int main()
#endif
#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
-#endif
-#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
-#define _GNU_SOURCE
-#endif
-#include <execinfo.h>
+# if defined(__PATHSCALE__) || defined(__PATHCC__) || \
+ (defined(__LSB_VERSION__) && (__LSB_VERSION__ < 41))
+backtrace does not work with this compiler or os
+# endif
+# if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
+# endif
+# include <execinfo.h>
int main()
{
void* stackSymbols[256];
@@ -291,10 +255,10 @@ int main()
#endif
#ifdef TEST_KWSYS_CXX_HAS_DLADDR
-#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
-#define _GNU_SOURCE
-#endif
-#include <dlfcn.h>
+# if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
+# endif
+# include <dlfcn.h>
int main()
{
Dl_info info;
@@ -304,14 +268,14 @@ int main()
#endif
#ifdef TEST_KWSYS_CXX_HAS_CXXABI
-#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
-#define _GNU_SOURCE
-#endif
-#if defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5130 && __linux && \
- __SUNPRO_CC_COMPAT == 'G'
-#include <iostream>
-#endif
-#include <cxxabi.h>
+# if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
+# endif
+# if defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5130 && __linux && \
+ __SUNPRO_CC_COMPAT == 'G'
+# include <iostream>
+# endif
+# include <cxxabi.h>
int main()
{
int status = 0;
@@ -352,7 +316,7 @@ int main()
#endif
#ifdef TEST_KWSYS_STL_HAS_WSTRING
-#include <string>
+# include <string>
void f(std::wstring*)
{
}
@@ -363,7 +327,7 @@ int main()
#endif
#ifdef TEST_KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H
-#include <ext/stdio_filebuf.h>
+# include <ext/stdio_filebuf.h>
int main()
{
return 0;
diff --git a/Source/kwsys/kwsysPrivate.h b/Source/kwsys/kwsysPrivate.h
index ce1b53ed8..dd9c1277f 100644
--- a/Source/kwsys/kwsysPrivate.h
+++ b/Source/kwsys/kwsysPrivate.h
@@ -1,11 +1,11 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#ifndef KWSYS_NAMESPACE
-#error "Do not include kwsysPrivate.h outside of kwsys c and cxx files."
+# error "Do not include kwsysPrivate.h outside of kwsys c and cxx files."
#endif
#ifndef _kwsysPrivate_h
-#define _kwsysPrivate_h
+# define _kwsysPrivate_h
/*
Define KWSYS_HEADER macro to help the c and cxx files include kwsys
@@ -18,17 +18,17 @@
/* clang-format off */
#define KWSYS_HEADER(x) KWSYS_HEADER0(KWSYS_NAMESPACE/x)
/* clang-format on */
-#define KWSYS_HEADER0(x) KWSYS_HEADER1(x)
-#define KWSYS_HEADER1(x) <x>
+# define KWSYS_HEADER0(x) KWSYS_HEADER1(x)
+# define KWSYS_HEADER1(x) <x>
/*
Define KWSYS_NAMESPACE_STRING to be a string constant containing the
name configured for this instance of the kwsys library.
*/
-#define KWSYS_NAMESPACE_STRING KWSYS_NAMESPACE_STRING0(KWSYS_NAMESPACE)
-#define KWSYS_NAMESPACE_STRING0(x) KWSYS_NAMESPACE_STRING1(x)
-#define KWSYS_NAMESPACE_STRING1(x) #x
+# define KWSYS_NAMESPACE_STRING KWSYS_NAMESPACE_STRING0(KWSYS_NAMESPACE)
+# define KWSYS_NAMESPACE_STRING0(x) KWSYS_NAMESPACE_STRING1(x)
+# define KWSYS_NAMESPACE_STRING1(x) # x
#else
-#error "kwsysPrivate.h included multiple times."
+# error "kwsysPrivate.h included multiple times."
#endif
diff --git a/Source/kwsys/testCommandLineArguments.cxx b/Source/kwsys/testCommandLineArguments.cxx
index d2215d62f..1778a9ba8 100644
--- a/Source/kwsys/testCommandLineArguments.cxx
+++ b/Source/kwsys/testCommandLineArguments.cxx
@@ -6,7 +6,7 @@
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "CommandLineArguments.hxx.in"
+# include "CommandLineArguments.hxx.in"
#endif
#include <iostream>
@@ -76,8 +76,8 @@ int testCommandLineArguments(int argc, char* argv[])
int some_int_variable = 10;
double some_double_variable = 10.10;
- char* some_string_variable = 0;
- std::string some_stl_string_variable = "";
+ char* some_string_variable = nullptr;
+ std::string some_stl_string_variable;
bool some_bool_variable = false;
bool some_bool_variable1 = false;
bool bool_arg1 = false;
@@ -136,7 +136,7 @@ int testCommandLineArguments(int argc, char* argv[])
arg.AddCallback("-C", argT::EQUAL_ARGUMENT, argument, random_ptr,
"Option -C takes argument after =");
arg.AddCallback("-D", argT::CONCAT_ARGUMENT, argument, random_ptr,
- "This option takes concatinated argument");
+ "This option takes concatenated argument");
arg.AddCallback("--long1", argT::NO_ARGUMENT, argument, random_ptr, "-A");
arg.AddCallback("--long2", argT::SPACE_ARGUMENT, argument, random_ptr, "-B");
arg.AddCallback("--long3", argT::EQUAL_ARGUMENT, argument, random_ptr,
@@ -165,25 +165,26 @@ int testCommandLineArguments(int argc, char* argv[])
}
size_t cc;
#define CompareTwoLists(list1, list_valid, lsize) \
- if (list1.size() != lsize) { \
- std::cerr << "Problem setting " #list1 ". Size is: " << list1.size() \
- << " should be: " << lsize << std::endl; \
- res = 1; \
- } else { \
- std::cout << #list1 " argument set:"; \
- for (cc = 0; cc < lsize; ++cc) { \
- std::cout << " " << list1[cc]; \
- if (!CompareTwoItemsOnList(list1[cc], list_valid[cc])) { \
- std::cerr << "Problem setting " #list1 ". Value of " << cc \
- << " is: [" << list1[cc] << "] <> [" << list_valid[cc] \
- << "]" << std::endl; \
- res = 1; \
- break; \
+ do { \
+ if (list1.size() != lsize) { \
+ std::cerr << "Problem setting " #list1 ". Size is: " << list1.size() \
+ << " should be: " << lsize << std::endl; \
+ res = 1; \
+ } else { \
+ std::cout << #list1 " argument set:"; \
+ for (cc = 0; cc < lsize; ++cc) { \
+ std::cout << " " << list1[cc]; \
+ if (!CompareTwoItemsOnList(list1[cc], list_valid[cc])) { \
+ std::cerr << "Problem setting " #list1 ". Value of " << cc \
+ << " is: [" << list1[cc] << "] <> [" << list_valid[cc] \
+ << "]" << std::endl; \
+ res = 1; \
+ break; \
+ } \
} \
+ std::cout << std::endl; \
} \
- std::cout << std::endl; \
- }
-
+ } while (0)
CompareTwoLists(numbers_argument, valid_numbers, 10);
CompareTwoLists(doubles_argument, valid_doubles, 3);
CompareTwoLists(bools_argument, valid_bools, 3);
@@ -202,7 +203,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] = nullptr;
}
return res;
}
diff --git a/Source/kwsys/testCommandLineArguments1.cxx b/Source/kwsys/testCommandLineArguments1.cxx
index 5a03401bc..64561b1e3 100644
--- a/Source/kwsys/testCommandLineArguments1.cxx
+++ b/Source/kwsys/testCommandLineArguments1.cxx
@@ -6,7 +6,7 @@
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "CommandLineArguments.hxx.in"
+# include "CommandLineArguments.hxx.in"
#endif
#include <iostream>
@@ -21,7 +21,7 @@ int testCommandLineArguments1(int argc, char* argv[])
arg.Initialize(argc, argv);
int n = 0;
- char* m = 0;
+ char* m = nullptr;
std::string p;
int res = 0;
@@ -55,11 +55,11 @@ int testCommandLineArguments1(int argc, char* argv[])
delete[] m;
}
- char** newArgv = 0;
+ char** newArgv = nullptr;
int newArgc = 0;
arg.GetUnusedArguments(&newArgc, &newArgv);
int cc;
- const char* valid_unused_args[9] = { 0,
+ const char* valid_unused_args[9] = { nullptr,
"--ignored",
"--second-ignored",
"third-ignored",
diff --git a/Source/kwsys/testConfigure.cxx b/Source/kwsys/testConfigure.cxx
new file mode 100644
index 000000000..a3c2ed3ae
--- /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/testConsoleBuf.cxx b/Source/kwsys/testConsoleBuf.cxx
index 816a4338e..4b7ddf053 100644
--- a/Source/kwsys/testConsoleBuf.cxx
+++ b/Source/kwsys/testConsoleBuf.cxx
@@ -13,24 +13,24 @@
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Encoding.hxx.in"
+# include "Encoding.hxx.in"
#endif
#if defined(_WIN32)
-#include <algorithm>
-#include <iomanip>
-#include <iostream>
-#include <stdexcept>
-#include <string.h>
-#include <wchar.h>
-#include <windows.h>
+# include <algorithm>
+# include <iomanip>
+# include <iostream>
+# include <stdexcept>
+# include <string.h>
+# include <wchar.h>
+# include <windows.h>
-#include "testConsoleBuf.hxx"
+# include "testConsoleBuf.hxx"
-#if defined(_MSC_VER) && _MSC_VER >= 1800
-#define KWSYS_WINDOWS_DEPRECATED_GetVersion
-#endif
+# if defined(_MSC_VER) && _MSC_VER >= 1800
+# define KWSYS_WINDOWS_DEPRECATED_GetVersion
+# endif
// يونيكود
static const WCHAR UnicodeInputTestString[] =
L"\u064A\u0648\u0646\u064A\u0643\u0648\u062F!";
@@ -51,7 +51,7 @@ static void displayError(DWORD errorCode)
LPWSTR message;
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, errorCode, 0, (LPWSTR)&message, 0, NULL)) {
+ nullptr, errorCode, 0, (LPWSTR)&message, 0, nullptr)) {
std::cerr << "Error message: " << kwsys::Encoding::ToNarrow(message)
<< std::endl;
HeapFree(GetProcessHeap(), 0, message);
@@ -124,7 +124,7 @@ static bool createProcess(HANDLE hIn, HANDLE hOut, HANDLE hErr)
}
WCHAR cmd[MAX_PATH];
- if (GetModuleFileNameW(NULL, cmd, MAX_PATH) == 0) {
+ if (GetModuleFileNameW(nullptr, cmd, MAX_PATH) == 0) {
std::cerr << "GetModuleFileName failed!" << std::endl;
return false;
}
@@ -136,14 +136,14 @@ static bool createProcess(HANDLE hIn, HANDLE hOut, HANDLE hErr)
wcscat(cmd, L".exe");
bool success =
- CreateProcessW(NULL, // No module name (use command line)
+ CreateProcessW(nullptr, // No module name (use command line)
cmd, // Command line
- NULL, // Process handle not inheritable
- NULL, // Thread handle not inheritable
+ nullptr, // Process handle not inheritable
+ nullptr, // Thread handle not inheritable
bInheritHandles, // Set handle inheritance
dwCreationFlags,
- NULL, // Use parent's environment block
- NULL, // Use parent's starting directory
+ nullptr, // Use parent's environment block
+ nullptr, // Use parent's starting directory
&startupInfo, // Pointer to STARTUPINFO structure
&processInfo) !=
0; // Pointer to PROCESS_INFORMATION structure
@@ -174,7 +174,7 @@ static bool createPipe(PHANDLE readPipe, PHANDLE writePipe)
SECURITY_ATTRIBUTES securityAttributes;
securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
securityAttributes.bInheritHandle = TRUE;
- securityAttributes.lpSecurityDescriptor = NULL;
+ securityAttributes.lpSecurityDescriptor = nullptr;
return CreatePipe(readPipe, writePipe, &securityAttributes, 0) == 0 ? false
: true;
}
@@ -194,7 +194,7 @@ static HANDLE createFile(LPCWSTR fileName)
SECURITY_ATTRIBUTES securityAttributes;
securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
securityAttributes.bInheritHandle = TRUE;
- securityAttributes.lpSecurityDescriptor = NULL;
+ securityAttributes.lpSecurityDescriptor = nullptr;
HANDLE file =
CreateFileW(fileName, GENERIC_READ | GENERIC_WRITE,
@@ -202,7 +202,7 @@ static HANDLE createFile(LPCWSTR fileName)
&securityAttributes,
CREATE_ALWAYS, // overwrite existing
FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
- NULL); // no template
+ nullptr); // no template
if (file == INVALID_HANDLE_VALUE) {
DWORD lastError = GetLastError();
std::cerr << "CreateFile(" << kwsys::Encoding::ToNarrow(fileName) << ")"
@@ -219,9 +219,9 @@ static void finishFile(HANDLE file)
}
}
-#ifndef MAPVK_VK_TO_VSC
-#define MAPVK_VK_TO_VSC (0)
-#endif
+# ifndef MAPVK_VK_TO_VSC
+# define MAPVK_VK_TO_VSC (0)
+# endif
static void writeInputKeyEvent(INPUT_RECORD inputBuffer[], WCHAR chr)
{
@@ -288,7 +288,7 @@ static int testPipe()
DWORD bytesWritten = 0;
if (!WriteFile(inPipeWrite, encodedInputTestString.c_str(),
(DWORD)encodedInputTestString.size(), &bytesWritten,
- NULL) ||
+ nullptr) ||
bytesWritten == 0) {
throw std::runtime_error("WriteFile failed!");
}
@@ -305,7 +305,8 @@ static int testPipe()
throw std::runtime_error("WaitForSingleObject failed!");
}
DWORD bytesRead = 0;
- if (!ReadFile(outPipeRead, buffer, sizeof(buffer), &bytesRead, NULL) ||
+ if (!ReadFile(outPipeRead, buffer, sizeof(buffer), &bytesRead,
+ nullptr) ||
bytesRead == 0) {
throw std::runtime_error("ReadFile#1 failed!");
}
@@ -313,7 +314,7 @@ static int testPipe()
if ((bytesRead <
encodedTestString.size() + 1 + encodedInputTestString.size() &&
!ReadFile(outPipeRead, buffer + bytesRead,
- sizeof(buffer) - bytesRead, &bytesRead, NULL)) ||
+ sizeof(buffer) - bytesRead, &bytesRead, nullptr)) ||
bytesRead == 0) {
throw std::runtime_error("ReadFile#2 failed!");
}
@@ -324,7 +325,7 @@ static int testPipe()
encodedInputTestString.size()) == 0) {
bytesRead = 0;
if (!ReadFile(errPipeRead, buffer2, sizeof(buffer2), &bytesRead,
- NULL) ||
+ nullptr) ||
bytesRead == 0) {
throw std::runtime_error("ReadFile#3 failed!");
}
@@ -383,13 +384,13 @@ static int testFile()
char buffer2[200];
int length;
- if ((length =
- WideCharToMultiByte(TestCodepage, 0, UnicodeInputTestString, -1,
- buffer, sizeof(buffer), NULL, NULL)) == 0) {
+ if ((length = WideCharToMultiByte(TestCodepage, 0, UnicodeInputTestString,
+ -1, buffer, sizeof(buffer), nullptr,
+ nullptr)) == 0) {
throw std::runtime_error("WideCharToMultiByte failed!");
}
buffer[length - 1] = '\n';
- if (!WriteFile(inFile, buffer, length, &bytesWritten, NULL) ||
+ if (!WriteFile(inFile, buffer, length, &bytesWritten, nullptr) ||
bytesWritten == 0) {
throw std::runtime_error("WriteFile failed!");
}
@@ -413,7 +414,7 @@ static int testFile()
INVALID_SET_FILE_POINTER) {
throw std::runtime_error("SetFilePointer#1 failed!");
}
- if (!ReadFile(outFile, buffer, sizeof(buffer), &bytesRead, NULL) ||
+ if (!ReadFile(outFile, buffer, sizeof(buffer), &bytesRead, nullptr) ||
bytesRead == 0) {
throw std::runtime_error("ReadFile#1 failed!");
}
@@ -429,7 +430,8 @@ static int testFile()
throw std::runtime_error("SetFilePointer#2 failed!");
}
- if (!ReadFile(errFile, buffer2, sizeof(buffer2), &bytesRead, NULL) ||
+ if (!ReadFile(errFile, buffer2, sizeof(buffer2), &bytesRead,
+ nullptr) ||
bytesRead == 0) {
throw std::runtime_error("ReadFile#2 failed!");
}
@@ -470,9 +472,9 @@ static int testFile()
return didFail;
}
-#ifndef _WIN32_WINNT_VISTA
-#define _WIN32_WINNT_VISTA 0x0600
-#endif
+# ifndef _WIN32_WINNT_VISTA
+# define _WIN32_WINNT_VISTA 0x0600
+# endif
static int testConsole()
{
@@ -495,29 +497,36 @@ static int testConsole()
DWORD FaceNameSize = sizeof(FaceName);
DWORD FontFamily = TestFontFamily;
DWORD FontSize = TestFontSize;
-#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersion
-#pragma warning(push)
-#ifdef __INTEL_COMPILER
-#pragma warning(disable : 1478)
-#else
-#pragma warning(disable : 4996)
-#endif
-#endif
+# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersion
+# pragma warning(push)
+# ifdef __INTEL_COMPILER
+# pragma warning(disable : 1478)
+# elif defined __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated-declarations"
+# else
+# pragma warning(disable : 4996)
+# endif
+# endif
const bool isVistaOrGreater =
LOBYTE(LOWORD(GetVersion())) >= HIBYTE(_WIN32_WINNT_VISTA);
-#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersion
-#pragma warning(pop)
-#endif
+# ifdef KWSYS_WINDOWS_DEPRECATED_GetVersion
+# ifdef __clang__
+# pragma clang diagnostic pop
+# else
+# pragma warning(pop)
+# endif
+# endif
if (!isVistaOrGreater) {
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0, KEY_READ | KEY_WRITE,
&hConsoleKey) == ERROR_SUCCESS) {
DWORD dwordSize = sizeof(DWORD);
- if (RegQueryValueExW(hConsoleKey, L"FontFamily", NULL, NULL,
+ if (RegQueryValueExW(hConsoleKey, L"FontFamily", nullptr, nullptr,
(LPBYTE)&FontFamily, &dwordSize) == ERROR_SUCCESS) {
if (FontFamily != TestFontFamily) {
- RegQueryValueExW(hConsoleKey, L"FaceName", NULL, NULL,
+ RegQueryValueExW(hConsoleKey, L"FaceName", nullptr, nullptr,
(LPBYTE)FaceName, &FaceNameSize);
- RegQueryValueExW(hConsoleKey, L"FontSize", NULL, NULL,
+ RegQueryValueExW(hConsoleKey, L"FontSize", nullptr, nullptr,
(LPBYTE)&FontSize, &dwordSize);
RegSetValueExW(hConsoleKey, L"FontFamily", 0, REG_DWORD,
@@ -550,10 +559,10 @@ static int testConsole()
SECURITY_ATTRIBUTES securityAttributes;
securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
securityAttributes.bInheritHandle = TRUE;
- securityAttributes.lpSecurityDescriptor = NULL;
+ securityAttributes.lpSecurityDescriptor = nullptr;
hIn = CreateFileW(L"CONIN$", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, &securityAttributes,
- OPEN_EXISTING, 0, NULL);
+ OPEN_EXISTING, 0, nullptr);
if (hIn == INVALID_HANDLE_VALUE) {
DWORD lastError = GetLastError();
std::cerr << "CreateFile(CONIN$)" << std::endl;
@@ -561,7 +570,7 @@ static int testConsole()
}
hOut = CreateFileW(L"CONOUT$", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, &securityAttributes,
- OPEN_EXISTING, 0, NULL);
+ OPEN_EXISTING, 0, nullptr);
if (hOut == INVALID_HANDLE_VALUE) {
DWORD lastError = GetLastError();
std::cerr << "CreateFile(CONOUT$)" << std::endl;
@@ -573,7 +582,7 @@ static int testConsole()
newConsole = true;
}
-#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
+# if _WIN32_WINNT >= _WIN32_WINNT_VISTA
if (isVistaOrGreater) {
CONSOLE_FONT_INFOEX consoleFont;
memset(&consoleFont, 0, sizeof(consoleFont));
@@ -603,7 +612,7 @@ static int testConsole()
std::cerr << "GetCurrentConsoleFontEx failed!" << std::endl;
}
} else {
-#endif
+# endif
if (restoreConsole &&
RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0, KEY_WRITE,
&hConsoleKey) == ERROR_SUCCESS) {
@@ -619,11 +628,11 @@ static int testConsole()
sizeof(FontSize));
RegCloseKey(hConsoleKey);
}
-#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
+# if _WIN32_WINNT >= _WIN32_WINNT_VISTA
}
-#endif
+# endif
- if (createProcess(NULL, NULL, NULL)) {
+ if (createProcess(nullptr, nullptr, nullptr)) {
try {
DWORD status;
if ((status = WaitForSingleObject(beforeInputEvent, waitTimeout)) !=
@@ -739,7 +748,7 @@ int testConsoleBuf(int, char* [])
int ret = 0;
#if defined(_WIN32)
- beforeInputEvent = CreateEventW(NULL,
+ beforeInputEvent = CreateEventW(nullptr,
FALSE, // auto-reset event
FALSE, // initial state is nonsignaled
BeforeInputEventName); // object name
@@ -748,7 +757,7 @@ int testConsoleBuf(int, char* [])
return 1;
}
- afterOutputEvent = CreateEventW(NULL, FALSE, FALSE, AfterOutputEventName);
+ afterOutputEvent = CreateEventW(nullptr, FALSE, FALSE, AfterOutputEventName);
if (!afterOutputEvent) {
std::cerr << "CreateEvent#2 failed " << GetLastError() << std::endl;
return 1;
diff --git a/Source/kwsys/testConsoleBufChild.cxx b/Source/kwsys/testConsoleBufChild.cxx
index 6a743edcd..3c8fdc2e1 100644
--- a/Source/kwsys/testConsoleBufChild.cxx
+++ b/Source/kwsys/testConsoleBufChild.cxx
@@ -8,8 +8,8 @@
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "ConsoleBuf.hxx.in"
-#include "Encoding.hxx.in"
+# include "ConsoleBuf.hxx.in"
+# include "Encoding.hxx.in"
#endif
#include <iostream>
diff --git a/Source/kwsys/testDirectory.cxx b/Source/kwsys/testDirectory.cxx
new file mode 100644
index 000000000..b1ab0c872
--- /dev/null
+++ b/Source/kwsys/testDirectory.cxx
@@ -0,0 +1,110 @@
+/* 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(Directory.hxx)
+#include KWSYS_HEADER(Encoding.hxx)
+#include KWSYS_HEADER(SystemTools.hxx)
+
+// Work-around CMake dependency scanning limitation. This must
+// duplicate the above list of headers.
+#if 0
+# include "Directory.hxx.in"
+# include "Encoding.hxx.in"
+# include "SystemTools.hxx.in"
+#endif
+
+#include <fstream>
+#include <iostream>
+#include <sstream>
+
+#include <testSystemTools.h>
+
+int _doLongPathTest()
+{
+ using namespace kwsys;
+ static const int LONG_PATH_THRESHOLD = 512;
+ int res = 0;
+ std::string topdir(TEST_SYSTEMTOOLS_BINARY_DIR "/directory_testing/");
+ std::stringstream testpathstrm;
+ std::string testdirpath;
+ std::string extendedtestdirpath;
+
+ testpathstrm << topdir;
+ size_t pathlen = testpathstrm.str().length();
+ testpathstrm.seekp(0, std::ios_base::end);
+ while (pathlen < LONG_PATH_THRESHOLD) {
+ testpathstrm << "0123456789/";
+ pathlen = testpathstrm.str().length();
+ }
+
+ testdirpath = testpathstrm.str();
+#ifdef _WIN32
+ extendedtestdirpath =
+ Encoding::ToNarrow(SystemTools::ConvertToWindowsExtendedPath(testdirpath));
+#else
+ extendedtestdirpath = testdirpath;
+#endif
+
+ if (SystemTools::MakeDirectory(extendedtestdirpath)) {
+ std::ofstream testfile1(
+ (extendedtestdirpath + "longfilepathtest1.txt").c_str());
+ std::ofstream testfile2(
+ (extendedtestdirpath + "longfilepathtest2.txt").c_str());
+ testfile1 << "foo";
+ testfile2 << "bar";
+ testfile1.close();
+ testfile2.close();
+
+ Directory testdir;
+ // Set res to failure if the directory doesn't load
+ res += !testdir.Load(testdirpath);
+ // Increment res failure if the directory appears empty
+ res += testdir.GetNumberOfFiles() == 0;
+ // Increment res failures if the path has changed from
+ // what was provided.
+ res += testdirpath != testdir.GetPath();
+
+ SystemTools::RemoveADirectory(topdir);
+ } else {
+ std::cerr << "Failed to create directory with long path: "
+ << extendedtestdirpath << std::endl;
+ res += 1;
+ }
+ return res;
+}
+
+int _copyDirectoryTest()
+{
+ using namespace kwsys;
+ const std::string source(TEST_SYSTEMTOOLS_BINARY_DIR
+ "/directory_testing/copyDirectoryTestSrc");
+ if (SystemTools::PathExists(source)) {
+ std::cerr << source << " shouldn't exist before test" << std::endl;
+ return 1;
+ }
+ const std::string destination(TEST_SYSTEMTOOLS_BINARY_DIR
+ "/directory_testing/copyDirectoryTestDst");
+ if (SystemTools::PathExists(destination)) {
+ std::cerr << destination << " shouldn't exist before test" << std::endl;
+ return 2;
+ }
+ const bool copysuccess = SystemTools::CopyADirectory(source, destination);
+ const bool destinationexists = SystemTools::PathExists(destination);
+ if (copysuccess) {
+ std::cerr << "CopyADirectory should have returned false" << std::endl;
+ SystemTools::RemoveADirectory(destination);
+ return 3;
+ }
+ if (destinationexists) {
+ std::cerr << "CopyADirectory returned false, but destination directory"
+ << " has been created" << std::endl;
+ SystemTools::RemoveADirectory(destination);
+ return 4;
+ }
+ return 0;
+}
+
+int testDirectory(int, char* [])
+{
+ return _doLongPathTest() + _copyDirectoryTest();
+}
diff --git a/Source/kwsys/testDynamicLoader.cxx b/Source/kwsys/testDynamicLoader.cxx
index b52ddda8b..2421ac0e1 100644
--- a/Source/kwsys/testDynamicLoader.cxx
+++ b/Source/kwsys/testDynamicLoader.cxx
@@ -5,13 +5,13 @@
#include KWSYS_HEADER(DynamicLoader.hxx)
#if defined(__BEOS__) || defined(__HAIKU__)
-#include <be/kernel/OS.h> /* disable_debugger() API. */
+# include <be/kernel/OS.h> /* disable_debugger() API. */
#endif
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "DynamicLoader.hxx.in"
+# include "DynamicLoader.hxx.in"
#endif
#include <iostream>
@@ -21,11 +21,15 @@
// left on disk.
#include <testSystemTools.h>
-static std::string GetLibName(const char* lname)
+static std::string GetLibName(const char* lname, const char* subdir = nullptr)
{
// Construct proper name of lib
std::string slname;
slname = EXECUTABLE_OUTPUT_PATH;
+ if (subdir) {
+ slname += "/";
+ slname += subdir;
+ }
#ifdef CMAKE_INTDIR
slname += "/";
slname += CMAKE_INTDIR;
@@ -45,26 +49,29 @@ static std::string GetLibName(const char* lname)
* r3: should CloseLibrary succeed ?
*/
static int TestDynamicLoader(const char* libname, const char* symbol, int r1,
- int r2, int r3)
+ int r2, int r3, int flags = 0)
{
std::cerr << "Testing: " << libname << std::endl;
kwsys::DynamicLoader::LibraryHandle l =
- kwsys::DynamicLoader::OpenLibrary(libname);
+ kwsys::DynamicLoader::OpenLibrary(libname, flags);
// If result is incompatible with expectation just fails (xor):
if ((r1 && !l) || (!r1 && l)) {
- std::cerr << kwsys::DynamicLoader::LastError() << std::endl;
+ std::cerr << "OpenLibrary: " << kwsys::DynamicLoader::LastError()
+ << std::endl;
return 1;
}
kwsys::DynamicLoader::SymbolPointer f =
kwsys::DynamicLoader::GetSymbolAddress(l, symbol);
if ((r2 && !f) || (!r2 && f)) {
- std::cerr << kwsys::DynamicLoader::LastError() << std::endl;
+ std::cerr << "GetSymbolAddress: " << kwsys::DynamicLoader::LastError()
+ << std::endl;
return 1;
}
#ifndef __APPLE__
int s = kwsys::DynamicLoader::CloseLibrary(l);
if ((r3 && !s) || (!r3 && s)) {
- std::cerr << kwsys::DynamicLoader::LastError() << std::endl;
+ std::cerr << "CloseLibrary: " << kwsys::DynamicLoader::LastError()
+ << std::endl;
return 1;
}
#else
@@ -113,5 +120,14 @@ int testDynamicLoader(int argc, char* argv[])
res += TestDynamicLoader(libname.c_str(), "TestDynamicLoaderData", 1, 1, 1);
res += TestDynamicLoader(libname.c_str(), "_TestDynamicLoaderData", 1, 0, 1);
+#ifdef _WIN32
+ libname = GetLibName(KWSYS_NAMESPACE_STRING "TestDynloadUse", "dynloaddir");
+ res += TestDynamicLoader(libname.c_str(), "dummy", 0, 0, 0);
+ res += TestDynamicLoader(libname.c_str(), "TestLoad", 1, 1, 1,
+ kwsys::DynamicLoader::SearchBesideLibrary);
+ res += TestDynamicLoader(libname.c_str(), "_TestLoad", 1, 0, 1,
+ kwsys::DynamicLoader::SearchBesideLibrary);
+#endif
+
return res;
}
diff --git a/Source/kwsys/testDynload.c b/Source/kwsys/testDynload.c
index cdb9e5c35..c49f747df 100644
--- a/Source/kwsys/testDynload.c
+++ b/Source/kwsys/testDynload.c
@@ -1,9 +1,9 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#ifdef _WIN32
-#define DL_EXPORT __declspec(dllexport)
+# define DL_EXPORT __declspec(dllexport)
#else
-#define DL_EXPORT
+# define DL_EXPORT
#endif
DL_EXPORT int TestDynamicLoaderData = 0;
diff --git a/Source/kwsys/testDynloadImpl.c b/Source/kwsys/testDynloadImpl.c
new file mode 100644
index 000000000..2b9069bc7
--- /dev/null
+++ b/Source/kwsys/testDynloadImpl.c
@@ -0,0 +1,10 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+
+#include "testDynloadImpl.h"
+
+int TestDynamicLoaderImplData = 0;
+
+void TestDynamicLoaderImplSymbolPointer()
+{
+}
diff --git a/Source/kwsys/testDynloadImpl.h b/Source/kwsys/testDynloadImpl.h
new file mode 100644
index 000000000..d0c9dfb75
--- /dev/null
+++ b/Source/kwsys/testDynloadImpl.h
@@ -0,0 +1,15 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+#ifdef _WIN32
+# ifdef BUILDING_TestDynloadImpl
+# define DLIMPL_EXPORT __declspec(dllexport)
+# else
+# define DLIMPL_EXPORT __declspec(dllimport)
+# endif
+#else
+# define DLIMPL_EXPORT
+#endif
+
+DLIMPL_EXPORT int TestDynamicLoaderImplData;
+
+DLIMPL_EXPORT void TestDynamicLoaderImplSymbolPointer();
diff --git a/Source/kwsys/testDynloadUse.c b/Source/kwsys/testDynloadUse.c
new file mode 100644
index 000000000..5402add6a
--- /dev/null
+++ b/Source/kwsys/testDynloadUse.c
@@ -0,0 +1,15 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+#include "testDynloadImpl.h"
+
+#ifdef _WIN32
+# define DL_EXPORT __declspec(dllexport)
+#else
+# define DL_EXPORT
+#endif
+
+DL_EXPORT int TestLoad()
+{
+ TestDynamicLoaderImplSymbolPointer();
+ return TestDynamicLoaderImplData;
+}
diff --git a/Source/kwsys/testEncode.c b/Source/kwsys/testEncode.c
index a20d46fd3..b7b6dd845 100644
--- a/Source/kwsys/testEncode.c
+++ b/Source/kwsys/testEncode.c
@@ -6,7 +6,7 @@
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "MD5.h.in"
+# include "MD5.h.in"
#endif
#include <stdio.h>
diff --git a/Source/kwsys/testEncoding.cxx b/Source/kwsys/testEncoding.cxx
index 2c5ef46eb..988697bff 100644
--- a/Source/kwsys/testEncoding.cxx
+++ b/Source/kwsys/testEncoding.cxx
@@ -3,7 +3,7 @@
#include "kwsysPrivate.h"
#if defined(_MSC_VER)
-#pragma warning(disable : 4786)
+# pragma warning(disable : 4786)
#endif
#include KWSYS_HEADER(Encoding.hxx)
@@ -18,8 +18,8 @@
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "Encoding.h.in"
-#include "Encoding.hxx.in"
+# include "Encoding.h.in"
+# include "Encoding.hxx.in"
#endif
static const unsigned char helloWorldStrings[][32] = {
@@ -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(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(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/testFStream.cxx b/Source/kwsys/testFStream.cxx
index a92a781c3..5009e9887 100644
--- a/Source/kwsys/testFStream.cxx
+++ b/Source/kwsys/testFStream.cxx
@@ -3,19 +3,19 @@
#include "kwsysPrivate.h"
#if defined(_MSC_VER)
-#pragma warning(disable : 4786)
+# pragma warning(disable : 4786)
#endif
#include KWSYS_HEADER(FStream.hxx)
#include <string.h>
#ifdef __BORLANDC__
-#include <mem.h> /* memcmp */
+# include <mem.h> /* memcmp */
#endif
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "FStream.hxx.in"
+# include "FStream.hxx.in"
#endif
#include <iostream>
diff --git a/Source/kwsys/testHashSTL.cxx b/Source/kwsys/testHashSTL.cxx
index 044487473..4ed2f899d 100644
--- a/Source/kwsys/testHashSTL.cxx
+++ b/Source/kwsys/testHashSTL.cxx
@@ -7,18 +7,19 @@
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "hash_map.hxx.in"
-#include "hash_set.hxx.in"
+# include "hash_map.hxx.in"
+# include "hash_set.hxx.in"
#endif
#include <iostream>
#if defined(_MSC_VER)
-#pragma warning(disable : 4786)
+# pragma warning(disable : 4786)
#endif
#if defined(__sgi) && !defined(__GNUC__)
-#pragma set woff 1468 /* inline function cannot be explicitly instantiated */
+# pragma set woff 1468 /* inline function cannot be explicitly instantiated \
+ */
#endif
template class kwsys::hash_map<const char*, int>;
diff --git a/Source/kwsys/testIOS.cxx b/Source/kwsys/testIOS.cxx
deleted file mode 100644
index 3e4c325c7..000000000
--- a/Source/kwsys/testIOS.cxx
+++ /dev/null
@@ -1,139 +0,0 @@
-/* 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)
-
-#include <fstream>
-#include <iostream>
-#include <sstream>
-#include <string.h> /* strlen */
-#include <vector>
-
-// Work-around CMake dependency scanning limitation. This must
-// duplicate the above list of headers.
-#if 0
-#include "Configure.hxx.in"
-#endif
-
-int testIOS(int, char* [])
-{
- std::ostringstream ostr;
- const char hello[] = "hello";
- ostr << hello;
- if (ostr.str() != hello) {
- std::cerr << "failed to write hello to ostr" << std::endl;
- return 1;
- }
- const char world[] = "world";
- std::ostringstream ostr2;
- ostr2.write(hello, strlen(hello)); /* I could do sizeof */
- ostr2.put('\0');
- ostr2.write(world, strlen(world));
- if (ostr2.str().size() != strlen(hello) + 1 + strlen(world)) {
- std::cerr << "failed to write hello to ostr2" << std::endl;
- return 1;
- }
- static const unsigned char array[] = {
- 0xff, 0x4f, 0xff, 0x51, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
- 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, 0x01, 0xff, 0x52, 0x00,
- 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x04, 0x04, 0x00, 0x01, 0xff,
- 0x5c, 0x00, 0x13, 0x40, 0x40, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0x48,
- 0x48, 0x50, 0x48, 0x48, 0x50, 0x48, 0x48, 0x50, 0xff, 0x64, 0x00, 0x2c,
- 0x00, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79,
- 0x20, 0x49, 0x54, 0x4b, 0x2f, 0x47, 0x44, 0x43, 0x4d, 0x2f, 0x4f, 0x70,
- 0x65, 0x6e, 0x4a, 0x50, 0x45, 0x47, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69,
- 0x6f, 0x6e, 0x20, 0x31, 0x2e, 0x30, 0xff, 0x90, 0x00, 0x0a, 0x00, 0x00,
- 0x00, 0x00, 0x06, 0x2c, 0x00, 0x01, 0xff, 0x93, 0xcf, 0xb0, 0x18, 0x08,
- 0x7f, 0xc6, 0x99, 0xbf, 0xff, 0xc0, 0xf8, 0xc1, 0xc1, 0xf3, 0x05, 0x81,
- 0xf2, 0x83, 0x0a, 0xa5, 0xff, 0x10, 0x90, 0xbf, 0x2f, 0xff, 0x04, 0xa8,
- 0x7f, 0xc0, 0xf8, 0xc4, 0xc1, 0xf3, 0x09, 0x81, 0xf3, 0x0c, 0x19, 0x34
- };
- const size_t narray = sizeof(array); // 180
- std::stringstream strstr;
- strstr.write((char*)array, narray);
- // strstr.seekp( narray / 2 ); // set position of put pointer in mid string
- if (strstr.str().size() != narray) {
- std::cerr << "failed to write array to strstr" << std::endl;
- return 1;
- }
-
- std::istringstream istr(" 10 20 str ");
- std::string s;
- int x;
- if (istr >> x) {
- if (x != 10) {
- std::cerr << "x != 10" << std::endl;
- return 1;
- }
- } else {
- std::cerr << "Failed to read 10 from istr" << std::endl;
- return 1;
- }
- if (istr >> x) {
- if (x != 20) {
- std::cerr << "x != 20" << std::endl;
- return 1;
- }
- } else {
- std::cerr << "Failed to read 20 from istr" << std::endl;
- return 1;
- }
- if (istr >> s) {
- if (s != "str") {
- std::cerr << "s != \"str\"" << std::endl;
- return 1;
- }
- } else {
- std::cerr << "Failed to read str from istr" << std::endl;
- return 1;
- }
- if (istr >> s) {
- std::cerr << "Able to read past end of stream" << std::endl;
- return 1;
- } else {
- // Clear the failure.
- istr.clear(istr.rdstate() & ~std::ios::eofbit);
- istr.clear(istr.rdstate() & ~std::ios::failbit);
- }
- istr.str("30");
- if (istr >> x) {
- if (x != 30) {
- std::cerr << "x != 30" << std::endl;
- return 1;
- }
- } else {
- std::cerr << "Failed to read 30 from istr" << std::endl;
- return 1;
- }
-
- std::stringstream sstr;
- sstr << "40 str2";
- if (sstr >> x) {
- if (x != 40) {
- std::cerr << "x != 40" << std::endl;
- return 1;
- }
- } else {
- std::cerr << "Failed to read 40 from sstr" << std::endl;
- return 1;
- }
- if (sstr >> s) {
- if (s != "str2") {
- std::cerr << "s != \"str2\"" << std::endl;
- return 1;
- }
- } else {
- std::cerr << "Failed to read str2 from sstr" << std::endl;
- return 1;
- }
-
- // Just try to compile this.
- if (x == 12345) {
- std::ifstream fin("/does_not_exist", std::ios::in | std::ios::binary);
- }
-
- std::cout << "IOS tests passed" << std::endl;
- return 0;
-}
diff --git a/Source/kwsys/testProcess.c b/Source/kwsys/testProcess.c
index 092dd0347..39aaa23ba 100644
--- a/Source/kwsys/testProcess.c
+++ b/Source/kwsys/testProcess.c
@@ -7,8 +7,8 @@
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "Encoding.h.in"
-#include "Process.h.in"
+# include "Encoding.h.in"
+# include "Process.h.in"
#endif
#include <assert.h>
@@ -18,21 +18,21 @@
#include <string.h>
#if defined(_WIN32)
-#include <windows.h>
+# include <windows.h>
#else
-#include <signal.h>
-#include <unistd.h>
+# include <signal.h>
+# include <unistd.h>
#endif
#if defined(__BORLANDC__)
-#pragma warn - 8060 /* possibly incorrect assignment */
+# pragma warn - 8060 /* possibly incorrect assignment */
#endif
/* Platform-specific sleep functions. */
#if defined(__BEOS__) && !defined(__ZETA__)
/* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */
-#include <be/kernel/OS.h>
+# include <be/kernel/OS.h>
static inline void testProcess_usleep(unsigned int usec)
{
snooze(usec);
@@ -44,7 +44,7 @@ static void testProcess_usleep(unsigned int usec)
Sleep(usec / 1000);
}
#else
-#define testProcess_usleep usleep
+# define testProcess_usleep usleep
#endif
#if defined(_WIN32)
@@ -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");
@@ -466,24 +477,27 @@ static int runChild2(kwsysProcess* kp, const char* cmd[], int state,
printf("Error in administrating child process: [%s]\n",
kwsysProcess_GetErrorString(kp));
break;
- };
+ }
if (result) {
if (exception != kwsysProcess_GetExitException(kp)) {
- fprintf(stderr, "Mismatch in exit exception. "
- "Should have been %d, was %d.\n",
+ fprintf(stderr,
+ "Mismatch in exit exception. "
+ "Should have been %d, was %d.\n",
exception, kwsysProcess_GetExitException(kp));
}
if (value != kwsysProcess_GetExitValue(kp)) {
- fprintf(stderr, "Mismatch in exit value. "
- "Should have been %d, was %d.\n",
+ fprintf(stderr,
+ "Mismatch in exit value. "
+ "Should have been %d, was %d.\n",
value, kwsysProcess_GetExitValue(kp));
}
}
if (kwsysProcess_GetState(kp) != state) {
- fprintf(stderr, "Mismatch in state. "
- "Should have been %d, was %d.\n",
+ fprintf(stderr,
+ "Mismatch in state. "
+ "Should have been %d, was %d.\n",
state, kwsysProcess_GetState(kp));
result = 1;
}
@@ -628,11 +642,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 +706,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/testSharedForward.c.in b/Source/kwsys/testSharedForward.c.in
index 9a0c0c061..b3eb41382 100644
--- a/Source/kwsys/testSharedForward.c.in
+++ b/Source/kwsys/testSharedForward.c.in
@@ -1,11 +1,11 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#if defined(CMAKE_INTDIR)
-#define CONFIG_DIR_PRE CMAKE_INTDIR "/"
-#define CONFIG_DIR_POST "/" CMAKE_INTDIR
+# define CONFIG_DIR_PRE CMAKE_INTDIR "/"
+# define CONFIG_DIR_POST "/" CMAKE_INTDIR
#else
-#define CONFIG_DIR_PRE ""
-#define CONFIG_DIR_POST ""
+# define CONFIG_DIR_PRE ""
+# define CONFIG_DIR_POST ""
#endif
#define @KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD "@EXEC_DIR@"
#define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD "." CONFIG_DIR_POST
@@ -18,7 +18,7 @@
#define @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_PRINT "--print"
#define @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_LDD "--ldd"
#if defined(CMAKE_INTDIR)
-#define @KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME CMAKE_INTDIR
+# define @KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME CMAKE_INTDIR
#endif
#include <@KWSYS_NAMESPACE@/SharedForward.h>
int main(int argc, char** argv)
diff --git a/Source/kwsys/testSystemInformation.cxx b/Source/kwsys/testSystemInformation.cxx
index 3a9217f2c..154517eae 100644
--- a/Source/kwsys/testSystemInformation.cxx
+++ b/Source/kwsys/testSystemInformation.cxx
@@ -6,25 +6,25 @@
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "SystemInformation.hxx.in"
+# include "SystemInformation.hxx.in"
#endif
#include <iostream>
#if defined(KWSYS_USE_LONG_LONG)
-#if defined(KWSYS_IOS_HAS_OSTREAM_LONG_LONG)
-#define iostreamLongLong(x) (x)
-#else
-#define iostreamLongLong(x) ((long)x)
-#endif
+# if defined(KWSYS_IOS_HAS_OSTREAM_LONG_LONG)
+# define iostreamLongLong(x) (x)
+# else
+# define iostreamLongLong(x) ((long)x)
+# endif
#elif defined(KWSYS_USE___INT64)
-#if defined(KWSYS_IOS_HAS_OSTREAM___INT64)
-#define iostreamLongLong(x) (x)
+# if defined(KWSYS_IOS_HAS_OSTREAM___INT64)
+# define iostreamLongLong(x) (x)
+# else
+# define iostreamLongLong(x) ((long)x)
+# endif
#else
-#define iostreamLongLong(x) ((long)x)
-#endif
-#else
-#error "No Long Long"
+# error "No Long Long"
#endif
#define printMethod(info, m) std::cout << #m << ": " << info.m() << "\n"
@@ -86,7 +86,7 @@ int testSystemInformation(int, char* [])
}
/* test stack trace
- */
+ */
std::cout << "Program Stack:" << std::endl
<< kwsys::SystemInformation::GetProgramStack(0, 0) << std::endl
<< std::endl;
diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx
index e6fbf6cda..1f3a15b59 100644
--- a/Source/kwsys/testSystemTools.cxx
+++ b/Source/kwsys/testSystemTools.cxx
@@ -3,7 +3,7 @@
#include "kwsysPrivate.h"
#if defined(_MSC_VER)
-#pragma warning(disable : 4786)
+# pragma warning(disable : 4786)
#endif
#include KWSYS_HEADER(FStream.hxx)
@@ -12,8 +12,8 @@
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
-#include "FStream.hxx.in"
-#include "SystemTools.hxx.in"
+# include "FStream.hxx.in"
+# include "SystemTools.hxx.in"
#endif
// Include with <> instead of "" to avoid getting any in-source copy
@@ -22,12 +22,13 @@
#include <iostream>
#include <sstream>
+#include <stdlib.h> /* free */
#include <string.h> /* strcmp */
#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <io.h> /* _umask (MSVC) / umask (Borland) */
-#ifdef _MSC_VER
-#define umask _umask // Note this is still umask on Borland
-#endif
+# include <io.h> /* _umask (MSVC) / umask (Borland) */
+# ifdef _MSC_VER
+# define umask _umask // Note this is still umask on Borland
+# endif
#endif
#include <sys/stat.h> /* umask (POSIX), _S_I* constants (Windows) */
// Visual C++ does not define mode_t (note that Borland does, however).
@@ -38,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" },
+ { nullptr, nullptr }
};
static bool CheckConvertToUnixSlashes(std::string const& input,
@@ -67,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" },
+ { " {} ", "{}", "#", " #{#} " },
+ { nullptr, nullptr, nullptr, nullptr }
+};
static bool CheckEscapeChars(std::string const& input,
const char* chars_to_escape, char escape_char,
@@ -158,7 +160,7 @@ static bool CheckFileOperations()
res = false;
}
// calling with 0 pointer should return false
- if (kwsys::SystemTools::MakeDirectory(0)) {
+ if (kwsys::SystemTools::MakeDirectory(nullptr)) {
std::cerr << "Problem with MakeDirectory(0)" << std::endl;
res = false;
}
@@ -204,7 +206,7 @@ static bool CheckFileOperations()
res = false;
}
- if (!kwsys::SystemTools::Touch(testNewFile.c_str(), true)) {
+ if (!kwsys::SystemTools::Touch(testNewFile, true)) {
std::cerr << "Problem with Touch for: " << testNewFile << std::endl;
res = false;
}
@@ -216,11 +218,11 @@ static bool CheckFileOperations()
}
// calling with 0 pointer should return false
- if (kwsys::SystemTools::FileExists(0)) {
+ if (kwsys::SystemTools::FileExists(nullptr)) {
std::cerr << "Problem with FileExists(0)" << std::endl;
res = false;
}
- if (kwsys::SystemTools::FileExists(0, true)) {
+ if (kwsys::SystemTools::FileExists(nullptr, true)) {
std::cerr << "Problem with FileExists(0) as file" << std::endl;
res = false;
}
@@ -253,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;
}
@@ -284,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;
}
@@ -413,7 +415,7 @@ static bool CheckFileOperations()
res = false;
}
- kwsys::SystemTools::Touch(testNewFile.c_str(), true);
+ kwsys::SystemTools::Touch(testNewFile, true);
if (!kwsys::SystemTools::RemoveADirectory(testNewDir)) {
std::cerr << "Problem with RemoveADirectory for: " << testNewDir
<< std::endl;
@@ -535,15 +537,14 @@ static bool CheckStringOperations()
}
delete[] cres;
- char* cres2 = new char[strlen("Mary Had A Little Lamb.") + 1];
- strcpy(cres2, "Mary Had A Little Lamb.");
+ char* cres2 = strdup("Mary Had A Little Lamb.");
kwsys::SystemTools::ReplaceChars(cres2, "aeiou", 'X');
if (strcmp(cres2, "MXry HXd A LXttlX LXmb.")) {
std::cerr << "Problem with ReplaceChars "
<< "\"Mary Had A Little Lamb.\"" << std::endl;
res = false;
}
- delete[] cres2;
+ free(cres2);
if (!kwsys::SystemTools::StringStartsWith("Mary Had A Little Lamb.",
"Mary ")) {
@@ -683,9 +684,10 @@ static bool CheckRelativePaths()
}
static bool CheckCollapsePath(const std::string& path,
- const std::string& expected)
+ const std::string& expected,
+ const char* base = nullptr)
{
- std::string result = kwsys::SystemTools::CollapseFullPath(path);
+ std::string result = kwsys::SystemTools::CollapseFullPath(path, base);
if (!kwsys::SystemTools::ComparePath(expected, result)) {
std::cerr << "CollapseFullPath(" << path << ") yielded " << result
<< " instead of " << expected << std::endl;
@@ -699,6 +701,19 @@ 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:/");
+ res &= CheckCollapsePath("../b", "../../b", "../");
+ res &= CheckCollapsePath("../a/../b", "../b", "../rel");
+ res &= CheckCollapsePath("a/../b", "../rel/b", "../rel");
return res;
}
@@ -727,29 +742,29 @@ static bool CheckGetPath()
#endif
const char* registryPath = "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MyApp; MyKey]";
- std::vector<std::string> originalPathes;
- originalPathes.push_back(registryPath);
+ std::vector<std::string> originalPaths;
+ originalPaths.push_back(registryPath);
- std::vector<std::string> expectedPathes;
- expectedPathes.push_back(registryPath);
+ std::vector<std::string> expectedPaths;
+ expectedPaths.push_back(registryPath);
#ifdef _WIN32
- expectedPathes.push_back("C:/Somewhere/something");
- expectedPathes.push_back("D:/Temp");
+ expectedPaths.push_back("C:/Somewhere/something");
+ expectedPaths.push_back("D:/Temp");
#else
- expectedPathes.push_back("/Somewhere/something");
- expectedPathes.push_back("/tmp");
+ expectedPaths.push_back("/Somewhere/something");
+ expectedPaths.push_back("/tmp");
#endif
bool res = true;
res &= CheckPutEnv(std::string(envName) + "=" + envValue, envName, envValue);
- std::vector<std::string> pathes = originalPathes;
- kwsys::SystemTools::GetPath(pathes, envName);
+ std::vector<std::string> paths = originalPaths;
+ kwsys::SystemTools::GetPath(paths, envName);
- if (pathes != expectedPathes) {
- std::cerr << "GetPath(" << StringVectorToString(originalPathes) << ", "
- << envName << ") yielded " << StringVectorToString(pathes)
- << " instead of " << StringVectorToString(expectedPathes)
+ if (paths != expectedPaths) {
+ std::cerr << "GetPath(" << StringVectorToString(originalPaths) << ", "
+ << envName << ") yielded " << StringVectorToString(paths)
+ << " instead of " << StringVectorToString(expectedPaths)
<< std::endl;
res = false;
}
@@ -758,6 +773,36 @@ static bool CheckGetPath()
return res;
}
+static bool CheckGetFilenameName()
+{
+ const char* windowsFilepath = "C:\\somewhere\\something";
+ const char* unixFilepath = "/somewhere/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 != expectedWindowsFilename) {
+ std::cerr << "GetFilenameName(" << windowsFilepath << ") yielded "
+ << filename << " instead of " << expectedWindowsFilename
+ << std::endl;
+ res = false;
+ }
+
+ filename = kwsys::SystemTools::GetFilenameName(unixFilepath);
+ if (filename != expectedUnixFilename) {
+ std::cerr << "GetFilenameName(" << unixFilepath << ") yielded " << filename
+ << " instead of " << expectedUnixFilename << std::endl;
+ res = false;
+ }
+ return res;
+}
+
static bool CheckFind()
{
bool res = true;
@@ -765,7 +810,7 @@ static bool CheckFind()
const std::string testFindFile(TEST_SYSTEMTOOLS_BINARY_DIR "/" +
testFindFileName);
- if (!kwsys::SystemTools::Touch(testFindFile.c_str(), true)) {
+ if (!kwsys::SystemTools::Touch(testFindFile, true)) {
std::cerr << "Problem with Touch for: " << testFindFile << std::endl;
// abort here as the existence of the file only makes the test meaningful
return false;
@@ -789,6 +834,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
@@ -838,6 +916,167 @@ static bool CheckGetLineFromStream()
return ret;
}
+static bool CheckGetLineFromStreamLongLine()
+{
+ const std::string fileWithLongLine("longlines.txt");
+ std::string firstLine, secondLine;
+ // First line: large buffer, containing a carriage return for some reason.
+ firstLine.assign(2050, ' ');
+ firstLine += "\rfirst";
+ secondLine.assign(2050, 'y');
+ secondLine += "second";
+
+ // Create file with long lines.
+ {
+ kwsys::ofstream out(fileWithLongLine.c_str(), std::ios::binary);
+ if (!out) {
+ std::cerr << "Problem opening for write: " << fileWithLongLine
+ << std::endl;
+ return false;
+ }
+ out << firstLine << "\r\n\n" << secondLine << "\n";
+ }
+
+ kwsys::ifstream file(fileWithLongLine.c_str(), std::ios::binary);
+ if (!file) {
+ std::cerr << "Problem opening: " << fileWithLongLine << std::endl;
+ return false;
+ }
+
+ std::string line;
+ bool has_newline = false;
+ bool result;
+
+ // Read first line.
+ result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline, -1);
+ if (!result || line != firstLine) {
+ std::cerr << "First line does not match, expected " << firstLine.size()
+ << " characters, got " << line.size() << std::endl;
+ return false;
+ }
+ if (!has_newline) {
+ std::cerr << "Expected new line to be read from first line" << std::endl;
+ return false;
+ }
+
+ // Read empty line.
+ has_newline = false;
+ result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline, -1);
+ if (!result || !line.empty()) {
+ std::cerr << "Expected successful read with an empty line, got "
+ << line.size() << " characters" << std::endl;
+ return false;
+ }
+ if (!has_newline) {
+ std::cerr << "Expected new line to be read for an empty line" << std::endl;
+ return false;
+ }
+
+ // Read second line.
+ has_newline = false;
+ result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline, -1);
+ if (!result || line != secondLine) {
+ std::cerr << "Second line does not match, expected " << secondLine.size()
+ << " characters, got " << line.size() << std::endl;
+ return false;
+ }
+ if (!has_newline) {
+ std::cerr << "Expected new line to be read from second line" << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+static bool writeFile(const char* fileName, const char* data)
+{
+ kwsys::ofstream out(fileName, std::ios::binary);
+ out << data;
+ if (!out) {
+ std::cerr << "Failed to write file: " << fileName << std::endl;
+ return false;
+ }
+ return true;
+}
+
+static std::string readFile(const char* fileName)
+{
+ kwsys::ifstream in(fileName, std::ios::binary);
+ std::stringstream sstr;
+ sstr << in.rdbuf();
+ std::string data = sstr.str();
+ if (!in) {
+ std::cerr << "Failed to read file: " << fileName << std::endl;
+ return std::string();
+ }
+ return data;
+}
+
+struct
+{
+ const char* a;
+ const char* b;
+ bool differ;
+} diff_test_cases[] = { { "one", "one", false },
+ { "one", "two", true },
+ { "", "", false },
+ { "\n", "\r\n", false },
+ { "one\n", "one\n", false },
+ { "one\r\n", "one\n", false },
+ { "one\n", "one", false },
+ { "one\ntwo", "one\ntwo", false },
+ { "one\ntwo", "one\r\ntwo", false } };
+
+static bool CheckTextFilesDiffer()
+{
+ const int num_test_cases =
+ sizeof(diff_test_cases) / sizeof(diff_test_cases[0]);
+ for (int i = 0; i < num_test_cases; ++i) {
+ if (!writeFile("file_a", diff_test_cases[i].a) ||
+ !writeFile("file_b", diff_test_cases[i].b)) {
+ return false;
+ }
+ if (kwsys::SystemTools::TextFilesDiffer("file_a", "file_b") !=
+ diff_test_cases[i].differ) {
+ std::cerr << "Incorrect TextFilesDiffer result for test case " << i + 1
+ << "." << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool CheckCopyFileIfDifferent()
+{
+ bool ret = true;
+ const int num_test_cases =
+ sizeof(diff_test_cases) / sizeof(diff_test_cases[0]);
+ for (int i = 0; i < num_test_cases; ++i) {
+ if (!writeFile("file_a", diff_test_cases[i].a) ||
+ !writeFile("file_b", diff_test_cases[i].b)) {
+ return false;
+ }
+ const char* cptarget =
+ i < 4 ? TEST_SYSTEMTOOLS_BINARY_DIR "/file_b" : "file_b";
+ if (!kwsys::SystemTools::CopyFileIfDifferent("file_a", cptarget)) {
+ std::cerr << "CopyFileIfDifferent() returned false for test case "
+ << i + 1 << "." << std::endl;
+ ret = false;
+ continue;
+ }
+ std::string bdata = readFile("file_b");
+ if (diff_test_cases[i].a != bdata) {
+ std::cerr << "Incorrect CopyFileIfDifferent file contents in test case "
+ << i + 1 << "." << std::endl;
+ ret = false;
+ continue;
+ }
+ }
+
+ return ret;
+}
+
int testSystemTools(int, char* [])
{
bool res = true;
@@ -873,7 +1112,17 @@ int testSystemTools(int, char* [])
res &= CheckFind();
+ res &= CheckIsSubDirectory();
+
res &= CheckGetLineFromStream();
+ res &= CheckGetLineFromStreamLongLine();
+
+ res &= CheckGetFilenameName();
+
+ res &= CheckTextFilesDiffer();
+
+ res &= CheckCopyFileIfDifferent();
+
return res ? 0 : 1;
}
diff --git a/Source/kwsys/testTerminal.c b/Source/kwsys/testTerminal.c
index f6c1eddb7..652830ccd 100644
--- a/Source/kwsys/testTerminal.c
+++ b/Source/kwsys/testTerminal.c
@@ -6,7 +6,7 @@
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
-#include "Terminal.h.in"
+# include "Terminal.h.in"
#endif
int testTerminal(int argc, char* argv[])